Pas de dépendances
#include <Windows.h> #include <GdiPlus.h> #include <stdio.h> #pragma comment(lib, "gdiplus.lib") int GetEncoderClsid(const WCHAR* format, CLSID* pClsid) { UINT num = 0; // number of image encoders UINT size = 0; // size of the image encoder array in bytes Gdiplus::ImageCodecInfo* pImageCodecInfo = NULL; Gdiplus::GetImageEncodersSize(&num, &size); if(size == 0) return -1; // Failure pImageCodecInfo = (Gdiplus::ImageCodecInfo*)(malloc(size)); if(pImageCodecInfo == NULL) return -1; // Failure Gdiplus::GetImageEncoders(num, size, pImageCodecInfo); for(UINT j = 0; j < num; ++j) { if( wcscmp(pImageCodecInfo[j].MimeType, format) == 0 ) { *pClsid = pImageCodecInfo[j].Clsid; free(pImageCodecInfo); return j; // Success } } free(pImageCodecInfo); return -1; // Failure } void SauverJPG(const wchar_t* fic,int width,int height,const char* flux) { Gdiplus::Bitmap B(width,height); 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) { Gdiplus::Color col(flux[curs+2],flux[curs+1],flux[curs]); B.SetPixel(i,j,col); } } CLSID jpgClsid; GetEncoderClsid(L"image/jpeg", &jpgClsid); if (B.Save(fic,&jpgClsid,NULL)==Gdiplus::Ok) printf("Sauvegarde ok\n"); else printf("Sauvegarde echoue\n"); ReleaseDC(Hcon, Hdc); } int main(void) { unsigned long m_gdiplusToken; Gdiplus::GdiplusStartupInput gdiplusStartupInput; Gdiplus::GdiplusStartup(&m_gdiplusToken, &gdiplusStartupInput, NULL); if(OpenClipboard(NULL)) { HANDLE h; h = GetClipboardData(CF_DIBV5); if(h) { BITMAPV5HEADER head; char *brut = (char *)GlobalLock(h); head = *((BITMAPV5HEADER*)brut); SauverJPG(L"out.jpg",head.bV5Width,head.bV5Height,brut+head.bV5Size); GlobalUnlock(h); CloseClipboard(); } else printf("Pas d'image dans le presse papier\n"); CloseClipboard(); } Gdiplus::GdiplusShutdown(m_gdiplusToken); return 0; }
Voici une partie de la librairie Windows appelée GDI (Graphic Device Interface). Notez que cette partie est en C++, et non plus en C. Avant de lancer le programme, faite un screenshot (la touche impr ecran, l'outil snipping tool, un copier dans Paint, ce que vous voulez...) L'essentiel est d'avoir une image dans le presse papier. Lancez le programme : un fichier out.jpg se crée : votre image est sauvegardée ! Pour la partie lecture du presse papier, je vous renvoie au §4.10.3 de ce recueil. Au lieu de dessiner l'image, nous allons la passer à la fonction SauverJPG. Tout d'abord, la librairie GDI d'initialise avec : unsigned long m_gdiplusToken; Gdiplus::GdiplusStartupInput gdiplusStartupInput; Gdiplus::GdiplusStartup(&m_gdiplusToken, &gdiplusStartupInput, NULL); et se libère avec : Gdiplus::GdiplusShutdown(m_gdiplusToken); La classe Bitmap : ------------------ Ce qui est intéressant dans ce paragraphe est la classe Gdiplus::Bitmap Cette classe permet de charger plusieurs formats d'image (BMP, GIF, JPG, PNG...) de les manipuler et également de les sauver ! Cette classe hérite de la classe Gdiplus::Image Voici les documentations pour voir toutes les méthodes disponibles : https://msdn.microsoft.com/en-us/library/windows/desktop/ms534420(v=vs.85).aspx https://msdn.microsoft.com/en-us/library/windows/desktop/ms534462(v=vs.85).aspx Tout d'abord, nous construisons une instance de Bitmap en passant la taille voulue (width et height) Puis nous remplissons chaque pixel dans le for en créeant des pixels de type Gdiplus::Color https://msdn.microsoft.com/en-us/library/windows/desktop/ms534427(v=vs.85).aspx Puis nous sauvegardons avec la méthode Save. La petite difficulté est qu'il faut récupérer un identifiant du codec d'encodage de l'image. En effet, Windows sait lire et écrire des JPG, des PNG, etc... Il a des codecs pour ça. Nous allons, grâce à la fonction GetEncoderClsid, récupérer le codec jpg pour l'utiliser, et sauver notre image en JPG. Cette fonction, je l'ai prise directement sur la MSDN ici : https://msdn.microsoft.com/en-us/library/windows/desktop/ms533843(v=vs.85).aspx Son fonctionnement est simple (mais est en C) : Gdiplus::GetImageEncodersSize récupère le nombre de codecs d'écriture présents. Gdiplus::GetImageEncoders les récupère dans un tableau. On fait un for, et si l'encodeur correspond à celui demandé, on renvoie le bon CLSID : l'identifiant du codec à passer à Save.