Displaying images from db on the go

1k views Asked by At

In Delphi I have an unknown number of image file names stored in a details table. These image files can be Bitmaps, Jpegs, PNGS and ICO files.

What's the paradigm / best practice to load and display those in a listview or a listbox on the go?
I take it I would somehow need to load those to a ImageList in OnBeforeScroll event of a master table and then assign that to a listview. Database components used are dbGO.

I only need to display thumbnails of predefined size (in a VCL program).

2

There are 2 answers

1
bummi On BEST ANSWER

The simplest method is to use TPicture, since the loading of different graphic formats is already implemented and you do have to care about different image classes .
You have to ensure that the required units are included in the with uses so here e.g. jpeg, gifimg, and pngimg.
After loading with TPicture.LoadFromFile the images are painted, centered and scaled, on a prepared Bitmap with the dimensions of the Imagelist.
Last step is simply to call teh AddBitmap procedure with the Bitmap and nil for the mask.

// make sure you included the needed units
// uses pngImage,jpeg,gifimg;

Procedure LoadImagesFromDataset2ImageList(il: TImageList; DS: TDataset; const FileFieldname: String);
var
  P: TPicture;
  bmp: TBitmap;

  Function CalcRectAndPrepare: TRect; // calculate Rect for here centered/streched output
  var // and fill the bitmap with the desired beckground color
    f: Double;
  begin
    bmp.Canvas.Brush.Color := clWhite;
    bmp.Canvas.FillRect(Rect(0, 0, bmp.Width, bmp.Height));
    if P.Width > P.Height then
      f := bmp.Width / P.Width
    else
      f := bmp.Height / P.Height;
    Result.Left := Round(bmp.Width - P.Width * f) div 2;
    Result.Top := Round(bmp.Height - P.Height * f) div 2;
    Result.Right := bmp.Width - Result.Left;
    Result.Bottom := bmp.Height - Result.Top;
  end;

begin
  P := TPicture.Create;
  bmp := TBitmap.Create;
  try
    bmp.Width := il.Width;
    bmp.Height := il.Height;
    DS.First;
    while not DS.Eof do
    begin
      if FileExists(DS.Fieldbyname(FileFieldname).asString) then
      begin
        P.LoadFromFile(DS.Fieldbyname(FileFieldname).asString);
        bmp.Canvas.StretchDraw(CalcRectAndPrepare, P.Graphic);
        il.Add(bmp, nil);
      end;
      DS.Next;
    end;
  finally
    P.Free;
    bmp.Free;
  end;
end;
1
mjn On

"Unknown number" sounds like there may be a huge number of images. So pre-rendered thumbnails would be very helpful. If your application can create thumbnails for all images and keep them in a separate database this would reduce the CPU resource usage for shrinking them. And you could reference the thumbnail database from your master database.

One thing I would check if RAM could be a limitation is how many instances of the actual thumbnail will be created in your application, for example if you load 1000 database records which all refer to the same thumbnail, does the database access component allocate 1000 image objects (using 1000 times more RAM than needed) or only one, which is referenced 1000 times. Also the de-allocation of the image data is important.