How to avoid "Random" Exceptions being raised when using TJPEGImage or the JPEG unit. Question: Answer: procedure TForm1.btnOpenDefaultClick(Sender: TObject); begin if OpenPictureDialog1.Execute then try Image1.Picture.LoadFromFile(OpenPictureDialog1.FileName); except end; end;But, unexpectedly, JPEG's sometimes display an exception message and it appears that the creator of the JPEG unit hard-coded a ShowMessage to display the exception. The problem is that the LoadFromFile procedure executes fine, and the actual drawing of the JPEG to the TImage is what is causing the problem. The drawing of the image is implicitly called after the image has loaded from the file. The way around this problem is to explicitly control when any possible errors happen. You can capture any errors that happen in the loading of the image, and/or in the drawing of the image. Below is an example of how to do this. The project consists of a unit (called MainFrm.pas). It has a TImage and an OpenPictureDialog placed on the form. Two buttons are also placed on it, one named btnOpenCatch and another called btnOpenDefault. The btnOpenCatchClick procedure demonstrates how each exception can be caught and displayed the the user. Alternatively, the exception could be "eaten" with an empty except section. The btnOpenDefaultClick displays the default way of opening an image and trying to eat an exception, which may still display a JPEG error. Also notice the addition of the JPEG unit to the uses clause. To create a corrupt JPEG that displays this error, open a JPEG image in a hex editor and change the first few bytes or the last few bytes. unit MainFrm; interface uses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, ExtDlgs, ExtCtrls, StdCtrls, JPEG; type TForm1 = class(TForm) btnOpenCatch: TButton; Image1: TImage; OpenPictureDialog1: TOpenPictureDialog; btnOpenDefault: TButton; procedure btnOpenCatchClick(Sender: TObject); procedure btnOpenDefaultClick(Sender: TObject); private { Private declarations } public { Public declarations } end; var Form1: TForm1; implementation {$R *.DFM} procedure TForm1.btnOpenCatchClick(Sender: TObject); var Picture: TPicture; Bitmap: TBitmap; begin if OpenPictureDialog1.Execute then begin Picture := TPicture.Create; try // Try to load the picture from a file. // I'm wrapping it in a try..except to capture // any exceptions that happen in loading the image from // a stream. try Picture.LoadFromFile(OpenPictureDialog1.FileName); except on E: EInvalidGraphic do begin ShowMessage('Capturing Load Error: ' + E.Message); Exit; // Exit the procedure end; end; Bitmap := TBitmap.Create; try try // Assign the Graphic to the Bitmap; any drawing errors/exceptions // will happen here, and will be captured and shown to the user Bitmap.Assign(Picture.Graphic); except // Eat invalid graphic messages (which may be raised // when a jpeg is being drawn) on E: EInvalidGraphic do begin ShowMessage('Capturing Assign (Drawing) Error: ' + E.Message); Exit; // Exit the procedure end; end; // Now draw the picture on the screen's TImage Image1.Picture.Bitmap.Assign(Bitmap); finally Bitmap.Free; end; finally Picture.Free; end; end; // OpenPictureDialog1.Execute end; procedure TForm1.btnOpenDefaultClick(Sender: TObject); begin if OpenPictureDialog1.Execute then try Image1.Picture.LoadFromFile(OpenPictureDialog1.FileName); except end; end; end. Another thing to notice is that the OpenPictureDialog does not contain this fix. It will display some JPEG error messages when you click on a corrupt JPEG and it attempts to display a preview image. |
Last Modified: 03-JAN-00