IceCold
IceCold

Reputation: 21154

Cannot compress JPEG image and show it on screen

I try to load an image in imgQInput (which is a TImage), assign it to a TJpegImage, compress it (compression factor 5) and show it in imgQOutput (another TImage). But it doesn't work. The image in imgQOutput is the same as the original. It should look VERY pixelated because of the compression factor! The compression works however, because when I save the JPEG to disk it is really small.

  JPG:= TJPEGImage.Create;
   TRY
     JPG.CompressionQuality:= trkQuality.Position;
     JPG.Assign(imgQInput.Picture.Graphic);
     CompressJpeg(JPG);
     imgQOutput.Picture.Assign(JPG);          <--------- something wrong here. the shown image is not the compressed image but the original one
   FINALLY
     FreeAndNil(JPG);
   END;


function CompressJpeg(OutJPG: TJPEGImage): Integer;
VAR tmpQStream: TMemoryStream;
begin
 tmpQStream:= TMemoryStream.Create;
 TRY
   OutJPG.Compress;
   OutJPG.SaveToStream(tmpQStream);
   OutJPG.SaveToFile('c:\CompTest.jpg');       <--------------- this works
   Result:= tmpQStream.Size;
 FINALLY
   FreeAndNil(tmpQStream);
 END;
end;

Upvotes: 5

Views: 2429

Answers (2)

OnTheFly
OnTheFly

Reputation: 2101

Here is a competing answer for you, with less data jugglery (remember, images can be large!)

type
  TJPEGExposed = class(TJPEGImage);     // unfortunately, local class declarations are not allowed

procedure TForm1.FormClick(Sender: TObject);
var
  JPEGImage: TJPEGImage;
const
  jqCrappy = 1;
begin
  Image1.Picture.Bitmap.LoadFromFile(GetDeskWallpaper);

  Image2.Picture.Graphic := TJPEGImage.Create;
  JPEGImage := Image2.Picture.Graphic as TJPEGImage;    // a reference
  JPEGImage.Assign(Image1.Picture.Bitmap);
  JPEGImage.CompressionQuality := jqCrappy;    // intentionally
  JPEGImage.Compress;
  TJPEGExposed(JPEGImage).FreeBitmap;    { confer: TBitmap.Dormant }
end;

TJPEGImage.FreeBitmap disposes volatile DIB contained within TJPEGImage instance. In the illustrated case this causes class to decode recently .Compress'ed JPEG in response to TImage repainting.

Upvotes: 3

Vahid Nasehi
Vahid Nasehi

Reputation: 463

You did not used the compressed JPG at all.

Change CompressJpeg as followings:

function CompressJpeg(OutJPG: TJPEGImage): Integer;
VAR tmpQStream: TMemoryStream;
begin
 tmpQStream:= TMemoryStream.Create;
 TRY
   OutJPG.Compress;
   OutJPG.SaveToStream(tmpQStream);
   OutJPG.SaveToFile('c:\CompTest.jpg');    // You can remove this line.
   tmpQStream.Position := 0;                //
   OutJPG.LoadFromStream(tmpQStream);       // Reload the jpeg stream to OutJPG
   Result:= tmpQStream.Size;
 FINALLY
   FreeAndNil(tmpQStream);
 END;
end;

Upvotes: 6

Related Questions