diff --git a/CMakeLists.txt b/CMakeLists.txt index 51f4714b..6596f010 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -5,7 +5,7 @@ if(CMAKE_EXECUTABLE_SUFFIX) endif() project(mozjpeg C) -set(VERSION 4.0.0) +set(VERSION 4.0.1) string(REPLACE "." ";" VERSION_TRIPLET ${VERSION}) list(GET VERSION_TRIPLET 0 VERSION_MAJOR) list(GET VERSION_TRIPLET 1 VERSION_MINOR) @@ -453,6 +453,21 @@ if(NOT INLINE_WORKS) endif() message(STATUS "INLINE = ${INLINE} (FORCE_INLINE = ${FORCE_INLINE})") +if(WITH_TURBOJPEG) + if(MSVC) + set(THREAD_LOCAL "__declspec(thread)") + else() + set(THREAD_LOCAL "__thread") + endif() + check_c_source_compiles("${THREAD_LOCAL} int i; int main(void) { i = 0; return i; }" HAVE_THREAD_LOCAL) + if(HAVE_THREAD_LOCAL) + message(STATUS "THREAD_LOCAL = ${THREAD_LOCAL}") + else() + message(WARNING "Thread-local storage is not available. The TurboJPEG API library's global error handler will not be thread-safe.") + unset(THREAD_LOCAL) + endif() +endif() + if(UNIX AND NOT APPLE) file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/conftest.map "VERS_1 { global: *; };") set(CMAKE_REQUIRED_FLAGS @@ -923,12 +938,18 @@ foreach(libtype ${TEST_LIBTYPES}) set(suffix -static) endif() if(WITH_TURBOJPEG) - add_test(tjunittest-${libtype} tjunittest${suffix}) - add_test(tjunittest-${libtype}-alloc tjunittest${suffix} -alloc) - add_test(tjunittest-${libtype}-yuv tjunittest${suffix} -yuv) - add_test(tjunittest-${libtype}-yuv-alloc tjunittest${suffix} -yuv -alloc) - add_test(tjunittest-${libtype}-yuv-nopad tjunittest${suffix} -yuv -noyuvpad) - add_test(tjunittest-${libtype}-bmp tjunittest${suffix} -bmp) + add_test(tjunittest-${libtype} + ${CMAKE_CROSSCOMPILING_EMULATOR} tjunittest${suffix}) + add_test(tjunittest-${libtype}-alloc + ${CMAKE_CROSSCOMPILING_EMULATOR} tjunittest${suffix} -alloc) + add_test(tjunittest-${libtype}-yuv + ${CMAKE_CROSSCOMPILING_EMULATOR} tjunittest${suffix} -yuv) + add_test(tjunittest-${libtype}-yuv-alloc + ${CMAKE_CROSSCOMPILING_EMULATOR} tjunittest${suffix} -yuv -alloc) + add_test(tjunittest-${libtype}-yuv-nopad + ${CMAKE_CROSSCOMPILING_EMULATOR} tjunittest${suffix} -yuv -noyuvpad) + add_test(tjunittest-${libtype}-bmp + ${CMAKE_CROSSCOMPILING_EMULATOR} tjunittest${suffix} -bmp) set(MD5_PPM_GRAY_TILE 89d3ca21213d9d864b50b4e4e7de4ca6) set(MD5_PPM_420_8x8_TILE 847fceab15c5b7b911cb986cf0f71de3) @@ -953,22 +974,23 @@ foreach(libtype ${TEST_LIBTYPES}) ${CMAKE_COMMAND} -E copy_if_different ${TESTIMAGES}/testorig.ppm testout_tile.ppm) add_test(tjbench-${libtype}-tile - tjbench${suffix} testout_tile.ppm 95 -rgb -quiet -tile -benchtime 0.01 - -warmup 0) + ${CMAKE_CROSSCOMPILING_EMULATOR} tjbench${suffix} testout_tile.ppm 95 + -rgb -quiet -tile -benchtime 0.01 -warmup 0) set_tests_properties(tjbench-${libtype}-tile PROPERTIES DEPENDS tjbench-${libtype}-tile-cp) foreach(tile 8 16 32 64 128) add_test(tjbench-${libtype}-tile-gray-${tile}x${tile}-cmp - ${MD5CMP} ${MD5_PPM_GRAY_TILE} + ${CMAKE_CROSSCOMPILING_EMULATOR} ${MD5CMP} ${MD5_PPM_GRAY_TILE} testout_tile_GRAY_Q95_${tile}x${tile}.ppm) foreach(subsamp 420 422) add_test(tjbench-${libtype}-tile-${subsamp}-${tile}x${tile}-cmp - ${MD5CMP} ${MD5_PPM_${subsamp}_${tile}x${tile}_TILE} + ${CMAKE_CROSSCOMPILING_EMULATOR} ${MD5CMP} + ${MD5_PPM_${subsamp}_${tile}x${tile}_TILE} testout_tile_${subsamp}_Q95_${tile}x${tile}.ppm) endforeach() add_test(tjbench-${libtype}-tile-444-${tile}x${tile}-cmp - ${MD5CMP} ${MD5_PPM_444_TILE} + ${CMAKE_CROSSCOMPILING_EMULATOR} ${MD5CMP} ${MD5_PPM_444_TILE} testout_tile_444_Q95_${tile}x${tile}.ppm) foreach(subsamp gray 420 422 444) set_tests_properties(tjbench-${libtype}-tile-${subsamp}-${tile}x${tile}-cmp @@ -980,19 +1002,22 @@ foreach(libtype ${TEST_LIBTYPES}) ${CMAKE_COMMAND} -E copy_if_different ${TESTIMAGES}/testorig.ppm testout_tilem.ppm) add_test(tjbench-${libtype}-tilem - tjbench${suffix} testout_tilem.ppm 95 -rgb -fastupsample -quiet -tile - -benchtime 0.01 -warmup 0) + ${CMAKE_CROSSCOMPILING_EMULATOR} tjbench${suffix} testout_tilem.ppm 95 + -rgb -fastupsample -quiet -tile -benchtime 0.01 -warmup 0) set_tests_properties(tjbench-${libtype}-tilem PROPERTIES DEPENDS tjbench-${libtype}-tilem-cp) add_test(tjbench-${libtype}-tile-420m-8x8-cmp - ${MD5CMP} ${MD5_PPM_420M_8x8_TILE} testout_tilem_420_Q95_8x8.ppm) + ${CMAKE_CROSSCOMPILING_EMULATOR} ${MD5CMP} ${MD5_PPM_420M_8x8_TILE} + testout_tilem_420_Q95_8x8.ppm) add_test(tjbench-${libtype}-tile-422m-8x8-cmp - ${MD5CMP} ${MD5_PPM_422M_8x8_TILE} testout_tilem_422_Q95_8x8.ppm) + ${CMAKE_CROSSCOMPILING_EMULATOR} ${MD5CMP} ${MD5_PPM_422M_8x8_TILE} + testout_tilem_422_Q95_8x8.ppm) foreach(tile 16 32 64 128) foreach(subsamp 420 422) add_test(tjbench-${libtype}-tile-${subsamp}m-${tile}x${tile}-cmp - ${MD5CMP} ${MD5_PPM_${subsamp}M_TILE} + ${CMAKE_CROSSCOMPILING_EMULATOR} ${MD5CMP} + ${MD5_PPM_${subsamp}M_TILE} testout_tilem_${subsamp}_Q95_${tile}x${tile}.ppm) endforeach() endforeach() @@ -1010,9 +1035,10 @@ foreach(libtype ${TEST_LIBTYPES}) macro(add_bittest PROG NAME ARGS OUTFILE INFILE MD5SUM) add_test(${PROG}-${libtype}-${NAME} - ${PROG}${suffix} ${ARGS} -outfile ${OUTFILE} ${INFILE}) + ${CMAKE_CROSSCOMPILING_EMULATOR} ${PROG}${suffix} ${ARGS} + -outfile ${OUTFILE} ${INFILE}) add_test(${PROG}-${libtype}-${NAME}-cmp - ${MD5CMP} ${MD5SUM} ${OUTFILE}) + ${CMAKE_CROSSCOMPILING_EMULATOR} ${MD5CMP} ${MD5SUM} ${OUTFILE}) set_tests_properties(${PROG}-${libtype}-${NAME}-cmp PROPERTIES DEPENDS ${PROG}-${libtype}-${NAME}) if(${ARGC} GREATER 6) @@ -1033,12 +1059,14 @@ foreach(libtype ${TEST_LIBTYPES}) ${MD5_PPM_RGB_ISLOW} cjpeg-${libtype}-rgb-islow) add_test(djpeg-${libtype}-rgb-islow-icc-cmp - ${MD5CMP} b06a39d730129122e85c1363ed1bbc9e testout_rgb_islow.icc) + ${CMAKE_CROSSCOMPILING_EMULATOR} ${MD5CMP} + b06a39d730129122e85c1363ed1bbc9e testout_rgb_islow.icc) set_tests_properties(djpeg-${libtype}-rgb-islow-icc-cmp PROPERTIES DEPENDS djpeg-${libtype}-rgb-islow) add_bittest(jpegtran icc "-copy;all;-icc;${TESTIMAGES}/test2.icc" - testout_rgb_islow2.jpg testout_rgb_islow.jpg ${MD5_JPEG_RGB_ISLOW2}) + testout_rgb_islow2.jpg testout_rgb_islow.jpg + ${MD5_JPEG_RGB_ISLOW2} cjpeg-${libtype}-rgb-islow) if(NOT WITH_12BIT) # CC: RGB->RGB565 SAMP: fullsize IDCT: islow ENT: huff @@ -1251,7 +1279,7 @@ foreach(libtype ${TEST_LIBTYPES}) # Context rows: Yes Intra-iMCU row: No iMCU row prefetch: No ENT: prog huff add_test(cjpeg-${libtype}-420-islow-prog - cjpeg${suffix} -dct int -prog + ${CMAKE_CROSSCOMPILING_EMULATOR} cjpeg${suffix} -dct int -prog -outfile testout_420_islow_prog.jpg ${TESTIMAGES}/testorig.ppm) add_bittest(djpeg 420-islow-prog-crop62x62_71_71 "-dct;int;-crop;62x62+71+71;-ppm" @@ -1268,7 +1296,7 @@ foreach(libtype ${TEST_LIBTYPES}) # Context rows: No Intra-iMCU row: Yes ENT: huff add_test(cjpeg-${libtype}-444-islow - cjpeg${suffix} -dct int -sample 1x1 + ${CMAKE_CROSSCOMPILING_EMULATOR} cjpeg${suffix} -dct int -sample 1x1 -outfile testout_444_islow.jpg ${TESTIMAGES}/testorig.ppm) add_bittest(djpeg 444-islow-skip1_6 "-dct;int;-skip;1,6;-ppm" testout_444_islow_skip1,6.ppm testout_444_islow.jpg @@ -1276,7 +1304,7 @@ foreach(libtype ${TEST_LIBTYPES}) # Context rows: No Intra-iMCU row: No ENT: prog huff add_test(cjpeg-${libtype}-444-islow-prog - cjpeg${suffix} -dct int -prog -sample 1x1 + ${CMAKE_CROSSCOMPILING_EMULATOR} cjpeg${suffix} -dct int -prog -sample 1x1 -outfile testout_444_islow_prog.jpg ${TESTIMAGES}/testorig.ppm) add_bittest(djpeg 444-islow-prog-crop98x98_13_13 "-dct;int;-crop;98x98+13+13;-ppm" @@ -1286,8 +1314,9 @@ foreach(libtype ${TEST_LIBTYPES}) # Context rows: No Intra-iMCU row: No ENT: arith if(WITH_ARITH_ENC) add_test(cjpeg-${libtype}-444-islow-ari - cjpeg${suffix} -dct int -arithmetic -sample 1x1 - -outfile testout_444_islow_ari.jpg ${TESTIMAGES}/testorig.ppm) + ${CMAKE_CROSSCOMPILING_EMULATOR} cjpeg${suffix} -dct int -arithmetic + -sample 1x1 -outfile testout_444_islow_ari.jpg + ${TESTIMAGES}/testorig.ppm) if(WITH_ARITH_DEC) add_bittest(djpeg 444-islow-ari-crop37x37_0_0 "-dct;int;-crop;37x37+0+0;-ppm" diff --git a/ChangeLog.md b/ChangeLog.md index 4d1219e5..59fb2de9 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -1,3 +1,33 @@ +2.0.5 +===== + +### Significant changes relative to 2.0.4: + +1. Worked around issues in the MIPS DSPr2 SIMD extensions that caused failures +in the libjpeg-turbo regression tests. Specifically, the +`jsimd_h2v1_downsample_dspr2()` and `jsimd_h2v2_downsample_dspr2()` functions +in the MIPS DSPr2 SIMD extensions are now disabled until/unless they can be +fixed, and other functions that are incompatible with big endian MIPS CPUs are +disabled when building libjpeg-turbo for such CPUs. + +2. Fixed an oversight in the `TJCompressor.compress(int)` method in the +TurboJPEG Java API that caused an error ("java.lang.IllegalStateException: No +source image is associated with this instance") when attempting to use that +method to compress a YUV image. + +3. Fixed an issue (CVE-2020-13790) in the PPM reader that caused a buffer +overrun in cjpeg, TJBench, or the `tjLoadImage()` function if one of the values +in a binary PPM/PGM input file exceeded the maximum value defined in the file's +header and that maximum value was less than 255. libjpeg-turbo 1.5.0 already +included a similar fix for binary PPM/PGM files with maximum values greater +than 255. + +4. The TurboJPEG API library's global error handler, which is used in functions +such as `tjBufSize()` and `tjLoadImage()` that do not require a TurboJPEG +instance handle, is now thread-safe on platforms that support thread-local +storage. + + 2.0.4 ===== @@ -562,10 +592,10 @@ application was linked against. 3. Fixed a couple of issues in the PPM reader that would cause buffer overruns in cjpeg if one of the values in a binary PPM/PGM input file exceeded the -maximum value defined in the file's header. libjpeg-turbo 1.4.2 already -included a similar fix for ASCII PPM/PGM files. Note that these issues were -not security bugs, since they were confined to the cjpeg program and did not -affect any of the libjpeg-turbo libraries. +maximum value defined in the file's header and that maximum value was greater +than 255. libjpeg-turbo 1.4.2 already included a similar fix for ASCII PPM/PGM +files. Note that these issues were not security bugs, since they were confined +to the cjpeg program and did not affect any of the libjpeg-turbo libraries. 4. Fixed an issue whereby attempting to decompress a JPEG file with a corrupt header using the `tjDecompressToYUV2()` function would cause the function to diff --git a/doc/html/group___turbo_j_p_e_g.html b/doc/html/group___turbo_j_p_e_g.html index 5d67d78a..2ee145f6 100644 --- a/doc/html/group___turbo_j_p_e_g.html +++ b/doc/html/group___turbo_j_p_e_g.html @@ -2129,7 +2129,7 @@ If you choose option 1, *jpegSize should be set to the size of your

Returns a descriptive error message explaining why the last command failed.

Parameters
- +
handlea handle to a TurboJPEG compressor, decompressor, or transformer instance, or NULL if the error was generated by a global function (but note that retrieving the error message for a global function is not thread-safe.)
handlea handle to a TurboJPEG compressor, decompressor, or transformer instance, or NULL if the error was generated by a global function (but note that retrieving the error message for a global function is thread-safe only on platforms that support thread-local storage.)
diff --git a/java/org/libjpegturbo/turbojpeg/TJCompressor.java b/java/org/libjpegturbo/turbojpeg/TJCompressor.java index 74e5db9c..6d4830f5 100644 --- a/java/org/libjpegturbo/turbojpeg/TJCompressor.java +++ b/java/org/libjpegturbo/turbojpeg/TJCompressor.java @@ -1,5 +1,5 @@ /* - * Copyright (C)2011-2015, 2018 D. R. Commander. All Rights Reserved. + * Copyright (C)2011-2015, 2018, 2020 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 @@ -377,8 +377,15 @@ public class TJCompressor implements Closeable { * #getCompressedSize} to obtain the size of the JPEG image. */ public byte[] compress(int flags) throws TJException { - checkSourceImage(); - byte[] buf = new byte[TJ.bufSize(srcWidth, srcHeight, subsamp)]; + byte[] buf; + if (srcYUVImage != null) { + buf = new byte[TJ.bufSize(srcYUVImage.getWidth(), + srcYUVImage.getHeight(), + srcYUVImage.getSubsamp())]; + } else { + checkSourceImage(); + buf = new byte[TJ.bufSize(srcWidth, srcHeight, subsamp)]; + } compress(buf, flags); return buf; } diff --git a/jconfigint.h.in b/jconfigint.h.in index 55df0536..68cbc2a5 100644 --- a/jconfigint.h.in +++ b/jconfigint.h.in @@ -7,6 +7,9 @@ /* How to obtain function inlining. */ #define INLINE @INLINE@ +/* How to obtain thread-local storage */ +#define THREAD_LOCAL @THREAD_LOCAL@ + /* Define to the full name of this package. */ #define PACKAGE_NAME "@CMAKE_PROJECT_NAME@" diff --git a/jpegtran.c b/jpegtran.c index 6ed99893..c4bfd7e5 100644 --- a/jpegtran.c +++ b/jpegtran.c @@ -51,7 +51,7 @@ boolean memsrc = FALSE; /* for -memsrc switch */ LOCAL(void) -usage (void) +usage(void) /* complain about bad command line */ { fprintf(stderr, "usage: %s [switches] ", progname); @@ -105,7 +105,7 @@ usage (void) LOCAL(void) -select_transform (JXFORM_CODE transform) +select_transform(JXFORM_CODE transform) /* Silly little routine to detect multiple transform options, * which we can't handle. */ @@ -128,7 +128,7 @@ select_transform (JXFORM_CODE transform) LOCAL(int) -parse_switches (j_compress_ptr cinfo, int argc, char **argv, +parse_switches(j_compress_ptr cinfo, int argc, char **argv, int last_file_arg_seen, boolean for_real) /* Parse optional switches. * Returns argv[] index of first file-name argument (== argc if none). @@ -208,7 +208,7 @@ parse_switches (j_compress_ptr cinfo, int argc, char **argv, #if TRANSFORMS_SUPPORTED if (++argn >= argc) /* advance to next argument */ usage(); - if (! jtransform_parse_crop_spec(&transformoption, argv[argn])) { + if (!jtransform_parse_crop_spec(&transformoption, argv[argn])) { fprintf(stderr, "%s: bogus -crop argument '%s'\n", progname, argv[argn]); exit(EXIT_FAILURE); @@ -223,7 +223,7 @@ parse_switches (j_compress_ptr cinfo, int argc, char **argv, /* On first -d, print version identification */ static boolean printed_version = FALSE; - if (! printed_version) { + if (!printed_version) { fprintf(stderr, "%s version %s (build %s)\n", PACKAGE_NAME, VERSION, BUILD); fprintf(stderr, "%s\n\n", JCOPYRIGHT); @@ -327,10 +327,10 @@ parse_switches (j_compress_ptr cinfo, int argc, char **argv, if (lval < 0 || lval > 65535L) usage(); if (ch == 'b' || ch == 'B') { - cinfo->restart_interval = (unsigned int) lval; + cinfo->restart_interval = (unsigned int)lval; cinfo->restart_in_rows = 0; /* else prior '-restart n' overrides me */ } else { - cinfo->restart_in_rows = (int) lval; + cinfo->restart_in_rows = (int)lval; /* restart_interval will be computed during startup */ } @@ -399,7 +399,7 @@ parse_switches (j_compress_ptr cinfo, int argc, char **argv, #ifdef C_MULTISCAN_FILES_SUPPORTED if (scansarg != NULL) /* process -scans if it was present */ - if (! read_scan_script(cinfo, scansarg)) + if (!read_scan_script(cinfo, scansarg)) usage(); #endif @@ -414,7 +414,7 @@ parse_switches (j_compress_ptr cinfo, int argc, char **argv, */ int -main (int argc, char **argv) +main(int argc, char **argv) { struct jpeg_decompress_struct srcinfo; struct jpeg_compress_struct dstinfo; @@ -468,14 +468,14 @@ main (int argc, char **argv) #ifdef TWO_FILE_COMMANDLINE /* Must have either -outfile switch or explicit output file name */ if (outfilename == NULL) { - if (file_index != argc-2) { + if (file_index != argc - 2) { fprintf(stderr, "%s: must name one input and one output file\n", progname); usage(); } - outfilename = argv[file_index+1]; + outfilename = argv[file_index + 1]; } else { - if (file_index != argc-1) { + if (file_index != argc - 1) { fprintf(stderr, "%s: must name one input and one output file\n", progname); usage(); @@ -483,7 +483,7 @@ main (int argc, char **argv) } #else /* Unix style: expect zero or one file name */ - if (file_index < argc-1) { + if (file_index < argc - 1) { fprintf(stderr, "%s: only one input file\n", progname); usage(); } @@ -531,7 +531,7 @@ main (int argc, char **argv) } #ifdef PROGRESS_REPORT - start_progress_monitor((j_common_ptr) &dstinfo, &progress); + start_progress_monitor((j_common_ptr)&dstinfo, &progress); #endif /* Specify data source for decompression */ @@ -567,7 +567,7 @@ main (int argc, char **argv) jcopy_markers_setup(&srcinfo, copyoption); /* Read file header */ - (void) jpeg_read_header(&srcinfo, TRUE); + (void)jpeg_read_header(&srcinfo, TRUE); /* Any space needed by a transform option must be requested before * jpeg_read_coefficients so that memory allocation will be done right. @@ -601,7 +601,7 @@ main (int argc, char **argv) /* Close input file, if we opened it. * Note: we assume that jpeg_read_coefficients consumed all input * until JPEG_REACHED_EOI, and that jpeg_finish_decompress will - * only consume more while (! cinfo->inputctl->eoi_reached). + * only consume more while (!cinfo->inputctl->eoi_reached). * We cannot call jpeg_finish_decompress here since we still need the * virtual arrays allocated from the source object for processing. */ @@ -676,7 +676,7 @@ main (int argc, char **argv) #endif jpeg_destroy_compress(&dstinfo); - (void) jpeg_finish_decompress(&srcinfo); + (void)jpeg_finish_decompress(&srcinfo); jpeg_destroy_decompress(&srcinfo); /* Close output file, if we opened it */ @@ -684,14 +684,13 @@ main (int argc, char **argv) fclose(fp); #ifdef PROGRESS_REPORT - end_progress_monitor((j_common_ptr) &dstinfo); + end_progress_monitor((j_common_ptr)&dstinfo); #endif free(inbuffer); free(outbuffer); - if (icc_profile != NULL) - free(icc_profile); + free(icc_profile); /* All done. */ exit(jsrcerr.num_warnings + jdsterr.num_warnings ? diff --git a/rdppm.c b/rdppm.c index 87bc3309..a8507b90 100644 --- a/rdppm.c +++ b/rdppm.c @@ -5,7 +5,7 @@ * Copyright (C) 1991-1997, Thomas G. Lane. * Modified 2009 by Bill Allombert, Guido Vollbeding. * libjpeg-turbo Modifications: - * Copyright (C) 2015-2017, D. R. Commander. + * Copyright (C) 2015-2017, 2020, D. R. Commander. * For conditions of distribution and use, see the accompanying README.ijg * file. * @@ -720,7 +720,7 @@ start_input_ppm(j_compress_ptr cinfo, cjpeg_source_ptr sinfo) /* On 16-bit-int machines we have to be careful of maxval = 65535 */ source->rescale = (JSAMPLE *) (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE, - (size_t)(((long)maxval + 1L) * + (size_t)(((long)MAX(maxval, 255) + 1L) * sizeof(JSAMPLE))); half_maxval = maxval / 2; for (val = 0; val <= (long)maxval; val++) { diff --git a/rdswitch.c b/rdswitch.c index aa4d1e96..77b2adfa 100644 --- a/rdswitch.c +++ b/rdswitch.c @@ -541,8 +541,8 @@ set_quality_ratings (j_compress_ptr cinfo, char *arg, boolean force_baseline) #else q_scale_factor[tblno] = jpeg_float_quality_scaling(val); #endif - while (*arg && *arg++ != ',') /* advance to next segment of arg string */ - ; + while (*arg && *arg++ != ','); /* advance to next segment of arg + string */ } else { /* reached end of parameter, set remaining factors to last value */ #if JPEG_LIB_VERSION >= 70 @@ -592,8 +592,8 @@ set_quant_slots (j_compress_ptr cinfo, char *arg) return FALSE; } cinfo->comp_info[ci].quant_tbl_no = val; - while (*arg && *arg++ != ',') /* advance to next segment of arg string */ - ; + while (*arg && *arg++ != ','); /* advance to next segment of arg + string */ } else { /* reached end of parameter, set remaining components to last table */ cinfo->comp_info[ci].quant_tbl_no = val; @@ -626,8 +626,8 @@ set_sample_factors (j_compress_ptr cinfo, char *arg) } cinfo->comp_info[ci].h_samp_factor = val1; cinfo->comp_info[ci].v_samp_factor = val2; - while (*arg && *arg++ != ',') /* advance to next segment of arg string */ - ; + while (*arg && *arg++ != ','); /* advance to next segment of arg + string */ } else { /* reached end of parameter, set remaining components to 1x1 sampling */ cinfo->comp_info[ci].h_samp_factor = 1; diff --git a/simd/mips/jsimd.c b/simd/mips/jsimd.c index 454cc99c..d2546eed 100644 --- a/simd/mips/jsimd.c +++ b/simd/mips/jsimd.c @@ -2,7 +2,7 @@ * jsimd_mips.c * * Copyright 2009 Pierre Ossman for Cendio AB - * Copyright (C) 2009-2011, 2014, 2016, 2018, D. R. Commander. + * Copyright (C) 2009-2011, 2014, 2016, 2018, 2020, D. R. Commander. * Copyright (C) 2013-2014, MIPS Technologies, Inc., California. * Copyright (C) 2015-2016, 2018, Matthieu Darbois. * @@ -29,9 +29,9 @@ static unsigned int simd_support = ~0; -#if defined(__linux__) +#if !(defined(__mips_dsp) && (__mips_dsp_rev >= 2)) && defined(__linux__) -LOCAL(int) +LOCAL(void) parse_proc_cpuinfo(const char *search_string) { const char *file_name = "/proc/cpuinfo"; @@ -45,13 +45,12 @@ parse_proc_cpuinfo(const char *search_string) if (strstr(cpuinfo_line, search_string) != NULL) { fclose(f); simd_support |= JSIMD_DSPR2; - return 1; + return; } } fclose(f); } /* Did not find string in the proc file, or not Linux ELF. */ - return 0; } #endif @@ -73,14 +72,13 @@ init_simd(void) simd_support = 0; -#if defined(__MIPSEL__) && defined(__mips_dsp) && (__mips_dsp_rev >= 2) +#if defined(__mips_dsp) && (__mips_dsp_rev >= 2) simd_support |= JSIMD_DSPR2; #elif defined(__linux__) /* We still have a chance to use MIPS DSPR2 regardless of globally used * -mdspr2 options passed to gcc by performing runtime detection via * /proc/cpuinfo parsing on linux */ - if (!parse_proc_cpuinfo("MIPS 74K")) - return; + parse_proc_cpuinfo("MIPS 74K"); #endif #ifndef NO_GETENV @@ -340,8 +338,13 @@ jsimd_can_h2v2_downsample(void) if (sizeof(JDIMENSION) != 4) return 0; + /* FIXME: jsimd_h2v2_downsample_dspr2() fails some of the TJBench tiling + * regression tests, probably because the DSPr2 SIMD implementation predates + * those tests. */ +#if 0 if (simd_support & JSIMD_DSPR2) return 1; +#endif return 0; } @@ -376,8 +379,13 @@ jsimd_can_h2v1_downsample(void) if (sizeof(JDIMENSION) != 4) return 0; + /* FIXME: jsimd_h2v1_downsample_dspr2() fails some of the TJBench tiling + * regression tests, probably because the DSPr2 SIMD implementation predates + * those tests. */ +#if 0 if (simd_support & JSIMD_DSPR2) return 1; +#endif return 0; } @@ -441,8 +449,10 @@ jsimd_can_h2v1_upsample(void) if (sizeof(JDIMENSION) != 4) return 0; +#if defined(__MIPSEL__) if (simd_support & JSIMD_DSPR2) return 1; +#endif return 0; } @@ -503,8 +513,10 @@ jsimd_can_h2v2_fancy_upsample(void) if (sizeof(JDIMENSION) != 4) return 0; +#if defined(__MIPSEL__) if (simd_support & JSIMD_DSPR2) return 1; +#endif return 0; } @@ -520,8 +532,10 @@ jsimd_can_h2v1_fancy_upsample(void) if (sizeof(JDIMENSION) != 4) return 0; +#if defined(__MIPSEL__) if (simd_support & JSIMD_DSPR2) return 1; +#endif return 0; } @@ -669,8 +683,10 @@ jsimd_can_convsamp(void) if (sizeof(DCTELEM) != 2) return 0; +#if defined(__MIPSEL__) if (simd_support & JSIMD_DSPR2) return 1; +#endif return 0; } @@ -727,8 +743,10 @@ jsimd_can_fdct_islow(void) if (sizeof(DCTELEM) != 2) return 0; +#if defined(__MIPSEL__) if (simd_support & JSIMD_DSPR2) return 1; +#endif return 0; } @@ -744,8 +762,10 @@ jsimd_can_fdct_ifast(void) if (sizeof(DCTELEM) != 2) return 0; +#if defined(__MIPSEL__) if (simd_support & JSIMD_DSPR2) return 1; +#endif return 0; } @@ -872,8 +892,10 @@ jsimd_can_idct_4x4(void) if (sizeof(ISLOW_MULT_TYPE) != 2) return 0; +#if defined(__MIPSEL__) if (simd_support & JSIMD_DSPR2) return 1; +#endif return 0; } @@ -1017,8 +1039,10 @@ jsimd_can_idct_ifast(void) if (IFAST_SCALE_BITS != 2) return 0; +#if defined(__MIPSEL__) if (simd_support & JSIMD_DSPR2) return 1; +#endif return 0; } diff --git a/turbojpeg.c b/turbojpeg.c index f8fd36bd..33ae14c7 100644 --- a/turbojpeg.c +++ b/turbojpeg.c @@ -1,5 +1,7 @@ /* - * Copyright (C)2009-2019 D. R. Commander. All Rights Reserved. + * Copyright (C)2009-2020 D. R. Commander. All Rights Reserved. + * mozjpeg Modifications: + * Copyright (C) 2014, Mozilla Corporation. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: @@ -43,6 +45,7 @@ #include "transupp.h" #include "./jpegcomp.h" #include "./cdjpeg.h" +#include "jconfigint.h" extern void jpeg_mem_dest_tj(j_compress_ptr, unsigned char **, unsigned long *, boolean); @@ -55,7 +58,7 @@ extern void jpeg_mem_src_tj(j_decompress_ptr, const unsigned char *, /* Error handling (based on example in example.txt) */ -static char errStr[JMSG_LENGTH_MAX] = "No error"; +static THREAD_LOCAL char errStr[JMSG_LENGTH_MAX] = "No error"; struct my_error_mgr { struct jpeg_error_mgr pub; @@ -243,6 +246,8 @@ static int setCompDefaults(struct jpeg_compress_struct *cinfo, int pixelFormat, cinfo->in_color_space = pf2cs[pixelFormat]; cinfo->input_components = tjPixelSize[pixelFormat]; + if((env=getenv("TJ_REVERT"))!=NULL && strlen(env)>0 && !strcmp(env, "1")) + cinfo->master->compress_profile=JCP_FASTEST; jpeg_set_defaults(cinfo); #ifndef NO_GETENV @@ -289,6 +294,10 @@ static int setCompDefaults(struct jpeg_compress_struct *cinfo, int pixelFormat, jpeg_simple_progression(cinfo); #endif + /* Set scan pattern again as colorspace might have changed */ + if(cinfo->master->compress_profile == JCP_MAX_COMPRESSION) + jpeg_simple_progression(cinfo); + cinfo->comp_info[0].h_samp_factor = tjMCUWidth[subsamp] / 8; cinfo->comp_info[1].h_samp_factor = 1; cinfo->comp_info[2].h_samp_factor = 1; diff --git a/turbojpeg.h b/turbojpeg.h index 074f015f..f3209dd3 100644 --- a/turbojpeg.h +++ b/turbojpeg.h @@ -1650,7 +1650,7 @@ DLLEXPORT void tjFree(unsigned char *buffer); * @param handle a handle to a TurboJPEG compressor, decompressor, or * transformer instance, or NULL if the error was generated by a global * function (but note that retrieving the error message for a global function - * is not thread-safe.) + * is thread-safe only on platforms that support thread-local storage.) * * @return a descriptive error message explaining why the last command failed. */