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
 Extract smallest picture from multiframe icon
 New Topic  Reply to Topic
Author Previous Topic Topic Next Topic  

dogofulaji-doanart

5 Posts

Posted - Mar 26 2017 :  14:06:42  Show Profile  Reply
i have multiframe icons that contains more than 1 different sized pictures.
how to extract and save to file the smallest picture from multiframe icon?

w2m

USA
1990 Posts

Posted - Mar 26 2017 :  14:09:33  Show Profile  Reply
Are you using TImageEnView to display all the icons or are you displaying one icon at a time in TImageEnView?

Bill Miller
Adirondack Software & Graphics
Email: w2m@hughes.net
EBook: http://www.imageen.com/ebook/
Custom Commercial ImageEn Development
Go to Top of Page

dogofulaji-doanart

5 Posts

Posted - Mar 26 2017 :  15:26:26  Show Profile  Reply
I don't need to display icons. I want only save the smallest icon loaded by this way: ImageEnIO.LoadFromFileICO('D:\1.ico');
Go to Top of Page

w2m

USA
1990 Posts

Posted - Mar 26 2017 :  18:11:47  Show Profile  Reply
Based on your criteria, this may not be possible because icons often and usually have more than 1 icon with the same width such as 16x16 4-bit, 16x16 8-bit, 16x16 24-bit and 16x16, 32-bit. As such, it is impossible to get the smallest icon based on the minimum width because in this case there are 4 icons, all with the same dimensions.

Even if you searched the icon for 16x16 24-bit frames there still can be more than one icon frame with a width of 16 and a bit depth of 24.

So I suppose at best, you need to search not only for the minimum size, but a specific bit depth as well. Even then the search may be incorrect if there are more than one frame with the same width and bit depth.

To get you started here is some code:
procedure TForm1.Open1Click(Sender: TObject);
begin
  if OpenPictureDialog1.Execute then
  begin
    if FileExists(OpenPictureDialog1.FileName) then
      ImageEnIO1.LoadFromFile(OpenPictureDialog1.FileName);
  end;
end;

procedure TForm1.SaveSmallestFrame1Click(Sender: TObject);
var
  i: integer;
  iFrames: integer;
  iWidth1: integer;
  iWidth2: integer;
  iSmallestIndex: integer;
  iSmallestWidth: integer;
  iBitDepth: integer;
begin
  if SavePictureDialog1.Execute then
  begin
    iSmallestIndex := -1;
    if FileExists(OpenPictureDialog1.FileName) then
    begin
      ImageEnIO1.LoadFromFile(SavePictureDialog1.FileName);
      iFrames := ImageEnIO1.Params.ImageCount;
      for i := 0 to iFrames - 1 do
      begin
        ImageEnIO1.Params.ImageIndex := i;
        iWidth1 := ImageEnIO1.Params.Width;
        iBitDepth := ImageEnIO1.Params.BitsPerSample * ImageEnIO1.Params.SamplesPerPixel;
        { Search only for 24-Bit icons }
        if iBitDepth <> 24 then
          break;
        ImageEnIO1.Params.ImageIndex := i + 1;
        iWidth2 := ImageEnIO1.Params.Width;
        iSmallestWidth := Min(iWidth1, iWidth2);
        if iWidth1 = iSmallestWidth then
          iSmallestIndex := i;
      end;
      if iSmallestIndex <> -1 then
      begin
        ImageEnIO1.Params.ImageIndex := iSmallestIndex;
        ImageEnIO1.SaveToFile(OpenPictureDialog1.FileName);
      end;
    end;
end;

I have not taken the time to test this, but it will get you started.
Nigel may also have some ideas to accomplish this.

Another much simpler and more reliable way would be to load the icons into a TImageEnMView, set EnableMultipleSelect property to true then select the frame you want to save and call this:

procedure TForm1.Open1Click(Sender: TObject);
{ Open the image. }
var
  i: Integer;
begin
  OpenPictureDialog1.DefaultExt := 'png';
  OpenPictureDialog1.Filename := ExtractFileName(AFilename);
  if OpenPictureDialog1.Execute then
  begin
    if FileExists(OpenPictureDialog1.Filename) then
    begin
      AFilename := OpenPictureDialog1.Filename;
      ImageEnMView1.MIO.LoadFromFile(AFilename, False);
      if ImageEnMView1.MIO.Aborting then
      begin
        MessageBox(0, 'An error occurred opening the file.', 'Error', MB_ICONERROR or MB_OK);
        exit;
      end;
      ImageEnMView1.SelectedImage := 0;
      { Set the frame to load }
      ImageEnView1.IO.Params.ImageIndex := ImageEnMView1.SelectedImage;
      { Load the frame }
      ImageEnView1.IEBitmap.AssignImage(ImageEnMView1.GetTIEBitmap(ImageEnMView1.SelectedImage));
      ImageEnView1.Update;
      ImageEnView1.IEBitmap.Modified := False;
      for i := 0 to ImageEnMView1.ImageCount - 1 do
      begin
        ImageEnMView1.ImageBottomText[i] := 'Frame ' + IntToStr(i + 1);
        if ImageEnMView1.MIO.Params[i].FileType = ioICO then
        begin
          case ImageEnMView1.MIO.Params[i].ICO_BitCount[i] of
            32:
              begin
                ImageEnMView1.MIO.Params[i].BitsPerSample := 8;
                ImageEnMView1.MIO.Params[i].SamplesPerPixel := 4;
              end;
            24:
              begin
                ImageEnMView1.MIO.Params[i].BitsPerSample := 8;
                ImageEnMView1.MIO.Params[i].SamplesPerPixel := 3;
              end;
            8:
              begin
                ImageEnMView1.MIO.Params[i].BitsPerSample := 8;
                ImageEnMView1.MIO.Params[i].SamplesPerPixel := 1;
              end;
            4:
              begin
                ImageEnMView1.MIO.Params[i].BitsPerSample := 4;
                ImageEnMView1.MIO.Params[i].SamplesPerPixel := 1;
              end;
          end; // case
        end;
      end;
      if ImageEnView1.IO.Params.BitsPerSample * ImageEnView1.IO.Params.SamplesPerPixel = 32 then
      begin
        { If the bitdepth is 32 then display with a chessboard style }
        ImageEnView1.Background := clBtnFace;
        ImageEnView1.BackgroundStyle := iebsChessboard;
        ImageEnView1.SetChessboardStyle(8);
        ImageEnView1.Update;
      end;
      ImageEnView1.Fit;
    end;
  end;
end;

procedure TForm1.SaveAs1Click(Sender: TObject);
{ Save the image with a new filename. }
begin
  SavePictureDialog1.DefaultExt := 'ico';
  SavePictureDialog1.Filename := JustName(AFilename);
  if SavePictureDialog1.Execute then
  begin
    Screen.Cursor := crHourGlass;
    try
      AFilename := SavePictureDialog1.Filename;
      { Save only selected frame }
      ImageEnMView1.MIO.SaveToFile(AFilename, True);
      if ImageEnMView1.MIO.Aborting then
      begin
        MessageBox(0, 'An error occurred saveing the file.', 'Error', MB_ICONERROR or MB_OK);
        exit;
      end;
      ImageEnView1.IEBitmap.Modified := False;
    finally
      Screen.Cursor := crDefault;
    end;
  end;
end;

Bill Miller
Adirondack Software & Graphics
Email: w2m@hughes.net
EBook: http://www.imageen.com/ebook/
Custom Commercial ImageEn Development
Go to Top of Page

dogofulaji-doanart

5 Posts

Posted - Mar 27 2017 :  04:39:24  Show Profile  Reply
Hi, Biil!
Thanks for the detailed answer!
It's no matter which bit depth have an icon, i need to save the first searched icon that have 16x16 size.

I tried to use your code procedure TForm1.SaveSmallestFrame1Click(Sender: TObject);, but it seems iFrames := ImageEnIO1.Params.ImageCount; function works not correct. It returns "1", despite the specified icon have 4 frames (this icon: https://mail.ru/favicon.ico). Why is so?
Go to Top of Page

w2m

USA
1990 Posts

Posted - Mar 27 2017 :  09:42:14  Show Profile  Reply
You have a very old version - Imageen v.4.1.4 which does not work well with icons. Some of the more modern versions of ImageEn were greatly enhanced for handing icons so your only choice is to update to the current version. This is especially true when dealing with icons.

It is possible however, that EnumICOIm function is in this early version which may work for you to return the number of images inside an ICO file,

EnumICOIm

Declaration

function EnumICOIm(const FileName: WideString): Integer;

Description

Returns the number of images inside an ICO file.
If the FileName doesn't exist or doesn't contain images, it returns 0.

Bill Miller
Adirondack Software & Graphics
Email: w2m@hughes.net
EBook: http://www.imageen.com/ebook/
Custom Commercial ImageEn Development
Go to Top of Page
  Previous Topic Topic Next Topic  
 New Topic  Reply to Topic
Jump To: