Author |
Topic  |
|
yogiyang
   
India
730 Posts |
Posted - Nov 21 2015 : 08:03:51
|
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
|
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 |
 |
|
xequte
    
39108 Posts |
Posted - Nov 21 2015 : 14:55:59
|
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 |
 |
|
xequte
    
39108 Posts |
Posted - Nov 21 2015 : 15:04:14
|
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
|
 |
|
w2m
   
USA
1990 Posts |
Posted - Nov 22 2015 : 11:26:27
|
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 |
 |
|
xequte
    
39108 Posts |
|
w2m
   
USA
1990 Posts |
Posted - Nov 22 2015 : 13:00:19
|
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 |
 |
|
w2m
   
USA
1990 Posts |
Posted - Nov 22 2015 : 14:32:30
|
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 |
 |
|
xequte
    
39108 Posts |
Posted - Nov 22 2015 : 17:12:20
|
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
|
 |
|
yogiyang
   
India
730 Posts |
Posted - Nov 23 2015 : 09:17:09
|
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 |
 |
|
|
Topic  |
|
|
|