Read an image

Is it possible to read an image from an excel file. I see there is a function getimage but there are no examples 

Hi,
There is really not too much to it: GetImage will return the bytes from the image, and the image type (jpeg, png, etc).

Maybe the most interesting part is how to get an specific image: If you know the name you can use ?@imagename? to get it. If the image doesn?t have a name (pseudo image names like ?image 1? are not really stored and FlexCel won?t find them), then you need to loop over all the images in the sheet.

I?ve added code examples to the documentation of GetImage showing both cases, and the code is below. The method GetImageFromName will retrieve an specific image given its name and save it to disk, while GetAllImagesInSheet will loop over all the images in the sheet and save them to disk.


class function DocExamples.GetExtension(const ImgType: TXlsImgType): string;
begin
  case ImgType of
    TXlsImgType.Bmp:
    begin
      exit('.bmp');
    end;
    TXlsImgType.Emf:
    begin
      exit('.emf');
    end;
    TXlsImgType.Jpeg:
    begin
      exit('.jpg');
    end;
    TXlsImgType.Wmf:
    begin
      exit('.wmf');
    end;
    TXlsImgType.Tiff:
    begin
      exit('.tif');
    end;
    TXlsImgType.Gif:
    begin
      exit('.gif');
    end;
    TXlsImgType.Png:
    begin
      exit('.png');
    end;
    else
    begin
      exit('');
    end;
  end;
end;

class procedure DocExamples.GetImageFromName;
var
  xls: TXlsFile;
  filename: string;
  imageType: TXlsImgType;
  ImageStream: TFileStream;
begin
  xls := TXlsFile.Create('myfile.xlsx');
  try
      //Get an image named "myimage" and save it 
      //as myimage.png, myimage.jpeg, etc depending in the 
      //image type.
      filename := 'myimage';  
      imageType := TXlsImgType.Unknown;
      ImageStream := TFileStream.Create(filename, fmCreate);
      try
        xls.GetImage(1, '@myimage', imageType, ImageStream);
      finally
        ImageStream.Free;
      end;
      TFile.Move(filename, TPath.ChangeExtension(filename, GetExtension(imageType)));
    finally
      xls.Free;
    end;
end;

class procedure DocExamples.GetAllImagesInSheet;
var
  xls: TXlsFile;
  imageType: TXlsImgType;
  i: Int32;
  filename: string;
  ImageStream: TFileStream;
begin
  xls := TXlsFile.Create('myfile.xlsx');
  try
     //Get all the images in the active sheet and save them
     //as myimage1.png, myimage2.jpeg, etc depending in the
     //image type.
    imageType := TXlsImgType.Unknown;
    for i := 1 to xls.ImageCount do
    begin
      filename := 'myimage' + IntToStr(i);
      ImageStream := TFileStream.Create(filename, fmCreate);
      try
        xls.GetImage(i, '', imageType, ImageStream);
      finally
        ImageStream.Free;
      end;
      TFile.Move(filename, TPath.ChangeExtension(filename, GetExtension(imageType)));
    end;
  finally
    xls.Free;
  end;

end;



Adrian Gallero2017-09-12 15:38:29

Hi Adrian

getallimagesinsheet works but getimage by name just returns the image with the specified index number and ignores the name. Is there something I missing 

Thanks Mike


Hi,

My bad, the line for GetAllImagesInSheet should have been:
xls.GetImage(1, '@myimage', imageType, ImageStream, true);

The "@" shortcut currently only works with objectIndexes, not with imageIndexes, so you need to set useObjectIndex to true. I'll review if we can add the shortcut also to imageIndexes.

Side note: The objectpath is a different thing: it is the path to find an image when you have grouped images. The "@" thing is just a fast way to locate images which piggy-backs in the object path and redefines it to give it a different use. In images an object path doesn't have much sense since you can't have an image inside another image, and this is why the "@" shortcut isn't implemented for image indexes. But I'll see if it can be added, to keep consistency.
That works great
Thank you Mike