Board index » delphi » Detecting a bad Jpeg using the JPEG unit

Detecting a bad Jpeg using the JPEG unit

The jpeg unit works quite well overall.  I just have one little problem.
When I attempt to load a jpeg that happens to be invalid, which many
downloaded jpegs are, an exception is raised that I haven't been able to
trap.  The following code demonstrates the problem.  As far as I can tell
the problem is that the exception that is raised happens deep inside the
decompression engine within the jpeg unit.  I would hate to have to re-write
or modify the jpeg code but that's what I'm looking at.

Procedure TForm1.ShowJpg (Image : TImage; Name : String);
Var
  Bitmap : TPicture;
  Loc : TRect;

Begin

  { Clear the Passed Image's Canvas }
  Image.Canvas.Brush.Color := clSilver;
  Image.Canvas.FillRect (Rect (0,0,Image.Width,Image.Height));

  { Create the temporary bitmap and load the jpeg image }
  Bitmap := TPicture.Create;

  Try {Even on a bad file the file loads }
    Bitmap.LoadFromFile (Name);
  except
    { report error }
  end;

  { Determine the basic rectangle for the picture }
  Loc := Location (Point (Image.Width,Image.Height),Point (Bitmap.Width,
Bitmap.Height));

  { Draw the image at the specified location }

  try { This raises exception in lower level code on a bad file }
    Image.Canvas.StretchDraw (Loc,BitMap.Graphic);
  Except
    { report error }
  End;

  Application.ProcessMessages;
  Bitmap.Free;
End;

 

Re:Detecting a bad Jpeg using the JPEG unit


In article <6hr6lv$r...@forums.borland.com>,  "Donn Ault"

Quote
<NoS...@NoSpam.com> wrote: > > The jpeg unit works quite well overall.  I

just have one little problem. > When I attempt to load a jpeg that happens to
be invalid, which many > downloaded jpegs are, an exception is raised that I
haven't been able to > trap.  The following code demonstrates the problem.
As far as I can tell > the problem is that the exception that is raised
happens deep inside the > decompression engine within the jpeg unit.  I would
hate to have to re-write > or modify the jpeg code but that's what I'm
looking at. > > Procedure TForm1.ShowJpg (Image : TImage; Name : String); >
Var >  Bitmap : TPicture; >  Loc : TRect; > > Begin > >  { Clear the Passed
Image's Canvas } >  Image.Canvas.Brush.Color := clSilver; >
Image.Canvas.FillRect (Rect (0,0,Image.Width,Image.Height)); > >  { Create
the temporary bitmap and load the jpeg image } >  Bitmap := TPicture.Create;
Quote
> >  Try {Even on a bad file the file loads } >  Bitmap.LoadFromFile (Name);
>  except >  { report error } >  end; > >  { Determine the basic rectangle

for the picture } >  Loc := Location (Point (Image.Width,Image.Height),Point
(Bitmap.Width, > Bitmap.Height)); > > { Draw the image at the specified
location } > >  try { This raises exception in lower level code on a bad
file } >  Image.Canvas.StretchDraw (Loc,BitMap.Graphic); >  Except >  {
report error } >  End; > >  Application.ProcessMessages; >  Bitmap.Free; >
End; > >  I am having the same problems with the borland jpeg componet.  I
have looked into the componet and I belive this is the area that creates the
problem: procedure JpegError(cinfo: j_common_ptr); begin  raise
EJPEG.CreateFmt(sJPEGError,[cinfo^.err^.msg_code]); end; It seems that EJPEG
doesn't get registered as an exception.  Looks as if the only way to get
around this would be to change it to read:  raise EJPEG.Create('Jpeg
Error'); I havn't tried this yet, I was hoping that someone would respond
with a better answer. Please e-mail me if you come up with a better way.
Matt{*word*106}ey w...@ameritech.net

-----== Posted via Deja News, The Leader in Internet Discussion ==-----
http://www.dejanews.com/   Now offering spam-free web-based newsreading

Re:Detecting a bad Jpeg using the JPEG unit


I've solved my own problem.  That's good right?  In the process I identified
and fixes a BUG in Borland's JPEG unit.

Problem

        While the jpeg unit raises an exception, an application program is
not
able to trap it.

Problem Location

        The definition for the exception is defined LOCALLY within the
implementation
section of the Jpeg.pas file and as a result your program can't use the
exception
name (EJPEG) and therefore can't trap the exception.

Solution

        Borland should have placed the EJPEG exception definition in the
interface
section, thereby making it available to the programmer.  You need to do the
following
to fix the problem.  With this fix in place your programs will no longer
crash if an
invalid jpeg is processed.

1.    Use the explorer to open the directory C:\Program Files\Borland\Delphi
3\Bin.
       or whatever it is on your computer.

2.    Be safe, back up Jpeg.dcu and Jconsts.dcu.

3.    Open your Delphi CD and find the directory called EXTRAS.  Within this
open the
       Directory JPEG.

4.    Here you will find jpeg.pas and Jconsts.pas, copy them to
       C:\Program Files\Borland\Delphi 3\Bin

5.    Still on the CD, open the Obj directory and copy all files there to
       C:\Program Files\Borland\Delphi 3\Bin

6.    Run Dephi and open and application that uses the Jpeg unit.  Right
click
       on "Jpeg" in the Uses Jpeg part of your program and select "Open File
       at Cursor"  This should open the jpeg.pas file.

7.    Locate the lines below and move them so that they are together with
       the first type statement.

type
  EJPEG = class(EInvalidGraphic);

8.    Recompile

9.    Change your try,except section to add the EJpeg catch as follows.

Procedure TForm1.ShowJpg (Image : TImage; Name : String);
Var
  Bitmap : TPicture;
  Loc : TRect;

Begin

  { Clear the Passed Image's Canvas }
  Image.Canvas.Brush.Color := clSilver;
  Image.Canvas.FillRect (Rect (0,0,Image.Width,Image.Height));

  { Create the temporary bitmap and load the jpeg image }
  Bitmap := TPicture.Create;

  Try {Even on a bad jpeg files the file loads }
    Bitmap.LoadFromFile (Name);
  except
    { report error }
  end;

  { Determine the basic rectangle for the picture }
  Loc := Location (Point (Image.Width,Image.Height),Point (Bitmap.Width,
Bitmap.Height));

  { Draw the image at the specified location }

  try { This raises exception in lower level code on a bad file }
    Image.Canvas.StretchDraw (Loc,BitMap.Graphic);
  Except
    { report error }
      on EJPEG do Application.MessageBox ('Bad Jpeg','Ooops',ID_OK);
  End;

  Application.ProcessMessages;
  Bitmap.Free;
End;

Re:Detecting a bad Jpeg using the JPEG unit


Hi!

Well, I'm having the same problem.
I implemented your solution, and it works... kind of.
I am now able to trap the EJPEG error (Except On EJPEG Do...).
However, it works on some JPEGs, and on others, it doesn't.
I am able to trap the "JPEG error #52", but it still doesn't trap the "JPEG
error #67"

Any ideas?

Thanks for your help.

Ziad

Quote
Donn Ault wrote:
> I've solved my own problem.  That's good right?  In the process I identified
> and fixes a BUG in Borland's JPEG unit.

> Problem

>         While the jpeg unit raises an exception, an application program is
> not
> able to trap it.

> Problem Location

>         The definition for the exception is defined LOCALLY within the
> implementation
> section of the Jpeg.pas file and as a result your program can't use the
> exception
> name (EJPEG) and therefore can't trap the exception.

> Solution

>         Borland should have placed the EJPEG exception definition in the
> interface
> section, thereby making it available to the programmer.  You need to do the
> following
> to fix the problem.  With this fix in place your programs will no longer
> crash if an
> invalid jpeg is processed.

> 1.    Use the explorer to open the directory C:\Program Files\Borland\Delphi
> 3\Bin.
>        or whatever it is on your computer.

> 2.    Be safe, back up Jpeg.dcu and Jconsts.dcu.

> 3.    Open your Delphi CD and find the directory called EXTRAS.  Within this
> open the
>        Directory JPEG.

> 4.    Here you will find jpeg.pas and Jconsts.pas, copy them to
>        C:\Program Files\Borland\Delphi 3\Bin

> 5.    Still on the CD, open the Obj directory and copy all files there to
>        C:\Program Files\Borland\Delphi 3\Bin

> 6.    Run Dephi and open and application that uses the Jpeg unit.  Right
> click
>        on "Jpeg" in the Uses Jpeg part of your program and select "Open File
>        at Cursor"  This should open the jpeg.pas file.

> 7.    Locate the lines below and move them so that they are together with
>        the first type statement.

> type
>   EJPEG = class(EInvalidGraphic);

> 8.    Recompile

> 9.    Change your try,except section to add the EJpeg catch as follows.

> Procedure TForm1.ShowJpg (Image : TImage; Name : String);
> Var
>   Bitmap : TPicture;
>   Loc : TRect;

> Begin

>   { Clear the Passed Image's Canvas }
>   Image.Canvas.Brush.Color := clSilver;
>   Image.Canvas.FillRect (Rect (0,0,Image.Width,Image.Height));

>   { Create the temporary bitmap and load the jpeg image }
>   Bitmap := TPicture.Create;

>   Try {Even on a bad jpeg files the file loads }
>     Bitmap.LoadFromFile (Name);
>   except
>     { report error }
>   end;

>   { Determine the basic rectangle for the picture }
>   Loc := Location (Point (Image.Width,Image.Height),Point (Bitmap.Width,
> Bitmap.Height));

>   { Draw the image at the specified location }

>   try { This raises exception in lower level code on a bad file }
>     Image.Canvas.StretchDraw (Loc,BitMap.Graphic);
>   Except
>     { report error }
>       on EJPEG do Application.MessageBox ('Bad Jpeg','Ooops',ID_OK);
>   End;

>   Application.ProcessMessages;
>   Bitmap.Free;
> End;

Re:Detecting a bad Jpeg using the JPEG unit


On Thu, 14 May 1998 18:52:30 -0500, Ziad Noueihed

Quote
<codes...@southwind.net> wrote:
>Hi!

>Well, I'm having the same problem.
>I implemented your solution, and it works... kind of.
>I am now able to trap the EJPEG error (Except On EJPEG Do...).
>However, it works on some JPEGs, and on others, it doesn't.
>I am able to trap the "JPEG error #52", but it still doesn't trap the "JPEG
>error #67"

>Any ideas?

Instead of going through all that effort just to catch EJPEG, why not
catch a broader range of exceptions?  Do something like this

   try { This raises exception in lower level code on a bad file }
     Image.Canvas.StretchDraw (Loc,BitMap.Graphic);
   Except
     { report error }
       on E:Exception do
          if E.classname = 'EJPEG' then
            Application.MessageBox ('Bad Jpeg','Ooops',ID_OK)
          else
            Application.MessageBox(E.classname,E.message,ID_OK);
   end;

Duncan Murdoch

Re:Detecting a bad Jpeg using the JPEG unit


Hi!

I had already tried that, but without success.
Again, it traps on some EJPEG errors (i.e. #52), but not on EJPEG #67.
If you look at the code below, when encountering an invalid JPEG, neither
condition is entered. Heck, the
Except statement is not entered alltogether.

Here is the relevant code snipet:

     Try
      Image1.Picture.LoadFromFile(DstList.Items[i]);        // Here is where I'm
loading the picture
     Except On E:Exception Do
      Begin
       If (E.ClassName='EJPEG') Then
        Begin
         Image1.Picture:=nil;
          MessageDlg('This JPEG Graphics file is invalid or not
supported.',mtInformation,[mbOK],0);
         Exit;
        End
       Else
        Begin
         Image1.Picture:=nil;
         MessageDlg('This Graphics file is invalid or not
supported.',mtInformation,[mbOK],0);
         Exit;
        End;
      End;
     End;

Any ideas?

Thanks for your help.

Ziad

Quote
Duncan Murdoch wrote:
> Instead of going through all that effort just to catch EJPEG, why not
> catch a broader range of exceptions?  Do something like this

>    try { This raises exception in lower level code on a bad file }
>      Image.Canvas.StretchDraw (Loc,BitMap.Graphic);
>    Except
>      { report error }
>        on E:Exception do
>           if E.classname = 'EJPEG' then
>             Application.MessageBox ('Bad Jpeg','Ooops',ID_OK)
>           else
>             Application.MessageBox(E.classname,E.message,ID_OK);
>    end;

> Duncan Murdoch

Other Threads