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
 JPEGs go large when I resize

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
Jonathon Posted - May 10 2013 : 00:59:31
Hi!

I have a problem whereby I need to load up existing JPEG files, put a border around them then save them again. The following code works fine for loading and saving, and the output stream is the same size as the input stream:

var
img:TImageEnView;
ms,imgStream:TMemoryStream;
begin
// setup of streams here
img.IO.LoadFromStreamJpeg(imgStream);
Log( format('Input Image size in bytes: %d' ,[imgstream.Size]));
// ** need to add a border here
img.IO.SaveToStreamJPEG(ms);
Log(Format('Saved to memory stream, size=%d',[ms.Size]));
// tear down and tidy up
end;

But if I add this line in after the second comment (i.e.: after the loadfromstream but before the save to stream)
img.Proc.ImageResize(img.IEBitmap.Width+10,img.IEBitmap.Height+10,iehCenter,ievCenter);

- Then the output JPEG size increases massively. I've played with the JPEG_Smooth and JPEG_Quality but in order to get back to around the original size I have to degrade the image quality massively (JPEG_Quality=20).

I actually do more than this, I add a border, then add a header and footer area and write metadata text to those regions; however the core issue boils down to the above. If I write text to the canvas without resizing it I don't seem to get the same issues.

I guess there is some kind of conversion or resampling going on.

Is there any way to resize the image canvas without getting this effect?

Thanks

Jonathon
2   L A T E S T    R E P L I E S    (Newest First)
Jonathon Posted - May 11 2013 : 17:49:19
Hi William, thanks for your attention!

It wasn't that (I do lots of stuff with streams), but your assurance that you don't see a similar effect gave me the confidence to do more investigation.

I was able to reproduce the effect with a simple test block of code:

ImageEn1.IO.Params.JPEG_DCTMethod:=ioJPEG_ISLOW;
ImageEn1.IO.LoadFromFileJpeg('c:\test.jpg');
ImageEn1.Proc.ImageResize(imageen1.IEBitmap.width+10,imageEn1.IEBitmap.height+10,iehCenter,ievCenter);
ImageEn1.IO.Params.JPEG_Quality:=(IECalcJpegFileQuality('c:\test.tif'));
Imageen1.IO.SaveToFileJpeg('c:\test2.jpg');

- and it appears that this issue was to do with re-compression and MCU boundaries. I have discovered that I can minimise the effect (and prevent obvious re-compression) by keeping my borders etc a multiple of 1 MCU - which is pretty much always 16x16 for the library I have to modify.

So, when I run the above code to add a 16 pixel border to an existing file the filesize grows from 102KB to 104KB - which is fair enough. Pixel-peeping reveals that there has been no visible recompression (artefacts appear identical). If I add a 10 pixel border (as I was) the filesize grows from 102KB to 122KB and the resulting image has been obviously (visibly) re-compressed with a consequent (significant) loss in image quality and increase in visible artefacts. Some images I was testing with, which were 600KB in size, would grow to over 1 MB so it is obviously (as I would expect with JPEG's) content dependent.

Different size borders give differing results, always falling to minimums on multiples of 16 pixels.

So, by choosing multiples of 16 bytes I can minimise the impact on the image but still add a border and top/bottom annotations, which is great.

Oddly enough there must be some recompression going on because the JPEG_Quality has an impact if I play with it, but on the whole - as long as it is not visible - I don't care!

Thanks for the hint!

Regards

Jonathon



w2m Posted - May 10 2013 : 05:58:36
I do not see a large increase in stream size that you describe. Perhaps it is caused by not setting the memory stream positions?
Before loading a memory stream its position must be set to 0. Are you doing this?
procedure TForm1.Button1Click(Sender: TObject);
var
  img: TImageEnView;
  ms, imgStream: TMemoryStream;
begin
  if Assigned(cxPageControl1.ActivePage) then
  begin
    ImageEnView := TImageEnView(cxPageControl1.ActivePage.Controls[0]);
    if Assigned(ImageEnView) then
    begin
      img := TImageEnView.Create(nil);
      try
        ms := TMemoryStream.Create;
        try
          imgStream := TMemoryStream.Create;
          try
            ImageEnView.IO.SaveToStreamJPEG(imgStream);
            imgStream.Position := 0;  // Important
            img.IO.LoadFromStreamJpeg(imgStream);
            ShowMessage(Format('Input Image size in bytes: %d', [imgstream.Size]));
            img.Proc.ImageResize(ImageEnView.IEBitmap.Width + 10, ImageEnView.IEBitmap.Height +
              10, iehCenter,
              ievCenter);
            img.IO.SaveToStreamJPEG(ms);
            ms.Position := 0; // Important
            ShowMessage(Format('Saved to memory stream, size=%d', [ms.Size]));
            ImageEnView.IO.LoadFromStreamJpeg(ms);
            ImageEnView.Update;
            UpdateStatusBar;
          finally
            imgStream.Free;
          end;
        finally
          ms.Free;
        end;
      finally
        img.Free;
      end;
    end;
  end;
end;

William Miller
Email: w2m@frontiernet.net
EBook: http://www.imageen.com/ebook/
Apprehend: http://www.frontiernet.net/~w2m/index.html