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
 Load thumbnails from ImageEnM to String Grid
 New Topic  Reply to Topic
Author Previous Topic Topic Next Topic  

yogiyang

India
730 Posts

Posted - Nov 21 2015 :  08:03:51  Show Profile  Reply
Hello,

How to load thumbnails show in ImageEnM to a string grid?

TIA

Yogi Yang


Yogi Yang

w2m

USA
1990 Posts

Posted - Nov 21 2015 :  08:38:34  Show Profile  Reply
I think to be able to display images in a stringgrid the stringgrid needs to be set to ownerdraw, so you will have to owner draw any text and images. This was posted at StackOverflow which shows how to draw the images. You will also have to draw any text as well if you want to see text:

procedure TForm1.StringGrid1DrawCell(Sender: TObject; ACol, ARow: Longint;
  Rect: TRect; State: TGridDrawState);
var
  s: string;
  aCanvas: TCanvas;
begin
  if (ACol <> 1) or (ARow = 0) then
    Exit;
  s := (Sender as TStringGrid).Cells[ACol, ARow];

  // Draw ImageX.Picture.Bitmap in all Rows in Col 1
  aCanvas := (Sender as TStringGrid).Canvas;  // To avoid with statement
  // Clear current cell rect
  aCanvas.FillRect(Rect);
  // Draw the image in the cell
  if (s = 'online') then
    aCanvas.Draw(Rect.Left, Rect.Top, Image1.Picture.Bitmap)
  else 
    aCanvas.Draw(Rect.Left, Rect.Top, Image2.Picture.Bitmap);
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

xequte

39108 Posts

Posted - Nov 21 2015 :  14:55:59  Show Profile  Reply
Hi

Yes, you will need to ownerdraw the cell as Bill advised above, though you need to draw it at a reduced size to fit into the cell area.

So your code will be something like:

// Get our image
aIEBitmap := ImageEnMView1.GetIEBitmap( idx );

// Adjust our rect to maintain aspect ratio
Rect := GetImageRectWithinArea( Rect, aIEBitmap.Width, aIEBitmap.Height );

// Draw the image
aIEBitmap := RenderToCanvas( (Sender as TStringGrid).Canvas, Rect.Left, Rect.Top, Rect.Right - Rect.Left, Rect.Bottom - Rect.Top, rfFastLinear, 0 );

// Release our image
ImageEnMView1.ReleaseBitmap( idx, False );



See descriptions at:

http://www.imageen.com/help/TImageEnMView.GetTIEBitmap.html
http://www.imageen.com/help/GetImageRectWithinArea.html
http://www.imageen.com/help/TIEBitmap.RenderToCanvas.html


Of course, the other issue is performance as the cell is being redrawn at even refresh. So ensure your TImageEnMView.StoreType is ietThumb, and that the ThumbWidth and ThumbHeight are set bigger than the draw size (but not too much bigger):

http://www.imageen.com/help/TImageEnMView.StoreType.html

That should provide adequate performance, but otherwise you could cache the cell images.

Nigel
Xequte Software
www.xequte.com
nigel@xequte.com
Go to Top of Page

xequte

39108 Posts

Posted - Nov 21 2015 :  15:04:14  Show Profile  Reply
Acutally I decided to create a full example to add to the ImageEn documentation:

// Col 1 of our string grid displays a thumbnail drawn from a TImageEnMView
procedure TForm1.StringGrid1DrawCell(Sender: TObject; ACol, ARow: Longint;
  Rect: TRect; State: TGridDrawState);
var
  aIEBitmap: IEBitmap;
  aCanvas: TCanvas;
  idx: Integer;
begin
  // Col 1 contains thumbnail. Row 0 is fixed header row
  if (ACol <> 1) or (ARow = 0) then
    Exit;

  idx := ARow;
  aCanvas := (Sender as TStringGrid).Canvas;

  // Clear current cell rect
  aCanvas.FillRect( Rect );

  // Get our image
  // Note: don't need to create or free the TIEBitmap
  aIEBitmap := ImageEnMView1.GetIEBitmap( idx );

  // Adjust our rect to maintain the image aspect ratio
  Rect := GetImageRectWithinArea( Rect, aIEBitmap.Width, aIEBitmap.Height );

  // Draw the image
  aIEBitmap := RenderToCanvas( aCanvas, Rect.Left, Rect.Top, Rect.Right - Rect.Left,   Rect.Bottom - Rect.Top, rfFastLinear, 0 );

  // Release our image
  ImageEnMView1.ReleaseBitmap( idx, False );
end;


Nigel
Xequte Software
www.xequte.com
nigel@xequte.com
Go to Top of Page

w2m

USA
1990 Posts

Posted - Nov 22 2015 :  11:26:27  Show Profile  Reply
Nigel,

Unfortunately your code needs a little work to be able to compile it.

I find owner drawing not easy to accomplish, but I gave it a try to improve the code somewhat. One of the problems is drawing a 32-bit icon with a white background to match the grid color. Here, 32-bit images with alpha, draw with a black background. I also find RenderToCanvasWithAlpha difficult to use. Maybe there should a simpler overload that doesn't have to pass 8 integers for the drawing. For now I substituted RenderToCanvasWithAlpha with castcolor to render the black transparent background as white, but this is a poor substitute. Please consider this or add to iexhelperfunctions.

Here is some code to experiment with to fill a owner drawn stringgrid with image properties and a thumbnail. The code I used to show the cells selected state needs work as well. (The entire cell should be selected not just the text).

procedure SetColumnFullWidth(Grid: TStringGrid; ACol: Integer);
var
  I: Integer;
  FixedWidth: Integer;
begin
  with Grid do
    if ACol >= FixedCols then
    begin
      FixedWidth := 0;
      for I := 0 to FixedCols - 1 do
        Inc(FixedWidth, ColWidths[I] + GridLineWidth);
      ColWidths[ACol] := ClientWidth - FixedWidth - GridLineWidth;
    end;
end;

procedure TForm1.FillTheGrid1Click(Sender: TObject);
var
  I: Integer;
begin
  for I := 0 to StringGrid1.RowCount - 1 do
    StringGrid1.Rows[I].Clear;
  StringGrid1.RowCount := ImageEnMView1.ImageCount;
  StringGrid1.Cells[0, 0] := 'Frame';
  StringGrid1.Cells[1, 0] := 'Filename';
  StringGrid1.Cells[2, 0] := 'Thumbnail';
  StringGrid1.Cells[3, 0] := 'Width';
  StringGrid1.Cells[4, 0] := 'Height';
  StringGrid1.Cells[5, 0] := 'Colors';
  StringGrid1.Cells[6, 0] := 'Background';
  for I := 1 to StringGrid1.RowCount - 1 do
  begin
    StringGrid1.Cells[0, I] := IntToStr(I);
    StringGrid1.Cells[1, I] := ImageEnMView1.MIO.Params[I].FileName;
    StringGrid1.Cells[3, I] := IntToStr(ImageEnMView1.MIO.Params[I].Width);
    StringGrid1.Cells[4, I] := IntToStr(ImageEnMView1.MIO.Params[I].Height);
    StringGrid1.Cells[5, I] :=
      IntToStr(ImageEnMView1.MIO.Params[I].BitsPerSample *
      ImageEnMView1.MIO.Params[I].SamplesPerPixel) + '-bit';
    StringGrid1.Cells[6, I] :=
      ColorToString(TRGB2TColor(ImageEnMView1.MIO.Params[I].ICO_Background));
  end;
  SetColumnFullWidth(StringGrid1, 1);
  StringGrid1.Invalidate;
end;

procedure TForm1.StringGrid1DrawCell(Sender: TObject; ACol, ARow: Integer;
  Rect: TRect; State: TGridDrawState);
var
  iIEBitmap: TIEBitmap;
  iCanvas: TCanvas;
  idx: Integer;
  iStrCell: string;
  iRect: TRect;
  s: String;
  iDrawRect: TRect;
  iImageEnProc: TImageEnProc;
  iRGB: TRGB;
begin
  if ImageEnMView1.ImageCount > 0 then
  begin
    StringGrid1.Canvas.FillRect(Rect);
    s := StringGrid1.Cells[ACol, ARow]; // the text in the cell
    if Length(s) > 0 then // is there any text needing to be formatted?
    begin
      iDrawRect := Rect;
     (* if (gdSelected in State) then
      begin
        StringGrid1.Canvas.Brush.Color := clHighlight;
        StringGrid1.Canvas.Font.Color := clHighlightText;
      end
      else
      begin
        StringGrid1.Canvas.Brush.Color := clWindow;
        StringGrid1.Canvas.Font.Color := clWindowText;
      end; *)
      StringGrid1.Canvas.Font.Name := 'Segoe UI';
      StringGrid1.Canvas.Font.Size := 9;
      DrawText(StringGrid1.Canvas.handle,
        Pchar(s), Length(s), iDrawRect, DT_CALCRECT OR DT_WORDBREAK OR DT_LEFT);
      // format the text as required, then use drawRect later as per DT_CALCRECT
      if (iDrawRect.bottom - iDrawRect.top) > StringGrid1.RowHeights[ARow] then
        // Does the row need to be adjusted?
        StringGrid1.RowHeights[ARow] := (iDrawRect.bottom - iDrawRect.top)
        // adjust row height
      else
      begin // fits in one line
        iDrawRect.Right := Rect.Right;
        StringGrid1.Canvas.FillRect(iDrawRect);
        DrawText(StringGrid1.Canvas.handle, Pchar(s), Length(s), iDrawRect,
          DT_LEFT);
      end;
    end;
    // Col 1 contains thumbnail. Row 0 is fixed header row
    if (ACol <> 2) or (ARow = 0) then
      Exit;
    idx := ARow;
    iCanvas := (Sender as TStringGrid).Canvas;
    // Get our image
    // Note: don't need to create or free the TIEBitmap
    iIEBitmap := ImageEnMView1.GetTIEBitmap(idx);
    // Adjust our rect to maintain the image aspect ratio
    Rect := GetImageRectWithinArea(iIEBitmap.Width, iIEBitmap.Height, Rect);
    // aIEBitmap.IEConvertToThumbnail(24, 24, True, rfNone, False, clBlack, False,
    // 1, 1, clWhite, clWhite);
    if ImageEnMView1.MIO.Params[idx].BitsPerSample * ImageEnMView1.MIO.Params
      [idx].SamplesPerPixel = 32 then
    begin
      iImageEnProc := TImageEnProc.Create(nil);
      iImageEnProc.AttachedIEBitmap := iIEBitmap;
      iImageEnProc.CastColor(0, iIEBitmap.Height - 1, TColor2TRGB(clWhite), 5);
      iImageEnProc.CastColor(iIEBitmap.Width - 1, iIEBitmap.Height - 1,
        TColor2TRGB(clWhite), 5);
      { iRGB := iIEBitmap.Pixels[0, iIEBitmap.Height - 1];
        iImageEnProc.SetTransparentColors(iRGB, iRGB, 0); }
      iImageEnProc.Free;
    end;
    // Draw the image
    iIEBitmap.RenderToCanvas(iCanvas, Rect.Left, Rect.top,
      Rect.Right - Rect.Left, Rect.bottom - Rect.top, rfFastLinear, 0);
    { aIEBitmap.RenderToCanvasWithAlpha(aCanvas, Rect.Left, Rect.Top,
      Rect.Right - Rect.Left, Rect.Bottom - Rect.Top, 0, 0, 0, 0, 255, rfNone, ielNormal, 255); }
    // Release our image
    ImageEnMView1.ReleaseBitmap(idx, False);
  end;
end;

Screen Capture of Result


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

xequte

39108 Posts

Posted - Nov 22 2015 :  12:58:48  Show Profile  Reply
Nice one, Bill

Nigel
Xequte Software
www.xequte.com
nigel@xequte.com
Go to Top of Page

w2m

USA
1990 Posts

Posted - Nov 22 2015 :  13:00:19  Show Profile  Reply
What is your opinion on this:
"I also find RenderToCanvasWithAlpha difficult to use. Maybe there should a simpler overload that doesn't have to pass 8 integers for the drawing."

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

w2m

USA
1990 Posts

Posted - Nov 22 2015 :  14:32:30  Show Profile  Reply
It is much easier to use a TListView with an imagelist to hold the thumbnails than it is to use a ownerdrawn string list. It requires much less code, is easy to use and produces better results with 32-bit images.

procedure TForm1.Fill1Click(Sender: TObject);
{ Fill ImageEnMView. }
begin
  ImageEnMView1.Clear;
  {FillFromDirectory with load on demand set to false}
  ImageEnMView1.FillFromDirectory(Folder1.Text, -1, False, '', False);
  ImageEnMView1.SelectedImage := 0;
end;

procedure TForm1.FillTheListview1Click(Sender: TObject);
{ Fill the listview with image properties and a thumbnail.}
var
  i: Integer;
  iItem: TListItem;
  iIEBitmap: TIEBitmap;
  iImageEnProc: TImageEnProc;
  iRGB: TRGB;
  iCounter: integer;
begin
  ListView1.Clear;
  { ImageList1 is set to hold 32x32 images with a colordepth of cd32Bit. Mask is true. }
  { Set the ListView small images to Imagelist1 }
  ImageList1.Clear;
  for i := 0 to ImageEnMView1.ImageCount - 1 do
  begin
    {Get the bitmap from ImageEnMView}
    iIEBitmap := ImageEnMView1.GetTIEBitmap(i);
    {Convert the bitmap to a 32x32 thumbnail}
    iIEBitmap.IEConvertToThumbnail(32, 32, True, rfNone, False, clBlack, False,
      1, 1, clBlack, clWhite);
    { Set the transparent color }
    iImageEnProc := TImageEnProc.Create(nil);
    iImageEnProc.AttachedIEBitmap := iIEBitmap;
    iRGB := iIEBitmap.Pixels[0, iIEBitmap.Height - 1];
    iImageEnProc.SetTransparentColors(iRGB, iRGB, 0);
    { Add the image to the image list }
    ImageList1.Masked := True;
    ImageList1.AddMasked(iIEBitmap.VclBitmap, clBlack);
    { Release the iIEBitmap }
    ImageEnMView1.ReleaseBitmap(i, False);
    { Free iImageEnProc }
    iImageEnProc.Free;
  end;
  iCounter := 0;
  { Fill the Listview }
  for i := 0 to ImageEnMView1.ImageCount - 1 do
  begin
    iItem := ListView1.Items.Add;
    Inc(iCounter);
    { Set the imageindex to -1 so icons do not appear with the caption }
    iItem.ImageIndex := -1;
    { Set the caption }
    iItem.Caption := IntToStr(iCounter);
    { Add the filename as a subitem }
    iItem.SubItems.Add(ImageEnMView1.MIO.Params[i].FileName);
    { Add a subitem for the thumbnail }
    iItem.SubItems.Add('');
    { Set the thumbnail subitem subitemimageindex }
    iItem.SubItemImages[1] := i;
    iItem.SubItems.Add(IntToStr(ImageEnMView1.MIO.Params[i].Width));
    iItem.SubItems.Add(IntToStr(ImageEnMView1.MIO.Params[i].Height));
    iItem.SubItems.Add(IntToStr(ImageEnMView1.MIO.Params[i].BitsPerSample *
      ImageEnMView1.MIO.Params[i].SamplesPerPixel) + '-bit');
    iItem.SubItems.Add(ColorToString(TRGB2TColor(ImageEnMView1.MIO.Params[i]
      .ICO_Background)));
  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

xequte

39108 Posts

Posted - Nov 22 2015 :  17:12:20  Show Profile  Reply
Hi Bill

Well the values for xSrc, ySrc, dxSrc, dySrc, will generally be 0, 0, Width, Height, so for example you might use:

// Draw aIEBitmap within aRect while maintaining the aspect ratio of the image:
aRect := GetImageRectWithinArea( aIEBitmap.Width, aIEBitmap.Height, aRect );
aIEBitmap.RenderToCanvasWithAlpha( aCanvas, aRect.Left, aRect.Top, aRect.Right - aRect.Left, aRect.Bottom - aRect.Top, 0, 0, aIEBitmap.Width, aIEBitmap.Height, 255, rfFastLinear );

I'll add this to the documentation.


Nigel
Xequte Software
www.xequte.com
nigel@xequte.com
Go to Top of Page

yogiyang

India
730 Posts

Posted - Nov 23 2015 :  09:17:09  Show Profile  Reply
Thanks everyone for help on my problem.

I really appreciate it.

I will implement this code and if I do run into any problem I will post here.

Regards,



Yogi Yang
Go to Top of Page
  Previous Topic Topic Next Topic  
 New Topic  Reply to Topic
Jump To: