NO

Author Topic: Gdi+ image operation  (Read 12607 times)

liut

  • Guest
Gdi+ image operation
« on: May 09, 2017, 09:49:42 AM »
Hello, I'm trying to use this lib (author by JohnF) for some image operations:

http://www.johnfindlay.plus.com/pellesc/GdiPlus/GdiPlusLibLib.zip

I can use the image decoder and encoder for an image's format conversion, and can also get the width/height of the image. However, I can't find a way to scale an image and save to another. I look into the h files, maybe lack of some api for bitmap/graphics class.

Can anybody show me an example code with this lib? Tks!!

Offline frankie

  • Global Moderator
  • Member
  • *****
  • Posts: 2096
Re: Gdi+ image operation
« Reply #1 on: May 09, 2017, 11:03:40 AM »
You may want switch to a native GDI+ usage using fGdiPlusFlat.h, that is also included in fsdk .
You can get the manual for fGdiPlusFlat.h here.
For an example of image cropping and scaling see chapter 7.5 "Cropping and Scaling Images" page 37.
Anyway under GdiPlusLibLib you should use:
Code: [Select]
GpStatus GpGraphics_DrawImageRcRcI(GP_GRAPHICS * this, GP_IMAGE * image, const RECTI * destRect, INT srcx, INT srcy, INT
                                                          srcwidth, INT srcheight, GpUnit srcUnit, const GP_IMAGEATTRIBUTES * imageAttributes,
                                                          DrawImageAbort callback, VOID* callbackData)
Or
Code: [Select]
GpStatus GpGraphics_DrawImagePtsRcI(GP_GRAPHICS * this, GP_IMAGE * image,
                                                   const POINTI * destPoints, INT count, INT srcx, INT srcy,
                                                   INT srcwidth, INT srcheight, GpUnit srcUnit, const GP_IMAGEATTRIBUTES * imageAttributes,
                                                   DrawImageAbort callback, VOID* callbackData)
« Last Edit: May 09, 2017, 11:21:48 AM by frankie »
It is better to be hated for what you are than to be loved for what you are not. - Andre Gide

liut

  • Guest
Re: Gdi+ image operation
« Reply #2 on: May 10, 2017, 03:58:02 AM »
Thanks Frankie. Actually I have read the manual of gdi+flat before and compared with gdi+liblib, their exported apis are similar. The actual problems:
1. No exported api for creating a graphic object via an existing bitmap object. I refered others' C++ code, it should like this:
     Image image(L"d:\\abc.jpg");   // create an image object, it can be done
     Bitmap bitmap(100, 100, PixelFormat32bppARGB);   // create a bitmap object with specified width/height/color, it can be done
     Graphics graph(&bitmap);   // create a graphic object via bitmap object,  no api for this
     graph.DrawImage(&image, Rect(0,0,100,100));   // draw image to this graphic object, it can be done

2. No exported api for saving a bitmap object to file. I check gdi+ manual of Microsoft, bitmap class is inherited from image class, so it should support the save method too. But I can't find api for this (only we have GpImage_SaveFile()):
    bitmap.Save(L"d:\\new_abc.jpg",   &encoderClsid,   &encoderParameters); 

BTW, in the manual the content for "cropping and scaling images", the code purpose is mainly for displaying an image, it should not be enough for me.
If no more idea, I may consider using gdi/hdc as an intermediate way to convert them, but it looks quite stupid :)

Offline frankie

  • Global Moderator
  • Member
  • *****
  • Posts: 2096
Re: Gdi+ image operation
« Reply #3 on: May 10, 2017, 02:46:14 PM »
Hello liut.
Actually I have read the manual of gdi+flat before and compared with gdi+liblib, their exported apis are similar. The actual problems:
1. No exported api for creating ...
2. No exported api for saving a bitmap object to file...
fGdiPlusFlat.h is not a library. It doesn't contain any helper class or function.
NeverthelessfGdiPlusFlat.h  exports the whole GDI+ API. All functions existent in GDI+ are available in fGdiPlusFlat.h.

I check gdi+ manual of Microsoft, bitmap class is inherited from image class, so it a graphic object via an existing bitmap object. I refered others' C++ code, it should like this:
     Image image(L"d:\\abc.jpg");   // create an image object, it can be done
     Bitmap bitmap(100, 100, PixelFormat32bppARGB);   // create a bitmap object with specified width/height/color, it can be done
     Graphics graph(&bitmap);   // create a graphic object via bitmap object,  no api for this
     graph.DrawImage(&image, Rect(0,0,100,100));   // draw image to this graphic object, it can be done
Everything can be done. GpBitmap and GPImage can be used indifferently.
Code: [Select]
GpImage *image = NULL;
GdipLoadImageFromFile(L"d:\\abc.jpg", &image); // create an image object
GpBitmap *bitmap = NULL;
GdipCreateBitmapFromScan0(100, 100, 0, PixelFormat32bppARGB, NULL, &bitmap); // create a bitmap object with specified width/height/color
GpGraphics *graph;
GdipGetImageGraphicsContext(bitmap, &graph); // create a graphic object via bitmap object
GdipDrawImageI(graph, image, 100, 100); // draw image to this graphic object, it can be done

2. No exported api for saving a bitmap object to file. I check gdi+ manual of Microsoft, bitmap class is inherited from image class, so it should support the save method too. But I can't find api for this (only we have GpImage_SaveFile()):
    bitmap.Save(L"d:\\new_abc.jpg",   &encoderClsid,   &encoderParameters); 
Have you took a look to the fGdiPlusFlat.h? Or on MSDN?
You can use GdipSaveImageToFile and image format got from GetImageEncoders, you can find a sample here.

   GdipSaveImageToFile(bitmap, L"mybitmap.bmp", &ImageFormatBMP, NULL);   //save bitmap in bitmap format
   GdipSaveImageToFile(bitmap, L"mybitmap.png", &ImageFormatPNG, NULL);   //save bitmap in PNG format
   GdipSaveImageToFile(image,  L"myimage.bmp",  &ImageFormatBMP, NULL);   //save bitmap in bitmap format
   GdipSaveImageToFile(image,  L"myimage.png",  &ImageFormatPNG, NULL);   //save bitmap in PNG format


BTW, in the manual the content for "cropping and scaling images", the code purpose is mainly for displaying an image, it should not be enough for me.
As I told the file fGdiPlusFlat.h is the complete GDI+ flat API, so everything that can be done in C++ with GDI+ can be done in C. Of course it is not straightforward, and you have to practice to use it (is a bare naked API).
The first page of the manual try to give an idea of how to use them, following the base rules and consulting the reference online it should be not so difficult to program with it.
« Last Edit: May 12, 2017, 05:26:11 PM by frankie »
It is better to be hated for what you are than to be loved for what you are not. - Andre Gide

liut

  • Guest
Re: Gdi+ image operation
« Reply #4 on: May 11, 2017, 09:48:47 AM »
Thanks again frankie!! Finally I make it works! Here is the complete code for reference:

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

#include "fGdiPlusFlat.h"

// The helper function code comes from Microsoft guideline without modification
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

   ImageCodecInfo* pImageCodecInfo = NULL;

   GdipGetImageEncodersSize(&num, &size);
   if(size == 0)
      return -1;  // Failure

   pImageCodecInfo = (ImageCodecInfo*)(malloc(size));
   if(pImageCodecInfo == NULL)
      return -1;  // Failure

   GdipGetImageEncoders(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
}

int CALLBACK WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpszCmdLine, int nCmdShow)
{
   GpStatus stat;

   ULONG_PTR gdiplusToken;

   GdiplusStartup(&gdiplusToken, &gdiplusStartupInputDef, NULL);

   GpImage *image=NULL;
   GdipLoadImageFromFile(L"d:\\Runner.jpg",&image);

   UINT width,height;
   GdipGetImageWidth(image,&width);
   GdipGetImageHeight(image,&height);

   PixelFormat pixfmt;
   GdipGetImagePixelFormat(image, &pixfmt);

   if(image){
      GpBitmap *bitmap=NULL;
      GdipCreateBitmapFromScan0(width/2, height/2, 0, pixfmt, NULL, &bitmap);

      if(bitmap){
         GpGraphics *graph=NULL;
         GdipGetImageGraphicsContext(bitmap, &graph);

         if(graph){
            GdipDrawImageRectI(graph, image, 0, 0, width/2, height/2);

            // Draw a line
            //GpPen *pen;
            //GdipCreatePen1(MakeARGB(255, 0, 0, 255), 2.0, UnitPixel, &pen);
            //GdipDrawLineI(graph, pen, 0, 0, 60, 30);

            CLSID encoderClsid;
            GetEncoderClsid(L"image/jpeg", &encoderClsid);

            // For jpeg encoder
            EncoderParameters para;
            ULONG quality;
            
            para.Count = 1;
            para.Parameter[0].Guid = EncoderQuality;
            para.Parameter[0].Type = EncoderParameterValueTypeLong;
            para.Parameter[0].NumberOfValues = 1;
            quality = 95;  // jpg quality level 95.
            para.Parameter[0].Value = &quality;

            //stat=GdipSaveImageToFile(bitmap, L"d:\\mybitmap.bmp", &ImageFormatBMP, NULL);  // Always return 10 (FileNotFound?) if directly using const ImageFormatXXX...
            stat=GdipSaveImageToFile(bitmap, L"d:\\mybitmap.jpg", &encoderClsid, &para);  // para for jpeg, NULL for bmp
            if(stat==Ok){
               MessageBox(NULL,"ok","ok",MB_OK);
            }
            else{
               char text[100];

               sprintf(text,"%d",stat);
               MessageBox(NULL,text,"GdipSaveImageToFile",MB_OK);
            }

            GdipDeleteGraphics(graph);
         }
      }

       GdipDisposeImage(image);
   }

   GdiplusShutdown(gdiplusToken);

   return 0;
}


There is still an issue: I can't directly use the const ImageFormatXXX in GdipSaveImageToFile(), and still need to use the helper function to get the clsid for the encoder. Anyway it's good enough for me!!

Offline TimoVJL

  • Global Moderator
  • Member
  • *****
  • Posts: 2091
Re: Gdi+ image operation
« Reply #5 on: May 11, 2017, 12:34:08 PM »
Maybe those are constants.
Code: [Select]
const CLSID CLSID_image_bmp =  {0x557CF400,0x1A04,0x11D3,0x9A,0x73,0x00,0x00,0xF8,0x1E,0xF3,0x2E};
const CLSID CLSID_image_jpeg = {0x557CF401,0x1A04,0x11D3,0x9A,0x73,0x00,0x00,0xF8,0x1E,0xF3,0x2E};
const CLSID CLSID_image_gif =  {0x557CF402,0x1A04,0x11D3,0x9A,0x73,0x00,0x00,0xF8,0x1E,0xF3,0x2E};
const CLSID CLSID_image_tiff = {0x557CF405,0x1A04,0x11D3,0x9A,0x73,0x00,0x00,0xF8,0x1E,0xF3,0x2E};
const CLSID CLSID_image_png =  {0x557CF406,0x1A04,0x11D3,0x9A,0x73,0x00,0x00,0xF8,0x1E,0xF3,0x2E};
const CLSID CLSID_image_ico =  {0x557CF407,0x1A04,0x11D3,0x9A,0x73,0x00,0x00,0xF8,0x1E,0xF3,0x2E};
EDIT: with one variable
Code: [Select]
CLSID CLSID_image =  {0x557CF400,0x1A04,0x11D3,0x9A,0x73,0x00,0x00,0xF8,0x1E,0xF3,0x2E};just change one byte like
Code: [Select]
*(BYTE*)&CLSID_image = 6; // PNG
Code: [Select]
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <objbase.h>
#pragma comment(lib, "ole32.lib")

CLSID CLSID_image =  {0x557CF400,0x1A04,0x11D3,0x9A,0x73,0x00,0x00,0xF8,0x1E,0xF3,0x2E};

void __cdecl WinMainCRTStartup(void)
{
wchar_t *pwc, wcTmp[555];
pwc = wcTmp;
for (char i=0; i<=7;i++) {
*(BYTE*)&CLSID_image = i;
pwc += StringFromGUID2(&CLSID_image, pwc, 39);
*(pwc-1) = 10;
}
MessageBoxW(0, wcTmp, 0, 0);
ExitProcess(0);
}
« Last Edit: May 13, 2017, 10:40:51 AM by TimoVJL »
May the source be with you

liut

  • Guest
Re: Gdi+ image operation
« Reply #6 on: May 12, 2017, 03:32:53 AM »
Thanks Timo. It works with these const perfectly!

Offline frankie

  • Global Moderator
  • Member
  • *****
  • Posts: 2096
Re: Gdi+ image operation
« Reply #7 on: May 12, 2017, 05:28:25 PM »
Sorry I was wrong with use of GdipSaveImageToFile.
I edited the post above.
It is better to be hated for what you are than to be loved for what you are not. - Andre Gide

Offline bitcoin

  • Member
  • *
  • Posts: 179
Re: Gdi+ image operation
« Reply #8 on: January 07, 2019, 03:31:21 PM »
How I can make screenshot with gdi? I tried source code , but i get 'Access violation' in string GdipGetImageEncodersSize(&num, &size);
Why?

Offline bitcoin

  • Member
  • *
  • Posts: 179
Re: Gdi+ image operation
« Reply #9 on: January 07, 2019, 04:20:35 PM »
Updated. I found a mistake and made it. It looks like a piece of shit, but it works. Maybe someone will come in handy (I doubt, because this is an example of "how not to code" and I am the worst coder on the planet, I have to kill myself).

Code: [Select]
void MakeScr(void)
{
GUID  FormatPNG = {0x557CF406,0x1A04,0x11d3,0x9A,0x73,0x00,0x00,0xf8,0x1e,0xf3,0x2e};     
const CLSID CLSID_image_png =  {0x557CF406,0x1A04,0x11D3,0x9A,0x73,0x00,0x00,0xF8,0x1E,0xF3,0x2E};

const GUID EncoderQuality = {0x1d5be4b5, 0xfa4a, 0x452d, 0x9c, 0xdd, 0x5d, 0xb3, 0x51, 0x05, 0xe7, 0xeb};


GdiplusStartupInput gdiplusStartupInput = {1,0,0,0};
ULONG_PTR gdiplusToken;

//i dont know how to check errors here, only log, if != 0 - error
  printf("%d",GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL));
 
HDC dc, hdc;
HBITMAP hbitmap;

dc = GetDC(0);

int Height, Width;
Height = GetSystemMetrics(SM_CYSCREEN);
Width = GetSystemMetrics(SM_CXSCREEN);

hbitmap = CreateCompatibleBitmap(dc, Width, Height);


hdc = CreateCompatibleDC(dc);

SelectObject(hdc, hbitmap);
BitBlt(hdc, 0, 0, Width, Height, dc, 0, 0, SRCCOPY);

GpBitmap *newBp;
printf ("%d \n",GdipCreateBitmapFromHBITMAP(hbitmap,0,&newBp));


CLSID encoderClsid;
EncoderParameters para;
ULONG quality;

//GetEncoderClsid(L"image/png",&encoderClsid); -

printf("%d\n",GdipSaveImageToFile(newBp, L"mybitmap.png", &FormatPNG, NULL));

    DeleteObject(hbitmap);
 
    //GdiplusShutdown?
    return 0;
}

Offline TimoVJL

  • Global Moderator
  • Member
  • *****
  • Posts: 2091
Re: Gdi+ image operation
« Reply #10 on: January 08, 2019, 12:31:35 PM »
As you are making a function, some release functions should be called too.
Like ReleaseDC(), GdipDisposeImage() to release resources.
Also printf () needs a console, so better to use like OutputDebugString() for checking values.
Code: [Select]
#define WIN32_LEAN_AND_MEAN
#include <windows.h>

#pragma comment(lib, "gdiplus.lib")

typedef int GpStatus;
#define WINGDIPAPI __stdcall
#define GDIPCONST const

typedef void GpBitmap;

typedef struct
{
    UINT32 GdiplusVersion ;
    void* DebugEventCallback ;
    BOOL SuppressBackgroundThread ;
    BOOL SuppressExternalCodecs ;
} GDIPLUSSTARTUPINPUT ;
/*
typedef int (_stdcall *NotificationHookProc)(ULONG_PTR *token);
typedef VOID (_stdcall *NotificationUnhookProc)(ULONG_PTR token);
*/
typedef struct
{
    void* NotificationHook; //NotificationHookProc NotificationHook;
    void* NotificationUnhook; //NotificationUnhookProc NotificationUnhook;
} GDIPLUSSTARTUPOUTPUT ;

int __stdcall GdiplusStartup(ULONG_PTR*, const GDIPLUSSTARTUPINPUT*, GDIPLUSSTARTUPOUTPUT*) ;
VOID __stdcall GdiplusShutdown(ULONG_PTR) ;

typedef void GpImage;
int __stdcall GdipSaveImageToFile(GpImage *image, WCHAR* filename, GDIPCONST CLSID* clsidEncoder, void*);
int __stdcall GdipCreateBitmapFromHBITMAP(HBITMAP hbm, HPALETTE hpal, GpBitmap** bitmap);
int __stdcall GdipDisposeImage(GpImage*);

void MakeScr(void)
{
const CLSID CLSID_image_png = { 0x557CF406, 0x1A04, 0x11D3, 0x9A, 0x73, 0x00, 0x00, 0xF8, 0x1E, 0xF3, 0x2E };
GDIPLUSSTARTUPINPUT gdiplusStartupInput = { 1, 0, 0, 1 };
ULONG_PTR gdiplusToken;

GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);

HDC dc, hdc;
HBITMAP hbitmap;

// HWND hWnd = GetDesktopWindow();
dc = GetDC(0);

int Height, Width;
Height = GetSystemMetrics(SM_CYSCREEN);
Width = GetSystemMetrics(SM_CXSCREEN);

hbitmap = CreateCompatibleBitmap(dc, Width, Height);
hdc = CreateCompatibleDC(dc);
SelectObject(hdc, hbitmap);
BitBlt(hdc, 0, 0, Width, Height, dc, 0, 0, SRCCOPY);
DeleteDC(hdc);
ReleaseDC(0, dc);

GpBitmap *newBp;
GdipCreateBitmapFromHBITMAP(hbitmap, 0, &newBp);
DeleteObject(hbitmap);

GdipSaveImageToFile(newBp, L"mybitmap.png", &CLSID_image_png, NULL);
GdipDisposeImage(newBp);


//GdiplusShutdown?
GdiplusShutdown(gdiplusToken);
}

void __cdecl WinMainCRTStartup(void)
{
MakeScr();
ExitProcess(0);
}
« Last Edit: January 08, 2019, 12:39:44 PM by TimoVJL »
May the source be with you

Offline frankie

  • Global Moderator
  • Member
  • *****
  • Posts: 2096
Re: Gdi+ image operation
« Reply #11 on: January 08, 2019, 02:58:03 PM »
After the excellent post of Timo, this is just another sample natively using fGdiPlusFlat.h

Code: [Select]
#include <windows.h>
#include <fGdiPlusFlat.h>
#include <stdio.h>
#pragma comment(lib, "User32.lib")
#pragma comment(lib, "gdi32.lib")
#pragma comment(lib, "gdiplus.lib")

#define GDI_ERR_CASE(x) case (x): return (const char *)#x
const char *GetGdiPlusErrorText(Status err)
{
switch (err)
{
GDI_ERR_CASE(Ok);
GDI_ERR_CASE(GenericError);
GDI_ERR_CASE(InvalidParameter);
GDI_ERR_CASE(OutOfMemory);
GDI_ERR_CASE(ObjectBusy);
GDI_ERR_CASE(InsufficientBuffer);
GDI_ERR_CASE(NotImplemented);
GDI_ERR_CASE(Win32Error);
GDI_ERR_CASE(WrongState);
GDI_ERR_CASE(Aborted);
GDI_ERR_CASE(FileNotFound);
GDI_ERR_CASE(ValueOverflow);
GDI_ERR_CASE(AccessDenied);
GDI_ERR_CASE(UnknownImageFormat);
GDI_ERR_CASE(FontFamilyNotFound);
GDI_ERR_CASE(FontStyleNotFound);
GDI_ERR_CASE(NotTrueTypeFont);
GDI_ERR_CASE(UnsupportedGdiplusVersion);
GDI_ERR_CASE(GdiplusNotInitialized);
GDI_ERR_CASE(PropertyNotFound);
GDI_ERR_CASE(PropertyNotSupported);
}

return (const char *)"Unknown error.";
}

BOOL GetEncoderClsid(const WCHAR *format, CLSID *pClsid)
{
UINT num = 0; // number of image encoders
UINT size = 0; // size of the image encoder array in bytes

ImageCodecInfo *pImageCodecInfo = NULL;

GdipGetImageEncodersSize(&num, &size);
if (size == 0)
return FALSE; // Failure

pImageCodecInfo = (ImageCodecInfo *) (malloc(size));
if (pImageCodecInfo == NULL)
return FALSE; // Failure

GdipGetImageEncoders(num, size, pImageCodecInfo);

for (UINT j = 0; j < num; ++j)
{
if (wcscmp(pImageCodecInfo[j].MimeType, format) == 0)
{
*pClsid = pImageCodecInfo[j].Clsid;
free(pImageCodecInfo);
return TRUE; // Success
}
}

free(pImageCodecInfo);
return FALSE; // Failure
}

BOOL SaveScrToFile(const WCHAR *szFileName, const WCHAR *ImgFormat)
{
BOOL bReturn = FALSE;

HDC hDcScreen   = GetDC(NULL); //Acquire screen DC
int Height      = GetSystemMetrics(SM_CYSCREEN); //Get Screen dimensions
int Width       = GetSystemMetrics(SM_CXSCREEN);
HBITMAP hbitmap = CreateCompatibleBitmap(hDcScreen, Width, Height);
HDC hdc         = CreateCompatibleDC(hDcScreen); //Create our memory DC for copy
HGDIOBJ hOldBmp = SelectObject(hdc, hbitmap);
BOOL bRes       = BitBlt(hdc, 0, 0, Width, Height, hDcScreen, 0, 0, SRCCOPY);
ReleaseDC(NULL, hDcScreen); //Release screen DC
if (!bRes) //Test result from BitBlt
goto Clean; //BitBlt failed!
GpBitmap * newBp;
Status sRes = GdipCreateBitmapFromHBITMAP(hbitmap, 0, &newBp);
if (Ok != sRes)
{
printf("Error %d='%s'calling GdipCreateBitmapFromHBITMAP.\n", sRes, GetGdiPlusErrorText(sRes));
goto Clean;
}
CLSID encoderClsid;
if(!GetEncoderClsid(ImgFormat,&encoderClsid)) //Retrieve encoder CLSID
goto Clean; //Encoder not available
sRes = GdipSaveImageToFile(newBp, szFileName, &encoderClsid, NULL);
GdipDisposeImage(newBp);
if (Ok != sRes)
{
printf("Error %d='%s'calling GdipSaveImageToFile.\n", sRes, GetGdiPlusErrorText(sRes));
goto Clean;
}
else
bReturn = TRUE;
Clean:
SelectObject(hdc, hOldBmp); //Select back old bitmap
DeleteObject(hbitmap); //Delete user bitmap
DeleteDC(hdc); //Delete memory DC
return bReturn;
}

int main(void)
{
GdiplusStartupInput gdiplusStartupInput = { 1, 0, 0, 0 };
ULONG_PTR gdiplusToken;
BOOL bReturn = FALSE;

printf("Saving screen to file \"MyScreen.png\".\n");
//Normally you init and shutdown GDI+ from main, so if you have other
//functions using GDI+ you don't have to restart it each time.
Status sRes = GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);
if (Ok != sRes)
{
printf("Error %d='%s'calling GdiplusStartup.\n", sRes, GetGdiPlusErrorText(sRes));
return bReturn;
}

if (SaveScrToFile(L"MyScreen.png", L"image/png"))
{
printf("File saved correctly!\n");
bReturn = TRUE;
}
else
{
printf("File not savedy!\n");
bReturn = FALSE;
}
GdiplusShutdown(gdiplusToken);
return !bReturn; //Negation to make return value conformant: OK=0, whatever=NOT_OK
}

EDIT: Fixed code.
« Last Edit: January 09, 2019, 10:47:04 AM by frankie »
It is better to be hated for what you are than to be loved for what you are not. - Andre Gide

Offline bitcoin

  • Member
  • *
  • Posts: 179
Re: Gdi+ image operation
« Reply #12 on: January 08, 2019, 03:57:53 PM »
frankie,TimoVJL, thank you, it works.
Are there diffences between GUID and CLSID?

Offline frankie

  • Global Moderator
  • Member
  • *****
  • Posts: 2096
Re: Gdi+ image operation
« Reply #13 on: January 08, 2019, 06:00:46 PM »
You're welcome.
The GUID, Globally Unique Identifier, and the CLSID, CLass ID, are both a 128 bits long code that is guarantee to be unique all over the world.
With a slight difference in the standard representation, a doubleword, 2 words and 8 bytes for GUID and a doubleword, 3 words and 6 bytes for CLSID, they anyways counts 128bits total (16 bytes).
It is better to be hated for what you are than to be loved for what you are not. - Andre Gide

Offline bitcoin

  • Member
  • *
  • Posts: 179
Re: Gdi+ image operation
« Reply #14 on: February 24, 2023, 01:51:00 PM »
Hello!
How I can compress the image? I use source code

Code: [Select]
void MakeShot(void)
{
GUID png_clsid = { 0x557CF406,0x1A04,0x11d3,0x9A,0x73,0x00,0x00,0xf8,0x1e,0xf3,0x2e };

GdiplusStartupInput gdiplusStartupInput = { 1,0,0,0 };
ULONG_PTR gdiplusToken;

GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);

HDC dc, hdc;
HBITMAP hbitmap;

dc = GetDC(0);

int Height, Width;
Height = GetSystemMetrics(SM_CYSCREEN);
Width = GetSystemMetrics(SM_CXSCREEN);

hbitmap = CreateCompatibleBitmap(dc, Width, Height);

hdc = CreateCompatibleDC(dc);

SelectObject(hdc, hbitmap);

BitBlt(hdc, 0, 0, Width, Height, dc, 0, 0, SRCCOPY);

GpBitmap* newBp;
GdipCreateBitmapFromHBITMAP(hbitmap, 0, &newBp);



EncoderParameters para;
para.Count = 1;
para.Parameter[0].Guid = EncoderQuality;
para.Parameter[0].Type = EncoderParameterValueTypeLong;
para.Parameter[0].NumberOfValues = 1;
int quality = 15;
para.Parameter[0].Value = &quality;

GdipSaveImageToFile(newBp, L"mybitmap.png", &png_clsid, &para);


GdipSaveImageToStream(newBp, iSend, &png_clsid, NULL);


DeleteObject(hbitmap);

GdiplusShutdown(gdiplusToken);

But int quality - has no effect! I got same images, compress don't work, why?