From 05655481917a2d2761cf2fe19b76f639b7f159ef Mon Sep 17 00:00:00 2001 From: DRC Date: Mon, 28 Feb 2022 20:41:56 -0600 Subject: [PATCH 01/24] BUILDING.md: Mention sub-project best practices People keep trying to include libjpeg-turbo into downstream CMake-based build systems by way of the add_subdirectory() function and requesting upstream support when something inevitably breaks. (Refer to: #122, #173, #176, #202, #241, #349, #353, #412, #504, https://github.com/libjpeg-turbo/libjpeg-turbo/commit/a3d4aadd0d1597ad46edcbe3b964499ec785d40c#commitcomment-67575889). libjpeg-turbo has never supported that method of sub-project integration, because doing so would require that we (minimally): 1. avoid using certain CMake variables, such as CMAKE_SOURCE_DIR, CMAKE_BINARY_DIR, and CMAKE_PROJECT_NAME; 2. avoid using implicit include directories and relative paths; 3. provide a way to optionally skip the installation of libjpeg-turbo components in response to 'make install'; 4. provide a way to optionally postfix target names, to avoid namespace conflicts; 5. restructure the top-level CMakeLists.txt so that it properly sets the PROJECT_VERSION variable; and 6. design automated CI tests to ensure that new commits don't break any of the above. Even if we did all of that, issues would still arise, because it is impossible for one upstream build system to anticipate the widely varying needs of every downstream build system. That's why the CMake ExternalProject_Add() function exists, and it is my sincere hope that adding a blurb to BUILDING.md mentioning the need to use that function will head off future GitHub issues on this topic. If not, then I can at least post a link to this commit and the blurb and avoid doing the same song and dance over and over again. --- BUILDING.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/BUILDING.md b/BUILDING.md index e682769e..43eb5002 100644 --- a/BUILDING.md +++ b/BUILDING.md @@ -79,6 +79,14 @@ Build Requirements * If using JDK 11 or later, CMake 3.10.x or later must also be used. +Sub-Project Builds +------------------ + +The libjpeg-turbo build system does not support being included as a sub-project +using the CMake `add_subdirectory()` function. Use the CMake +`ExternalProject_Add()` function instead. + + Out-of-Tree Builds ------------------ From fdab4a7af46e80d6211a616202e3cd771199e20a Mon Sep 17 00:00:00 2001 From: DRC Date: Tue, 8 Mar 2022 17:25:57 -0600 Subject: [PATCH 02/24] Progs: Eliminate obsolete Mac ccommand() interface ccommand() was a 1990s-vintage hack for running console applications without a console. It doesn't exist in any modern macOS compiler. --- cjpeg.c | 15 --------------- djpeg.c | 15 --------------- jpegtran.c | 15 --------------- rdjpgcom.c | 15 --------------- wrjpgcom.c | 15 --------------- 5 files changed, 75 deletions(-) diff --git a/cjpeg.c b/cjpeg.c index 41020a8f..dae18a3f 100644 --- a/cjpeg.c +++ b/cjpeg.c @@ -38,16 +38,6 @@ #include "jversion.h" /* for version message */ #include "jconfigint.h" -#ifdef USE_CCOMMAND /* command-line reader for Macintosh */ -#ifdef __MWERKS__ -#include /* Metrowerks needs this */ -#include /* ... and this */ -#endif -#ifdef THINK_C -#include /* Think declares it here */ -#endif -#endif - /* Create the add-on message string table. */ @@ -584,11 +574,6 @@ main(int argc, char **argv) unsigned long outsize = 0; JDIMENSION num_scanlines; - /* On Mac, fetch a command line. */ -#ifdef USE_CCOMMAND - argc = ccommand(&argv); -#endif - progname = argv[0]; if (progname == NULL || progname[0] == 0) progname = "cjpeg"; /* in case C library doesn't provide it */ diff --git a/djpeg.c b/djpeg.c index 5190e687..7666e3fe 100644 --- a/djpeg.c +++ b/djpeg.c @@ -38,16 +38,6 @@ #include /* to declare isprint() */ -#ifdef USE_CCOMMAND /* command-line reader for Macintosh */ -#ifdef __MWERKS__ -#include /* Metrowerks needs this */ -#include /* ... and this */ -#endif -#ifdef THINK_C -#include /* Think declares it here */ -#endif -#endif - /* Create the add-on message string table. */ @@ -550,11 +540,6 @@ main(int argc, char **argv) #endif JDIMENSION num_scanlines; - /* On Mac, fetch a command line. */ -#ifdef USE_CCOMMAND - argc = ccommand(&argv); -#endif - progname = argv[0]; if (progname == NULL || progname[0] == 0) progname = "djpeg"; /* in case C library doesn't provide it */ diff --git a/jpegtran.c b/jpegtran.c index 4c7ab772..d1552ec7 100644 --- a/jpegtran.c +++ b/jpegtran.c @@ -23,16 +23,6 @@ #include "jversion.h" /* for version message */ #include "jconfigint.h" -#ifdef USE_CCOMMAND /* command-line reader for Macintosh */ -#ifdef __MWERKS__ -#include /* Metrowerks needs this */ -#include /* ... and this */ -#endif -#ifdef THINK_C -#include /* Think declares it here */ -#endif -#endif - /* * Argument-parsing code. @@ -483,11 +473,6 @@ main(int argc, char **argv) JOCTET *icc_profile = NULL; long icc_len = 0; - /* On Mac, fetch a command line. */ -#ifdef USE_CCOMMAND - argc = ccommand(&argv); -#endif - progname = argv[0]; if (progname == NULL || progname[0] == 0) progname = "jpegtran"; /* in case C library doesn't provide it */ diff --git a/rdjpgcom.c b/rdjpgcom.c index 9910a634..d9a6f85a 100644 --- a/rdjpgcom.c +++ b/rdjpgcom.c @@ -30,16 +30,6 @@ #include /* to declare setmode() */ #endif -#ifdef USE_CCOMMAND /* command-line reader for Macintosh */ -#ifdef __MWERKS__ -#include /* Metrowerks needs this */ -#include /* ... and this */ -#endif -#ifdef THINK_C -#include /* Think declares it here */ -#endif -#endif - #ifdef DONT_USE_B_MODE /* define mode parameters for fopen() */ #define READ_BINARY "r" #else @@ -450,11 +440,6 @@ main(int argc, char **argv) char *arg; int verbose = 0, raw = 0; - /* On Mac, fetch a command line. */ -#ifdef USE_CCOMMAND - argc = ccommand(&argv); -#endif - progname = argv[0]; if (progname == NULL || progname[0] == 0) progname = "rdjpgcom"; /* in case C library doesn't provide it */ diff --git a/wrjpgcom.c b/wrjpgcom.c index 3ee08a0e..060925fe 100644 --- a/wrjpgcom.c +++ b/wrjpgcom.c @@ -28,16 +28,6 @@ #include /* to declare setmode() */ #endif -#ifdef USE_CCOMMAND /* command-line reader for Macintosh */ -#ifdef __MWERKS__ -#include /* Metrowerks needs this */ -#include /* ... and this */ -#endif -#ifdef THINK_C -#include /* Think declares it here */ -#endif -#endif - #ifdef DONT_USE_B_MODE /* define mode parameters for fopen() */ #define READ_BINARY "r" #define WRITE_BINARY "w" @@ -415,11 +405,6 @@ main(int argc, char **argv) unsigned int comment_length = 0; int marker; - /* On Mac, fetch a command line. */ -#ifdef USE_CCOMMAND - argc = ccommand(&argv); -#endif - progname = argv[0]; if (progname == NULL || progname[0] == 0) progname = "wrjpgcom"; /* in case C library doesn't provide it */ From 932b5bb0d56bfa6b51a185f6c1f4181c255fe2b2 Mon Sep 17 00:00:00 2001 From: DRC Date: Wed, 9 Mar 2022 10:50:51 -0600 Subject: [PATCH 03/24] IJG dox: Wordsmithing and formatting tweaks - Remove the section in libjpeg.txt that advised against building libjpeg as a shared library. We obviously do not follow that advice, and libjpeg-turbo does guarantee backward ABI compatibility in our libjpeg API library, even though libjpeg did not and does not. (Future expansion of our libjpeg API library, if necessary, will be accomplished using get/set functions that store the new parameters in the opaque master structs. Refer to https://github.com/mozilla/mozjpeg/commit/db2986c96fcebe10c8700081578e5305fd7bc7dc.) - Unmention install.txt, which was never relevant to libjpeg-turbo and was removed in v1.3 (6f96153c67e9a88775b457f998fc7fdd64c62cee). - Remove extraneous spaces. - Document the fact that TWO_FILE_COMMANDLINE must be defined in order to use the two-file interface with cjpeg, djpeg, jpegtran, and wrjpgcom. libjpeg-turbo never enables that interface by default. --- libjpeg.txt | 20 ++++---------------- usage.txt | 27 ++++++++++++++------------- 2 files changed, 18 insertions(+), 29 deletions(-) diff --git a/libjpeg.txt b/libjpeg.txt index 3c680b5f..309f9d3b 100644 --- a/libjpeg.txt +++ b/libjpeg.txt @@ -3,7 +3,7 @@ USING THE IJG JPEG LIBRARY This file was part of the Independent JPEG Group's software: Copyright (C) 1994-2013, Thomas G. Lane, Guido Vollbeding. libjpeg-turbo Modifications: -Copyright (C) 2010, 2014-2018, 2020, D. R. Commander. +Copyright (C) 2010, 2014-2018, 2020, 2022, D. R. Commander. Copyright (C) 2015, Google, Inc. For conditions of distribution and use, see the accompanying README.ijg file. @@ -840,18 +840,7 @@ is to prepare a library file ("libjpeg.a", or a corresponding name on non-Unix machines) and reference it at your link step. If you use only half of the library (only compression or only decompression), only that much code will be included from the library, unless your linker is hopelessly brain-damaged. -The supplied makefiles build libjpeg.a automatically (see install.txt). - -While you can build the JPEG library as a shared library if the whim strikes -you, we don't really recommend it. The trouble with shared libraries is that -at some point you'll probably try to substitute a new version of the library -without recompiling the calling applications. That generally doesn't work -because the parameter struct declarations usually change with each new -version. In other words, the library's API is *not* guaranteed binary -compatible across versions; we only try to ensure source-code compatibility. -(In hindsight, it might have been smarter to hide the parameter structs from -applications and introduce a ton of access functions instead. Too late now, -however.) +The supplied build system builds libjpeg.a automatically. It may be worth pointing out that the core JPEG library does not actually require the stdio library: only the default source/destination managers and @@ -3075,9 +3064,8 @@ BITS_IN_JSAMPLE as 12 rather than 8. Note that this causes JSAMPLE to be larger than a char, so it affects the surrounding application's image data. The sample applications cjpeg and djpeg can support 12-bit mode only for PPM and GIF file formats; you must disable the other file formats to compile a -12-bit cjpeg or djpeg. (install.txt has more information about that.) -At present, a 12-bit library can handle *only* 12-bit images, not both -precisions. +12-bit cjpeg or djpeg. At present, a 12-bit library can handle *only* 12-bit +images, not both precisions. Note that a 12-bit library always compresses in Huffman optimization mode, in order to generate valid Huffman tables. This is necessary because our diff --git a/usage.txt b/usage.txt index bc2253f1..0b6036ac 100644 --- a/usage.txt +++ b/usage.txt @@ -25,7 +25,7 @@ GENERAL USAGE We provide two programs, cjpeg to compress an image file into JPEG format, and djpeg to decompress a JPEG file back into a conventional image format. -On Unix-like systems, you say: +On most systems, you say: cjpeg [switches] [imagefile] >jpegfile or djpeg [switches] [jpegfile] >imagefile @@ -34,19 +34,19 @@ named. They always write to standard output (with trace/error messages to standard error). These conventions are handy for piping images between programs. -On most non-Unix systems, you say: +If you defined TWO_FILE_COMMANDLINE when compiling the programs, you can +instead say: cjpeg [switches] imagefile jpegfile or djpeg [switches] jpegfile imagefile i.e., both the input and output files are named on the command line. This style is a little more foolproof, and it loses no functionality if you don't -have pipes. (You can get this style on Unix too, if you prefer, by defining -TWO_FILE_COMMANDLINE when you compile the programs; see install.txt.) +have pipes. You can also say: cjpeg [switches] -outfile jpegfile imagefile or - djpeg [switches] -outfile imagefile jpegfile + djpeg [switches] -outfile imagefile jpegfile This syntax works on all systems, so it is useful for scripts. The currently supported image file formats are: PPM (PBMPLUS color format), @@ -143,8 +143,8 @@ customized) quantization tables can be set with the -qtables option and assigned to components with the -qslots option (see the "wizard" switches below.) -JPEG files generated with separate luminance and chrominance quality are -fully compliant with standard JPEG decoders. +JPEG files generated with separate luminance and chrominance quality are fully +compliant with standard JPEG decoders. CAUTION: For this setting to be useful, be sure to pass an argument of -sample 1x1 to cjpeg to disable chrominance subsampling. Otherwise, the @@ -218,7 +218,7 @@ Switches for advanced users: space is needed, an error will occur. -verbose Enable debug printout. More -v's give more printout. - or -debug Also, version information is printed at startup. + or -debug Also, version information is printed at startup. The -restart option inserts extra markers that allow a JPEG decoder to resynchronize after a transmission error. Without restart markers, any damage @@ -467,9 +467,10 @@ quality. However, while the image data is losslessly transformed, metadata can be removed. See the -copy option for specifics. jpegtran uses a command line syntax similar to cjpeg or djpeg. -On Unix-like systems, you say: +On most systems, you say: jpegtran [switches] [inputfile] >outputfile -On most non-Unix systems, you say: +If you defined TWO_FILE_COMMANDLINE when compiling the program, you can instead +say: jpegtran [switches] inputfile outputfile where both the input and output files are JPEG files. @@ -649,13 +650,13 @@ file; it does not modify the input file. DO NOT try to overwrite the input file by directing wrjpgcom's output back into it; on most systems this will just destroy your file. -The command line syntax for wrjpgcom is similar to cjpeg's. On Unix-like -systems, it is +The command line syntax for wrjpgcom is similar to cjpeg's. On most systems, +it is wrjpgcom [switches] [inputfilename] The output file is written to standard output. The input file comes from the named file, or from standard input if no input file is named. -On most non-Unix systems, the syntax is +If you defined TWO_FILE_COMMANDLINE when compiling the program, the syntax is: wrjpgcom [switches] inputfilename outputfilename where both input and output file names must be given explicitly. From 9abeff46d87bd201a952e276f3e4339556a403a3 Mon Sep 17 00:00:00 2001 From: DRC Date: Wed, 9 Mar 2022 11:48:30 -0600 Subject: [PATCH 04/24] Remove extraneous #include directives jinclude.h already includes stdio.h, stdlib.h, and string.h. --- simd/arm/aarch32/jsimd.c | 2 -- simd/arm/aarch64/jsimd.c | 2 -- simd/mips/jsimd.c | 2 -- simd/mips64/jsimd.c | 2 -- simd/powerpc/jsimd.c | 2 -- turbojpeg-jni.c | 2 -- turbojpeg.c | 2 -- 7 files changed, 14 deletions(-) diff --git a/simd/arm/aarch32/jsimd.c b/simd/arm/aarch32/jsimd.c index e3adf23d..920f7656 100644 --- a/simd/arm/aarch32/jsimd.c +++ b/simd/arm/aarch32/jsimd.c @@ -25,8 +25,6 @@ #include "../../../jsimddct.h" #include "../../jsimd.h" -#include -#include #include static unsigned int simd_support = ~0; diff --git a/simd/arm/aarch64/jsimd.c b/simd/arm/aarch64/jsimd.c index 604d5472..41c06d31 100644 --- a/simd/arm/aarch64/jsimd.c +++ b/simd/arm/aarch64/jsimd.c @@ -25,8 +25,6 @@ #include "../../jsimd.h" #include "jconfigint.h" -#include -#include #include #define JSIMD_FASTLD3 1 diff --git a/simd/mips/jsimd.c b/simd/mips/jsimd.c index d2546eed..36ea865d 100644 --- a/simd/mips/jsimd.c +++ b/simd/mips/jsimd.c @@ -23,8 +23,6 @@ #include "../../jsimddct.h" #include "../jsimd.h" -#include -#include #include static unsigned int simd_support = ~0; diff --git a/simd/mips64/jsimd.c b/simd/mips64/jsimd.c index e8f1af56..2e626b2d 100644 --- a/simd/mips64/jsimd.c +++ b/simd/mips64/jsimd.c @@ -24,8 +24,6 @@ #include "../../jsimddct.h" #include "../jsimd.h" -#include -#include #include static unsigned int simd_support = ~0; diff --git a/simd/powerpc/jsimd.c b/simd/powerpc/jsimd.c index b9e86dcf..3f648ef3 100644 --- a/simd/powerpc/jsimd.c +++ b/simd/powerpc/jsimd.c @@ -27,8 +27,6 @@ #include "../../jsimddct.h" #include "../jsimd.h" -#include -#include #include #if defined(__OpenBSD__) diff --git a/turbojpeg-jni.c b/turbojpeg-jni.c index ba76634e..0cf5f702 100644 --- a/turbojpeg-jni.c +++ b/turbojpeg-jni.c @@ -26,8 +26,6 @@ * POSSIBILITY OF SUCH DAMAGE. */ -#include -#include #include "turbojpeg.h" #include "jinclude.h" #include diff --git a/turbojpeg.c b/turbojpeg.c index d5e31360..1a37e8cf 100644 --- a/turbojpeg.c +++ b/turbojpeg.c @@ -30,8 +30,6 @@ /* TurboJPEG/LJT: this implements the TurboJPEG API using libjpeg or libjpeg-turbo */ -#include -#include #include #include #define JPEG_INTERNALS From 6f1534d61828577050ea7681b74db72d849d98a5 Mon Sep 17 00:00:00 2001 From: DRC Date: Wed, 9 Mar 2022 12:58:17 -0600 Subject: [PATCH 05/24] example.txt: Fix a typo --- example.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/example.txt b/example.txt index bc0ba49d..d473aede 100644 --- a/example.txt +++ b/example.txt @@ -311,7 +311,7 @@ read_JPEG_file(char *filename) * We call the libjpeg API from within a separate function, because modifying * the local non-volatile jpeg_decompress_struct instance below the setjmp() * return point and then accessing the instance after setjmp() returns would - * return in undefined behavior that may potentially overwrite all or part of + * result in undefined behavior that may potentially overwrite all or part of * the structure. */ From f3c716a2bc1dce073ed729619a141b9927653d72 Mon Sep 17 00:00:00 2001 From: DRC Date: Thu, 10 Mar 2022 22:31:20 -0600 Subject: [PATCH 06/24] Link Sponsor button to GitHub Sponsors ... ... instead of PayPal. --- .github/FUNDING.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml index 05df08bf..e64059f0 100644 --- a/.github/FUNDING.yml +++ b/.github/FUNDING.yml @@ -1 +1 @@ -custom: ['https://www.paypal.com/cgi-bin/webscr?cmd=_donations&business=information%40libjpeg-turbo%2eorg&lc=US&item_name=The%20libjpeg-turbo%20General%20Fund&no_note=0¤cy_code=USD&bn=PP%2dDonationsBF%3abtn_donateCC_LG%2egif%3aNonHostedGuest'] +github: libjpeg-turbo From a0148454030bddfabcebe59724e64fbb7b7ad678 Mon Sep 17 00:00:00 2001 From: DRC Date: Fri, 11 Mar 2022 10:50:47 -0600 Subject: [PATCH 07/24] Win: Fix build with Visual Studio 2010 (broken by 607b668ff96e40fdc749de9b1bb98e7f40c86d93) - Visual Studio 2010 apparently doesn't have the snprintf() inline function, so restore the macro that emulates that function using _snprintf_s(). - Explicitly include errno.h in strtest.c, since jinclude.h doesn't include it when building with Visual Studio. --- CMakeLists.txt | 2 +- ChangeLog.md | 9 +++++++++ jerror.c | 4 ++-- jinclude.h | 12 ++++++++++++ strtest.c | 1 + tjbench.c | 24 ++++++++++++------------ tjunittest.c | 4 ++-- tjutil.h | 9 ++++++++- turbojpeg.c | 34 +++++++++++++++++----------------- 9 files changed, 64 insertions(+), 35 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 1198eced..a977b99b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -10,7 +10,7 @@ if(CMAKE_EXECUTABLE_SUFFIX) endif() project(libjpeg-turbo C) -set(VERSION 2.1.3) +set(VERSION 2.1.4) set(COPYRIGHT_YEAR "1991-2022") string(REPLACE "." ";" VERSION_TRIPLET ${VERSION}) list(GET VERSION_TRIPLET 0 VERSION_MAJOR) diff --git a/ChangeLog.md b/ChangeLog.md index e6700c3c..62a9b0cf 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -1,3 +1,12 @@ +2.1.4 +===== + +### Significant changes relative to 2.1.3 + +1. Fixed a regression introduced in 2.1.3 that caused build failures with +Visual Studio 2010. + + 2.1.3 ===== diff --git a/jerror.c b/jerror.c index d5447029..d0ab5b88 100644 --- a/jerror.c +++ b/jerror.c @@ -189,9 +189,9 @@ format_message(j_common_ptr cinfo, char *buffer) /* Format the message into the passed buffer */ if (isstring) - snprintf(buffer, JMSG_LENGTH_MAX, msgtext, err->msg_parm.s); + SNPRINTF(buffer, JMSG_LENGTH_MAX, msgtext, err->msg_parm.s); else - snprintf(buffer, JMSG_LENGTH_MAX, msgtext, + SNPRINTF(buffer, JMSG_LENGTH_MAX, msgtext, err->msg_parm.i[0], err->msg_parm.i[1], err->msg_parm.i[2], err->msg_parm.i[3], err->msg_parm.i[4], err->msg_parm.i[5], diff --git a/jinclude.h b/jinclude.h index 120614b2..e8d983ac 100644 --- a/jinclude.h +++ b/jinclude.h @@ -45,6 +45,18 @@ */ +#ifdef _MSC_VER + +#define SNPRINTF(str, n, format, ...) \ + _snprintf_s(str, n, _TRUNCATE, format, ##__VA_ARGS__) + +#else + +#define SNPRINTF snprintf + +#endif + + #ifndef NO_GETENV #ifdef _MSC_VER diff --git a/strtest.c b/strtest.c index ceaad91a..88b568c9 100644 --- a/strtest.c +++ b/strtest.c @@ -27,6 +27,7 @@ */ #include "jinclude.h" +#include #define CHECK_VALUE(actual, expected, desc) \ diff --git a/tjbench.c b/tjbench.c index 8730a022..90786cf0 100644 --- a/tjbench.c +++ b/tjbench.c @@ -107,7 +107,7 @@ static char *formatName(int subsamp, int cs, char *buf) if (cs == TJCS_YCbCr) return (char *)subNameLong[subsamp]; else if (cs == TJCS_YCCK || cs == TJCS_CMYK) { - snprintf(buf, 80, "%s %s", csName[cs], subNameLong[subsamp]); + SNPRINTF(buf, 80, "%s %s", csName[cs], subNameLong[subsamp]); return buf; } else return (char *)csName[cs]; @@ -120,10 +120,10 @@ static char *sigfig(double val, int figs, char *buf, int len) int digitsAfterDecimal = figs - (int)ceil(log10(fabs(val))); if (digitsAfterDecimal < 1) - snprintf(format, 80, "%%.0f"); + SNPRINTF(format, 80, "%%.0f"); else - snprintf(format, 80, "%%.%df", digitsAfterDecimal); - snprintf(buf, len, format, val); + SNPRINTF(format, 80, "%%.%df", digitsAfterDecimal); + SNPRINTF(buf, len, format, val); return buf; } @@ -160,7 +160,7 @@ static int decomp(unsigned char *srcBuf, unsigned char **jpegBuf, unsigned char *dstPtr, *dstPtr2, *yuvBuf = NULL; if (jpegQual > 0) { - snprintf(qualStr, 13, "_Q%d", jpegQual); + SNPRINTF(qualStr, 13, "_Q%d", jpegQual); qualStr[12] = 0; } @@ -262,20 +262,20 @@ static int decomp(unsigned char *srcBuf, unsigned char **jpegBuf, if (!doWrite) goto bailout; if (sf.num != 1 || sf.denom != 1) - snprintf(sizeStr, 24, "%d_%d", sf.num, sf.denom); + SNPRINTF(sizeStr, 24, "%d_%d", sf.num, sf.denom); else if (tilew != w || tileh != h) - snprintf(sizeStr, 24, "%dx%d", tilew, tileh); - else snprintf(sizeStr, 24, "full"); + SNPRINTF(sizeStr, 24, "%dx%d", tilew, tileh); + else SNPRINTF(sizeStr, 24, "full"); if (decompOnly) - snprintf(tempStr, 1024, "%s_%s.%s", fileName, sizeStr, ext); + SNPRINTF(tempStr, 1024, "%s_%s.%s", fileName, sizeStr, ext); else - snprintf(tempStr, 1024, "%s_%s%s_%s.%s", fileName, subName[subsamp], + SNPRINTF(tempStr, 1024, "%s_%s%s_%s.%s", fileName, subName[subsamp], qualStr, sizeStr, ext); if (tjSaveImage(tempStr, dstBuf, scaledw, 0, scaledh, pf, flags) == -1) THROW_TJG("saving bitmap"); ptr = strrchr(tempStr, '.'); - snprintf(ptr, 1024 - (ptr - tempStr), "-err.%s", ext); + SNPRINTF(ptr, 1024 - (ptr - tempStr), "-err.%s", ext); if (srcBuf && sf.num == 1 && sf.denom == 1) { if (!quiet) printf("Compression error written to %s.\n", tempStr); if (subsamp == TJ_GRAYSCALE) { @@ -478,7 +478,7 @@ static int fullTest(unsigned char *srcBuf, int w, int h, int subsamp, (double)totalJpegSize * 8. / 1000000. * (double)iter / elapsed); } if (tilew == w && tileh == h && doWrite) { - snprintf(tempStr, 1024, "%s_%s_Q%d.jpg", fileName, subName[subsamp], + SNPRINTF(tempStr, 1024, "%s_%s_Q%d.jpg", fileName, subName[subsamp], jpegQual); if ((file = fopen(tempStr, "wb")) == NULL) THROW_UNIX("opening reference image"); diff --git a/tjunittest.c b/tjunittest.c index bda65f95..b3f03113 100644 --- a/tjunittest.c +++ b/tjunittest.c @@ -409,7 +409,7 @@ static void compTest(tjhandle handle, unsigned char **dstBuf, jpegQual, flags)); } - snprintf(tempStr, 1024, "%s_enc_%s_%s_%s_Q%d.jpg", basename, pfStr, buStr, + SNPRINTF(tempStr, 1024, "%s_enc_%s_%s_%s_Q%d.jpg", basename, pfStr, buStr, subName[subsamp], jpegQual); writeJPEG(*dstBuf, *dstSize, tempStr); printf("Done.\n Result in %s\n", tempStr); @@ -782,7 +782,7 @@ static int doBmpTest(const char *ext, int width, int align, int height, int pf, THROW("Could not allocate memory"); initBitmap(buf, width, pitch, height, pf, flags); - snprintf(filename, 80, "test_bmp_%s_%d_%s.%s", pixFormatStr[pf], align, + SNPRINTF(filename, 80, "test_bmp_%s_%d_%s.%s", pixFormatStr[pf], align, (flags & TJFLAG_BOTTOMUP) ? "bu" : "td", ext); TRY_TJ(tjSaveImage(filename, buf, width, pitch, height, pf, flags)); md5sum = MD5File(filename, md5buf); diff --git a/tjutil.h b/tjutil.h index fc8a17a7..9f4d0892 100644 --- a/tjutil.h +++ b/tjutil.h @@ -1,5 +1,5 @@ /* - * Copyright (C)2011 D. R. Commander. All Rights Reserved. + * Copyright (C)2011, 2022 D. R. Commander. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: @@ -31,6 +31,13 @@ #define strncasecmp strnicmp #endif +#ifdef _MSC_VER +#define SNPRINTF(str, n, format, ...) \ + _snprintf_s(str, n, _TRUNCATE, format, ##__VA_ARGS__) +#else +#define SNPRINTF snprintf +#endif + #ifndef min #define min(a, b) ((a) < (b) ? (a) : (b)) #endif diff --git a/turbojpeg.c b/turbojpeg.c index 1a37e8cf..32394cca 100644 --- a/turbojpeg.c +++ b/turbojpeg.c @@ -126,9 +126,9 @@ static void my_progress_monitor(j_common_ptr dinfo) int scan_no = ((j_decompress_ptr)dinfo)->input_scan_number; if (scan_no > 500) { - snprintf(myprog->this->errStr, JMSG_LENGTH_MAX, + SNPRINTF(myprog->this->errStr, JMSG_LENGTH_MAX, "Progressive JPEG image has more than 500 scans"); - snprintf(errStr, JMSG_LENGTH_MAX, + SNPRINTF(errStr, JMSG_LENGTH_MAX, "Progressive JPEG image has more than 500 scans"); myprog->this->isInstanceError = TRUE; myerr->warning = FALSE; @@ -191,24 +191,24 @@ static int cs2pf[JPEG_NUMCS] = { }; #define THROWG(m) { \ - snprintf(errStr, JMSG_LENGTH_MAX, "%s", m); \ + SNPRINTF(errStr, JMSG_LENGTH_MAX, "%s", m); \ retval = -1; goto bailout; \ } #ifdef _MSC_VER #define THROW_UNIX(m) { \ char strerrorBuf[80] = { 0 }; \ strerror_s(strerrorBuf, 80, errno); \ - snprintf(errStr, JMSG_LENGTH_MAX, "%s\n%s", m, strerrorBuf); \ + SNPRINTF(errStr, JMSG_LENGTH_MAX, "%s\n%s", m, strerrorBuf); \ retval = -1; goto bailout; \ } #else #define THROW_UNIX(m) { \ - snprintf(errStr, JMSG_LENGTH_MAX, "%s\n%s", m, strerror(errno)); \ + SNPRINTF(errStr, JMSG_LENGTH_MAX, "%s\n%s", m, strerror(errno)); \ retval = -1; goto bailout; \ } #endif #define THROW(m) { \ - snprintf(this->errStr, JMSG_LENGTH_MAX, "%s", m); \ + SNPRINTF(this->errStr, JMSG_LENGTH_MAX, "%s", m); \ this->isInstanceError = TRUE; THROWG(m) \ } @@ -223,7 +223,7 @@ static int cs2pf[JPEG_NUMCS] = { j_decompress_ptr dinfo = NULL; \ \ if (!this) { \ - snprintf(errStr, JMSG_LENGTH_MAX, "Invalid handle"); \ + SNPRINTF(errStr, JMSG_LENGTH_MAX, "Invalid handle"); \ return -1; \ } \ cinfo = &this->cinfo; dinfo = &this->dinfo; \ @@ -235,7 +235,7 @@ static int cs2pf[JPEG_NUMCS] = { j_compress_ptr cinfo = NULL; \ \ if (!this) { \ - snprintf(errStr, JMSG_LENGTH_MAX, "Invalid handle"); \ + SNPRINTF(errStr, JMSG_LENGTH_MAX, "Invalid handle"); \ return -1; \ } \ cinfo = &this->cinfo; \ @@ -247,7 +247,7 @@ static int cs2pf[JPEG_NUMCS] = { j_decompress_ptr dinfo = NULL; \ \ if (!this) { \ - snprintf(errStr, JMSG_LENGTH_MAX, "Invalid handle"); \ + SNPRINTF(errStr, JMSG_LENGTH_MAX, "Invalid handle"); \ return -1; \ } \ dinfo = &this->dinfo; \ @@ -519,12 +519,12 @@ DLLEXPORT tjhandle tjInitCompress(void) tjinstance *this = NULL; if ((this = (tjinstance *)malloc(sizeof(tjinstance))) == NULL) { - snprintf(errStr, JMSG_LENGTH_MAX, + SNPRINTF(errStr, JMSG_LENGTH_MAX, "tjInitCompress(): Memory allocation failure"); return NULL; } memset(this, 0, sizeof(tjinstance)); - snprintf(this->errStr, JMSG_LENGTH_MAX, "No error"); + SNPRINTF(this->errStr, JMSG_LENGTH_MAX, "No error"); return _tjInitCompress(this); } @@ -1193,12 +1193,12 @@ DLLEXPORT tjhandle tjInitDecompress(void) tjinstance *this; if ((this = (tjinstance *)malloc(sizeof(tjinstance))) == NULL) { - snprintf(errStr, JMSG_LENGTH_MAX, + SNPRINTF(errStr, JMSG_LENGTH_MAX, "tjInitDecompress(): Memory allocation failure"); return NULL; } memset(this, 0, sizeof(tjinstance)); - snprintf(this->errStr, JMSG_LENGTH_MAX, "No error"); + SNPRINTF(this->errStr, JMSG_LENGTH_MAX, "No error"); return _tjInitDecompress(this); } @@ -1277,7 +1277,7 @@ DLLEXPORT int tjDecompressHeader(tjhandle handle, unsigned char *jpegBuf, DLLEXPORT tjscalingfactor *tjGetScalingFactors(int *numscalingfactors) { if (numscalingfactors == NULL) { - snprintf(errStr, JMSG_LENGTH_MAX, + SNPRINTF(errStr, JMSG_LENGTH_MAX, "tjGetScalingFactors(): Invalid argument"); return NULL; } @@ -1884,12 +1884,12 @@ DLLEXPORT tjhandle tjInitTransform(void) tjhandle handle = NULL; if ((this = (tjinstance *)malloc(sizeof(tjinstance))) == NULL) { - snprintf(errStr, JMSG_LENGTH_MAX, + SNPRINTF(errStr, JMSG_LENGTH_MAX, "tjInitTransform(): Memory allocation failure"); return NULL; } memset(this, 0, sizeof(tjinstance)); - snprintf(this->errStr, JMSG_LENGTH_MAX, "No error"); + SNPRINTF(this->errStr, JMSG_LENGTH_MAX, "No error"); handle = _tjInitCompress(this); if (!handle) return NULL; handle = _tjInitDecompress(this); @@ -1980,7 +1980,7 @@ DLLEXPORT int tjTransform(tjhandle handle, const unsigned char *jpegBuf, if (xinfo[i].crop) { if ((t[i].r.x % tjMCUWidth[jpegSubsamp]) != 0 || (t[i].r.y % tjMCUHeight[jpegSubsamp]) != 0) { - snprintf(this->errStr, JMSG_LENGTH_MAX, + SNPRINTF(this->errStr, JMSG_LENGTH_MAX, "To crop this JPEG image, x must be a multiple of %d\n" "and y must be a multiple of %d.\n", tjMCUWidth[jpegSubsamp], tjMCUHeight[jpegSubsamp]); From 30cba2a2f870ff13ac8e1f3670fc6babada2a3cf Mon Sep 17 00:00:00 2001 From: DRC Date: Fri, 11 Mar 2022 11:49:34 -0600 Subject: [PATCH 08/24] Build/Win: Fix CMake warning when WITH_TURBOJPEG=0 When 12-bit-per-component JPEG support is enabled (WITH_12BIT=1) or the TurboJPEG API library and associated test programs are disabled (WITH_TURBOJPEG=0), the Windows installer target should not depend on the turbojpeg, turbojpeg-static, and tjbench targets. --- cmakescripts/BuildPackages.cmake | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/cmakescripts/BuildPackages.cmake b/cmakescripts/BuildPackages.cmake index cfbb2c8a..40744588 100644 --- a/cmakescripts/BuildPackages.cmake +++ b/cmakescripts/BuildPackages.cmake @@ -109,10 +109,13 @@ configure_file(win/${INST_ID}/projectTargets-release.cmake.in if(WITH_JAVA) set(JAVA_DEPEND turbojpeg-java) endif() +if(WITH_TURBOJPEG) + set(TURBOJPEG_DEPEND turbojpeg turbojpeg-static tjbench) +endif() add_custom_target(installer makensis -nocd ${INST_DEFS} installer.nsi - DEPENDS jpeg jpeg-static turbojpeg turbojpeg-static rdjpgcom wrjpgcom - cjpeg djpeg jpegtran tjbench ${JAVA_DEPEND} + DEPENDS jpeg jpeg-static rdjpgcom wrjpgcom cjpeg djpeg jpegtran + ${JAVA_DEPEND} ${TURBOJPEG_DEPEND} SOURCES installer.nsi) endif() # WIN32 From 2ee7264d40910f2529690de327988ce0c2276812 Mon Sep 17 00:00:00 2001 From: DRC Date: Fri, 11 Mar 2022 17:28:36 -0600 Subject: [PATCH 09/24] Build: Don't set DEFAULT_FLOATTEST for x86 MSVC Newer versions of the 32-bit x86 Visual Studio compiler produce results compatible with FLOATTEST=no-fp-contract, so we can no longer intelligently set a default FLOATTEST value for that platform. --- CMakeLists.txt | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index a977b99b..6617ee8b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -909,10 +909,8 @@ if(CPU_TYPE STREQUAL "x86_64" OR CPU_TYPE STREQUAL "i386") set(DEFAULT_FLOATTEST sse) elseif(CPU_TYPE STREQUAL "x86_64") set(DEFAULT_FLOATTEST no-fp-contract) - elseif(CPU_TYPE STREQUAL "i386" AND MSVC) - set(DEFAULT_FLOATTEST msvc) # else we can't really set an intelligent default for i386. The appropriate - # value could be 387, no-fp-contract, or fp-contract, depending on the + # value could be no-fp-contract, fp-contract, 387, or msvc, depending on the # compiler and compiler options. We leave it to the user to set FLOATTEST # manually. endif() From df3c3dcb9b0b24d78f9e58e28c8b509a49967ba8 Mon Sep 17 00:00:00 2001 From: DRC Date: Thu, 31 Mar 2022 10:22:06 -0500 Subject: [PATCH 10/24] BUILDING.md: Generify PowerTools repo advice This advice applies to CentOS Stream as well as to popular CentOS 8 replacements, such as Rocky Linux and AlmaLinux. --- BUILDING.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/BUILDING.md b/BUILDING.md index 43eb5002..2ce65d61 100644 --- a/BUILDING.md +++ b/BUILDING.md @@ -26,8 +26,8 @@ Build Requirements slashes rather than backslashes in the path (for example, **c:/nasm/nasm.exe**). * NASM and Yasm are located in the CRB (Code Ready Builder) repository on - Red Hat Enterprise Linux 8 and in the PowerTools repository on CentOS 8, - which is not enabled by default. + Red Hat Enterprise Linux 8 and in the PowerTools repository on RHEL + derivatives, which is not enabled by default. ### Un*x Platforms (including Linux, Mac, FreeBSD, Solaris, and Cygwin) From 5c8cac97c0c130f287e67d9dafc3e4928110f478 Mon Sep 17 00:00:00 2001 From: DRC Date: Wed, 6 Apr 2022 10:51:58 -0500 Subject: [PATCH 11/24] CI: Un-integrate CIFuzz Referring to the conversation in https://github.com/google/oss-fuzz/issues/7479 and #559, there was a misunderstanding regarding how CIFuzz works. It cannot be used to fuzz arbitrary PRs or code branches, and it has a 90-day delay in downloading corpora from OSS-Fuzz. That makes it unsuitable for libjpeg-turbo. --- .github/workflows/cifuzz.yml | 35 ----------------------------------- 1 file changed, 35 deletions(-) delete mode 100644 .github/workflows/cifuzz.yml diff --git a/.github/workflows/cifuzz.yml b/.github/workflows/cifuzz.yml deleted file mode 100644 index 3b3964fb..00000000 --- a/.github/workflows/cifuzz.yml +++ /dev/null @@ -1,35 +0,0 @@ -name: CIFuzz - -on: - push: - branches: - - '**' - tags-ignore: - - '**' - pull_request: - workflow_dispatch: - -jobs: - Fuzzing: - runs-on: ubuntu-latest - steps: - - name: Build Fuzzers - id: build - uses: google/oss-fuzz/infra/cifuzz/actions/build_fuzzers@master - with: - oss-fuzz-project-name: 'libjpeg-turbo' - dry-run: false - language: c - - name: Run Fuzzers - uses: google/oss-fuzz/infra/cifuzz/actions/run_fuzzers@master - with: - oss-fuzz-project-name: 'libjpeg-turbo' - fuzz-seconds: 600 - language: c - dry-run: false - - name: Upload Crash - uses: actions/upload-artifact@v1 - if: failure() && steps.build.outcome == 'success' - with: - name: artifacts - path: ./out/artifacts From 67cb059046cac6b43da1779547ca725d7677899c Mon Sep 17 00:00:00 2001 From: DRC Date: Wed, 6 Apr 2022 10:50:33 -0500 Subject: [PATCH 12/24] OSS-Fuzz: Allow fuzzer suffix to be specified This facilitates fuzzing multiple branches of the code. --- fuzz/CMakeLists.txt | 20 ++++++++++++-------- fuzz/build.sh | 20 +++++++++++++------- 2 files changed, 25 insertions(+), 15 deletions(-) diff --git a/fuzz/CMakeLists.txt b/fuzz/CMakeLists.txt index dcd19c3a..9f044c67 100644 --- a/fuzz/CMakeLists.txt +++ b/fuzz/CMakeLists.txt @@ -25,16 +25,20 @@ set(EFFECTIVE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${CMAKE_CXX_FLAGS_${CMAKE_BUILD_TYPE_UC}}") message(STATUS "C++ Compiler flags = ${EFFECTIVE_CXX_FLAGS}") -add_executable(cjpeg_fuzzer cjpeg.cc ../cdjpeg.c ../rdbmp.c ../rdgif.c - ../rdppm.c ../rdswitch.c ../rdtarga.c) -set_property(TARGET cjpeg_fuzzer PROPERTY COMPILE_FLAGS ${COMPILE_FLAGS}) -target_link_libraries(cjpeg_fuzzer ${FUZZ_LIBRARY} jpeg-static) -install(TARGETS cjpeg_fuzzer RUNTIME DESTINATION ${FUZZ_BINDIR}) +add_executable(cjpeg_fuzzer${FUZZER_SUFFIX} cjpeg.cc ../cdjpeg.c ../rdbmp.c + ../rdgif.c ../rdppm.c ../rdswitch.c ../rdtarga.c) +set_property(TARGET cjpeg_fuzzer${FUZZER_SUFFIX} PROPERTY COMPILE_FLAGS + ${COMPILE_FLAGS}) +target_link_libraries(cjpeg_fuzzer${FUZZER_SUFFIX} ${FUZZ_LIBRARY} jpeg-static) +install(TARGETS cjpeg_fuzzer${FUZZER_SUFFIX} RUNTIME DESTINATION + ${FUZZ_BINDIR}) macro(add_fuzz_target target source_file) - add_executable(${target}_fuzzer ${source_file}) - target_link_libraries(${target}_fuzzer ${FUZZ_LIBRARY} turbojpeg-static) - install(TARGETS ${target}_fuzzer RUNTIME DESTINATION ${FUZZ_BINDIR}) + add_executable(${target}_fuzzer${FUZZER_SUFFIX} ${source_file}) + target_link_libraries(${target}_fuzzer${FUZZER_SUFFIX} ${FUZZ_LIBRARY} + turbojpeg-static) + install(TARGETS ${target}_fuzzer${FUZZER_SUFFIX} RUNTIME DESTINATION + ${FUZZ_BINDIR}) endmacro() add_fuzz_target(compress compress.cc) diff --git a/fuzz/build.sh b/fuzz/build.sh index 882ce7dc..c769f58c 100644 --- a/fuzz/build.sh +++ b/fuzz/build.sh @@ -3,16 +3,22 @@ set -u set -e +FUZZER_SUFFIX= +if [ $# -ge 1 ]; then + FUZZER_SUFFIX="$1" +fi + cmake . -DCMAKE_BUILD_TYPE=RelWithDebInfo -DENABLE_STATIC=1 -DENABLE_SHARED=0 \ -DCMAKE_C_FLAGS_RELWITHDEBINFO="-g -DNDEBUG" \ -DCMAKE_CXX_FLAGS_RELWITHDEBINFO="-g -DNDEBUG" -DCMAKE_INSTALL_PREFIX=$WORK \ - -DWITH_FUZZ=1 -DFUZZ_BINDIR=$OUT -DFUZZ_LIBRARY=$LIB_FUZZING_ENGINE + -DWITH_FUZZ=1 -DFUZZ_BINDIR=$OUT -DFUZZ_LIBRARY=$LIB_FUZZING_ENGINE \ + -DFUZZER_SUFFIX="$FUZZER_SUFFIX" make "-j$(nproc)" "--load-average=$(nproc)" make install -cp $SRC/compress_fuzzer_seed_corpus.zip $OUT/cjpeg_fuzzer_seed_corpus.zip -cp $SRC/compress_fuzzer_seed_corpus.zip $OUT/compress_fuzzer_seed_corpus.zip -cp $SRC/compress_fuzzer_seed_corpus.zip $OUT/compress_yuv_fuzzer_seed_corpus.zip -cp $SRC/decompress_fuzzer_seed_corpus.zip $OUT/libjpeg_turbo_fuzzer_seed_corpus.zip -cp $SRC/decompress_fuzzer_seed_corpus.zip $OUT/decompress_yuv_fuzzer_seed_corpus.zip -cp $SRC/decompress_fuzzer_seed_corpus.zip $OUT/transform_fuzzer_seed_corpus.zip +cp $SRC/compress_fuzzer_seed_corpus.zip $OUT/cjpeg_fuzzer${FUZZER_SUFFIX}_seed_corpus.zip +cp $SRC/compress_fuzzer_seed_corpus.zip $OUT/compress_fuzzer${FUZZER_SUFFIX}_seed_corpus.zip +cp $SRC/compress_fuzzer_seed_corpus.zip $OUT/compress_yuv_fuzzer${FUZZER_SUFFIX}_seed_corpus.zip +cp $SRC/decompress_fuzzer_seed_corpus.zip $OUT/libjpeg_turbo_fuzzer${FUZZER_SUFFIX}_seed_corpus.zip +cp $SRC/decompress_fuzzer_seed_corpus.zip $OUT/decompress_yuv_fuzzer${FUZZER_SUFFIX}_seed_corpus.zip +cp $SRC/decompress_fuzzer_seed_corpus.zip $OUT/transform_fuzzer${FUZZER_SUFFIX}_seed_corpus.zip From dfc63d42ee3d1ae8eacb921e89e64ac57861dff6 Mon Sep 17 00:00:00 2001 From: Alex Richardson Date: Mon, 28 Mar 2022 22:30:54 +0000 Subject: [PATCH 13/24] Fix non-SIMD alignment if void* bigger than double When building without the SIMD extensions, memory allocations are currently aligned to sizeof(double). However, this may be insufficient on architectures such as Arm Morello or 64-bit CHERI-RISC-V where pointers require 16-byte rather than 8-byte alignment. This patch causes memory allocations to be aligned to MAX(sizeof(void *), sizeof(double)) when building without the SIMD extensions. (NOTE: With C11 we could instead use alignof(max_align_t), but C89 compatibility is still necessary in libjpeg-turbo.) Closes #587 --- jmemmgr.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/jmemmgr.c b/jmemmgr.c index 8f5a4ab1..a40446f6 100644 --- a/jmemmgr.c +++ b/jmemmgr.c @@ -68,10 +68,13 @@ round_up_pow2(size_t a, size_t b) * There isn't any really portable way to determine the worst-case alignment * requirement. This module assumes that the alignment requirement is * multiples of ALIGN_SIZE. - * By default, we define ALIGN_SIZE as sizeof(double). This is necessary on - * some workstations (where doubles really do need 8-byte alignment) and will - * work fine on nearly everything. If your machine has lesser alignment needs, - * you can save a few bytes by making ALIGN_SIZE smaller. + * By default, we define ALIGN_SIZE as the maximum of sizeof(double) and + * sizeof(void *). This is necessary on some workstations (where doubles + * really do need 8-byte alignment) and will work fine on nearly everything. + * We use the maximum of sizeof(double) and sizeof(void *) since sizeof(double) + * may be insufficient, for example, on CHERI-enabled platforms with 16-byte + * pointers and a 16-byte alignment requirement. If your machine has lesser + * alignment needs, you can save a few bytes by making ALIGN_SIZE smaller. * The only place I know of where this will NOT work is certain Macintosh * 680x0 compilers that define double as a 10-byte IEEE extended float. * Doing 10-byte alignment is counterproductive because longwords won't be @@ -81,7 +84,7 @@ round_up_pow2(size_t a, size_t b) #ifndef ALIGN_SIZE /* so can override from jconfig.h */ #ifndef WITH_SIMD -#define ALIGN_SIZE sizeof(double) +#define ALIGN_SIZE MAX(sizeof(void *), sizeof(double)) #else #define ALIGN_SIZE 32 /* Most of the SIMD instructions we support require 16-byte (128-bit) alignment, but AVX2 requires From d0e7c4548a908166b6c4daba549ee86cabe3efba Mon Sep 17 00:00:00 2001 From: DRC Date: Mon, 18 Apr 2022 11:34:07 -0500 Subject: [PATCH 14/24] Don't install libturbojpeg.pc if WITH_TURBOJPEG=0 Fixes #593 --- CMakeLists.txt | 5 ++++- cmakescripts/BuildPackages.cmake | 4 +++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 6617ee8b..cca29663 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1501,8 +1501,11 @@ if(UNIX OR MINGW) DESTINATION ${CMAKE_INSTALL_MANDIR}/man1) endif() install(FILES ${CMAKE_CURRENT_BINARY_DIR}/pkgscripts/libjpeg.pc - ${CMAKE_CURRENT_BINARY_DIR}/pkgscripts/libturbojpeg.pc DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig) +if(WITH_TURBOJPEG) + install(FILES ${CMAKE_CURRENT_BINARY_DIR}/pkgscripts/libturbojpeg.pc + DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig) +endif() install(FILES ${CMAKE_CURRENT_BINARY_DIR}/pkgscripts/${CMAKE_PROJECT_NAME}Config.cmake ${CMAKE_CURRENT_BINARY_DIR}/pkgscripts/${CMAKE_PROJECT_NAME}ConfigVersion.cmake diff --git a/cmakescripts/BuildPackages.cmake b/cmakescripts/BuildPackages.cmake index 40744588..7d6fa2c6 100644 --- a/cmakescripts/BuildPackages.cmake +++ b/cmakescripts/BuildPackages.cmake @@ -162,7 +162,9 @@ add_custom_target(tarball pkgscripts/maketarball configure_file(release/libjpeg.pc.in pkgscripts/libjpeg.pc @ONLY) -configure_file(release/libturbojpeg.pc.in pkgscripts/libturbojpeg.pc @ONLY) +if(WITH_TURBOJPEG) + configure_file(release/libturbojpeg.pc.in pkgscripts/libturbojpeg.pc @ONLY) +endif() include(CMakePackageConfigHelpers) write_basic_package_version_file( From 9171fd4bdef0f3aecba61413b858b1766bbad8d5 Mon Sep 17 00:00:00 2001 From: DRC Date: Tue, 26 Apr 2022 10:42:35 -0500 Subject: [PATCH 15/24] OSS-Fuzz: '.' --> '_' in fuzzer suffix Referring to https://github.com/google/oss-fuzz/issues/7575, if the fuzzer suffix contains periods, it can cause ClusterFuzz to misinterpret the file extension of the fuzzer executables and thus misidentify them. --- fuzz/build.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/fuzz/build.sh b/fuzz/build.sh index c769f58c..70330224 100644 --- a/fuzz/build.sh +++ b/fuzz/build.sh @@ -6,6 +6,7 @@ set -e FUZZER_SUFFIX= if [ $# -ge 1 ]; then FUZZER_SUFFIX="$1" + FUZZER_SUFFIX="`echo $1 | sed 's/\./_/g'`" fi cmake . -DCMAKE_BUILD_TYPE=RelWithDebInfo -DENABLE_STATIC=1 -DENABLE_SHARED=0 \ From 290ddbf71a912644e16f7a21329005e16df4403f Mon Sep 17 00:00:00 2001 From: modbw Date: Fri, 22 Apr 2022 08:30:21 +0200 Subject: [PATCH 16/24] MinGW: Fix str*casecmp() macro redef. warning MinGW defines strcasecmp() and strncasecmp() as macros in string.h if __CRT__NO_INLINE is defined, which will be the case when including any of the Win32 API headers. Closes #594 --- tjutil.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tjutil.h b/tjutil.h index 9f4d0892..10272e98 100644 --- a/tjutil.h +++ b/tjutil.h @@ -27,9 +27,13 @@ */ #ifdef _WIN32 +#ifndef strcasecmp #define strcasecmp stricmp +#endif +#ifndef strncasecmp #define strncasecmp strnicmp #endif +#endif #ifdef _MSC_VER #define SNPRINTF(str, n, format, ...) \ From fac8381441f630910f7814f389b2cd07fbf10771 Mon Sep 17 00:00:00 2001 From: Jiaxun Yang Date: Sat, 14 May 2022 14:34:43 +0100 Subject: [PATCH 17/24] Build: Don't enable Loongson MMI with MIPS R6+ MIPS R6 removed some instructions, so Loongson MMI cannot be built with MIPS R6+ toolchains. Closes #598 --- simd/CMakeLists.txt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/simd/CMakeLists.txt b/simd/CMakeLists.txt index 8521e42b..60249001 100644 --- a/simd/CMakeLists.txt +++ b/simd/CMakeLists.txt @@ -449,6 +449,9 @@ elseif(CPU_TYPE STREQUAL "loongson" OR CPU_TYPE MATCHES "^mips64") set(CMAKE_REQUIRED_FLAGS -Wa,-mloongson-mmi,-mloongson-ext) check_c_source_compiles(" + #if !(defined(__mips__) && __mips_isa_rev < 6) + #error Loongson MMI can't work with MIPS Release 6+ + #endif int main(void) { int c = 0, a = 0, b = 0; asm ( From a405519e961aeee3096f7bff45be6330dfa054b8 Mon Sep 17 00:00:00 2001 From: DRC Date: Fri, 27 May 2022 11:59:56 -0500 Subject: [PATCH 18/24] Fix build if UPSAMPLE_MERGING_SUPPORTED undefined Although it is uncommon, some downstream implementations undefine one or more of the *_SUPPORTED macros in jmorecfg.h in order to reduce the size of the library. In the interest of maintaining backward compatibility with libjpeg, this is still a supported use case. Regression introduced by 9120a247436e84c0b4eea828cb11e8f665fcde30 Based on: https://github.com/fhanau/libjpeg-turbo/commit/74c4d032f0448edb0c8898b6e096123ae1aa093f Closes #601 --- jdapistd.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/jdapistd.c b/jdapistd.c index 8827d8ab..f9908a7a 100644 --- a/jdapistd.c +++ b/jdapistd.c @@ -159,7 +159,9 @@ jpeg_crop_scanline(j_decompress_ptr cinfo, JDIMENSION *xoffset, JDIMENSION input_xoffset; boolean reinit_upsampler = FALSE; jpeg_component_info *compptr; +#ifdef UPSAMPLE_MERGING_SUPPORTED my_master_ptr master = (my_master_ptr)cinfo->master; +#endif if (cinfo->global_state != DSTATE_SCANNING || cinfo->output_scanline != 0) ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); @@ -209,11 +211,13 @@ jpeg_crop_scanline(j_decompress_ptr cinfo, JDIMENSION *xoffset, */ *width = *width + input_xoffset - *xoffset; cinfo->output_width = *width; +#ifdef UPSAMPLE_MERGING_SUPPORTED if (master->using_merged_upsample && cinfo->max_v_samp_factor == 2) { my_merged_upsample_ptr upsample = (my_merged_upsample_ptr)cinfo->upsample; upsample->out_row_width = cinfo->output_width * cinfo->out_color_components; } +#endif /* Set the first and last iMCU columns that we must decompress. These values * will be used in single-scan decompressions. @@ -324,7 +328,9 @@ LOCAL(void) read_and_discard_scanlines(j_decompress_ptr cinfo, JDIMENSION num_lines) { JDIMENSION n; +#ifdef UPSAMPLE_MERGING_SUPPORTED my_master_ptr master = (my_master_ptr)cinfo->master; +#endif JSAMPLE dummy_sample[1] = { 0 }; JSAMPROW dummy_row = dummy_sample; JSAMPARRAY scanlines = NULL; @@ -348,10 +354,12 @@ read_and_discard_scanlines(j_decompress_ptr cinfo, JDIMENSION num_lines) cinfo->cquantize->color_quantize = noop_quantize; } +#ifdef UPSAMPLE_MERGING_SUPPORTED if (master->using_merged_upsample && cinfo->max_v_samp_factor == 2) { my_merged_upsample_ptr upsample = (my_merged_upsample_ptr)cinfo->upsample; scanlines = &upsample->spare_row; } +#endif for (n = 0; n < num_lines; n++) jpeg_read_scanlines(cinfo, scanlines, 1); From ba22c0f76d88f596e157b6c546c599e21ebbaf64 Mon Sep 17 00:00:00 2001 From: DRC Date: Fri, 24 Jun 2022 14:03:03 -0500 Subject: [PATCH 19/24] tjDecompressHeader3(): Accept tables-only streams Inspired by: https://github.com/amyspark/libjpeg-turbo/commit/b3b15cfe74cf07914122e26cf1e408a9a9cf3135 Closes #604 Closes #605 --- ChangeLog.md | 6 +++++ doc/html/annotated.html | 2 +- doc/html/classes.html | 2 +- doc/html/functions.html | 2 +- doc/html/functions_vars.html | 2 +- doc/html/group___turbo_j_p_e_g.html | 18 ++++++------- doc/html/index.html | 2 +- doc/html/modules.html | 2 +- doc/html/structtjregion.html | 2 +- doc/html/structtjscalingfactor.html | 2 +- doc/html/structtjtransform.html | 2 +- doxygen.config | 2 +- java/doc/index-all.html | 3 ++- .../turbojpeg/TJDecompressor.html | 20 +++++++++++---- .../turbojpeg/TJDecompressor.java | 19 ++++++++++---- turbojpeg.c | 8 +++++- turbojpeg.h | 25 +++++++++++++------ 17 files changed, 81 insertions(+), 38 deletions(-) diff --git a/ChangeLog.md b/ChangeLog.md index 62a9b0cf..a00651ac 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -6,6 +6,12 @@ 1. Fixed a regression introduced in 2.1.3 that caused build failures with Visual Studio 2010. +2. The `tjDecompressHeader3()` function in the TurboJPEG C API and the +`TJDecompressor.setSourceImage()` method in the TurboJPEG Java API now accept +"abbreviated table specification" (AKA "tables-only") datastreams, which can be +used to prime the decompressor with quantization and Huffman tables that can be +used when decompressing subsequent "abbreviated image" datastreams. + 2.1.3 ===== diff --git a/doc/html/annotated.html b/doc/html/annotated.html index b7773dd4..c735a5a7 100644 --- a/doc/html/annotated.html +++ b/doc/html/annotated.html @@ -23,7 +23,7 @@
TurboJPEG -  2.1 +  2.1.4
diff --git a/doc/html/classes.html b/doc/html/classes.html index bfcf32a9..42f38f6b 100644 --- a/doc/html/classes.html +++ b/doc/html/classes.html @@ -23,7 +23,7 @@
TurboJPEG -  2.1 +  2.1.4
diff --git a/doc/html/functions.html b/doc/html/functions.html index 055b876f..5de4c6fb 100644 --- a/doc/html/functions.html +++ b/doc/html/functions.html @@ -23,7 +23,7 @@
TurboJPEG -  2.1 +  2.1.4
diff --git a/doc/html/functions_vars.html b/doc/html/functions_vars.html index 540b3e44..2b010f40 100644 --- a/doc/html/functions_vars.html +++ b/doc/html/functions_vars.html @@ -23,7 +23,7 @@
TurboJPEG -  2.1 +  2.1.4
diff --git a/doc/html/group___turbo_j_p_e_g.html b/doc/html/group___turbo_j_p_e_g.html index bf100736..63d47910 100644 --- a/doc/html/group___turbo_j_p_e_g.html +++ b/doc/html/group___turbo_j_p_e_g.html @@ -23,7 +23,7 @@
TurboJPEG -  2.1 +  2.1.4
@@ -273,7 +273,7 @@ Functions  Create a TurboJPEG decompressor instance. More...
  DLLEXPORT int tjDecompressHeader3 (tjhandle handle, const unsigned char *jpegBuf, unsigned long jpegSize, int *width, int *height, int *jpegSubsamp, int *jpegColorspace) - Retrieve information about a JPEG image without decompressing it. More...
+ Retrieve information about a JPEG image without decompressing it, or prime the decompressor with quantization and Huffman tables. More...
  DLLEXPORT tjscalingfactortjGetScalingFactors (int *numscalingfactors)  Returns a list of fractional scaling factors that the JPEG decompressor in this implementation of TurboJPEG supports. More...
@@ -1725,16 +1725,16 @@ If you choose option 1, *jpegSize should be set to the size of your
-

Retrieve information about a JPEG image without decompressing it.

+

Retrieve information about a JPEG image without decompressing it, or prime the decompressor with quantization and Huffman tables.

Parameters
- - - - - - + + + + + +
handlea handle to a TurboJPEG decompressor or transformer instance
jpegBufpointer to a buffer containing a JPEG image
jpegSizesize of the JPEG image (in bytes)
widthpointer to an integer variable that will receive the width (in pixels) of the JPEG image
heightpointer to an integer variable that will receive the height (in pixels) of the JPEG image
jpegSubsamppointer to an integer variable that will receive the level of chrominance subsampling used when the JPEG image was compressed (see Chrominance subsampling options.)
jpegColorspacepointer to an integer variable that will receive one of the JPEG colorspace constants, indicating the colorspace of the JPEG image (see JPEG colorspaces.)
jpegBufpointer to a buffer containing a JPEG image or an "abbreviated table specification" (AKA "tables-only") datastream. Passing a tables-only datastream to this function primes the decompressor with quantization and Huffman tables that can be used when decompressing subsequent "abbreviated image" datastreams. This is useful, for instance, when decompressing video streams in which all frames share the same quantization and Huffman tables.
jpegSizesize of the JPEG image or tables-only datastream (in bytes)
widthpointer to an integer variable that will receive the width (in pixels) of the JPEG image. If jpegBuf points to a tables-only datastream, then width is ignored.
heightpointer to an integer variable that will receive the height (in pixels) of the JPEG image. If jpegBuf points to a tables-only datastream, then height is ignored.
jpegSubsamppointer to an integer variable that will receive the level of chrominance subsampling used when the JPEG image was compressed (see Chrominance subsampling options.) If jpegBuf points to a tables-only datastream, then jpegSubsamp is ignored.
jpegColorspacepointer to an integer variable that will receive one of the JPEG colorspace constants, indicating the colorspace of the JPEG image (see JPEG colorspaces.) If jpegBuf points to a tables-only datastream, then jpegColorspace is ignored.
diff --git a/doc/html/index.html b/doc/html/index.html index 165a589f..a6f272a3 100644 --- a/doc/html/index.html +++ b/doc/html/index.html @@ -23,7 +23,7 @@
TurboJPEG -  2.1 +  2.1.4
diff --git a/doc/html/modules.html b/doc/html/modules.html index b3fa1c06..d48980a4 100644 --- a/doc/html/modules.html +++ b/doc/html/modules.html @@ -23,7 +23,7 @@
TurboJPEG -  2.1 +  2.1.4
diff --git a/doc/html/structtjregion.html b/doc/html/structtjregion.html index daa206aa..72d49d27 100644 --- a/doc/html/structtjregion.html +++ b/doc/html/structtjregion.html @@ -23,7 +23,7 @@
TurboJPEG -  2.1 +  2.1.4
diff --git a/doc/html/structtjscalingfactor.html b/doc/html/structtjscalingfactor.html index 021a36f0..1606a02c 100644 --- a/doc/html/structtjscalingfactor.html +++ b/doc/html/structtjscalingfactor.html @@ -23,7 +23,7 @@
TurboJPEG -  2.1 +  2.1.4
diff --git a/doc/html/structtjtransform.html b/doc/html/structtjtransform.html index 92aa3fa3..ba78980e 100644 --- a/doc/html/structtjtransform.html +++ b/doc/html/structtjtransform.html @@ -23,7 +23,7 @@
TurboJPEG -  2.1 +  2.1.4
diff --git a/doxygen.config b/doxygen.config index 6deb064e..16708b03 100644 --- a/doxygen.config +++ b/doxygen.config @@ -1,5 +1,5 @@ PROJECT_NAME = TurboJPEG -PROJECT_NUMBER = 2.1 +PROJECT_NUMBER = 2.1.4 OUTPUT_DIRECTORY = doc/ USE_WINDOWS_ENCODING = NO OPTIMIZE_OUTPUT_FOR_C = YES diff --git a/java/doc/index-all.html b/java/doc/index-all.html index 3a49818e..5def53ee 100644 --- a/java/doc/index-all.html +++ b/java/doc/index-all.html @@ -792,7 +792,8 @@
setSourceImage(byte[], int) - Method in class org.libjpegturbo.turbojpeg.TJDecompressor
-
Associate the JPEG image of length imageSize bytes stored in +
Associate the JPEG image or "abbreviated table specification" (AKA + "tables-only") datastream of length imageSize bytes stored in jpegImage with this decompressor instance.
setSourceImage(YUVImage) - Method in class org.libjpegturbo.turbojpeg.TJDecompressor
diff --git a/java/doc/org/libjpegturbo/turbojpeg/TJDecompressor.html b/java/doc/org/libjpegturbo/turbojpeg/TJDecompressor.html index b281e327..6666e4e1 100644 --- a/java/doc/org/libjpegturbo/turbojpeg/TJDecompressor.html +++ b/java/doc/org/libjpegturbo/turbojpeg/TJDecompressor.html @@ -418,7 +418,8 @@ implements java.io.Closeable void setSourceImage(byte[] jpegImage, int imageSize) -
Associate the JPEG image of length imageSize bytes stored in +
Associate the JPEG image or "abbreviated table specification" (AKA + "tables-only") datastream of length imageSize bytes stored in jpegImage with this decompressor instance.
@@ -611,10 +612,19 @@ implements java.io.Closeable
public void setSourceImage(byte[] jpegImage,
                   int imageSize)
                     throws TJException
-
Associate the JPEG image of length imageSize bytes stored in - jpegImage with this decompressor instance. This image will - be used as the source image for subsequent decompress operations.
-
Parameters:
jpegImage - JPEG image buffer. This buffer is not modified.
imageSize - size of the JPEG image (in bytes)
+
Associate the JPEG image or "abbreviated table specification" (AKA + "tables-only") datastream of length imageSize bytes stored in + jpegImage with this decompressor instance. If + jpegImage contains a JPEG image, then this image will be used + as the source image for subsequent decompress operations. Passing a + tables-only datastream to this method primes the decompressor with + quantization and Huffman tables that can be used when decompressing + subsequent "abbreviated image" datastreams. This is useful, for instance, + when decompressing video streams in which all frames share the same + quantization and Huffman tables.
+
Parameters:
jpegImage - buffer containing a JPEG image or an "abbreviated table + specification" (AKA "tables-only") datastream. This buffer is not + modified.
imageSize - size of the JPEG image (in bytes)
Throws:
TJException
diff --git a/java/org/libjpegturbo/turbojpeg/TJDecompressor.java b/java/org/libjpegturbo/turbojpeg/TJDecompressor.java index cba9ff03..aba390b1 100644 --- a/java/org/libjpegturbo/turbojpeg/TJDecompressor.java +++ b/java/org/libjpegturbo/turbojpeg/TJDecompressor.java @@ -1,5 +1,5 @@ /* - * Copyright (C)2011-2015, 2018 D. R. Commander. All Rights Reserved. + * Copyright (C)2011-2015, 2018, 2022 D. R. Commander. All Rights Reserved. * Copyright (C)2015 Viktor Szathmáry. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without @@ -89,11 +89,20 @@ public class TJDecompressor implements Closeable { } /** - * Associate the JPEG image of length imageSize bytes stored in - * jpegImage with this decompressor instance. This image will - * be used as the source image for subsequent decompress operations. + * Associate the JPEG image or "abbreviated table specification" (AKA + * "tables-only") datastream of length imageSize bytes stored in + * jpegImage with this decompressor instance. If + * jpegImage contains a JPEG image, then this image will be used + * as the source image for subsequent decompress operations. Passing a + * tables-only datastream to this method primes the decompressor with + * quantization and Huffman tables that can be used when decompressing + * subsequent "abbreviated image" datastreams. This is useful, for instance, + * when decompressing video streams in which all frames share the same + * quantization and Huffman tables. * - * @param jpegImage JPEG image buffer. This buffer is not modified. + * @param jpegImage buffer containing a JPEG image or an "abbreviated table + * specification" (AKA "tables-only") datastream. This buffer is not + * modified. * * @param imageSize size of the JPEG image (in bytes) */ diff --git a/turbojpeg.c b/turbojpeg.c index 32394cca..a1544f24 100644 --- a/turbojpeg.c +++ b/turbojpeg.c @@ -1225,7 +1225,13 @@ DLLEXPORT int tjDecompressHeader3(tjhandle handle, } jpeg_mem_src_tj(dinfo, jpegBuf, jpegSize); - jpeg_read_header(dinfo, TRUE); + + /* jpeg_read_header() calls jpeg_abort() and returns JPEG_HEADER_TABLES_ONLY + if the datastream is a tables-only datastream. Since we aren't using a + suspending data source, the only other value it can return is + JPEG_HEADER_OK. */ + if (jpeg_read_header(dinfo, FALSE) == JPEG_HEADER_TABLES_ONLY) + return 0; *width = dinfo->image_width; *height = dinfo->image_height; diff --git a/turbojpeg.h b/turbojpeg.h index 5b33ad84..02b54ca9 100644 --- a/turbojpeg.h +++ b/turbojpeg.h @@ -1129,27 +1129,38 @@ DLLEXPORT tjhandle tjInitDecompress(void); /** - * Retrieve information about a JPEG image without decompressing it. + * Retrieve information about a JPEG image without decompressing it, or prime + * the decompressor with quantization and Huffman tables. * * @param handle a handle to a TurboJPEG decompressor or transformer instance * - * @param jpegBuf pointer to a buffer containing a JPEG image + * @param jpegBuf pointer to a buffer containing a JPEG image or an + * "abbreviated table specification" (AKA "tables-only") datastream. Passing a + * tables-only datastream to this function primes the decompressor with + * quantization and Huffman tables that can be used when decompressing + * subsequent "abbreviated image" datastreams. This is useful, for instance, + * when decompressing video streams in which all frames share the same + * quantization and Huffman tables. * - * @param jpegSize size of the JPEG image (in bytes) + * @param jpegSize size of the JPEG image or tables-only datastream (in bytes) * * @param width pointer to an integer variable that will receive the width (in - * pixels) of the JPEG image + * pixels) of the JPEG image. If jpegBuf points to a tables-only + * datastream, then width is ignored. * * @param height pointer to an integer variable that will receive the height - * (in pixels) of the JPEG image + * (in pixels) of the JPEG image. If jpegBuf points to a tables-only + * datastream, then height is ignored. * * @param jpegSubsamp pointer to an integer variable that will receive the * level of chrominance subsampling used when the JPEG image was compressed - * (see @ref TJSAMP "Chrominance subsampling options".) + * (see @ref TJSAMP "Chrominance subsampling options".) If jpegBuf + * points to a tables-only datastream, then jpegSubsamp is ignored. * * @param jpegColorspace pointer to an integer variable that will receive one * of the JPEG colorspace constants, indicating the colorspace of the JPEG - * image (see @ref TJCS "JPEG colorspaces".) + * image (see @ref TJCS "JPEG colorspaces".) If jpegBuf + * points to a tables-only datastream, then jpegColorspace is ignored. * * @return 0 if successful, or -1 if an error occurred (see #tjGetErrorStr2() * and #tjGetErrorCode().) From 59337a67b1cf47a74cf1415c7445fed4275a5d5e Mon Sep 17 00:00:00 2001 From: Donovan Watteau Date: Wed, 6 Jul 2022 12:11:50 +0200 Subject: [PATCH 20/24] PowerPC: Detect AltiVec support on OS X libjpeg-turbo's AltiVec SIMD extensions previously assumed that AltiVec instructions were available on all Power Macs that supported OS X 10.4 "Tiger" (the earliest version of OS X that libjpeg-turbo has ever supported), but Tiger can actually run on PowerPC G3 processors, which lack AltiVec instructions. This commit enables run-time detection of AltiVec instructions on OS X/PowerPC systems if AltiVec instructions are not force-enabled at compile time (using -maltivec). This allows the same build of libjpeg-turbo to support G3, G4, and G5 Power Macs. Closes #609 --- ChangeLog.md | 5 +++++ simd/powerpc/jsimd.c | 13 ++++++++++--- 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/ChangeLog.md b/ChangeLog.md index a00651ac..88fbfbd9 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -12,6 +12,11 @@ Visual Studio 2010. used to prime the decompressor with quantization and Huffman tables that can be used when decompressing subsequent "abbreviated image" datastreams. +3. libjpeg-turbo now performs run-time detection of AltiVec instructions on +OS X/PowerPC systems if AltiVec instructions are not enabled at compile time. +This allows both AltiVec-equipped (PowerPC G4 and G5) and non-AltiVec-equipped +(PowerPC G3) CPUs to be supported using the same build of libjpeg-turbo. + 2.1.3 ===== diff --git a/simd/powerpc/jsimd.c b/simd/powerpc/jsimd.c index 3f648ef3..9a452a30 100644 --- a/simd/powerpc/jsimd.c +++ b/simd/powerpc/jsimd.c @@ -29,7 +29,10 @@ #include -#if defined(__OpenBSD__) +#if defined(__APPLE__) +#include +#include +#elif defined(__OpenBSD__) #include #include #include @@ -119,6 +122,10 @@ init_simd(void) int bufsize = 1024; /* an initial guess for the line buffer size limit */ #elif defined(__amigaos4__) uint32 altivec = 0; +#elif defined(__APPLE__) + int mib[2] = { CTL_HW, HW_VECTORUNIT }; + int altivec; + size_t len = sizeof(altivec); #elif defined(__OpenBSD__) int mib[2] = { CTL_MACHDEP, CPU_ALTIVEC }; int altivec; @@ -132,7 +139,7 @@ init_simd(void) simd_support = 0; -#if defined(__ALTIVEC__) || defined(__APPLE__) +#if defined(__ALTIVEC__) simd_support |= JSIMD_ALTIVEC; #elif defined(__linux__) || defined(ANDROID) || defined(__ANDROID__) while (!parse_proc_cpuinfo(bufsize)) { @@ -144,7 +151,7 @@ init_simd(void) IExec->GetCPUInfoTags(GCIT_VectorUnit, &altivec, TAG_DONE); if (altivec == VECTORTYPE_ALTIVEC) simd_support |= JSIMD_ALTIVEC; -#elif defined(__OpenBSD__) +#elif defined(__APPLE__) || defined(__OpenBSD__) if (sysctl(mib, 2, &altivec, &len, NULL, 0) == 0 && altivec != 0) simd_support |= JSIMD_ALTIVEC; #elif defined(__FreeBSD__) From 4dbc293125b417f97e5b1ca9e7260c82ff199a06 Mon Sep 17 00:00:00 2001 From: DRC Date: Sun, 7 Aug 2022 09:24:57 -0500 Subject: [PATCH 21/24] Fix buf image mode decompr err w/ short prog JPEGs Regression introduced by 6d91e950c871103a11bac2f10c63bf998796c719 Because we're now using a 5x5 smoothing window when decompressing progressive JPEG images, we need to ensure that the whole_image virtual array contains at least five rows. Previously that was not always the case unless the progressive JPEG image being decompressed had at least five iMCU rows. Since an iMCU has a height of (8 * the vertical sampling factor), attempting to decompress 4:2:2 and 4:4:4 images <= 32 pixels in height or 4:2:0 images <= 64 pixels in height triggered a JERR_BAD_VIRTUAL_ACCESS error in decompress_smooth_data(), because access_rows exceeded the number of rows in the virtual array. Fixes #613 --- ChangeLog.md | 5 +++++ jdcoefct.c | 13 ++++++++----- 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/ChangeLog.md b/ChangeLog.md index 88fbfbd9..995e0e83 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -17,6 +17,11 @@ OS X/PowerPC systems if AltiVec instructions are not enabled at compile time. This allows both AltiVec-equipped (PowerPC G4 and G5) and non-AltiVec-equipped (PowerPC G3) CPUs to be supported using the same build of libjpeg-turbo. +4. Fixed an error ("Bogus virtual array access") that occurred when attempting +to decompress a progressive JPEG image with a height less than or equal to +(32 * the vertical sampling factor) using buffered image mode. This was a +regression introduced by 2.1 beta1[6(b)]. + 2.1.3 ===== diff --git a/jdcoefct.c b/jdcoefct.c index 15e6cded..75ea526d 100644 --- a/jdcoefct.c +++ b/jdcoefct.c @@ -5,7 +5,7 @@ * Copyright (C) 1994-1997, Thomas G. Lane. * libjpeg-turbo Modifications: * Copyright 2009 Pierre Ossman for Cendio AB - * Copyright (C) 2010, 2015-2016, 2019-2020, D. R. Commander. + * Copyright (C) 2010, 2015-2016, 2019-2020, 2022, D. R. Commander. * Copyright (C) 2015, 2020, Google, Inc. * For conditions of distribution and use, see the accompanying README.ijg * file. @@ -835,18 +835,21 @@ jinit_d_coef_controller(j_decompress_ptr cinfo, boolean need_full_buffer) for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; ci++, compptr++) { + JDIMENSION num_rows = + (JDIMENSION)jround_up((long)compptr->height_in_blocks, + (long)compptr->v_samp_factor); access_rows = compptr->v_samp_factor; #ifdef BLOCK_SMOOTHING_SUPPORTED /* If block smoothing could be used, need a bigger window */ - if (cinfo->progressive_mode) + if (cinfo->progressive_mode) { access_rows *= 5; + num_rows = MAX(num_rows, access_rows); + } #endif coef->whole_image[ci] = (*cinfo->mem->request_virt_barray) ((j_common_ptr)cinfo, JPOOL_IMAGE, TRUE, (JDIMENSION)jround_up((long)compptr->width_in_blocks, - (long)compptr->h_samp_factor), - (JDIMENSION)jround_up((long)compptr->height_in_blocks, - (long)compptr->v_samp_factor), + (long)compptr->h_samp_factor), num_rows, (JDIMENSION)access_rows); } coef->pub.consume_data = consume_data; From 9f8f683e745972720433406cff4b31e95bd6a33e Mon Sep 17 00:00:00 2001 From: DRC Date: Sun, 7 Aug 2022 14:15:03 -0500 Subject: [PATCH 22/24] jdcoefct.c: Fix signed/unsigned mismatch VC++ wrng (introduced by previous commit) --- jdcoefct.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/jdcoefct.c b/jdcoefct.c index 75ea526d..19eb56a4 100644 --- a/jdcoefct.c +++ b/jdcoefct.c @@ -843,7 +843,7 @@ jinit_d_coef_controller(j_decompress_ptr cinfo, boolean need_full_buffer) /* If block smoothing could be used, need a bigger window */ if (cinfo->progressive_mode) { access_rows *= 5; - num_rows = MAX(num_rows, access_rows); + num_rows = MAX(num_rows, (JDIMENSION)access_rows); } #endif coef->whole_image[ci] = (*cinfo->mem->request_virt_barray) From 2e136a7190063322e9f982e7fbc3f4a523f1af4e Mon Sep 17 00:00:00 2001 From: DRC Date: Mon, 8 Aug 2022 14:17:51 -0500 Subject: [PATCH 23/24] Re-fix buf img mode decompr err w/short prog JPEGs This commit reverts 4dbc293125b417f97e5b1ca9e7260c82ff199a06 and 9f8f683e745972720433406cff4b31e95bd6a33e (the previous two commits) and fixes #613 the correct way. The crux of the issue wasn't the size of the whole_image virtual array but rather that, since last_iMCU_row is unsigned, (last_iMCU_row - 1) wrapped around to 0xFFFFFFFF when last_iMCU_row was 0. This caused the interblock smoothing algorithm introduced in 6d91e950c871103a11bac2f10c63bf998796c719 to erroneously try to access the next two iMCU rows, neither of which existed. The first attempt at a fix (4dbc293125b417f97e5b1ca9e7260c82ff199a06) exposed a NULL dereference, detected by OSS-Fuzz, that occurred when attempting to decompress a specially-crafted malformed JPEG image to a YUV buffer using tjDecompressToYUV*() with 1/4 IDCT scaling. Fixes #613 (again) Also fixes https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=49898 --- ChangeLog.md | 7 ++++--- jdcoefct.c | 15 ++++++--------- 2 files changed, 10 insertions(+), 12 deletions(-) diff --git a/ChangeLog.md b/ChangeLog.md index 995e0e83..59ca516c 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -18,9 +18,10 @@ This allows both AltiVec-equipped (PowerPC G4 and G5) and non-AltiVec-equipped (PowerPC G3) CPUs to be supported using the same build of libjpeg-turbo. 4. Fixed an error ("Bogus virtual array access") that occurred when attempting -to decompress a progressive JPEG image with a height less than or equal to -(32 * the vertical sampling factor) using buffered image mode. This was a -regression introduced by 2.1 beta1[6(b)]. +to decompress a progressive JPEG image with a height less than or equal to one +iMCU (8 * the vertical sampling factor) using buffered-image mode with +interblock smoothing enabled. This was a regression introduced by +2.1 beta1[6(b)]. 2.1.3 diff --git a/jdcoefct.c b/jdcoefct.c index 19eb56a4..88e10c08 100644 --- a/jdcoefct.c +++ b/jdcoefct.c @@ -475,7 +475,7 @@ decompress_smooth_data(j_decompress_ptr cinfo, JSAMPIMAGE output_buf) if (!compptr->component_needed) continue; /* Count non-dummy DCT block rows in this iMCU row. */ - if (cinfo->output_iMCU_row < last_iMCU_row - 1) { + if (cinfo->output_iMCU_row + 1 < last_iMCU_row) { block_rows = compptr->v_samp_factor; access_rows = block_rows * 3; /* this and next two iMCU rows */ } else if (cinfo->output_iMCU_row < last_iMCU_row) { @@ -560,7 +560,7 @@ decompress_smooth_data(j_decompress_ptr cinfo, JSAMPIMAGE output_buf) next_block_row = buffer_ptr; if (block_row < block_rows - 2 || - cinfo->output_iMCU_row < last_iMCU_row - 1) + cinfo->output_iMCU_row + 1 < last_iMCU_row) next_next_block_row = buffer[block_row + 2] + cinfo->master->first_MCU_col[ci]; else @@ -835,21 +835,18 @@ jinit_d_coef_controller(j_decompress_ptr cinfo, boolean need_full_buffer) for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; ci++, compptr++) { - JDIMENSION num_rows = - (JDIMENSION)jround_up((long)compptr->height_in_blocks, - (long)compptr->v_samp_factor); access_rows = compptr->v_samp_factor; #ifdef BLOCK_SMOOTHING_SUPPORTED /* If block smoothing could be used, need a bigger window */ - if (cinfo->progressive_mode) { + if (cinfo->progressive_mode) access_rows *= 5; - num_rows = MAX(num_rows, (JDIMENSION)access_rows); - } #endif coef->whole_image[ci] = (*cinfo->mem->request_virt_barray) ((j_common_ptr)cinfo, JPOOL_IMAGE, TRUE, (JDIMENSION)jround_up((long)compptr->width_in_blocks, - (long)compptr->h_samp_factor), num_rows, + (long)compptr->h_samp_factor), + (JDIMENSION)jround_up((long)compptr->height_in_blocks, + (long)compptr->v_samp_factor), (JDIMENSION)access_rows); } coef->pub.consume_data = consume_data; From 8162eddf041e0be26f5c671bb6528723c55fed9d Mon Sep 17 00:00:00 2001 From: DRC Date: Mon, 8 Aug 2022 16:02:34 -0500 Subject: [PATCH 24/24] Fix issues w/ partial img decompr + buf img mode Fixes #611 --- ChangeLog.md | 9 +++++++++ jdapistd.c | 5 +++-- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/ChangeLog.md b/ChangeLog.md index 59ca516c..b0d166ea 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -23,6 +23,15 @@ iMCU (8 * the vertical sampling factor) using buffered-image mode with interblock smoothing enabled. This was a regression introduced by 2.1 beta1[6(b)]. +5. Fixed two issues that prevented partial image decompression from working +properly with buffered-image mode: + + - Attempting to call `jpeg_crop_scanline()` after +`jpeg_start_decompress()` but before `jpeg_start_output()` resulted in an error +("Improper call to JPEG library in state 207".) + - Attempting to use `jpeg_skip_scanlines()` resulted in an error ("Bogus +virtual array access") under certain circumstances. + 2.1.3 ===== diff --git a/jdapistd.c b/jdapistd.c index f9908a7a..02cd0cb9 100644 --- a/jdapistd.c +++ b/jdapistd.c @@ -163,7 +163,8 @@ jpeg_crop_scanline(j_decompress_ptr cinfo, JDIMENSION *xoffset, my_master_ptr master = (my_master_ptr)cinfo->master; #endif - if (cinfo->global_state != DSTATE_SCANNING || cinfo->output_scanline != 0) + if ((cinfo->global_state != DSTATE_SCANNING && + cinfo->global_state != DSTATE_BUFIMAGE) || cinfo->output_scanline != 0) ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); if (!xoffset || !width) @@ -525,7 +526,7 @@ jpeg_skip_scanlines(j_decompress_ptr cinfo, JDIMENSION num_lines) * all of the entropy decoding occurs in jpeg_start_decompress(), assuming * that the input data source is non-suspending. This makes skipping easy. */ - if (cinfo->inputctl->has_multiple_scans) { + if (cinfo->inputctl->has_multiple_scans || cinfo->buffered_image) { if (cinfo->upsample->need_context_rows) { cinfo->output_scanline += lines_to_skip; cinfo->output_iMCU_row += lines_to_skip / lines_per_iMCU_row;