Work around an issue in Visual C++ 2010 and 2013 that was causing the 256-bit bitmap test in the regression tests to fail. More specifically, when optimization is enabled in these versions of Visual C++, the optimizer seems to get confused by the following code block:

delta = cur0 * 2;
       cur0 += delta;          /* form error * 3 */
       errorptr[0] = (FSERROR) (bpreverr0 + cur0);
       cur0 += delta;          /* form error * 5 */
       bpreverr0 = belowerr0 + cur0;
       cur0 += delta;          /* form error * 7 */

Each time cur0 is incremented by delta, the compiled code doubles the value of delta (WTF?!)  Thus, by the time the end of the block is reached, cur0 is equal to 15 times its former self, not 7 times its former self as it should be.  At any rate, it was a lot simpler to just refactor the code so that it uses multiplication.


git-svn-id: svn+ssh://svn.code.sf.net/p/libjpeg-turbo/code/branches/1.3.x@1253 632fc199-4ca6-4c93-a231-07263d6284db
This commit is contained in:
DRC 2014-04-20 07:22:21 +00:00
Родитель 06fa20d407 beb0b33764
Коммит ac9a92ebbd
2 изменённых файлов: 34 добавлений и 33 удалений

Просмотреть файл

@ -1,3 +1,13 @@
1.3.2
=====
[1] Worked around an issue with Visual C++ 2010 and later that caused incorrect
pixels to be generated when decompressing a JPEG image to a 256-color bitmap,
if compiler optimization was enabled when libjpeg-turbo was built. This caused
the regression tests to fail when doing a release build under Visual C++ 2010
and later.
1.3.1 1.3.1
===== =====

Просмотреть файл

@ -4,7 +4,7 @@
* This file was part of the Independent JPEG Group's software: * This file was part of the Independent JPEG Group's software:
* Copyright (C) 1991-1996, Thomas G. Lane. * Copyright (C) 1991-1996, Thomas G. Lane.
* libjpeg-turbo Modifications: * libjpeg-turbo Modifications:
* Copyright (C) 2009, D. R. Commander. * Copyright (C) 2009, 2014, D. R. Commander.
* For conditions of distribution and use, see the accompanying README file. * For conditions of distribution and use, see the accompanying README file.
* *
* This file contains 2-pass color quantization (color mapping) routines. * This file contains 2-pass color quantization (color mapping) routines.
@ -43,7 +43,7 @@
* color space, and repeatedly splits the "largest" remaining box until we * color space, and repeatedly splits the "largest" remaining box until we
* have as many boxes as desired colors. Then the mean color in each * have as many boxes as desired colors. Then the mean color in each
* remaining box becomes one of the possible output colors. * remaining box becomes one of the possible output colors.
* *
* The second pass over the image maps each input pixel to the closest output * The second pass over the image maps each input pixel to the closest output
* color (optionally after applying a Floyd-Steinberg dithering correction). * color (optionally after applying a Floyd-Steinberg dithering correction).
* This mapping is logically trivial, but making it go fast enough requires * This mapping is logically trivial, but making it go fast enough requires
@ -261,7 +261,7 @@ find_biggest_color_pop (boxptr boxlist, int numboxes)
register int i; register int i;
register long maxc = 0; register long maxc = 0;
boxptr which = NULL; boxptr which = NULL;
for (i = 0, boxp = boxlist; i < numboxes; i++, boxp++) { for (i = 0, boxp = boxlist; i < numboxes; i++, boxp++) {
if (boxp->colorcount > maxc && boxp->volume > 0) { if (boxp->colorcount > maxc && boxp->volume > 0) {
which = boxp; which = boxp;
@ -281,7 +281,7 @@ find_biggest_volume (boxptr boxlist, int numboxes)
register int i; register int i;
register INT32 maxv = 0; register INT32 maxv = 0;
boxptr which = NULL; boxptr which = NULL;
for (i = 0, boxp = boxlist; i < numboxes; i++, boxp++) { for (i = 0, boxp = boxlist; i < numboxes; i++, boxp++) {
if (boxp->volume > maxv) { if (boxp->volume > maxv) {
which = boxp; which = boxp;
@ -304,11 +304,11 @@ update_box (j_decompress_ptr cinfo, boxptr boxp)
int c0min,c0max,c1min,c1max,c2min,c2max; int c0min,c0max,c1min,c1max,c2min,c2max;
INT32 dist0,dist1,dist2; INT32 dist0,dist1,dist2;
long ccount; long ccount;
c0min = boxp->c0min; c0max = boxp->c0max; c0min = boxp->c0min; c0max = boxp->c0max;
c1min = boxp->c1min; c1max = boxp->c1max; c1min = boxp->c1min; c1max = boxp->c1max;
c2min = boxp->c2min; c2max = boxp->c2max; c2min = boxp->c2min; c2max = boxp->c2max;
if (c0max > c0min) if (c0max > c0min)
for (c0 = c0min; c0 <= c0max; c0++) for (c0 = c0min; c0 <= c0max; c0++)
for (c1 = c1min; c1 <= c1max; c1++) { for (c1 = c1min; c1 <= c1max; c1++) {
@ -388,7 +388,7 @@ update_box (j_decompress_ptr cinfo, boxptr boxp)
dist1 = ((c1max - c1min) << C1_SHIFT) * C1_SCALE; dist1 = ((c1max - c1min) << C1_SHIFT) * C1_SCALE;
dist2 = ((c2max - c2min) << C2_SHIFT) * C2_SCALE; dist2 = ((c2max - c2min) << C2_SHIFT) * C2_SCALE;
boxp->volume = dist0*dist0 + dist1*dist1 + dist2*dist2; boxp->volume = dist0*dist0 + dist1*dist1 + dist2*dist2;
/* Now scan remaining volume of box and compute population */ /* Now scan remaining volume of box and compute population */
ccount = 0; ccount = 0;
for (c0 = c0min; c0 <= c0max; c0++) for (c0 = c0min; c0 <= c0max; c0++)
@ -495,11 +495,11 @@ compute_color (j_decompress_ptr cinfo, boxptr boxp, int icolor)
long c0total = 0; long c0total = 0;
long c1total = 0; long c1total = 0;
long c2total = 0; long c2total = 0;
c0min = boxp->c0min; c0max = boxp->c0max; c0min = boxp->c0min; c0max = boxp->c0max;
c1min = boxp->c1min; c1max = boxp->c1max; c1min = boxp->c1min; c1max = boxp->c1max;
c2min = boxp->c2min; c2max = boxp->c2max; c2min = boxp->c2min; c2max = boxp->c2max;
for (c0 = c0min; c0 <= c0max; c0++) for (c0 = c0min; c0 <= c0max; c0++)
for (c1 = c1min; c1 <= c1max; c1++) { for (c1 = c1min; c1 <= c1max; c1++) {
histp = & histogram[c0][c1][c2min]; histp = & histogram[c0][c1][c2min];
@ -512,7 +512,7 @@ compute_color (j_decompress_ptr cinfo, boxptr boxp, int icolor)
} }
} }
} }
cinfo->colormap[0][icolor] = (JSAMPLE) ((c0total + (total>>1)) / total); cinfo->colormap[0][icolor] = (JSAMPLE) ((c0total + (total>>1)) / total);
cinfo->colormap[1][icolor] = (JSAMPLE) ((c1total + (total>>1)) / total); cinfo->colormap[1][icolor] = (JSAMPLE) ((c1total + (total>>1)) / total);
cinfo->colormap[2][icolor] = (JSAMPLE) ((c2total + (total>>1)) / total); cinfo->colormap[2][icolor] = (JSAMPLE) ((c2total + (total>>1)) / total);
@ -781,17 +781,17 @@ find_best_colors (j_decompress_ptr cinfo, int minc0, int minc1, int minc2,
bptr = bestdist; bptr = bestdist;
for (i = BOX_C0_ELEMS*BOX_C1_ELEMS*BOX_C2_ELEMS-1; i >= 0; i--) for (i = BOX_C0_ELEMS*BOX_C1_ELEMS*BOX_C2_ELEMS-1; i >= 0; i--)
*bptr++ = 0x7FFFFFFFL; *bptr++ = 0x7FFFFFFFL;
/* For each color selected by find_nearby_colors, /* For each color selected by find_nearby_colors,
* compute its distance to the center of each cell in the box. * compute its distance to the center of each cell in the box.
* If that's less than best-so-far, update best distance and color number. * If that's less than best-so-far, update best distance and color number.
*/ */
/* Nominal steps between cell centers ("x" in Thomas article) */ /* Nominal steps between cell centers ("x" in Thomas article) */
#define STEP_C0 ((1 << C0_SHIFT) * C0_SCALE) #define STEP_C0 ((1 << C0_SHIFT) * C0_SCALE)
#define STEP_C1 ((1 << C1_SHIFT) * C1_SCALE) #define STEP_C1 ((1 << C1_SHIFT) * C1_SCALE)
#define STEP_C2 ((1 << C2_SHIFT) * C2_SCALE) #define STEP_C2 ((1 << C2_SHIFT) * C2_SCALE)
for (i = 0; i < numcolors; i++) { for (i = 0; i < numcolors; i++) {
icolor = GETJSAMPLE(colorlist[i]); icolor = GETJSAMPLE(colorlist[i]);
/* Compute (square of) distance from minc0/c1/c2 to this color */ /* Compute (square of) distance from minc0/c1/c2 to this color */
@ -865,7 +865,7 @@ fill_inverse_cmap (j_decompress_ptr cinfo, int c0, int c1, int c2)
minc0 = (c0 << BOX_C0_SHIFT) + ((1 << C0_SHIFT) >> 1); minc0 = (c0 << BOX_C0_SHIFT) + ((1 << C0_SHIFT) >> 1);
minc1 = (c1 << BOX_C1_SHIFT) + ((1 << C1_SHIFT) >> 1); minc1 = (c1 << BOX_C1_SHIFT) + ((1 << C1_SHIFT) >> 1);
minc2 = (c2 << BOX_C2_SHIFT) + ((1 << C2_SHIFT) >> 1); minc2 = (c2 << BOX_C2_SHIFT) + ((1 << C2_SHIFT) >> 1);
/* Determine which colormap entries are close enough to be candidates /* Determine which colormap entries are close enough to be candidates
* for the nearest entry to some cell in the update box. * for the nearest entry to some cell in the update box.
*/ */
@ -1025,32 +1025,23 @@ pass2_fs_dither (j_decompress_ptr cinfo,
* Add these into the running sums, and simultaneously shift the * Add these into the running sums, and simultaneously shift the
* next-line error sums left by 1 column. * next-line error sums left by 1 column.
*/ */
{ register LOCFSERROR bnexterr, delta; { register LOCFSERROR bnexterr;
bnexterr = cur0; /* Process component 0 */ bnexterr = cur0; /* Process component 0 */
delta = cur0 * 2; errorptr[0] = (FSERROR) (bpreverr0 + cur0 * 3);
cur0 += delta; /* form error * 3 */ bpreverr0 = belowerr0 + cur0 * 5;
errorptr[0] = (FSERROR) (bpreverr0 + cur0);
cur0 += delta; /* form error * 5 */
bpreverr0 = belowerr0 + cur0;
belowerr0 = bnexterr; belowerr0 = bnexterr;
cur0 += delta; /* form error * 7 */ cur0 *= 7;
bnexterr = cur1; /* Process component 1 */ bnexterr = cur1; /* Process component 1 */
delta = cur1 * 2; errorptr[1] = (FSERROR) (bpreverr1 + cur1 * 3);
cur1 += delta; /* form error * 3 */ bpreverr1 = belowerr1 + cur1 * 5;
errorptr[1] = (FSERROR) (bpreverr1 + cur1);
cur1 += delta; /* form error * 5 */
bpreverr1 = belowerr1 + cur1;
belowerr1 = bnexterr; belowerr1 = bnexterr;
cur1 += delta; /* form error * 7 */ cur1 *= 7;
bnexterr = cur2; /* Process component 2 */ bnexterr = cur2; /* Process component 2 */
delta = cur2 * 2; errorptr[2] = (FSERROR) (bpreverr2 + cur2 * 3);
cur2 += delta; /* form error * 3 */ bpreverr2 = belowerr2 + cur2 * 5;
errorptr[2] = (FSERROR) (bpreverr2 + cur2);
cur2 += delta; /* form error * 5 */
bpreverr2 = belowerr2 + cur2;
belowerr2 = bnexterr; belowerr2 = bnexterr;
cur2 += delta; /* form error * 7 */ cur2 *= 7;
} }
/* At this point curN contains the 7/16 error value to be propagated /* At this point curN contains the 7/16 error value to be propagated
* to the next pixel on the current line, and all the errors for the * to the next pixel on the current line, and all the errors for the