ImageEn for Delphi and C++ Builder ImageEn for Delphi and C++ Builder

 

ImageEn Forum
Profile    Join    Active Topics    Forum FAQ    Search this forumSearch
 All Forums
 ImageEn Library for Delphi, C++ and .Net
 ImageEn and IEvolution Support Forum
 Error loading DB image into MView with IDRequestEx

Note: You must be registered in order to post a reply.
To register, click here. Registration is FREE!

View 
UserName:
Password:
Format  Bold Italicized Underline  Align Left Centered Align Right  Horizontal Rule  Insert Hyperlink   Browse for an image to attach to your post Browse for a zip to attach to your post Insert Code  Insert Quote Insert List
   
Message 

 

Emoji
Smile [:)] Big Smile [:D] Cool [8D] Blush [:I]
Tongue [:P] Evil [):] Wink [;)] Black Eye [B)]
Frown [:(] Shocked [:0] Angry [:(!] Sleepy [|)]
Kisses [:X] Approve [^] Disapprove [V] Question [?]

 
Check here to subscribe to this topic.
   

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.