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!!
You may want switch to a native GDI+ usage using fGdiPlusFlat.h, that is also included in fsdk (http://forum.pellesc.de/index.php?topic=7017.0) .
You can get the manual for fGdiPlusFlat.h here (http://www.johnfindlay.plus.com/pellesc/GdiPlus/GdiPlusTests.zip).
For an example of image cropping and scaling see chapter 7.5 "Cropping and Scaling Images" page 37.
Anyway under GdiPlusLibLib you should use:
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
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)
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 :)
Hello liut.
Quote from: liut on May 10, 2017, 03:58:02 AM
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.
Nevertheless
fGdiPlusFlat.h exports the whole GDI+ API. All functions existent in GDI+ are available in
fGdiPlusFlat.h.
Quote from: liut on May 10, 2017, 03:58:02 AM
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.
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
Quote from: liut on May 10, 2017, 03:58:02 AM
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 (https://msdn.microsoft.com/en-us/library/vs/alm/ms533969(v=vs.85).aspx)?
You can use
GdipSaveImageToFile and image format got from
GetImageEncoders, you can find a sample here (https://msdn.microsoft.com/en-us/library/windows/desktop/ms533843(v=vs.85).aspx).
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 formatQuote from: liut on May 10, 2017, 03:58:02 AM
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.
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 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!!
Maybe those are constants.
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 CLSID CLSID_image = {0x557CF400,0x1A04,0x11D3,0x9A,0x73,0x00,0x00,0xF8,0x1E,0xF3,0x2E};
just change one byte like*(BYTE*)&CLSID_image = 6; // PNG
#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);
}
Thanks Timo. It works with these const perfectly!
Sorry I was wrong with use of GdipSaveImageToFile.
I edited the post above.
How I can make screenshot with gdi? I tried source code , but i get 'Access violation' in string GdipGetImageEncodersSize(&num, &size);
Why?
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).
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;
}
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.
#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);
}
After the excellent post of Timo, this is just another sample natively using fGdiPlusFlat.h
#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.
frankie,TimoVJL, thank you, it works.
Are there diffences between GUID and CLSID?
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).
Hello!
How I can compress the image? I use source code
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, ¶);
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?
Hi bitcoin,
Well I'm taking a stab in the dark at it.....
Isn't the png format always a lossless compression? In lossless compression the quality value
would be meaningless so the compression would always be the same....
jpg is not necessarily lossless so the quality value less than 100 has an effect on the compression
and therefore the size.
John Z
Quote from: John Z on February 24, 2023, 03:34:18 PM
Isn't the png format always a lossless compression? In lossless compression the quality value
would be meaningless so the compression would always be the same....
May be, you are right..
As John said the PNG format is lossless, what could be changed is the compression level (see this (https://www.howtogeek.com/203979/is-the-png-format-lossless-since-it-has-a-compression-parameter/)).
You may want use the "EncoderCompression" GUID instead of "EncoderQuality".
I made same experiments, PNG encoder only accepts a custom parameter block that is undocumented. I made many searches in the net, but no info seems to be available.
Hey frankie:
All this talk about GDI+ reminded me that I noticed a recent update to your FSDK.
https://github.com/Frankie-PellesC/fSDK (https://github.com/Frankie-PellesC/fSDK)
I must have missed the announcement but anyway Thank You for the FSDK GDI+ User Manual.
A monumental piece of work. Truly a tour de force.
Hello Robert
Thanks
You're right There was no announcement. The manual has been realized many years ago, 2016, together with the 'fGdiPlusFlat.h' and posted on the forum (here (https://forum.pellesc.de/index.php?topic=6949.msg26326#msg26326)).
Few days ago looking at my github pages I realized that the manual was missing and simply, and silently, added it. :)
My SDK is getting old and would need some mainteinance and upgrade, but unfortunately I'm too busy to afford the job up to now :(
I hope I could do it in the future. :P