Creating and Saving a Multiple-Frame Image

With certain file formats, you can save multiple images (frames) to a single file. For example, you can save several pages to a single TIFF file. To save the first page, call the Save method of the Image class. To save subsequent pages, call the SaveAdd method of the Image class.


You cannot use SaveAdd to add frames to an animated gif file.


The following console application creates a TIFF file with four pages. The images that become the pages of the TIFF file come from four disk files: Shapes.bmp, Cereal.gif, Iron.jpg, and House.png. The code first constructs four Image objects: multi, page2, page3, and page4. At first, multi contains only the image from Shapes.bmp, but eventually it contains all four images. As the individual pages are added to the multi  Image object, they are also added to the disk file Multiframe.tif.

Note that the code calls Save (not SaveAdd) to save the first page. The first argument passed to the Save method is the name of the disk file that will eventually contain several frames. The second argument passed to the Save method specifies the encoder that will be used to convert the data in the multi  Image object to the format (in this case TIFF) required by the disk file. That same encoder is used automatically by all subsequent calls to the SaveAdd method of the multi  Image object.

The third argument passed to the Save method is the address of an EncoderParameters object. The EncoderParameters object has an array that contains a single EncoderParameter object. The Guid member of that EncoderParameter object is set to EncoderSaveFlag. The Value member of the EncoderParameter object points to a ULONG that contains the value EncoderValueMultiFrame.

The code saves the second, third, and fourth pages by calling the SaveAdd method of the multi  Image object. The first argument passed to the SaveAdd method is the address of an Image object. The image in that Image object is added to the multi  Image object and is also added to the Multiframe.tif disk file. The second argument passed to the SaveAdd method is the address of the same EncoderParameters object that was used by the Save method. The difference is that the ULONG pointed to by the Value member now contains the value EncoderValueFrameDimensionPage.

The main function relies on the helper function GetEncoderClsid, which is shown in Retrieving the Class Identifier for an Encoder.

#include <windows.h>
#include <gdiplus.h>
#include <stdio.h>
using namespace Gdiplus;

INT GetEncoderClsid(const WCHAR* format, CLSID* pClsid);  // helper function

INT main()
   // Initialize GDI+.
   GdiplusStartupInput gdiplusStartupInput;
   ULONG_PTR gdiplusToken;
   GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);

   EncoderParameters encoderParameters;
   ULONG             parameterValue;
   Status            stat;

   // An EncoderParameters object has an array of
   // EncoderParameter objects. In this case, there is only
   // one EncoderParameter object in the array.
   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;

   // Get the CLSID of the TIFF encoder.
   CLSID encoderClsid;
   GetEncoderClsid(L"image/tiff", &encoderClsid);

   // Create four image objects.
   Image* multi = new Image(L"Shapes.bmp");
   Image* page2 = new Image(L"Cereal.gif");
   Image* page3 = new Image(L"Iron.jpg");
   Image* page4 = new Image(L"House.png");

   // Save the first page (frame).
   parameterValue = EncoderValueMultiFrame;
   stat = multi->Save(L"MultiFrame.tif", &encoderClsid, &encoderParameters);
   if(stat == Ok)
      printf("Page 1 saved successfully.\n");

   // Save the second page (frame).
   parameterValue = EncoderValueFrameDimensionPage;
   stat = multi->SaveAdd(page2, &encoderParameters);
   if(stat == Ok)
      printf("Page 2 saved successfully.\n");

   // Save the third page (frame).
   parameterValue = EncoderValueFrameDimensionPage;
   stat = multi->SaveAdd(page3, &encoderParameters);
   if(stat == Ok)
      printf("Page 3 saved successfully.\n");

   // Save the fourth page (frame).
   parameterValue = EncoderValueFrameDimensionPage;
   stat = multi->SaveAdd(page4, &encoderParameters);
   if(stat == Ok)
      printf("Page 4 saved successfully.\n");

   // Close the multiframe file.
   parameterValue = EncoderValueFlush;
   stat = multi->SaveAdd(&encoderParameters);
   if(stat == Ok)
      printf("File closed successfully.\n");

   delete multi;
   delete page2;
   delete page3;
   delete page4;
   return 0;