Skip to content

Conversation

@dcommander
Copy link
Contributor

Prerequisites

  • I have written a descriptive pull-request title
  • I have verified that there are no overlapping pull-requests open
  • I have verified that I am following the existing coding patterns and practices as demonstrated in the repository.

Description

  • Add support for 3/8, 5/8, 3/4, 7/8, 9/8, 5/4, 11/8, 3/2, 13/8, 7/4, 15/8, and 2/1 scaling factors if IM is built against libjpeg-turbo or libjpeg v7+.
  • Add support for any legal lossless data precision (from 2 to 16 bits per sample inclusive) if IM is built against libjpeg-turbo 3.1+. This also improves the accuracy of converting samples between different data precisions in the JPEG module.
  • Add support for generating 12-bit-per-sample lossy JPEG images if IM is built against libjpeg-turbo 3.0+.

These changes have been validated using a set of scripts that iterates over the various permutations of JPEG settings and formats using separate builds of IM targetting libjpeg-turbo 3.1.x, 3.0.x, and 2.1.x, as well as libjpeg v6b with Ken Murchison's lossless JPEG patch.

- If compiled with libjpeg-turbo 3.1.x or later and lossless JPEG
  compression is selected, directly encode pixel data with 2 to 16 bits
  per channel into a lossless JPEG image with the same data precision,
  rather than upconverting to an 8-bit-per-sample, 12-bit-per-sample, or
  16-bit-per-sample lossless JPEG image.  (If compiled with
  libjpeg-turbo 3.0.x, upconverting is still performed.)

- If compiled with libjpeg-turbo 3.1.x or later, directly decode
  lossless JPEG images with 2 to 16 bits per sample into pixel data with
  the same data precision, rather than upconverting to
  8-bit-per-channel, 12-bit-per-channel, or 16-bit-per-channel pixel
  data.

- If compiled with libjpeg-turbo 3.0.x or later and lossy JPEG
  compression is selected, upconvert or downconvert pixel data with 9 to
  16 bits per channel into a 12-bit-per-sample lossy JPEG image.

- If compiled with libjpeg-turbo 2.1.x or earlier (or libjpeg),
  upconvert or downconvert pixel data with 2 to 16 bits per channel into
  an 8-bit-per-sample lossy JPEG image.
@dcommander dcommander force-pushed the jpeg-format-enhancements branch from ea7dbe8 to 3c1e84b Compare November 16, 2025 13:18
@dcommander
Copy link
Contributor Author

Force-pushed to correct a couple of formatting issues and fix the Windows build.

@urban-warrior urban-warrior merged commit 3044c6c into ImageMagick:main Nov 16, 2025
8 checks passed
@dcommander dcommander deleted the jpeg-format-enhancements branch November 16, 2025 17:34
@dlemstra
Copy link
Member

dlemstra commented Dec 5, 2025

In the next release writing high depth jpeg files will require setting the jpeg:high-bit-depth define. This will not be enabled by default anymore because a lot of decoders will not support reading these kind of files.

@dcommander
Copy link
Contributor Author

Playing Devil's advocate, can't users simply force the output bit depth to 8 if they want compatibility with more limited decoders? If you convert, say, a 16-bit PPM image into a 16-bit TIFF or PNG image, ImageMagick doesn't silently drop the bit depth in order to preserve backward compatibility with more limited decoders. It fully uses the capabilities of the most popular TIFF and PNG decoders. libjpeg-turbo is the most popular JPEG decoder, as well as the official ISO/ITU-T reference implementation.

My main concern is that there may be a chicken-and-egg issue. If ImageMagick supports all JPEG-1 variants by default, then it will encourage other applications to do likewise, and those other applications can now easily do so by using libjpeg-turbo. However, if ImageMagick doesn't support all JPEG-1 variants by default, then other applications will have little impetus to do so, and higher-bit-depth and lossless images will remain orphaned even though they are conformant JPEG-1 images.

Perhaps disabling jpeg:high-bit-depth by default could be temporary, until libjpeg-turbo 3.0.x and later become more widely available in operating systems? Or perhaps it could be enabled by default only if ImageMagick is built with libjpeg-turbo 3.1.x and later?

A bit of historical context:
libjpeg originated in an era before shared libraries were common, so it was designed to be compiled and linked statically with individual applications. Thus, it supports 12-bit lossy JPEG images, but only if you recompile it in a way that collides with the namespace of, and breaks API/ABI compatibility with, the 8-bit version of the library. Thus, the default feature set of libjpeg became canonical once the library was integrated into Linux and other operating systems. That limited the adoption of 12-bit lossy JPEG images, even though technically they have been supported all along. Similarly, Tom Lane stepped away from the IJG before he could integrate lossless support, so people who wanted to encode/decode lossless JPEG images had to compile libjpeg with Ken Murchison's patch that also collides and breaks compatibility with the 8-bit lossy version of the library. That limited the adoption of lossless JPEG images. libjpeg-turbo attempts to address those historical limitations by providing support for all JPEG-1 variants using the same API/ABI.

dlemstra added a commit that referenced this pull request Dec 6, 2025
This was referenced Dec 30, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

3 participants