ImageEn for Delphi and C++ Builder ImageEn for Delphi and C++ Builder

 

ImageEn Forum
Profile    Join    Active Topics    Forum FAQ    Search this forumSearch
Forum membership is Free!  Click Join to sign-up
Username:
Password:
Save Password
Forgot your Password?

 All Forums
 ImageEn Library for Delphi, C++ and .Net
 ImageEn and IEvolution Support Forum
 How to make MIO load first frame of MultiFrame?
 New Topic  Reply to Topic
Author Previous Topic Topic Next Topic  

PeterPanino

860 Posts

Posted - May 25 2021 :  19:48:30  Show Profile  Reply
MIO.LoadFromFile and MIO.LoadFromFileAuto automatically load all frames from a Multi-Frame file (ICO, GIF, ...).

How can I prevent this in some special cases and make MIO load only the first frame of a Multi-Frame file (or the largest frame from an ICO file)? Is there a built-in function or parameter for this?

PeterPanino

860 Posts

Posted - May 26 2021 :  04:24:54  Show Profile  Reply
I have written this code to achieve this:

procedure TForm1.LoadMultiFrameFiles;
var
  B: TIEBitmap;
begin
  B := TIEBitmap.Create;
  try
    B.Read('C:\DELPHI\_test\MIOLoadFirstFrame\TestIcon1.ico');
    mimgTest.AppendImage(B);
    B.Read('C:\DELPHI\_test\MIOLoadFirstFrame\TestGIF1.gif');
    mimgTest.AppendImage(B);
    B.Read('C:\DELPHI\_test\MIOLoadFirstFrame\TestTIFMulti.tif');
    mimgTest.AppendImage(B);
  finally
    B.Free;
  end;
end;




Can this be optimized?

For example, in an .ICO file, how can I load the frame with the highest dimensions?

(TestIcon1.ico contains 8 frames where the first frame has the highest dimension, as you can see from this screenshot of another IconEditor app):



But despite the first frame is 128*128, it is displayed with poor quality in the ImageEnMView.

attach/PeterPanino/20215264381_TestIcon1.zip
13.05 KB
Go to Top of Page

PeterPanino

860 Posts

Posted - May 26 2021 :  08:42:53  Show Profile  Reply
To retrieve the number of the largest frame from the ICO file, I wrote this code:


P := TIOParams.Create;
if P.Read('TestIcon1.ico') then
begin
  LargestFrame := 0;
  LargestFrameIndex := 0;
  for i := 0 to P.ImageCount - 1 do
  begin
    WxH := P.ICO_Sizes[i].Width * P.ICO_Sizes[i].Height;
    if WxH > LargestFrame then
    begin
      LargestFrame := WxH;
      LargestFrameIndex := i;
    end;
  end;
  CodeSite.Send('LargestFrameIndex', LargestFrameIndex);
end;
P.Free;
Go to Top of Page

PeterPanino

860 Posts

Posted - May 26 2021 :  09:42:27  Show Profile  Reply
So the problem is now solved:


procedure TForm1.LoadSingleFrameFromMultiFrameFiles;

  procedure LoadLargestFrameFromIco(const aIcoFile: string);
  var
    B: TIEBitmap;
    P: TIOParams;
    LargestFrame, LargestFrameIndex, WxH, FrameCount: Integer;
    i: Integer;
    ThisImage: Integer;
  begin
    B := TIEBitmap.Create;
    P := TIOParams.Create;
    try
      if P.Read(aIcoFile) then
      begin
        LargestFrameIndex := 0;
        FrameCount := P.ImageCount;
        if FrameCount > 1 then
        begin
          LargestFrame := 0;
          for i := 0 to FrameCount - 1 do
          begin
            WxH := P.ICO_Sizes[i].Width * P.ICO_Sizes[i].Height;
            if WxH > LargestFrame then
            begin
              LargestFrame := WxH;
              LargestFrameIndex := i;
            end;
          end;
        end;

        P.ImageIndex := LargestFrameIndex;
        B.Read(aIcoFile, P);
        ThisImage := mimgTest.AppendImage();
        mimgTest.SetImage(ThisImage, B);
        mimgTest.ImageTopText[ThisImage] := ExtractFileName(aIcoFile) + ' (Frame #' + IntToStr(LargestFrameIndex + 1) + '/' + IntToStr(P.ImageCount) + ')';
        mimgTest.ImageInfoText[ThisImage] := IntToStr(B.Width) + ' x ' + IntToStr(B.Height);
        FImagePaths.Add(aIcoFile);
      end;
    finally
      P.Free;
      B.Free;
    end;
  end;

  procedure LoadImage(const aImageFile: string);
  var
    P: TIOParams;
    ThisImage, FrameCount: Integer;
    ThisTopText: string;
  begin
    P := TIOParams.Create;
    try
      if P.Read(aImageFile) then
      begin
        FrameCount := P.ImageCount;
        if FrameCount = 1 then
          ThisTopText := ExtractFileName(aImageFile)
        else if FrameCount > 1 then
          ThisTopText := ExtractFileName(aImageFile) + ' (' + IntToStr(FrameCount) + ' frames)';

        ThisImage := mimgTest.AppendImage(aImageFile);
        mimgTest.ImageTopText[ThisImage] := ThisTopText;
        mimgTest.ImageInfoText[ThisImage] := IntToStr(mimgTest.ImageWidth[ThisImage]) + ' x ' + IntToStr(mimgTest.ImageHeight[ThisImage]);
        FImagePaths.Add(aImageFile);
      end;
    finally
      P.Free;
    end;
  end;

begin
  // ICO containing multiple frames:
  LoadLargestFrameFromIco('C:\DELPHI\_test\MIOLoadFirstFrame\TestIcon1.ico');

  // GIF:
  LoadImage('C:\DELPHI\_test\MIOLoadFirstFrame\TestGIF1.gif');

  // TIF:
  LoadImage('C:\DELPHI\_test\MIOLoadFirstFrame\TestTIFMulti.tif');

  // PNG:
  LoadImage('C:\DELPHI\_test\MIOLoadFirstFrame\flowers.png');

  // ICO containing only 1 frame:
  LoadLargestFrameFromIco('C:\DELPHI\_test\MIOLoadFirstFrame\Testicon2.ico');

  mimgTest.SelectedImage := 0;
  ShowFilePathInStatusBar(0);
end;




Here is the whole project, so you can test it in Delphi:

attach/PeterPanino/2021527165118_MIOLoadFirstFrame_v3.zip
737.9 KB
Go to Top of Page

PeterPanino

860 Posts

Posted - May 26 2021 :  09:53:38  Show Profile  Reply
It is a lot of fun writing code with the ImageEn library!
Go to Top of Page

xequte

38180 Posts

Posted - May 27 2021 :  18:12:09  Show Profile  Reply
Thanks Peter, your code looks good and I don't have any suggestions for optimization.

Nigel
Xequte Software
www.imageen.com
Go to Top of Page

PeterPanino

860 Posts

Posted - May 27 2021 :  18:34:44  Show Profile  Reply
Hi Nigel,

if you want you can use it as a demo for your library.
Go to Top of Page

xequte

38180 Posts

Posted - May 27 2021 :  20:01:33  Show Profile  Reply
Hi Peter

I have added the LoadLargestFrameFromIco() method to the documentation.

Nigel
Xequte Software
www.imageen.com
Go to Top of Page

PeterPanino

860 Posts

Posted - May 28 2021 :  05:58:25  Show Profile  Reply
Hi Nigel,

I have added another optimization to this test project - now in the preview the frame can be selected with the next/previous buttons (and with the PageUp/PageDown/Home/End keys), and the frame number is shown in the preview status bar:



attach/PeterPanino/202152855632_MIOLoadFirstFrame_v4.zip
738.42 KB
Go to Top of Page
  Previous Topic Topic Next Topic  
 New Topic  Reply to Topic
Jump To: