Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations Chris Miller on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Visualising images 1

Status
Not open for further replies.

liamlaurent

IS-IT--Management
Oct 30, 2006
30
DM
Hello there,

I need to be pointed in the right direction here. What I wanna accomplish is displaying thumbnail views of images that are contained in a folder (much like what is done when you go into the MyDocuments\My Pictures folder in Windows.

I was thinking of using a grid to store the images and their names but I wanted to know if I was giving myself excess work to do.

Does anyone have an easier alternative?

Thanks
Liam
 
Tlistview gives you report, icon, list ect..
but images are stored in Timagelist.

i use the free easylistview

very fast and you can load the images from a file and store them as streams in the items.

i use it to load images from database blobs and display thumbs.

Aaron Taylor
John Mutch Electronics
 
Thanks for the tip. I will download the component and try it out. By the way does it support .jpeg?

Liam
 
it's thumb images are bmp but you can load your jpg resize it convert it to a bmp.

thats what i do with my database, but instead of a jpg file its a jpg blob.

i have 2 neat little routines 1 that gives you back a bmp when you give it a jpg and 1 that resizes a jpg and keeps the aspect ratio, you pass it the image and the size you want.

i'll post it here 4 you when i get home.

Aaron Taylor
John Mutch Electronics
 
Resize JPG
Code:
function ResizeJPG(Source : TJPegImage; W: Integer) : TJPegImage;
var bitmap: TBitmap;
begin
  Try
   bitmap := TBitmap.create;
   result := TJPegImage.create;
   result.PixelFormat:=jf24bit;
   bitmap.width := W;
   bitmap.height := round(Source.Height/(Source.Width/W));
   bitmap.canvas.stretchDraw(rect( 0,0, W, round(Source.Height/(Source.Width/W))), Source);
   result.Assign(bitmap);
   result.JpegNeeded;
  Finally
   bitmap.free;
 end;
end;

Resize BMP
Code:
function ResizeBmp(Source : TBitmap; W: Integer) : TBitmap;
begin
  Result := TBitmap.create;
  Try
   with Result do
    begin
     Width := W;
     Height := round(Source.Height/(Source.Width/W));
     Canvas.StretchDraw(rect( 0,0, W, round(Source.Height/(Source.Width/W))), Source);
    end;
  except
    Result.Free;
    raise;
  end;
end;

Make BMP
Code:
function MakeBmp(Source : TGraphic): TBitmap;
begin
 Result := TBitmap.create;
 Try
   with Result do
    begin
     Width := Source.Width;
     Height := Source.Height;
     Canvas.Draw(0,0,Source);
    end;
  except
    Result.Free;
    raise;
  end;
end;


Aaron Taylor
John Mutch Electronics
 
how to load images into easylistview items

Code:
procedure TThumbForm.LoadThumbsBtnClick(Sender: Tbutton);
var
 Group: TEasyGroup;
 Item: TEasyItem;
 bmpimg: tbitmap;
 Stream: TMemoryStream;
 jpgimg: TJpegimage;
begin
 EasyListview.Groups.clear;
 jpgimg:= tjpegimage.create;
 bmpimg:=Tbitmap.Create;
 Group := EasyListview.Groups.add;
 Group.Caption := 'Images Group1';
 EasyListview.BeginUpdate;
 jpgimg.loadfromfile('c:\image.jpg');
 Item := Group.items.Add;
 Item.Caption := 'Image';

 if not Assigned(Item.Data) then
    begin
     Stream := TMemoryStream.Create;
     Item.Data := Stream;
     bmpimg.assign(ResizeBmp(MakeBmp(jpgimg),134));
     bmpimg.SaveToStream(Stream);
    end;

 EasyListview.EndUpdate;
 bmpimg.Free;
 jpgimg.free;
end;

procedure TThumbForm.EasyListviewItemFreeing Yada Yada...
begin
 Item.Data.Free;
 Item.Data := nil;
end;

procedure TThumbForm.EasyListviewItemImageDrawIsCustom Yada Yada...
begin
 IsCustom:=True;
end;

procedure TThumbForm.EasyListviewItemImageDraw Yada Yada...
var
 img: TBitmap;
begin
 Img:=Tbitmap.Create;
 (Item.Data as TMemoryStream).Position := 0;
 Img.LoadFromStream(Item.Data as TMemoryStream);
 AlphaBlender.Blend(EasyListview, Item, ACanvas,
 RectArray.IconRect, Img);
 Img.Free;
end;

Aaron Taylor
John Mutch Electronics
 
Thanks for the code snippets Aaron.

I modified your ResizeBmp to accommodate both portrait and Landscape images. Hope this code proves useful to you too.

function ResizeBmp(Source : TBitmap; W: Integer) : TBitmap;
begin
Result := TBitmap.create;
Try
with Result do
begin
if (Source.Height/Source.Width >1) then //portrait
begin
Height:=W;
Width:= round(Source.Width/(Source.Height/W));
end
else //Landscape
begin
Width := W;
Height := round(Source.Height/(Source.Width/W));
end;
Canvas.StretchDraw(rect( 0,0, W, round(Source.Height/(Source.Width/W))), Source);
end;
except
Result.Free;
raise;
end;
end;
 
Hello Aaron,

I used the code snippets that you sent but I am having a memory problem while loading the images to the TEasyListView. I have a TreeView with different categories of photos and everytime I click on a category the EasyListView is supposed to load the corresponding images but it seems like it does not free the previously loaded photo streams from memory. The first few sets of photos are displayed ok but when I try to generste the 4th or 5th set I get an EOutOfResources (Not enough storage to execute the command). This is the procedure that I use to load the images:

procedure TForm1.LoadPics;
var
Group: TEasyGroup;
Item: TEasyItem;
bmpimg: tbitmap;
Stream: TMemoryStream;
jpgimg: TJpegimage;

begin

EasyListview1.Groups.clear;
jpgimg:= tjpegimage.create;
bmpimg:=Tbitmap.Create;
Group := EasyListview1.Groups.add;
Group.Caption := TreeView1.Selected.Text;
EasyListview1.BeginUpdate;
dmMain.ADOQuery1.First;

While not dmMain.ADOQuery1.Eof do
begin
jpgimg.loadfromfile(Trim(DataModule1.ADODataSet1.Fields[5].AsString) + '\' + Trim(dmMain.ADOQuery1.FieldByName('id').AsString) + '.ndc');
Item := Group.items.Add;
Item.Caption := Trim(dmMain.ADOQuery1.FieldByName('id').AsString);
Item.Caption := Item.Caption + ' - ' + Trim(dmMain.ADOQuery1.FieldByName('Title').AsString);

if not Assigned(Item.Data) then
begin
Stream := TMemoryStream.Create;
Item.Data := Stream; // <--- compiler stops here
bmpimg.assign(ResizeBmp(MakeBmp(jpgimg),134));
bmpimg.SaveToStream(Stream);
end;
dmMain.ADOQuery1.Next;
end;

EasyListView1.EndUpdate;
bmpimg.Free;
jpgimg.Free;
end;

I tried freeing the TEasyListView's Items manually in the procedure above but ended up with 'Access Violation' errors.

Got any ideas?

Liam
 
its not you, i just found that mine does it too.

ive mentioned it on the components help forum.
i will keep you posted.

Aaron Taylor
John Mutch Electronics
 
Thanks much Aaron,

Let me know when you find a work around. If I find out anything I will be sure to let you know.

Liam
 
Hello Aaron,

I have been monitoring the MustangPeak forum for the past weeks and it seems like they have placed this memory issue on the backburner. I guess we will hahve to revert to using the Listview component that comes with Delphi.

Liam
 
yes i tought that too, seems jim was away or busy.

any way when i made a small test app that he asked me for i decided to remove the my resize bmp and make bmp functions to make it simpler and guess what no more prob.

the fault was that these functions create a result tbitmap that is not being freed.

i dont even know where you would free them, so i moved them to the make thumbs code (see below).

by the way i found that when you resize the bmp it also converts from jpg (see below).

Code:
procedure TThumbForm.Thumbs;
var
 Group: TEasyGroup;
 Item: TEasyItem;
 SourceJpg: TJpegimage;
 ResizedBmp: TBitmap;
 Stream: TMemoryStream;
 I: Integer;
 Const W=134;
begin
 EasyListview.Groups.clear;
 SourceJpg:= TJpegImage.create;
 ResizedBmp:=Tbitmap.Create;
 EasyListview.BeginUpdate;
 TblImages.First;
 while not Tblimages.Eof do
  begin
   SourceJpg.Assign(TblImagesImage);
   //Make Bmp & Resize
   with ResizedBmp do
    begin
     PixelFormat:=pf16bit;
     Width:= W;
     Height := round(SourceJpg.Height/(SourceJpg.Width/W));
     Canvas.StretchDraw(rect( 0,0, W, round(SourceJpg.Height/(SourceJpg.Width/W))), SourceJpg);
    end;
    Group := EasyListview.Groups.add;
    Group.Caption := TblImagesProject.value;
    Item := Group.items.Add;
    Item.Caption := TblImagesProject.value;
    Item.Tag:=TblImagesIDNum.AsInteger;
   if not Assigned(Item.Data) then
    begin
     Stream := TMemoryStream.Create;
     Item.Data := Stream;
     ResizedBmp.SaveToStream(Stream);
    end;
   TblImages.Next;
  end;
 EasyListview.EndUpdate;
 SourceJpg.Free;
 ResizedBmp.Free;
 TblImages.Close;
end;

Aaron Taylor
John Mutch Electronics
 
Thanks Aaron,

I checked out the thread and it makes sense to pass the Dest variable by reference using the var reserved word. That way you can be guaranteed that when the Bmp variable is freed it will free up the momory allocated for the Dest bitmap. I was exploring another variant but I have not had the time to test it out as yet. If it works I will post it here for you as well.

Thanks

Liam
 
Hello Aaron,

I managed to modify your ResizeBmp and MakeBmp functions so that you would be able to use them from a seperate unit rather than place them in your actual code as you did. All you need to do is free the variables you pass to these functions after you have finished working with them. I will place the code snippets here for you when I get home.

On another note I would like to disable multiselect for the EasyListView.This is already done in the Object inspector but whenever I press the [Control] key and click on an item the program pops up an Access Violation Error. Any ideas?

Liam
 
i have no problem with multiselect, enabled or not.

although its disabled by default have you tried enabling and disabling it then compile.

i have found this works sometimes with these sort of problems, dont know why.

Aaron
John Mutch Electronics
 
Hello Aaron,

I opened up my program today and there were no problems with the MultiSelect. Guess it was some bug in the system.

On another note what considerations do I have to make if I wanna put 2 EasyListViews on my form (Each on a different Tab od a PageControl component)?



Liam
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top