Return to Digital Photography Articles
How to extend a JPEG image losslessly
Interest in Lossless operations for JPEG photos
Over the last couple years, there has been great interest amongst photographers to preserve every detail of their original digital photos. It's widely known that resaving JPEG photos causes some degree of image degradation in the process. The amount of image degradation is typically very small, yet most serious enthusiasts cringe at the thought of any such "losses".
Interestingly, it would be hard to find an equivalent degree of image preservation in the context of film. Most of us accepted some uncertainty in the appearance of film grain itself. That said, recompression error in digital photos is more of an annoyance because it introduces some regularlities and inorganic boundaries (blockiness) into the resulting image.
Real Lossless Operations
There are some operations that one may perform on a digital photo that don't really "modify" the image content. Rotating, flipping and even cropping are operations that one often applies to digital photos, with the expectation that the image content will not suffer as a result. Thus, we have tools available to perform lossless rotation, lossless flip and lossless crop.
Since most people will fail to recognize a single round of high-quality recompression error in the resulting photograph, the desire for these lossless operations is generally based on the idea that you can perform the operation on the original file without saving a backup copy.
Should you decide later that you didn't like the outcome, you could simply losslessly rotate the image back to the original orientation, or flip. Of course cropping would be an irreversible operation.
Edited Lossless Operations
However, there has also been some interest in performing edits to a small region of the image content while still preserving the rest of the image losslessly. In this scenario, I would expect that users would in fact keep an original copy (prior to edit) and therefore the need for these edits to be "regionally" lossless is based primarily on concerns of image quality degradation for the new output file. As the recompression "error" resulting from one cycle of resaving with higher JPEG compression quality settings is quite minimal, this concern may generally be harder to justify.
With a few restrictions in mind, it is possible to make localized/regional edits to a JPEG image without affecting other regions. For example:
- Lossless extend / Lossless extension:
Increase the dimension of the JPEG image in one or more dimensions. The size of the extension in each direction must be a multiple of the MCU (usually x8, but x16 if chroma subsampling is used). For example, one can place a 16 pixel border around an digital photo, leaving the original content intact perfectly. In JPEGclub terminology, this operation is still called "lossless crop", even though it is a crop with negative dimensions. The JPEGclub page doesn't make this feature particularly obvious.
- Lossless cut and paste / copy and paste:
Copy the content of one image into another, while preserving the content of the pasted photo portion and the underlying original image (outside of the paste region) perfectly. So long as both the source and destination box coordinates are aligned to the MCU boundaries, this can be done. This is a more complex operation, particularly when the two images have different quantization tables. In the JPEGclub terminology, this operation is called "lossless drop".
- Local modification / edit / overlay:
Change only a portion of the original image content, leaving the rest intact perfectly. In this operation, only a region bounded by coordinates falling on the MCU boundaries will be touched, leaving all other MCU blocks untouched. If the coordinates of the region do not lie on MCU boundaries, then the size of the affected region is increased up to the next MCU boundary. This functionality is very similar to the lossless copy and paste, with the same difficulties when dealing with the quantization matrices.
While I originally tried to accomplish these operations in the uncompressed image space (i.e. after JPEG decompression), I soon realized some of the limitations of the JPEG compression / decompression with regards to lossless reversibility. Therefore, the best way to accomplish this is by using a special utility that operates on images in the DCT block level, rather than at the uncompressed pixel level.
Downloading the Software: jpegtran
Most of these transformations can be performed with the sample programs provided by JPEGclub. The most relevant of these is a tool called jpegtran. jpegtran is a lossless transformation utility for JPEG images that can perform many different lossless operations on a digital photo. This includes lossless crop, lossless extend and lossless drop, etc.
While there are several Windows applications that provide this functionality, jpegtran is a free tool with source code provided, relying on the most recent jpeglib library version 6b. Unfortunately, command-line utilities are not particularly easy to use for the average Windows user, so it may be worth having a look at some of the fuller-featured (shareware, commercial and freeware) programs currently using this core functionality: lossless jpegtran software.
I will update this page once I find a more user-friendly front-end, free Windows application that has the lossless extend functionality. Note that while many applications provide the lossless crop capability (of jpegtran), very few seem to allow for the extend.
You can find the most recent versions of the free JPEG utilities on the JPEGclub website, or download versions from here:
jpegtran.zip (64KB, command line utility) Written by Thomas G. Lane
How do I do lossless extend?
Dimensions for Lossless Extend
First, one needs to determine the original image's dimensions. This is easily done with any image editor or even with Windows XP "Details" or "Properties->Summary". Let the width be Xo & the height be Yo.
How to create a border on all four sides: Let's assume that you have an original image with dimensions Xo x Yo pixels. You would like to add a border around the original image, with varying widths. Let Xl be the width of the extension to the left, Xr be the width of the extension to the right, Yt to the top and Yb to the bottom.
|Final Width||W = Xo + Xl + Xr|
|Final Height||H = Yo + Yt + Yb|
|Offset X||X = Xl|
|Offset Y||Y = Yl|
For example, to do a lossless extension on a JPEG image that is sized 3072 x 1024 pixels, with a top border of 8 pixels, left and right borders of 32 pixels and a bottom border of 40 pixels:
|Original Width||Xo = 3072|
|Original Height||Yo = 1024|
|Extension to Left||Xl = 32|
|Extension to Right||Xr = 32|
|Extension to Top||Yt = 8|
|Extension to Bottom||Yb = 40|
|Final Width||W = Xo + Xl + Xr||3072+32+32 = 3136|
|Final Height||H = Yo + Yt + Yb||1024+8+40 = 1072|
|Offset X||X = Xl||32|
|Offset Y||Y = Yl||8|
|COMMAND:||jpegtran -crop 3136x1072+32+8 before.jpg after.jpg|
Assuming you have an original image named "before.jpg", typing in the above command into a shell window (command prompt) will generate a resulting image called "after.jpg".
How to Run jpegtran
If you are not familiar with command-line execution, please read the brief intro at the bottom of this page.
Restrictions on Size and Offsets
In general, all of the lossless transformation commands rely on the fact that the widths, heights as well as X & Y offsets are all multiples of the MCU size. In other words, all corners of the rectangles shown in the diagram above will line up on the boundaries of the JPEG MCU (Minimum Coded Unit) blocks.
In general, these blocks are 8x8 pixels, but can be 16x8, 16x16 or 8x16, depending on the chroma subsampling being used.
To be on the safe side, it is recommended that you try to select dimensions and offsets that are multiples of 16 pixels. In other words, W, H, X and Y should all be multiples of 16.
Command-line Execution of jpegtran
If you are not familiar with command-line execution, do the following:
- Download the jpegtran application, right-click on jpegtran.zip and select "Extract All...". Extract to the directory that contains the image you'd like to modify.
- Open up a command-line shell by selecting "Run..." from the Windows XP Start menu.
- Type in "cmd" and click on OK.
- Change directory into the folder you placed jpegtran (e.g. cd c:\photos\ )
- Make sure that both the photo and jpegtran are in your current directory (check with dir)
- Execute the command as described above (e.g. jpegtran -crop 3136x1072+32+8 before.jpg after.jpg )
Lossless Aspect Ratio Conversion Batch Script
One interesting use for the lossless extend capability is in converting images from the 4:3 aspect ratio (typical in point & shoot digicams) to the 3:2 aspect ratio (common in nearly all SLRs).
It is extremely easy to create a Windows batch script (.bat) that automatically performs a lossless extension of your JPEG images to match a new aspect ratio. While there are tools out there such as BetterJPEG that allow you to perform lossless operations, it is sometimes nice to use a free alternative that can perform the same operation across many files at the same time.
The following batch script was originally suggested by reader Michael Lee.
for %%i in (%*) do jpegtran -copy all -crop 2916x1944+166+0 %%i "\%%~ni%%~xi"
The very last part ("\%%~ni%%~xi") will cause this script to place the converted output JPEG files in your root directory (e.g. C:\) with the same name as the original. As I prefer to keep original and derivate files distinguished by filename, I would offer an alternate last part which places the output files in the same directory as the originals, but with an -x suffix (note that this must be on the same line as the original for command):
The following table is an example of the parameters you can use to convert from a 4:3 image to a 3:2 image for common digicam resolutions. Substitute the parameter string in the script above (which reads 2916x...+0) for your particular camera and orientation as suggested below.
In the general case, the formula you can use to determine your new crop parameter string for a given digicam is:
Let orig_x be the horizontal resolution of your digicam
Let orig_y be the vertical resolution of your digicam
|For conversion of landscape photos:||For conversion of portrait photos:|
nx = 1.5 * orig_y
ny = orig_y
ox = ( (1.5 * orig_y) - orig_x) / 2
oy = 0
nx = orig_x
ny = 1.5 * orig_x
ox = 0
oy = ( (1.5 * orig_x) - orig_y) / 2
The parameter string will then be: nxxny+ox+oy
Modify the crop parameter string as noted above, matching the desired conversion for your digicam. Save this file as a batch file (e.g. jpegexth.bat for landscape and jpegextv.bat for portrait conversions) into the same directory as your jpegtran executable. Then, you can simply drag and drop multiple JPEG files (up to 9) onto the batch file. This will automatically generate output JPEG files as described in the NOTE section above. Note that you need to use a different batch script for landscape photos and portrait photos.
Installing Context Menu for Script
If this conversion is someone you intend to use often, you may want to consider installing the script in Windows explorer's right-click context menu. This way, you can simply right-click on the JPEG image to convert, and select the conversion type. There are several methods you can use to install right-click context menu option. For example, in Windows XP explorer, select Tools->Folder Options, then click on the File Types tab. From there, select the JPEG Image type and click on Advanced.
Click on New... to generate a new context-menu option, and enter a representative name for the action, such as Lossless Ext 3:2 Horz. Where it asks for the application, locate your batch file and append %1. Click OK and then you're done!