#1 Re: GDI+ » Support for viewing/retrieving individual pages of a multi-page TIFF » 2013-05-29 15:33:15

Hi,

I just took a look at the repository and noticed that the code you posted missed the constructor override for TTiffImage and thus the initialization code of the fActivePageIndex variable.

Ryan.

#2 GDI+ » Support for viewing/retrieving individual pages of a multi-page TIFF » 2013-05-28 16:43:31

sllimr7139
Replies: 3

Sorry for the mess....but I wanted to post back to the group before I moved on and forgot that I had done this.

This is based off of the latest version of the syngdiplus.pas file found in the source code repository.

// ****************************************
//    Interface Section Code
// ****************************************

    // ****************************************
    // add to the private section of the TGDIPlus class
    // ****************************************
    GetFrameCount: function (image: THandle; dimensionID: PGUID; var count: UINT): TGdipStatus; stdcall;
    SelectActiveFrame: function (image: THandle; dimensionID: PGUID; frameIndex: UINT): TGdipStatus; stdcall;


    // ****************************************
    // Replace the existing declaration of TTiffImage
    // ****************************************
   TTiffImage = class(TSynPicture)
  private
    fActivePage : integer;
  protected
    //Selects the active frame/page for the TIFF
    procedure SelectPage(index:integer); //rjm
  public
    constructor Create; override; //rjm

    //Extract a page from the TIFF and assign it to a bitmap
    procedure ExtractPage(index:integer; wBMP:TBitmap); //rjm

    //Retrieve the number of pages in the TIFF file
    function GetPageCount:integer;

    //Default Frame/Page Index is 0
    property ActivePageIndex : integer read fActivePage write SelectPage;
  end;


// ****************************************
//    Implementation Section Code
// ****************************************


    // ****************************************
    // add to the top of the implementaion section
    // ****************************************
const
//---------------------------------------------------------------------------
// Predefined multi-frame dimension IDs
//---------------------------------------------------------------------------

  FrameDimensionPage       : TGUID = '{7462dc86-6180-4c7e-8e3f-ee7333a7a483}';
  {$EXTERNALSYM FrameDimensionPage}


    // ****************************************
    // Replace the existing declaration of GdiPProcNames
    // ****************************************

const GdiPProcNames: array[0..18{$ifdef USEDPI}+1{$endif}
      {$ifdef USEENCODERS}+2{$endif}] of PChar =
    ('GdiplusStartup','GdiplusShutdown',
     'GdipDeleteGraphics','GdipCreateFromHDC',
     'GdipLoadImageFromStream','GdipLoadImageFromFile',
     'GdipDrawImageRectI','GdipDrawImageRectRectI',
{$ifdef USEDPI} 'GdipDrawImageI', {$endif}
     'GdipDisposeImage', 'GdipGetImageRawFormat',
     'GdipGetImageWidth','GdipGetImageHeight','GdipSaveImageToStream',
{$ifdef USEENCODERS} 'GdipGetImageEncodersSize','GdipGetImageEncoders', {$endif}
     'GdipCreateBitmapFromHBITMAP','GdipCreateBitmapFromGdiDib','GdipBitmapSetResolution',
     'GdipImageGetFrameCount', 'GdipImageSelectActiveFrame',  // <--new function names //rjm
     nil);

    // ****************************************
    //  add to the bottom of the unit above the initialization section
    // ****************************************


{ TTiffImage }

//rjm
function TTiffImage.GetPageCount: integer;
var
  wCount : UINT;
begin
  if (fImage<>0) then
  begin
    Gdip.GetFrameCount(fImage, @FrameDimensionPage, wCount);
    result := wCount;
  end
  else
    result := 0;
end;

//rjm
procedure TTiffImage.SelectPage(index: integer);
var
  wFrames : integer;
begin
  wFrames := GetPageCount;
  if (wFrames > 0) and ((index >= 0) and (index < wFrames)) then
  begin
    Gdip.SelectActiveFrame(fImage, @FrameDimensionPage, index);
    fActivePage := index;
  end
  else
    raise ERangeError.Create('Invalid Page Index');
end;

//rjm
constructor TTiffImage.Create;
begin
  inherited;
  fActivePage := 0;
end;

//rjm
procedure TTiffImage.ExtractPage(index: integer; wBMP:TBitmap);
var
  wFrames : integer;
  wStrm : TMemoryStream;
begin
  wFrames := GetPageCount;
  if (wFrames > 0) and ((index >= 0) and (index < wFrames)) then
  begin
    Try
      Gdip.SelectActiveFrame(fImage, @FrameDimensionPage, index);
      wStrm := TMemoryStream.Create;
      try
        SaveAs(wstrm,gptBMP);
        wStrm.Position := 0;
        wBmp.LoadFromStream(wStrm);
      finally
        wStrm.Free;
      end;
    finally
      Gdip.SelectActiveFrame(fImage, @FrameDimensionPage, fActivePage);
    end;
  end
  else
    raise ERangeError.Create('Invalid Page Index');
end;

#3 GDI+ » Code Changes for SynGDIPlus » 2012-03-29 16:54:30

sllimr7139
Replies: 6

Thanks for a great library.

Here are a two changes that I've made for my use that I think other might find usefull.

procedure TSynPicture.AssignTo(Dest: TPersistent);
begin
  //This currently only handles TBitmap but could/should be extended for other TGraphic Classes
  if Dest is TBitmap then
  begin
    TBitmap(Dest).Assign(Self.ToBitmap);

    //This block is not really necessary.  I've left it here for the completeness of my change
    if TBitmap(Dest).PixelFormat = pfDevice then
    begin
      if Self is TPngImage then
        TBitmap(Dest).PixelFormat := pf32bit  //Possibly Alpha Transaparancy

      else if Self is TGifImage then
        TBitmap(Dest).PixelFormat := pf8bit  //Palletted Image

      else  //TTiffImage, TJpegImage
        TBitmap(Dest).PixelFormat := pf24bit;  //Everything else
    end;
  end
  else
    Inherited;
end;

The above code allows for the common usage of assigning a TGraphic class to another TGraphic Class

For Example:

     var
       wBMP : TBitmap;
     begin
       wBMP := TBitmap.create;
       try

         ...

         //wPic is a TImage, and then Graphic is a TSynPicture descendant class (TTiffImage for example )
         wBMP.Assign( wPic.Picture.Graphic ); 
     
         ...

       Finally
         wBMP.free;
       end;
     end;

The other change is in the ability to Define registering only specific TSynPicture classes

The following block should go under the NOTSYNPICTIREREGISTER define at the top of the file

{ if NOTSYNPICTUREREGISTER is not defined then the following has no effect }
{$define RegisterIndividualFormats}
{if RegisterIndividualFormats is not defined then all of the file formats are registered }

{ if RegisterIndividualFormats is defined then the following defines will register the appropriate TGraphic classes }
{$define RegisterTIFF}
{.$define RegisterJPEG}
{.$define RegisterPNG}
{$define RegisterGIF}

The following block should replace the If GetClass('TTiffImage') = nil then block of code in then RegisterPictures method

  {$ifdef RegisterIndividualFormats}
    {$ifdef RegisterJPEG}
      RegisterClass(TJpegImage);
      TPicture.RegisterFileFormat(PicturesExt[0], PictureName(PictureClasses[0]), PictureClasses[0]);
      TPicture.RegisterFileFormat(PicturesExt[1], PictureName(PictureClasses[1]), PictureClasses[1]);
    {$endif}

    {$ifdef RegisterPNG}
      RegisterClass(TPngImage);
      TPicture.RegisterFileFormat(PicturesExt[2], PictureName(PictureClasses[2]), PictureClasses[2]);
    {$endif}

    {$ifdef RegisterGIF}
      RegisterClass(TGifImage);
      TPicture.RegisterFileFormat(PicturesExt[3], PictureName(PictureClasses[3]), PictureClasses[3]);
    {$endif}

    {$ifdef RegisterTIFF}
      RegisterClass(TTiffImage);
      TPicture.RegisterFileFormat(PicturesExt[4], PictureName(PictureClasses[4]), PictureClasses[4]);
      TPicture.RegisterFileFormat(PicturesExt[5], PictureName(PictureClasses[5]), PictureClasses[5]);
    {$endif}
  {$else}

//   register JPG and PNG pictures as TGraphic
    if GetClass('TTiffImage')=nil then
    begin
      RegisterClass(TJpegImage);
      RegisterClass(TPngImage);
      RegisterClass(TGifImage);
      RegisterClass(TTiffImage);
      for i := 0 to high(PicturesExt) do
        TPicture.RegisterFileFormat(PicturesExt[i],
          PictureName(PictureClasses[i]),PictureClasses[i]);
    end;
  {$endif}

Hopefully other people find this useful.

Ryan.

Board footer

Powered by FluxBB