aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDRC <information@libjpeg-turbo.org>2016-02-19 18:32:10 -0600
committerMatt Sarett <msarett@google.com>2016-02-22 12:41:17 -0500
commit0ef076fb7b326dc201b4ab3bd30fefd4e35ad1c4 (patch)
tree25418d0a0c4af0db25df96f084bf62fc9ab103ff
parent83a8b415ea3dfa7b5c584c4239dd39b56f2bf6e0 (diff)
downloadlibjpeg-turbo-0ef076fb7b326dc201b4ab3bd30fefd4e35ad1c4.tar.gz
libjpeg API: Partial scanline decompression
This, in combination with the existing jpeg_skip_scanlines() function, provides the ability to crop the image both horizontally and vertically while decompressing (certain restrictions apply-- see libjpeg.txt.) This also cleans up the documentation of the line skipping feature and removes the "strip decompression" feature from djpeg, since the new cropping feature is a superset of it. Refer to #34 for discussion. Closes #34 Cherry picked from upstream: https://github.com/libjpeg-turbo/libjpeg-turbo/commit/3ab68cf563f6edc2608c085f5c8b2d5d5c61157e BUG:27290496 Change-Id: Id11312fa43959531bc6bea04ebb657c6e1140363
-rw-r--r--CMakeLists.txt77
-rw-r--r--Makefile.am39
-rw-r--r--README.android10
-rw-r--r--djpeg.116
-rw-r--r--djpeg.c125
-rw-r--r--jdapimin.c16
-rw-r--r--jdapistd.c104
-rw-r--r--jdcoefct.c82
-rw-r--r--jdinput.c11
-rw-r--r--jdmaster.c39
-rw-r--r--jdmaster.h28
-rw-r--r--jdsample.c23
-rw-r--r--jpegint.h14
-rw-r--r--jpeglib.h4
-rw-r--r--jversion.h18
-rw-r--r--libjpeg.txt58
-rwxr-xr-xwin/jpeg62-memsrcdst.def1
-rwxr-xr-xwin/jpeg62.def1
-rw-r--r--win/jpeg7.def1
-rw-r--r--win/jpeg8.def1
-rw-r--r--wrppm.c16
-rw-r--r--wrppm.h26
22 files changed, 485 insertions, 225 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 0be768e8..07d510dd 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -357,9 +357,9 @@ if(WITH_12BIT)
set(MD5_PPM_420M_ISLOW_1_4 35fd59d866e44659edfa3c18db2a3edb)
set(MD5_PPM_420M_ISLOW_1_8 ccaed48ac0aedefda5d4abe4013f4ad7)
set(MD5_PPM_420_ISLOW_SKIP15_31 86664cd9dc956536409e44e244d20a97)
- set(MD5_PPM_420_ISLOW_PROG_STRIP71_132 a5c3706bb2e59bd01786b1181f67f97c)
+ set(MD5_PPM_420_ISLOW_PROG_CROP62x62_71_71 452a21656115a163029cfba5c04fa76a)
set(MD5_PPM_444_ISLOW_SKIP1_6 ef63901f71ef7a75cd78253fc0914f84)
- set(MD5_PPM_444_ISLOW_PROG_STRIP13_110 6d228f8d05381d8639f3d078b91b2ee0)
+ set(MD5_PPM_444_ISLOW_PROG_CROP98x98_13_13 15b173fb5872d9575572fbcc1b05956f)
set(MD5_JPEG_CROP cdb35ff4b4519392690ea040c56ea99c)
else()
set(TESTORIG testorig.jpg)
@@ -411,11 +411,11 @@ else()
set(MD5_BMP_420M_ISLOW_565D d1be3a3339166255e76fa50a0d70d73e)
set(MD5_PPM_420_ISLOW_SKIP15_31 c4c65c1e43d7275cd50328a61e6534f0)
set(MD5_PPM_420_ISLOW_ARI_SKIP16_139 087c6b123db16ac00cb88c5b590bb74a)
- set(MD5_PPM_420_ISLOW_PROG_STRIP71_132 a7f2ba6ea335f03549888bed66a89fae)
- set(MD5_PPM_420_ISLOW_ARI_STRIP4_56 0e5e44a39b94817917a1bac72903246b)
+ set(MD5_PPM_420_ISLOW_PROG_CROP62x62_71_71 26eb36ccc7d1f0cb80cdabb0ac8b5d99)
+ set(MD5_PPM_420_ISLOW_ARI_CROP53x53_4_4 886c6775af22370257122f8b16207e6d)
set(MD5_PPM_444_ISLOW_SKIP1_6 5606f86874cf26b8fcee1117a0a436a6)
- set(MD5_PPM_444_ISLOW_PROG_STRIP13_110 40b5d9742558dca6229d7332fc2dda07)
- set(MD5_PPM_444_ISLOW_ARI_STRIP0_36 9aceb5b9449c900b892a1d2fe39351b4)
+ set(MD5_PPM_444_ISLOW_PROG_CROP98x98_13_13 db87dc7ce26bcdc7a6b56239ce2b9d6c)
+ set(MD5_PPM_444_ISLOW_ARI_CROP37x37_0_0 cb57b32bd6d03e35432362f7bf184b6d)
set(MD5_JPEG_CROP b4197f377e621c4e9b1d20471432610d)
endif()
@@ -794,25 +794,25 @@ foreach(libtype ${TEST_LIBTYPES})
endif()
# Context rows: Yes Intra-iMCU row: No iMCU row prefetch: No ENT: prog huff
add_test(cjpeg${suffix}-420-islow-prog
- ${dir}cjpeg${suffix} -dct int -prog -outfile testout_420_islow_prog.jpg
- ${CMAKE_SOURCE_DIR}/testimages/testorig.ppm)
- add_test(djpeg${suffix}-420-islow-prog-strip71_132
- ${dir}djpeg${suffix} -dct int -strip 71,132 -ppm
- -outfile testout_420_islow_strip71,132.ppm testout_420_islow_prog.jpg)
- add_test(djpeg${suffix}-420-islow-prog-strip71_132-cmp
- ${CMAKE_COMMAND} -DMD5=${MD5_PPM_420_ISLOW_PROG_STRIP71_132}
- -DFILE=testout_420_islow_strip71,132.ppm
- -P ${CMAKE_SOURCE_DIR}/cmakescripts/md5cmp.cmake)
+ ${dir}cjpeg${suffix} -dct int -prog
+ -outfile testout_420_islow_prog.jpg ${TESTIMAGES}/testorig.ppm)
+ add_test(djpeg${suffix}-420-islow-prog-crop62x62_71_71
+ ${dir}djpeg${suffix} -dct int -crop 62x62+71+71 -ppm
+ -outfile testout_420_islow_prog_crop62x62,71,71.ppm
+ testout_420_islow_prog.jpg)
+ add_test(djpeg${suffix}-420-islow-prog-crop62x62_71_71-cmp
+ ${MD5CMP} ${MD5_PPM_420_ISLOW_PROG_CROP62x62_71_71}
+ testout_420_islow_prog_crop62x62,71,71.ppm)
+
# Context rows: Yes Intra-iMCU row: No iMCU row prefetch: No ENT: arith
if(WITH_ARITH_DEC)
- add_test(djpeg${suffix}-420-islow-ari-strip4_56
- ${dir}djpeg${suffix} -dct int -strip 4,56 -ppm
- -outfile testout_420_islow_ari_strip4,56.ppm
- ${CMAKE_SOURCE_DIR}/testimages/testimgari.jpg)
- add_test(djpeg${suffix}-420-islow-ari-strip4_56-cmp
- ${CMAKE_COMMAND} -DMD5=${MD5_PPM_420_ISLOW_ARI_STRIP4_56}
- -DFILE=testout_420_islow_ari_strip4,56.ppm
- -P ${CMAKE_SOURCE_DIR}/cmakescripts/md5cmp.cmake)
+ add_test(djpeg${suffix}-420-islow-ari-crop53x53_4_4
+ ${dir}djpeg${suffix} -dct int -crop 53x53+4+4 -ppm
+ -outfile testout_420_islow_ari_crop53x53,4,4.ppm
+ ${TESTIMAGES}/testimgari.jpg)
+ add_test(djpeg${suffix}-420-islow-ari-crop53x53_4_4-cmp
+ ${MD5CMP} ${MD5_PPM_420_ISLOW_ARI_CROP53x53_4_4}
+ testout_420_islow_ari_crop53x53,4,4.ppm)
endif()
# Context rows: No Intra-iMCU row: Yes ENT: huff
add_test(cjpeg${suffix}-444-islow
@@ -828,15 +828,15 @@ foreach(libtype ${TEST_LIBTYPES})
# Context rows: No Intra-iMCU row: No ENT: prog huff
add_test(cjpeg${suffix}-444-islow-prog
${dir}cjpeg${suffix} -dct int -prog -sample 1x1
- -outfile testout_444_islow_prog.jpg
- ${CMAKE_SOURCE_DIR}/testimages/testorig.ppm)
- add_test(djpeg${suffix}-444-islow-prog-strip13_110
- ${dir}djpeg${suffix} -dct int -strip 13,110 -ppm
- -outfile testout_444_islow_prog_strip13,110.ppm testout_444_islow_prog.jpg)
- add_test(djpeg${suffix}-444-islow-prog_strip13_110-cmp
- ${CMAKE_COMMAND} -DMD5=${MD5_PPM_444_ISLOW_PROG_STRIP13_110}
- -DFILE=testout_444_islow_prog_strip13,110.ppm
- -P ${CMAKE_SOURCE_DIR}/cmakescripts/md5cmp.cmake)
+ -outfile testout_444_islow_prog.jpg ${TESTIMAGES}/testorig.ppm)
+ add_test(djpeg${suffix}-444-islow-prog-crop98x98_13_13
+ ${dir}djpeg${suffix} -dct int -crop 98x98+13+13 -ppm
+ -outfile testout_444_islow_prog_crop98x98,13,13.ppm
+ testout_444_islow_prog.jpg)
+ add_test(djpeg${suffix}-444-islow-prog_crop98x98_13_13-cmp
+ ${MD5CMP} ${MD5_PPM_444_ISLOW_PROG_CROP98x98_13_13}
+ testout_444_islow_prog_crop98x98,13,13.ppm)
+
# Context rows: No Intra-iMCU row: No ENT: arith
if(WITH_ARITH_ENC)
add_test(cjpeg${suffix}-444-islow-ari
@@ -844,14 +844,13 @@ foreach(libtype ${TEST_LIBTYPES})
-outfile testout_444_islow_ari.jpg
${CMAKE_SOURCE_DIR}/testimages/testorig.ppm)
if(WITH_ARITH_DEC)
- add_test(djpeg${suffix}-444-islow-ari-strip0_36
- ${dir}djpeg${suffix} -dct int -strip 0,36 -ppm
- -outfile testout_444_islow_ari_strip0,36.ppm
+ add_test(djpeg${suffix}-444-islow-ari-crop37x37_0_0
+ ${dir}djpeg${suffix} -dct int -crop 37x37+0+0 -ppm
+ -outfile testout_444_islow_ari_crop37x37,0,0.ppm
testout_444_islow_ari.jpg)
- add_test(djpeg${suffix}-444-islow-ari-strip0_36-cmp
- ${CMAKE_COMMAND} -DMD5=${MD5_PPM_444_ISLOW_ARI_STRIP0_36}
- -DFILE=testout_444_islow_ari_strip0,36.ppm
- -P ${CMAKE_SOURCE_DIR}/cmakescripts/md5cmp.cmake)
+ add_test(djpeg${suffix}-444-islow-ari-crop37x37_0_0-cmp
+ ${MD5CMP} ${MD5_PPM_444_ISLOW_ARI_CROP37x37_0_0}
+ testout_444_islow_ari_crop37x37,0,0.ppm)
endif()
endif()
diff --git a/Makefile.am b/Makefile.am
index 17cda345..3481ad62 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -168,7 +168,8 @@ dist_example_DATA = example.c
EXTRA_DIST = win release $(DOCS) testimages CMakeLists.txt \
sharedlib/CMakeLists.txt cmakescripts libjpeg.map.in doc doxygen.config \
doxygen-extra.css jccolext.c jdcolext.c jdcol565.c jdmrgext.c jdmrg565.c \
- jstdhuff.c LICENSE.txt
+ jstdhuff.c jdcoefct.h jdmainct.h jdmaster.h jdsample.h wrppm.h \
+ md5/CMakeLists.txt
dist-hook:
rm -rf `find $(distdir) -name .svn`
@@ -211,9 +212,9 @@ MD5_PPM_420M_ISLOW_3_8 = 343d19015531b7bbe746124127244fa8
MD5_PPM_420M_ISLOW_1_4 = 35fd59d866e44659edfa3c18db2a3edb
MD5_PPM_420M_ISLOW_1_8 = ccaed48ac0aedefda5d4abe4013f4ad7
MD5_PPM_420_ISLOW_SKIP15_31 = 86664cd9dc956536409e44e244d20a97
-MD5_PPM_420_ISLOW_PROG_STRIP71_132 = a5c3706bb2e59bd01786b1181f67f97c
+MD5_PPM_420_ISLOW_PROG_CROP62x62_71_71 = 452a21656115a163029cfba5c04fa76a
MD5_PPM_444_ISLOW_SKIP1_6 = ef63901f71ef7a75cd78253fc0914f84
-MD5_PPM_444_ISLOW_PROG_STRIP13_110 = 6d228f8d05381d8639f3d078b91b2ee0
+MD5_PPM_444_ISLOW_PROG_CROP98x98_13_13 = 15b173fb5872d9575572fbcc1b05956f
MD5_JPEG_CROP = cdb35ff4b4519392690ea040c56ea99c
else
@@ -268,11 +269,11 @@ MD5_BMP_420M_ISLOW_565 = 8dc0185245353cfa32ad97027342216f
MD5_BMP_420M_ISLOW_565D =d1be3a3339166255e76fa50a0d70d73e
MD5_PPM_420_ISLOW_SKIP15_31 = c4c65c1e43d7275cd50328a61e6534f0
MD5_PPM_420_ISLOW_ARI_SKIP16_139 = 087c6b123db16ac00cb88c5b590bb74a
-MD5_PPM_420_ISLOW_PROG_STRIP71_132 = a7f2ba6ea335f03549888bed66a89fae
-MD5_PPM_420_ISLOW_ARI_STRIP4_56 = 0e5e44a39b94817917a1bac72903246b
+MD5_PPM_420_ISLOW_PROG_CROP62x62_71_71 = 26eb36ccc7d1f0cb80cdabb0ac8b5d99
+MD5_PPM_420_ISLOW_ARI_CROP53x53_4_4 = 886c6775af22370257122f8b16207e6d
MD5_PPM_444_ISLOW_SKIP1_6 = 5606f86874cf26b8fcee1117a0a436a6
-MD5_PPM_444_ISLOW_PROG_STRIP13_110 = 40b5d9742558dca6229d7332fc2dda07
-MD5_PPM_444_ISLOW_ARI_STRIP0_36 = 9aceb5b9449c900b892a1d2fe39351b4
+MD5_PPM_444_ISLOW_PROG_CROP98x98_13_13 = db87dc7ce26bcdc7a6b56239ce2b9d6c
+MD5_PPM_444_ISLOW_ARI_CROP37x37_0_0 = cb57b32bd6d03e35432362f7bf184b6d
MD5_JPEG_CROP = b4197f377e621c4e9b1d20471432610d
endif
@@ -599,14 +600,14 @@ if WITH_ARITH_DEC
endif
# Context rows: Yes Intra-iMCU row: No iMCU row prefetch: No ENT: prog huff
./cjpeg -dct int -prog -outfile testout_420_islow_prog.jpg $(srcdir)/testimages/testorig.ppm
- ./djpeg -dct int -strip 71,132 -ppm -outfile testout_420_islow_prog_strip71,132.ppm testout_420_islow_prog.jpg
- md5/md5cmp $(MD5_PPM_420_ISLOW_PROG_STRIP71_132) testout_420_islow_prog_strip71,132.ppm
- rm testout_420_islow_prog_strip71,132.ppm testout_420_islow_prog.jpg
+ ./djpeg -dct int -crop 62x62+71+71 -ppm -outfile testout_420_islow_prog_crop62x62,71,71.ppm testout_420_islow_prog.jpg
+ md5/md5cmp $(MD5_PPM_420_ISLOW_PROG_CROP62x62_71_71) testout_420_islow_prog_crop62x62,71,71.ppm
+ rm -f testout_420_islow_prog_crop62x62,71,71.ppm testout_420_islow_prog.jpg
# Context rows: Yes Intra-iMCU row: No iMCU row prefetch: No ENT: arith
if WITH_ARITH_DEC
- ./djpeg -dct int -strip 4,56 -ppm -outfile testout_420_islow_ari_strip4,56.ppm $(srcdir)/testimages/testimgari.jpg
- md5/md5cmp $(MD5_PPM_420_ISLOW_ARI_STRIP4_56) testout_420_islow_ari_strip4,56.ppm
- rm testout_420_islow_ari_strip4,56.ppm
+ ./djpeg -dct int -crop 53x53+4+4 -ppm -outfile testout_420_islow_ari_crop53x53,4,4.ppm $(srcdir)/testimages/testimgari.jpg
+ md5/md5cmp $(MD5_PPM_420_ISLOW_ARI_CROP53x53_4_4) testout_420_islow_ari_crop53x53,4,4.ppm
+ rm -f testout_420_islow_ari_crop53x53,4,4.ppm
endif
# Context rows: No Intra-iMCU row: Yes ENT: huff
./cjpeg -dct int -sample 1x1 -outfile testout_444_islow.jpg $(srcdir)/testimages/testorig.ppm
@@ -615,16 +616,16 @@ endif
rm testout_444_islow_skip1,6.ppm testout_444_islow.jpg
# Context rows: No Intra-iMCU row: No ENT: prog huff
./cjpeg -dct int -prog -sample 1x1 -outfile testout_444_islow_prog.jpg $(srcdir)/testimages/testorig.ppm
- ./djpeg -dct int -strip 13,110 -ppm -outfile testout_444_islow_prog_strip13,110.ppm testout_444_islow_prog.jpg
- md5/md5cmp $(MD5_PPM_444_ISLOW_PROG_STRIP13_110) testout_444_islow_prog_strip13,110.ppm
- rm testout_444_islow_prog_strip13,110.ppm testout_444_islow_prog.jpg
+ ./djpeg -dct int -crop 98x98+13+13 -ppm -outfile testout_444_islow_prog_crop98x98,13,13.ppm testout_444_islow_prog.jpg
+ md5/md5cmp $(MD5_PPM_444_ISLOW_PROG_CROP98x98_13_13) testout_444_islow_prog_crop98x98,13,13.ppm
+ rm -f testout_444_islow_prog_crop98x98,13,13.ppm testout_444_islow_prog.jpg
# Context rows: No Intra-iMCU row: No ENT: arith
if WITH_ARITH_ENC
./cjpeg -dct int -arithmetic -sample 1x1 -outfile testout_444_islow_ari.jpg $(srcdir)/testimages/testorig.ppm
if WITH_ARITH_DEC
- ./djpeg -dct int -strip 0,36 -ppm -outfile testout_444_islow_ari_strip0,36.ppm testout_444_islow_ari.jpg
- md5/md5cmp $(MD5_PPM_444_ISLOW_ARI_STRIP0_36) testout_444_islow_ari_strip0,36.ppm
- rm testout_444_islow_ari_strip0,36.ppm
+ ./djpeg -dct int -crop 37x37+0+0 -ppm -outfile testout_444_islow_ari_crop37x37,0,0.ppm testout_444_islow_ari.jpg
+ md5/md5cmp $(MD5_PPM_444_ISLOW_ARI_CROP37x37_0_0) testout_444_islow_ari_crop37x37,0,0.ppm
+ rm -f testout_444_islow_ari_crop37x37,0,0.ppm
endif
rm testout_444_islow_ari.jpg
endif
diff --git a/README.android b/README.android
index b83c4d79..6d0c0879 100644
--- a/README.android
+++ b/README.android
@@ -13,15 +13,7 @@ to add some multi-platform flexibility to the INLINE and SIZEOF_SIZE_T macros.
(2) Partial decoding optimizations
These have been cherry picked from upstream and will be included in the 1.5
-release. The cherry picked commits are:
-90c92ed5bf98bda381fcc369f0da46837dbb8894
-fc235cfdabbcd1c915fa3a87a56d73727da2eaeb
-9bafc6a7ffa62ed7109314cbb66085075cd1c334
-3fb56e969c890e6aa7b044eea7e24751ab6f4e97
-e67a7e37deb26db5ac7da420560d22e1ca7ea4b4
-f8a1775eab51fb0a83e82343d2eae8cf52b16124
-15884f48eb1a4acd9c6c24291db974c596e71934
-ac30a1bf12751bd82e56158eb9456a28d9c086f3
+release.
(3) simd/jsimdext.inc
diff --git a/djpeg.1 b/djpeg.1
index 17296abd..71cbd02c 100644
--- a/djpeg.1
+++ b/djpeg.1
@@ -1,4 +1,4 @@
-.TH DJPEG 1 "26 June 2015"
+.TH DJPEG 1 "18 February 2016"
.SH NAME
djpeg \- decompress a JPEG file to an image file
.SH SYNOPSIS
@@ -195,13 +195,15 @@ Load input file into memory before decompressing. This feature was implemented
mainly as a way of testing the in-memory source manager (jpeg_mem_src().)
.TP
.BI \-skip " Y0,Y1"
-Decode all rows of the JPEG image except those between Y0 and Y1 (inclusive.)
-Note that if decompression scaling is being used, Y0 and Y1 are relative to the
-scaled image dimensions.
+Decompress all rows of the JPEG image except those between Y0 and Y1
+(inclusive.) Note that if decompression scaling is being used, then Y0 and Y1
+are relative to the scaled image dimensions.
.TP
-.BI \-strip " Y0,Y1"
-Decode only the rows of the JPEG image between Y0 and Y1 (inclusive.) Note
-that if decompression scaling is being used, Y0 and Y1 are relative to the
+.BI \-crop " WxH+X+Y"
+Decompress only a rectangular subregion of the image, starting at point X,Y
+with width W and height H. If necessary, X will be shifted left to the nearest
+iMCU boundary, and the width will be increased accordingly. Note that if
+decompression scaling is being used, then X, Y, W, and H are relative to the
scaled image dimensions.
.TP
.B \-verbose
diff --git a/djpeg.c b/djpeg.c
index d41f94f1..4162ffda 100644
--- a/djpeg.c
+++ b/djpeg.c
@@ -4,7 +4,7 @@
* This file was part of the Independent JPEG Group's software:
* Copyright (C) 1991-1997, Thomas G. Lane.
* libjpeg-turbo Modifications:
- * Copyright (C) 2010-2011, 2013-2015, D. R. Commander.
+ * Copyright (C) 2010-2011, 2013-2016, D. R. Commander.
* Copyright (C) 2015, Google, Inc.
* For conditions of distribution and use, see the accompanying README file.
*
@@ -29,6 +29,7 @@
#include "cdjpeg.h" /* Common decls for cjpeg/djpeg applications */
#include "jversion.h" /* for version message */
#include "jconfigint.h"
+#include "wrppm.h"
#include <ctype.h> /* to declare isprint() */
@@ -86,11 +87,12 @@ static IMAGE_FORMATS requested_fmt;
*/
-static const char * progname; /* program name for error messages */
-static char * outfilename; /* for -outfile switch */
-boolean memsrc; /* for -memsrc switch */
-boolean strip, skip;
-JDIMENSION startY, endY;
+static const char *progname; /* program name for error messages */
+static char *outfilename; /* for -outfile switch */
+boolean memsrc; /* for -memsrc switch */
+boolean skip, crop;
+JDIMENSION skip_start, skip_end;
+JDIMENSION crop_x, crop_y, crop_width, crop_height;
#define INPUT_BUF_SIZE 4096
@@ -167,8 +169,8 @@ usage (void)
fprintf(stderr, " -memsrc Load input file into memory before decompressing\n");
#endif
- fprintf(stderr, " -skip Y0,Y1 Decode all rows except those between Y0 and Y1 (inclusive)\n");
- fprintf(stderr, " -strip Y0,Y1 Decode only rows between Y0 and Y1 (inclusive)\n");
+ fprintf(stderr, " -skip Y0,Y1 Decompress all rows except those between Y0 and Y1 (inclusive)\n");
+ fprintf(stderr, " -crop WxH+X+Y Decompress only a rectangular subregion of the image\n");
fprintf(stderr, " -verbose or -debug Emit debug output\n");
fprintf(stderr, " -version Print version information and exit\n");
exit(EXIT_FAILURE);
@@ -194,8 +196,8 @@ parse_switches (j_decompress_ptr cinfo, int argc, char **argv,
requested_fmt = DEFAULT_FMT; /* set default output file format */
outfilename = NULL;
memsrc = FALSE;
- strip = FALSE;
skip = FALSE;
+ crop = FALSE;
cinfo->err->trace_level = 0;
/* Scan command line options, adjust parameters */
@@ -376,20 +378,23 @@ parse_switches (j_decompress_ptr cinfo, int argc, char **argv,
&cinfo->scale_num, &cinfo->scale_denom) != 2)
usage();
- } else if (keymatch(arg, "strip", 2)) {
+ } else if (keymatch(arg, "skip", 2)) {
if (++argn >= argc)
usage();
- if (sscanf(argv[argn], "%d,%d", &startY, &endY) != 2 || startY > endY)
+ if (sscanf(argv[argn], "%u,%u", &skip_start, &skip_end) != 2 ||
+ skip_start > skip_end)
usage();
- strip = TRUE;
-
+ skip = TRUE;
- } else if (keymatch(arg, "skip", 2)) {
+ } else if (keymatch(arg, "crop", 2)) {
+ char c;
if (++argn >= argc)
usage();
- if (sscanf(argv[argn], "%d,%d", &startY, &endY) != 2 || startY > endY)
+ if (sscanf(argv[argn], "%u%c%u+%u+%u", &crop_width, &c, &crop_height,
+ &crop_x, &crop_y) != 5 ||
+ (c != 'X' && c != 'x') || crop_width < 1 || crop_height < 1)
usage();
- skip = TRUE;
+ crop = TRUE;
} else if (keymatch(arg, "targa", 1)) {
/* Targa output format. */
@@ -656,54 +661,78 @@ main (int argc, char **argv)
/* Start decompressor */
(void) jpeg_start_decompress(&cinfo);
- /* Strip decode */
- if (strip || skip) {
+ /* Skip rows */
+ if (skip) {
JDIMENSION tmp;
- /* Check for valid endY. We cannot check this value until after
+ /* Check for valid skip_end. We cannot check this value until after
* jpeg_start_decompress() is called. Note that we have already verified
- * that startY <= endY.
+ * that skip_start <= skip_end.
*/
- if (endY > cinfo.output_height - 1) {
- fprintf(stderr, "%s: strip %d-%d exceeds image height %d\n", progname,
- startY, endY, cinfo.output_height);
+ if (skip_end > cinfo.output_height - 1) {
+ fprintf(stderr, "%s: skip region exceeds image height %d\n", progname,
+ cinfo.output_height);
exit(EXIT_FAILURE);
}
/* Write output file header. This is a hack to ensure that the destination
- * manager creates an image of the proper size for the partial decode.
+ * manager creates an output image of the proper size.
*/
tmp = cinfo.output_height;
- cinfo.output_height = endY - startY + 1;
- if (skip)
- cinfo.output_height = tmp - cinfo.output_height;
+ cinfo.output_height -= (skip_end - skip_start + 1);
(*dest_mgr->start_output) (&cinfo, dest_mgr);
cinfo.output_height = tmp;
/* Process data */
- if (skip) {
- while (cinfo.output_scanline < startY) {
- num_scanlines = jpeg_read_scanlines(&cinfo, dest_mgr->buffer,
- dest_mgr->buffer_height);
- (*dest_mgr->put_pixel_rows) (&cinfo, dest_mgr, num_scanlines);
- }
- jpeg_skip_scanlines(&cinfo, endY - startY + 1);
- while (cinfo.output_scanline < cinfo.output_height) {
- num_scanlines = jpeg_read_scanlines(&cinfo, dest_mgr->buffer,
- dest_mgr->buffer_height);
- (*dest_mgr->put_pixel_rows) (&cinfo, dest_mgr, num_scanlines);
- }
- } else {
- jpeg_skip_scanlines(&cinfo, startY);
- while (cinfo.output_scanline <= endY) {
- num_scanlines = jpeg_read_scanlines(&cinfo, dest_mgr->buffer,
- dest_mgr->buffer_height);
- (*dest_mgr->put_pixel_rows) (&cinfo, dest_mgr, num_scanlines);
- }
- jpeg_skip_scanlines(&cinfo, cinfo.output_height - endY + 1);
+ while (cinfo.output_scanline < skip_start) {
+ num_scanlines = jpeg_read_scanlines(&cinfo, dest_mgr->buffer,
+ dest_mgr->buffer_height);
+ (*dest_mgr->put_pixel_rows) (&cinfo, dest_mgr, num_scanlines);
+ }
+ jpeg_skip_scanlines(&cinfo, skip_end - skip_start + 1);
+ while (cinfo.output_scanline < cinfo.output_height) {
+ num_scanlines = jpeg_read_scanlines(&cinfo, dest_mgr->buffer,
+ dest_mgr->buffer_height);
+ (*dest_mgr->put_pixel_rows) (&cinfo, dest_mgr, num_scanlines);
+ }
+
+ /* Decompress a subregion */
+ } else if (crop) {
+ JDIMENSION tmp;
+
+ /* Check for valid crop dimensions. We cannot check these values until
+ * after jpeg_start_decompress() is called.
+ */
+ if (crop_x + crop_width > cinfo.output_width ||
+ crop_y + crop_height > cinfo.output_height) {
+ fprintf(stderr, "%s: crop dimensions exceed image dimensions %d x %d\n",
+ progname, cinfo.output_width, cinfo.output_height);
+ exit(EXIT_FAILURE);
+ }
+
+ jpeg_crop_scanline(&cinfo, &crop_x, &crop_width);
+ ((ppm_dest_ptr) dest_mgr)->buffer_width = cinfo.output_width *
+ cinfo.out_color_components *
+ sizeof(JSAMPLE);
+
+ /* Write output file header. This is a hack to ensure that the destination
+ * manager creates an output image of the proper size.
+ */
+ tmp = cinfo.output_height;
+ cinfo.output_height = crop_height;
+ (*dest_mgr->start_output) (&cinfo, dest_mgr);
+ cinfo.output_height = tmp;
+
+ /* Process data */
+ jpeg_skip_scanlines(&cinfo, crop_y);
+ while (cinfo.output_scanline < crop_y + crop_height) {
+ num_scanlines = jpeg_read_scanlines(&cinfo, dest_mgr->buffer,
+ dest_mgr->buffer_height);
+ (*dest_mgr->put_pixel_rows) (&cinfo, dest_mgr, num_scanlines);
}
+ jpeg_skip_scanlines(&cinfo, cinfo.output_height - crop_y - crop_height);
- /* Normal full image decode */
+ /* Normal full-image decompress */
} else {
/* Write output file header */
(*dest_mgr->start_output) (&cinfo, dest_mgr);
diff --git a/jdapimin.c b/jdapimin.c
index fc8898f8..f80a1466 100644
--- a/jdapimin.c
+++ b/jdapimin.c
@@ -3,9 +3,10 @@
*
* This file was part of the Independent JPEG Group's software:
* Copyright (C) 1994-1998, Thomas G. Lane.
- * It was modified by The libjpeg-turbo Project to include only code relevant
- * to libjpeg-turbo.
- * For conditions of distribution and use, see the accompanying README file.
+ * libjpeg-turbo Modifications:
+ * Copyright (C) 2016, D. R. Commander.
+ * For conditions of distribution and use, see the accompanying README.ijg
+ * file.
*
* This file contains application interface code for the decompression half
* of the JPEG library. These are the "minimum" API routines that may be
@@ -21,6 +22,7 @@
#define JPEG_INTERNALS
#include "jinclude.h"
#include "jpeglib.h"
+#include "jdmaster.h"
/*
@@ -82,6 +84,14 @@ jpeg_CreateDecompress (j_decompress_ptr cinfo, int version, size_t structsize)
/* OK, I'm ready */
cinfo->global_state = DSTATE_START;
+
+ /* The master struct is used to store extension parameters, so we allocate it
+ * here.
+ */
+ cinfo->master = (struct jpeg_decomp_master *)
+ (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
+ sizeof(my_decomp_master));
+ MEMZERO(cinfo->master, sizeof(my_decomp_master));
}
diff --git a/jdapistd.c b/jdapistd.c
index 18f9f6ce..76cb2def 100644
--- a/jdapistd.c
+++ b/jdapistd.c
@@ -139,6 +139,110 @@ output_pass_setup (j_decompress_ptr cinfo)
/*
+ * Enable partial scanline decompression
+ *
+ * Must be called after jpeg_start_decompress() and before any calls to
+ * jpeg_read_scanlines() or jpeg_skip_scanlines().
+ *
+ * Refer to libjpeg.txt for more information.
+ */
+
+GLOBAL(void)
+jpeg_crop_scanline (j_decompress_ptr cinfo, JDIMENSION *xoffset,
+ JDIMENSION *width)
+{
+ int ci, align, orig_downsampled_width;
+ JDIMENSION input_xoffset;
+ boolean reinit_upsampler = FALSE;
+ jpeg_component_info *compptr;
+
+ if (cinfo->global_state != DSTATE_SCANNING || cinfo->output_scanline != 0)
+ ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
+
+ if (!xoffset || !width)
+ ERREXIT(cinfo, JERR_BAD_CROP_SPEC);
+
+ /* xoffset and width must fall within the output image dimensions. */
+ if (*width == 0 || *xoffset + *width > cinfo->output_width)
+ ERREXIT(cinfo, JERR_WIDTH_OVERFLOW);
+
+ /* No need to do anything if the caller wants the entire width. */
+ if (*width == cinfo->output_width)
+ return;
+
+ /* Ensuring the proper alignment of xoffset is tricky. At minimum, it
+ * must align with an MCU boundary, because:
+ *
+ * (1) The IDCT is performed in blocks, and it is not feasible to modify
+ * the algorithm so that it can transform partial blocks.
+ * (2) Because of the SIMD extensions, any input buffer passed to the
+ * upsampling and color conversion routines must be aligned to the
+ * SIMD word size (for instance, 128-bit in the case of SSE2.) The
+ * easiest way to accomplish this without copying data is to ensure
+ * that upsampling and color conversion begin at the start of the
+ * first MCU column that will be inverse transformed.
+ *
+ * In practice, we actually impose a stricter alignment requirement. We
+ * require that xoffset be a multiple of the maximum MCU column width of all
+ * of the components (the "iMCU column width.") This is to simplify the
+ * single-pass decompression case, allowing us to use the same MCU column
+ * width for all of the components.
+ */
+ align = cinfo->min_DCT_scaled_size * cinfo->max_h_samp_factor;
+
+ /* Adjust xoffset to the nearest iMCU boundary <= the requested value */
+ input_xoffset = *xoffset;
+ *xoffset = (input_xoffset / align) * align;
+
+ /* Adjust the width so that the right edge of the output image is as
+ * requested (only the left edge is altered.) It is important that calling
+ * programs check this value after this function returns, so that they can
+ * allocate an output buffer with the appropriate size.
+ */
+ *width = *width + input_xoffset - *xoffset;
+ cinfo->output_width = *width;
+
+ /* Set the first and last iMCU columns that we must decompress. These values
+ * will be used in single-scan decompressions.
+ */
+ cinfo->master->first_iMCU_col =
+ (JDIMENSION) (long) (*xoffset) / (long) align;
+ cinfo->master->last_iMCU_col =
+ (JDIMENSION) jdiv_round_up((long) (*xoffset + cinfo->output_width),
+ (long) align) - 1;
+
+ for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
+ ci++, compptr++) {
+ /* Set downsampled_width to the new output width. */
+ orig_downsampled_width = compptr->downsampled_width;
+ compptr->downsampled_width =
+ (JDIMENSION) jdiv_round_up((long) (cinfo->output_width *
+ compptr->h_samp_factor),
+ (long) cinfo->max_h_samp_factor);
+ if (compptr->downsampled_width < 2 && orig_downsampled_width >= 2)
+ reinit_upsampler = TRUE;
+
+ /* Set the first and last iMCU columns that we must decompress. These
+ * values will be used in multi-scan decompressions.
+ */
+ cinfo->master->first_MCU_col[ci] =
+ (JDIMENSION) (long) (*xoffset * compptr->h_samp_factor) /
+ (long) align;
+ cinfo->master->last_MCU_col[ci] =
+ (JDIMENSION) jdiv_round_up((long) ((*xoffset + cinfo->output_width) *
+ compptr->h_samp_factor),
+ (long) align) - 1;
+ }
+
+ if (reinit_upsampler) {
+ cinfo->master->jinit_upsampler_no_alloc = TRUE;
+ jinit_upsampler(cinfo);
+ cinfo->master->jinit_upsampler_no_alloc = FALSE;
+ }
+}
+
+
+/*
* Read some scanlines of data from the JPEG decompressor.
*
* The return value will be the number of lines actually read.
diff --git a/jdcoefct.c b/jdcoefct.c
index 17a97b1b..72f69d9c 100644
--- a/jdcoefct.c
+++ b/jdcoefct.c
@@ -5,8 +5,10 @@
* Copyright (C) 1994-1997, Thomas G. Lane.
* libjpeg-turbo Modifications:
* Copyright 2009 Pierre Ossman <ossman@cendio.se> for Cendio AB
- * Copyright (C) 2010, D. R. Commander.
- * For conditions of distribution and use, see the accompanying README file.
+ * Copyright (C) 2010, 2015-2016, D. R. Commander.
+ * Copyright (C) 2015, Google, Inc.
+ * For conditions of distribution and use, see the accompanying README.ijg
+ * file.
*
* This file contains the coefficient buffer controller for decompression.
* This controller is the top level of the JPEG decompressor proper.
@@ -106,38 +108,46 @@ decompress_onepass (j_decompress_ptr cinfo, JSAMPIMAGE output_buf)
coef->MCU_ctr = MCU_col_num;
return JPEG_SUSPENDED;
}
- /* Determine where data should go in output_buf and do the IDCT thing.
- * We skip dummy blocks at the right and bottom edges (but blkn gets
- * incremented past them!). Note the inner loop relies on having
- * allocated the MCU_buffer[] blocks sequentially.
+
+ /* Only perform the IDCT on blocks that are contained within the desired
+ * cropping region.
*/
- blkn = 0; /* index of current DCT block within MCU */
- for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
- compptr = cinfo->cur_comp_info[ci];
- /* Don't bother to IDCT an uninteresting component. */
- if (! compptr->component_needed) {
- blkn += compptr->MCU_blocks;
- continue;
- }
- inverse_DCT = cinfo->idct->inverse_DCT[compptr->component_index];
- useful_width = (MCU_col_num < last_MCU_col) ? compptr->MCU_width
- : compptr->last_col_width;
- output_ptr = output_buf[compptr->component_index] +
- yoffset * compptr->_DCT_scaled_size;
- start_col = MCU_col_num * compptr->MCU_sample_width;
- for (yindex = 0; yindex < compptr->MCU_height; yindex++) {
- if (cinfo->input_iMCU_row < last_iMCU_row ||
- yoffset+yindex < compptr->last_row_height) {
- output_col = start_col;
- for (xindex = 0; xindex < useful_width; xindex++) {
- (*inverse_DCT) (cinfo, compptr,
- (JCOEFPTR) coef->MCU_buffer[blkn+xindex],
- output_ptr, output_col);
- output_col += compptr->_DCT_scaled_size;
+ if (MCU_col_num >= cinfo->master->first_iMCU_col &&
+ MCU_col_num <= cinfo->master->last_iMCU_col) {
+ /* Determine where data should go in output_buf and do the IDCT thing.
+ * We skip dummy blocks at the right and bottom edges (but blkn gets
+ * incremented past them!). Note the inner loop relies on having
+ * allocated the MCU_buffer[] blocks sequentially.
+ */
+ blkn = 0; /* index of current DCT block within MCU */
+ for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
+ compptr = cinfo->cur_comp_info[ci];
+ /* Don't bother to IDCT an uninteresting component. */
+ if (! compptr->component_needed) {
+ blkn += compptr->MCU_blocks;
+ continue;
+ }
+ inverse_DCT = cinfo->idct->inverse_DCT[compptr->component_index];
+ useful_width = (MCU_col_num < last_MCU_col) ? compptr->MCU_width
+ : compptr->last_col_width;
+ output_ptr = output_buf[compptr->component_index] +
+ yoffset * compptr->_DCT_scaled_size;
+ start_col = (MCU_col_num - cinfo->master->first_iMCU_col) *
+ compptr->MCU_sample_width;
+ for (yindex = 0; yindex < compptr->MCU_height; yindex++) {
+ if (cinfo->input_iMCU_row < last_iMCU_row ||
+ yoffset+yindex < compptr->last_row_height) {
+ output_col = start_col;
+ for (xindex = 0; xindex < useful_width; xindex++) {
+ (*inverse_DCT) (cinfo, compptr,
+ (JCOEFPTR) coef->MCU_buffer[blkn+xindex],
+ output_ptr, output_col);
+ output_col += compptr->_DCT_scaled_size;
+ }
}
+ blkn += compptr->MCU_width;
+ output_ptr += compptr->_DCT_scaled_size;
}
- blkn += compptr->MCU_width;
- output_ptr += compptr->_DCT_scaled_size;
}
}
}
@@ -292,9 +302,10 @@ decompress_data (j_decompress_ptr cinfo, JSAMPIMAGE output_buf)
output_ptr = output_buf[ci];
/* Loop over all DCT blocks to be processed. */
for (block_row = 0; block_row < block_rows; block_row++) {
- buffer_ptr = buffer[block_row];
+ buffer_ptr = buffer[block_row] + cinfo->master->first_MCU_col[ci];
output_col = 0;
- for (block_num = 0; block_num < compptr->width_in_blocks; block_num++) {
+ for (block_num = cinfo->master->first_MCU_col[ci];
+ block_num <= cinfo->master->last_MCU_col[ci]; block_num++) {
(*inverse_DCT) (cinfo, compptr, (JCOEFPTR) buffer_ptr,
output_ptr, output_col);
buffer_ptr++;
@@ -480,7 +491,7 @@ decompress_smooth_data (j_decompress_ptr cinfo, JSAMPIMAGE output_buf)
output_ptr = output_buf[ci];
/* Loop over all DCT blocks to be processed. */
for (block_row = 0; block_row < block_rows; block_row++) {
- buffer_ptr = buffer[block_row];
+ buffer_ptr = buffer[block_row] + cinfo->master->first_MCU_col[ci];
if (first_row && block_row == 0)
prev_block_row = buffer_ptr;
else
@@ -497,7 +508,8 @@ decompress_smooth_data (j_decompress_ptr cinfo, JSAMPIMAGE output_buf)
DC7 = DC8 = DC9 = (int) next_block_row[0][0];
output_col = 0;
last_block_column = compptr->width_in_blocks - 1;
- for (block_num = 0; block_num <= last_block_column; block_num++) {
+ for (block_num = cinfo->master->first_MCU_col[ci];
+ block_num <= cinfo->master->last_MCU_col[ci]; block_num++) {
/* Fetch current DCT block into workspace so we can modify it. */
jcopy_block_row(buffer_ptr, (JBLOCKROW) workspace, (JDIMENSION) 1);
/* Update DC values */
diff --git a/jdinput.c b/jdinput.c
index 6f4ea7ba..25ed3f15 100644
--- a/jdinput.c
+++ b/jdinput.c
@@ -4,8 +4,10 @@
* This file was part of the Independent JPEG Group's software:
* Copyright (C) 1991-1997, Thomas G. Lane.
* libjpeg-turbo Modifications:
- * Copyright (C) 2010, D. R. Commander.
- * For conditions of distribution and use, see the accompanying README file.
+ * Copyright (C) 2010, 2016, D. R. Commander.
+ * Copyright (C) 2015, Google, Inc.
+ * For conditions of distribution and use, see the accompanying README.ijg
+ * file.
*
* This file contains input control logic for the JPEG decompressor.
* These routines are concerned with controlling the decompressor's input
@@ -104,6 +106,11 @@ initial_setup (j_decompress_ptr cinfo)
compptr->height_in_blocks = (JDIMENSION)
jdiv_round_up((long) cinfo->image_height * (long) compptr->v_samp_factor,
(long) (cinfo->max_v_samp_factor * DCTSIZE));
+ /* Set the first and last MCU columns to decompress from multi-scan images.
+ * By default, decompress all of the MCU columns.
+ */
+ cinfo->master->first_MCU_col[ci] = 0;
+ cinfo->master->last_MCU_col[ci] = compptr->width_in_blocks - 1;
/* downsampled_width and downsampled_height will also be overridden by
* jdmaster.c if we are doing full decompression. The transcoder library
* doesn't use these values, but the calling application might.
diff --git a/jdmaster.c b/jdmaster.c
index 604e2916..63237ae9 100644
--- a/jdmaster.c
+++ b/jdmaster.c
@@ -5,9 +5,11 @@
* Copyright (C) 1991-1997, Thomas G. Lane.
* Modified 2002-2009 by Guido Vollbeding.
* libjpeg-turbo Modifications:
- * Copyright (C) 2009-2011, D. R. Commander.
+ * Copyright (C) 2009-2011, 2016, D. R. Commander.
* Copyright (C) 2013, Linaro Limited.
- * For conditions of distribution and use, see the accompanying README file.
+ * Copyright (C) 2015, Google, Inc.
+ * For conditions of distribution and use, see the accompanying README.ijg
+ * file.
*
* This file contains master control logic for the JPEG decompressor.
* These routines are concerned with selecting the modules to be executed
@@ -19,25 +21,7 @@
#include "jinclude.h"
#include "jpeglib.h"
#include "jpegcomp.h"
-
-
-/* Private state */
-
-typedef struct {
- struct jpeg_decomp_master pub; /* public fields */
-
- int pass_number; /* # of passes completed */
-
- boolean using_merged_upsample; /* TRUE if using merged upsample/cconvert */
-
- /* Saved references to initialized quantizer modules,
- * in case we need to switch modes.
- */
- struct jpeg_color_quantizer * quantizer_1pass;
- struct jpeg_color_quantizer * quantizer_2pass;
-} my_decomp_master;
-
-typedef my_decomp_master * my_master_ptr;
+#include "jdmaster.h"
/*
@@ -578,6 +562,12 @@ master_selection (j_decompress_ptr cinfo)
/* Initialize input side of decompressor to consume first scan. */
(*cinfo->inputctl->start_input_pass) (cinfo);
+ /* Set the first and last iMCU columns to decompress from single-scan images.
+ * By default, decompress all of the iMCU columns.
+ */
+ cinfo->master->first_iMCU_col = 0;
+ cinfo->master->last_iMCU_col = cinfo->MCUs_per_row - 1;
+
#ifdef D_MULTISCAN_FILES_SUPPORTED
/* If jpeg_start_decompress will read the whole file, initialize
* progress monitoring appropriately. The input step is counted
@@ -722,16 +712,13 @@ jpeg_new_colormap (j_decompress_ptr cinfo)
GLOBAL(void)
jinit_master_decompress (j_decompress_ptr cinfo)
{
- my_master_ptr master;
+ my_master_ptr master = (my_master_ptr) cinfo->master;
- master = (my_master_ptr)
- (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
- sizeof(my_decomp_master));
- cinfo->master = (struct jpeg_decomp_master *) master;
master->pub.prepare_for_output_pass = prepare_for_output_pass;
master->pub.finish_output_pass = finish_output_pass;
master->pub.is_dummy_pass = FALSE;
+ master->pub.jinit_upsampler_no_alloc = FALSE;
master_selection(cinfo);
}
diff --git a/jdmaster.h b/jdmaster.h
new file mode 100644
index 00000000..76897e28
--- /dev/null
+++ b/jdmaster.h
@@ -0,0 +1,28 @@
+/*
+ * jdmaster.h
+ *
+ * This file was part of the Independent JPEG Group's software:
+ * Copyright (C) 1991-1995, Thomas G. Lane.
+ * For conditions of distribution and use, see the accompanying README.ijg
+ * file.
+ *
+ * This file contains the master control structure for the JPEG decompressor.
+ */
+
+/* Private state */
+
+typedef struct {
+ struct jpeg_decomp_master pub; /* public fields */
+
+ int pass_number; /* # of passes completed */
+
+ boolean using_merged_upsample; /* TRUE if using merged upsample/cconvert */
+
+ /* Saved references to initialized quantizer modules,
+ * in case we need to switch modes.
+ */
+ struct jpeg_color_quantizer *quantizer_1pass;
+ struct jpeg_color_quantizer *quantizer_2pass;
+} my_decomp_master;
+
+typedef my_decomp_master *my_master_ptr;
diff --git a/jdsample.c b/jdsample.c
index 5738c2fd..23c6c8fa 100644
--- a/jdsample.c
+++ b/jdsample.c
@@ -7,7 +7,9 @@
* Copyright 2009 Pierre Ossman <ossman@cendio.se> for Cendio AB
* Copyright (C) 2010, D. R. Commander.
* Copyright (C) 2014, MIPS Technologies, Inc., California
- * For conditions of distribution and use, see the accompanying README file.
+ * Copyright (C) 2015, Google, Inc.
+ * For conditions of distribution and use, see the accompanying README.ijg
+ * file.
*
* This file contains upsampling routines.
*
@@ -371,13 +373,16 @@ jinit_upsampler (j_decompress_ptr cinfo)
boolean need_buffer, do_fancy;
int h_in_group, v_in_group, h_out_group, v_out_group;
- upsample = (my_upsample_ptr)
- (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
- sizeof(my_upsampler));
- cinfo->upsample = (struct jpeg_upsampler *) upsample;
- upsample->pub.start_pass = start_pass_upsample;
- upsample->pub.upsample = sep_upsample;
- upsample->pub.need_context_rows = FALSE; /* until we find out differently */
+ if (!cinfo->master->jinit_upsampler_no_alloc) {
+ upsample = (my_upsample_ptr)
+ (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ sizeof(my_upsampler));
+ cinfo->upsample = (struct jpeg_upsampler *) upsample;
+ upsample->pub.start_pass = start_pass_upsample;
+ upsample->pub.upsample = sep_upsample;
+ upsample->pub.need_context_rows = FALSE; /* until we find out differently */
+ } else
+ upsample = (my_upsample_ptr) cinfo->upsample;
if (cinfo->CCIR601_sampling) /* this isn't supported */
ERREXIT(cinfo, JERR_CCIR601_NOTIMPL);
@@ -453,7 +458,7 @@ jinit_upsampler (j_decompress_ptr cinfo)
upsample->v_expand[ci] = (UINT8) (v_out_group / v_in_group);
} else
ERREXIT(cinfo, JERR_FRACT_SAMPLE_NOTIMPL);
- if (need_buffer) {
+ if (need_buffer && !cinfo->master->jinit_upsampler_no_alloc) {
upsample->color_buf[ci] = (*cinfo->mem->alloc_sarray)
((j_common_ptr) cinfo, JPOOL_IMAGE,
(JDIMENSION) jround_up((long) cinfo->output_width,
diff --git a/jpegint.h b/jpegint.h
index eaf51833..8ff5d44f 100644
--- a/jpegint.h
+++ b/jpegint.h
@@ -5,9 +5,10 @@
* Copyright (C) 1991-1997, Thomas G. Lane.
* Modified 1997-2009 by Guido Vollbeding.
* libjpeg-turbo Modifications:
- * It was modified by The libjpeg-turbo Project to include only code relevant
- * to libjpeg-turbo.
- * For conditions of distribution and use, see the accompanying README file.
+ * Copyright (C) 2015-2016, D. R. Commander
+ * Copyright (C) 2015, Google, Inc.
+ * For conditions of distribution and use, see the accompanying README.ijg
+ * file.
*
* This file provides common declarations for the various JPEG modules.
* These declarations are considered internal to the JPEG library; most
@@ -150,6 +151,13 @@ struct jpeg_decomp_master {
/* State variables made visible to other modules */
boolean is_dummy_pass; /* True during 1st pass for 2-pass quant */
+
+ /* Partial decompression variables */
+ JDIMENSION first_iMCU_col;
+ JDIMENSION last_iMCU_col;
+ JDIMENSION first_MCU_col[MAX_COMPS_IN_SCAN];
+ JDIMENSION last_MCU_col[MAX_COMPS_IN_SCAN];
+ boolean jinit_upsampler_no_alloc;
};
/* Input control module */
diff --git a/jpeglib.h b/jpeglib.h
index a41bec44..e2ca0ba3 100644
--- a/jpeglib.h
+++ b/jpeglib.h
@@ -5,7 +5,7 @@
* Copyright (C) 1991-1998, Thomas G. Lane.
* Modified 2002-2009 by Guido Vollbeding.
* libjpeg-turbo Modifications:
- * Copyright (C) 2009-2011, 2013-2014, D. R. Commander.
+ * Copyright (C) 2009-2011, 2013-2014, 2016, D. R. Commander.
* Copyright (C) 2015, Google, Inc.
* For conditions of distribution and use, see the accompanying README file.
*
@@ -993,6 +993,8 @@ EXTERN(JDIMENSION) jpeg_read_scanlines (j_decompress_ptr cinfo,
JDIMENSION max_lines);
EXTERN(JDIMENSION) jpeg_skip_scanlines (j_decompress_ptr cinfo,
JDIMENSION num_lines);
+EXTERN(void) jpeg_crop_scanline (j_decompress_ptr cinfo, JDIMENSION *xoffset,
+ JDIMENSION *width);
EXTERN(boolean) jpeg_finish_decompress (j_decompress_ptr cinfo);
/* Replaces jpeg_read_scanlines when reading raw downsampled data. */
diff --git a/jversion.h b/jversion.h
index 949b4f4d..68a20a7d 100644
--- a/jversion.h
+++ b/jversion.h
@@ -25,7 +25,23 @@
#endif
-#define JCOPYRIGHT "Copyright (C) 1991-2012 Thomas G. Lane, Guido Vollbeding\n" \
+/*
+ * NOTE: It is our convention to place the authors in the following order:
+ * - libjpeg-turbo authors (2009-) in descending order of the date of their
+ * most recent contribution to the project, then in ascending order of the
+ * date of their first contribution to the project
+ * - Upstream authors in descending order of the date of the first inclusion of
+ * their code
+ */
+
+#define JCOPYRIGHT "Copyright (C) 2009-2016 D. R. Commander\n" \
+ "Copyright (C) 2011-2016 Siarhei Siamashka\n" \
+ "Copyright (C) 2015-2016 Matthieu Darbois\n" \
+ "Copyright (C) 2015 Google, Inc.\n" \
+ "Copyright (C) 2013-2014 MIPS Technologies, Inc.\n" \
+ "Copyright (C) 2013 Linaro Limited\n" \
+ "Copyright (C) 2009-2011 Nokia Corporation and/or its subsidiary(-ies)\n" \
+ "Copyright (C) 2009 Pierre Ossman for Cendio AB\n" \
"Copyright (C) 1999-2006 MIYASAKA Masaru\n" \
"Copyright (C) 2009 Pierre Ossman for Cendio AB\n" \
"Copyright (C) 2009-2015 D. R. Commander\n" \
diff --git a/libjpeg.txt b/libjpeg.txt
index 52b6d8b8..5fbae937 100644
--- a/libjpeg.txt
+++ b/libjpeg.txt
@@ -3,7 +3,7 @@ USING THE IJG JPEG LIBRARY
This file was part of the Independent JPEG Group's software:
Copyright (C) 1994-2011, Thomas G. Lane, Guido Vollbeding.
libjpeg-turbo Modifications:
-Copyright (C) 2010, 2014, 2015, D. R. Commander.
+Copyright (C) 2010, 2014-2016, D. R. Commander.
Copyright (C) 2015, Google, Inc.
For conditions of distribution and use, see the accompanying README file.
@@ -730,16 +730,21 @@ jpeg_abort_decompress() or jpeg_abort() if you want to reuse the object.
The previous discussion of aborting compression cycles applies here too.
-Skipping rows when decompressing
---------------------------------
+Partial image decompression
+---------------------------
-jpeg_skip_scanlines(j_decompress_ptr cinfo, JDIMENSION num_lines);
+Partial image decompression is convenient for performance-critical applications
+that wish to view only a portion of a large JPEG image without decompressing
+the whole thing. It it also useful in memory-constrained environments (such as
+on mobile devices.) This library provides the following functions to support
+partial image decompression:
+
+1. Skipping rows when decompressing
+
+ jpeg_skip_scanlines(j_decompress_ptr cinfo, JDIMENSION num_lines);
This function provides application programmers with the ability to skip over
-multiple rows in the JPEG image, thus decoding only a subset of the image data.
-This is convenient for performance-critical applications that wish to view only
-a portion of a large JPEG image without decompressing the whole thing. It it
-also useful in memory-constrained environments (such as on mobile devices.)
+multiple rows in the JPEG image.
Suspending data sources are not supported by this function. Calling
jpeg_skip_scanlines() with a suspending data source will result in undefined
@@ -772,6 +777,43 @@ These issues are especially tricky for cases in which upsampling requires
context rows. In the worst case, jpeg_skip_scanlines() will perform similarly
to jpeg_read_scanlines() (since it will actually call jpeg_read_scanlines().)
+2. Decompressing partial scanlines
+
+ jpeg_crop_scanline (j_decompress_ptr cinfo, JDIMENSION *xoffset,
+ JDIMENSION *width)
+
+This function provides application programmers with the ability to decompress
+only a portion of each row in the JPEG image. It must be called after
+jpeg_start_decompress() and before any calls to jpeg_read_scanlines() or
+jpeg_skip_scanlines().
+
+If xoffset and width do not form a valid subset of the image row, then this
+function will generate an error. Note that if the output image is scaled, then
+xoffset and width are relative to the scaled image dimensions.
+
+xoffset and width are passed by reference because xoffset must fall on an iMCU
+boundary. If it doesn't, then it will be moved left to the nearest iMCU
+boundary, and width will be increased accordingly. If the calling program does
+not like the adjusted values of xoffset and width, then it can call
+jpeg_crop_scanline() again with new values (for instance, if it wants to move
+xoffset to the nearest iMCU boundary to the right instead of to the left.)
+
+After calling this function, cinfo->output_width will be set to the adjusted
+width. This value should be used when allocating an output buffer to pass to
+jpeg_read_scanlines().
+
+The output image from a partial-width decompression will be identical to the
+corresponding image region from a full decode, with one exception: The "fancy"
+(smooth) h2v2 (4:2:0) and h2v1 (4:2:2) upsampling algorithms fill in the
+missing chroma components by averaging the chroma components from neighboring
+pixels, except on the right and left edges of the image (where there are no
+neighboring pixels.) When performing a partial-width decompression, these
+"fancy" upsampling algorithms may treat the left and right edges of the partial
+image region as if they are the left and right edges of the image, meaning that
+the upsampling algorithm may be simplified. The result is that the pixels on
+the left or right edge of the partial image may not be exactly identical to the
+corresponding pixels in the original image.
+
Mechanics of usage: include files, linking, etc
-----------------------------------------------
diff --git a/win/jpeg62-memsrcdst.def b/win/jpeg62-memsrcdst.def
index 949d2679..6499316a 100755
--- a/win/jpeg62-memsrcdst.def
+++ b/win/jpeg62-memsrcdst.def
@@ -103,3 +103,4 @@ EXPORTS
jpeg_mem_dest @ 102 ;
jpeg_mem_src @ 103 ;
jpeg_skip_scanlines @ 104 ;
+ jpeg_crop_scanline @ 105 ;
diff --git a/win/jpeg62.def b/win/jpeg62.def
index c64df50a..9f30b1a2 100755
--- a/win/jpeg62.def
+++ b/win/jpeg62.def
@@ -101,3 +101,4 @@ EXPORTS
jround_up @ 100 ;
jzero_far @ 101 ;
jpeg_skip_scanlines @ 102 ;
+ jpeg_crop_scanline @ 103 ;
diff --git a/win/jpeg7.def b/win/jpeg7.def
index 8daa35f9..92463c51 100644
--- a/win/jpeg7.def
+++ b/win/jpeg7.def
@@ -103,3 +103,4 @@ EXPORTS
jround_up @ 102 ;
jzero_far @ 103 ;
jpeg_skip_scanlines @ 104 ;
+ jpeg_crop_scanline @ 105 ;
diff --git a/win/jpeg8.def b/win/jpeg8.def
index 01deb69f..19246ac9 100644
--- a/win/jpeg8.def
+++ b/win/jpeg8.def
@@ -106,3 +106,4 @@ EXPORTS
jround_up @ 105 ;
jzero_far @ 106 ;
jpeg_skip_scanlines @ 107 ;
+ jpeg_crop_scanline @ 108 ;
diff --git a/wrppm.c b/wrppm.c
index d3a613c8..ad8b49d7 100644
--- a/wrppm.c
+++ b/wrppm.c
@@ -19,6 +19,7 @@
*/
#include "cdjpeg.h" /* Common decls for cjpeg/djpeg applications */
+#include "wrppm.h"
#ifdef PPM_SUPPORTED
@@ -61,21 +62,6 @@
*/
-/* Private version of data destination object */
-
-typedef struct {
- struct djpeg_dest_struct pub; /* public fields */
-
- /* Usually these two pointers point to the same place: */
- char *iobuffer; /* fwrite's I/O buffer */
- JSAMPROW pixrow; /* decompressor output buffer */
- size_t buffer_width; /* width of I/O buffer */
- JDIMENSION samples_per_row; /* JSAMPLEs per output row */
-} ppm_dest_struct;
-
-typedef ppm_dest_struct * ppm_dest_ptr;
-
-
/*
* Write some pixel data.
* In this module rows_supplied will always be 1.
diff --git a/wrppm.h b/wrppm.h
new file mode 100644
index 00000000..aa6c5626
--- /dev/null
+++ b/wrppm.h
@@ -0,0 +1,26 @@
+/*
+ * wrppm.h
+ *
+ * This file was part of the Independent JPEG Group's software:
+ * Copyright (C) 1994, Thomas G. Lane.
+ * For conditions of distribution and use, see the accompanying README.ijg
+ * file.
+ */
+
+#ifdef PPM_SUPPORTED
+
+/* Private version of data destination object */
+
+typedef struct {
+ struct djpeg_dest_struct pub; /* public fields */
+
+ /* Usually these two pointers point to the same place: */
+ char *iobuffer; /* fwrite's I/O buffer */
+ JSAMPROW pixrow; /* decompressor output buffer */
+ size_t buffer_width; /* width of I/O buffer */
+ JDIMENSION samples_per_row; /* JSAMPLEs per output row */
+} ppm_dest_struct;
+
+typedef ppm_dest_struct *ppm_dest_ptr;
+
+#endif