Récupérer et afficher une image depuis le presse papier.

Récupérer et afficher une image depuis le presse papier.

GetClipboardData, SetPixel, BITMAPV5HEADER

Voir version :

Pas de dépendances

Télécharger :

#include <windows.h>
#include <stdio.h>

void Dessiner(int width,int height,const char* flux)
{
    int i,j,curs;
    HWND Hcon = GetConsoleWindow();
    HDC Hdc = GetDC(Hcon);  
    for(curs=0,j=height-1;j>=0;j--)
    {
        for(i=0;i<width;i++,curs+=4)
        {
            COLORREF COLOR = RGB(flux[curs+2],flux[curs+1],flux[curs]);
            SetPixel(Hdc,i,j,COLOR);
        }
    }
    ReleaseDC(Hcon, Hdc);
}

int main(void)
{
    if(OpenClipboard(NULL))
    {
        HANDLE h;
        h = GetClipboardData(CF_DIBV5);
        if(h)
        {
            BITMAPV5HEADER head;
            char *brut = (char *)GlobalLock(h);
            head = *((BITMAPV5HEADER*)brut);
            Dessiner(head.bV5Width,head.bV5Height,brut+head.bV5Size);
            GlobalUnlock(h);
            CloseClipboard();
        }
        else
            printf("Pas d'image dans le presse papier\n");
        CloseClipboard();
    }
    return 0;
}




Commentaires

	Pour tester ce code, ouvrez l'outile de capture, ou bien paint, ou bien la touche du clavier "impr ecran"
	ou bien n'importe quel logiciel qui vous permette de copier une image ou un bout d'image.
	Bref, mettez une image dans le presse papier Windows.

	Lancez le programme, il va vous afficher l'image dans la console. 
	(c'est un peu lent, donc si vous avez une très grande image, patientez quelques secondes).

	Le programme ouvre le presse papier, regarde si il y a des informations de type image, et l'affiche.

	Si on regarde le main :
	J'ouvre le ClipBoard (presse papier). 
	Ensuite, je regade s'il y a une image dedans. le format usuel s'appelle CF_DIBV5. Si ce n'est pas le cas on quitte.
	
	Les données récupérées dans le char* brut ressemble au format BMP, c'est à dire un header, puis les pixels.
	
	La structure BITMAPV5HEADER épouse les premiers octets du flux. En castant le char* dessus, on a toutes les données bien rangées.
	Voici ces données :

	typedef struct {
	DWORD        bV5Size;
	LONG         bV5Width;
	LONG         bV5Height;
	WORD         bV5Planes;
	WORD         bV5BitCount;
	DWORD        bV5Compression;
	DWORD        bV5SizeImage;
	LONG         bV5XPelsPerMeter;
	LONG         bV5YPelsPerMeter;
	DWORD        bV5ClrUsed;
	DWORD        bV5ClrImportant;
	DWORD        bV5RedMask;
	DWORD        bV5GreenMask;
	DWORD        bV5BlueMask;
	DWORD        bV5AlphaMask;
	DWORD        bV5CSType;
	CIEXYZTRIPLE bV5Endpoints;
	DWORD        bV5GammaRed;
	DWORD        bV5GammaGreen;
	DWORD        bV5GammaBlue;
	DWORD        bV5Intent;
	DWORD        bV5ProfileData;
	DWORD        bV5ProfileSize;
	DWORD        bV5Reserved;
	} BITMAPV5HEADER, FAR *LPBITMAPV5HEADER, *PBITMAPV5HEADER;

	
	Si vous posez un breakpoint dessus, vous pouvez voir (entre autres) :
	- bV5Size : la taille de ce header : ainsi, un décalage de bV5Size ira sur les données pixel
	- bV5Width : le nombre de pixels en X
	- bV5Height : le nombre de pixels en Y

	Pour voir les autres champs :
	http://msdn.microsoft.com/en-us/library/windows/desktop/dd183381%28v=vs.85%29.aspx
	
	Ma fonction Dessiner part du principe que le format me convient, je ne teste pas les différents cas.
	Si ça foire chez vous (vous avez un affichage moche, un plantage, envoyez moi un mail pour me dire de quelle façon vous
	avez fait votre screenshot, je suis curieux de savoir dans quel cas les screenshots établissent un autre format :) )
		
	Ce que je passe à ma fonction Dessiner, c'est donc le width, le height, ainsi que le pointeur au 
	début du bloc de pixels.

	La fonction Dessiner dessine les pixels de gauche à droite, et de bas à en haut, ainsi le veut la norme bitmap.
	Voila pourquoi le for du j décrémente.

	Chaque pixel est codé sur 4 octets (voila pourquoi je fais curs+=4)

	Chaque pixel est de la forme BGRA : bleu, vert, rouge, alpha
	J'ignore l'alpha, je ne me sers que du bleu, vert, rouge. 
	Comme la fonction RGB prend rouge, vert, bleu, je passe d'abord l'octet curs+2, puis curs+1, puis curs (+0)