我的程序管理“项目”(将它们想象成庄严的家)并与每个项目关联零个、一个或多个图像。到目前为止,这些都在数据库之外。数据库中的项目通过文件名和路径指向图像。图像保存在专用文件夹树中。现在需要将图像移动到数据库本身。 需要处理的图像类型有: jpeg(最常见,有时大到 4 Mb) bmp(也很常见,而且很大) PNG 电动势 wmf gif(仅静态,罕见,但确实会出现)。
目前,当一个文件与一个项目相关联时,除了在图像数据库表中创建一个条目之外,没有对图像做任何事情。当用户查看项目时,将使用 ShellBrowser 显示图像缩略图以访问文件并生成显示在屏幕上的 96 x 96 缩略图位图。
我的计划是将图像和缩略图作为每个记录的两个新 BLOB 字段存储在图像表中,全图和缩略图,都是位图。
这是我第一次涉足数据库中的图像,所以请耐心等待我加快速度。
问题一:下面的代码段是否将上述6种文件类型转换为完整的图像位图?好像是这样的
uses
Graphics, Jpeg, pngimage, GIFImg;
procedure TForm1.Button1Click (Sender: TObject);
var
Picture: TPicture;
Bitmap: TBitmap;
begin
Picture := TPicture.Create;
try
Picture.LoadFromFile('C:\imagedata.dat');
Bitmap := TBitmap.Create;
try
Bitmap.Width := Picture.Width;
Bitmap.Height := Picture.Height;
Bitmap.Canvas.Draw(0, 0, Picture.Graphic);
Bitmap.SaveToFile('C:\test.bmp');
finally
Bitmap.Free;
end;
finally
Picture.Free;
end;
end;
问题 2:如何使用 TStream 或 TMemoryStream 将位图移动到 Blob 字段中?优势和问题的对比。代码将位图移动到流以及从流到 BLOB ??
问题三:我的感觉是,将原始文件存储在Blob字段中,占用空间小,但更难在屏幕上呈现。有什么想法吗?
TPicture.LoadFromFile()
使用文件扩展名来知道使用哪个 TGraphic
类来加载数据。除非您创建了自定义类,否则标准类都不会使用 .dat
.
使用
TDataSet.CreateBlobStream()
和TGraphic.SaveToStream()
/LoadFromStream()
。不过,我不会强行将所有图像转换为 BMP 进行存储。那会使数据库膨胀。 JPG 和 PNG 更加紧凑。
存储在blob中的图像可以显示在
TDBImage
中。或者,您可以简单地自己加载图像,然后将其分配给TImage
.
既然我现在已经设法回答了我原来的问题,我觉得发布我最终的“研究”代码是合适的,以防将来它可能对其他人有用。
需要说的是,已经决定将图像保存在数据库之外以避免膨胀,但将缩略图保存在数据库中。
uses Vcl.imaging.pngimage, Vcl.imaging.GIFImg, Vcl.imaging.jpeg;
procedure TImagesInABLOB.LoadImageButtonClick (Sender: TObject);
var
Name_And_Path_File_Selected: string;
File_Extension: string;
Local_ShellBrowser: TShellBrowser;
Thumbnail_Bitmap: TBitmap;
Thumbnail_Stream: TMemoryStream;
ADO_Stream: TADOBlobStream;
mRect: TRect;
nRect: TRect;
label
Load_Thumbnail_Into_DB;
begin
// Using ShellBrowser, create a 96 x 96 pixel thumbnail image as a bitmap.
// ShellBrowser returns nil when the image type is .emf or .wmf.
// The bitmap created is upside down and must be rotated 180 degrees.
Local_ShellBrowser := TShellBrowser.Create(Self);
try
Local_ShellBrowser.FullPath := Name_And_Path_File_Selected;
Thumbnail_Bitmap := Local_ShellBrowser.GetThumbnailBitmap (96, 96, False);
finally
Local_ShellBrowser.Free;
end;
if (Thumbnail_Bitmap <> nil) then
begin // Turn bitmap upside down.
mRect := rect (0, 0, Thumbnail_Bitmap.Width, Thumbnail_Bitmap.Height);
nRect := rect (0, Thumbnail_Bitmap.Height - 1, Thumbnail_Bitmap.Width, -1);
Thumbnail_Bitmap.Canvas.CopyRect(mRect, Thumbnail_Bitmap.Canvas, nRect);
goto Load_Thumbnail_Into_DB;
end;
// If the image file extension is .emf or .wmf, call an appropriate routine to
// to create a thumbnail bitmap from the metafile.
File_Extension := LowerCase(ExtractFileExt(Name_And_Path_File_Selected));
if ((Thumbnail_Bitmap = nil) and (File_Extension = '.emf')) then
begin
Get_EMF_Thumbnail (Name_And_Path_File_Selected, 96, 96, Thumbnail_Bitmap);
if (Thumbnail_Bitmap = nil) then
JFMessageDlg ('Thumbnail could not be created from the .emf file.', mtError, [mbOK], [Txt_Btn_Caption_OK]);
goto Load_Thumbnail_Into_DB;
end;
if ((Thumbnail_Bitmap = nil) and (File_Extension = '.wmf')) then
begin
Get_WMF_Thumbnail (Name_And_Path_File_Selected, 96, 96, Thumbnail_Bitmap);
if (Thumbnail_Bitmap = nil) then
JFMessageDlg ('Thumbnail could not be created from the .wmf file.', mtError, [mbOK], [Txt_Btn_Caption_OK]);
end;
// If Thumbnail_Bitmap exists, load the thumbnail bitmap into the current record
// record of the Oracle table and release the thumbnail bitmap.
Load_Thumbnail_Into_DB:
if (Thumbnail_Bitmap <> nil) then
begin
if ((QryImages_In_BLOB.State <> dsEdit) and (QryImages_In_BLOB.State <> dsInsert)) then
QryImages_In_BLOB.Edit;
ADO_Stream := TADOBlobStream.Create(QryImages_In_BLOBTHUMBNAIL_IMAGE, bmWrite);
try
Thumbnail_Bitmap.SaveToStream(ADO_Stream);
finally
ADO_Stream.Free;
end;
Thumbnail_Bitmap.Free;
end;
// Post any change made to the current record.
if ((QryImages_In_BLOB.State = dsEdit) or (QryImages_In_BLOB.State = dsInsert)) then
QryImages_In_BLOB.Post;
end;
{--------------------------------------------------------------------------------}
procedure TImagesInABLOB.Get_EMF_Thumbnail (const Path: Unicodestring; Width:
Integer; Height: Integer; out Bitmap: TBitmap);
var
APicture: TPicture;
begin
if (LowerCase(ExtractFileExt(Path)) = '.emf') then
begin
APicture := TPicture.Create;
try
APicture.LoadFromFile(Path);
Bitmap := TBitmap.Create; // Must be freed by the caller.
Bitmap.PixelFormat := pf24bit;
Bitmap.Width := Width;
Bitmap.Height := Height;
Bitmap.Canvas.Lock; // Important in multithreaded applications,
// see http://qc.embarcadero.com/wc/qcmain.aspx?d=55871
Bitmap.Canvas.StretchDraw(Rect(0, 0, Width, Height), APicture.Graphic);
Bitmap.Canvas.Unlock;
finally
APicture.Free;
end;
end;
end;
{------------------------------------------------------------------------}
procedure TImagesInABLOB.Get_WMF_Thumbnail (const Path: Unicodestring; Width:
Integer; Height: Integer; out Bitmap: TBitmap);
var
APicture: TPicture;
begin
if (LowerCase(ExtractFileExt(Path)) = '.wmf') then
begin
APicture := TPicture.Create;
try
APicture.LoadFromFile(Path);
Bitmap := TBitmap.Create; // Must be freed by the caller.
Bitmap.PixelFormat := pf24bit;
Bitmap.Width := Width;
Bitmap.Height := Height;
Bitmap.Canvas.Lock; // Important in multithreaded applications,
// see http://qc.embarcadero.com/wc/qcmain.aspx?d=55871
Bitmap.Canvas.StretchDraw(Rect(0, 0, Width, Height), APicture.Graphic);
Bitmap.Canvas.Unlock;
finally
APicture.Free;
end;
end;
end;