Hash :
98ff1fd1
Author :
Date :
2022-11-21T20:57:39
TurboJPEG: Add lossless JPEG detection capability Add a new TurboJPEG C API function (tjDecompressHeader4()) and Java API method (TJDecompressor.getFlags()) that return the bitwise OR of any flags that are relevant to the JPEG image being decompressed (currently TJFLAG_PROGRESSIVE, TJFLAG_ARITHMETIC, TJFLAG_LOSSLESS, and their Java equivalents.) This allows a calling program to determine whether the image being decompressed is a lossless JPEG image, which means that the decompression scaling feature will not be available and that a full-sized destination buffer should be allocated. More specifically, this fixes a buffer overrun in TJBench, TJExample, and the decompress* fuzz targets that occurred when attempting (in vain) to decompress a lossless JPEG image with decompression scaling enabled.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282
#!/bin/bash
set -u
set -e
trap onexit INT
trap onexit TERM
trap onexit EXIT
onexit()
{
if [ -d $OUTDIR ]; then
rm -rf $OUTDIR
fi
}
runme()
{
echo \*\*\* $*
$*
}
EXT=bmp
IMAGES="vgl_5674_0098.${EXT} vgl_6434_0018a.${EXT} vgl_6548_0026a.${EXT} nightshot_iso_100.${EXT}"
IMGDIR=@CMAKE_CURRENT_SOURCE_DIR@/testimages
OUTDIR=`mktemp -d /tmp/__tjbenchtest_output.XXXXXX`
EXEDIR=@CMAKE_CURRENT_BINARY_DIR@
BMPARG=
NSARG=
YUVARG=
ALLOC=0
ALLOCARG=
PROGARG=
ARIARG=
LOSSLSARG=
LOSSLSPSV=
TJQUAL=95
h1SUBSAMP="GRAY 444"
h2SUBSAMP="420 422"
ALLSUBSAMP="GRAY 420 422 444"
if [ "$EXT" = "bmp" ]; then BMPARG=-bmp; fi
if [ -d $OUTDIR ]; then
rm -rf $OUTDIR
fi
mkdir -p $OUTDIR
while [ $# -gt 0 ]; do
case "$1" in
-yuv)
NSARG=-nosmooth
YUVARG=-yuv
# NOTE: The combination of tjEncodeYUV*() and tjCompressFromYUV*() does not
# always produce bitwise-identical results to tjCompress*() if subsampling is
# enabled. In both cases, if the image width or height are not evenly
# divisible by the MCU width/height, then the bottom and/or right edge are
# expanded. However, the libjpeg code performs this expansion prior to
# downsampling, and TurboJPEG performs it in tjCompressFromYUV*(), which is
# after downsampling. Thus, the two will agree only if the width/height along
# each downsampled dimension is an odd number or is evenly divisible by the MCU
# width/height. This disagreement basically amounts to a round-off error, but
# there is no easy way around it, so for now, we just test the only image that
# works. (NOTE: nightshot_iso_100 does not suffer from the above issue, but
# it suffers from an unrelated problem whereby the combination of
# tjDecompressToYUV*() and tjDecodeYUV*() do not produce bitwise-identical
# results to tjDecompress*() if decompression scaling is enabled. This latter
# phenomenon is not yet fully understood but is also believed to be some sort
# of round-off error.)
IMAGES="vgl_6548_0026a.${EXT}"
;;
-alloc)
ALLOCARG=-alloc
ALLOC=1
;;
-progressive)
PROGARG=-progressive
;;
-arithmetic)
ARIARG=-arithmetic
;;
-lossless)
LOSSLSARG="-lossless"
LOSSLSPSV=4
TJQUAL=40
h1SUBSAMP=444
h2SUBSAMP=444
ALLSUBSAMP=444
;;
esac
shift
done
exec >$EXEDIR/tjbenchtest$YUVARG$ALLOCARG$PROGARG$ARIARG$LOSSLSARG.log
# Standard tests
for image in $IMAGES; do
cp $IMGDIR/$image $OUTDIR
basename=`basename $image .${EXT}`
runme $EXEDIR/cjpeg -quality 95 -dct fast $PROGARG $ARIARG $LOSSLSARG $LOSSLSPSV -grayscale -outfile $OUTDIR/${basename}_GRAY_fast_cjpeg.jpg $IMGDIR/${basename}.${EXT}
runme $EXEDIR/cjpeg -quality 95 -dct fast $PROGARG $ARIARG $LOSSLSARG $LOSSLSPSV -sample 2x2 -outfile $OUTDIR/${basename}_420_fast_cjpeg.jpg $IMGDIR/${basename}.${EXT}
runme $EXEDIR/cjpeg -quality 95 -dct fast $PROGARG $ARIARG $LOSSLSARG $LOSSLSPSV -sample 2x1 -outfile $OUTDIR/${basename}_422_fast_cjpeg.jpg $IMGDIR/${basename}.${EXT}
runme $EXEDIR/cjpeg -quality 95 -dct fast $PROGARG $ARIARG $LOSSLSARG $LOSSLSPSV -sample 1x1 -outfile $OUTDIR/${basename}_444_fast_cjpeg.jpg $IMGDIR/${basename}.${EXT}
runme $EXEDIR/cjpeg -quality 95 -dct int $PROGARG $ARIARG $LOSSLSARG $LOSSLSPSV -grayscale -outfile $OUTDIR/${basename}_GRAY_accurate_cjpeg.jpg $IMGDIR/${basename}.${EXT}
runme $EXEDIR/cjpeg -quality 95 -dct int $PROGARG $ARIARG $LOSSLSARG $LOSSLSPSV -sample 2x2 -outfile $OUTDIR/${basename}_420_accurate_cjpeg.jpg $IMGDIR/${basename}.${EXT}
runme $EXEDIR/cjpeg -quality 95 -dct int $PROGARG $ARIARG $LOSSLSARG $LOSSLSPSV -sample 2x1 -outfile $OUTDIR/${basename}_422_accurate_cjpeg.jpg $IMGDIR/${basename}.${EXT}
runme $EXEDIR/cjpeg -quality 95 -dct int $PROGARG $ARIARG $LOSSLSARG $LOSSLSPSV -sample 1x1 -outfile $OUTDIR/${basename}_444_accurate_cjpeg.jpg $IMGDIR/${basename}.${EXT}
for samp in $ALLSUBSAMP; do
runme $EXEDIR/djpeg -rgb $NSARG $BMPARG -outfile $OUTDIR/${basename}_${samp}_default_djpeg.${EXT} $OUTDIR/${basename}_${samp}_fast_cjpeg.jpg
runme $EXEDIR/djpeg -dct fast -rgb $NSARG $BMPARG -outfile $OUTDIR/${basename}_${samp}_fast_djpeg.${EXT} $OUTDIR/${basename}_${samp}_fast_cjpeg.jpg
runme $EXEDIR/djpeg -dct int -rgb $NSARG $BMPARG -outfile $OUTDIR/${basename}_${samp}_accurate_djpeg.${EXT} $OUTDIR/${basename}_${samp}_accurate_cjpeg.jpg
done
for samp in $h2SUBSAMP; do
runme $EXEDIR/djpeg -nosmooth $BMPARG -outfile $OUTDIR/${basename}_${samp}_default_nosmooth_djpeg.${EXT} $OUTDIR/${basename}_${samp}_fast_cjpeg.jpg
runme $EXEDIR/djpeg -dct fast -nosmooth $BMPARG -outfile $OUTDIR/${basename}_${samp}_fast_nosmooth_djpeg.${EXT} $OUTDIR/${basename}_${samp}_fast_cjpeg.jpg
runme $EXEDIR/djpeg -dct int -nosmooth $BMPARG -outfile $OUTDIR/${basename}_${samp}_accurate_nosmooth_djpeg.${EXT} $OUTDIR/${basename}_${samp}_accurate_cjpeg.jpg
done
# Compression
for dct in accurate fast; do
runme $EXEDIR/tjbench $OUTDIR/$image $TJQUAL -rgb -quiet -benchtime 0.01 -warmup 0 -${dct}dct $YUVARG $ALLOCARG $PROGARG $ARIARG $LOSSLSARG
for samp in $ALLSUBSAMP; do
runme cmp $OUTDIR/${basename}_${samp}_Q${TJQUAL}.jpg $OUTDIR/${basename}_${samp}_${dct}_cjpeg.jpg
done
done
for dct in fast accurate default; do
dctarg=-${dct}dct
if [ "${dct}" = "default" ]; then
dctarg=
fi
# Tiled compression & decompression
runme $EXEDIR/tjbench $OUTDIR/$image $TJQUAL -rgb -tile -quiet -benchtime 0.01 -warmup 0 ${dctarg} $YUVARG $ALLOCARG $PROGARG $ARIARG $LOSSLSARG
for samp in $h1SUBSAMP; do
if [ $ALLOC = 1 ]; then
runme cmp $OUTDIR/${basename}_${samp}_Q${TJQUAL}_full.${EXT} $OUTDIR/${basename}_${samp}_${dct}_djpeg.${EXT}
rm $OUTDIR/${basename}_${samp}_Q${TJQUAL}_full.${EXT}
else
for i in $OUTDIR/${basename}_${samp}_Q${TJQUAL}_[0-9]*[0-9]x[0-9]*[0-9].${EXT} \
$OUTDIR/${basename}_${samp}_Q${TJQUAL}_full.${EXT}; do
runme cmp $i $OUTDIR/${basename}_${samp}_${dct}_djpeg.${EXT}
rm $i
done
fi
done
runme $EXEDIR/tjbench $OUTDIR/$image $TJQUAL -rgb -tile -quiet -benchtime 0.01 -warmup 0 -fastupsample ${dctarg} $YUVARG $ALLOCARG $PROGARG $ARIARG $LOSSLSARG
for samp in $h2SUBSAMP; do
if [ $ALLOC = 1 ]; then
runme cmp $OUTDIR/${basename}_${samp}_Q${TJQUAL}_full.${EXT} $OUTDIR/${basename}_${samp}_${dct}_nosmooth_djpeg.${EXT}
rm $OUTDIR/${basename}_${samp}_Q${TJQUAL}_full.${EXT}
else
for i in $OUTDIR/${basename}_${samp}_Q${TJQUAL}_[0-9]*[0-9]x[0-9]*[0-9].${EXT} \
$OUTDIR/${basename}_${samp}_Q${TJQUAL}_full.${EXT}; do
runme cmp $i $OUTDIR/${basename}_${samp}_${dct}_nosmooth_djpeg.${EXT}
rm $i
done
fi
done
# Tiled decompression
if [ "$LOSSLSARG" != "-lossless" ]; then
for samp in GRAY 444; do
runme $EXEDIR/tjbench $OUTDIR/${basename}_${samp}_Q95.jpg $BMPARG -tile -quiet -benchtime 0.01 -warmup 0 ${dctarg} $YUVARG $ALLOCARG $PROGARG $ARIARG
if [ $ALLOC = 1 ]; then
runme cmp $OUTDIR/${basename}_${samp}_Q95_full.${EXT} $OUTDIR/${basename}_${samp}_${dct}_djpeg.${EXT}
rm $OUTDIR/${basename}_${samp}_Q95_full.${EXT}
else
for i in $OUTDIR/${basename}_${samp}_Q95_[0-9]*[0-9]x[0-9]*[0-9].${EXT} \
$OUTDIR/${basename}_${samp}_Q95_full.${EXT}; do
runme cmp $i $OUTDIR/${basename}_${samp}_${dct}_djpeg.${EXT}
rm $i
done
fi
done
for samp in 420 422; do
runme $EXEDIR/tjbench $OUTDIR/${basename}_${samp}_Q95.jpg $BMPARG -tile -quiet -benchtime 0.01 -warmup 0 -fastupsample ${dctarg} $YUVARG $ALLOCARG $PROGARG $ARIARG
if [ $ALLOC = 1 ]; then
runme cmp $OUTDIR/${basename}_${samp}_Q95_full.${EXT} $OUTDIR/${basename}_${samp}_${dct}_nosmooth_djpeg.${EXT}
rm $OUTDIR/${basename}_${samp}_Q95_full.${EXT}
else
for i in $OUTDIR/${basename}_${samp}_Q95_[0-9]*[0-9]x[0-9]*[0-9].${EXT} \
$OUTDIR/${basename}_${samp}_Q95_full.${EXT}; do
runme cmp $i $OUTDIR/${basename}_${samp}_${dct}_nosmooth_djpeg.${EXT}
rm $i
done
fi
done
fi
done
# Scaled decompression
for scale in 2_1 15_8 7_4 13_8 3_2 11_8 5_4 9_8 7_8 3_4 5_8 1_2 3_8 1_4 1_8; do
scalearg=`echo $scale | sed 's/\_/\//g'`
SCALE=$scale
if [ "$LOSSLSARG" = "-lossless" ]; then
SCALE=full
fi
for samp in $ALLSUBSAMP; do
runme $EXEDIR/djpeg -rgb -scale ${scalearg} $NSARG $BMPARG -outfile $OUTDIR/${basename}_${samp}_${scale}_djpeg.${EXT} $OUTDIR/${basename}_${samp}_fast_cjpeg.jpg
runme $EXEDIR/tjbench $OUTDIR/${basename}_${samp}_Q${TJQUAL}.jpg $BMPARG -scale ${scalearg} -quiet -benchtime 0.01 -warmup 0 $YUVARG $ALLOCARG $PROGARG $ARIARG $LOSSLSARG
runme cmp $OUTDIR/${basename}_${samp}_Q${TJQUAL}_${SCALE}.${EXT} $OUTDIR/${basename}_${samp}_${scale}_djpeg.${EXT}
rm $OUTDIR/${basename}_${samp}_Q${TJQUAL}_${SCALE}.${EXT}
done
done
# Transforms
if [ "$LOSSLSARG" != "-lossless" ]; then
for samp in GRAY 420 422 444; do
runme $EXEDIR/jpegtran -flip horizontal -trim -outfile $OUTDIR/${basename}_${samp}_hflip_jpegtran.jpg $OUTDIR/${basename}_${samp}_Q95.jpg
runme $EXEDIR/jpegtran -flip vertical -trim -outfile $OUTDIR/${basename}_${samp}_vflip_jpegtran.jpg $OUTDIR/${basename}_${samp}_Q95.jpg
runme $EXEDIR/jpegtran -transpose -trim -outfile $OUTDIR/${basename}_${samp}_transpose_jpegtran.jpg $OUTDIR/${basename}_${samp}_Q95.jpg
runme $EXEDIR/jpegtran -transverse -trim -outfile $OUTDIR/${basename}_${samp}_transverse_jpegtran.jpg $OUTDIR/${basename}_${samp}_Q95.jpg
runme $EXEDIR/jpegtran -rotate 90 -trim -outfile $OUTDIR/${basename}_${samp}_rot90_jpegtran.jpg $OUTDIR/${basename}_${samp}_Q95.jpg
runme $EXEDIR/jpegtran -rotate 180 -trim -outfile $OUTDIR/${basename}_${samp}_rot180_jpegtran.jpg $OUTDIR/${basename}_${samp}_Q95.jpg
runme $EXEDIR/jpegtran -rotate 270 -trim -outfile $OUTDIR/${basename}_${samp}_rot270_jpegtran.jpg $OUTDIR/${basename}_${samp}_Q95.jpg
done
for xform in hflip vflip transpose transverse rot90 rot180 rot270; do
for samp in GRAY 444; do
runme $EXEDIR/djpeg -rgb $BMPARG -outfile $OUTDIR/${basename}_${samp}_${xform}_jpegtran.${EXT} $OUTDIR/${basename}_${samp}_${xform}_jpegtran.jpg
runme $EXEDIR/tjbench $OUTDIR/${basename}_${samp}_Q95.jpg $BMPARG -$xform -tile -quiet -benchtime 0.01 -warmup 0 $YUVARG $ALLOCARG $PROGARG $ARIARG
if [ $ALLOC = 1 ]; then
runme cmp $OUTDIR/${basename}_${samp}_Q95_full.${EXT} $OUTDIR/${basename}_${samp}_${xform}_jpegtran.${EXT}
rm $OUTDIR/${basename}_${samp}_Q95_full.${EXT}
else
for i in $OUTDIR/${basename}_${samp}_Q95_[0-9]*[0-9]x[0-9]*[0-9].${EXT} \
$OUTDIR/${basename}_${samp}_Q95_full.${EXT}; do
runme cmp $i $OUTDIR/${basename}_${samp}_${xform}_jpegtran.${EXT}
rm $i
done
fi
done
for samp in 420 422; do
runme $EXEDIR/djpeg -nosmooth -rgb $BMPARG -outfile $OUTDIR/${basename}_${samp}_${xform}_jpegtran.${EXT} $OUTDIR/${basename}_${samp}_${xform}_jpegtran.jpg
runme $EXEDIR/tjbench $OUTDIR/${basename}_${samp}_Q95.jpg $BMPARG -$xform -tile -quiet -benchtime 0.01 -warmup 0 -fastupsample $YUVARG $ALLOCARG $PROGARG $ARIARG
if [ $ALLOC = 1 ]; then
runme cmp $OUTDIR/${basename}_${samp}_Q95_full.${EXT} $OUTDIR/${basename}_${samp}_${xform}_jpegtran.${EXT}
rm $OUTDIR/${basename}_${samp}_Q95_full.${EXT}
else
for i in $OUTDIR/${basename}_${samp}_Q95_[0-9]*[0-9]x[0-9]*[0-9].${EXT} \
$OUTDIR/${basename}_${samp}_Q95_full.${EXT}; do
runme cmp $i $OUTDIR/${basename}_${samp}_${xform}_jpegtran.${EXT}
rm $i
done
fi
done
done
# Grayscale transform
for xform in hflip vflip transpose transverse rot90 rot180 rot270; do
for samp in GRAY 444 422 420; do
runme $EXEDIR/tjbench $OUTDIR/${basename}_${samp}_Q95.jpg $BMPARG -$xform -tile -quiet -benchtime 0.01 -warmup 0 -grayscale $YUVARG $ALLOCARG $PROGARG $ARIARG
if [ $ALLOC = 1 ]; then
runme cmp $OUTDIR/${basename}_${samp}_Q95_full.${EXT} $OUTDIR/${basename}_GRAY_${xform}_jpegtran.${EXT}
rm $OUTDIR/${basename}_${samp}_Q95_full.${EXT}
else
for i in $OUTDIR/${basename}_${samp}_Q95_[0-9]*[0-9]x[0-9]*[0-9].${EXT} \
$OUTDIR/${basename}_${samp}_Q95_full.${EXT}; do
runme cmp $i $OUTDIR/${basename}_GRAY_${xform}_jpegtran.${EXT}
rm $i
done
fi
done
done
# Transforms with scaling
for xform in hflip vflip transpose transverse rot90 rot180 rot270; do
for samp in GRAY 444 422 420; do
for scale in 2_1 15_8 7_4 13_8 3_2 11_8 5_4 9_8 7_8 3_4 5_8 1_2 3_8 1_4 1_8; do
scalearg=`echo $scale | sed 's/\_/\//g'`
runme $EXEDIR/djpeg -rgb -scale ${scalearg} $NSARG $BMPARG -outfile $OUTDIR/${basename}_${samp}_${xform}_${scale}_jpegtran.${EXT} $OUTDIR/${basename}_${samp}_${xform}_jpegtran.jpg
runme $EXEDIR/tjbench $OUTDIR/${basename}_${samp}_Q95.jpg $BMPARG -$xform -scale ${scalearg} -quiet -benchtime 0.01 -warmup 0 $YUVARG $ALLOCARG $PROGARG $ARIARG
runme cmp $OUTDIR/${basename}_${samp}_Q95_${scale}.${EXT} $OUTDIR/${basename}_${samp}_${xform}_${scale}_jpegtran.${EXT}
rm $OUTDIR/${basename}_${samp}_Q95_${scale}.${EXT}
done
done
done
fi
done
echo SUCCESS!