16-bit lossless JPEG support

This commit is contained in:
DRC
2022-12-15 12:20:50 -06:00
parent ad4e2ad86f
commit 2241434eb9
46 changed files with 906 additions and 148 deletions

View File

@@ -556,7 +556,7 @@ if(WITH_ARITH_DEC)
set(JPEG_SOURCES ${JPEG_SOURCES} jdarith.c) set(JPEG_SOURCES ${JPEG_SOURCES} jdarith.c)
endif() endif()
# Compile a separate version of these source files with 12-bit data # Compile a separate version of these source files with 12-bit and 16-bit data
# precision. # precision.
add_library(jpeg12 OBJECT jcapistd.c jccoefct.c jccolor.c jcdctmgr.c jcdiffct.c add_library(jpeg12 OBJECT jcapistd.c jccoefct.c jccolor.c jcdctmgr.c jcdiffct.c
jclossls.c jcmainct.c jcprepct.c jcsample.c jdapistd.c jdcoefct.c jdcolor.c jclossls.c jcmainct.c jcprepct.c jcsample.c jdapistd.c jdcoefct.c jdcolor.c
@@ -564,6 +564,10 @@ add_library(jpeg12 OBJECT jcapistd.c jccoefct.c jccolor.c jcdctmgr.c jcdiffct.c
jfdctfst.c jfdctint.c jidctflt.c jidctfst.c jidctint.c jidctred.c jquant1.c jfdctfst.c jfdctint.c jidctflt.c jidctfst.c jidctint.c jidctred.c jquant1.c
jquant2.c jutils.c) jquant2.c jutils.c)
set_property(TARGET jpeg12 PROPERTY COMPILE_FLAGS "-DBITS_IN_JSAMPLE=12") set_property(TARGET jpeg12 PROPERTY COMPILE_FLAGS "-DBITS_IN_JSAMPLE=12")
add_library(jpeg16 OBJECT jcapistd.c jccolor.c jcdiffct.c jclossls.c jcmainct.c
jcprepct.c jcsample.c jdapistd.c jdcolor.c jddiffct.c jdlossls.c jdmainct.c
jdpostct.c jdsample.c jquant1.c jquant2.c jutils.c)
set_property(TARGET jpeg16 PROPERTY COMPILE_FLAGS "-DBITS_IN_JSAMPLE=16")
if(WITH_SIMD) if(WITH_SIMD)
add_subdirectory(simd) add_subdirectory(simd)
@@ -597,7 +601,7 @@ endif()
if(ENABLE_STATIC) if(ENABLE_STATIC)
add_library(jpeg-static STATIC ${JPEG_SOURCES} ${SIMD_TARGET_OBJECTS} add_library(jpeg-static STATIC ${JPEG_SOURCES} ${SIMD_TARGET_OBJECTS}
${SIMD_OBJS} $<TARGET_OBJECTS:jpeg12>) ${SIMD_OBJS} $<TARGET_OBJECTS:jpeg12> $<TARGET_OBJECTS:jpeg16>)
if(NOT MSVC) if(NOT MSVC)
set_target_properties(jpeg-static PROPERTIES OUTPUT_NAME jpeg) set_target_properties(jpeg-static PROPERTIES OUTPUT_NAME jpeg)
endif() endif()
@@ -607,7 +611,7 @@ if(WITH_TURBOJPEG)
if(ENABLE_SHARED) if(ENABLE_SHARED)
set(TURBOJPEG_SOURCES ${JPEG_SOURCES} ${SIMD_TARGET_OBJECTS} ${SIMD_OBJS} set(TURBOJPEG_SOURCES ${JPEG_SOURCES} ${SIMD_TARGET_OBJECTS} ${SIMD_OBJS}
turbojpeg.c transupp.c jdatadst-tj.c jdatasrc-tj.c rdbmp.c rdppm.c turbojpeg.c transupp.c jdatadst-tj.c jdatasrc-tj.c rdbmp.c rdppm.c
wrbmp.c wrppm.c $<TARGET_OBJECTS:jpeg12>) wrbmp.c wrppm.c $<TARGET_OBJECTS:jpeg12> $<TARGET_OBJECTS:jpeg16>)
set(TJMAPFILE ${CMAKE_CURRENT_SOURCE_DIR}/turbojpeg-mapfile) set(TJMAPFILE ${CMAKE_CURRENT_SOURCE_DIR}/turbojpeg-mapfile)
if(WITH_JAVA) if(WITH_JAVA)
set(TURBOJPEG_SOURCES ${TURBOJPEG_SOURCES} turbojpeg-jni.c) set(TURBOJPEG_SOURCES ${TURBOJPEG_SOURCES} turbojpeg-jni.c)
@@ -659,7 +663,8 @@ if(WITH_TURBOJPEG)
if(ENABLE_STATIC) if(ENABLE_STATIC)
add_library(turbojpeg-static STATIC ${JPEG_SOURCES} ${SIMD_TARGET_OBJECTS} add_library(turbojpeg-static STATIC ${JPEG_SOURCES} ${SIMD_TARGET_OBJECTS}
${SIMD_OBJS} turbojpeg.c transupp.c jdatadst-tj.c jdatasrc-tj.c rdbmp.c ${SIMD_OBJS} turbojpeg.c transupp.c jdatadst-tj.c jdatasrc-tj.c rdbmp.c
rdppm.c wrbmp.c wrppm.c $<TARGET_OBJECTS:jpeg12>) rdppm.c wrbmp.c wrppm.c $<TARGET_OBJECTS:jpeg12>
$<TARGET_OBJECTS:jpeg16>)
set_property(TARGET turbojpeg-static PROPERTY COMPILE_FLAGS set_property(TARGET turbojpeg-static PROPERTY COMPILE_FLAGS
"-DBMP_SUPPORTED -DPPM_SUPPORTED") "-DBMP_SUPPORTED -DPPM_SUPPORTED")
if(NOT MSVC) if(NOT MSVC)
@@ -685,24 +690,32 @@ set(CDJPEG_COMPILE_FLAGS
"-DBMP_SUPPORTED -DGIF_SUPPORTED -DPPM_SUPPORTED -DTARGA_SUPPORTED ${USE_SETMODE}") "-DBMP_SUPPORTED -DGIF_SUPPORTED -DPPM_SUPPORTED -DTARGA_SUPPORTED ${USE_SETMODE}")
if(ENABLE_STATIC) if(ENABLE_STATIC)
# Compile a separate version of these source files with 12-bit data # Compile a separate version of these source files with 12-bit and 16-bit
# precision. # data precision.
add_library(cjpeg12-static OBJECT rdgif.c rdppm.c) add_library(cjpeg12-static OBJECT rdgif.c rdppm.c)
set_property(TARGET cjpeg12-static PROPERTY COMPILE_FLAGS set_property(TARGET cjpeg12-static PROPERTY COMPILE_FLAGS
"-DBITS_IN_JSAMPLE=12 -DGIF_SUPPORTED -DPPM_SUPPORTED") "-DBITS_IN_JSAMPLE=12 -DGIF_SUPPORTED -DPPM_SUPPORTED")
add_library(cjpeg16-static OBJECT rdgif.c rdppm.c)
set_property(TARGET cjpeg16-static PROPERTY COMPILE_FLAGS
"-DBITS_IN_JSAMPLE=16 -DGIF_SUPPORTED -DPPM_SUPPORTED")
add_executable(cjpeg-static cjpeg.c cdjpeg.c rdbmp.c rdgif.c rdppm.c add_executable(cjpeg-static cjpeg.c cdjpeg.c rdbmp.c rdgif.c rdppm.c
rdswitch.c rdtarga.c $<TARGET_OBJECTS:cjpeg12-static>) rdswitch.c rdtarga.c $<TARGET_OBJECTS:cjpeg12-static>
$<TARGET_OBJECTS:cjpeg16-static>)
set_property(TARGET cjpeg-static PROPERTY COMPILE_FLAGS set_property(TARGET cjpeg-static PROPERTY COMPILE_FLAGS
${CDJPEG_COMPILE_FLAGS}) ${CDJPEG_COMPILE_FLAGS})
target_link_libraries(cjpeg-static jpeg-static) target_link_libraries(cjpeg-static jpeg-static)
# Compile a separate version of these source files with 12-bit data # Compile a separate version of these source files with 12-bit and 16-bit
# precision. # data precision.
add_library(djpeg12-static OBJECT rdcolmap.c wrgif.c wrppm.c) add_library(djpeg12-static OBJECT rdcolmap.c wrgif.c wrppm.c)
set_property(TARGET djpeg12-static PROPERTY COMPILE_FLAGS set_property(TARGET djpeg12-static PROPERTY COMPILE_FLAGS
"-DBITS_IN_JSAMPLE=12 -DGIF_SUPPORTED -DPPM_SUPPORTED") "-DBITS_IN_JSAMPLE=12 -DGIF_SUPPORTED -DPPM_SUPPORTED")
add_library(djpeg16-static OBJECT rdcolmap.c wrgif.c wrppm.c)
set_property(TARGET djpeg16-static PROPERTY COMPILE_FLAGS
"-DBITS_IN_JSAMPLE=16 -DGIF_SUPPORTED -DPPM_SUPPORTED")
add_executable(djpeg-static djpeg.c cdjpeg.c rdcolmap.c rdswitch.c wrbmp.c add_executable(djpeg-static djpeg.c cdjpeg.c rdcolmap.c rdswitch.c wrbmp.c
wrgif.c wrppm.c wrtarga.c $<TARGET_OBJECTS:djpeg12-static>) wrgif.c wrppm.c wrtarga.c $<TARGET_OBJECTS:djpeg12-static>
$<TARGET_OBJECTS:djpeg16-static>)
set_property(TARGET djpeg-static PROPERTY COMPILE_FLAGS set_property(TARGET djpeg-static PROPERTY COMPILE_FLAGS
${CDJPEG_COMPILE_FLAGS}) ${CDJPEG_COMPILE_FLAGS})
target_link_libraries(djpeg-static jpeg-static) target_link_libraries(djpeg-static jpeg-static)
@@ -988,12 +1001,15 @@ foreach(libtype ${TEST_LIBTYPES})
# SIMD-accelerated ones.) # SIMD-accelerated ones.)
macro(add_bittest PROG NAME ARGS OUTFILE INFILE MD5SUM) macro(add_bittest PROG NAME ARGS OUTFILE INFILE MD5SUM)
if(${PROG} STREQUAL "cjpeg12") if(${PROG} STREQUAL "cjpeg16")
set(ACTUAL_ARGS "${ARGS};-precision;16")
elseif(${PROG} STREQUAL "cjpeg12")
set(ACTUAL_ARGS "${ARGS};-precision;12") set(ACTUAL_ARGS "${ARGS};-precision;12")
else() else()
set(ACTUAL_ARGS ${ARGS}) set(ACTUAL_ARGS ${ARGS})
endif() endif()
string(REGEX REPLACE "12" "" ACTUAL_PROG ${PROG}) string(REGEX REPLACE "16" "" ACTUAL_PROG ${PROG})
string(REGEX REPLACE "12" "" ACTUAL_PROG ${ACTUAL_PROG})
add_test(${PROG}-${libtype}-${NAME} add_test(${PROG}-${libtype}-${NAME}
${CMAKE_CROSSCOMPILING_EMULATOR} ${ACTUAL_PROG}${suffix} ${ACTUAL_ARGS} ${CMAKE_CROSSCOMPILING_EMULATOR} ${ACTUAL_PROG}${suffix} ${ACTUAL_ARGS}
-outfile ${OUTFILE} ${INFILE}) -outfile ${OUTFILE} ${INFILE})
@@ -1008,6 +1024,20 @@ foreach(libtype ${TEST_LIBTYPES})
endif() endif()
endmacro() endmacro()
set(MD5_JPEG_LOSSLESS fe99437df4e9976fe5e841969242b208)
set(MD5_PPM_LOSSLESS 01d9642a2b8723fefebbe9cb074ccd02)
# Lossless (all arguments other than -lossless and -restart should have no
# effect)
add_bittest(cjpeg16 lossless
"-lossless;4;-restart;1;-quality;1;-grayscale;-optimize;-dct;float;-smooth;100;-baseline;-qslots;1,0,0;-sample;1x2,3x4,2x1"
testout16_lossless.jpg ${TESTIMAGES}/testorig.ppm
${MD5_JPEG_LOSSLESS})
add_bittest(djpeg16 lossless
"-fast;-scale;1/8;-dct;float;-dither;none;-nosmooth;-onepass"
testout16_lossless.ppm testout16_lossless.jpg
${MD5_PPM_LOSSLESS} cjpeg16-${libtype}-lossless)
foreach(sample_bits 8 12) foreach(sample_bits 8 12)
if(sample_bits EQUAL 12) if(sample_bits EQUAL 12)

View File

@@ -3,41 +3,46 @@
### Significant changes relative to 2.1.4: ### Significant changes relative to 2.1.4:
1. 12-bit-per-component JPEG support is now included in the libjpeg API 1. Significantly sped up the computation of optimal Huffman tables. This
library, cjpeg, djpeg, and jpegtran:
- The existing `data_precision` field in `jpeg_compress_struct` and
`jpeg_decompress_struct` has been repurposed to enable the creation of
12-bit-per-component JPEG images or to detect whether a 12-bit-per-component
JPEG image is being decompressed.
- New 12-bit-per-component versions of `jpeg_write_scanlines()`,
`jpeg_write_raw_data()`, `jpeg_read_scanlines()`, `jpeg_skip_scanlines()`,
`jpeg_crop_scanline()`, and `jpeg_read_raw_data()` provide interfaces for
compressing from/decompressing to 12-bit-per-component uncompressed image
buffers.
- A new cjpeg command-line argument (`-precision`) can be used to create
a 12-bit-per-component JPEG image. (djpeg and jpegtran handle
12-bit-per-component JPEG images automatically.)
Refer to [libjpeg.txt](libjpeg.txt) and [usage.txt](usage.txt) for more
details.
2. Significantly sped up the computation of optimal Huffman tables. This
speeds up the compression of tiny images by as much as 2x and provides a speeds up the compression of tiny images by as much as 2x and provides a
noticeable speedup for images as large as 256x256 when using optimal Huffman noticeable speedup for images as large as 256x256 when using optimal Huffman
tables. tables.
3. All deprecated fields, constructors, and methods in the TurboJPEG Java API 2. All deprecated fields, constructors, and methods in the TurboJPEG Java API
have been removed. have been removed.
4. Added support for 8-bit and 12-bit lossless JPEG images. A new libjpeg API 3. Added support for 8-bit, 12-bit, and 16-bit lossless JPEG images. A new
function (`jpeg_enable_lossless()`), TurboJPEG API flag (`TJFLAG_LOSSLESS` in libjpeg API function (`jpeg_enable_lossless()`), TurboJPEG API flag
the C API and `TJ.FLAG_LOSSLESS` in the Java API), and cjpeg/TJBench (`TJFLAG_LOSSLESS` in the C API and `TJ.FLAG_LOSSLESS` in the Java API), and
command-line argument (`-lossless`) can be used to create a lossless JPEG cjpeg/TJBench command-line argument (`-lossless`) can be used to create a
image. (Decompression of lossless JPEG images is handled automatically.) Note lossless JPEG image. (Decompression of lossless JPEG images is handled
that the TurboJPEG API and TJBench can currently only be used to create and automatically.) Note that the TurboJPEG API and TJBench can currently only be
decompress 8-bit lossless JPEG images. Refer to [libjpeg.txt](libjpeg.txt), used to create and decompress 8-bit lossless JPEG images. Refer to
[usage.txt](usage.txt), and the TurboJPEG API documentation for more details. [libjpeg.txt](libjpeg.txt), [usage.txt](usage.txt), and the TurboJPEG API
documentation for more details.
4. 12-bit-per-component (lossy and lossless) and 16-bit-per-component
(lossless) JPEG support is now included in the libjpeg API library, cjpeg,
djpeg, and jpegtran:
- The existing `data_precision` field in `jpeg_compress_struct` and
`jpeg_decompress_struct` has been repurposed to enable the creation of
12-bit-per-component and 16-bit-per-component JPEG images or to detect whether
a 12-bit-per-component or 16-bit-per-component JPEG image is being
decompressed.
- New 12-bit-per-component and 16-bit-per-component versions of
`jpeg_write_scanlines()` and `jpeg_read_scanlines()`, as well as new
12-bit-per-component versions of `jpeg_write_raw_data()`,
`jpeg_skip_scanlines()`, `jpeg_crop_scanline()`, and `jpeg_read_raw_data()`,
provide interfaces for compressing from/decompressing to 12-bit-per-component
and 16-bit-per-component uncompressed image buffers.
- A new cjpeg command-line argument (`-precision`) can be used to create
a 12-bit-per-component or 16-bit-per-component JPEG image. (djpeg and jpegtran
handle 12-bit-per-component and 16-bit-per-component JPEG images
automatically.)
Refer to [libjpeg.txt](libjpeg.txt) and [usage.txt](usage.txt) for more
details.
5. Introduced a new flag in the TurboJPEG C and Java APIs (`TJFLAG_ARITHMETIC` 5. Introduced a new flag in the TurboJPEG C and Java APIs (`TJFLAG_ARITHMETIC`
and `TJ.FLAG_ARITHMETIC`, respectively) that causes the library to use and `TJ.FLAG_ARITHMETIC`, respectively) that causes the library to use

View File

@@ -36,6 +36,9 @@ struct cjpeg_source_struct {
JSAMPARRAY buffer; JSAMPARRAY buffer;
J12SAMPARRAY buffer12; J12SAMPARRAY buffer12;
#ifdef C_LOSSLESS_SUPPORTED
J16SAMPARRAY buffer16;
#endif
JDIMENSION buffer_height; JDIMENSION buffer_height;
#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION #ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
JDIMENSION max_pixels; JDIMENSION max_pixels;
@@ -77,6 +80,9 @@ struct djpeg_dest_struct {
*/ */
JSAMPARRAY buffer; JSAMPARRAY buffer;
J12SAMPARRAY buffer12; J12SAMPARRAY buffer12;
#ifdef D_LOSSLESS_SUPPORTED
J16SAMPARRAY buffer16;
#endif
JDIMENSION buffer_height; JDIMENSION buffer_height;
}; };
@@ -111,13 +117,26 @@ EXTERN(djpeg_dest_ptr) jinit_write_bmp(j_decompress_ptr cinfo, boolean is_os2,
boolean use_inversion_array); boolean use_inversion_array);
EXTERN(cjpeg_source_ptr) jinit_read_gif(j_compress_ptr cinfo); EXTERN(cjpeg_source_ptr) jinit_read_gif(j_compress_ptr cinfo);
EXTERN(cjpeg_source_ptr) j12init_read_gif(j_compress_ptr cinfo); EXTERN(cjpeg_source_ptr) j12init_read_gif(j_compress_ptr cinfo);
#ifdef C_LOSSLESS_SUPPORTED
EXTERN(cjpeg_source_ptr) j16init_read_gif(j_compress_ptr cinfo);
#endif
EXTERN(djpeg_dest_ptr) jinit_write_gif(j_decompress_ptr cinfo, boolean is_lzw); EXTERN(djpeg_dest_ptr) jinit_write_gif(j_decompress_ptr cinfo, boolean is_lzw);
EXTERN(djpeg_dest_ptr) j12init_write_gif(j_decompress_ptr cinfo, EXTERN(djpeg_dest_ptr) j12init_write_gif(j_decompress_ptr cinfo,
boolean is_lzw); boolean is_lzw);
#ifdef D_LOSSLESS_SUPPORTED
EXTERN(djpeg_dest_ptr) j16init_write_gif(j_decompress_ptr cinfo,
boolean is_lzw);
#endif
EXTERN(cjpeg_source_ptr) jinit_read_ppm(j_compress_ptr cinfo); EXTERN(cjpeg_source_ptr) jinit_read_ppm(j_compress_ptr cinfo);
EXTERN(cjpeg_source_ptr) j12init_read_ppm(j_compress_ptr cinfo); EXTERN(cjpeg_source_ptr) j12init_read_ppm(j_compress_ptr cinfo);
#ifdef C_LOSSLESS_SUPPORTED
EXTERN(cjpeg_source_ptr) j16init_read_ppm(j_compress_ptr cinfo);
#endif
EXTERN(djpeg_dest_ptr) jinit_write_ppm(j_decompress_ptr cinfo); EXTERN(djpeg_dest_ptr) jinit_write_ppm(j_decompress_ptr cinfo);
EXTERN(djpeg_dest_ptr) j12init_write_ppm(j_decompress_ptr cinfo); EXTERN(djpeg_dest_ptr) j12init_write_ppm(j_decompress_ptr cinfo);
#ifdef D_LOSSLESS_SUPPORTED
EXTERN(djpeg_dest_ptr) j16init_write_ppm(j_decompress_ptr cinfo);
#endif
EXTERN(cjpeg_source_ptr) jinit_read_targa(j_compress_ptr cinfo); EXTERN(cjpeg_source_ptr) jinit_read_targa(j_compress_ptr cinfo);
EXTERN(djpeg_dest_ptr) jinit_write_targa(j_decompress_ptr cinfo); EXTERN(djpeg_dest_ptr) jinit_write_targa(j_decompress_ptr cinfo);
@@ -135,6 +154,9 @@ EXTERN(boolean) set_sample_factors(j_compress_ptr cinfo, char *arg);
EXTERN(void) read_color_map(j_decompress_ptr cinfo, FILE *infile); EXTERN(void) read_color_map(j_decompress_ptr cinfo, FILE *infile);
EXTERN(void) read_color_map_12(j_decompress_ptr cinfo, FILE *infile); EXTERN(void) read_color_map_12(j_decompress_ptr cinfo, FILE *infile);
#ifdef D_LOSSLESS_SUPPORTED
EXTERN(void) read_color_map_16(j_decompress_ptr cinfo, FILE *infile);
#endif
/* common support routines (in cdjpeg.c) */ /* common support routines (in cdjpeg.c) */

11
cjpeg.1
View File

@@ -1,4 +1,4 @@
.TH CJPEG 1 "16 November 2022" .TH CJPEG 1 "30 November 2022"
.SH NAME .SH NAME
cjpeg \- compress an image file to a JPEG file cjpeg \- compress an image file to a JPEG file
.SH SYNOPSIS .SH SYNOPSIS
@@ -150,10 +150,13 @@ about the same --- often a little smaller.
Switches for advanced users: Switches for advanced users:
.TP .TP
.BI \-precision " N" .BI \-precision " N"
Create JPEG file with N-bit data precision. N is 8 or 12; default is 8. Create JPEG file with N-bit data precision. N is 8, 12, or 16; default is 8.
If N is 16, then
.B -lossless
must also be specified.
.B Caution: .B Caution:
12-bit JPEG is not yet widely implemented, so many decoders will be unable to 12-bit and 16-bit JPEG is not yet widely implemented, so many decoders will be
view a 12-bit JPEG file at all. unable to view a 12-bit or 16-bit JPEG file at all.
.TP .TP
.BI \-lossless " psv[,Pt]" .BI \-lossless " psv[,Pt]"
Create a lossless JPEG file using the specified predictor selection value Create a lossless JPEG file using the specified predictor selection value

38
cjpeg.c
View File

@@ -105,14 +105,28 @@ select_file_type(j_compress_ptr cinfo, FILE *infile)
#endif #endif
#ifdef GIF_SUPPORTED #ifdef GIF_SUPPORTED
case 'G': case 'G':
if (cinfo->data_precision == 12) if (cinfo->data_precision == 16) {
#ifdef C_LOSSLESS_SUPPORTED
return j16init_read_gif(cinfo);
#else
ERREXIT1(cinfo, JERR_BAD_PRECISION, cinfo->data_precision);
break;
#endif
} else if (cinfo->data_precision == 12)
return j12init_read_gif(cinfo); return j12init_read_gif(cinfo);
else else
return jinit_read_gif(cinfo); return jinit_read_gif(cinfo);
#endif #endif
#ifdef PPM_SUPPORTED #ifdef PPM_SUPPORTED
case 'P': case 'P':
if (cinfo->data_precision == 12) if (cinfo->data_precision == 16) {
#ifdef C_LOSSLESS_SUPPORTED
return j16init_read_ppm(cinfo);
#else
ERREXIT1(cinfo, JERR_BAD_PRECISION, cinfo->data_precision);
break;
#endif
} else if (cinfo->data_precision == 12)
return j12init_read_ppm(cinfo); return j12init_read_ppm(cinfo);
else else
return jinit_read_ppm(cinfo); return jinit_read_ppm(cinfo);
@@ -213,7 +227,12 @@ usage(void)
#endif #endif
fprintf(stderr, "Switches for advanced users:\n"); fprintf(stderr, "Switches for advanced users:\n");
fprintf(stderr, " -precision N Create JPEG file with N-bit data precision\n"); fprintf(stderr, " -precision N Create JPEG file with N-bit data precision\n");
#ifdef C_LOSSLESS_SUPPORTED
fprintf(stderr, " (N is 8, 12, or 16; default is 8; if N is 16, then -lossless\n");
fprintf(stderr, " must also be specified)\n");
#else
fprintf(stderr, " (N is 8 or 12; default is 8)\n"); fprintf(stderr, " (N is 8 or 12; default is 8)\n");
#endif
#ifdef C_LOSSLESS_SUPPORTED #ifdef C_LOSSLESS_SUPPORTED
fprintf(stderr, " -lossless psv[,Pt] Create lossless JPEG file\n"); fprintf(stderr, " -lossless psv[,Pt] Create lossless JPEG file\n");
#endif #endif
@@ -427,7 +446,11 @@ parse_switches(j_compress_ptr cinfo, int argc, char **argv,
usage(); usage();
if (sscanf(argv[argn], "%d", &val) != 1) if (sscanf(argv[argn], "%d", &val) != 1)
usage(); usage();
#ifdef C_LOSSLESS_SUPPORTED
if (val != 8 && val != 12 && val != 16)
#else
if (val != 8 && val != 12) if (val != 8 && val != 12)
#endif
usage(); usage();
cinfo->data_precision = val; cinfo->data_precision = val;
@@ -768,7 +791,16 @@ main(int argc, char **argv)
jpeg_write_icc_profile(&cinfo, icc_profile, (unsigned int)icc_len); jpeg_write_icc_profile(&cinfo, icc_profile, (unsigned int)icc_len);
/* Process data */ /* Process data */
if (cinfo.data_precision == 12) { if (cinfo.data_precision == 16) {
#ifdef C_LOSSLESS_SUPPORTED
while (cinfo.next_scanline < cinfo.image_height) {
num_scanlines = (*src_mgr->get_pixel_rows) (&cinfo, src_mgr);
(void)jpeg16_write_scanlines(&cinfo, src_mgr->buffer16, num_scanlines);
}
#else
ERREXIT1(&cinfo, JERR_BAD_PRECISION, cinfo.data_precision);
#endif
} else if (cinfo.data_precision == 12) {
while (cinfo.next_scanline < cinfo.image_height) { while (cinfo.next_scanline < cinfo.image_height) {
num_scanlines = (*src_mgr->get_pixel_rows) (&cinfo, src_mgr); num_scanlines = (*src_mgr->get_pixel_rows) (&cinfo, src_mgr);
(void)jpeg12_write_scanlines(&cinfo, src_mgr->buffer12, num_scanlines); (void)jpeg12_write_scanlines(&cinfo, src_mgr->buffer12, num_scanlines);

43
djpeg.c
View File

@@ -662,7 +662,14 @@ main(int argc, char **argv)
#endif #endif
#ifdef GIF_SUPPORTED #ifdef GIF_SUPPORTED
case FMT_GIF: case FMT_GIF:
if (cinfo.data_precision == 12) if (cinfo.data_precision == 16) {
#ifdef D_LOSSLESS_SUPPORTED
dest_mgr = j16init_write_gif(&cinfo, TRUE);
#else
ERREXIT1(&cinfo, JERR_BAD_PRECISION, cinfo.data_precision);
break;
#endif
} else if (cinfo.data_precision == 12)
dest_mgr = j12init_write_gif(&cinfo, TRUE); dest_mgr = j12init_write_gif(&cinfo, TRUE);
else else
dest_mgr = jinit_write_gif(&cinfo, TRUE); dest_mgr = jinit_write_gif(&cinfo, TRUE);
@@ -673,7 +680,14 @@ main(int argc, char **argv)
#endif #endif
#ifdef PPM_SUPPORTED #ifdef PPM_SUPPORTED
case FMT_PPM: case FMT_PPM:
if (cinfo.data_precision == 12) if (cinfo.data_precision == 16) {
#ifdef D_LOSSLESS_SUPPORTED
dest_mgr = j16init_write_ppm(&cinfo);
#else
ERREXIT1(&cinfo, JERR_BAD_PRECISION, cinfo.data_precision);
break;
#endif
} else if (cinfo.data_precision == 12)
dest_mgr = j12init_write_ppm(&cinfo); dest_mgr = j12init_write_ppm(&cinfo);
else else
dest_mgr = jinit_write_ppm(&cinfo); dest_mgr = jinit_write_ppm(&cinfo);
@@ -715,7 +729,9 @@ main(int argc, char **argv)
(*dest_mgr->start_output) (&cinfo, dest_mgr); (*dest_mgr->start_output) (&cinfo, dest_mgr);
cinfo.output_height = tmp; cinfo.output_height = tmp;
if (cinfo.data_precision == 12) { if (cinfo.data_precision == 16)
ERREXIT(&cinfo, JERR_NOTIMPL);
else if (cinfo.data_precision == 12) {
/* Process data */ /* Process data */
while (cinfo.output_scanline < skip_start) { while (cinfo.output_scanline < skip_start) {
num_scanlines = jpeg12_read_scanlines(&cinfo, dest_mgr->buffer12, num_scanlines = jpeg12_read_scanlines(&cinfo, dest_mgr->buffer12,
@@ -767,7 +783,9 @@ main(int argc, char **argv)
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
if (cinfo.data_precision == 12) if (cinfo.data_precision == 16)
ERREXIT(&cinfo, JERR_NOTIMPL);
else if (cinfo.data_precision == 12)
jpeg12_crop_scanline(&cinfo, &crop_x, &crop_width); jpeg12_crop_scanline(&cinfo, &crop_x, &crop_width);
else else
jpeg_crop_scanline(&cinfo, &crop_x, &crop_width); jpeg_crop_scanline(&cinfo, &crop_x, &crop_width);
@@ -784,7 +802,9 @@ main(int argc, char **argv)
(*dest_mgr->start_output) (&cinfo, dest_mgr); (*dest_mgr->start_output) (&cinfo, dest_mgr);
cinfo.output_height = tmp; cinfo.output_height = tmp;
if (cinfo.data_precision == 12) { if (cinfo.data_precision == 16)
ERREXIT(&cinfo, JERR_NOTIMPL);
else if (cinfo.data_precision == 12) {
/* Process data */ /* Process data */
if ((tmp = jpeg12_skip_scanlines(&cinfo, crop_y)) != crop_y) { if ((tmp = jpeg12_skip_scanlines(&cinfo, crop_y)) != crop_y) {
fprintf(stderr, "%s: jpeg12_skip_scanlines() returned %u rather than %u\n", fprintf(stderr, "%s: jpeg12_skip_scanlines() returned %u rather than %u\n",
@@ -831,7 +851,18 @@ main(int argc, char **argv)
/* Write output file header */ /* Write output file header */
(*dest_mgr->start_output) (&cinfo, dest_mgr); (*dest_mgr->start_output) (&cinfo, dest_mgr);
if (cinfo.data_precision == 12) { if (cinfo.data_precision == 16) {
#ifdef D_LOSSLESS_SUPPORTED
/* Process data */
while (cinfo.output_scanline < cinfo.output_height) {
num_scanlines = jpeg16_read_scanlines(&cinfo, dest_mgr->buffer16,
dest_mgr->buffer_height);
(*dest_mgr->put_pixel_rows) (&cinfo, dest_mgr, num_scanlines);
}
#else
ERREXIT1(&cinfo, JERR_BAD_PRECISION, cinfo.data_precision);
#endif
} else if (cinfo.data_precision == 12) {
/* Process data */ /* Process data */
while (cinfo.output_scanline < cinfo.output_height) { while (cinfo.output_scanline < cinfo.output_height) {
num_scanlines = jpeg12_read_scanlines(&cinfo, dest_mgr->buffer12, num_scanlines = jpeg12_read_scanlines(&cinfo, dest_mgr->buffer12,

View File

@@ -42,6 +42,15 @@ target_link_libraries(cjpeg12_fuzzer${FUZZER_SUFFIX} ${FUZZ_LIBRARY}
install(TARGETS cjpeg12_fuzzer${FUZZER_SUFFIX} RUNTIME DESTINATION install(TARGETS cjpeg12_fuzzer${FUZZER_SUFFIX} RUNTIME DESTINATION
${FUZZ_BINDIR}) ${FUZZ_BINDIR})
add_executable(cjpeg16_fuzzer${FUZZER_SUFFIX} cjpeg16.cc ../cdjpeg.c ../rdbmp.c
../rdgif.c ../rdppm.c ../rdswitch.c ../rdtarga.c)
set_property(TARGET cjpeg16_fuzzer${FUZZER_SUFFIX} PROPERTY COMPILE_FLAGS
${COMPILE_FLAGS})
target_link_libraries(cjpeg16_fuzzer${FUZZER_SUFFIX} ${FUZZ_LIBRARY}
jpeg-static)
install(TARGETS cjpeg16_fuzzer${FUZZER_SUFFIX} RUNTIME DESTINATION
${FUZZ_BINDIR})
macro(add_fuzz_target target source_file) macro(add_fuzz_target target source_file)
add_executable(${target}_fuzzer${FUZZER_SUFFIX} ${source_file}) add_executable(${target}_fuzzer${FUZZER_SUFFIX} ${source_file})
target_link_libraries(${target}_fuzzer${FUZZER_SUFFIX} ${FUZZ_LIBRARY} target_link_libraries(${target}_fuzzer${FUZZER_SUFFIX} ${FUZZ_LIBRARY}

View File

@@ -19,6 +19,7 @@ make install
cp $SRC/compress_fuzzer_seed_corpus.zip $OUT/cjpeg_fuzzer${FUZZER_SUFFIX}_seed_corpus.zip cp $SRC/compress_fuzzer_seed_corpus.zip $OUT/cjpeg_fuzzer${FUZZER_SUFFIX}_seed_corpus.zip
cp $SRC/compress_fuzzer_seed_corpus.zip $OUT/cjpeg12_fuzzer${FUZZER_SUFFIX}_seed_corpus.zip cp $SRC/compress_fuzzer_seed_corpus.zip $OUT/cjpeg12_fuzzer${FUZZER_SUFFIX}_seed_corpus.zip
cp $SRC/compress_fuzzer_seed_corpus.zip $OUT/cjpeg16_fuzzer${FUZZER_SUFFIX}_seed_corpus.zip
cp $SRC/compress_fuzzer_seed_corpus.zip $OUT/compress_fuzzer${FUZZER_SUFFIX}_seed_corpus.zip cp $SRC/compress_fuzzer_seed_corpus.zip $OUT/compress_fuzzer${FUZZER_SUFFIX}_seed_corpus.zip
cp $SRC/compress_fuzzer_seed_corpus.zip $OUT/compress_yuv_fuzzer${FUZZER_SUFFIX}_seed_corpus.zip cp $SRC/compress_fuzzer_seed_corpus.zip $OUT/compress_yuv_fuzzer${FUZZER_SUFFIX}_seed_corpus.zip
cp $SRC/compress_fuzzer_seed_corpus.zip $OUT/compress_lossless_fuzzer${FUZZER_SUFFIX}_seed_corpus.zip cp $SRC/compress_fuzzer_seed_corpus.zip $OUT/compress_lossless_fuzzer${FUZZER_SUFFIX}_seed_corpus.zip

79
fuzz/cjpeg16.cc Normal file
View File

@@ -0,0 +1,79 @@
/*
* Copyright (C)2021-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:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* - Neither the name of the libjpeg-turbo Project nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS",
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/* This fuzz target wraps cjpeg in order to test esoteric compression options
as well as the GIF and Targa readers. */
#define main cjpeg_main
#define CJPEG_FUZZER
extern "C" {
#include "../cjpeg.c"
}
#undef main
#undef CJPEG_FUZZER
#include <stdint.h>
#include <unistd.h>
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
{
char filename[FILENAME_MAX] = { 0 };
char *argv1[] = {
(char *)"cjpeg", (char *)"-precision", (char *)"16",
(char *)"-lossless", (char *)"1,4", NULL
};
char *argv2[] = {
(char *)"cjpeg", (char *)"-precision", (char *)"16",
(char *)"-lossless", (char *)"4,0", NULL
};
int fd = -1;
#if defined(__has_feature) && __has_feature(memory_sanitizer)
char env[18] = "JSIMD_FORCENONE=1";
/* The libjpeg-turbo SIMD extensions produce false positives with
MemorySanitizer. */
putenv(env);
#endif
snprintf(filename, FILENAME_MAX, "/tmp/libjpeg-turbo_cjpeg16_fuzz.XXXXXX");
if ((fd = mkstemp(filename)) < 0 || write(fd, data, size) < 0)
goto bailout;
argv1[5] = argv2[5] = filename;
cjpeg_main(6, argv1);
cjpeg_main(6, argv2);
bailout:
if (fd >= 0) {
close(fd);
if (strlen(filename) > 0) unlink(filename);
}
return 0;
}

View File

@@ -194,7 +194,14 @@ jpeg_finish_compress(j_compress_ptr cinfo)
/* We bypass the main controller and invoke coef controller directly; /* We bypass the main controller and invoke coef controller directly;
* all work is being done from the coefficient buffer. * all work is being done from the coefficient buffer.
*/ */
if (cinfo->data_precision == 12) { if (cinfo->data_precision == 16) {
#ifdef C_LOSSLESS_SUPPORTED
if (!(*cinfo->coef->compress_data_16) (cinfo, (J16SAMPIMAGE)NULL))
ERREXIT(cinfo, JERR_CANT_SUSPEND);
#else
ERREXIT1(cinfo, JERR_BAD_PRECISION, cinfo->data_precision);
#endif
} else if (cinfo->data_precision == 12) {
if (!(*cinfo->coef->compress_data_12) (cinfo, (J12SAMPIMAGE)NULL)) if (!(*cinfo->coef->compress_data_12) (cinfo, (J12SAMPIMAGE)NULL))
ERREXIT(cinfo, JERR_CANT_SUSPEND); ERREXIT(cinfo, JERR_CANT_SUSPEND);
} else { } else {

View File

@@ -85,6 +85,7 @@ GLOBAL(JDIMENSION)
_jpeg_write_scanlines(j_compress_ptr cinfo, _JSAMPARRAY scanlines, _jpeg_write_scanlines(j_compress_ptr cinfo, _JSAMPARRAY scanlines,
JDIMENSION num_lines) JDIMENSION num_lines)
{ {
#if BITS_IN_JSAMPLE != 16 || defined(C_LOSSLESS_SUPPORTED)
JDIMENSION row_ctr, rows_left; JDIMENSION row_ctr, rows_left;
if (cinfo->data_precision != BITS_IN_JSAMPLE) if (cinfo->data_precision != BITS_IN_JSAMPLE)
@@ -119,9 +120,15 @@ _jpeg_write_scanlines(j_compress_ptr cinfo, _JSAMPARRAY scanlines,
(*cinfo->main->_process_data) (cinfo, scanlines, &row_ctr, num_lines); (*cinfo->main->_process_data) (cinfo, scanlines, &row_ctr, num_lines);
cinfo->next_scanline += row_ctr; cinfo->next_scanline += row_ctr;
return row_ctr; return row_ctr;
#else
ERREXIT1(cinfo, JERR_BAD_PRECISION, cinfo->data_precision);
return 0;
#endif
} }
#if BITS_IN_JSAMPLE != 16
/* /*
* Alternate entry point to write raw data. * Alternate entry point to write raw data.
* Processes exactly one iMCU row per call, unless suspended. * Processes exactly one iMCU row per call, unless suspended.
@@ -176,3 +183,5 @@ _jpeg_write_raw_data(j_compress_ptr cinfo, _JSAMPIMAGE data,
cinfo->next_scanline += lines_per_iMCU_row; cinfo->next_scanline += lines_per_iMCU_row;
return lines_per_iMCU_row; return lines_per_iMCU_row;
} }
#endif /* BITS_IN_JSAMPLE != 16 */

View File

@@ -33,6 +33,7 @@ rgb_ycc_convert_internal(j_compress_ptr cinfo, _JSAMPARRAY input_buf,
_JSAMPIMAGE output_buf, JDIMENSION output_row, _JSAMPIMAGE output_buf, JDIMENSION output_row,
int num_rows) int num_rows)
{ {
#if BITS_IN_JSAMPLE != 16
my_cconvert_ptr cconvert = (my_cconvert_ptr)cinfo->cconvert; my_cconvert_ptr cconvert = (my_cconvert_ptr)cinfo->cconvert;
register int r, g, b; register int r, g, b;
register JLONG *ctab = cconvert->rgb_ycc_tab; register JLONG *ctab = cconvert->rgb_ycc_tab;
@@ -68,6 +69,9 @@ rgb_ycc_convert_internal(j_compress_ptr cinfo, _JSAMPARRAY input_buf,
ctab[b + B_CR_OFF]) >> SCALEBITS); ctab[b + B_CR_OFF]) >> SCALEBITS);
} }
} }
#else
ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL);
#endif
} }
@@ -87,6 +91,7 @@ rgb_gray_convert_internal(j_compress_ptr cinfo, _JSAMPARRAY input_buf,
_JSAMPIMAGE output_buf, JDIMENSION output_row, _JSAMPIMAGE output_buf, JDIMENSION output_row,
int num_rows) int num_rows)
{ {
#if BITS_IN_JSAMPLE != 16
my_cconvert_ptr cconvert = (my_cconvert_ptr)cinfo->cconvert; my_cconvert_ptr cconvert = (my_cconvert_ptr)cinfo->cconvert;
register int r, g, b; register int r, g, b;
register JLONG *ctab = cconvert->rgb_ycc_tab; register JLONG *ctab = cconvert->rgb_ycc_tab;
@@ -109,6 +114,9 @@ rgb_gray_convert_internal(j_compress_ptr cinfo, _JSAMPARRAY input_buf,
ctab[b + B_Y_OFF]) >> SCALEBITS); ctab[b + B_Y_OFF]) >> SCALEBITS);
} }
} }
#else
ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL);
#endif
} }

View File

@@ -20,13 +20,17 @@
#include "jsamplecomp.h" #include "jsamplecomp.h"
#if BITS_IN_JSAMPLE != 16 || defined(C_LOSSLESS_SUPPORTED)
/* Private subobject */ /* Private subobject */
typedef struct { typedef struct {
struct jpeg_color_converter pub; /* public fields */ struct jpeg_color_converter pub; /* public fields */
#if BITS_IN_JSAMPLE != 16
/* Private state for RGB->YCC conversion */ /* Private state for RGB->YCC conversion */
JLONG *rgb_ycc_tab; /* => table for RGB to YCbCr conversion */ JLONG *rgb_ycc_tab; /* => table for RGB to YCbCr conversion */
#endif
} my_color_converter; } my_color_converter;
typedef my_color_converter *my_cconvert_ptr; typedef my_color_converter *my_cconvert_ptr;
@@ -209,6 +213,7 @@ typedef my_color_converter *my_cconvert_ptr;
METHODDEF(void) METHODDEF(void)
rgb_ycc_start(j_compress_ptr cinfo) rgb_ycc_start(j_compress_ptr cinfo)
{ {
#if BITS_IN_JSAMPLE != 16
my_cconvert_ptr cconvert = (my_cconvert_ptr)cinfo->cconvert; my_cconvert_ptr cconvert = (my_cconvert_ptr)cinfo->cconvert;
JLONG *rgb_ycc_tab; JLONG *rgb_ycc_tab;
JLONG i; JLONG i;
@@ -235,6 +240,9 @@ rgb_ycc_start(j_compress_ptr cinfo)
rgb_ycc_tab[i + G_CR_OFF] = (-FIX(0.41869)) * i; rgb_ycc_tab[i + G_CR_OFF] = (-FIX(0.41869)) * i;
rgb_ycc_tab[i + B_CR_OFF] = (-FIX(0.08131)) * i; rgb_ycc_tab[i + B_CR_OFF] = (-FIX(0.08131)) * i;
} }
#else
ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL);
#endif
} }
@@ -388,6 +396,7 @@ METHODDEF(void)
cmyk_ycck_convert(j_compress_ptr cinfo, _JSAMPARRAY input_buf, cmyk_ycck_convert(j_compress_ptr cinfo, _JSAMPARRAY input_buf,
_JSAMPIMAGE output_buf, JDIMENSION output_row, int num_rows) _JSAMPIMAGE output_buf, JDIMENSION output_row, int num_rows)
{ {
#if BITS_IN_JSAMPLE != 16
my_cconvert_ptr cconvert = (my_cconvert_ptr)cinfo->cconvert; my_cconvert_ptr cconvert = (my_cconvert_ptr)cinfo->cconvert;
register int r, g, b; register int r, g, b;
register JLONG *ctab = cconvert->rgb_ycc_tab; register JLONG *ctab = cconvert->rgb_ycc_tab;
@@ -426,6 +435,9 @@ cmyk_ycck_convert(j_compress_ptr cinfo, _JSAMPARRAY input_buf,
ctab[b + B_CR_OFF]) >> SCALEBITS); ctab[b + B_CR_OFF]) >> SCALEBITS);
} }
} }
#else
ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL);
#endif
} }
@@ -716,3 +728,5 @@ _jinit_color_converter(j_compress_ptr cinfo)
break; break;
} }
} }
#endif /* BITS_IN_JSAMPLE != 16 || defined(C_LOSSLESS_SUPPORTED) */

View File

@@ -40,7 +40,16 @@ jinit_compress_master(j_compress_ptr cinfo)
/* Preprocessing */ /* Preprocessing */
if (!cinfo->raw_data_in) { if (!cinfo->raw_data_in) {
if (cinfo->data_precision == 12) { if (cinfo->data_precision == 16) {
#ifdef C_LOSSLESS_SUPPORTED
j16init_color_converter(cinfo);
j16init_downsampler(cinfo);
j16init_c_prep_controller(cinfo,
FALSE /* never need full buffer here */);
#else
ERREXIT1(cinfo, JERR_BAD_PRECISION, cinfo->data_precision);
#endif
} else if (cinfo->data_precision == 12) {
j12init_color_converter(cinfo); j12init_color_converter(cinfo);
j12init_downsampler(cinfo); j12init_downsampler(cinfo);
j12init_c_prep_controller(cinfo, j12init_c_prep_controller(cinfo,
@@ -55,7 +64,9 @@ jinit_compress_master(j_compress_ptr cinfo)
if (cinfo->master->lossless) { if (cinfo->master->lossless) {
#ifdef C_LOSSLESS_SUPPORTED #ifdef C_LOSSLESS_SUPPORTED
/* Prediction, sample differencing, and point transform */ /* Prediction, sample differencing, and point transform */
if (cinfo->data_precision == 12) if (cinfo->data_precision == 16)
j16init_lossless_compressor(cinfo);
else if (cinfo->data_precision == 12)
j12init_lossless_compressor(cinfo); j12init_lossless_compressor(cinfo);
else else
jinit_lossless_compressor(cinfo); jinit_lossless_compressor(cinfo);
@@ -67,7 +78,10 @@ jinit_compress_master(j_compress_ptr cinfo)
} }
/* Need a full-image difference buffer in any multi-pass mode. */ /* Need a full-image difference buffer in any multi-pass mode. */
if (cinfo->data_precision == 12) if (cinfo->data_precision == 16)
j16init_c_diff_controller(cinfo, (boolean)(cinfo->num_scans > 1 ||
cinfo->optimize_coding));
else if (cinfo->data_precision == 12)
j12init_c_diff_controller(cinfo, (boolean)(cinfo->num_scans > 1 || j12init_c_diff_controller(cinfo, (boolean)(cinfo->num_scans > 1 ||
cinfo->optimize_coding)); cinfo->optimize_coding));
else else
@@ -77,6 +91,8 @@ jinit_compress_master(j_compress_ptr cinfo)
ERREXIT(cinfo, JERR_NOT_COMPILED); ERREXIT(cinfo, JERR_NOT_COMPILED);
#endif #endif
} else { } else {
if (cinfo->data_precision == 16)
ERREXIT1(cinfo, JERR_BAD_PRECISION, cinfo->data_precision);
/* Forward DCT */ /* Forward DCT */
if (cinfo->data_precision == 12) if (cinfo->data_precision == 12)
j12init_forward_dct(cinfo); j12init_forward_dct(cinfo);
@@ -109,7 +125,13 @@ jinit_compress_master(j_compress_ptr cinfo)
cinfo->optimize_coding)); cinfo->optimize_coding));
} }
if (cinfo->data_precision == 12) if (cinfo->data_precision == 16)
#ifdef C_LOSSLESS_SUPPORTED
j16init_c_main_controller(cinfo, FALSE /* never need full buffer here */);
#else
ERREXIT1(cinfo, JERR_BAD_PRECISION, cinfo->data_precision);
#endif
else if (cinfo->data_precision == 12)
j12init_c_main_controller(cinfo, FALSE /* never need full buffer here */); j12init_c_main_controller(cinfo, FALSE /* never need full buffer here */);
else else
jinit_c_main_controller(cinfo, FALSE /* never need full buffer here */); jinit_c_main_controller(cinfo, FALSE /* never need full buffer here */);

View File

@@ -21,6 +21,8 @@
#include "jsamplecomp.h" #include "jsamplecomp.h"
#if BITS_IN_JSAMPLE != 16 || defined(C_LOSSLESS_SUPPORTED)
/* Private buffer controller object */ /* Private buffer controller object */
typedef struct { typedef struct {
@@ -167,3 +169,5 @@ _jinit_c_main_controller(j_compress_ptr cinfo, boolean need_full_buffer)
} }
} }
} }
#endif /* BITS_IN_JSAMPLE != 16 || defined(C_LOSSLESS_SUPPORTED) */

View File

@@ -83,7 +83,12 @@ initial_setup(j_compress_ptr cinfo, boolean transcode_only)
if ((long)jd_samplesperrow != samplesperrow) if ((long)jd_samplesperrow != samplesperrow)
ERREXIT(cinfo, JERR_WIDTH_OVERFLOW); ERREXIT(cinfo, JERR_WIDTH_OVERFLOW);
#ifdef C_LOSSLESS_SUPPORTED
if (cinfo->data_precision != 8 && cinfo->data_precision != 12 &&
cinfo->data_precision != 16)
#else
if (cinfo->data_precision != 8 && cinfo->data_precision != 12) if (cinfo->data_precision != 8 && cinfo->data_precision != 12)
#endif
ERREXIT1(cinfo, JERR_BAD_PRECISION, cinfo->data_precision); ERREXIT1(cinfo, JERR_BAD_PRECISION, cinfo->data_precision);
/* Check that number of components won't exceed internal array sizes */ /* Check that number of components won't exceed internal array sizes */

View File

@@ -25,6 +25,8 @@
#include "jsamplecomp.h" #include "jsamplecomp.h"
#if BITS_IN_JSAMPLE != 16 || defined(C_LOSSLESS_SUPPORTED)
/* At present, jcsample.c can request context rows only for smoothing. /* At present, jcsample.c can request context rows only for smoothing.
* In the future, we might also need context rows for CCIR601 sampling * In the future, we might also need context rows for CCIR601 sampling
* or other more-complex downsampling procedures. The code to support * or other more-complex downsampling procedures. The code to support
@@ -359,3 +361,5 @@ _jinit_c_prep_controller(j_compress_ptr cinfo, boolean need_full_buffer)
} }
} }
} }
#endif /* BITS_IN_JSAMPLE != 16 || defined(C_LOSSLESS_SUPPORTED) */

View File

@@ -59,6 +59,8 @@
#include "jsamplecomp.h" #include "jsamplecomp.h"
#if BITS_IN_JSAMPLE != 16 || defined(C_LOSSLESS_SUPPORTED)
/* Pointer to routine to downsample a single component */ /* Pointer to routine to downsample a single component */
typedef void (*downsample1_ptr) (j_compress_ptr cinfo, typedef void (*downsample1_ptr) (j_compress_ptr cinfo,
jpeg_component_info *compptr, jpeg_component_info *compptr,
@@ -537,3 +539,5 @@ _jinit_downsampler(j_compress_ptr cinfo)
TRACEMS(cinfo, 0, JTRC_SMOOTH_NOTIMPL); TRACEMS(cinfo, 0, JTRC_SMOOTH_NOTIMPL);
#endif #endif
} }
#endif /* BITS_IN_JSAMPLE != 16 || defined(C_LOSSLESS_SUPPORTED) */

View File

@@ -19,8 +19,13 @@
*/ */
#include "jinclude.h" #include "jinclude.h"
#if BITS_IN_JSAMPLE != 16 || defined(D_LOSSLESS_SUPPORTED)
#include "jdmainct.h" #include "jdmainct.h"
#include "jdcoefct.h" #include "jdcoefct.h"
#else
#define JPEG_INTERNALS
#include "jpeglib.h"
#endif
#include "jdmaster.h" #include "jdmaster.h"
#include "jdmerge.h" #include "jdmerge.h"
#include "jdsample.h" #include "jdsample.h"
@@ -151,6 +156,8 @@ output_pass_setup(j_decompress_ptr cinfo)
#endif /* BITS_IN_JSAMPLE == 8 */ #endif /* BITS_IN_JSAMPLE == 8 */
#if BITS_IN_JSAMPLE != 16
/* /*
* Enable partial scanline decompression * Enable partial scanline decompression
* *
@@ -274,6 +281,8 @@ _jpeg_crop_scanline(j_decompress_ptr cinfo, JDIMENSION *xoffset,
} }
} }
#endif /* BITS_IN_JSAMPLE != 16 */
/* /*
* Read some scanlines of data from the JPEG decompressor. * Read some scanlines of data from the JPEG decompressor.
@@ -292,6 +301,7 @@ GLOBAL(JDIMENSION)
_jpeg_read_scanlines(j_decompress_ptr cinfo, _JSAMPARRAY scanlines, _jpeg_read_scanlines(j_decompress_ptr cinfo, _JSAMPARRAY scanlines,
JDIMENSION max_lines) JDIMENSION max_lines)
{ {
#if BITS_IN_JSAMPLE != 16 || defined(D_LOSSLESS_SUPPORTED)
JDIMENSION row_ctr; JDIMENSION row_ctr;
if (cinfo->data_precision != BITS_IN_JSAMPLE) if (cinfo->data_precision != BITS_IN_JSAMPLE)
@@ -316,9 +326,15 @@ _jpeg_read_scanlines(j_decompress_ptr cinfo, _JSAMPARRAY scanlines,
(*cinfo->main->_process_data) (cinfo, scanlines, &row_ctr, max_lines); (*cinfo->main->_process_data) (cinfo, scanlines, &row_ctr, max_lines);
cinfo->output_scanline += row_ctr; cinfo->output_scanline += row_ctr;
return row_ctr; return row_ctr;
#else
ERREXIT1(cinfo, JERR_BAD_PRECISION, cinfo->data_precision);
return 0;
#endif
} }
#if BITS_IN_JSAMPLE != 16
/* Dummy color convert function used by _jpeg_skip_scanlines() */ /* Dummy color convert function used by _jpeg_skip_scanlines() */
LOCAL(void) LOCAL(void)
noop_convert(j_decompress_ptr cinfo, _JSAMPIMAGE input_buf, noop_convert(j_decompress_ptr cinfo, _JSAMPIMAGE input_buf,
@@ -660,6 +676,8 @@ _jpeg_read_raw_data(j_decompress_ptr cinfo, _JSAMPIMAGE data,
return lines_per_iMCU_row; return lines_per_iMCU_row;
} }
#endif /* BITS_IN_JSAMPLE != 16 */
#if BITS_IN_JSAMPLE == 8 #if BITS_IN_JSAMPLE == 8

View File

@@ -6,6 +6,7 @@
* libjpeg-turbo Modifications: * libjpeg-turbo Modifications:
* Copyright 2009 Pierre Ossman <ossman@cendio.se> for Cendio AB * Copyright 2009 Pierre Ossman <ossman@cendio.se> for Cendio AB
* Copyright (C) 2020, Google, Inc. * Copyright (C) 2020, Google, Inc.
* Copyright (C) 2022, D. R. Commander.
* For conditions of distribution and use, see the accompanying README.ijg * For conditions of distribution and use, see the accompanying README.ijg
* file. * file.
*/ */
@@ -14,6 +15,8 @@
#include "jpeglib.h" #include "jpeglib.h"
#if BITS_IN_JSAMPLE != 16 || defined(D_LOSSLESS_SUPPORTED)
/* Block smoothing is only applicable for progressive JPEG, so: */ /* Block smoothing is only applicable for progressive JPEG, so: */
#ifndef D_PROGRESSIVE_SUPPORTED #ifndef D_PROGRESSIVE_SUPPORTED
#undef BLOCK_SMOOTHING_SUPPORTED #undef BLOCK_SMOOTHING_SUPPORTED
@@ -81,3 +84,5 @@ start_iMCU_row(j_decompress_ptr cinfo)
coef->MCU_ctr = 0; coef->MCU_ctr = 0;
coef->MCU_vert_offset = 0; coef->MCU_vert_offset = 0;
} }
#endif /* BITS_IN_JSAMPLE != 16 || defined(D_LOSSLESS_SUPPORTED) */

View File

@@ -21,6 +21,7 @@ ycc_rgb565_convert_internal(j_decompress_ptr cinfo, _JSAMPIMAGE input_buf,
JDIMENSION input_row, _JSAMPARRAY output_buf, JDIMENSION input_row, _JSAMPARRAY output_buf,
int num_rows) int num_rows)
{ {
#if BITS_IN_JSAMPLE != 16
my_cconvert_ptr cconvert = (my_cconvert_ptr)cinfo->cconvert; my_cconvert_ptr cconvert = (my_cconvert_ptr)cinfo->cconvert;
register int y, cb, cr; register int y, cb, cr;
register _JSAMPROW outptr; register _JSAMPROW outptr;
@@ -91,6 +92,9 @@ ycc_rgb565_convert_internal(j_decompress_ptr cinfo, _JSAMPIMAGE input_buf,
*(INT16 *)outptr = (INT16)rgb; *(INT16 *)outptr = (INT16)rgb;
} }
} }
#else
ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL);
#endif
} }
@@ -100,6 +104,7 @@ ycc_rgb565D_convert_internal(j_decompress_ptr cinfo, _JSAMPIMAGE input_buf,
JDIMENSION input_row, _JSAMPARRAY output_buf, JDIMENSION input_row, _JSAMPARRAY output_buf,
int num_rows) int num_rows)
{ {
#if BITS_IN_JSAMPLE != 16
my_cconvert_ptr cconvert = (my_cconvert_ptr)cinfo->cconvert; my_cconvert_ptr cconvert = (my_cconvert_ptr)cinfo->cconvert;
register int y, cb, cr; register int y, cb, cr;
register _JSAMPROW outptr; register _JSAMPROW outptr;
@@ -177,6 +182,9 @@ ycc_rgb565D_convert_internal(j_decompress_ptr cinfo, _JSAMPIMAGE input_buf,
*(INT16 *)outptr = (INT16)rgb; *(INT16 *)outptr = (INT16)rgb;
} }
} }
#else
ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL);
#endif
} }

View File

@@ -32,6 +32,7 @@ ycc_rgb_convert_internal(j_decompress_ptr cinfo, _JSAMPIMAGE input_buf,
JDIMENSION input_row, _JSAMPARRAY output_buf, JDIMENSION input_row, _JSAMPARRAY output_buf,
int num_rows) int num_rows)
{ {
#if BITS_IN_JSAMPLE != 16
my_cconvert_ptr cconvert = (my_cconvert_ptr)cinfo->cconvert; my_cconvert_ptr cconvert = (my_cconvert_ptr)cinfo->cconvert;
register int y, cb, cr; register int y, cb, cr;
register _JSAMPROW outptr; register _JSAMPROW outptr;
@@ -70,6 +71,9 @@ ycc_rgb_convert_internal(j_decompress_ptr cinfo, _JSAMPIMAGE input_buf,
outptr += RGB_PIXELSIZE; outptr += RGB_PIXELSIZE;
} }
} }
#else
ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL);
#endif
} }

View File

@@ -21,11 +21,14 @@
#include "jsamplecomp.h" #include "jsamplecomp.h"
#if BITS_IN_JSAMPLE != 16 || defined(D_LOSSLESS_SUPPORTED)
/* Private subobject */ /* Private subobject */
typedef struct { typedef struct {
struct jpeg_color_deconverter pub; /* public fields */ struct jpeg_color_deconverter pub; /* public fields */
#if BITS_IN_JSAMPLE != 16
/* Private state for YCC->RGB conversion */ /* Private state for YCC->RGB conversion */
int *Cr_r_tab; /* => table for Cr to R conversion */ int *Cr_r_tab; /* => table for Cr to R conversion */
int *Cb_b_tab; /* => table for Cb to B conversion */ int *Cb_b_tab; /* => table for Cb to B conversion */
@@ -34,6 +37,7 @@ typedef struct {
/* Private state for RGB->Y conversion */ /* Private state for RGB->Y conversion */
JLONG *rgb_y_tab; /* => table for RGB to Y conversion */ JLONG *rgb_y_tab; /* => table for RGB to Y conversion */
#endif
} my_color_deconverter; } my_color_deconverter;
typedef my_color_deconverter *my_cconvert_ptr; typedef my_color_deconverter *my_cconvert_ptr;
@@ -210,6 +214,7 @@ typedef my_color_deconverter *my_cconvert_ptr;
LOCAL(void) LOCAL(void)
build_ycc_rgb_table(j_decompress_ptr cinfo) build_ycc_rgb_table(j_decompress_ptr cinfo)
{ {
#if BITS_IN_JSAMPLE != 16
my_cconvert_ptr cconvert = (my_cconvert_ptr)cinfo->cconvert; my_cconvert_ptr cconvert = (my_cconvert_ptr)cinfo->cconvert;
int i; int i;
JLONG x; JLONG x;
@@ -243,6 +248,9 @@ build_ycc_rgb_table(j_decompress_ptr cinfo)
/* We also add in ONE_HALF so that need not do it in inner loop */ /* We also add in ONE_HALF so that need not do it in inner loop */
cconvert->Cb_g_tab[i] = (-FIX(0.34414)) * x + ONE_HALF; cconvert->Cb_g_tab[i] = (-FIX(0.34414)) * x + ONE_HALF;
} }
#else
ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL);
#endif
} }
@@ -301,6 +309,7 @@ ycc_rgb_convert(j_decompress_ptr cinfo, _JSAMPIMAGE input_buf,
LOCAL(void) LOCAL(void)
build_rgb_y_table(j_decompress_ptr cinfo) build_rgb_y_table(j_decompress_ptr cinfo)
{ {
#if BITS_IN_JSAMPLE != 16
my_cconvert_ptr cconvert = (my_cconvert_ptr)cinfo->cconvert; my_cconvert_ptr cconvert = (my_cconvert_ptr)cinfo->cconvert;
JLONG *rgb_y_tab; JLONG *rgb_y_tab;
JLONG i; JLONG i;
@@ -315,6 +324,9 @@ build_rgb_y_table(j_decompress_ptr cinfo)
rgb_y_tab[i + G_Y_OFF] = FIX(0.58700) * i; rgb_y_tab[i + G_Y_OFF] = FIX(0.58700) * i;
rgb_y_tab[i + B_Y_OFF] = FIX(0.11400) * i + ONE_HALF; rgb_y_tab[i + B_Y_OFF] = FIX(0.11400) * i + ONE_HALF;
} }
#else
ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL);
#endif
} }
@@ -326,6 +338,7 @@ METHODDEF(void)
rgb_gray_convert(j_decompress_ptr cinfo, _JSAMPIMAGE input_buf, rgb_gray_convert(j_decompress_ptr cinfo, _JSAMPIMAGE input_buf,
JDIMENSION input_row, _JSAMPARRAY output_buf, int num_rows) JDIMENSION input_row, _JSAMPARRAY output_buf, int num_rows)
{ {
#if BITS_IN_JSAMPLE != 16
my_cconvert_ptr cconvert = (my_cconvert_ptr)cinfo->cconvert; my_cconvert_ptr cconvert = (my_cconvert_ptr)cinfo->cconvert;
register int r, g, b; register int r, g, b;
register JLONG *ctab = cconvert->rgb_y_tab; register JLONG *ctab = cconvert->rgb_y_tab;
@@ -349,6 +362,9 @@ rgb_gray_convert(j_decompress_ptr cinfo, _JSAMPIMAGE input_buf,
ctab[b + B_Y_OFF]) >> SCALEBITS); ctab[b + B_Y_OFF]) >> SCALEBITS);
} }
} }
#else
ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL);
#endif
} }
@@ -528,6 +544,7 @@ METHODDEF(void)
ycck_cmyk_convert(j_decompress_ptr cinfo, _JSAMPIMAGE input_buf, ycck_cmyk_convert(j_decompress_ptr cinfo, _JSAMPIMAGE input_buf,
JDIMENSION input_row, _JSAMPARRAY output_buf, int num_rows) JDIMENSION input_row, _JSAMPARRAY output_buf, int num_rows)
{ {
#if BITS_IN_JSAMPLE != 16
my_cconvert_ptr cconvert = (my_cconvert_ptr)cinfo->cconvert; my_cconvert_ptr cconvert = (my_cconvert_ptr)cinfo->cconvert;
register int y, cb, cr; register int y, cb, cr;
register _JSAMPROW outptr; register _JSAMPROW outptr;
@@ -564,6 +581,9 @@ ycck_cmyk_convert(j_decompress_ptr cinfo, _JSAMPIMAGE input_buf,
outptr += 4; outptr += 4;
} }
} }
#else
ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL);
#endif
} }
@@ -901,3 +921,5 @@ _jinit_color_deconverter(j_decompress_ptr cinfo)
else else
cinfo->output_components = cinfo->out_color_components; cinfo->output_components = cinfo->out_color_components;
} }
#endif /* BITS_IN_JSAMPLE != 16 || defined(D_LOSSLESS_SUPPORTED) */

View File

@@ -57,7 +57,12 @@ initial_setup(j_decompress_ptr cinfo)
ERREXIT1(cinfo, JERR_IMAGE_TOO_BIG, (unsigned int)JPEG_MAX_DIMENSION); ERREXIT1(cinfo, JERR_IMAGE_TOO_BIG, (unsigned int)JPEG_MAX_DIMENSION);
/* For now, precision must match compiled-in value... */ /* For now, precision must match compiled-in value... */
#ifdef D_LOSSLESS_SUPPORTED
if (cinfo->data_precision != 8 && cinfo->data_precision != 12 &&
cinfo->data_precision != 16)
#else
if (cinfo->data_precision != 8 && cinfo->data_precision != 12) if (cinfo->data_precision != 8 && cinfo->data_precision != 12)
#endif
ERREXIT1(cinfo, JERR_BAD_PRECISION, cinfo->data_precision); ERREXIT1(cinfo, JERR_BAD_PRECISION, cinfo->data_precision);
/* Check that number of components won't exceed internal array sizes */ /* Check that number of components won't exceed internal array sizes */

View File

@@ -20,6 +20,8 @@
#include "jdmainct.h" #include "jdmainct.h"
#if BITS_IN_JSAMPLE != 16 || defined(D_LOSSLESS_SUPPORTED)
/* /*
* In the current system design, the main buffer need never be a full-image * In the current system design, the main buffer need never be a full-image
* buffer; any full-height buffers will be found inside the coefficient, * buffer; any full-height buffers will be found inside the coefficient,
@@ -463,3 +465,5 @@ _jinit_d_main_controller(j_decompress_ptr cinfo, boolean need_full_buffer)
(JDIMENSION)(rgroup * ngroups)); (JDIMENSION)(rgroup * ngroups));
} }
} }
#endif /* BITS_IN_JSAMPLE != 16 || defined(D_LOSSLESS_SUPPORTED) */

View File

@@ -15,6 +15,8 @@
#include "jsamplecomp.h" #include "jsamplecomp.h"
#if BITS_IN_JSAMPLE != 16 || defined(D_LOSSLESS_SUPPORTED)
/* Private buffer controller object */ /* Private buffer controller object */
typedef struct { typedef struct {
@@ -72,3 +74,5 @@ set_wraparound_pointers(j_decompress_ptr cinfo)
} }
} }
} }
#endif /* BITS_IN_JSAMPLE != 16 || defined(D_LOSSLESS_SUPPORTED) */

View File

@@ -414,9 +414,39 @@ prepare_range_limit_table(j_decompress_ptr cinfo)
{ {
JSAMPLE *table; JSAMPLE *table;
J12SAMPLE *table12; J12SAMPLE *table12;
#ifdef D_LOSSLESS_SUPPORTED
J16SAMPLE *table16;
#endif
int i; int i;
if (cinfo->data_precision == 12) { if (cinfo->data_precision == 16) {
#ifdef D_LOSSLESS_SUPPORTED
table16 = (J16SAMPLE *)
(*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE,
(5 * (MAXJ16SAMPLE + 1) + CENTERJ16SAMPLE) *
sizeof(J16SAMPLE));
table16 += (MAXJ16SAMPLE + 1); /* allow negative subscripts of simple
table */
cinfo->sample_range_limit = (JSAMPLE *)table16;
/* First segment of "simple" table: limit[x] = 0 for x < 0 */
memset(table16 - (MAXJ16SAMPLE + 1), 0,
(MAXJ16SAMPLE + 1) * sizeof(J16SAMPLE));
/* Main part of "simple" table: limit[x] = x */
for (i = 0; i <= MAXJ16SAMPLE; i++)
table16[i] = (J16SAMPLE)i;
table16 += CENTERJ16SAMPLE; /* Point to where post-IDCT table starts */
/* End of simple table, rest of first half of post-IDCT table */
for (i = CENTERJ16SAMPLE; i < 2 * (MAXJ16SAMPLE + 1); i++)
table16[i] = MAXJ16SAMPLE;
/* Second half of post-IDCT table */
memset(table16 + (2 * (MAXJ16SAMPLE + 1)), 0,
(2 * (MAXJ16SAMPLE + 1) - CENTERJ16SAMPLE) * sizeof(J16SAMPLE));
memcpy(table16 + (4 * (MAXJ16SAMPLE + 1) - CENTERJ16SAMPLE),
cinfo->sample_range_limit, CENTERJ16SAMPLE * sizeof(J16SAMPLE));
#else
ERREXIT1(cinfo, JERR_BAD_PRECISION, cinfo->data_precision);
#endif
} else if (cinfo->data_precision == 12) {
table12 = (J12SAMPLE *) table12 = (J12SAMPLE *)
(*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE, (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE,
(5 * (MAXJ12SAMPLE + 1) + CENTERJ12SAMPLE) * (5 * (MAXJ12SAMPLE + 1) + CENTERJ12SAMPLE) *
@@ -536,7 +566,13 @@ master_selection(j_decompress_ptr cinfo)
if (cinfo->enable_1pass_quant) { if (cinfo->enable_1pass_quant) {
#ifdef QUANT_1PASS_SUPPORTED #ifdef QUANT_1PASS_SUPPORTED
if (cinfo->data_precision == 12) if (cinfo->data_precision == 16)
#ifdef D_LOSSLESS_SUPPORTED
j16init_1pass_quantizer(cinfo);
#else
ERREXIT1(cinfo, JERR_BAD_PRECISION, cinfo->data_precision);
#endif
else if (cinfo->data_precision == 12)
j12init_1pass_quantizer(cinfo); j12init_1pass_quantizer(cinfo);
else else
jinit_1pass_quantizer(cinfo); jinit_1pass_quantizer(cinfo);
@@ -549,7 +585,13 @@ master_selection(j_decompress_ptr cinfo)
/* We use the 2-pass code to map to external colormaps. */ /* We use the 2-pass code to map to external colormaps. */
if (cinfo->enable_2pass_quant || cinfo->enable_external_quant) { if (cinfo->enable_2pass_quant || cinfo->enable_external_quant) {
#ifdef QUANT_2PASS_SUPPORTED #ifdef QUANT_2PASS_SUPPORTED
if (cinfo->data_precision == 12) if (cinfo->data_precision == 16)
#ifdef D_LOSSLESS_SUPPORTED
j16init_2pass_quantizer(cinfo);
#else
ERREXIT1(cinfo, JERR_BAD_PRECISION, cinfo->data_precision);
#endif
else if (cinfo->data_precision == 12)
j12init_2pass_quantizer(cinfo); j12init_2pass_quantizer(cinfo);
else else
jinit_2pass_quantizer(cinfo); jinit_2pass_quantizer(cinfo);
@@ -567,7 +609,9 @@ master_selection(j_decompress_ptr cinfo)
if (!cinfo->raw_data_out) { if (!cinfo->raw_data_out) {
if (master->using_merged_upsample) { if (master->using_merged_upsample) {
#ifdef UPSAMPLE_MERGING_SUPPORTED #ifdef UPSAMPLE_MERGING_SUPPORTED
if (cinfo->data_precision == 12) if (cinfo->data_precision == 16)
ERREXIT1(cinfo, JERR_BAD_PRECISION, cinfo->data_precision);
else if (cinfo->data_precision == 12)
j12init_merged_upsampler(cinfo); /* does color conversion too */ j12init_merged_upsampler(cinfo); /* does color conversion too */
else else
jinit_merged_upsampler(cinfo); /* does color conversion too */ jinit_merged_upsampler(cinfo); /* does color conversion too */
@@ -575,7 +619,14 @@ master_selection(j_decompress_ptr cinfo)
ERREXIT(cinfo, JERR_NOT_COMPILED); ERREXIT(cinfo, JERR_NOT_COMPILED);
#endif #endif
} else { } else {
if (cinfo->data_precision == 12) { if (cinfo->data_precision == 16) {
#ifdef D_LOSSLESS_SUPPORTED
j16init_color_deconverter(cinfo);
j16init_upsampler(cinfo);
#else
ERREXIT1(cinfo, JERR_BAD_PRECISION, cinfo->data_precision);
#endif
} else if (cinfo->data_precision == 12) {
j12init_color_deconverter(cinfo); j12init_color_deconverter(cinfo);
j12init_upsampler(cinfo); j12init_upsampler(cinfo);
} else { } else {
@@ -583,7 +634,13 @@ master_selection(j_decompress_ptr cinfo)
jinit_upsampler(cinfo); jinit_upsampler(cinfo);
} }
} }
if (cinfo->data_precision == 12) if (cinfo->data_precision == 16)
#ifdef D_LOSSLESS_SUPPORTED
j16init_d_post_controller(cinfo, cinfo->enable_2pass_quant);
#else
ERREXIT1(cinfo, JERR_BAD_PRECISION, cinfo->data_precision);
#endif
else if (cinfo->data_precision == 12)
j12init_d_post_controller(cinfo, cinfo->enable_2pass_quant); j12init_d_post_controller(cinfo, cinfo->enable_2pass_quant);
else else
jinit_d_post_controller(cinfo, cinfo->enable_2pass_quant); jinit_d_post_controller(cinfo, cinfo->enable_2pass_quant);
@@ -594,7 +651,9 @@ master_selection(j_decompress_ptr cinfo)
/* Prediction, sample undifferencing, point transform, and sample size /* Prediction, sample undifferencing, point transform, and sample size
* scaling * scaling
*/ */
if (cinfo->data_precision == 12) if (cinfo->data_precision == 16)
j16init_lossless_decompressor(cinfo);
else if (cinfo->data_precision == 12)
j12init_lossless_decompressor(cinfo); j12init_lossless_decompressor(cinfo);
else else
jinit_lossless_decompressor(cinfo); jinit_lossless_decompressor(cinfo);
@@ -608,7 +667,9 @@ master_selection(j_decompress_ptr cinfo)
/* Initialize principal buffer controllers. */ /* Initialize principal buffer controllers. */
use_c_buffer = cinfo->inputctl->has_multiple_scans || use_c_buffer = cinfo->inputctl->has_multiple_scans ||
cinfo->buffered_image; cinfo->buffered_image;
if (cinfo->data_precision == 12) if (cinfo->data_precision == 16)
j16init_d_diff_controller(cinfo, use_c_buffer);
else if (cinfo->data_precision == 12)
j12init_d_diff_controller(cinfo, use_c_buffer); j12init_d_diff_controller(cinfo, use_c_buffer);
else else
jinit_d_diff_controller(cinfo, use_c_buffer); jinit_d_diff_controller(cinfo, use_c_buffer);
@@ -616,6 +677,8 @@ master_selection(j_decompress_ptr cinfo)
ERREXIT(cinfo, JERR_NOT_COMPILED); ERREXIT(cinfo, JERR_NOT_COMPILED);
#endif #endif
} else { } else {
if (cinfo->data_precision == 16)
ERREXIT1(cinfo, JERR_BAD_PRECISION, cinfo->data_precision);
/* Inverse DCT */ /* Inverse DCT */
if (cinfo->data_precision == 12) if (cinfo->data_precision == 12)
j12init_inverse_dct(cinfo); j12init_inverse_dct(cinfo);
@@ -649,7 +712,14 @@ master_selection(j_decompress_ptr cinfo)
} }
if (!cinfo->raw_data_out) { if (!cinfo->raw_data_out) {
if (cinfo->data_precision == 12) if (cinfo->data_precision == 16)
#ifdef D_LOSSLESS_SUPPORTED
j16init_d_main_controller(cinfo,
FALSE /* never need full buffer here */);
#else
ERREXIT1(cinfo, JERR_BAD_PRECISION, cinfo->data_precision);
#endif
else if (cinfo->data_precision == 12)
j12init_d_main_controller(cinfo, j12init_d_main_controller(cinfo,
FALSE /* never need full buffer here */); FALSE /* never need full buffer here */);
else else

View File

@@ -25,6 +25,8 @@
#include "jsamplecomp.h" #include "jsamplecomp.h"
#if BITS_IN_JSAMPLE != 16 || defined(D_LOSSLESS_SUPPORTED)
/* Private buffer controller object */ /* Private buffer controller object */
typedef struct { typedef struct {
@@ -296,3 +298,5 @@ _jinit_d_post_controller(j_decompress_ptr cinfo, boolean need_full_buffer)
} }
} }
} }
#endif /* BITS_IN_JSAMPLE != 16 || defined(D_LOSSLESS_SUPPORTED) */

View File

@@ -32,6 +32,8 @@
#if BITS_IN_JSAMPLE != 16 || defined(D_LOSSLESS_SUPPORTED)
/* /*
* Initialize for an upsampling pass. * Initialize for an upsampling pass.
*/ */
@@ -534,3 +536,5 @@ _jinit_upsampler(j_decompress_ptr cinfo)
} }
} }
} }
#endif /* BITS_IN_JSAMPLE != 16 || defined(D_LOSSLESS_SUPPORTED) */

View File

@@ -353,9 +353,10 @@ alloc_small(j_common_ptr cinfo, int pool_id, size_t sizeofobject)
* request is large enough that it may as well be passed directly to * request is large enough that it may as well be passed directly to
* jpeg_get_large; the pool management just links everything together * jpeg_get_large; the pool management just links everything together
* so that we can free it all on demand. * so that we can free it all on demand.
* Note: the major use of "large" objects is in JSAMPARRAY/J12SAMPARRAY and * Note: the major use of "large" objects is in
* JBLOCKARRAY structures. The routines that create these structures (see * JSAMPARRAY/J12SAMPARRAY/J16SAMPARRAY and JBLOCKARRAY structures. The
* below) deliberately bunch rows together to ensure a large request size. * routines that create these structures (see below) deliberately bunch rows
* together to ensure a large request size.
*/ */
METHODDEF(void *) METHODDEF(void *)
@@ -441,11 +442,17 @@ alloc_sarray(j_common_ptr cinfo, int pool_id, JDIMENSION samplesperrow,
long ltemp; long ltemp;
J12SAMPARRAY result12; J12SAMPARRAY result12;
J12SAMPROW workspace12; J12SAMPROW workspace12;
#if defined(C_LOSSLESS_SUPPORTED) || defined(D_LOSSLESS_SUPPORTED)
J16SAMPARRAY result16;
J16SAMPROW workspace16;
#endif
int data_precision = cinfo->is_decompressor ? int data_precision = cinfo->is_decompressor ?
((j_decompress_ptr)cinfo)->data_precision : ((j_decompress_ptr)cinfo)->data_precision :
((j_compress_ptr)cinfo)->data_precision; ((j_compress_ptr)cinfo)->data_precision;
size_t sample_size = data_precision == 12 ? size_t sample_size = data_precision == 16 ?
sizeof(J12SAMPLE) : sizeof(JSAMPLE); sizeof(J16SAMPLE) : (data_precision == 12 ?
sizeof(J12SAMPLE) :
sizeof(JSAMPLE));
/* Make sure each row is properly aligned */ /* Make sure each row is properly aligned */
if ((ALIGN_SIZE % sample_size) != 0) if ((ALIGN_SIZE % sample_size) != 0)
@@ -470,7 +477,31 @@ alloc_sarray(j_common_ptr cinfo, int pool_id, JDIMENSION samplesperrow,
rowsperchunk = numrows; rowsperchunk = numrows;
mem->last_rowsperchunk = rowsperchunk; mem->last_rowsperchunk = rowsperchunk;
if (data_precision == 12) { if (data_precision == 16) {
#if defined(C_LOSSLESS_SUPPORTED) || defined(D_LOSSLESS_SUPPORTED)
/* Get space for row pointers (small object) */
result16 = (J16SAMPARRAY)alloc_small(cinfo, pool_id,
(size_t)(numrows *
sizeof(J16SAMPROW)));
/* Get the rows themselves (large objects) */
currow = 0;
while (currow < numrows) {
rowsperchunk = MIN(rowsperchunk, numrows - currow);
workspace16 = (J16SAMPROW)alloc_large(cinfo, pool_id,
(size_t)((size_t)rowsperchunk * (size_t)samplesperrow * sample_size));
for (i = rowsperchunk; i > 0; i--) {
result16[currow++] = workspace16;
workspace16 += samplesperrow;
}
}
return (JSAMPARRAY)result16;
#else
ERREXIT1(cinfo, JERR_BAD_PRECISION, data_precision);
return NULL;
#endif
} else if (data_precision == 12) {
/* Get space for row pointers (small object) */ /* Get space for row pointers (small object) */
result12 = (J12SAMPARRAY)alloc_small(cinfo, pool_id, result12 = (J12SAMPARRAY)alloc_small(cinfo, pool_id,
(size_t)(numrows * (size_t)(numrows *
@@ -672,8 +703,10 @@ realize_virt_arrays(j_common_ptr cinfo)
int data_precision = cinfo->is_decompressor ? int data_precision = cinfo->is_decompressor ?
((j_decompress_ptr)cinfo)->data_precision : ((j_decompress_ptr)cinfo)->data_precision :
((j_compress_ptr)cinfo)->data_precision; ((j_compress_ptr)cinfo)->data_precision;
size_t sample_size = data_precision == 12 ? size_t sample_size = data_precision == 16 ?
sizeof(J12SAMPLE) : sizeof(JSAMPLE); sizeof(J16SAMPLE) : (data_precision == 12 ?
sizeof(J12SAMPLE) :
sizeof(JSAMPLE));
/* Compute the minimum space needed (maxaccess rows in each buffer) /* Compute the minimum space needed (maxaccess rows in each buffer)
* and the maximum space needed (full image height in each buffer). * and the maximum space needed (full image height in each buffer).
@@ -788,8 +821,10 @@ do_sarray_io(j_common_ptr cinfo, jvirt_sarray_ptr ptr, boolean writing)
int data_precision = cinfo->is_decompressor ? int data_precision = cinfo->is_decompressor ?
((j_decompress_ptr)cinfo)->data_precision : ((j_decompress_ptr)cinfo)->data_precision :
((j_compress_ptr)cinfo)->data_precision; ((j_compress_ptr)cinfo)->data_precision;
size_t sample_size = data_precision == 12 ? size_t sample_size = data_precision == 16 ?
sizeof(J12SAMPLE) : sizeof(JSAMPLE); sizeof(J16SAMPLE) : (data_precision == 12 ?
sizeof(J12SAMPLE) :
sizeof(JSAMPLE));
bytesperrow = (long)ptr->samplesperrow * (long)sample_size; bytesperrow = (long)ptr->samplesperrow * (long)sample_size;
file_offset = ptr->cur_start_row * bytesperrow; file_offset = ptr->cur_start_row * bytesperrow;
@@ -805,7 +840,22 @@ do_sarray_io(j_common_ptr cinfo, jvirt_sarray_ptr ptr, boolean writing)
if (rows <= 0) /* this chunk might be past end of file! */ if (rows <= 0) /* this chunk might be past end of file! */
break; break;
byte_count = rows * bytesperrow; byte_count = rows * bytesperrow;
if (data_precision == 12) { if (data_precision == 16) {
#if defined(C_LOSSLESS_SUPPORTED) || defined(D_LOSSLESS_SUPPORTED)
J16SAMPARRAY mem_buffer16 = (J16SAMPARRAY)ptr->mem_buffer;
if (writing)
(*ptr->b_s_info.write_backing_store) (cinfo, &ptr->b_s_info,
(void *)mem_buffer16[i],
file_offset, byte_count);
else
(*ptr->b_s_info.read_backing_store) (cinfo, &ptr->b_s_info,
(void *)mem_buffer16[i],
file_offset, byte_count);
#else
ERREXIT1(cinfo, JERR_BAD_PRECISION, data_precision);
#endif
} else if (data_precision == 12) {
J12SAMPARRAY mem_buffer12 = (J12SAMPARRAY)ptr->mem_buffer; J12SAMPARRAY mem_buffer12 = (J12SAMPARRAY)ptr->mem_buffer;
if (writing) if (writing)
@@ -876,8 +926,10 @@ access_virt_sarray(j_common_ptr cinfo, jvirt_sarray_ptr ptr,
int data_precision = cinfo->is_decompressor ? int data_precision = cinfo->is_decompressor ?
((j_decompress_ptr)cinfo)->data_precision : ((j_decompress_ptr)cinfo)->data_precision :
((j_compress_ptr)cinfo)->data_precision; ((j_compress_ptr)cinfo)->data_precision;
size_t sample_size = data_precision == 12 ? size_t sample_size = data_precision == 16 ?
sizeof(J12SAMPLE) : sizeof(JSAMPLE); sizeof(J16SAMPLE) : (data_precision == 12 ?
sizeof(J12SAMPLE) :
sizeof(JSAMPLE));
/* debugging check */ /* debugging check */
if (end_row > ptr->rows_in_array || num_rows > ptr->maxaccess || if (end_row > ptr->rows_in_array || num_rows > ptr->maxaccess ||

View File

@@ -60,6 +60,14 @@ typedef short J12SAMPLE;
#define CENTERJ12SAMPLE 2048 #define CENTERJ12SAMPLE 2048
/* J16SAMPLE should be the smallest type that will hold the values 0..65535. */
typedef unsigned short J16SAMPLE;
#define MAXJ16SAMPLE 65535
#define CENTERJ16SAMPLE 32768
/* Representation of a DCT frequency coefficient. /* Representation of a DCT frequency coefficient.
* This should be a signed value of at least 16 bits; "short" is usually OK. * This should be a signed value of at least 16 bits; "short" is usually OK.
* Again, we allocate large arrays of these, but you can change to int * Again, we allocate large arrays of these, but you can change to int

View File

@@ -106,6 +106,10 @@ struct jpeg_c_main_controller {
JDIMENSION *in_row_ctr, JDIMENSION in_rows_avail); JDIMENSION *in_row_ctr, JDIMENSION in_rows_avail);
void (*process_data_12) (j_compress_ptr cinfo, J12SAMPARRAY input_buf, void (*process_data_12) (j_compress_ptr cinfo, J12SAMPARRAY input_buf,
JDIMENSION *in_row_ctr, JDIMENSION in_rows_avail); JDIMENSION *in_row_ctr, JDIMENSION in_rows_avail);
#ifdef C_LOSSLESS_SUPPORTED
void (*process_data_16) (j_compress_ptr cinfo, J16SAMPARRAY input_buf,
JDIMENSION *in_row_ctr, JDIMENSION in_rows_avail);
#endif
}; };
/* Compression preprocessing (downsampling input buffer control) */ /* Compression preprocessing (downsampling input buffer control) */
@@ -122,6 +126,14 @@ struct jpeg_c_prep_controller {
J12SAMPIMAGE output_buf, J12SAMPIMAGE output_buf,
JDIMENSION *out_row_group_ctr, JDIMENSION *out_row_group_ctr,
JDIMENSION out_row_groups_avail); JDIMENSION out_row_groups_avail);
#ifdef C_LOSSLESS_SUPPORTED
void (*pre_process_data_16) (j_compress_ptr cinfo, J16SAMPARRAY input_buf,
JDIMENSION *in_row_ctr,
JDIMENSION in_rows_avail,
J16SAMPIMAGE output_buf,
JDIMENSION *out_row_group_ctr,
JDIMENSION out_row_groups_avail);
#endif
}; };
/* Lossy mode: Coefficient buffer control /* Lossy mode: Coefficient buffer control
@@ -131,6 +143,9 @@ struct jpeg_c_coef_controller {
void (*start_pass) (j_compress_ptr cinfo, J_BUF_MODE pass_mode); void (*start_pass) (j_compress_ptr cinfo, J_BUF_MODE pass_mode);
boolean (*compress_data) (j_compress_ptr cinfo, JSAMPIMAGE input_buf); boolean (*compress_data) (j_compress_ptr cinfo, JSAMPIMAGE input_buf);
boolean (*compress_data_12) (j_compress_ptr cinfo, J12SAMPIMAGE input_buf); boolean (*compress_data_12) (j_compress_ptr cinfo, J12SAMPIMAGE input_buf);
#ifdef C_LOSSLESS_SUPPORTED
boolean (*compress_data_16) (j_compress_ptr cinfo, J16SAMPIMAGE input_buf);
#endif
}; };
/* Colorspace conversion */ /* Colorspace conversion */
@@ -142,6 +157,11 @@ struct jpeg_color_converter {
void (*color_convert_12) (j_compress_ptr cinfo, J12SAMPARRAY input_buf, void (*color_convert_12) (j_compress_ptr cinfo, J12SAMPARRAY input_buf,
J12SAMPIMAGE output_buf, JDIMENSION output_row, J12SAMPIMAGE output_buf, JDIMENSION output_row,
int num_rows); int num_rows);
#ifdef C_LOSSLESS_SUPPORTED
void (*color_convert_16) (j_compress_ptr cinfo, J16SAMPARRAY input_buf,
J16SAMPIMAGE output_buf, JDIMENSION output_row,
int num_rows);
#endif
}; };
/* Downsampling */ /* Downsampling */
@@ -153,6 +173,11 @@ struct jpeg_downsampler {
void (*downsample_12) (j_compress_ptr cinfo, J12SAMPIMAGE input_buf, void (*downsample_12) (j_compress_ptr cinfo, J12SAMPIMAGE input_buf,
JDIMENSION in_row_index, J12SAMPIMAGE output_buf, JDIMENSION in_row_index, J12SAMPIMAGE output_buf,
JDIMENSION out_row_group_index); JDIMENSION out_row_group_index);
#ifdef C_LOSSLESS_SUPPORTED
void (*downsample_16) (j_compress_ptr cinfo, J16SAMPIMAGE input_buf,
JDIMENSION in_row_index, J16SAMPIMAGE output_buf,
JDIMENSION out_row_group_index);
#endif
boolean need_context_rows; /* TRUE if need rows above & below */ boolean need_context_rows; /* TRUE if need rows above & below */
}; };
@@ -245,6 +270,10 @@ struct jpeg_d_main_controller {
JDIMENSION *out_row_ctr, JDIMENSION out_rows_avail); JDIMENSION *out_row_ctr, JDIMENSION out_rows_avail);
void (*process_data_12) (j_decompress_ptr cinfo, J12SAMPARRAY output_buf, void (*process_data_12) (j_decompress_ptr cinfo, J12SAMPARRAY output_buf,
JDIMENSION *out_row_ctr, JDIMENSION out_rows_avail); JDIMENSION *out_row_ctr, JDIMENSION out_rows_avail);
#ifdef D_LOSSLESS_SUPPORTED
void (*process_data_16) (j_decompress_ptr cinfo, J16SAMPARRAY output_buf,
JDIMENSION *out_row_ctr, JDIMENSION out_rows_avail);
#endif
}; };
/* Lossy mode: Coefficient buffer control /* Lossy mode: Coefficient buffer control
@@ -256,6 +285,9 @@ struct jpeg_d_coef_controller {
void (*start_output_pass) (j_decompress_ptr cinfo); void (*start_output_pass) (j_decompress_ptr cinfo);
int (*decompress_data) (j_decompress_ptr cinfo, JSAMPIMAGE output_buf); int (*decompress_data) (j_decompress_ptr cinfo, JSAMPIMAGE output_buf);
int (*decompress_data_12) (j_decompress_ptr cinfo, J12SAMPIMAGE output_buf); int (*decompress_data_12) (j_decompress_ptr cinfo, J12SAMPIMAGE output_buf);
#ifdef D_LOSSLESS_SUPPORTED
int (*decompress_data_16) (j_decompress_ptr cinfo, J16SAMPIMAGE output_buf);
#endif
/* These variables keep track of the current location of the input side. */ /* These variables keep track of the current location of the input side. */
/* cinfo->input_iMCU_row is also used for this. */ /* cinfo->input_iMCU_row is also used for this. */
@@ -284,6 +316,14 @@ struct jpeg_d_post_controller {
J12SAMPARRAY output_buf, J12SAMPARRAY output_buf,
JDIMENSION *out_row_ctr, JDIMENSION *out_row_ctr,
JDIMENSION out_rows_avail); JDIMENSION out_rows_avail);
#ifdef D_LOSSLESS_SUPPORTED
void (*post_process_data_16) (j_decompress_ptr cinfo, J16SAMPIMAGE input_buf,
JDIMENSION *in_row_group_ctr,
JDIMENSION in_row_groups_avail,
J16SAMPARRAY output_buf,
JDIMENSION *out_row_ctr,
JDIMENSION out_rows_avail);
#endif
}; };
/* Marker reading & parsing */ /* Marker reading & parsing */
@@ -358,6 +398,12 @@ struct jpeg_upsampler {
JDIMENSION *in_row_group_ctr, JDIMENSION *in_row_group_ctr,
JDIMENSION in_row_groups_avail, J12SAMPARRAY output_buf, JDIMENSION in_row_groups_avail, J12SAMPARRAY output_buf,
JDIMENSION *out_row_ctr, JDIMENSION out_rows_avail); JDIMENSION *out_row_ctr, JDIMENSION out_rows_avail);
#ifdef D_LOSSLESS_SUPPORTED
void (*upsample_16) (j_decompress_ptr cinfo, J16SAMPIMAGE input_buf,
JDIMENSION *in_row_group_ctr,
JDIMENSION in_row_groups_avail, J16SAMPARRAY output_buf,
JDIMENSION *out_row_ctr, JDIMENSION out_rows_avail);
#endif
boolean need_context_rows; /* TRUE if need rows above & below */ boolean need_context_rows; /* TRUE if need rows above & below */
}; };
@@ -371,6 +417,11 @@ struct jpeg_color_deconverter {
void (*color_convert_12) (j_decompress_ptr cinfo, J12SAMPIMAGE input_buf, void (*color_convert_12) (j_decompress_ptr cinfo, J12SAMPIMAGE input_buf,
JDIMENSION input_row, J12SAMPARRAY output_buf, JDIMENSION input_row, J12SAMPARRAY output_buf,
int num_rows); int num_rows);
#ifdef D_LOSSLESS_SUPPORTED
void (*color_convert_16) (j_decompress_ptr cinfo, J16SAMPIMAGE input_buf,
JDIMENSION input_row, J16SAMPARRAY output_buf,
int num_rows);
#endif
}; };
/* Color quantization or color precision reduction */ /* Color quantization or color precision reduction */
@@ -380,6 +431,10 @@ struct jpeg_color_quantizer {
JSAMPARRAY output_buf, int num_rows); JSAMPARRAY output_buf, int num_rows);
void (*color_quantize_12) (j_decompress_ptr cinfo, J12SAMPARRAY input_buf, void (*color_quantize_12) (j_decompress_ptr cinfo, J12SAMPARRAY input_buf,
J12SAMPARRAY output_buf, int num_rows); J12SAMPARRAY output_buf, int num_rows);
#ifdef D_LOSSLESS_SUPPORTED
void (*color_quantize_16) (j_decompress_ptr cinfo, J16SAMPARRAY input_buf,
J16SAMPARRAY output_buf, int num_rows);
#endif
void (*finish_pass) (j_decompress_ptr cinfo); void (*finish_pass) (j_decompress_ptr cinfo);
void (*new_color_map) (j_decompress_ptr cinfo); void (*new_color_map) (j_decompress_ptr cinfo);
}; };
@@ -442,13 +497,22 @@ EXTERN(void) jinit_phuff_encoder(j_compress_ptr cinfo);
EXTERN(void) jinit_arith_encoder(j_compress_ptr cinfo); EXTERN(void) jinit_arith_encoder(j_compress_ptr cinfo);
EXTERN(void) jinit_marker_writer(j_compress_ptr cinfo); EXTERN(void) jinit_marker_writer(j_compress_ptr cinfo);
#ifdef C_LOSSLESS_SUPPORTED #ifdef C_LOSSLESS_SUPPORTED
EXTERN(void) j16init_c_main_controller(j_compress_ptr cinfo,
boolean need_full_buffer);
EXTERN(void) j16init_c_prep_controller(j_compress_ptr cinfo,
boolean need_full_buffer);
EXTERN(void) j16init_color_converter(j_compress_ptr cinfo);
EXTERN(void) j16init_downsampler(j_compress_ptr cinfo);
EXTERN(void) jinit_c_diff_controller(j_compress_ptr cinfo, EXTERN(void) jinit_c_diff_controller(j_compress_ptr cinfo,
boolean need_full_buffer); boolean need_full_buffer);
EXTERN(void) j12init_c_diff_controller(j_compress_ptr cinfo, EXTERN(void) j12init_c_diff_controller(j_compress_ptr cinfo,
boolean need_full_buffer); boolean need_full_buffer);
EXTERN(void) j16init_c_diff_controller(j_compress_ptr cinfo,
boolean need_full_buffer);
EXTERN(void) jinit_lhuff_encoder(j_compress_ptr cinfo); EXTERN(void) jinit_lhuff_encoder(j_compress_ptr cinfo);
EXTERN(void) jinit_lossless_compressor(j_compress_ptr cinfo); EXTERN(void) jinit_lossless_compressor(j_compress_ptr cinfo);
EXTERN(void) j12init_lossless_compressor(j_compress_ptr cinfo); EXTERN(void) j12init_lossless_compressor(j_compress_ptr cinfo);
EXTERN(void) j16init_lossless_compressor(j_compress_ptr cinfo);
#endif #endif
/* Decompression module initialization routines */ /* Decompression module initialization routines */
@@ -483,13 +547,24 @@ EXTERN(void) j12init_2pass_quantizer(j_decompress_ptr cinfo);
EXTERN(void) jinit_merged_upsampler(j_decompress_ptr cinfo); EXTERN(void) jinit_merged_upsampler(j_decompress_ptr cinfo);
EXTERN(void) j12init_merged_upsampler(j_decompress_ptr cinfo); EXTERN(void) j12init_merged_upsampler(j_decompress_ptr cinfo);
#ifdef D_LOSSLESS_SUPPORTED #ifdef D_LOSSLESS_SUPPORTED
EXTERN(void) j16init_d_main_controller(j_decompress_ptr cinfo,
boolean need_full_buffer);
EXTERN(void) j16init_d_post_controller(j_decompress_ptr cinfo,
boolean need_full_buffer);
EXTERN(void) j16init_upsampler(j_decompress_ptr cinfo);
EXTERN(void) j16init_color_deconverter(j_decompress_ptr cinfo);
EXTERN(void) j16init_1pass_quantizer(j_decompress_ptr cinfo);
EXTERN(void) j16init_2pass_quantizer(j_decompress_ptr cinfo);
EXTERN(void) jinit_d_diff_controller(j_decompress_ptr cinfo, EXTERN(void) jinit_d_diff_controller(j_decompress_ptr cinfo,
boolean need_full_buffer); boolean need_full_buffer);
EXTERN(void) j12init_d_diff_controller(j_decompress_ptr cinfo, EXTERN(void) j12init_d_diff_controller(j_decompress_ptr cinfo,
boolean need_full_buffer); boolean need_full_buffer);
EXTERN(void) j16init_d_diff_controller(j_decompress_ptr cinfo,
boolean need_full_buffer);
EXTERN(void) jinit_lhuff_decoder(j_decompress_ptr cinfo); EXTERN(void) jinit_lhuff_decoder(j_decompress_ptr cinfo);
EXTERN(void) jinit_lossless_decompressor(j_decompress_ptr cinfo); EXTERN(void) jinit_lossless_decompressor(j_decompress_ptr cinfo);
EXTERN(void) j12init_lossless_decompressor(j_decompress_ptr cinfo); EXTERN(void) j12init_lossless_decompressor(j_decompress_ptr cinfo);
EXTERN(void) j16init_lossless_decompressor(j_decompress_ptr cinfo);
#endif #endif
/* Memory manager initialization */ /* Memory manager initialization */
@@ -504,6 +579,11 @@ EXTERN(void) jcopy_sample_rows(JSAMPARRAY input_array, int source_row,
EXTERN(void) j12copy_sample_rows(J12SAMPARRAY input_array, int source_row, EXTERN(void) j12copy_sample_rows(J12SAMPARRAY input_array, int source_row,
J12SAMPARRAY output_array, int dest_row, J12SAMPARRAY output_array, int dest_row,
int num_rows, JDIMENSION num_cols); int num_rows, JDIMENSION num_cols);
#if defined(C_LOSSLESS_SUPPORTED) || defined(D_LOSSLESS_SUPPORTED)
EXTERN(void) j16copy_sample_rows(J16SAMPARRAY input_array, int source_row,
J16SAMPARRAY output_array, int dest_row,
int num_rows, JDIMENSION num_cols);
#endif
EXTERN(void) jcopy_block_row(JBLOCKROW input_row, JBLOCKROW output_row, EXTERN(void) jcopy_block_row(JBLOCKROW input_row, JBLOCKROW output_row,
JDIMENSION num_blocks); JDIMENSION num_blocks);
EXTERN(void) jzero_far(void *target, size_t bytestozero); EXTERN(void) jzero_far(void *target, size_t bytestozero);

View File

@@ -86,6 +86,13 @@ typedef J12SAMPROW *J12SAMPARRAY; /* ptr to some 12-bit sample rows (a 2-D
typedef J12SAMPARRAY *J12SAMPIMAGE; /* a 3-D 12-bit sample array: top index is typedef J12SAMPARRAY *J12SAMPIMAGE; /* a 3-D 12-bit sample array: top index is
color */ color */
typedef J16SAMPLE *J16SAMPROW; /* ptr to one image row of 16-bit pixel
samples. */
typedef J16SAMPROW *J16SAMPARRAY; /* ptr to some 16-bit sample rows (a 2-D
16-bit sample array) */
typedef J16SAMPARRAY *J16SAMPIMAGE; /* a 3-D 16-bit sample array: top index is
color */
typedef JCOEF JBLOCK[DCTSIZE2]; /* one block of coefficients */ typedef JCOEF JBLOCK[DCTSIZE2]; /* one block of coefficients */
typedef JBLOCK *JBLOCKROW; /* pointer to one row of coefficient blocks */ typedef JBLOCK *JBLOCKROW; /* pointer to one row of coefficient blocks */
typedef JBLOCKROW *JBLOCKARRAY; /* a 2-D array of coefficient blocks */ typedef JBLOCKROW *JBLOCKARRAY; /* a 2-D array of coefficient blocks */
@@ -566,10 +573,11 @@ struct jpeg_decompress_struct {
*/ */
int actual_number_of_colors; /* number of entries in use */ int actual_number_of_colors; /* number of entries in use */
JSAMPARRAY colormap; /* The color map as a 2-D pixel array JSAMPARRAY colormap; /* The color map as a 2-D pixel array
If data_precision is 12, then this is If data_precision is 12 or 16, then this is
actually a J12SAMPARRAY, so callers must actually a J12SAMPARRAY or a J16SAMPARRAY,
type-cast it in order to read/write 12-bit so callers must type-cast it in order to
samples from/to the array. */ read/write 12-bit or 16-bit samples from/to
the array. */
/* State variables: these variables indicate the progress of decompression. /* State variables: these variables indicate the progress of decompression.
* The application may examine these but must not modify them. * The application may examine these but must not modify them.
@@ -689,10 +697,11 @@ struct jpeg_decompress_struct {
*/ */
JSAMPLE *sample_range_limit; /* table for fast range-limiting JSAMPLE *sample_range_limit; /* table for fast range-limiting
If data_precision is 12, then this is If data_precision is 12 or 16, then this is
actually a J12SAMPLE pointer, so callers actually a J12SAMPLE pointer or a J16SAMPLE
must type-cast it in order to read 12-bit pointer, so callers must type-cast it in
samples from the array. */ order to read 12-bit or 16-bit samples from
the array. */
/* /*
* These fields are valid during any one scan. * These fields are valid during any one scan.
@@ -873,10 +882,10 @@ struct jpeg_memory_mgr {
void *(*alloc_small) (j_common_ptr cinfo, int pool_id, size_t sizeofobject); void *(*alloc_small) (j_common_ptr cinfo, int pool_id, size_t sizeofobject);
void *(*alloc_large) (j_common_ptr cinfo, int pool_id, void *(*alloc_large) (j_common_ptr cinfo, int pool_id,
size_t sizeofobject); size_t sizeofobject);
/* If cinfo->data_precision is 12, then this method and the /* If cinfo->data_precision is 12 or 16, then this method and the
* access_virt_sarray method actually return a J12SAMPARRAY, so callers must * access_virt_sarray method actually return a J12SAMPARRAY or a
* type-cast the return value in order to read/write 12-bit samples from/to * J16SAMPARRAY, so callers must type-cast the return value in order to
* the array. * read/write 12-bit or 16-bit samples from/to the array.
*/ */
JSAMPARRAY (*alloc_sarray) (j_common_ptr cinfo, int pool_id, JSAMPARRAY (*alloc_sarray) (j_common_ptr cinfo, int pool_id,
JDIMENSION samplesperrow, JDIMENSION numrows); JDIMENSION samplesperrow, JDIMENSION numrows);
@@ -1000,6 +1009,9 @@ EXTERN(JDIMENSION) jpeg_write_scanlines(j_compress_ptr cinfo,
EXTERN(JDIMENSION) jpeg12_write_scanlines(j_compress_ptr cinfo, EXTERN(JDIMENSION) jpeg12_write_scanlines(j_compress_ptr cinfo,
J12SAMPARRAY scanlines, J12SAMPARRAY scanlines,
JDIMENSION num_lines); JDIMENSION num_lines);
EXTERN(JDIMENSION) jpeg16_write_scanlines(j_compress_ptr cinfo,
J16SAMPARRAY scanlines,
JDIMENSION num_lines);
EXTERN(void) jpeg_finish_compress(j_compress_ptr cinfo); EXTERN(void) jpeg_finish_compress(j_compress_ptr cinfo);
#if JPEG_LIB_VERSION >= 70 #if JPEG_LIB_VERSION >= 70
@@ -1051,6 +1063,9 @@ EXTERN(JDIMENSION) jpeg_read_scanlines(j_decompress_ptr cinfo,
EXTERN(JDIMENSION) jpeg12_read_scanlines(j_decompress_ptr cinfo, EXTERN(JDIMENSION) jpeg12_read_scanlines(j_decompress_ptr cinfo,
J12SAMPARRAY scanlines, J12SAMPARRAY scanlines,
JDIMENSION max_lines); JDIMENSION max_lines);
EXTERN(JDIMENSION) jpeg16_read_scanlines(j_decompress_ptr cinfo,
J16SAMPARRAY scanlines,
JDIMENSION max_lines);
EXTERN(JDIMENSION) jpeg_skip_scanlines(j_decompress_ptr cinfo, EXTERN(JDIMENSION) jpeg_skip_scanlines(j_decompress_ptr cinfo,
JDIMENSION num_lines); JDIMENSION num_lines);
EXTERN(JDIMENSION) jpeg12_skip_scanlines(j_decompress_ptr cinfo, EXTERN(JDIMENSION) jpeg12_skip_scanlines(j_decompress_ptr cinfo,

View File

@@ -18,7 +18,8 @@
#include "jpeglib.h" #include "jpeglib.h"
#include "jsamplecomp.h" #include "jsamplecomp.h"
#ifdef QUANT_1PASS_SUPPORTED #if defined(QUANT_1PASS_SUPPORTED) && \
(BITS_IN_JSAMPLE != 16 || defined(D_LOSSLESS_SUPPORTED))
/* /*
@@ -857,4 +858,5 @@ _jinit_1pass_quantizer(j_decompress_ptr cinfo)
alloc_fs_workspace(cinfo); alloc_fs_workspace(cinfo);
} }
#endif /* QUANT_1PASS_SUPPORTED */ #endif /* defined(QUANT_1PASS_SUPPORTED) &&
(BITS_IN_JSAMPLE != 16 || defined(D_LOSSLESS_SUPPORTED)) */

View File

@@ -25,7 +25,8 @@
#include "jpeglib.h" #include "jpeglib.h"
#include "jsamplecomp.h" #include "jsamplecomp.h"
#ifdef QUANT_2PASS_SUPPORTED #if defined(QUANT_2PASS_SUPPORTED) && \
(BITS_IN_JSAMPLE != 16 || defined(D_LOSSLESS_SUPPORTED))
/* /*
@@ -1289,4 +1290,5 @@ _jinit_2pass_quantizer(j_decompress_ptr cinfo)
} }
} }
#endif /* QUANT_2PASS_SUPPORTED */ #endif /* defined(QUANT_2PASS_SUPPORTED) &&
(BITS_IN_JSAMPLE != 16 || defined(D_LOSSLESS_SUPPORTED)) */

View File

@@ -16,7 +16,99 @@
#ifndef JSAMPLECOMP_H #ifndef JSAMPLECOMP_H
#define JSAMPLECOMP_H #define JSAMPLECOMP_H
#if BITS_IN_JSAMPLE == 12 #if BITS_IN_JSAMPLE == 16
/* Sample data types and macros (jmorecfg.h) */
#define _JSAMPLE J16SAMPLE
#define _MAXJSAMPLE MAXJ16SAMPLE
#define _CENTERJSAMPLE CENTERJ16SAMPLE
#define _JSAMPROW J16SAMPROW
#define _JSAMPARRAY J16SAMPARRAY
#define _JSAMPIMAGE J16SAMPIMAGE
/* External functions (jpeglib.h) */
#define _jpeg_write_scanlines jpeg16_write_scanlines
#define _jpeg_read_scanlines jpeg16_read_scanlines
/* Internal methods (jpegint.h) */
#ifdef C_LOSSLESS_SUPPORTED
/* Use the 16-bit method in the jpeg_c_main_controller structure. */
#define _process_data process_data_16
/* Use the 16-bit method in the jpeg_c_prep_controller structure. */
#define _pre_process_data pre_process_data_16
/* Use the 16-bit method in the jpeg_c_coef_controller structure. */
#define _compress_data compress_data_16
/* Use the 16-bit method in the jpeg_color_converter structure. */
#define _color_convert color_convert_16
/* Use the 16-bit method in the jpeg_downsampler structure. */
#define _downsample downsample_16
#endif
#ifdef D_LOSSLESS_SUPPORTED
/* Use the 16-bit method in the jpeg_d_main_controller structure. */
#define _process_data process_data_16
/* Use the 16-bit method in the jpeg_d_coef_controller structure. */
#define _decompress_data decompress_data_16
/* Use the 16-bit method in the jpeg_d_post_controller structure. */
#define _post_process_data post_process_data_16
/* Use the 16-bit method in the jpeg_upsampler structure. */
#define _upsample upsample_16
/* Use the 16-bit method in the jpeg_color_converter structure. */
#define _color_convert color_convert_16
/* Use the 16-bit method in the jpeg_color_quantizer structure. */
#define _color_quantize color_quantize_16
#endif
/* Global internal functions (jpegint.h) */
#ifdef C_LOSSLESS_SUPPORTED
#define _jinit_c_main_controller j16init_c_main_controller
#define _jinit_c_prep_controller j16init_c_prep_controller
#define _jinit_color_converter j16init_color_converter
#define _jinit_downsampler j16init_downsampler
#define _jinit_c_diff_controller j16init_c_diff_controller
#define _jinit_lossless_compressor j16init_lossless_compressor
#endif
#ifdef D_LOSSLESS_SUPPORTED
#define _jinit_d_main_controller j16init_d_main_controller
#define _jinit_d_post_controller j16init_d_post_controller
#define _jinit_upsampler j16init_upsampler
#define _jinit_color_deconverter j16init_color_deconverter
#define _jinit_1pass_quantizer j16init_1pass_quantizer
#define _jinit_2pass_quantizer j16init_2pass_quantizer
#define _jinit_merged_upsampler j16init_merged_upsampler
#define _jinit_d_diff_controller j16init_d_diff_controller
#define _jinit_lossless_decompressor j16init_lossless_decompressor
#endif
#if defined(C_LOSSLESS_SUPPORTED) || defined(D_LOSSLESS_SUPPORTED)
#define _jcopy_sample_rows j16copy_sample_rows
#endif
/* Internal fields (cdjpeg.h) */
#if defined(C_LOSSLESS_SUPPORTED) || defined(D_LOSSLESS_SUPPORTED)
/* Use the 16-bit buffer in the cjpeg_source_struct and djpeg_dest_struct
structures. */
#define _buffer buffer16
#endif
/* Image I/O functions (cdjpeg.h) */
#ifdef C_LOSSLESS_SUPPORTED
#define _jinit_read_gif j16init_read_gif
#define _jinit_read_ppm j16init_read_ppm
#endif
#ifdef D_LOSSLESS_SUPPORTED
#define _jinit_write_gif j16init_write_gif
#define _jinit_write_ppm j16init_write_ppm
#define _read_color_map read_color_map_16
#endif
#elif BITS_IN_JSAMPLE == 12
/* Sample data types and macros (jmorecfg.h) */ /* Sample data types and macros (jmorecfg.h) */
#define _JSAMPLE J12SAMPLE #define _JSAMPLE J12SAMPLE

View File

@@ -95,6 +95,9 @@ jround_up(long a, long b)
#endif /* BITS_IN_JSAMPLE == 8 */ #endif /* BITS_IN_JSAMPLE == 8 */
#if BITS_IN_JSAMPLE != 16 || \
defined(C_LOSSLESS_SUPPORTED) || defined(D_LOSSLESS_SUPPORTED)
GLOBAL(void) GLOBAL(void)
_jcopy_sample_rows(_JSAMPARRAY input_array, int source_row, _jcopy_sample_rows(_JSAMPARRAY input_array, int source_row,
_JSAMPARRAY output_array, int dest_row, int num_rows, _JSAMPARRAY output_array, int dest_row, int num_rows,
@@ -119,6 +122,9 @@ _jcopy_sample_rows(_JSAMPARRAY input_array, int source_row,
} }
} }
#endif /* BITS_IN_JSAMPLE != 16 ||
defined(C_LOSSLESS_SUPPORTED) || defined(D_LOSSLESS_SUPPORTED) */
#if BITS_IN_JSAMPLE == 8 #if BITS_IN_JSAMPLE == 8

View File

@@ -31,7 +31,7 @@ TABLE OF CONTENTS
Overview: Overview:
Functions provided by the library Functions provided by the library
12-bit Data Precision 12-bit and 16-bit Data Precision
Outline of typical usage Outline of typical usage
Basic library usage: Basic library usage:
Data formats Data formats
@@ -101,7 +101,8 @@ use.) Unsupported ISO options include:
* Hierarchical storage * Hierarchical storage
* DNL marker * DNL marker
* Nonintegral subsampling ratios * Nonintegral subsampling ratios
We support both 8- and 12-bit data precision. We support 8-bit (lossy and lossless), 12-bit (lossy and lossless), and 16-bit
(lossless) data precision.
By itself, the library handles only interchange JPEG datastreams --- in By itself, the library handles only interchange JPEG datastreams --- in
particular the widely used JFIF file format. The library can be used by particular the widely used JFIF file format. The library can be used by
@@ -110,15 +111,17 @@ are embedded in more complex file formats. (For example, this library is
used by the free LIBTIFF library to support JPEG compression in TIFF.) used by the free LIBTIFF library to support JPEG compression in TIFF.)
12-bit Data Precision 12-bit and 16-bit Data Precision
--------------------- --------------------------------
The JPEG standard provides for both the baseline 8-bit DCT process and a 12-bit The JPEG standard provides for baseline 8-bit and 12-bit DCT processes as well
DCT process. The IJG code supports 12-bit-per-component lossy JPEG if you set as 8-bit, 12-bit, and 16-bit lossless (predictive) processes. This code
cinfo->data_precision to 12. Note that this causes the sample size to be supports 12-bit-per-component lossy or lossless JPEG if you set
cinfo->data_precision to 12 and 16-bit-per-component lossless JPEG if you set
cinfo->data_precision to 16. Note that this causes the sample size to be
larger than a char, so it affects the surrounding application's image data. larger than a char, so it affects the surrounding application's image data.
The sample applications cjpeg and djpeg can support 12-bit mode only for PPM The sample applications cjpeg and djpeg can support 12-bit and 16-bit mode only
and GIF file formats. for PPM and GIF file formats.
Note that, when 12-bit data precision is enabled, the library always compresses Note that, when 12-bit data precision is enabled, the library always compresses
in Huffman optimization mode, in order to generate valid Huffman tables. This in Huffman optimization mode, in order to generate valid Huffman tables. This
@@ -138,15 +141,26 @@ instead of "jpeg_" and use the following data types and macros:
* MAXJ12SAMPLE instead of MAXJSAMPLE * MAXJ12SAMPLE instead of MAXJSAMPLE
* CENTERJ12SAMPLE instead of CENTERJSAMPLE * CENTERJ12SAMPLE instead of CENTERJSAMPLE
This allows both 8-bit and 12-bit data precision to be used in a single Functions that are specific to 16-bit data precision have a prefix of "jpeg16_"
instead of "jpeg_" and use the following data types and macros:
* J16SAMPLE instead of JSAMPLE
* J16SAMPROW instead of JSAMPROW
* J16SAMPARRAY instead of JSAMPARRAY
* J16SAMPIMAGE instead of JSAMPIMAGE
* MAXJ16SAMPLE instead of MAXJSAMPLE
* CENTERJ16SAMPLE instead of CENTERJSAMPLE
This allows 8-bit, 12-bit, and 16-bit data precision to be used in a single
application. (Refer to example.c). Arithmetic coding and SIMD acceleration application. (Refer to example.c). Arithmetic coding and SIMD acceleration
are not currently implemented for 12-bit data precision. are not currently implemented for 12-bit data precision, nor are they
implemented for lossless mode with any data precision.
Refer to the descriptions of the data_precision compression and decompression Refer to the descriptions of the data_precision compression and decompression
parameters below for further information. parameters below for further information.
This documentation uses "J*SAMPLE", "J*SAMPROW", "J*SAMPARRAY", and This documentation uses "J*SAMPLE", "J*SAMPROW", "J*SAMPARRAY", and
"J*SAMPIMAGE" to generically refer to either the 8-bit or 12-bit data types. "J*SAMPIMAGE" to generically refer to the 8-bit, 12-bit, or 16-bit data types.
Outline of typical usage Outline of typical usage
@@ -160,7 +174,9 @@ The rough outline of a JPEG compression operation is:
jpeg_start_compress(...); jpeg_start_compress(...);
while (scan lines remain to be written) while (scan lines remain to be written)
jpeg_write_scanlines(...); /* Use jpeg12_write_scanlines() for jpeg_write_scanlines(...); /* Use jpeg12_write_scanlines() for
12-bit data precision. */ 12-bit data precision and
jpeg16_write_scanlines() for
16-bit data precision. */
jpeg_finish_compress(...); jpeg_finish_compress(...);
Release the JPEG compression object Release the JPEG compression object
@@ -188,7 +204,9 @@ Similarly, the rough outline of a JPEG decompression operation is:
jpeg_start_decompress(...); jpeg_start_decompress(...);
while (scan lines remain to be read) while (scan lines remain to be read)
jpeg_read_scanlines(...); /* Use jpeg12_read_scanlines() for jpeg_read_scanlines(...); /* Use jpeg12_read_scanlines() for
12-bit data precision. */ 12-bit data precision and
jpeg16_read_scanlines() for
16-bit data precision. */
jpeg_finish_decompress(...); jpeg_finish_decompress(...);
Release the JPEG decompression object Release the JPEG decompression object
@@ -270,7 +288,7 @@ For best results, source data values should have the precision specified by
cinfo->data_precision (normally 8 bits). For instance, if you choose to cinfo->data_precision (normally 8 bits). For instance, if you choose to
compress data that's only 6 bits/channel, you should left-justify each value in compress data that's only 6 bits/channel, you should left-justify each value in
a byte before passing it to the compressor. If you need to compress data a byte before passing it to the compressor. If you need to compress data
that has more than 8 bits/channel, set cinfo->data_precision = 12. that has more than 8 bits/channel, set cinfo->data_precision = 12 or 16.
The data format returned by the decompressor is the same in all details, The data format returned by the decompressor is the same in all details,
@@ -283,8 +301,8 @@ a 2-D J*SAMPARRAY in which each row holds the values of one color component,
that is, colormap[i][j] is the value of the i'th color component for pixel that is, colormap[i][j] is the value of the i'th color component for pixel
value (map index) j. Note that since the colormap indexes are stored in value (map index) j. Note that since the colormap indexes are stored in
J*SAMPLEs, the maximum number of colors is limited by the size of J*SAMPLE J*SAMPLEs, the maximum number of colors is limited by the size of J*SAMPLE
(ie, at most 256 colors for 8-bit data precision and 4096 colors for 12-bit (ie, at most 256 colors for 8-bit data precision, 4096 colors for 12-bit data
data precision). precision, and 65536 colors for 16-bit data precision).
Compression details Compression details
@@ -422,7 +440,9 @@ the compression cycle.
5. while (scan lines remain to be written) 5. while (scan lines remain to be written)
jpeg_write_scanlines(...); /* Use jpeg12_write_scanlines() for 12-bit jpeg_write_scanlines(...); /* Use jpeg12_write_scanlines() for 12-bit
data precision. */ data precision and
jpeg16_write_scanlines() for 16-bit data
precision. */
Now write all the required image data by calling jpeg*_write_scanlines() Now write all the required image data by calling jpeg*_write_scanlines()
one or more times. You can pass one or more scanlines in each call, up one or more times. You can pass one or more scanlines in each call, up
@@ -449,13 +469,16 @@ array containing 3-byte RGB pixels:
JSAMPROW row_pointer[1]; /* pointer to a single row JSAMPROW row_pointer[1]; /* pointer to a single row
Use J12SAMPROW for 12-bit data Use J12SAMPROW for 12-bit data
precision. */ precision and J16SAMPROW for 16-bit
data precision. */
while (cinfo.next_scanline < cinfo.image_height) { while (cinfo.next_scanline < cinfo.image_height) {
row_pointer[0] = image_buffer[cinfo.next_scanline]; row_pointer[0] = image_buffer[cinfo.next_scanline];
jpeg_write_scanlines(&cinfo, row_pointer, 1); jpeg_write_scanlines(&cinfo, row_pointer, 1);
/* Use jpeg12_write_scanlines() for /* Use jpeg12_write_scanlines() for
12-bit data precision. */ 12-bit data precision and
jpeg16_write_scanlines() for 16-bit
data precision. */
} }
jpeg*_write_scanlines() returns the number of scanlines actually written. jpeg*_write_scanlines() returns the number of scanlines actually written.
@@ -700,7 +723,9 @@ relevant parameters (scaling, output color space, and quantization flag).
6. while (scan lines remain to be read) 6. while (scan lines remain to be read)
jpeg_read_scanlines(...); /* Use jpeg12_read_scanlines() for 12-bit jpeg_read_scanlines(...); /* Use jpeg12_read_scanlines() for 12-bit
data precision. */ data precision and
jpeg16_read_scanlines() for 16-bit data
precision. */
Now you can read the decompressed image data by calling jpeg*_read_scanlines() Now you can read the decompressed image data by calling jpeg*_read_scanlines()
one or more times. At each call, you pass in the maximum number of scanlines one or more times. At each call, you pass in the maximum number of scanlines
@@ -1029,7 +1054,10 @@ int data_precision
To create a 12-bit-per-component JPEG file, set data_precision to 12 To create a 12-bit-per-component JPEG file, set data_precision to 12
prior to calling jpeg_start_compress() or using the memory manager, prior to calling jpeg_start_compress() or using the memory manager,
then use jpeg12_write_scanlines() or jpeg12_write_raw_data() instead of then use jpeg12_write_scanlines() or jpeg12_write_raw_data() instead of
jpeg_write_scanlines() or jpeg_write_raw_data(). jpeg_write_scanlines() or jpeg_write_raw_data(). To create a
16-bit-per-component lossless JPEG file, set data_precision to 16 prior
to calling jpeg_start_compress() or using the memory manager, then use
jpeg16_write_scanlines() instead of jpeg_write_scanlines().
J_DCT_METHOD dct_method J_DCT_METHOD dct_method
Selects the algorithm used for the DCT step. Choices are: Selects the algorithm used for the DCT step. Choices are:
@@ -1256,7 +1284,8 @@ int data_precision Data precision (bits per component)
jpeg12_skip_scanlines(), jpeg12_crop_scanline(), and/or jpeg12_skip_scanlines(), jpeg12_crop_scanline(), and/or
jpeg12_read_raw_data() instead of jpeg_read_scanlines(), jpeg12_read_raw_data() instead of jpeg_read_scanlines(),
jpeg_skip_scanlines(), jpeg_crop_scanline(), and/or jpeg_skip_scanlines(), jpeg_crop_scanline(), and/or
jpeg_read_raw_data(). jpeg_read_raw_data(). If data_precision is 16, then use
jpeg16_read_scanlines() instead of jpeg_read_scanlines().
JDIMENSION image_width Width and height of image JDIMENSION image_width Width and height of image
JDIMENSION image_height JDIMENSION image_height
@@ -1341,9 +1370,9 @@ JSAMPARRAY colormap
CAUTION: if the JPEG library creates its own colormap, the storage CAUTION: if the JPEG library creates its own colormap, the storage
pointed to by this field is released by jpeg_finish_decompress(). pointed to by this field is released by jpeg_finish_decompress().
Copy the colormap somewhere else first, if you want to save it. Copy the colormap somewhere else first, if you want to save it.
CAUTION: if data_precision is 12, then this is actually a J12SAMPARRAY, CAUTION: if data_precision is 12 or 16, then this is actually a
so it must be type-cast in order to read 12-bit samples from or write J12SAMPARRAY or a J16SAMPARRAY, so it must be type-cast in order to
12-bit samples to the array. read/write 12-bit or 16-bit samples from/to the array.
int actual_number_of_colors int actual_number_of_colors
The number of colors in the color map. The number of colors in the color map.
@@ -2053,7 +2082,9 @@ The basic control flow for buffered-image decoding is
jpeg_start_output() /* start a new output pass */ jpeg_start_output() /* start a new output pass */
for (all scanlines in image) { for (all scanlines in image) {
jpeg_read_scanlines() /* Use jpeg12_read_scanlines() for jpeg_read_scanlines() /* Use jpeg12_read_scanlines() for
12-bit data precision. */ 12-bit data precision and
jpeg16_read_scanlines() for 16-bit
data precision. */
display scanlines display scanlines
} }
jpeg_finish_output() /* terminate output pass */ jpeg_finish_output() /* terminate output pass */
@@ -3121,9 +3152,9 @@ This does not count any memory allocated by the application, such as a
buffer to hold the final output image. buffer to hold the final output image.
The above figures are valid for 8-bit JPEG data precision and a machine with The above figures are valid for 8-bit JPEG data precision and a machine with
32-bit ints. For 12-bit JPEG data, double the size of the strip buffers and 32-bit ints. For 12-bit and 16-bit JPEG data, double the size of the strip
quantization pixel buffer. The "fixed-size" data will be somewhat smaller buffers and quantization pixel buffer. The "fixed-size" data will be somewhat
with 16-bit ints, larger with 64-bit ints. Also, CMYK or other unusual smaller with 16-bit ints, larger with 64-bit ints. Also, CMYK or other unusual
color spaces will require different amounts of space. color spaces will require different amounts of space.
The full-image coefficient and pixel buffers, if needed at all, do not The full-image coefficient and pixel buffers, if needed at all, do not

View File

@@ -28,6 +28,7 @@
#include "jsamplecomp.h" #include "jsamplecomp.h"
#ifdef QUANT_2PASS_SUPPORTED /* otherwise can't quantize to supplied map */ #ifdef QUANT_2PASS_SUPPORTED /* otherwise can't quantize to supplied map */
#if BITS_IN_JSAMPLE != 16 || defined(D_LOSSLESS_SUPPORTED)
/* Portions of this code are based on the PBMPLUS library, which is: /* Portions of this code are based on the PBMPLUS library, which is:
** **
@@ -256,4 +257,5 @@ _read_color_map(j_decompress_ptr cinfo, FILE *infile)
} }
} }
#endif /* BITS_IN_JSAMPLE != 16 || defined(D_LOSSLESS_SUPPORTED) */
#endif /* QUANT_2PASS_SUPPORTED */ #endif /* QUANT_2PASS_SUPPORTED */

View File

@@ -36,7 +36,8 @@
#include "cdjpeg.h" /* Common decls for cjpeg/djpeg applications */ #include "cdjpeg.h" /* Common decls for cjpeg/djpeg applications */
#include "jsamplecomp.h" #include "jsamplecomp.h"
#ifdef GIF_SUPPORTED #if defined(GIF_SUPPORTED) && \
(BITS_IN_JSAMPLE != 16 || defined(C_LOSSLESS_SUPPORTED))
/* Macros to deal with unsigned chars as efficiently as compiler allows */ /* Macros to deal with unsigned chars as efficiently as compiler allows */
@@ -721,4 +722,5 @@ _jinit_read_gif(j_compress_ptr cinfo)
return (cjpeg_source_ptr)source; return (cjpeg_source_ptr)source;
} }
#endif /* GIF_SUPPORTED */ #endif /* defined(GIF_SUPPORTED) &&
(BITS_IN_JSAMPLE != 16 || defined(C_LOSSLESS_SUPPORTED)) */

View File

@@ -25,7 +25,8 @@
#include "cmyk.h" #include "cmyk.h"
#include "cdjpeg.h" /* Common decls for cjpeg/djpeg applications */ #include "cdjpeg.h" /* Common decls for cjpeg/djpeg applications */
#ifdef PPM_SUPPORTED #if defined(PPM_SUPPORTED) && \
(BITS_IN_JSAMPLE != 16 || defined(C_LOSSLESS_SUPPORTED))
/* Portions of this code are based on the PBMPLUS library, which is: /* Portions of this code are based on the PBMPLUS library, which is:
@@ -781,4 +782,5 @@ _jinit_read_ppm(j_compress_ptr cinfo)
return (cjpeg_source_ptr)source; return (cjpeg_source_ptr)source;
} }
#endif /* PPM_SUPPORTED */ #endif /* defined(PPM_SUPPORTED) &&
(BITS_IN_JSAMPLE != 16 || defined(C_LOSSLESS_SUPPORTED)) */

View File

@@ -37,7 +37,7 @@ if(MSVC)
set(JPEG_SRCS ${JPEG_SRCS} ${CMAKE_BINARY_DIR}/win/jpeg.rc) set(JPEG_SRCS ${JPEG_SRCS} ${CMAKE_BINARY_DIR}/win/jpeg.rc)
endif() endif()
add_library(jpeg SHARED ${JPEG_SRCS} ${DEFFILE} ${SIMD_TARGET_OBJECTS} add_library(jpeg SHARED ${JPEG_SRCS} ${DEFFILE} ${SIMD_TARGET_OBJECTS}
${SIMD_OBJS} $<TARGET_OBJECTS:jpeg12>) ${SIMD_OBJS} $<TARGET_OBJECTS:jpeg12> $<TARGET_OBJECTS:jpeg16>)
set_target_properties(jpeg PROPERTIES SOVERSION ${SO_MAJOR_VERSION} set_target_properties(jpeg PROPERTIES SOVERSION ${SO_MAJOR_VERSION}
VERSION ${SO_MAJOR_VERSION}.${SO_AGE}.${SO_MINOR_VERSION}) VERSION ${SO_MAJOR_VERSION}.${SO_AGE}.${SO_MINOR_VERSION})
@@ -68,21 +68,31 @@ endif()
set(CDJPEG_COMPILE_FLAGS set(CDJPEG_COMPILE_FLAGS
"-DBMP_SUPPORTED -DGIF_SUPPORTED -DPPM_SUPPORTED -DTARGA_SUPPORTED ${USE_SETMODE}") "-DBMP_SUPPORTED -DGIF_SUPPORTED -DPPM_SUPPORTED -DTARGA_SUPPORTED ${USE_SETMODE}")
# Compile a separate version of these source files with 12-bit data precision. # Compile a separate version of these source files with 12-bit and 16-bit data
# precision.
add_library(cjpeg12 OBJECT ../rdgif.c ../rdppm.c) add_library(cjpeg12 OBJECT ../rdgif.c ../rdppm.c)
set_property(TARGET cjpeg12 PROPERTY COMPILE_FLAGS set_property(TARGET cjpeg12 PROPERTY COMPILE_FLAGS
"-DBITS_IN_JSAMPLE=12 -DGIF_SUPPORTED -DPPM_SUPPORTED") "-DBITS_IN_JSAMPLE=12 -DGIF_SUPPORTED -DPPM_SUPPORTED")
add_library(cjpeg16 OBJECT ../rdgif.c ../rdppm.c)
set_property(TARGET cjpeg16 PROPERTY COMPILE_FLAGS
"-DBITS_IN_JSAMPLE=16 -DGIF_SUPPORTED -DPPM_SUPPORTED")
add_executable(cjpeg ../cjpeg.c ../cdjpeg.c ../rdbmp.c ../rdgif.c ../rdppm.c add_executable(cjpeg ../cjpeg.c ../cdjpeg.c ../rdbmp.c ../rdgif.c ../rdppm.c
../rdswitch.c ../rdtarga.c $<TARGET_OBJECTS:cjpeg12>) ../rdswitch.c ../rdtarga.c $<TARGET_OBJECTS:cjpeg12>
$<TARGET_OBJECTS:cjpeg16>)
set_property(TARGET cjpeg PROPERTY COMPILE_FLAGS ${CDJPEG_COMPILE_FLAGS}) set_property(TARGET cjpeg PROPERTY COMPILE_FLAGS ${CDJPEG_COMPILE_FLAGS})
target_link_libraries(cjpeg jpeg) target_link_libraries(cjpeg jpeg)
# Compile a separate version of these source files with 12-bit data precision. # Compile a separate version of these source files with 12-bit and 16-bit data
# precision.
add_library(djpeg12 OBJECT ../rdcolmap.c ../wrgif.c ../wrppm.c) add_library(djpeg12 OBJECT ../rdcolmap.c ../wrgif.c ../wrppm.c)
set_property(TARGET djpeg12 PROPERTY COMPILE_FLAGS set_property(TARGET djpeg12 PROPERTY COMPILE_FLAGS
"-DBITS_IN_JSAMPLE=12 -DGIF_SUPPORTED -DPPM_SUPPORTED") "-DBITS_IN_JSAMPLE=12 -DGIF_SUPPORTED -DPPM_SUPPORTED")
add_library(djpeg16 OBJECT ../rdcolmap.c ../wrgif.c ../wrppm.c)
set_property(TARGET djpeg16 PROPERTY COMPILE_FLAGS
"-DBITS_IN_JSAMPLE=16 -DGIF_SUPPORTED -DPPM_SUPPORTED")
add_executable(djpeg ../djpeg.c ../cdjpeg.c ../rdcolmap.c ../rdswitch.c add_executable(djpeg ../djpeg.c ../cdjpeg.c ../rdcolmap.c ../rdswitch.c
../wrbmp.c ../wrgif.c ../wrppm.c ../wrtarga.c $<TARGET_OBJECTS:djpeg12>) ../wrbmp.c ../wrgif.c ../wrppm.c ../wrtarga.c $<TARGET_OBJECTS:djpeg12>
$<TARGET_OBJECTS:djpeg16>)
set_property(TARGET djpeg PROPERTY COMPILE_FLAGS ${CDJPEG_COMPILE_FLAGS}) set_property(TARGET djpeg PROPERTY COMPILE_FLAGS ${CDJPEG_COMPILE_FLAGS})
target_link_libraries(djpeg jpeg) target_link_libraries(djpeg jpeg)

View File

@@ -519,9 +519,9 @@ shown are:
is not used for full-color output. Works on one pixel row at a time; may is not used for full-color output. Works on one pixel row at a time; may
require two passes to generate a color map. Note that the output will require two passes to generate a color map. Note that the output will
always be a single component representing colormap indexes. In the current always be a single component representing colormap indexes. In the current
design, the output values are JSAMPLEs or J12SAMPLEs, so the library cannot design, the output values are JSAMPLEs, J12SAMPLEs, or J16SAMPLEs, so the
quantize to more than 256 colors when using 8-bit data precision. This is library cannot quantize to more than 256 colors when using 8-bit data
unlikely to be a problem in practice. precision. This is unlikely to be a problem in practice.
* Color reduction: this module handles color precision reduction, e.g., * Color reduction: this module handles color precision reduction, e.g.,
generating 15-bit color (5 bits/primary) from JPEG's 24-bit output. generating 15-bit color (5 bits/primary) from JPEG's 24-bit output.
@@ -621,8 +621,16 @@ Arrays of 12-bit pixel sample values use the following data structure:
typedef J12SAMPROW *J12SAMPARRAY; ptr to a list of rows typedef J12SAMPROW *J12SAMPARRAY; ptr to a list of rows
typedef J12SAMPARRAY *J12SAMPIMAGE; ptr to a list of color-component arrays typedef J12SAMPARRAY *J12SAMPIMAGE; ptr to a list of color-component arrays
The basic element type JSAMPLE (8-bit sample) will be unsigned char, and the Arrays of 16-bit pixel sample values use the following data structure:
basic element type J12SAMPLE (12-bit sample) with be short.
typedef something J16SAMPLE; a pixel component value, 0..MAXJ16SAMPLE
typedef J16SAMPLE *J16SAMPROW; ptr to a row of samples
typedef J16SAMPROW *J16SAMPARRAY; ptr to a list of rows
typedef J16SAMPARRAY *J16SAMPIMAGE; ptr to a list of color-component arrays
The basic element type JSAMPLE (8-bit sample) will be unsigned char, the basic
element type J12SAMPLE (12-bit sample) will be short, and the basic element
type J16SAMPLE (16-bit sample) will be unsigned short.
With these conventions, J*SAMPLE values can be assumed to be >= 0. This helps With these conventions, J*SAMPLE values can be assumed to be >= 0. This helps
simplify correct rounding during downsampling, etc. The JPEG standard's simplify correct rounding during downsampling, etc. The JPEG standard's
@@ -633,7 +641,8 @@ decompression the output of the IDCT step will be immediately shifted back to
When 8-bit samples are in use, the code uses MAXJSAMPLE and CENTERJSAMPLE, When 8-bit samples are in use, the code uses MAXJSAMPLE and CENTERJSAMPLE,
which are defined as 255 and 128 respectively. When 12-bit samples are in use, which are defined as 255 and 128 respectively. When 12-bit samples are in use,
the code uses MAXJ12SAMPLE and CENTERJ12SAMPLE, which are defined as 4095 and the code uses MAXJ12SAMPLE and CENTERJ12SAMPLE, which are defined as 4095 and
2048 respectively.) 2048 respectively. When 16-bit samples are in use, the code uses MAXJ16SAMPLE
and CENTERJ16SAMPLE, which are defined as 65535 and 32768 respectively.)
We use a pointer per row, rather than a two-dimensional J*SAMPLE array. This We use a pointer per row, rather than a two-dimensional J*SAMPLE array. This
choice costs only a small amount of memory and has several benefits: choice costs only a small amount of memory and has several benefits:

View File

@@ -161,7 +161,11 @@ file size is about the same --- often a little smaller.
Switches for advanced users: Switches for advanced users:
-precision N Create JPEG file with N-bit data precision. -precision N Create JPEG file with N-bit data precision.
N is 8 or 12; default is 8. N is 8, 12, or 16; default is 8. If N is 16, then
-lossless must also be specified. CAUTION: 12-bit and
16-bit JPEG is not yet widely implemented, so many
decoders will be unable to view a 12-bit or 16-bit JPEG
file at all.
-lossless psv[,Pt] Create a lossless JPEG file using the specified -lossless psv[,Pt] Create a lossless JPEG file using the specified
predictor selection value (1 - 7) and optional point predictor selection value (1 - 7) and optional point

View File

@@ -33,7 +33,8 @@
#include "cdjpeg.h" /* Common decls for cjpeg/djpeg applications */ #include "cdjpeg.h" /* Common decls for cjpeg/djpeg applications */
#include "jsamplecomp.h" #include "jsamplecomp.h"
#ifdef GIF_SUPPORTED #if defined(GIF_SUPPORTED) && \
(BITS_IN_JSAMPLE != 16 || defined(D_LOSSLESS_SUPPORTED))
#define MAX_LZW_BITS 12 /* maximum LZW code size (4096 symbols) */ #define MAX_LZW_BITS 12 /* maximum LZW code size (4096 symbols) */
@@ -582,4 +583,5 @@ _jinit_write_gif(j_decompress_ptr cinfo, boolean is_lzw)
return (djpeg_dest_ptr)dest; return (djpeg_dest_ptr)dest;
} }
#endif /* GIF_SUPPORTED */ #endif /* defined(GIF_SUPPORTED) &&
(BITS_IN_JSAMPLE != 16 || defined(D_LOSSLESS_SUPPORTED)) */

View File

@@ -22,7 +22,8 @@
#include "cmyk.h" #include "cmyk.h"
#include "cdjpeg.h" /* Common decls for cjpeg/djpeg applications */ #include "cdjpeg.h" /* Common decls for cjpeg/djpeg applications */
#ifdef PPM_SUPPORTED #if defined(PPM_SUPPORTED) && \
(BITS_IN_JSAMPLE != 16 || defined(D_LOSSLESS_SUPPORTED))
/* /*
@@ -366,4 +367,5 @@ _jinit_write_ppm(j_decompress_ptr cinfo)
return (djpeg_dest_ptr)dest; return (djpeg_dest_ptr)dest;
} }
#endif /* PPM_SUPPORTED */ #endif /* defined(PPM_SUPPORTED) &&
(BITS_IN_JSAMPLE != 16 || defined(D_LOSSLESS_SUPPORTED)) */