Combine differently sized JPEGs with jpegtran

510 views Asked by At

I've successfully used jpegtran to combine JPEGs of the same size (512x512) using the method described in this stackoverflow answer: https://stackoverflow.com/a/29615714/2364680

These are tiled JPEGs from the internet that make a 360 panorama when combined. As I said, the 512x512 images combined perfectly with jpegtran; however, I realized that some of the tiles that make up the panorama are 256x256 and need to be doubled in size when combined with the other tiles in order to form the panorama (in the 2D form of an equirectangular projection).

Simply put, I need to know if jpegtran can losslessly combine two JPEGs of different sizes -- for instance, if I can losslessly double the resolution of a 256x256 tile and then combine it with another 512x512 tile.

I know this can be done through reencoding, but I'm asking if it can be done totally losslessly. Thanks.

1

There are 1 answers

0
rsaxvc On

Not currently, no. We'd need the following:

  1. Lossless crop - long supported
  2. SmartScale - note that this is not ITU JPEG compliant, will change the pixel size of macroblocks, and will fail with many decoders.
  3. Ability to change macroblock size partway through a file. My guess is that SmartScale doesn't support this, but some newer image/video compression formats do.
  4. Supporting software - not currently available. I tested the latest available at this time, JPEG-9e, which cannot append JPEGs of differing SmartScale ratios / macroblock sizes

Here's what I came up with given that jpegtran's -crop, -scale and -drop operations cannot be combined:

#start with two images
#512x512.jpg - 64x64 macroblocks
#256x256.jpg - 32x32 macroblocks

#uncrop 2x1x using libjpeg7+ to give us space for later.
#out.jpg resolution is 1024x512, 128x64 macroblocks
jpegtran -crop 1024x512+0+0 -outfile out.jpg 512x512.jpg

#upscale the 256px image to 512x512 using libjpeg8+'s SmartScale
#Note: Does not change image width/height in macroblocks!
#Note: Only changes width/height of macroblocks!
#upscale.jpg is 512x512 but still 32x32 macroblocks
jpegtran -scale 8/4 -outfile upscale.jpg 256x256.jpg

#drop in upscale.jpg on the right half of the output image.
jpegtran -drop +512+0 upscale.jpg -outfile out.jpg out.jpg

However, the last command fails with: "Bogus virtual array access" which is the string for JERR_BAD_VIRTUAL_ACCESS error thrown by jpeg-9e/jmemmgr.c line 857.

It fails because end_row > ptr->rows_in_array where rows_in_array is 32 macroblocks and end_row reaches 33 macroblocks - the first macroblock row not present in upscale.jpg

jpegtran is expecting a 512x512 pixel image to be 64x64 macroblocks using the destination image macroblock size, so halfway through upscale.jpg it runs out of source macroblocks and walks off the end of the image. If we patched libjpeg to use the correct macroblock size, we'd need some way to encode into the file that the size of macroblocks has changed, but I'm not sure how that would be done.