Releases: libjpeg-turbo/libjpeg-turbo
3.1.90 (3.2 beta1)
Assets
- libjpeg-turbo-3.1.90.tar.gz is the official source tarball for this release. The automatically generated "Source code" assets are not supported.
- Refer to https://libjpeg-turbo.org/Downloads/DigitalSignatures for information regarding the methods used to sign the files in this release and instructions for verifying the signatures.
- Refer to https://libjpeg-turbo.org/Documentation/OfficialBinaries for information regarding the compatibility of the binary packages in this release.
Support
Code Quality: Beta
Current Support Category: Active
Release Notes
Significant changes relative to 3.1.4.1:
-
The legacy GNU Assembler (GAS) implementation of the Arm Neon SIMD extensions has been removed. Arm builds of libjpeg-turbo must now use GCC 12 or later or Clang in order to achieve full performance.
-
The SIMD dispatchers have been overhauled so that the list of supported SIMD instruction sets is initialized on a per-instance basis rather than a per-thread basis, thus eliminating the need for thread-local storage in the libjpeg API library. The overhaul also streamlines and modernizes the dispatcher architecture, eliminates redundant and unnecessary code, and generally simplifies the process of adding new SIMD extensions. A new test program (simdcoverage) can be used to validate the correctness of a particular dispatcher.
-
If the
WITH_PROFILECMake variable is enabled, libjpeg-turbo now measures the cumulative average throughput of each lossy JPEG compression and decompression algorithm and reports it to the command line whenjpeg_destroy_compress(),jpeg_destroy_decompress(), ortj3Destroy()is called. -
jpegtran now honors the
-trimand-perfectoptions when expanding the image size using the-cropoption. If-trimis specified, then partial iMCUs from the source image are discarded in the expanded image (equivalent to the previous behavior.) If-trimis not specified, then partial iMCUs are left in place. If-perfectis specified, then expanding the image size using the-cropoption will fail if there are any partial iMCUs in the source image. The new default behavior is useful, in combination with the-dropoption, for reversibly combining multiple JPEG source images into a single composite JPEG image. -
The MIPS DSPr2 SIMD extensions have been removed. Justifications:
- MIPS Technologies deprecated the MIPS architecture in favor of RISC-V in 2021.
- The DSPr2 instruction set was already obsolete at that point, having been superseded by the MSA instruction set (which is now also deprecated.)
- The overall speedup from the DSPr2 SIMD extensions was never compelling, in part because some of the modules were implemented using scalar (non-SIMD) instructions and were thus no faster than the equivalent C modules.
- Some of the DSPr2 SIMD modules had long-standing bugs, and it was necessary to disable those modules in order to prevent accuracy issues with libjpeg-turbo on MIPS CPUs.
- The DSPr2 SIMD extensions only worked with 32-bit MIPS applications.
- The libjpeg-turbo Project has never had access to a MIPS test platform, which limited our ability to maintain the DSPr2 SIMD extensions.
Even before the MIPS architecture was deprecated, the aforementioned limitations had already reduced the number of platforms and applications that could benefit from the DSPr2 SIMD extensions to near zero. The DSPr2 SIMD extensions will continue to be maintained in the 3.1.x branch on a break/fix basis.
-
Added RISC-V Vector (RVV) SIMD implementations of the colorspace conversion, chroma downsampling and upsampling, integer quantization and sample conversion, and integer DCT/IDCT algorithms. When using the accurate integer DCT/IDCT algorithms, RGB-to-baseline JPEG compression is approximately 149-246% (avg. 201%) faster relative to libjpeg-turbo 3.1.x, and baseline-to-RGB JPEG decompression is approximately 48-180% (avg. 115%) faster. (Tested on a 1.6 GHz Ky X1 CPU. Actual mileage may vary.)
-
The TurboJPEG Java API has been moved to a dedicated repository where it can evolve independently of the TurboJPEG C API based on demand. Justifications:
- The TurboJPEG Java API was designed around the needs of Java Web Start, an obsolete "zero-install" method of Java application deployment. The idea was that JWS applications could be deployed along with JAR files containing the TurboJPEG Java API and TurboJPEG API library, which contained Java Native Interface (JNI) bindings to support the former. It made sense for our project to package those resources so downstream developers could easily sign and deploy them via JWS. These days, however, Java applications are more frequently deployed as standalone applications.
- The TurboJPEG Java API was designed at a time when libjpeg-turbo was not ubiquitous and JNA was nascent. These days, libjpeg-turbo is used by most operating systems, so there is less of a need for us to package an end-to-end solution for high-speed JPEG support in Java.
- The Java-friendly design of the TurboJPEG Java API (specifically, the requirement that it work directly with Java arrays rather than NIO buffers) necessitated allocating all buffers on the Java heap in order to avoid buffer copies. That necessitated using fixed-size JPEG buffers (the equivalent of
TJPARAM_NOREALLOC), which meant that all JPEG buffers had to be big enough to account for the size of the ICC profile and the possibility of zero compression. Some of the proposed new TurboJPEG API features would have been impossible to implement in the TurboJPEG Java API without completely redesigning it. - The Java-friendly design of the TurboJPEG Java API made it more difficult to maintain, document, and extend than the C API, which reduced our ability to add needed features in a timely manner.
Example code (TurboJPEG/JNA) demonstrating how to use the TurboJPEG C API through Java Native Access (JNA) has been added to the source tree and can be built, tested, and installed by setting the
WITH_JNACMake variable. TurboJPEG/JNA generally performs as well as the TurboJPEG C API, whereas compressing JPEG images with the TurboJPEG Java API was slower on some platforms. -
To facilitate shadow recovery in underexposed images, the libjpeg and TurboJPEG APIs and associated programs now allow an 8-bit-per-sample lossy JPEG image to be decompressed to a 12-bit-per-sample output image. This is enabled in the libjpeg API by setting
cinfo->data_precision = 12after callingjpeg_read_header(), and in the TurboJPEG API by callingtj3Decompress12()after callingtj3DecompressHeader(). -
cjpeg, djpeg,
tj3LoadImage*(), andtj3SaveImage*()now support 8-bit-per-channel and 16-bit-per-channel PNG images.- By default, cjpeg transfers the embedded ICC profile from a PNG input image to the JPEG image, and djpeg transfers the embedded ICC profile from the JPEG image to a PNG output image. A new option (
-noicc) can be used to disable that behavior. - If called with a TurboJPEG compression instance,
tj3LoadImage*()extracts the embedded ICC profile from a PNG image and associates it with the TurboJPEG instance ifTJPARAM_SAVEMARKERSis set to 2 or 4. - If called with a TurboJPEG decompression instance,
tj3SaveImage*()transfers the ICC profile that was previously extracted from the JPEG image to a PNG image ifTJPARAM_SAVEMARKERSis set to 2 or 4. - The PNG writer upscales images with 2-7 and 9-15 bits of data precision to, respectively, 8-bit-per-channel and 16-bit-per-channel PNG images. The upscaling algorithm is reversible, so a lossless JPEG image with a non-standard data precision can be losslessly converted to a PNG image and back to a lossless JPEG image with the same data precision.
- By default, cjpeg transfers the embedded ICC profile from a PNG input image to the JPEG image, and djpeg transfers the embedded ICC profile from the JPEG image to a PNG output image. A new option (
-
The TurboJPEG API has been improved in the following ways:
tj3GetICCProfile()can now be called multiple times to retrieve the ICC profile that was previously extracted from a JPEG image.tj3GetICCProfile()can now be used to retrieve the ICC profile associated with a TurboJPEG compression instance (including an ICC profile extracted from a PNG image bytj3LoadImage*().)- The JPEG colorspace can now be reset to the default, using a new
TJPARAM_COLORSPACEvalue (TJCS_DEFAULT.) - 4:1:0 and 2:4 subsampling are now supported.
-
Added a new cjpeg, djpeg, and jpegtran option (
-nooverwrite) that causes the programs to fail if the specified output file exists. -
jpegtran now includes a
-rolloption that performs a lossless roll transform (shift with wraparound), which is similar in concept to the-rolloption in ImageMagick and the Offset filter/tool in Photoshop and GIMP.
3.1.4.1
Assets
- libjpeg-turbo-3.1.4.1.tar.gz is the official source tarball for this release. The automatically generated "Source code" assets are not supported.
- Refer to https://libjpeg-turbo.org/Downloads/DigitalSignatures for information regarding the methods used to sign the files in this release and instructions for verifying the signatures.
- Refer to https://libjpeg-turbo.org/Documentation/OfficialBinaries for information regarding the compatibility of the binary packages in this release.
Support
Code Quality: Stable
Current Support Category: Active
Release Notes
Significant changes relative to 3.1.4:
- Fixed multiple issues, some long-standing and some that were regressions introduced in 3.1.4, that made the CMake package config files non-relocatable and broke the
--prefixoption tocmake --install.
Significant changes relative to 3.1.3:
-
Fixed an issue in the TurboJPEG 2.x compatibility wrapper whereby, if a calling program attempted to decompress a lossless JPEG image using
tjDecompress2()with decompression scaling, the decompressed image was unexpectedly unscaled. This could have led to a buffer overrun if the caller allocated the packed-pixel destination buffer based on the assumption that the decompressed image would be scaled down. -
The SIMD dispatchers now use
getauxval()orelf_aux_info(), if available, to detect support for Neon and AltiVec instructions on AArch32 and PowerPC Linux, Android, and *BSD systems. -
Hardened the libjpeg API against hypothetical applications that may erroneously set one of the exposed quantization table values to 0 just before calling
jpeg_start_compress(). (This would never happen in a correctly-written program, becausejpeg_add_quant_table()clamps all values less than 1.) -
Fixed a division-by-zero error that occurred when attempting to use the jpegtran
-dropoption with a specially-crafted malformed drop image (specifically an image in which one or more of the quantization table values was 0.) -
Fixed an issue in the TurboJPEG API library's data destination manager that manifested as:
- a memory leak that occurred if a pre-allocated JPEG destination buffer was passed to
tj3Compress*()ortj3Transform(),TJPARAM_NOREALLOCwas unset, and it was necessary for the library to re-allocate the buffer to accommodate the destination image, and - a potential caller double free that occurred if pre-allocated JPEG destination buffers were passed to
tj3Transform(), multiple lossless transform operations were performed, and it was necessary for the library to re-allocate the second buffer to accommodate the second destination image.
- a memory leak that occurred if a pre-allocated JPEG destination buffer was passed to
-
Fixed an issue in
tj3Transform()whereby, ifTJPARAM_SAVEMARKERSwas set to 2 or 4,TJXOPT_COPYNONEwas not specified, an ICC profile was extracted from the source image, and another ICC profile was associated with the TurboJPEG instance usingtj3SetICCProfile(), both profiles were embedded in the destination image. The documented API behavior is forTJXOPT_COPYNONEto take precedence overTJPARAM_SAVEMARKERSand forTJPARAM_SAVEMARKERSto take precedence over the associated ICC profile. Thus,tj3Transform()now ignores the associated ICC profile unlessTJXOPT_COPYNONEis specified orTJPARAM_SAVEMARKERSis set to something other than 2 or 4. -
Fixed an oversight in the libjpeg API whereby, if a calling application manually set
cinfo.Ss(the predictor selection value) to a value less than 1 or greater than 7 after callingjpeg_enable_lossless()and prior to callingjpeg_start_compress(), an incorrect (all white) lossless JPEG image was silently generated. -
Further hardened the TurboJPEG Java API against hypothetical applications that may erroneously pass huge values to one of the compression, YUV encoding, decompression, YUV decoding, or packed-pixel image I/O methods, leading to signed integer overflow in the JNI wrapper's buffer size checks that rendered those checks ineffective.
3.1.4
Assets
- libjpeg-turbo-3.1.4.tar.gz is the official source tarball for this release. The automatically generated "Source code" assets are not supported.
- Refer to https://libjpeg-turbo.org/Downloads/DigitalSignatures for information regarding the methods used to sign the files in this release and instructions for verifying the signatures.
- Refer to https://libjpeg-turbo.org/Documentation/OfficialBinaries for information regarding the compatibility of the binary packages in this release.
Support
Code Quality: Stable
Current Support Category: Active
Release Notes
Significant changes relative to 3.1.3:
-
Fixed an issue in the TurboJPEG 2.x compatibility wrapper whereby, if a calling program attempted to decompress a lossless JPEG image using
tjDecompress2()with decompression scaling, the decompressed image was unexpectedly unscaled. This could have led to a buffer overrun if the caller allocated the packed-pixel destination buffer based on the assumption that the decompressed image would be scaled down. -
The SIMD dispatchers now use
getauxval()orelf_aux_info(), if available, to detect support for Neon and AltiVec instructions on AArch32 and PowerPC Linux, Android, and *BSD systems. -
Hardened the libjpeg API against hypothetical applications that may erroneously set one of the exposed quantization table values to 0 just before calling
jpeg_start_compress(). (This would never happen in a correctly-written program, becausejpeg_add_quant_table()clamps all values less than 1.) -
Fixed a division-by-zero error that occurred when attempting to use the jpegtran
-dropoption with a specially-crafted malformed drop image (specifically an image in which one or more of the quantization table values was 0.) -
Fixed an issue in the TurboJPEG API library's data destination manager that manifested as:
- a memory leak that occurred if a pre-allocated JPEG destination buffer was passed to
tj3Compress*()ortj3Transform(),TJPARAM_NOREALLOCwas unset, and it was necessary for the library to re-allocate the buffer to accommodate the destination image, and - a potential caller double free that occurred if pre-allocated JPEG destination buffers were passed to
tj3Transform(), multiple lossless transform operations were performed, and it was necessary for the library to re-allocate the second buffer to accommodate the second destination image.
- a memory leak that occurred if a pre-allocated JPEG destination buffer was passed to
-
Fixed an issue in
tj3Transform()whereby, ifTJPARAM_SAVEMARKERSwas set to 2 or 4,TJXOPT_COPYNONEwas not specified, an ICC profile was extracted from the source image, and another ICC profile was associated with the TurboJPEG instance usingtj3SetICCProfile(), both profiles were embedded in the destination image. The documented API behavior is forTJXOPT_COPYNONEto take precedence overTJPARAM_SAVEMARKERSand forTJPARAM_SAVEMARKERSto take precedence over the associated ICC profile. Thus,tj3Transform()now ignores the associated ICC profile unlessTJXOPT_COPYNONEis specified orTJPARAM_SAVEMARKERSis set to something other than 2 or 4. -
Fixed an oversight in the libjpeg API whereby, if a calling application manually set
cinfo.Ss(the predictor selection value) to a value less than 1 or greater than 7 after callingjpeg_enable_lossless()and prior to callingjpeg_start_compress(), an incorrect (all white) lossless JPEG image was silently generated. -
Further hardened the TurboJPEG Java API against hypothetical applications that may erroneously pass huge values to one of the compression, YUV encoding, decompression, YUV decoding, or packed-pixel image I/O methods, leading to signed integer overflow in the JNI wrapper's buffer size checks that rendered those checks ineffective.
3.1.3
Assets
- libjpeg-turbo-3.1.3.tar.gz is the official source tarball for this release. The automatically generated "Source code" assets are not supported.
- Refer to https://libjpeg-turbo.org/Downloads/DigitalSignatures for information regarding the methods used to sign the files in this release and instructions for verifying the signatures.
- Refer to https://libjpeg-turbo.org/Documentation/OfficialBinaries for information regarding the compatibility of the binary packages in this release.
Support
Code Quality: Stable
Current Support Category: Active
Release Notes
Significant changes relative to 3.1.2:
-
Hardened the TurboJPEG API against hypothetical applications that may erroneously call
tj*Compress*()ortj*Transform()with a reused JPEG destination buffer pointer while specifying a destination buffer size of 0. -
Hardened the TurboJPEG API against hypothetical applications that may erroneously set
TJPARAM_LOSSLESSorTJPARAM_COLORSPACEprior to callingtj3EncodeYUV*8()ortj3CompressFromYUV*8().tj3EncodeYUV*8()andtj3CompressFromYUV*8()now ignoreTJPARAM_LOSSLESSandTJPARAM_COLORSPACE. -
Hardened the TurboJPEG Java API against hypothetical applications that may erroneously pass huge X or Y offsets to one of the compression, YUV encoding, decompression, or YUV decoding methods, leading to signed integer overflow in the JNI wrapper's buffer size checks that rendered those checks ineffective.
-
Fixed an issue in the TurboJPEG Java API whereby
TJCompressor.getSourceBuf()sometimes returned the buffer from a previous invocation ofTJCompressor.loadSourceImage()if the target data precision was changed before the most recent invocation. -
Fixed an issue in the PPM reader that caused incorrect pixels to be generated when using
tj3LoadImage*()orTJCompressor.loadSourceImage()to load a PBMPLUS (PPM/PGM) file into a CMYK buffer with a different data precision than that of the file.
3.1.2
Assets
- libjpeg-turbo-3.1.2.tar.gz is the official source tarball for this release. The automatically generated "Source code" assets are not supported.
- Refer to https://libjpeg-turbo.org/Downloads/DigitalSignatures for information regarding the methods used to sign the files in this release and instructions for verifying the signatures.
- Refer to https://libjpeg-turbo.org/Documentation/OfficialBinaries for information regarding the compatibility of the binary packages in this release.
Support
Code Quality: Stable
Current Support Category: Active
Release Notes
Significant changes relative to 3.1.1:
-
Fixed a regression introduced by 3.1 beta1[5] that caused a segfault in TJBench if
-copyor-cwas passed as the last command-line argument. -
The build system now uses wrappers rather than CMake object libraries to compile source files for multiple data precisions. This improves code readability and facilitates adapting the libjpeg-turbo source code to non-CMake build systems.
-
Fixed an issue whereby decompressing a 4:2:0 or 4:2:2 JPEG image with merged upsampling disabled/one-pass color quantization enabled, then reusing the same API instance to decompress a 4:2:0 or 4:2:2 JPEG image with merged upsampling enabled/color quantization disabled, caused
jpeg_skip_scanlines()to use freed memory. In practice, the freed memory was not reclaimed before it was used. Thus, this issue did not cause a segfault or other user-visible errant behavior (it was only detectable with ASan), and it did not likely pose a security risk. -
The AArch64 (Arm 64-bit) Neon SIMD extensions and accelerated Huffman codec now support the Arm64EC ABI on Windows, which allows Windows/x64 applications to call native Arm64 functions when running under the Windows/x64 emulator on Windows/Arm.
3.1.1
Assets
- libjpeg-turbo-3.1.1.tar.gz is the official source tarball for this release. The automatically generated "Source code" assets are not supported.
- Refer to https://libjpeg-turbo.org/Downloads/DigitalSignatures for information regarding the methods used to sign the files in this release and instructions for verifying the signatures.
- Refer to https://libjpeg-turbo.org/Documentation/OfficialBinaries for information regarding the compatibility of the binary packages in this release.
Packaging Changes
- The macOS packages are now notarized, which eliminates a Gatekeeper warning with recent macOS releases. (Previously, installing libjpeg-turbo on recent macOS releases required overriding the warning in the Privacy & Security pane under System Settings.)
- A Windows/Arm package is now provided.
- New builds of libjpeg-turbo-3.1.1-vc-x64.exe and libjpeg-turbo-3.1.1-vc-arm64.exe built with clang-cl were uploaded on 2025-06-18. Relative to the Visual C++ compiler, clang-cl improves the overall performance of libjpeg-turbo by approximately 10% on average for x64 systems and 30-35% on average for Arm64 systems.
- A new build of libjpeg-turbo-3.1.1.dmg was uploaded on 2025-08-13 to address an issue whereby the TurboJPEG Java wrapper could not be used with the x86-64 architecture.
Support
Code Quality: Stable
Current Support Category: Active
Release Notes
Significant changes relative to 3.1.0:
- Hardened the libjpeg API against hypothetical calling applications that may erroneously change the value of the
data_precisionfield injpeg_compress_structorjpeg_decompress_structafter callingjpeg_start_compress()orjpeg_start_decompress().
3.1.0
Assets
- libjpeg-turbo-3.1.0.tar.gz is the official source tarball for this release. The automatically generated "Source code" assets are not supported.
- Refer to https://libjpeg-turbo.org/Downloads/DigitalSignatures for information regarding the methods used to sign the files in this release and instructions for verifying the signatures.
- Refer to https://libjpeg-turbo.org/Documentation/OfficialBinaries for information regarding the compatibility of the binary packages in this release.
Packaging Changes
- The RPM packages now contain SHA-256 header and payload digests. This fixes an issue whereby the RPM signatures could not be verified on Red Hat Enterprise Linux with FIPS mode enabled. The RPM packages now require GLIBC 2.17 or later.
- A new build of libjpeg-turbo-3.1.0.dmg was uploaded on 2025-08-13 to address an issue whereby the TurboJPEG Java wrapper could not be used with the x86-64 architecture.
Support
Code Quality: Stable
Current Support Category: Active
Release Sponsors
This release was made possible via funding from MathWorks.
Release Notes
Significant changes relative to 3.1 beta1:
-
Fixed an issue in the TurboJPEG API whereby, when generating a lossless JPEG image with more than 8 bits per sample, specifying a point transform value greater than 7 resulted in an error ("Parameter value out of range") unless
TJPARAM_PRECISION/TJ.PARAM_PRECISIONwas specified beforeTJPARAM_LOSSLESSPT/TJ.PARAM_LOSSLESSPT. -
Fixed a regression introduced by 1.4 beta1[3] that prevented
jpeg_set_defaults()from resetting the Huffman tables to default (baseline) values if Huffman table optimization or progressive mode was previously enabled in the same libjpeg instance. -
Fixed an issue whereby lossless JPEG compression could not be disabled if it was previously enabled in a libjpeg or TurboJPEG instance.
jpeg_set_defaults()now disables lossless JPEG compression in a libjpeg instance, and settingTJPARAM_LOSSLESS/TJ.PARAM_LOSSLESSto0now disables lossless JPEG compression in a TurboJPEG instance.
3.0.90 (3.1 beta1)
Assets
- libjpeg-turbo-3.0.90.tar.gz is the official source tarball for this release. The automatically generated "Source code" assets are not supported.
- Refer to https://libjpeg-turbo.org/Downloads/DigitalSignatures for information regarding the methods used to sign the files in this release and instructions for verifying the signatures.
- Refer to https://libjpeg-turbo.org/Documentation/OfficialBinaries for information regarding the compatibility of the binary packages in this release.
Packaging Changes
- The RPM packages now contain SHA-256 header and payload digests. This fixes an issue whereby the RPM signatures could not be verified on Red Hat Enterprise Linux with FIPS mode enabled. The RPM packages now require GLIBC 2.17 or later.
Support
Code Quality: Beta
Current Support Category: EOL
Release Sponsors
This release was made possible via funding from MathWorks.
Release Notes
Significant changes relative to 3.0.4:
-
The libjpeg-turbo source tree has been reorganized to make it easier to find the README files, license information, and build instructions. The documentation for the libjpeg API library and associated programs has been moved into the doc/ subdirectory, all C source code and headers have been moved into a new src/ subdirectory, and test scripts have been moved into a new test/ subdirectory.
-
cjpeg no longer allows GIF input files to be converted into 12-bit-per-sample JPEG files. That was never a useful feature, since GIF images have at most 256 colors referenced from a palette of 8-bit-per-component RGB values.
-
Added support for lossless JPEG images with 2 to 15 bits per sample to the libjpeg and TurboJPEG APIs. When creating or decompressing a lossless JPEG image and when loading or saving a PBMPLUS image, functions/methods specific to 8-bit samples now handle 8-bit samples with 2 to 8 bits of data precision (specified using the
data_precisionfield injpeg_compress_structorjpeg_decompress_structor usingTJPARAM_PRECISION/TJ.PARAM_PRECISION), functions/methods specific to 12-bit samples now handle 12-bit samples with 9 to 12 bits of data precision, and functions/methods specific to 16-bit samples now handle 16-bit samples with 13 to 16 bits of data precision. Refer to libjpeg.txt, usage.txt, and the TurboJPEG API documentation for more details. -
All deprecated constants and methods in the TurboJPEG Java API have been removed.
-
TJBench command-line arguments are now more consistent with those of cjpeg, djpeg, and jpegtran. More specifically:
-copynonehas been replaced with-copy none.-fastdcthas been replaced with-dct fast.-fastupsamplehas been replaced with-nosmooth.-hflipand-vfliphave been replaced with-flip {horizontal|vertical}.-limitscanshas been replaced with-maxscans, which allows the scan limit to be specified.-rgb,-bgr,-rgbx,-bgrx,-xbgr,-xrgb, and-cmykhave been replaced with-pixelformat {rgb|bgr|rgbx|bgrx|xbgr|xrgb|cmyk}.-rot90,-rot180, and-rot270have been replaced with-rotate {90|180|270}.-stoponwarninghas been replaced with-strict.- British spellings for
gray(grey) andoptimize(optimise) are now allowed.
The old command-line arguments are deprecated and will be removed in a future release. TJBench command-line arguments can now be abbreviated as well. (Where possible, the abbreviations are the same as those supported by cjpeg, djpeg, and jpegtran.)
-
Added a new TJBench option (
-pixelformat gray) that can be used to test the performance of compressing/decompressing a grayscale JPEG image from/to a packed-pixel grayscale image. -
Fixed an issue whereby, if
TJPARAM_NOREALLOCwas set, TurboJPEG compression and lossless transformation functions ignored the JPEG buffer size(s) passed to them and assumed that the JPEG buffer(s) had been allocated to a worst-case size returned bytj3JPEGBufSize(). This behavior was never documented, although the documentation was unclear regarding whether the JPEG buffer size should be specified if a JPEG buffer is pre-allocated to a worst-case size. -
The TurboJPEG C and Java APIs have been improved in the following ways:
- New image I/O methods (
TJCompressor.loadSourceImage()andTJDecompressor.saveImage()) have been added to the Java API. These methods work similarly to thetj3LoadImage*()andtj3SaveImage*()functions in the C API. - The TurboJPEG lossless transformation function and methods now add restart markers to all destination images if
TJPARAM_RESTARTBLOCKS/TJ.PARAM_RESTARTBLOCKSorTJPARAM_RESTARTROWS/TJ.PARAM_RESTARTROWSis set. - New functions/methods (
tj3SetICCProfile()/TJCompressor.setICCProfile()/TJTransformer.setICCProfile()andtj3GetICCProfile()/TJDecompressor.getICCProfile()) can be used to embed and retrieve ICC profiles. - A new parameter (
TJPARAM_SAVEMARKERS/TJ.PARAM_SAVEMARKERS) can be used to specify the types of markers that will be copied from the source image to the destination image during lossless transformation ifTJXOPT_COPYNONE/TJTransform.OPT_COPYNONEis not specified. - A new convenience function/method (
tj3TransformBufSize()/TJTransformer.bufSize()) can be used to compute the worst-case destination buffer size for a given lossless transform, taking into account cropping, transposition of the width and height, grayscale conversion, and the embedded or extracted ICC profile.
- New image I/O methods (
-
TJExample has been replaced with three programs (TJComp, TJDecomp, and TJTran) that demonstrate how to approximate the functionality of cjpeg, djpeg, and jpegtran using the TurboJPEG C and Java APIs.
3.0.4
Assets
- libjpeg-turbo-3.0.4.tar.gz is the official source tarball for this release. The automatically generated "Source code" assets are not supported.
- Refer to https://libjpeg-turbo.org/Downloads/DigitalSignatures for information regarding the methods used to sign the files in this release and instructions for verifying the signatures.
- Refer to https://libjpeg-turbo.org/Documentation/OfficialBinaries for information regarding the compatibility of the binary packages in this release.
Packaging Changes
- A new build of libjpeg-turbo-3.0.4.dmg was uploaded on 2025-08-13 to address an issue whereby the TurboJPEG Java wrapper could not be used with the Arm64 architecture.
Support
Code Quality: Stable
Current Support Category: Maintenance
Release Notes
Significant changes relative to 3.0.3:
-
Fixed an issue whereby the CPU usage of the default marker processor in the decompressor grew exponentially with the number of markers. This caused an unreasonable slow-down in
jpeg_read_header()if an application calledjpeg_save_markers()to save markers of a particular type and then attempted to decompress a JPEG image containing an excessive number of markers of that type. -
Hardened the default marker processor in the decompressor to guard against an issue (exposed by 3.0 beta2[6]) whereby attempting to decompress a specially-crafted malformed JPEG image (specifically an image with a complete 12-bit-per-sample Start Of Frame segment followed by an incomplete 8-bit-per-sample Start Of Frame segment) using buffered-image mode and input prefetching caused a segfault if the
fill_input_buffer()method in the calling application's custom source manager incorrectly returnedFALSEin response to a prematurely-terminated JPEG data stream. -
Fixed an issue in cjpeg whereby, when generating a 12-bit-per-sample or 16-bit-per-sample lossless JPEG image, specifying a point transform value greater than 7 resulted in an error ("Invalid progressive/lossless parameters") unless the
-precisionoption was specified before the-losslessoption. -
Fixed a regression introduced by 3.0.3[3] that made it impossible for calling applications to generate 12-bit-per-sample arithmetic-coded lossy JPEG images using the TurboJPEG API.
-
Fixed an error ("Destination buffer is not large enough") that occurred when attempting to generate a full-color lossless JPEG image using the TurboJPEG Java API's
byte[] TJCompressor.compress()method if the value ofTJ.PARAM_SUBSAMPwas notTJ.SAMP_444. -
Fixed a segfault in djpeg that occurred if a negative width was specified with the
-cropoption. Since the cropping region width was read into an unsigned 32-bit integer, a negative width was interpreted as a very large value. With certain negative width and positive left boundary values, the bounds checks in djpeg andjpeg_crop_scanline()overflowed and did not detect the out-of-bounds width, which caused a buffer overrun in the upsampling or color conversion routine. Both bounds checks now use 64-bit integers to guard against overflow, and djpeg now checks for negative numbers when it parses the crop specification from the command line. -
Fixed an issue whereby the TurboJPEG lossless transformation function and methods checked the specified cropping region against the source image dimensions and level of chrominance subsampling rather than the destination image dimensions and level of chrominance subsampling, which caused some cropping regions to be unduly rejected when performing 90-degree rotation, 270-degree rotation, transposition, transverse transposition, or grayscale conversion.
-
Fixed a regression, introduced by 3.0 beta2[4], that prevented the
tjTransform()backward compatibility function from copying extra markers from the source image to the destination image. -
Fixed an issue whereby the TurboJPEG lossless transformation function and methods did not honor
TJXOPT_COPYNONE/TJTransform.OPT_COPYNONEunless it was specified for all lossless transforms.
3.0.3
Assets
- libjpeg-turbo-3.0.3.tar.gz is the official source tarball for this release. The automatically generated "Source code" assets are not supported.
- Refer to https://libjpeg-turbo.org/Downloads/DigitalSignatures for information regarding the methods used to sign the files in this release and instructions for verifying the signatures.
- Refer to https://libjpeg-turbo.org/Documentation/OfficialBinaries for information regarding the compatibility of the binary packages in this release.
Support
Code Quality: Stable
Current Support Category: Maintenance
Release Notes
Significant changes relative to 3.0.2:
-
Fixed an issue in the build system, introduced in 3.0.2, that caused all libjpeg-turbo components to depend on the Visual C++ run-time DLL when built with Visual C++ and CMake 3.15 or later, regardless of value of the
WITH_CRT_DLLCMake variable. -
The x86-64 SIMD extensions now include support for Intel Control-flow Enforcement Technology (CET), which is enabled automatically if CET is enabled in the C compiler.
-
Fixed a regression introduced by 3.0 beta2[6] that made it impossible for calling applications to supply custom Huffman tables when generating 12-bit-per-component lossy JPEG images using the libjpeg API.
-
Fixed a segfault that occurred when attempting to use the jpegtran
-dropoption with a specially-crafted malformed input image or drop image (specifically an image in which all of the scans contain fewer components than the number of components specified in the Start Of Frame segment.)