Skip to content

Commit

Permalink
Fix negative shift with IFAST FDCT and qual=100
Browse files Browse the repository at this point in the history
With certain images, compressing using quality=100 and the fast integer
forward DCT will cause the divisor passed to compute_reciprocal() to be
1.  In those cases, the library already disables the SIMD quantization
algorithm to avoid 16-bit overflow.  However, compute_reciprocal()
doesn't properly handle the divisor==1 case, so we need to use special
values in that case so that the C quantization algorithm will behave
like an identity function.
  • Loading branch information
dcommander committed Aug 29, 2015
1 parent f3395fe commit 4cfa3f4
Show file tree
Hide file tree
Showing 2 changed files with 21 additions and 2 deletions.
5 changes: 5 additions & 0 deletions ChangeLog.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,11 @@ negative width or height was used as an input image (Windows bitmaps can have
a negative height if they are stored in top-down order, but such files are
rare and not supported by libjpeg-turbo.)

[2] Fixed an issue whereby, under certain circumstances, libjpeg-turbo would
incorrectly encode certain JPEG images when quality=100 and the fast integer
forward DCT were used. This was known to cause 'make test' to fail when the
library was built with '-march=haswell' on x86 systems.


1.4.1
=====
Expand Down
18 changes: 16 additions & 2 deletions jcdctmgr.c
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
* libjpeg-turbo Modifications:
* Copyright (C) 1999-2006, MIYASAKA Masaru.
* Copyright 2009 Pierre Ossman <ossman@cendio.se> for Cendio AB
* Copyright (C) 2011, 2014 D. R. Commander
* Copyright (C) 2011, 2014-2015 D. R. Commander
* For conditions of distribution and use, see the accompanying README file.
*
* This file contains the forward-DCT management logic.
Expand Down Expand Up @@ -175,6 +175,19 @@ compute_reciprocal (UINT16 divisor, DCTELEM * dtbl)
UDCTELEM c;
int b, r;

if (divisor == 1) {
/* divisor == 1 means unquantized, so these reciprocal/correction/shift
* values will cause the C quantization algorithm to act like the
* identity function. Since only the C quantization algorithm is used in
* these cases, the scale value is irrelevant.
*/
dtbl[DCTSIZE2 * 0] = (DCTELEM) 1; /* reciprocal */
dtbl[DCTSIZE2 * 1] = (DCTELEM) 0; /* correction */
dtbl[DCTSIZE2 * 2] = (DCTELEM) 1; /* scale */
dtbl[DCTSIZE2 * 3] = (DCTELEM) (-sizeof(DCTELEM) * 8); /* shift */
return 0;
}

b = flss(divisor) - 1;
r = sizeof(DCTELEM) * 8 + b;

Expand Down Expand Up @@ -395,7 +408,8 @@ quantize (JCOEFPTR coef_block, DCTELEM * divisors, DCTELEM * workspace)

#if BITS_IN_JSAMPLE == 8

UDCTELEM recip, corr, shift;
UDCTELEM recip, corr;
int shift;
UDCTELEM2 product;

for (i = 0; i < DCTSIZE2; i++) {
Expand Down

0 comments on commit 4cfa3f4

Please sign in to comment.