T O P I C R E V I E W |
hinsona |
Posted - May 07 2021 : 01:04:39 I have a project in Delphi 7. I'm using ImageEn 9.3.1.
Code that I've been using for several years to load images from a query using a blobstream throws an AV when calling LoadFromStream. Has something changed or am I doing something wrong?
I've broken the code into a sample project to illustrate the issue. I've uploaded it to OneDrive since it was giving me an issue attaching it. https://1drv.ms/u/s!AsNfPwVDI-xGsMxUnIrcMgBCb9BBIg
There is a .SQL file in the project zip that contains a query to add a test table and insert the images I am using, if needed.

unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, ieview, iemview, DB, ADODB, imageenview, hyiedefs, hyieutils, iemio, imageenio,
iexBitmaps, StdCtrls;
type
TForm1 = class(TForm)
DataSource1: TDataSource;
ImgEnMv: TImageEnMView;
QryImages: TADOQuery;
Label1: TLabel;
procedure ImgEnMvImageIDRequestEx(Sender: TObject; Index, ID: Integer; var Bitmap: TIEBitmap);
procedure FormCreate(Sender: TObject);
private
{ Private declarations }
TmpEnV: TImageEnView;
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.FormCreate(Sender: TObject);
begin
TmpEnV := TImageEnView.Create(nil);
ImgEnMv.Clear;
QryImages.Close;
QryImages.Open;
QryImages.First;
while not QryImages.Eof do
begin
ImgEnMv.ImageID[ImgEnMv.AppendImage] := QryImages.RecNo;
QryImages.Next;
end;
end;
procedure TForm1.ImgEnMvImageIDRequestEx(Sender: TObject; Index, ID: Integer; var Bitmap: TIEBitmap);
var
s: TStream;
begin
s := QryImages.CreateBlobStream(QryImages.FieldByName('ImageData'), bmRead);
s.Position := 0;
try
try
if (TmpEnV.IO.LoadFromStream(s)) then
Bitmap := TmpEnV.IO.IEBitmap;
except on e: Exception do
Label1.Caption := 'An error occurred while loading image, Index: ' + IntToStr(Index) + ', ID: ' + IntToStr(ID) + ' Error:' + E.Message;
end;
finally
s.Free;
end;
end;
end.
Thank you. |
6 L A T E S T R E P L I E S (Newest First) |
hinsona |
Posted - May 10 2021 : 01:12:47 Ah yes, that was the fix. I missed that, thank you. |
xequte |
Posted - May 10 2021 : 01:02:21 Yes, note the TODO in the code above. You need to position your database at the correct id.
Nigel Xequte Software www.imageen.com
|
hinsona |
Posted - May 09 2021 : 23:21:39 This doesn't crash, but it loads the same image for every image.
https://i.imgur.com/A5hXce9.png |
hinsona |
Posted - May 09 2021 : 23:07:13 I will give this a try. Thank you. |
xequte |
Posted - May 09 2021 : 22:23:34 Hi
The control will automatically free the TIEBitmap you pass to the OnImageIDRequestEx event, so you cannot use a TImageEnView.IEBitmap. You should create a temporary object instead.
Also, you can just read directly to the TIEBitmap:
procedure TForm1.ImgEnMvImageIDRequestEx(Sender: TObject; Index, ID: Integer; var Bitmap: TIEBitmap);
var
s: TStream;
begin
// todo: Position table at ID
s := QryImages.CreateBlobStream(QryImages.FieldByName('ImageData'), bmRead);
s.Position := 0;
try
try
Bitmap := TIEBitmap.create;
Bitmap.Read( s, ioJPEG );
except
on e: Exception do
Label1.Caption := 'An error occurred while loading image, Index: ' + IntToStr(Index) + ', ID: ' + IntToStr(ID) + ' Error:' + E.Message;
end;
finally
s.Free;
end;
end;
Nigel Xequte Software www.imageen.com
|
hinsona |
Posted - May 09 2021 : 20:24:31 I tried modifying the DBMultiBitmap example project by adding an ADO query using the same data and it didn't work either.
If I point a reporting services report at the data and tell it the column is a jpeg image it displays correctly, so the data appears to be intact.
The data was inserted using the following...
Files are selected in TImageEnFolderMView.
for I := 0 to AImgFMView.ImageCount -1 do
begin
if (AImgFMView.Checked[I]) then
begin
srcPath := AImgFMView.MIO.Params[I].Filename;
if not ieImage.IO.LoadFromFileAuto(srcPath) then
begin
ShowMessage(GetMsg('Unable to load the image file: ' + #13 +
'[' + srcPath + '].' + #13 +
'This image will be skipped.',0));
Continue;
end;
//Create new image index in iemImage
newI := iemImage.AppendImage;
//Set the IEBitmap at newI in iemImage to the IEBitmap at I in AImgFMView
//iemImage.SetIEBitmap(newI, AImgFMView.GetTIEBitmap(I));
iemImage.SetImage(newI, ieImage.IO.IEBitmap);
//Release the temporary bitmap in AImgFMView to free memory
AImgFMView.ReleaseBitmap(I);
//Copy the MIO.Params and text from AImgFMView to iemImage
iemImage.MIO.Params[newI].Assign(AImgFMView.MIO.Params[I]);
ImgTop_ImgSeq := DMImages.GetNextSeq(TicketId);
ImgBottom_TypeId := AImgFMView.ImageBottomText[I];
ImgInfo_Info := AImgFMView.ImageInfoText[I];
iemImage.ImageTopText[newI] := IntToStr(ImgTop_ImgSeq);
iemImage.ImageBottomText[newI] := ImgBottom_TypeId;
iemImage.ImageInfoText[newI] := ImgInfo_Info;
//get the local user profile temp folder
tmpPath := GetSpecialFolderPath(CSIDL_LOCAL_APPDATA) + '\Temp\';
if (AResizeOnImport) then
begin
//resample oversized images to save space
if (ieImage.IO.IEBitmap.Width > ieImage.IO.IEBitmap.Height) then
begin
if (ieImage.IO.IEBitmap.Width > 1024) then // resample it
ieImage.Proc.Resample(1024, -1, rfLanczos3, True);
end
else
begin
if (ieImage.IO.IEBitmap.Height > 1024) then // resample it
ieImage.Proc.Resample(-1, 1024, rfLanczos3, True);
end;
end;
// Save as JPEG
ImgFormat := ioJPEG;
ieImage.IO.StreamHeaders := False;
ieImage.IO.Params.JPEG_Progressive := True;
ieImage.IO.Params.JPEG_Smooth := 50;
ieImage.IO.Params.JPEG_Quality := 60;
ieImage.IO.Params.JPEG_ColorSpace := ioJPEG_YCbCr;
// Generate a temp file name so there are no issues
tmpFileName := CreateTmpFileName(tmpPath, 'tmpimg', '.jpg');
// Save the temp file to the temp path
ieImage.IO.SaveToFileJpeg(tmpPath + tmpFileName);
// Blank the image to clear the canvas
ieImage.Blank();
// Add the image to the database
try
DMImage.SaveImage(TicketId, tmpPath + tmpFileName, ImgBottom_TypeId, ImgInfo_Info, ImgTop_ImgSeq, ImgFormat);
if (ADelAfterImport) then
ImgsToDel.Add(srcPath);
except
// The save failed ... remove the current image from iemImage
iemImage.DeleteImage(newI);
raise;
end;
DelFile(tmpPath + tmpFileName);
end;
procedure TDMImage.SaveImage(TicketId, tmpFilePath, ImgBottom_TypeId, ImgInfo_Info: String; ImgTop_DocSeq: Integer; ImgFormat: TIOFileType);
var
s: TStream;
tmpIE: TImageEnView;
begin
tmpIE := TImageEnView.Create(nil);
fCNN.ShowWaiting('Saving images...', aviCopyFile);
try
tmpIE.IO.LoadFromFile(tmpFilePath, ImgFormat);
except
raise EError.Create('An error occurred loading a temporary file. Unable to save image, try again by importing images from Void/View.', 0, svWarning, False);
end;
if not (fCNN.InTransaction) then
begin
fCNN.StartTransaction;
qryImages.Close;
qryImages.SQL.Clear;
qryImages.SQL.Add('select * from TICKET_IMAGE where Id = 0x' + StrToHex(Id));
qryImages.Open;
qryImages.Insert;
s := qryImages.CreateBlobStream(qryImages.FieldByName('ImageData'), bmWrite);
try
try
if (tmpIE.IO.SaveToStream(s, ImgFormat)) then
begin
qryImages.FieldByName('Id').AsString := Id;
qryImages.FieldByName('StoreId').AsInteger := StoreId;
qryImages.FieldByName('ImgSeq').AsInteger := ImgTop_DocSeq;
qryImages.FieldByName('Info').AsString := ImgInfo_Info;
qryImages.FieldByName('TypeId').AsString := GetImageTypeIdFromText(ImgBottom_TypeId);
qryImages.Post;
fCNN.Commit;
end
else
ShowMessage('Failed to load image stream while attempting to save. Please try again.');
except
qryImages.Cancel;
fCNN.Rollback;
raise EError.Create('An error occurred while saving images. Try again or import images from Void/View.', 0, svWarning, False);
end;
finally
s.Free;
tmpIE.Free;
end;
end;
fCNN.DisplayingMsg := False;
end;
Any suggestions you can provide would be helpful.
Thanks. |
|
|