From a0148454030bddfabcebe59724e64fbb7b7ad678 Mon Sep 17 00:00:00 2001 From: DRC Date: Fri, 11 Mar 2022 10:50:47 -0600 Subject: [PATCH 1/3] 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 2/3] 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 3/3] 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()