NO

Author Topic: SGL - win32 made simple!  (Read 2804 times)

Offline henrin

  • Member
  • *
  • Posts: 21
Re: SGL - win32 made simple!
« Reply #15 on: November 21, 2016, 09:34:50 AM »
Hello jj2007,

I never heard about animated PNGs. This format does not seem to be widely accepted, and I am not surprised that GDI+ ignore it.

To test multiframe TIFF images, I used the attached image (probably the only one I have found, and I do not remember where!).

In a previous post I did not attach correctly the message box sample. Here it is.

Offline TimoVJL

  • Global Moderator
  • Member
  • *****
  • Posts: 1612
Re: SGL - win32 made simple!
« Reply #16 on: November 21, 2016, 09:58:35 AM »
May the source be with you

Offline jj2007

  • Member
  • *
  • Posts: 454
Re: SGL - win32 made simple!
« Reply #17 on: November 21, 2016, 01:21:28 PM »
I do not remember where

http://www.nightprogrammer.org/development/multipage-tiff-example-download-test-image-file/

There are two examples, and indeed I didn't find any others on the wide world web :(
But they both work fine. In contrast to the GIFs, their PropertyTagFrameDelay is not set, though.

APNG is a different story indeed, not supported by Gdi+, and while it would be theoretically possible to pick a frame from an APNG, it would be a lot of work with a badly documented format.
« Last Edit: November 21, 2016, 01:26:03 PM by jj2007 »

Offline henrin

  • Member
  • *
  • Posts: 21
Re: SGL - win32 made simple!
« Reply #18 on: November 21, 2016, 05:22:32 PM »
Make your own multiframe TIFF images!

I just remember few years ago ( today its my birthday  8) ) I created multiframe images, here is how :

- use ACDSee (my sersion is ACDSee Pro 7)
- select several images
- menu batch image conversion

The last option before conversion starts is for multiframe.

TIP : sample_image64/32.exe does not erase the panel before each image.
Results may be unpleasant if all frames don't have the same size.


It is possible to view multiframe images with ACDSee, as well as with FastStome Image Viewer.

Offline jj2007

  • Member
  • *
  • Posts: 454
Re: SGL - win32 made simple!
« Reply #19 on: November 21, 2016, 05:54:35 PM »
Happy birthday then  :)

Re roll your own: Not worth the effort for TIFFs. It's an exotic format anyway, so I guess animated GIFs is enough for 99% of all users. APNG may be the future. I wonder if they have much better compression than GIF, though.

Offline TimoVJL

  • Global Moderator
  • Member
  • *****
  • Posts: 1612
Re: SGL - win32 made simple!
« Reply #20 on: November 21, 2016, 06:02:35 PM »
MultiTIFF, remind me a FAX
This example make 3 pages TIFF.
Code: [Select]
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
//#include "GdiPlusFlat.h"

#pragma comment(linker, "-subsystem:windows")
#pragma comment(lib, "gdiplus.lib")
// https://msdn.microsoft.com/en-us/library/windows/desktop/ms534041(v=vs.85).aspx
// https://msdn.microsoft.com/en-us/library/ms533839(v=vs.85).aspx
typedef int GpStatus;
#define WINGDIPAPI __stdcall
#define GDIPCONST const

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 ;

typedef struct EncoderParameter {
GUID Guid;
ULONG NumberOfValues;
ULONG Type;
VOID *Value;
} EncoderParameter;

typedef struct EncoderParameters {
UINT Count;
EncoderParameter Parameter[1];
} EncoderParameters;

typedef enum EncoderParameterValueType {
EncoderParameterValueTypeByte = 1,
EncoderParameterValueTypeASCII = 2,
EncoderParameterValueTypeShort = 3,
EncoderParameterValueTypeLong = 4,
EncoderParameterValueTypeRational = 5,
EncoderParameterValueTypeLongRange = 6,
EncoderParameterValueTypeUndefined = 7,
EncoderParameterValueTypeRationalRange = 8,
EncoderParameterValueTypePointer = 9
} EncoderParameterValueType;

typedef enum EncoderValue {
EncoderValueColorTypeCMYK = 0,
EncoderValueColorTypeYCCK = 1,
EncoderValueCompressionLZW = 2,
EncoderValueCompressionCCITT3 = 3,
EncoderValueCompressionCCITT4 = 4,
EncoderValueCompressionRle = 5,
EncoderValueCompressionNone = 6,
EncoderValueScanMethodInterlaced = 7,
EncoderValueScanMethodNonInterlaced = 8,
EncoderValueVersionGif87 = 9,
EncoderValueVersionGif89 = 10,
EncoderValueRenderProgressive = 11,
EncoderValueRenderNonProgressive = 12,
EncoderValueTransformRotate90 = 13,
EncoderValueTransformRotate180 = 14,
EncoderValueTransformRotate270 = 15,
EncoderValueTransformFlipHorizontal = 16,
EncoderValueTransformFlipVertical = 17,
EncoderValueMultiFrame = 18,
EncoderValueLastFrame = 19,
EncoderValueFlush = 20,
EncoderValueFrameDimensionTime = 21,
EncoderValueFrameDimensionResolution = 22,
EncoderValueFrameDimensionPage = 23
} EncoderValue;

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

typedef void GpImage;
int __stdcall GdipLoadImageFromFile(WCHAR* filename, GpImage **image);
int __stdcall GdipSaveImageToFile(GpImage *image, WCHAR* filename, GDIPCONST CLSID* clsidEncoder, void*);
//                    EncoderParameters* encoderParams);
int __stdcall GdipSaveAdd(GpImage*,GDIPCONST EncoderParameters*);
int __stdcall GdipSaveAddImage(GpImage*,GpImage*,GDIPCONST EncoderParameters*);
int __stdcall GdipDisposeImage(GpImage*);

GDIPLUSSTARTUPINPUT gdiplusStartupInput = { 1, NULL, FALSE, FALSE } ;
ULONG_PTR gdiplusToken;

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};

//292266fc-ac40-47bf-8cfc-a85b89a655de
const CLSID EncoderSaveFlag = {0x292266FC,0xAC40,0x47BF,0x8C,0xFC,0xA8,0x5B,0x89,0xA6,0x55,0xDE};

void __cdecl WinMainCRTStartup(void)
{
GpStatus status;
GpImage *image = NULL;
EncoderParameters encoderParameters;
ULONG parameterValue;

GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);
encoderParameters.Count = 1;

// Initialize the one EncoderParameter object.
encoderParameters.Parameter[0].Guid = EncoderSaveFlag;
encoderParameters.Parameter[0].Type = EncoderParameterValueTypeLong;
encoderParameters.Parameter[0].NumberOfValues = 1;
encoderParameters.Parameter[0].Value = &parameterValue;
// Load the first page (frame).
status = GdipLoadImageFromFile(L"testimg.bmp", (GpImage **)&image);
if (status == 0) {
GpImage *image2 = NULL;
// Save the first page (frame).
parameterValue = EncoderValueMultiFrame;
status = GdipSaveImageToFile(image, L"test1.tif", &CLSID_image_tiff, &encoderParameters);
// Save the second page (frame).
status = GdipLoadImageFromFile(L"testimg.bmp", (GpImage **)&image2);
parameterValue = EncoderValueFrameDimensionPage;
status = GdipSaveAddImage(image, image2, &encoderParameters);
GdipDisposeImage(image2);
// Save the third page (frame).
status = GdipLoadImageFromFile(L"testimg.bmp", (GpImage **)&image2);
parameterValue = EncoderValueFrameDimensionPage;
status = GdipSaveAddImage(image, image2, &encoderParameters);
GdipDisposeImage(image2);
// Close the multiframe file.
parameterValue = EncoderValueFlush;
status = GdipSaveAdd(image, &encoderParameters);
GdipDisposeImage(image);
}
GdiplusShutdown(gdiplusToken);
ExitProcess(0);
}
« Last Edit: November 21, 2016, 06:08:04 PM by TimoVJL »
May the source be with you