Merge mozjpeg into libjpeg-turbo

* origin/master: (23 commits)
  Update .gitignore
  .func/.endfunc are only necessary when generating STABS debug info, which basically went out of style with parachute pants and Rick Astley.  At any rate, none of the platforms for which we're building the ARM code use it (DWARF is the common format these days), and the .func/.endfunc directives cause the clang integrated assembler to fail (http://llvm.org/bugs/show_bug.cgi?id=20424).
  Enable DC trellis by default
  Avoid double inline attribute
  Detect libpng
  Implement DHT Merging
  Add .gitignore for autotools files
  Check memory alloc success
  Update cjpeg usage text
  Implement DQT merging
  Fix issue with scan printout
  Get rid of unnecessary and obsolete platform configuration instructions.
  Add error checks for malloc calls that don't already have them. Issue #87.
  yuvjpeg: fix trivial leak
  Parse quality as float
  PNG reading support
  Fix issue with DC trellis
  Add option to split DC scans
  Add trellis for DC
  Bump version to 2.1.
  ...

Conflicts:
	BUILDING.txt
	cdjpeg.h
	jcdctmgr.c
	jchuff.h
	jcmarker.c
	jcmaster.c
	jconfig.txt
	jpeglib.h
	rdswitch.c
This commit is contained in:
Kornel Lesiński
2014-09-07 17:57:06 +01:00
22 changed files with 1031 additions and 568 deletions

14
.gitignore vendored Normal file
View File

@@ -0,0 +1,14 @@
Makefile.in
/autom4te.cache
/aclocal.m4
/compile
/configure
/depcomp
/install-sh
/missing
/stamp-h1
/config.guess
/config.h.in
/config.sub
/ltmain.sh
/ar-lib

View File

@@ -216,17 +216,6 @@ Add
to the configure command line. to the configure command line.
64-bit Build on 64-bit OS X
---------------------------
Add
--host x86_64-apple-darwin NASM=/opt/local/bin/nasm
to the configure command line. NASM 2.07 or later from MacPorts must be
installed.
32-bit Build on 64-bit OS X 32-bit Build on 64-bit OS X
--------------------------- ---------------------------

View File

@@ -9,7 +9,7 @@ if(POLICY CMP0022)
endif() endif()
project(libmozjpeg C) project(libmozjpeg C)
set(VERSION 2.0.1) set(VERSION 2.1)
if(CYGWIN OR NOT CMAKE_HOST_SYSTEM_NAME STREQUAL "Windows") if(CYGWIN OR NOT CMAKE_HOST_SYSTEM_NAME STREQUAL "Windows")
execute_process(COMMAND "date" "+%Y%m%d" OUTPUT_VARIABLE BUILD) execute_process(COMMAND "date" "+%Y%m%d" OUTPUT_VARIABLE BUILD)

View File

@@ -116,6 +116,12 @@ cjpeg_LDADD = libjpeg.la
cjpeg_CFLAGS = -DBMP_SUPPORTED -DGIF_SUPPORTED -DPPM_SUPPORTED \ cjpeg_CFLAGS = -DBMP_SUPPORTED -DGIF_SUPPORTED -DPPM_SUPPORTED \
-DTARGA_SUPPORTED -DTARGA_SUPPORTED
if HAVE_LIBPNG
cjpeg_CFLAGS += -DPNG_SUPPORTED $(libpng_CFLAGS)
cjpeg_LDADD += $(libpng_LIBS)
cjpeg_SOURCES += rdpng.c
endif
djpeg_SOURCES = cdjpeg.h cderror.h cdjpeg.c djpeg.c rdcolmap.c rdswitch.c \ djpeg_SOURCES = cdjpeg.h cderror.h cdjpeg.c djpeg.c rdcolmap.c rdswitch.c \
wrbmp.c wrgif.c wrppm.c wrtarga.c wrbmp.c wrgif.c wrppm.c wrtarga.c

View File

@@ -7,6 +7,8 @@ The idea is to reduce transfer times for JPEGs on the Web, thus reducing page lo
'mozjpeg' is not intended to be a general JPEG library replacement. It makes tradeoffs that are intended to benefit Web use cases and focuses solely on improving encoding. It is best used as part of a Web encoding workflow. For a general JPEG library (e.g. your system libjpeg), especially if you care about decoding, we recommend libjpeg-turbo. 'mozjpeg' is not intended to be a general JPEG library replacement. It makes tradeoffs that are intended to benefit Web use cases and focuses solely on improving encoding. It is best used as part of a Web encoding workflow. For a general JPEG library (e.g. your system libjpeg), especially if you care about decoding, we recommend libjpeg-turbo.
For more information, see the project announcement: More information:
https://blog.mozilla.org/research/2014/03/05/introducing-the-mozjpeg-project/ * [Version 1.0 Announcement](https://blog.mozilla.org/research/2014/03/05/introducing-the-mozjpeg-project/)
* [Version 2.0 Announcement](https://blog.mozilla.org/research/2014/07/15/mozilla-advances-jpeg-encoding-with-mozjpeg-2-0/)
* [Mailing List](https://lists.mozilla.org/listinfo/dev-mozjpeg)</a>

View File

@@ -122,6 +122,10 @@ JMESSAGE(JERR_UNKNOWN_FORMAT, "Unrecognized input file format")
#endif #endif
JMESSAGE(JERR_UNSUPPORTED_FORMAT, "Unsupported output file format") JMESSAGE(JERR_UNSUPPORTED_FORMAT, "Unsupported output file format")
#ifdef PNG_SUPPORTED
JMESSAGE(JERR_PNG_ERROR, "Unable to read PNG file: %s")
#endif
#ifdef JMAKE_ENUM_LIST #ifdef JMAKE_ENUM_LIST
JMSG_LASTADDONCODE JMSG_LASTADDONCODE

View File

@@ -13,12 +13,12 @@
* cjpeg and djpeg. It is NOT used by the core JPEG library. * cjpeg and djpeg. It is NOT used by the core JPEG library.
*/ */
#define JPEG_CJPEG_DJPEG /* define proper options in jconfig.h */ #define JPEG_CJPEG_DJPEG /* define proper options in jconfig.h */
#define JPEG_INTERNAL_OPTIONS /* cjpeg.c,djpeg.c need to see xxx_SUPPORTED */ #define JPEG_INTERNAL_OPTIONS /* cjpeg.c,djpeg.c need to see xxx_SUPPORTED */
#include "jinclude.h" #include "jinclude.h"
#include "jpeglib.h" #include "jpeglib.h"
#include "jerror.h" /* get library error codes too */ #include "jerror.h" /* get library error codes too */
#include "cderror.h" /* get application-specific error codes */ #include "cderror.h" /* get application-specific error codes */
#define JPEG_RAW_READER 0 #define JPEG_RAW_READER 0
@@ -85,9 +85,9 @@ struct djpeg_dest_struct {
*/ */
struct cdjpeg_progress_mgr { struct cdjpeg_progress_mgr {
struct jpeg_progress_mgr pub; /* fields known to JPEG library */ struct jpeg_progress_mgr pub; /* fields known to JPEG library */
int completed_extra_passes; /* extra passes completed */ int completed_extra_passes; /* extra passes completed */
int total_extra_passes; /* total extra */ int total_extra_passes; /* total extra */
/* last printed percentage stored here to avoid multiple printouts */ /* last printed percentage stored here to avoid multiple printouts */
int percent_done; int percent_done;
}; };
@@ -104,6 +104,7 @@ EXTERN(cjpeg_source_ptr) jinit_read_gif (j_compress_ptr cinfo);
EXTERN(djpeg_dest_ptr) jinit_write_gif (j_decompress_ptr cinfo); EXTERN(djpeg_dest_ptr) jinit_write_gif (j_decompress_ptr cinfo);
EXTERN(cjpeg_source_ptr) jinit_read_jpeg (j_compress_ptr cinfo); EXTERN(cjpeg_source_ptr) jinit_read_jpeg (j_compress_ptr cinfo);
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) jinit_read_png (j_compress_ptr cinfo);
EXTERN(djpeg_dest_ptr) jinit_write_ppm (j_decompress_ptr cinfo); EXTERN(djpeg_dest_ptr) jinit_write_ppm (j_decompress_ptr cinfo);
EXTERN(cjpeg_source_ptr) jinit_read_rle (j_compress_ptr cinfo); EXTERN(cjpeg_source_ptr) jinit_read_rle (j_compress_ptr cinfo);
EXTERN(djpeg_dest_ptr) jinit_write_rle (j_decompress_ptr cinfo); EXTERN(djpeg_dest_ptr) jinit_write_rle (j_decompress_ptr cinfo);
@@ -136,15 +137,15 @@ EXTERN(FILE *) write_stdout (void);
/* miscellaneous useful macros */ /* miscellaneous useful macros */
#ifdef DONT_USE_B_MODE /* define mode parameters for fopen() */ #ifdef DONT_USE_B_MODE /* define mode parameters for fopen() */
#define READ_BINARY "r" #define READ_BINARY "r"
#define WRITE_BINARY "w" #define WRITE_BINARY "w"
#else #else
#define READ_BINARY "rb" #define READ_BINARY "rb"
#define WRITE_BINARY "wb" #define WRITE_BINARY "wb"
#endif #endif
#ifndef EXIT_FAILURE /* define exit() codes if not provided */ #ifndef EXIT_FAILURE /* define exit() codes if not provided */
#define EXIT_FAILURE 1 #define EXIT_FAILURE 1
#endif #endif
#ifndef EXIT_SUCCESS #ifndef EXIT_SUCCESS

29
cjpeg.c
View File

@@ -113,6 +113,10 @@ select_file_type (j_compress_ptr cinfo, FILE * infile)
case 'P': case 'P':
return jinit_read_ppm(cinfo); return jinit_read_ppm(cinfo);
#endif #endif
#ifdef PNG_SUPPORTED
case 0x89:
return jinit_read_png(cinfo);
#endif
#ifdef RLE_SUPPORTED #ifdef RLE_SUPPORTED
case 'R': case 'R':
return jinit_read_rle(cinfo); return jinit_read_rle(cinfo);
@@ -168,13 +172,17 @@ usage (void)
#ifdef C_PROGRESSIVE_SUPPORTED #ifdef C_PROGRESSIVE_SUPPORTED
fprintf(stderr, " -progressive Create progressive JPEG file (enabled by default)\n"); fprintf(stderr, " -progressive Create progressive JPEG file (enabled by default)\n");
#endif #endif
fprintf(stderr, " -baseline Create baseline JPEG file (disable progressive coding)\n");
#ifdef TARGA_SUPPORTED #ifdef TARGA_SUPPORTED
fprintf(stderr, " -targa Input file is Targa format (usually not needed)\n"); fprintf(stderr, " -targa Input file is Targa format (usually not needed)\n");
#endif #endif
fprintf(stderr, " -revert Revert to standard defaults (instead of mozjpeg defaults)\n"); fprintf(stderr, " -revert Revert to standard defaults (instead of mozjpeg defaults)\n");
fprintf(stderr, " -fastcrush Disable progressive scan optimization\n"); fprintf(stderr, " -fastcrush Disable progressive scan optimization\n");
fprintf(stderr, " -multidcscan Use multiple DC scans (may be incompatible with some JPEG decoders)\n"); fprintf(stderr, " -opt-dc-scan Optimize DC scans (may be incompatible with some JPEG decoders)\n");
fprintf(stderr, " -split-dc-scan Use one DC scan per component (may be incompatible with some JPEG decoders?)\n");
fprintf(stderr, " -notrellis Disable trellis optimization\n"); fprintf(stderr, " -notrellis Disable trellis optimization\n");
fprintf(stderr, " -trellis-dc Enable trellis optimization of DC coefficients (default)\n");
fprintf(stderr, " -notrellis-dc Disable trellis optimization of DC coefficients\n");
fprintf(stderr, " -tune-psnr Tune trellis optimization for PSNR\n"); fprintf(stderr, " -tune-psnr Tune trellis optimization for PSNR\n");
fprintf(stderr, " -tune-hvs-psnr Tune trellis optimization for PSNR-HVS (default)\n"); fprintf(stderr, " -tune-hvs-psnr Tune trellis optimization for PSNR-HVS (default)\n");
fprintf(stderr, " -tune-ssim Tune trellis optimization for SSIM\n"); fprintf(stderr, " -tune-ssim Tune trellis optimization for SSIM\n");
@@ -206,7 +214,6 @@ usage (void)
#endif #endif
fprintf(stderr, " -verbose or -debug Emit debug output\n"); fprintf(stderr, " -verbose or -debug Emit debug output\n");
fprintf(stderr, "Switches for wizards:\n"); fprintf(stderr, "Switches for wizards:\n");
fprintf(stderr, " -baseline Force baseline quantization tables\n");
fprintf(stderr, " -qtables file Use quantization tables given in file\n"); fprintf(stderr, " -qtables file Use quantization tables given in file\n");
fprintf(stderr, " -qslots N[,...] Set component quantization tables\n"); fprintf(stderr, " -qslots N[,...] Set component quantization tables\n");
fprintf(stderr, " -sample HxV[,...] Set component sampling factors\n"); fprintf(stderr, " -sample HxV[,...] Set component sampling factors\n");
@@ -279,6 +286,10 @@ parse_switches (j_compress_ptr cinfo, int argc, char **argv,
} else if (keymatch(arg, "baseline", 1)) { } else if (keymatch(arg, "baseline", 1)) {
/* Force baseline-compatible output (8-bit quantizer values). */ /* Force baseline-compatible output (8-bit quantizer values). */
force_baseline = TRUE; force_baseline = TRUE;
/* Disable multiple scans */
simple_progressive = FALSE;
cinfo->num_scans = 0;
cinfo->scan_info = NULL;
} else if (keymatch(arg, "dct", 2)) { } else if (keymatch(arg, "dct", 2)) {
/* Select DCT algorithm. */ /* Select DCT algorithm. */
@@ -349,7 +360,7 @@ parse_switches (j_compress_ptr cinfo, int argc, char **argv,
lval *= 1000L; lval *= 1000L;
cinfo->mem->max_memory_to_use = lval * 1000L; cinfo->mem->max_memory_to_use = lval * 1000L;
} else if (keymatch(arg, "multidcscan", 3)) { } else if (keymatch(arg, "opt-dc-scan", 6)) {
cinfo->one_dc_scan = FALSE; cinfo->one_dc_scan = FALSE;
} else if (keymatch(arg, "optimize", 1) || keymatch(arg, "optimise", 1)) { } else if (keymatch(arg, "optimize", 1) || keymatch(arg, "optimise", 1)) {
@@ -475,14 +486,26 @@ parse_switches (j_compress_ptr cinfo, int argc, char **argv,
usage(); usage();
cinfo->smoothing_factor = val; cinfo->smoothing_factor = val;
} else if (keymatch(arg, "split-dc-scans", 3)) {
cinfo->one_dc_scan = FALSE;
cinfo->sep_dc_scan = TRUE;
} else if (keymatch(arg, "targa", 1)) { } else if (keymatch(arg, "targa", 1)) {
/* Input file is Targa format. */ /* Input file is Targa format. */
is_targa = TRUE; is_targa = TRUE;
} else if (keymatch(arg, "notrellis-dc", 11)) {
/* disable trellis quantization */
cinfo->trellis_quant_dc = FALSE;
} else if (keymatch(arg, "notrellis", 1)) { } else if (keymatch(arg, "notrellis", 1)) {
/* disable trellis quantization */ /* disable trellis quantization */
cinfo->trellis_quant = FALSE; cinfo->trellis_quant = FALSE;
} else if (keymatch(arg, "trellis-dc", 9)) {
/* enable DC trellis quantization */
cinfo->trellis_quant_dc = TRUE;
} else if (keymatch(arg, "tune-psnr", 6)) { } else if (keymatch(arg, "tune-psnr", 6)) {
cinfo->use_flat_quant_tbl = TRUE; cinfo->use_flat_quant_tbl = TRUE;
cinfo->lambda_log_scale1 = 9.0; cinfo->lambda_log_scale1 = 9.0;

View File

@@ -2,7 +2,7 @@
# Process this file with autoconf to produce a configure script. # Process this file with autoconf to produce a configure script.
AC_PREREQ([2.56]) AC_PREREQ([2.56])
AC_INIT([libmozjpeg], [2.0.1]) AC_INIT([libmozjpeg], [2.1])
BUILD=`date +%Y%m%d` BUILD=`date +%Y%m%d`
AM_INIT_AUTOMAKE([-Wall foreign dist-bzip2]) AM_INIT_AUTOMAKE([-Wall foreign dist-bzip2])
@@ -93,6 +93,11 @@ fi
# Checks for libraries. # Checks for libraries.
AC_CHECK_LIB([m],[pow]) AC_CHECK_LIB([m],[pow])
PKG_CHECK_MODULES([libpng], [libpng], [HAVE_LIBPNG=1], [
PKG_CHECK_MODULES([libpng], [libpng12], [HAVE_LIBPNG=1], [HAVE_LIBPNG=0])
])
AM_CONDITIONAL([HAVE_LIBPNG], [test "$HAVE_LIBPNG" -eq 1])
# Checks for header files. # Checks for header files.
AC_HEADER_STDC AC_HEADER_STDC
AC_CHECK_HEADERS([stddef.h stdlib.h locale.h string.h]) AC_CHECK_HEADERS([stddef.h stdlib.h locale.h string.h])
@@ -263,7 +268,7 @@ int bar() { return foo();], ljt_cv_inline="__inline",
AC_TRY_COMPILE(, [} inline int foo() { return 0; } AC_TRY_COMPILE(, [} inline int foo() { return 0; }
int bar() { return foo();], ljt_cv_inline="inline")))) int bar() { return foo();], ljt_cv_inline="inline"))))
AC_MSG_RESULT($ljt_cv_inline) AC_MSG_RESULT($ljt_cv_inline)
AC_DEFINE_UNQUOTED([INLINE],[inline $ljt_cv_inline],[How to obtain function inlining.]) AC_DEFINE_UNQUOTED([INLINE],[$ljt_cv_inline],[How to obtain function inlining.])
# Arithmetic coding support # Arithmetic coding support
AC_MSG_CHECKING([whether to include arithmetic encoding support]) AC_MSG_CHECKING([whether to include arithmetic encoding support])

View File

@@ -360,10 +360,13 @@ compress_trellis_pass (j_compress_ptr cinfo, JSAMPIMAGE input_buf)
JBLOCKARRAY buffer_dst; JBLOCKARRAY buffer_dst;
for (ci = 0; ci < cinfo->comps_in_scan; ci++) { for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
c_derived_tbl dctbl_data;
c_derived_tbl *dctbl = &dctbl_data;
c_derived_tbl actbl_data; c_derived_tbl actbl_data;
c_derived_tbl *actbl = &actbl_data; c_derived_tbl *actbl = &actbl_data;
compptr = cinfo->cur_comp_info[ci]; compptr = cinfo->cur_comp_info[ci];
jpeg_make_c_derived_tbl(cinfo, TRUE, compptr->dc_tbl_no, &dctbl);
jpeg_make_c_derived_tbl(cinfo, FALSE, compptr->ac_tbl_no, &actbl); jpeg_make_c_derived_tbl(cinfo, FALSE, compptr->ac_tbl_no, &actbl);
/* Align the virtual buffer for this component. */ /* Align the virtual buffer for this component. */
@@ -391,12 +394,15 @@ compress_trellis_pass (j_compress_ptr cinfo, JSAMPIMAGE input_buf)
ndummy = (int) (blocks_across % h_samp_factor); ndummy = (int) (blocks_across % h_samp_factor);
if (ndummy > 0) if (ndummy > 0)
ndummy = h_samp_factor - ndummy; ndummy = h_samp_factor - ndummy;
lastDC = 0;
/* Perform DCT for all non-dummy blocks in this iMCU row. Each call /* Perform DCT for all non-dummy blocks in this iMCU row. Each call
* on forward_DCT processes a complete horizontal row of DCT blocks. * on forward_DCT processes a complete horizontal row of DCT blocks.
*/ */
for (block_row = 0; block_row < block_rows; block_row++) { for (block_row = 0; block_row < block_rows; block_row++) {
thisblockrow = buffer[block_row]; thisblockrow = buffer[block_row];
quantize_trellis(cinfo, actbl, thisblockrow, buffer_dst[block_row], blocks_across, cinfo->quant_tbl_ptrs[compptr->quant_tbl_no], cinfo->norm_src[compptr->quant_tbl_no], cinfo->norm_coef[compptr->quant_tbl_no]); quantize_trellis(cinfo, dctbl, actbl, thisblockrow, buffer_dst[block_row], blocks_across, cinfo->quant_tbl_ptrs[compptr->quant_tbl_no], cinfo->norm_src[compptr->quant_tbl_no], cinfo->norm_coef[compptr->quant_tbl_no], &lastDC);
if (ndummy > 0) { if (ndummy > 0) {
/* Create dummy blocks at the right edge of the image. */ /* Create dummy blocks at the right edge of the image. */

View File

@@ -20,7 +20,7 @@
#define JPEG_INTERNALS #define JPEG_INTERNALS
#include "jinclude.h" #include "jinclude.h"
#include "jpeglib.h" #include "jpeglib.h"
#include "jdct.h" /* Private declarations for DCT subsystem */ #include "jdct.h" /* Private declarations for DCT subsystem */
#include "jsimddct.h" #include "jsimddct.h"
#include <assert.h> #include <assert.h>
#include <math.h> #include <math.h>
@@ -46,7 +46,7 @@ typedef void (*float_quantize_method_ptr) (JCOEFPTR coef_block,
METHODDEF(void) quantize (JCOEFPTR, DCTELEM *, DCTELEM *); METHODDEF(void) quantize (JCOEFPTR, DCTELEM *, DCTELEM *);
typedef struct { typedef struct {
struct jpeg_forward_dct pub; /* public fields */ struct jpeg_forward_dct pub; /* public fields */
/* Pointer to the DCT routine actually in use */ /* Pointer to the DCT routine actually in use */
forward_DCT_method_ptr dct; forward_DCT_method_ptr dct;
@@ -223,7 +223,7 @@ start_pass_fdctmgr (j_compress_ptr cinfo)
qtblno = compptr->quant_tbl_no; qtblno = compptr->quant_tbl_no;
/* Make sure specified quantization table is present */ /* Make sure specified quantization table is present */
if (qtblno < 0 || qtblno >= NUM_QUANT_TBLS || if (qtblno < 0 || qtblno >= NUM_QUANT_TBLS ||
cinfo->quant_tbl_ptrs[qtblno] == NULL) cinfo->quant_tbl_ptrs[qtblno] == NULL)
ERREXIT1(cinfo, JERR_NO_QUANT_TABLE, qtblno); ERREXIT1(cinfo, JERR_NO_QUANT_TABLE, qtblno);
qtbl = cinfo->quant_tbl_ptrs[qtblno]; qtbl = cinfo->quant_tbl_ptrs[qtblno];
/* Compute divisors for this quant table */ /* Compute divisors for this quant table */
@@ -235,91 +235,91 @@ start_pass_fdctmgr (j_compress_ptr cinfo)
* coefficients multiplied by 8 (to counteract scaling). * coefficients multiplied by 8 (to counteract scaling).
*/ */
if (fdct->divisors[qtblno] == NULL) { if (fdct->divisors[qtblno] == NULL) {
fdct->divisors[qtblno] = (DCTELEM *) fdct->divisors[qtblno] = (DCTELEM *)
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
(DCTSIZE2 * 4) * sizeof(DCTELEM)); (DCTSIZE2 * 4) * sizeof(DCTELEM));
} }
dtbl = fdct->divisors[qtblno]; dtbl = fdct->divisors[qtblno];
for (i = 0; i < DCTSIZE2; i++) { for (i = 0; i < DCTSIZE2; i++) {
if(!compute_reciprocal(qtbl->quantval[i] << 3, &dtbl[i]) if(!compute_reciprocal(qtbl->quantval[i] << 3, &dtbl[i])
&& fdct->quantize == jsimd_quantize) && fdct->quantize == jsimd_quantize)
fdct->quantize = quantize; fdct->quantize = quantize;
} }
break; break;
#endif #endif
#ifdef DCT_IFAST_SUPPORTED #ifdef DCT_IFAST_SUPPORTED
case JDCT_IFAST: case JDCT_IFAST:
{ {
/* For AA&N IDCT method, divisors are equal to quantization /* For AA&N IDCT method, divisors are equal to quantization
* coefficients scaled by scalefactor[row]*scalefactor[col], where * coefficients scaled by scalefactor[row]*scalefactor[col], where
* scalefactor[0] = 1 * scalefactor[0] = 1
* scalefactor[k] = cos(k*PI/16) * sqrt(2) for k=1..7 * scalefactor[k] = cos(k*PI/16) * sqrt(2) for k=1..7
* We apply a further scale factor of 8. * We apply a further scale factor of 8.
*/ */
#define CONST_BITS 14 #define CONST_BITS 14
static const INT16 aanscales[DCTSIZE2] = { static const INT16 aanscales[DCTSIZE2] = {
/* precomputed values scaled up by 14 bits */ /* precomputed values scaled up by 14 bits */
16384, 22725, 21407, 19266, 16384, 12873, 8867, 4520, 16384, 22725, 21407, 19266, 16384, 12873, 8867, 4520,
22725, 31521, 29692, 26722, 22725, 17855, 12299, 6270, 22725, 31521, 29692, 26722, 22725, 17855, 12299, 6270,
21407, 29692, 27969, 25172, 21407, 16819, 11585, 5906, 21407, 29692, 27969, 25172, 21407, 16819, 11585, 5906,
19266, 26722, 25172, 22654, 19266, 15137, 10426, 5315, 19266, 26722, 25172, 22654, 19266, 15137, 10426, 5315,
16384, 22725, 21407, 19266, 16384, 12873, 8867, 4520, 16384, 22725, 21407, 19266, 16384, 12873, 8867, 4520,
12873, 17855, 16819, 15137, 12873, 10114, 6967, 3552, 12873, 17855, 16819, 15137, 12873, 10114, 6967, 3552,
8867, 12299, 11585, 10426, 8867, 6967, 4799, 2446, 8867, 12299, 11585, 10426, 8867, 6967, 4799, 2446,
4520, 6270, 5906, 5315, 4520, 3552, 2446, 1247 4520, 6270, 5906, 5315, 4520, 3552, 2446, 1247
}; };
SHIFT_TEMPS SHIFT_TEMPS
if (fdct->divisors[qtblno] == NULL) { if (fdct->divisors[qtblno] == NULL) {
fdct->divisors[qtblno] = (DCTELEM *) fdct->divisors[qtblno] = (DCTELEM *)
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
(DCTSIZE2 * 4) * sizeof(DCTELEM)); (DCTSIZE2 * 4) * sizeof(DCTELEM));
} }
dtbl = fdct->divisors[qtblno]; dtbl = fdct->divisors[qtblno];
for (i = 0; i < DCTSIZE2; i++) { for (i = 0; i < DCTSIZE2; i++) {
if(!compute_reciprocal( if(!compute_reciprocal(
DESCALE(MULTIPLY16V16((INT32) qtbl->quantval[i], DESCALE(MULTIPLY16V16((INT32) qtbl->quantval[i],
(INT32) aanscales[i]), (INT32) aanscales[i]),
CONST_BITS-3), &dtbl[i]) CONST_BITS-3), &dtbl[i])
&& fdct->quantize == jsimd_quantize) && fdct->quantize == jsimd_quantize)
fdct->quantize = quantize; fdct->quantize = quantize;
} }
} }
break; break;
#endif #endif
#ifdef DCT_FLOAT_SUPPORTED #ifdef DCT_FLOAT_SUPPORTED
case JDCT_FLOAT: case JDCT_FLOAT:
{ {
/* For float AA&N IDCT method, divisors are equal to quantization /* For float AA&N IDCT method, divisors are equal to quantization
* coefficients scaled by scalefactor[row]*scalefactor[col], where * coefficients scaled by scalefactor[row]*scalefactor[col], where
* scalefactor[0] = 1 * scalefactor[0] = 1
* scalefactor[k] = cos(k*PI/16) * sqrt(2) for k=1..7 * scalefactor[k] = cos(k*PI/16) * sqrt(2) for k=1..7
* We apply a further scale factor of 8. * We apply a further scale factor of 8.
* What's actually stored is 1/divisor so that the inner loop can * What's actually stored is 1/divisor so that the inner loop can
* use a multiplication rather than a division. * use a multiplication rather than a division.
*/ */
FAST_FLOAT * fdtbl; FAST_FLOAT * fdtbl;
int row, col; int row, col;
static const double aanscalefactor[DCTSIZE] = { static const double aanscalefactor[DCTSIZE] = {
1.0, 1.387039845, 1.306562965, 1.175875602, 1.0, 1.387039845, 1.306562965, 1.175875602,
1.0, 0.785694958, 0.541196100, 0.275899379 1.0, 0.785694958, 0.541196100, 0.275899379
}; };
if (fdct->float_divisors[qtblno] == NULL) { if (fdct->float_divisors[qtblno] == NULL) {
fdct->float_divisors[qtblno] = (FAST_FLOAT *) fdct->float_divisors[qtblno] = (FAST_FLOAT *)
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
DCTSIZE2 * sizeof(FAST_FLOAT)); DCTSIZE2 * sizeof(FAST_FLOAT));
} }
fdtbl = fdct->float_divisors[qtblno]; fdtbl = fdct->float_divisors[qtblno];
i = 0; i = 0;
for (row = 0; row < DCTSIZE; row++) { for (row = 0; row < DCTSIZE; row++) {
for (col = 0; col < DCTSIZE; col++) { for (col = 0; col < DCTSIZE; col++) {
fdtbl[i] = (FAST_FLOAT) fdtbl[i] = (FAST_FLOAT)
(1.0 / (((double) qtbl->quantval[i] * (1.0 / (((double) qtbl->quantval[i] *
aanscalefactor[row] * aanscalefactor[col] * 8.0))); aanscalefactor[row] * aanscalefactor[col] * 8.0)));
i++; i++;
} }
} }
} }
break; break;
#endif #endif
@@ -346,7 +346,7 @@ convsamp (JSAMPARRAY sample_data, JDIMENSION start_col, DCTELEM * workspace)
for (elemr = 0; elemr < DCTSIZE; elemr++) { for (elemr = 0; elemr < DCTSIZE; elemr++) {
elemptr = sample_data[elemr] + start_col; elemptr = sample_data[elemr] + start_col;
#if DCTSIZE == 8 /* unroll the inner loop */ #if DCTSIZE == 8 /* unroll the inner loop */
*workspaceptr++ = GETJSAMPLE(*elemptr++) - CENTERJSAMPLE; *workspaceptr++ = GETJSAMPLE(*elemptr++) - CENTERJSAMPLE;
*workspaceptr++ = GETJSAMPLE(*elemptr++) - CENTERJSAMPLE; *workspaceptr++ = GETJSAMPLE(*elemptr++) - CENTERJSAMPLE;
*workspaceptr++ = GETJSAMPLE(*elemptr++) - CENTERJSAMPLE; *workspaceptr++ = GETJSAMPLE(*elemptr++) - CENTERJSAMPLE;
@@ -412,8 +412,8 @@ quantize (JCOEFPTR coef_block, DCTELEM * divisors, DCTELEM * workspace)
METHODDEF(void) METHODDEF(void)
forward_DCT (j_compress_ptr cinfo, jpeg_component_info * compptr, forward_DCT (j_compress_ptr cinfo, jpeg_component_info * compptr,
JSAMPARRAY sample_data, JBLOCKROW coef_blocks, JSAMPARRAY sample_data, JBLOCKROW coef_blocks,
JDIMENSION start_row, JDIMENSION start_col, JDIMENSION start_row, JDIMENSION start_col,
JDIMENSION num_blocks, JBLOCKROW dst) JDIMENSION num_blocks, JBLOCKROW dst)
/* This version is used for integer DCT implementations. */ /* This version is used for integer DCT implementations. */
{ {
@@ -429,7 +429,7 @@ forward_DCT (j_compress_ptr cinfo, jpeg_component_info * compptr,
quantize_method_ptr do_quantize = fdct->quantize; quantize_method_ptr do_quantize = fdct->quantize;
workspace = fdct->workspace; workspace = fdct->workspace;
sample_data += start_row; /* fold in the vertical offset once */ sample_data += start_row; /* fold in the vertical offset once */
for (bi = 0; bi < num_blocks; bi++, start_col += DCTSIZE) { for (bi = 0; bi < num_blocks; bi++, start_col += DCTSIZE) {
/* Load data into workspace, applying unsigned->signed conversion */ /* Load data into workspace, applying unsigned->signed conversion */
@@ -487,7 +487,7 @@ convsamp_float (JSAMPARRAY sample_data, JDIMENSION start_col, FAST_FLOAT * works
workspaceptr = workspace; workspaceptr = workspace;
for (elemr = 0; elemr < DCTSIZE; elemr++) { for (elemr = 0; elemr < DCTSIZE; elemr++) {
elemptr = sample_data[elemr] + start_col; elemptr = sample_data[elemr] + start_col;
#if DCTSIZE == 8 /* unroll the inner loop */ #if DCTSIZE == 8 /* unroll the inner loop */
*workspaceptr++ = (FAST_FLOAT)(GETJSAMPLE(*elemptr++) - CENTERJSAMPLE); *workspaceptr++ = (FAST_FLOAT)(GETJSAMPLE(*elemptr++) - CENTERJSAMPLE);
*workspaceptr++ = (FAST_FLOAT)(GETJSAMPLE(*elemptr++) - CENTERJSAMPLE); *workspaceptr++ = (FAST_FLOAT)(GETJSAMPLE(*elemptr++) - CENTERJSAMPLE);
*workspaceptr++ = (FAST_FLOAT)(GETJSAMPLE(*elemptr++) - CENTERJSAMPLE); *workspaceptr++ = (FAST_FLOAT)(GETJSAMPLE(*elemptr++) - CENTERJSAMPLE);
@@ -532,8 +532,8 @@ quantize_float (JCOEFPTR coef_block, FAST_FLOAT * divisors, FAST_FLOAT * workspa
METHODDEF(void) METHODDEF(void)
forward_DCT_float (j_compress_ptr cinfo, jpeg_component_info * compptr, forward_DCT_float (j_compress_ptr cinfo, jpeg_component_info * compptr,
JSAMPARRAY sample_data, JBLOCKROW coef_blocks, JSAMPARRAY sample_data, JBLOCKROW coef_blocks,
JDIMENSION start_row, JDIMENSION start_col, JDIMENSION start_row, JDIMENSION start_col,
JDIMENSION num_blocks, JBLOCKROW dst) JDIMENSION num_blocks, JBLOCKROW dst)
/* This version is used for floating-point DCT implementations. */ /* This version is used for floating-point DCT implementations. */
{ {
@@ -552,7 +552,7 @@ forward_DCT_float (j_compress_ptr cinfo, jpeg_component_info * compptr,
float_quantize_method_ptr do_quantize = fdct->float_quantize; float_quantize_method_ptr do_quantize = fdct->float_quantize;
workspace = fdct->float_workspace; workspace = fdct->float_workspace;
sample_data += start_row; /* fold in the vertical offset once */ sample_data += start_row; /* fold in the vertical offset once */
for (bi = 0; bi < num_blocks; bi++, start_col += DCTSIZE) { for (bi = 0; bi < num_blocks; bi++, start_col += DCTSIZE) {
/* Load data into workspace, applying unsigned->signed conversion */ /* Load data into workspace, applying unsigned->signed conversion */
@@ -614,10 +614,10 @@ static const float jpeg_lambda_weights_csf_luma[64] = {
}; };
GLOBAL(void) GLOBAL(void)
quantize_trellis(j_compress_ptr cinfo, c_derived_tbl *actbl, JBLOCKROW coef_blocks, JBLOCKROW src, JDIMENSION num_blocks, quantize_trellis(j_compress_ptr cinfo, c_derived_tbl *dctbl, c_derived_tbl *actbl, JBLOCKROW coef_blocks, JBLOCKROW src, JDIMENSION num_blocks,
JQUANT_TBL * qtbl, double *norm_src, double *norm_coef) JQUANT_TBL * qtbl, double *norm_src, double *norm_coef, JCOEF *last_dc_val)
{ {
int i, j, k; int i, j, k, l;
float accumulated_zero_dist[DCTSIZE2]; float accumulated_zero_dist[DCTSIZE2];
float accumulated_cost[DCTSIZE2]; float accumulated_cost[DCTSIZE2];
int run_start[DCTSIZE2]; int run_start[DCTSIZE2];
@@ -627,6 +627,7 @@ quantize_trellis(j_compress_ptr cinfo, c_derived_tbl *actbl, JBLOCKROW coef_bloc
float norm = 0.0; float norm = 0.0;
float lambda_base; float lambda_base;
float lambda; float lambda;
float lambda_dc;
const float *lambda_tbl = (cinfo->use_lambda_weight_tbl) ? jpeg_lambda_weights_csf_luma : jpeg_lambda_weights_flat; const float *lambda_tbl = (cinfo->use_lambda_weight_tbl) ? jpeg_lambda_weights_csf_luma : jpeg_lambda_weights_flat;
int Ss, Se; int Ss, Se;
float *accumulated_zero_block_cost = NULL; float *accumulated_zero_block_cost = NULL;
@@ -640,6 +641,9 @@ quantize_trellis(j_compress_ptr cinfo, c_derived_tbl *actbl, JBLOCKROW coef_bloc
int zero_run; int zero_run;
int run_bits; int run_bits;
int rate; int rate;
float *accumulated_dc_cost[3];
int *dc_cost_backtrack[3];
JCOEF *dc_candidate[3];
Ss = cinfo->Ss; Ss = cinfo->Ss;
Se = cinfo->Se; Se = cinfo->Se;
@@ -652,11 +656,29 @@ quantize_trellis(j_compress_ptr cinfo, c_derived_tbl *actbl, JBLOCKROW coef_bloc
accumulated_block_cost = (float *)malloc((num_blocks + 1) * sizeof(float)); accumulated_block_cost = (float *)malloc((num_blocks + 1) * sizeof(float));
block_run_start = (int *)malloc(num_blocks * sizeof(int)); block_run_start = (int *)malloc(num_blocks * sizeof(int));
requires_eob = (int *)malloc((num_blocks + 1) * sizeof(int)); requires_eob = (int *)malloc((num_blocks + 1) * sizeof(int));
if (!accumulated_zero_block_cost ||
!accumulated_block_cost ||
!block_run_start ||
!requires_eob) {
ERREXIT(cinfo, JERR_OUT_OF_MEMORY);
}
accumulated_zero_block_cost[0] = 0; accumulated_zero_block_cost[0] = 0;
accumulated_block_cost[0] = 0; accumulated_block_cost[0] = 0;
requires_eob[0] = 0; requires_eob[0] = 0;
} }
if (cinfo->trellis_quant_dc) {
for (i = 0; i < 3; i++) {
accumulated_dc_cost[i] = (float *)malloc(num_blocks * sizeof(float));
dc_cost_backtrack[i] = (int *)malloc(num_blocks * sizeof(int));
dc_candidate[i] = (JCOEF *)malloc(num_blocks * sizeof(JCOEF));
if (!accumulated_dc_cost[i] ||
!dc_cost_backtrack[i] ||
!dc_candidate[i]) {
ERREXIT(cinfo, JERR_OUT_OF_MEMORY);
}
}
}
norm = 0.0; norm = 0.0;
for (i = 1; i < DCTSIZE2; i++) { for (i = 1; i < DCTSIZE2; i++) {
norm += qtbl->quantval[i] * qtbl->quantval[i]; norm += qtbl->quantval[i] * qtbl->quantval[i];
@@ -678,9 +700,65 @@ quantize_trellis(j_compress_ptr cinfo, c_derived_tbl *actbl, JBLOCKROW coef_bloc
else else
lambda = pow(2.0, cinfo->lambda_log_scale1-12.0) * lambda_base; lambda = pow(2.0, cinfo->lambda_log_scale1-12.0) * lambda_base;
lambda_dc = lambda * lambda_tbl[0];
accumulated_zero_dist[Ss-1] = 0.0; accumulated_zero_dist[Ss-1] = 0.0;
accumulated_cost[Ss-1] = 0.0; accumulated_cost[Ss-1] = 0.0;
// Do DC coefficient
if (cinfo->trellis_quant_dc) {
int sign = src[bi][0] >> 31;
int x = abs(src[bi][0]);
int q = 8 * qtbl->quantval[0];
int qval;
float dc_candidate_dist;
qval = (x + q/2) / q; /* quantized value (round nearest) */
for (k = 0; k < 3; k++) {
int delta;
int dc_delta;
int bits;
dc_candidate[k][bi] = qval - 1 + k;
delta = dc_candidate[k][bi] * q - x;
dc_candidate_dist = delta * delta * lambda_dc;
dc_candidate[k][bi] *= 1 + 2*sign;
if (bi == 0) {
dc_delta = dc_candidate[k][bi] - *last_dc_val;
// Derive number of suffix bits
bits = 0;
dc_delta = abs(dc_delta);
while (dc_delta) {
dc_delta >>= 1;
bits++;
}
cost = bits + dctbl->ehufsi[bits] + dc_candidate_dist;
accumulated_dc_cost[k][0] = cost;
dc_cost_backtrack[k][0] = -1;
} else {
for (l = 0; l < 3; l++) {
dc_delta = dc_candidate[k][bi] - dc_candidate[l][bi-1];
// Derive number of suffix bits
bits = 0;
dc_delta = abs(dc_delta);
while (dc_delta) {
dc_delta >>= 1;
bits++;
}
cost = bits + dctbl->ehufsi[bits] + dc_candidate_dist + accumulated_dc_cost[l][bi-1];
if (l == 0 || cost < accumulated_dc_cost[k][bi]) {
accumulated_dc_cost[k][bi] = cost;
dc_cost_backtrack[k][bi] = l;
}
}
}
}
}
// Do AC coefficients
for (i = Ss; i <= Se; i++) { for (i = Ss; i <= Se; i++) {
int z = jpeg_natural_order[i]; int z = jpeg_natural_order[i];
@@ -864,6 +942,28 @@ quantize_trellis(j_compress_ptr cinfo, c_derived_tbl *actbl, JBLOCKROW coef_bloc
} }
} }
} }
if (cinfo->trellis_quant_dc) {
j = 0;
for (i = 1; i < 3; i++) {
if (accumulated_dc_cost[i][num_blocks-1] < accumulated_dc_cost[j][num_blocks-1])
j = i;
}
for (bi = num_blocks-1; bi >= 0; bi--) {
coef_blocks[bi][0] = dc_candidate[j][bi];
j = dc_cost_backtrack[j][bi];
}
// Save DC predictor
*last_dc_val = coef_blocks[num_blocks-1][0];
for (i = 0; i < 3; i++) {
free(accumulated_dc_cost[i]);
free(dc_cost_backtrack[i]);
free(dc_candidate[i]);
}
}
} }
/* /*

View File

@@ -29,8 +29,8 @@
/* Derived data constructed for each Huffman table */ /* Derived data constructed for each Huffman table */
typedef struct { typedef struct {
unsigned int ehufco[256]; /* code for each symbol */ unsigned int ehufco[256]; /* code for each symbol */
char ehufsi[256]; /* length of code for each symbol */ char ehufsi[256]; /* length of code for each symbol */
/* If no code has been allocated for a symbol S, ehufsi[S] contains 0 */ /* If no code has been allocated for a symbol S, ehufsi[S] contains 0 */
} c_derived_tbl; } c_derived_tbl;
@@ -44,5 +44,5 @@ EXTERN(void) jpeg_gen_optimal_table
(j_compress_ptr cinfo, JHUFF_TBL * htbl, long freq[]); (j_compress_ptr cinfo, JHUFF_TBL * htbl, long freq[]);
EXTERN(void) quantize_trellis EXTERN(void) quantize_trellis
(j_compress_ptr cinfo, c_derived_tbl *actbl, JBLOCKROW coef_blocks, JBLOCKROW src, JDIMENSION num_blocks, (j_compress_ptr cinfo, c_derived_tbl *dctbl, c_derived_tbl *actbl, JBLOCKROW coef_blocks, JBLOCKROW src, JDIMENSION num_blocks,
JQUANT_TBL * qtbl, double *norm_src, double *norm_coef); JQUANT_TBL * qtbl, double *norm_src, double *norm_coef, JCOEF *last_dc_val);

View File

@@ -17,7 +17,7 @@
#include "jpegcomp.h" #include "jpegcomp.h"
typedef enum { /* JPEG marker codes */ typedef enum { /* JPEG marker codes */
M_SOF0 = 0xc0, M_SOF0 = 0xc0,
M_SOF1 = 0xc1, M_SOF1 = 0xc1,
M_SOF2 = 0xc2, M_SOF2 = 0xc2,
@@ -173,7 +173,7 @@ emit_dqt (j_compress_ptr cinfo, int index)
/* The table entries must be emitted in zigzag order. */ /* The table entries must be emitted in zigzag order. */
unsigned int qval = qtbl->quantval[jpeg_natural_order[i]]; unsigned int qval = qtbl->quantval[jpeg_natural_order[i]];
if (prec) if (prec)
emit_byte(cinfo, (int) (qval >> 8)); emit_byte(cinfo, (int) (qval >> 8));
emit_byte(cinfo, (int) (qval & 0xFF)); emit_byte(cinfo, (int) (qval & 0xFF));
} }
@@ -183,6 +183,69 @@ emit_dqt (j_compress_ptr cinfo, int index)
return prec; return prec;
} }
LOCAL(int)
emit_multi_dqt (j_compress_ptr cinfo)
/* Emits a DQT marker containing all quantization tables */
/* Returns number of emitted 16-bit tables, or -1 for failed for baseline checking. */
{
int prec[MAX_COMPONENTS];
int seen[MAX_COMPONENTS] = { 0 };
int fin_prec = 0;
int ci;
for (ci = 0; ci < cinfo->num_components; ci++) {
int tbl_num = cinfo->comp_info[ci].quant_tbl_no;
int i;
JQUANT_TBL * qtbl = cinfo->quant_tbl_ptrs[tbl_num];
if (qtbl == NULL || qtbl->sent_table == TRUE)
return -1;
prec[ci] = 0;
for (i = 0; i < DCTSIZE2; i++)
prec[ci] = !!(prec[ci] + (qtbl->quantval[i] > 255));
fin_prec += prec[ci];
}
emit_marker(cinfo, M_DQT);
int size = 0;
for (ci = 0; ci < cinfo->num_components; ci++) {
int tbl_num = cinfo->comp_info[ci].quant_tbl_no;
if (!seen[tbl_num]) {
size += DCTSIZE2 * (prec[ci] + 1) + 1;
seen[tbl_num] = 1;
}
}
size += 2;
emit_2bytes(cinfo, size);
for (ci = 0; ci < cinfo->num_components; ci++) {
int tbl_num = cinfo->comp_info[ci].quant_tbl_no;
int i;
JQUANT_TBL * qtbl = cinfo->quant_tbl_ptrs[tbl_num];
if (qtbl->sent_table == TRUE)
continue;
emit_byte(cinfo, tbl_num + (prec[ci] << 4));
for (i = 0; i < DCTSIZE2; i++) {
unsigned int qval = qtbl->quantval[jpeg_natural_order[i]];
if (prec[ci])
emit_byte(cinfo, (int) (qval >> 8));
emit_byte(cinfo, (int) (qval & 0xFF));
}
qtbl->sent_table = TRUE;
}
return fin_prec;
}
LOCAL(void) LOCAL(void)
emit_dht (j_compress_ptr cinfo, int index, boolean is_ac) emit_dht (j_compress_ptr cinfo, int index, boolean is_ac)
@@ -193,7 +256,7 @@ emit_dht (j_compress_ptr cinfo, int index, boolean is_ac)
if (is_ac) { if (is_ac) {
htbl = cinfo->ac_huff_tbl_ptrs[index]; htbl = cinfo->ac_huff_tbl_ptrs[index];
index += 0x10; /* output index has AC bit set */ index += 0x10; /* output index has AC bit set */
} else { } else {
htbl = cinfo->dc_huff_tbl_ptrs[index]; htbl = cinfo->dc_huff_tbl_ptrs[index];
} }
@@ -221,6 +284,112 @@ emit_dht (j_compress_ptr cinfo, int index, boolean is_ac)
} }
} }
LOCAL(boolean)
emit_multi_dht (j_compress_ptr cinfo)
/* Emit all DHT markers */
/* Returns FALSE on failure, TRUE otherwise. */
{
int i, j;
int length = 2;
int dclens[NUM_HUFF_TBLS] = { 0 };
int aclens[NUM_HUFF_TBLS] = { 0 };
JHUFF_TBL *dcseen[NUM_HUFF_TBLS] = { NULL };
JHUFF_TBL *acseen[NUM_HUFF_TBLS] = { NULL };
/* Calclate the total length. */
for (i = 0; i < cinfo->comps_in_scan; i++) {
jpeg_component_info *compptr = cinfo->cur_comp_info[i];
int dcidx = compptr->dc_tbl_no;
int acidx = compptr->ac_tbl_no;
JHUFF_TBL *dctbl = cinfo->dc_huff_tbl_ptrs[dcidx];
JHUFF_TBL *actbl = cinfo->ac_huff_tbl_ptrs[acidx];
int seen = 0;
/* Handle DC table lenghts */
if (cinfo->Ss == 0 && cinfo->Ah == 0) {
if (dctbl == NULL)
ERREXIT1(cinfo, JERR_NO_HUFF_TABLE, dcidx);
if (dctbl->sent_table)
continue;
for (j = 0; j < NUM_HUFF_TBLS; j++)
seen += (dctbl == dcseen[j]);
if (seen)
continue;
dcseen[i] = dctbl;
for (j = 1; j <= 16; j++)
dclens[i] += dctbl->bits[j];
length += dclens[i] + 16 + 1;
}
/* Handle AC table lengths */
if (cinfo->Se) {
if (actbl == NULL)
ERREXIT1(cinfo, JERR_NO_HUFF_TABLE, acidx + 0x10);
if (actbl->sent_table)
continue;
seen = 0;
for (j = 0; j < NUM_HUFF_TBLS; j++)
seen += (actbl == acseen[j]);
if (seen)
continue;
acseen[i] = actbl;
for (j = 1; j <= 16; j++)
aclens[i] += actbl->bits[j];
length += aclens[i] + 16 + 1;
}
}
/* Make sure we can fit it all into one DHT marker */
if (length > (1 << 16) - 1)
return FALSE;
emit_marker(cinfo, M_DHT);
emit_2bytes(cinfo, length);
for (i = 0; i < cinfo->comps_in_scan; i++) {
jpeg_component_info *compptr = cinfo->cur_comp_info[i];
int dcidx = compptr->dc_tbl_no;
int acidx = compptr->ac_tbl_no;
JHUFF_TBL *dctbl = cinfo->dc_huff_tbl_ptrs[dcidx];
JHUFF_TBL *actbl = cinfo->ac_huff_tbl_ptrs[acidx];
acidx += 0x10;
/* DC */
if (cinfo->Ss == 0 && cinfo->Ah == 0 && !dctbl->sent_table) {
emit_byte(cinfo, dcidx);
for (j = 1; j <= 16; j++)
emit_byte(cinfo, dctbl->bits[j]);
for (j = 0; j < dclens[i]; j++)
emit_byte(cinfo, dctbl->huffval[j]);
dctbl->sent_table = TRUE;
}
if (cinfo->Se && !actbl->sent_table) {
emit_byte(cinfo, acidx);
for (j = 1; j <= 16; j++)
emit_byte(cinfo, actbl->bits[j]);
for (j = 0; j < aclens[i]; j++)
emit_byte(cinfo, actbl->huffval[j]);
actbl->sent_table = TRUE;
}
}
return TRUE;
}
LOCAL(void) LOCAL(void)
emit_dac (j_compress_ptr cinfo) emit_dac (j_compress_ptr cinfo)
@@ -258,12 +427,12 @@ emit_dac (j_compress_ptr cinfo)
for (i = 0; i < NUM_ARITH_TBLS; i++) { for (i = 0; i < NUM_ARITH_TBLS; i++) {
if (dc_in_use[i]) { if (dc_in_use[i]) {
emit_byte(cinfo, i); emit_byte(cinfo, i);
emit_byte(cinfo, cinfo->arith_dc_L[i] + (cinfo->arith_dc_U[i]<<4)); emit_byte(cinfo, cinfo->arith_dc_L[i] + (cinfo->arith_dc_U[i]<<4));
} }
if (ac_in_use[i]) { if (ac_in_use[i]) {
emit_byte(cinfo, i + 0x10); emit_byte(cinfo, i + 0x10);
emit_byte(cinfo, cinfo->arith_ac_K[i]); emit_byte(cinfo, cinfo->arith_ac_K[i]);
} }
} }
} }
@@ -277,7 +446,7 @@ emit_dri (j_compress_ptr cinfo)
{ {
emit_marker(cinfo, M_DRI); emit_marker(cinfo, M_DRI);
emit_2bytes(cinfo, 4); /* fixed length */ emit_2bytes(cinfo, 4); /* fixed length */
emit_2bytes(cinfo, (int) cinfo->restart_interval); emit_2bytes(cinfo, (int) cinfo->restart_interval);
} }
@@ -354,22 +523,22 @@ emit_jfif_app0 (j_compress_ptr cinfo)
/* Emit a JFIF-compliant APP0 marker */ /* Emit a JFIF-compliant APP0 marker */
{ {
/* /*
* Length of APP0 block (2 bytes) * Length of APP0 block (2 bytes)
* Block ID (4 bytes - ASCII "JFIF") * Block ID (4 bytes - ASCII "JFIF")
* Zero byte (1 byte to terminate the ID string) * Zero byte (1 byte to terminate the ID string)
* Version Major, Minor (2 bytes - major first) * Version Major, Minor (2 bytes - major first)
* Units (1 byte - 0x00 = none, 0x01 = inch, 0x02 = cm) * Units (1 byte - 0x00 = none, 0x01 = inch, 0x02 = cm)
* Xdpu (2 bytes - dots per unit horizontal) * Xdpu (2 bytes - dots per unit horizontal)
* Ydpu (2 bytes - dots per unit vertical) * Ydpu (2 bytes - dots per unit vertical)
* Thumbnail X size (1 byte) * Thumbnail X size (1 byte)
* Thumbnail Y size (1 byte) * Thumbnail Y size (1 byte)
*/ */
emit_marker(cinfo, M_APP0); emit_marker(cinfo, M_APP0);
emit_2bytes(cinfo, 2 + 4 + 1 + 2 + 1 + 2 + 2 + 1 + 1); /* length */ emit_2bytes(cinfo, 2 + 4 + 1 + 2 + 1 + 2 + 2 + 1 + 1); /* length */
emit_byte(cinfo, 0x4A); /* Identifier: ASCII "JFIF" */ emit_byte(cinfo, 0x4A); /* Identifier: ASCII "JFIF" */
emit_byte(cinfo, 0x46); emit_byte(cinfo, 0x46);
emit_byte(cinfo, 0x49); emit_byte(cinfo, 0x49);
emit_byte(cinfo, 0x46); emit_byte(cinfo, 0x46);
@@ -379,7 +548,7 @@ emit_jfif_app0 (j_compress_ptr cinfo)
emit_byte(cinfo, cinfo->density_unit); /* Pixel size information */ emit_byte(cinfo, cinfo->density_unit); /* Pixel size information */
emit_2bytes(cinfo, (int) cinfo->X_density); emit_2bytes(cinfo, (int) cinfo->X_density);
emit_2bytes(cinfo, (int) cinfo->Y_density); emit_2bytes(cinfo, (int) cinfo->Y_density);
emit_byte(cinfo, 0); /* No thumbnail image */ emit_byte(cinfo, 0); /* No thumbnail image */
emit_byte(cinfo, 0); emit_byte(cinfo, 0);
} }
@@ -389,12 +558,12 @@ emit_adobe_app14 (j_compress_ptr cinfo)
/* Emit an Adobe APP14 marker */ /* Emit an Adobe APP14 marker */
{ {
/* /*
* Length of APP14 block (2 bytes) * Length of APP14 block (2 bytes)
* Block ID (5 bytes - ASCII "Adobe") * Block ID (5 bytes - ASCII "Adobe")
* Version Number (2 bytes - currently 100) * Version Number (2 bytes - currently 100)
* Flags0 (2 bytes - currently 0) * Flags0 (2 bytes - currently 0)
* Flags1 (2 bytes - currently 0) * Flags1 (2 bytes - currently 0)
* Color transform (1 byte) * Color transform (1 byte)
* *
* Although Adobe TN 5116 mentions Version = 101, all the Adobe files * Although Adobe TN 5116 mentions Version = 101, all the Adobe files
* now in circulation seem to use Version = 100, so that's what we write. * now in circulation seem to use Version = 100, so that's what we write.
@@ -408,23 +577,23 @@ emit_adobe_app14 (j_compress_ptr cinfo)
emit_2bytes(cinfo, 2 + 5 + 2 + 2 + 2 + 1); /* length */ emit_2bytes(cinfo, 2 + 5 + 2 + 2 + 2 + 1); /* length */
emit_byte(cinfo, 0x41); /* Identifier: ASCII "Adobe" */ emit_byte(cinfo, 0x41); /* Identifier: ASCII "Adobe" */
emit_byte(cinfo, 0x64); emit_byte(cinfo, 0x64);
emit_byte(cinfo, 0x6F); emit_byte(cinfo, 0x6F);
emit_byte(cinfo, 0x62); emit_byte(cinfo, 0x62);
emit_byte(cinfo, 0x65); emit_byte(cinfo, 0x65);
emit_2bytes(cinfo, 100); /* Version */ emit_2bytes(cinfo, 100); /* Version */
emit_2bytes(cinfo, 0); /* Flags0 */ emit_2bytes(cinfo, 0); /* Flags0 */
emit_2bytes(cinfo, 0); /* Flags1 */ emit_2bytes(cinfo, 0); /* Flags1 */
switch (cinfo->jpeg_color_space) { switch (cinfo->jpeg_color_space) {
case JCS_YCbCr: case JCS_YCbCr:
emit_byte(cinfo, 1); /* Color transform = 1 */ emit_byte(cinfo, 1); /* Color transform = 1 */
break; break;
case JCS_YCCK: case JCS_YCCK:
emit_byte(cinfo, 2); /* Color transform = 2 */ emit_byte(cinfo, 2); /* Color transform = 2 */
break; break;
default: default:
emit_byte(cinfo, 0); /* Color transform = 0 */ emit_byte(cinfo, 0); /* Color transform = 0 */
break; break;
} }
} }
@@ -442,12 +611,12 @@ METHODDEF(void)
write_marker_header (j_compress_ptr cinfo, int marker, unsigned int datalen) write_marker_header (j_compress_ptr cinfo, int marker, unsigned int datalen)
/* Emit an arbitrary marker header */ /* Emit an arbitrary marker header */
{ {
if (datalen > (unsigned int) 65533) /* safety check */ if (datalen > (unsigned int) 65533) /* safety check */
ERREXIT(cinfo, JERR_BAD_LENGTH); ERREXIT(cinfo, JERR_BAD_LENGTH);
emit_marker(cinfo, (JPEG_MARKER) marker); emit_marker(cinfo, (JPEG_MARKER) marker);
emit_2bytes(cinfo, (int) (datalen + 2)); /* total length */ emit_2bytes(cinfo, (int) (datalen + 2)); /* total length */
} }
METHODDEF(void) METHODDEF(void)
@@ -474,12 +643,12 @@ write_file_header (j_compress_ptr cinfo)
{ {
my_marker_ptr marker = (my_marker_ptr) cinfo->marker; my_marker_ptr marker = (my_marker_ptr) cinfo->marker;
emit_marker(cinfo, M_SOI); /* first the SOI */ emit_marker(cinfo, M_SOI); /* first the SOI */
/* SOI is defined to reset restart interval to 0 */ /* SOI is defined to reset restart interval to 0 */
marker->last_restart_interval = 0; marker->last_restart_interval = 0;
if (cinfo->write_JFIF_header) /* next an optional JFIF APP0 */ if (cinfo->write_JFIF_header) /* next an optional JFIF APP0 */
emit_jfif_app0(cinfo); emit_jfif_app0(cinfo);
if (cinfo->write_Adobe_marker) /* next an optional Adobe APP14 */ if (cinfo->write_Adobe_marker) /* next an optional Adobe APP14 */
emit_adobe_app14(cinfo); emit_adobe_app14(cinfo);
@@ -504,10 +673,13 @@ write_frame_header (j_compress_ptr cinfo)
/* Emit DQT for each quantization table. /* Emit DQT for each quantization table.
* Note that emit_dqt() suppresses any duplicate tables. * Note that emit_dqt() suppresses any duplicate tables.
*/ */
prec = 0; prec = emit_multi_dqt(cinfo);
for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; if (prec == -1) {
ci++, compptr++) { prec = 0;
prec += emit_dqt(cinfo, compptr->quant_tbl_no); for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
ci++, compptr++) {
prec += emit_dqt(cinfo, compptr->quant_tbl_no);
}
} }
/* now prec is nonzero iff there are any 16-bit quant tables. */ /* now prec is nonzero iff there are any 16-bit quant tables. */
@@ -520,9 +692,9 @@ write_frame_header (j_compress_ptr cinfo)
} else { } else {
is_baseline = TRUE; is_baseline = TRUE;
for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
ci++, compptr++) { ci++, compptr++) {
if (compptr->dc_tbl_no > 1 || compptr->ac_tbl_no > 1) if (compptr->dc_tbl_no > 1 || compptr->ac_tbl_no > 1)
is_baseline = FALSE; is_baseline = FALSE;
} }
if (prec && is_baseline) { if (prec && is_baseline) {
is_baseline = FALSE; is_baseline = FALSE;
@@ -539,11 +711,11 @@ write_frame_header (j_compress_ptr cinfo)
emit_sof(cinfo, M_SOF9); /* SOF code for sequential arithmetic */ emit_sof(cinfo, M_SOF9); /* SOF code for sequential arithmetic */
} else { } else {
if (cinfo->progressive_mode) if (cinfo->progressive_mode)
emit_sof(cinfo, M_SOF2); /* SOF code for progressive Huffman */ emit_sof(cinfo, M_SOF2); /* SOF code for progressive Huffman */
else if (is_baseline) else if (is_baseline)
emit_sof(cinfo, M_SOF0); /* SOF code for baseline implementation */ emit_sof(cinfo, M_SOF0); /* SOF code for baseline implementation */
else else
emit_sof(cinfo, M_SOF1); /* SOF code for non-baseline Huffman file */ emit_sof(cinfo, M_SOF1); /* SOF code for non-baseline Huffman file */
} }
} }
@@ -571,14 +743,16 @@ write_scan_header (j_compress_ptr cinfo)
/* Emit Huffman tables. /* Emit Huffman tables.
* Note that emit_dht() suppresses any duplicate tables. * Note that emit_dht() suppresses any duplicate tables.
*/ */
for (i = 0; i < cinfo->comps_in_scan; i++) { if (!emit_multi_dht(cinfo)) {
compptr = cinfo->cur_comp_info[i]; for (i = 0; i < cinfo->comps_in_scan; i++) {
/* DC needs no table for refinement scan */ compptr = cinfo->cur_comp_info[i];
if (cinfo->Ss == 0 && cinfo->Ah == 0) /* DC needs no table for refinement scan */
emit_dht(cinfo, compptr->dc_tbl_no, FALSE); if (cinfo->Ss == 0 && cinfo->Ah == 0)
/* AC needs no table when not present */ emit_dht(cinfo, compptr->dc_tbl_no, FALSE);
if (cinfo->Se) /* AC needs no table when not present */
emit_dht(cinfo, compptr->ac_tbl_no, TRUE); if (cinfo->Se)
emit_dht(cinfo, compptr->ac_tbl_no, TRUE);
}
} }
} }
@@ -627,9 +801,9 @@ write_tables_only (j_compress_ptr cinfo)
if (! cinfo->arith_code) { if (! cinfo->arith_code) {
for (i = 0; i < NUM_HUFF_TBLS; i++) { for (i = 0; i < NUM_HUFF_TBLS; i++) {
if (cinfo->dc_huff_tbl_ptrs[i] != NULL) if (cinfo->dc_huff_tbl_ptrs[i] != NULL)
emit_dht(cinfo, i, FALSE); emit_dht(cinfo, i, FALSE);
if (cinfo->ac_huff_tbl_ptrs[i] != NULL) if (cinfo->ac_huff_tbl_ptrs[i] != NULL)
emit_dht(cinfo, i, TRUE); emit_dht(cinfo, i, TRUE);
} }
} }

View File

@@ -25,26 +25,27 @@
/* Private state */ /* Private state */
typedef enum { typedef enum {
main_pass, /* input data, also do first output step */ main_pass, /* input data, also do first output step */
huff_opt_pass, /* Huffman code optimization pass */ huff_opt_pass, /* Huffman code optimization pass */
output_pass, /* data output pass */ output_pass, /* data output pass */
trellis_pass /* trellis quantization pass */ trellis_pass /* trellis quantization pass */
} c_pass_type; } c_pass_type;
typedef struct { typedef struct {
struct jpeg_comp_master pub; /* public fields */ struct jpeg_comp_master pub; /* public fields */
c_pass_type pass_type; /* the type of the current pass */ c_pass_type pass_type; /* the type of the current pass */
int pass_number; /* # of passes completed */ int pass_number; /* # of passes completed */
int total_passes; /* total # of passes needed */ int total_passes; /* total # of passes needed */
int scan_number; /* current index in scan_info[] */ int scan_number; /* current index in scan_info[] */
/* fields for scan optimisation */ /* fields for scan optimisation */
int pass_number_scan_opt_base; /* pass number where scan optimization begins */ int pass_number_scan_opt_base; /* pass number where scan optimization begins */
unsigned char * scan_buffer[64]; /* buffer for a given scan */ unsigned char * scan_buffer[64]; /* buffer for a given scan */
unsigned long scan_size[64]; /* size for a given scan */ unsigned long scan_size[64]; /* size for a given scan */
int actual_Al[64]; /* actual value of Al used for a scan */
unsigned long best_cost; /* bit count for best frequency split */ unsigned long best_cost; /* bit count for best frequency split */
int best_freq_split_idx_luma; /* index for best frequency split (luma) */ int best_freq_split_idx_luma; /* index for best frequency split (luma) */
int best_freq_split_idx_chroma; /* index for best frequency split (chroma) */ int best_freq_split_idx_chroma; /* index for best frequency split (chroma) */
@@ -120,7 +121,7 @@ initial_setup (j_compress_ptr cinfo, boolean transcode_only)
/* Check that number of components won't exceed internal array sizes */ /* Check that number of components won't exceed internal array sizes */
if (cinfo->num_components > MAX_COMPONENTS) if (cinfo->num_components > MAX_COMPONENTS)
ERREXIT2(cinfo, JERR_COMPONENT_COUNT, cinfo->num_components, ERREXIT2(cinfo, JERR_COMPONENT_COUNT, cinfo->num_components,
MAX_COMPONENTS); MAX_COMPONENTS);
/* Compute maximum sampling factors; check factor validity */ /* Compute maximum sampling factors; check factor validity */
cinfo->max_h_samp_factor = 1; cinfo->max_h_samp_factor = 1;
@@ -128,12 +129,12 @@ initial_setup (j_compress_ptr cinfo, boolean transcode_only)
for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
ci++, compptr++) { ci++, compptr++) {
if (compptr->h_samp_factor<=0 || compptr->h_samp_factor>MAX_SAMP_FACTOR || if (compptr->h_samp_factor<=0 || compptr->h_samp_factor>MAX_SAMP_FACTOR ||
compptr->v_samp_factor<=0 || compptr->v_samp_factor>MAX_SAMP_FACTOR) compptr->v_samp_factor<=0 || compptr->v_samp_factor>MAX_SAMP_FACTOR)
ERREXIT(cinfo, JERR_BAD_SAMPLING); ERREXIT(cinfo, JERR_BAD_SAMPLING);
cinfo->max_h_samp_factor = MAX(cinfo->max_h_samp_factor, cinfo->max_h_samp_factor = MAX(cinfo->max_h_samp_factor,
compptr->h_samp_factor); compptr->h_samp_factor);
cinfo->max_v_samp_factor = MAX(cinfo->max_v_samp_factor, cinfo->max_v_samp_factor = MAX(cinfo->max_v_samp_factor,
compptr->v_samp_factor); compptr->v_samp_factor);
} }
/* Compute dimensions of components */ /* Compute dimensions of components */
@@ -150,17 +151,17 @@ initial_setup (j_compress_ptr cinfo, boolean transcode_only)
/* Size in DCT blocks */ /* Size in DCT blocks */
compptr->width_in_blocks = (JDIMENSION) compptr->width_in_blocks = (JDIMENSION)
jdiv_round_up((long) cinfo->_jpeg_width * (long) compptr->h_samp_factor, jdiv_round_up((long) cinfo->_jpeg_width * (long) compptr->h_samp_factor,
(long) (cinfo->max_h_samp_factor * DCTSIZE)); (long) (cinfo->max_h_samp_factor * DCTSIZE));
compptr->height_in_blocks = (JDIMENSION) compptr->height_in_blocks = (JDIMENSION)
jdiv_round_up((long) cinfo->_jpeg_height * (long) compptr->v_samp_factor, jdiv_round_up((long) cinfo->_jpeg_height * (long) compptr->v_samp_factor,
(long) (cinfo->max_v_samp_factor * DCTSIZE)); (long) (cinfo->max_v_samp_factor * DCTSIZE));
/* Size in samples */ /* Size in samples */
compptr->downsampled_width = (JDIMENSION) compptr->downsampled_width = (JDIMENSION)
jdiv_round_up((long) cinfo->_jpeg_width * (long) compptr->h_samp_factor, jdiv_round_up((long) cinfo->_jpeg_width * (long) compptr->h_samp_factor,
(long) cinfo->max_h_samp_factor); (long) cinfo->max_h_samp_factor);
compptr->downsampled_height = (JDIMENSION) compptr->downsampled_height = (JDIMENSION)
jdiv_round_up((long) cinfo->_jpeg_height * (long) compptr->v_samp_factor, jdiv_round_up((long) cinfo->_jpeg_height * (long) compptr->v_samp_factor,
(long) cinfo->max_v_samp_factor); (long) cinfo->max_v_samp_factor);
/* Mark component needed (this flag isn't actually used for compression) */ /* Mark component needed (this flag isn't actually used for compression) */
compptr->component_needed = TRUE; compptr->component_needed = TRUE;
} }
@@ -170,7 +171,7 @@ initial_setup (j_compress_ptr cinfo, boolean transcode_only)
*/ */
cinfo->total_iMCU_rows = (JDIMENSION) cinfo->total_iMCU_rows = (JDIMENSION)
jdiv_round_up((long) cinfo->_jpeg_height, jdiv_round_up((long) cinfo->_jpeg_height,
(long) (cinfo->max_v_samp_factor*DCTSIZE)); (long) (cinfo->max_v_samp_factor*DCTSIZE));
} }
@@ -213,7 +214,7 @@ validate_script (j_compress_ptr cinfo)
last_bitpos_ptr = & last_bitpos[0][0]; last_bitpos_ptr = & last_bitpos[0][0];
for (ci = 0; ci < cinfo->num_components; ci++) for (ci = 0; ci < cinfo->num_components; ci++)
for (coefi = 0; coefi < DCTSIZE2; coefi++) for (coefi = 0; coefi < DCTSIZE2; coefi++)
*last_bitpos_ptr++ = -1; *last_bitpos_ptr++ = -1;
#else #else
ERREXIT(cinfo, JERR_NOT_COMPILED); ERREXIT(cinfo, JERR_NOT_COMPILED);
#endif #endif
@@ -231,10 +232,10 @@ validate_script (j_compress_ptr cinfo)
for (ci = 0; ci < ncomps; ci++) { for (ci = 0; ci < ncomps; ci++) {
thisi = scanptr->component_index[ci]; thisi = scanptr->component_index[ci];
if (thisi < 0 || thisi >= cinfo->num_components) if (thisi < 0 || thisi >= cinfo->num_components)
ERREXIT1(cinfo, JERR_BAD_SCAN_SCRIPT, scanno); ERREXIT1(cinfo, JERR_BAD_SCAN_SCRIPT, scanno);
/* Components must appear in SOF order within each scan */ /* Components must appear in SOF order within each scan */
if (ci > 0 && thisi <= scanptr->component_index[ci-1]) if (ci > 0 && thisi <= scanptr->component_index[ci-1])
ERREXIT1(cinfo, JERR_BAD_SCAN_SCRIPT, scanno); ERREXIT1(cinfo, JERR_BAD_SCAN_SCRIPT, scanno);
} }
/* Validate progression parameters */ /* Validate progression parameters */
Ss = scanptr->Ss; Ss = scanptr->Ss;
@@ -256,43 +257,43 @@ validate_script (j_compress_ptr cinfo)
#define MAX_AH_AL 13 #define MAX_AH_AL 13
#endif #endif
if (Ss < 0 || Ss >= DCTSIZE2 || Se < Ss || Se >= DCTSIZE2 || if (Ss < 0 || Ss >= DCTSIZE2 || Se < Ss || Se >= DCTSIZE2 ||
Ah < 0 || Ah > MAX_AH_AL || Al < 0 || Al > MAX_AH_AL) Ah < 0 || Ah > MAX_AH_AL || Al < 0 || Al > MAX_AH_AL)
ERREXIT1(cinfo, JERR_BAD_PROG_SCRIPT, scanno); ERREXIT1(cinfo, JERR_BAD_PROG_SCRIPT, scanno);
if (Ss == 0) { if (Ss == 0) {
if (Se != 0) /* DC and AC together not OK */ if (Se != 0) /* DC and AC together not OK */
ERREXIT1(cinfo, JERR_BAD_PROG_SCRIPT, scanno); ERREXIT1(cinfo, JERR_BAD_PROG_SCRIPT, scanno);
} else { } else {
if (ncomps != 1) /* AC scans must be for only one component */ if (ncomps != 1) /* AC scans must be for only one component */
ERREXIT1(cinfo, JERR_BAD_PROG_SCRIPT, scanno); ERREXIT1(cinfo, JERR_BAD_PROG_SCRIPT, scanno);
} }
for (ci = 0; ci < ncomps; ci++) { for (ci = 0; ci < ncomps; ci++) {
last_bitpos_ptr = & last_bitpos[scanptr->component_index[ci]][0]; last_bitpos_ptr = & last_bitpos[scanptr->component_index[ci]][0];
if (Ss != 0 && last_bitpos_ptr[0] < 0) /* AC without prior DC scan */ if (Ss != 0 && last_bitpos_ptr[0] < 0) /* AC without prior DC scan */
ERREXIT1(cinfo, JERR_BAD_PROG_SCRIPT, scanno); ERREXIT1(cinfo, JERR_BAD_PROG_SCRIPT, scanno);
for (coefi = Ss; coefi <= Se; coefi++) { for (coefi = Ss; coefi <= Se; coefi++) {
if (last_bitpos_ptr[coefi] < 0) { if (last_bitpos_ptr[coefi] < 0) {
/* first scan of this coefficient */ /* first scan of this coefficient */
if (Ah != 0) if (Ah != 0)
ERREXIT1(cinfo, JERR_BAD_PROG_SCRIPT, scanno); ERREXIT1(cinfo, JERR_BAD_PROG_SCRIPT, scanno);
} else { } else {
/* not first scan */ /* not first scan */
if (Ah != last_bitpos_ptr[coefi] || Al != Ah-1) if (Ah != last_bitpos_ptr[coefi] || Al != Ah-1)
ERREXIT1(cinfo, JERR_BAD_PROG_SCRIPT, scanno); ERREXIT1(cinfo, JERR_BAD_PROG_SCRIPT, scanno);
} }
last_bitpos_ptr[coefi] = Al; last_bitpos_ptr[coefi] = Al;
} }
} }
#endif #endif
} else { } else {
/* For sequential JPEG, all progression parameters must be these: */ /* For sequential JPEG, all progression parameters must be these: */
if (Ss != 0 || Se != DCTSIZE2-1 || Ah != 0 || Al != 0) if (Ss != 0 || Se != DCTSIZE2-1 || Ah != 0 || Al != 0)
ERREXIT1(cinfo, JERR_BAD_PROG_SCRIPT, scanno); ERREXIT1(cinfo, JERR_BAD_PROG_SCRIPT, scanno);
/* Make sure components are not sent twice */ /* Make sure components are not sent twice */
for (ci = 0; ci < ncomps; ci++) { for (ci = 0; ci < ncomps; ci++) {
thisi = scanptr->component_index[ci]; thisi = scanptr->component_index[ci];
if (component_sent[thisi]) if (component_sent[thisi])
ERREXIT1(cinfo, JERR_BAD_SCAN_SCRIPT, scanno); ERREXIT1(cinfo, JERR_BAD_SCAN_SCRIPT, scanno);
component_sent[thisi] = TRUE; component_sent[thisi] = TRUE;
} }
} }
} }
@@ -307,13 +308,13 @@ validate_script (j_compress_ptr cinfo)
*/ */
for (ci = 0; ci < cinfo->num_components; ci++) { for (ci = 0; ci < cinfo->num_components; ci++) {
if (last_bitpos[ci][0] < 0) if (last_bitpos[ci][0] < 0)
ERREXIT(cinfo, JERR_MISSING_DATA); ERREXIT(cinfo, JERR_MISSING_DATA);
} }
#endif #endif
} else { } else {
for (ci = 0; ci < cinfo->num_components; ci++) { for (ci = 0; ci < cinfo->num_components; ci++) {
if (! component_sent[ci]) if (! component_sent[ci])
ERREXIT(cinfo, JERR_MISSING_DATA); ERREXIT(cinfo, JERR_MISSING_DATA);
} }
} }
} }
@@ -348,7 +349,7 @@ select_scan_parameters (j_compress_ptr cinfo)
cinfo->comps_in_scan = scanptr->comps_in_scan; cinfo->comps_in_scan = scanptr->comps_in_scan;
for (ci = 0; ci < scanptr->comps_in_scan; ci++) { for (ci = 0; ci < scanptr->comps_in_scan; ci++) {
cinfo->cur_comp_info[ci] = cinfo->cur_comp_info[ci] =
&cinfo->comp_info[scanptr->component_index[ci]]; &cinfo->comp_info[scanptr->component_index[ci]];
} }
cinfo->Ss = scanptr->Ss; cinfo->Ss = scanptr->Ss;
cinfo->Se = scanptr->Se; cinfo->Se = scanptr->Se;
@@ -363,7 +364,9 @@ select_scan_parameters (j_compress_ptr cinfo)
if (master->scan_number >= cinfo->num_scans_luma+cinfo->num_scans_chroma_dc+(6*cinfo->Al_max_chroma+4) && if (master->scan_number >= cinfo->num_scans_luma+cinfo->num_scans_chroma_dc+(6*cinfo->Al_max_chroma+4) &&
master->scan_number < cinfo->num_scans) master->scan_number < cinfo->num_scans)
cinfo->Al = master->best_Al_chroma; cinfo->Al = master->best_Al_chroma;
} }
/* save value for later retrieval during printout of scans */
master->actual_Al[master->scan_number] = cinfo->Al;
} }
else else
#endif #endif
@@ -371,7 +374,7 @@ select_scan_parameters (j_compress_ptr cinfo)
/* Prepare for single sequential-JPEG scan containing all components */ /* Prepare for single sequential-JPEG scan containing all components */
if (cinfo->num_components > MAX_COMPS_IN_SCAN) if (cinfo->num_components > MAX_COMPS_IN_SCAN)
ERREXIT2(cinfo, JERR_COMPONENT_COUNT, cinfo->num_components, ERREXIT2(cinfo, JERR_COMPONENT_COUNT, cinfo->num_components,
MAX_COMPS_IN_SCAN); MAX_COMPS_IN_SCAN);
cinfo->comps_in_scan = cinfo->num_components; cinfo->comps_in_scan = cinfo->num_components;
for (ci = 0; ci < cinfo->num_components; ci++) { for (ci = 0; ci < cinfo->num_components; ci++) {
cinfo->cur_comp_info[ci] = &cinfo->comp_info[ci]; cinfo->cur_comp_info[ci] = &cinfo->comp_info[ci];
@@ -423,15 +426,15 @@ per_scan_setup (j_compress_ptr cinfo)
/* Interleaved (multi-component) scan */ /* Interleaved (multi-component) scan */
if (cinfo->comps_in_scan <= 0 || cinfo->comps_in_scan > MAX_COMPS_IN_SCAN) if (cinfo->comps_in_scan <= 0 || cinfo->comps_in_scan > MAX_COMPS_IN_SCAN)
ERREXIT2(cinfo, JERR_COMPONENT_COUNT, cinfo->comps_in_scan, ERREXIT2(cinfo, JERR_COMPONENT_COUNT, cinfo->comps_in_scan,
MAX_COMPS_IN_SCAN); MAX_COMPS_IN_SCAN);
/* Overall image size in MCUs */ /* Overall image size in MCUs */
cinfo->MCUs_per_row = (JDIMENSION) cinfo->MCUs_per_row = (JDIMENSION)
jdiv_round_up((long) cinfo->_jpeg_width, jdiv_round_up((long) cinfo->_jpeg_width,
(long) (cinfo->max_h_samp_factor*DCTSIZE)); (long) (cinfo->max_h_samp_factor*DCTSIZE));
cinfo->MCU_rows_in_scan = (JDIMENSION) cinfo->MCU_rows_in_scan = (JDIMENSION)
jdiv_round_up((long) cinfo->_jpeg_height, jdiv_round_up((long) cinfo->_jpeg_height,
(long) (cinfo->max_v_samp_factor*DCTSIZE)); (long) (cinfo->max_v_samp_factor*DCTSIZE));
cinfo->blocks_in_MCU = 0; cinfo->blocks_in_MCU = 0;
@@ -452,9 +455,9 @@ per_scan_setup (j_compress_ptr cinfo)
/* Prepare array describing MCU composition */ /* Prepare array describing MCU composition */
mcublks = compptr->MCU_blocks; mcublks = compptr->MCU_blocks;
if (cinfo->blocks_in_MCU + mcublks > C_MAX_BLOCKS_IN_MCU) if (cinfo->blocks_in_MCU + mcublks > C_MAX_BLOCKS_IN_MCU)
ERREXIT(cinfo, JERR_BAD_MCU_SIZE); ERREXIT(cinfo, JERR_BAD_MCU_SIZE);
while (mcublks-- > 0) { while (mcublks-- > 0) {
cinfo->MCU_membership[cinfo->blocks_in_MCU++] = ci; cinfo->MCU_membership[cinfo->blocks_in_MCU++] = ci;
} }
} }
@@ -498,8 +501,8 @@ prepare_for_pass (j_compress_ptr cinfo)
(*cinfo->fdct->start_pass) (cinfo); (*cinfo->fdct->start_pass) (cinfo);
(*cinfo->entropy->start_pass) (cinfo, cinfo->optimize_coding); (*cinfo->entropy->start_pass) (cinfo, cinfo->optimize_coding);
(*cinfo->coef->start_pass) (cinfo, (*cinfo->coef->start_pass) (cinfo,
(master->total_passes > 1 ? (master->total_passes > 1 ?
JBUF_SAVE_AND_PASS : JBUF_PASS_THRU)); JBUF_SAVE_AND_PASS : JBUF_PASS_THRU));
(*cinfo->main->start_pass) (cinfo, JBUF_PASS_THRU); (*cinfo->main->start_pass) (cinfo, JBUF_PASS_THRU);
if (cinfo->optimize_coding) { if (cinfo->optimize_coding) {
/* No immediate data output; postpone writing frame/scan headers */ /* No immediate data output; postpone writing frame/scan headers */
@@ -613,7 +616,7 @@ copy_buffer (j_compress_ptr cinfo, int scan_idx)
for (i = 0; i < cinfo->scan_info[scan_idx].comps_in_scan; i++) for (i = 0; i < cinfo->scan_info[scan_idx].comps_in_scan; i++)
fprintf(stderr, "%s%d", (i==0)?"":",", cinfo->scan_info[scan_idx].component_index[i]); fprintf(stderr, "%s%d", (i==0)?"":",", cinfo->scan_info[scan_idx].component_index[i]);
fprintf(stderr, ": %d %d", cinfo->scan_info[scan_idx].Ss, cinfo->scan_info[scan_idx].Se); fprintf(stderr, ": %d %d", cinfo->scan_info[scan_idx].Ss, cinfo->scan_info[scan_idx].Se);
fprintf(stderr, " %d %d", cinfo->scan_info[scan_idx].Ah, cinfo->scan_info[scan_idx].Al); fprintf(stderr, " %d %d", cinfo->scan_info[scan_idx].Ah, master->actual_Al[scan_idx]);
fprintf(stderr, "\n"); fprintf(stderr, "\n");
} }
@@ -757,7 +760,7 @@ select_scans (j_compress_ptr cinfo, int next_scan_number)
if (cinfo->num_scans > cinfo->num_scans_luma && !cinfo->one_dc_scan) { if (cinfo->num_scans > cinfo->num_scans_luma && !cinfo->one_dc_scan) {
base_scan_idx = cinfo->num_scans_luma; base_scan_idx = cinfo->num_scans_luma;
if (master->interleave_chroma_dc) if (master->interleave_chroma_dc && !cinfo->sep_dc_scan)
copy_buffer(cinfo, base_scan_idx); copy_buffer(cinfo, base_scan_idx);
else { else {
copy_buffer(cinfo, base_scan_idx+1); copy_buffer(cinfo, base_scan_idx+1);
@@ -835,9 +838,9 @@ finish_pass_master (j_compress_ptr cinfo)
if (cinfo->trellis_quant) if (cinfo->trellis_quant)
master->pass_type = trellis_pass; master->pass_type = trellis_pass;
else { else {
master->pass_type = output_pass; master->pass_type = output_pass;
if (! cinfo->optimize_coding) if (! cinfo->optimize_coding)
master->scan_number++; master->scan_number++;
} }
break; break;
case huff_opt_pass: case huff_opt_pass:
@@ -869,7 +872,7 @@ finish_pass_master (j_compress_ptr cinfo)
if (q > 254) q = 254; if (q > 254) q = 254;
if (q < 1) q = 1; if (q < 1) q = 1;
cinfo->quant_tbl_ptrs[i]->quantval[j] = q; cinfo->quant_tbl_ptrs[i]->quantval[j] = q;
} }
} }
} }
} }
@@ -912,7 +915,7 @@ jinit_c_master_control (j_compress_ptr cinfo, boolean transcode_only)
cinfo->num_scans = 1; cinfo->num_scans = 1;
} }
if (cinfo->progressive_mode && !cinfo->arith_code) /* TEMPORARY HACK ??? */ if (cinfo->progressive_mode && !cinfo->arith_code) /* TEMPORARY HACK ??? */
cinfo->optimize_coding = TRUE; /* assume default tables no good for progressive mode */ cinfo->optimize_coding = TRUE; /* assume default tables no good for progressive mode */
/* Initialize my private state */ /* Initialize my private state */
@@ -933,8 +936,11 @@ jinit_c_master_control (j_compress_ptr cinfo, boolean transcode_only)
else else
master->total_passes = cinfo->num_scans; master->total_passes = cinfo->num_scans;
if (cinfo->trellis_quant) master->pass_number_scan_opt_base = 0;
master->total_passes += ((cinfo->use_scans_in_trellis) ? 4 : 2) * cinfo->num_components * cinfo->trellis_num_loops; if (cinfo->trellis_quant) {
master->pass_number_scan_opt_base = ((cinfo->use_scans_in_trellis) ? 4 : 2) * cinfo->num_components * cinfo->trellis_num_loops;
master->total_passes += master->pass_number_scan_opt_base;
}
if (cinfo->optimize_scans) { if (cinfo->optimize_scans) {
int i; int i;
@@ -942,10 +948,5 @@ jinit_c_master_control (j_compress_ptr cinfo, boolean transcode_only)
for (i = 0; i < cinfo->num_scans; i++) for (i = 0; i < cinfo->num_scans; i++)
master->scan_buffer[i] = NULL; master->scan_buffer[i] = NULL;
} }
if (cinfo->trellis_quant)
master->pass_number_scan_opt_base = ((cinfo->use_scans_in_trellis) ? 4 : 2) * cinfo->num_components * cinfo->trellis_num_loops;
else
master->pass_number_scan_opt_base = 0;
} }

View File

@@ -78,10 +78,10 @@
/* Define "boolean" as unsigned char, not int, on Windows systems. /* Define "boolean" as unsigned char, not int, on Windows systems.
*/ */
#ifdef _WIN32 #ifdef _WIN32
#ifndef __RPCNDR_H__ /* don't conflict if rpcndr.h already read */ #ifndef __RPCNDR_H__ /* don't conflict if rpcndr.h already read */
typedef unsigned char boolean; typedef unsigned char boolean;
#endif #endif
#define HAVE_BOOLEAN /* prevent jmorecfg.h from redefining it */ #define HAVE_BOOLEAN /* prevent jmorecfg.h from redefining it */
#endif #endif
@@ -114,11 +114,12 @@ typedef unsigned char boolean;
/* These defines indicate which image (non-JPEG) file formats are allowed. */ /* These defines indicate which image (non-JPEG) file formats are allowed. */
#define BMP_SUPPORTED /* BMP image file format */ #define PNG_SUPPORTED /* PNG image file format */
#define GIF_SUPPORTED /* GIF image file format */ #define BMP_SUPPORTED /* BMP image file format */
#define PPM_SUPPORTED /* PBMPLUS PPM/PGM image file format */ #define GIF_SUPPORTED /* GIF image file format */
#undef RLE_SUPPORTED /* Utah RLE image file format */ #define PPM_SUPPORTED /* PBMPLUS PPM/PGM image file format */
#define TARGA_SUPPORTED /* Targa image file format */ #undef RLE_SUPPORTED /* Utah RLE image file format */
#define TARGA_SUPPORTED /* Targa image file format */
/* Define this if you want to name both input and output files on the command /* Define this if you want to name both input and output files on the command
* line, rather than using stdout and optionally stdin. You MUST do this if * line, rather than using stdout and optionally stdin. You MUST do this if

View File

@@ -152,14 +152,20 @@ jpeg_set_linear_quality (j_compress_ptr cinfo, int scale_factor,
GLOBAL(int) GLOBAL(int)
jpeg_quality_scaling (int quality) jpeg_quality_scaling (int quality)
{
return jpeg_float_quality_scaling(quality);
}
GLOBAL(float)
jpeg_float_quality_scaling(float quality)
/* Convert a user-specified quality rating to a percentage scaling factor /* Convert a user-specified quality rating to a percentage scaling factor
* for an underlying quantization table, using our recommended scaling curve. * for an underlying quantization table, using our recommended scaling curve.
* The input 'quality' factor should be 0 (terrible) to 100 (very good). * The input 'quality' factor should be 0 (terrible) to 100 (very good).
*/ */
{ {
/* Safety limit on quality factor. Convert 0 to 1 to avoid zero divide. */ /* Safety limit on quality factor. Convert 0 to 1 to avoid zero divide. */
if (quality <= 0) quality = 1; if (quality <= 0.f) quality = 1.f;
if (quality > 100) quality = 100; if (quality > 100.f) quality = 100.f;
/* The basic table is used as-is (scaling 100) for a quality of 50. /* The basic table is used as-is (scaling 100) for a quality of 50.
* Qualities 50..100 are converted to scaling percentage 200 - 2*Q; * Qualities 50..100 are converted to scaling percentage 200 - 2*Q;
@@ -167,10 +173,10 @@ jpeg_quality_scaling (int quality)
* to make all the table entries 1 (hence, minimum quantization loss). * to make all the table entries 1 (hence, minimum quantization loss).
* Qualities 1..50 are converted to scaling percentage 5000/Q. * Qualities 1..50 are converted to scaling percentage 5000/Q.
*/ */
if (quality < 50) if (quality < 50.f)
quality = 5000 / quality; quality = 5000.f / quality;
else else
quality = 200 - quality*2; quality = 200.f - quality*2.f;
return quality; return quality;
} }
@@ -335,6 +341,7 @@ jpeg_set_defaults (j_compress_ptr cinfo)
cinfo->trellis_freq_split = 8; cinfo->trellis_freq_split = 8;
cinfo->trellis_num_loops = 1; cinfo->trellis_num_loops = 1;
cinfo->trellis_q_opt = FALSE; cinfo->trellis_q_opt = FALSE;
cinfo->trellis_quant_dc = TRUE;
} }
@@ -730,6 +737,11 @@ jpeg_simple_progression (j_compress_ptr cinfo)
/* Initial DC scan */ /* Initial DC scan */
if (cinfo->one_dc_scan) if (cinfo->one_dc_scan)
scanptr = fill_dc_scans(scanptr, ncomps, 0, 0); scanptr = fill_dc_scans(scanptr, ncomps, 0, 0);
else if (cinfo->sep_dc_scan) {
scanptr = fill_a_scan(scanptr, 0, 0, 0, 0, 0);
scanptr = fill_a_scan(scanptr, 1, 0, 0, 0, 0);
scanptr = fill_a_scan(scanptr, 2, 0, 0, 0, 0);
}
else { else {
scanptr = fill_dc_scans(scanptr, 1, 0, 0); scanptr = fill_dc_scans(scanptr, 1, 0, 0);
scanptr = fill_a_scan_pair(scanptr, 1, 0, 0, 0, 0); scanptr = fill_a_scan_pair(scanptr, 1, 0, 0, 0, 0);

413
jpeglib.h
View File

@@ -25,10 +25,10 @@
* manual configuration options that most people need not worry about. * manual configuration options that most people need not worry about.
*/ */
#ifndef JCONFIG_INCLUDED /* in case jinclude.h already did */ #ifndef JCONFIG_INCLUDED /* in case jinclude.h already did */
#include "jconfig.h" /* widely used configuration options */ #include "jconfig.h" /* widely used configuration options */
#endif #endif
#include "jmorecfg.h" /* seldom changed options */ #include "jmorecfg.h" /* seldom changed options */
#ifdef __cplusplus #ifdef __cplusplus
@@ -43,13 +43,13 @@ extern "C" {
* if you want to be compatible. * if you want to be compatible.
*/ */
#define DCTSIZE 8 /* The basic DCT block is 8x8 samples */ #define DCTSIZE 8 /* The basic DCT block is 8x8 samples */
#define DCTSIZE2 64 /* DCTSIZE squared; # of elements in a block */ #define DCTSIZE2 64 /* DCTSIZE squared; # of elements in a block */
#define NUM_QUANT_TBLS 4 /* Quantization tables are numbered 0..3 */ #define NUM_QUANT_TBLS 4 /* Quantization tables are numbered 0..3 */
#define NUM_HUFF_TBLS 4 /* Huffman tables are numbered 0..3 */ #define NUM_HUFF_TBLS 4 /* Huffman tables are numbered 0..3 */
#define NUM_ARITH_TBLS 16 /* Arith-coding tables are numbered 0..15 */ #define NUM_ARITH_TBLS 16 /* Arith-coding tables are numbered 0..15 */
#define MAX_COMPS_IN_SCAN 4 /* JPEG limit on # of components in one scan */ #define MAX_COMPS_IN_SCAN 4 /* JPEG limit on # of components in one scan */
#define MAX_SAMP_FACTOR 4 /* JPEG limit on sampling factors */ #define MAX_SAMP_FACTOR 4 /* JPEG limit on sampling factors */
/* Unfortunately, some bozo at Adobe saw no reason to be bound by the standard; /* Unfortunately, some bozo at Adobe saw no reason to be bound by the standard;
* the PostScript DCT filter can emit files with many more than 10 blocks/MCU. * the PostScript DCT filter can emit files with many more than 10 blocks/MCU.
* If you happen to run across such a file, you can up D_MAX_BLOCKS_IN_MCU * If you happen to run across such a file, you can up D_MAX_BLOCKS_IN_MCU
@@ -67,13 +67,13 @@ extern "C" {
*/ */
typedef JSAMPLE *JSAMPROW; /* ptr to one image row of pixel samples. */ typedef JSAMPLE *JSAMPROW; /* ptr to one image row of pixel samples. */
typedef JSAMPROW *JSAMPARRAY; /* ptr to some rows (a 2-D sample array) */ typedef JSAMPROW *JSAMPARRAY; /* ptr to some rows (a 2-D sample array) */
typedef JSAMPARRAY *JSAMPIMAGE; /* a 3-D sample array: top index is color */ typedef JSAMPARRAY *JSAMPIMAGE; /* a 3-D 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 */
typedef JBLOCKARRAY *JBLOCKIMAGE; /* a 3-D array of coefficient blocks */ typedef JBLOCKARRAY *JBLOCKIMAGE; /* a 3-D array of coefficient blocks */
typedef JCOEF *JCOEFPTR; /* useful in a couple of places */ typedef JCOEF *JCOEFPTR; /* useful in a couple of places */
@@ -88,13 +88,13 @@ typedef struct {
* (not the zigzag order in which they are stored in a JPEG DQT marker). * (not the zigzag order in which they are stored in a JPEG DQT marker).
* CAUTION: IJG versions prior to v6a kept this array in zigzag order. * CAUTION: IJG versions prior to v6a kept this array in zigzag order.
*/ */
UINT16 quantval[DCTSIZE2]; /* quantization step for each coefficient */ UINT16 quantval[DCTSIZE2]; /* quantization step for each coefficient */
/* This field is used only during compression. It's initialized FALSE when /* This field is used only during compression. It's initialized FALSE when
* the table is created, and set TRUE when it's been output to the file. * the table is created, and set TRUE when it's been output to the file.
* You could suppress output of a table by setting this to TRUE. * You could suppress output of a table by setting this to TRUE.
* (See jpeg_suppress_tables for an example.) * (See jpeg_suppress_tables for an example.)
*/ */
boolean sent_table; /* TRUE when table has been output */ boolean sent_table; /* TRUE when table has been output */
} JQUANT_TBL; } JQUANT_TBL;
@@ -102,15 +102,15 @@ typedef struct {
typedef struct { typedef struct {
/* These two fields directly represent the contents of a JPEG DHT marker */ /* These two fields directly represent the contents of a JPEG DHT marker */
UINT8 bits[17]; /* bits[k] = # of symbols with codes of */ UINT8 bits[17]; /* bits[k] = # of symbols with codes of */
/* length k bits; bits[0] is unused */ /* length k bits; bits[0] is unused */
UINT8 huffval[256]; /* The symbols, in order of incr code length */ UINT8 huffval[256]; /* The symbols, in order of incr code length */
/* This field is used only during compression. It's initialized FALSE when /* This field is used only during compression. It's initialized FALSE when
* the table is created, and set TRUE when it's been output to the file. * the table is created, and set TRUE when it's been output to the file.
* You could suppress output of a table by setting this to TRUE. * You could suppress output of a table by setting this to TRUE.
* (See jpeg_suppress_tables for an example.) * (See jpeg_suppress_tables for an example.)
*/ */
boolean sent_table; /* TRUE when table has been output */ boolean sent_table; /* TRUE when table has been output */
} JHUFF_TBL; } JHUFF_TBL;
@@ -120,17 +120,17 @@ typedef struct {
/* These values are fixed over the whole image. */ /* These values are fixed over the whole image. */
/* For compression, they must be supplied by parameter setup; */ /* For compression, they must be supplied by parameter setup; */
/* for decompression, they are read from the SOF marker. */ /* for decompression, they are read from the SOF marker. */
int component_id; /* identifier for this component (0..255) */ int component_id; /* identifier for this component (0..255) */
int component_index; /* its index in SOF or cinfo->comp_info[] */ int component_index; /* its index in SOF or cinfo->comp_info[] */
int h_samp_factor; /* horizontal sampling factor (1..4) */ int h_samp_factor; /* horizontal sampling factor (1..4) */
int v_samp_factor; /* vertical sampling factor (1..4) */ int v_samp_factor; /* vertical sampling factor (1..4) */
int quant_tbl_no; /* quantization table selector (0..3) */ int quant_tbl_no; /* quantization table selector (0..3) */
/* These values may vary between scans. */ /* These values may vary between scans. */
/* For compression, they must be supplied by parameter setup; */ /* For compression, they must be supplied by parameter setup; */
/* for decompression, they are read from the SOS marker. */ /* for decompression, they are read from the SOS marker. */
/* The decompressor output side may not use these variables. */ /* The decompressor output side may not use these variables. */
int dc_tbl_no; /* DC entropy table selector (0..3) */ int dc_tbl_no; /* DC entropy table selector (0..3) */
int ac_tbl_no; /* AC entropy table selector (0..3) */ int ac_tbl_no; /* AC entropy table selector (0..3) */
/* Remaining fields should be treated as private by applications. */ /* Remaining fields should be treated as private by applications. */
@@ -159,22 +159,22 @@ typedef struct {
* and similarly for height. For decompression, IDCT scaling is included, so * and similarly for height. For decompression, IDCT scaling is included, so
* downsampled_width = ceil(image_width * Hi/Hmax * DCT_[h_]scaled_size/DCTSIZE) * downsampled_width = ceil(image_width * Hi/Hmax * DCT_[h_]scaled_size/DCTSIZE)
*/ */
JDIMENSION downsampled_width; /* actual width in samples */ JDIMENSION downsampled_width; /* actual width in samples */
JDIMENSION downsampled_height; /* actual height in samples */ JDIMENSION downsampled_height; /* actual height in samples */
/* This flag is used only for decompression. In cases where some of the /* This flag is used only for decompression. In cases where some of the
* components will be ignored (eg grayscale output from YCbCr image), * components will be ignored (eg grayscale output from YCbCr image),
* we can skip most computations for the unused components. * we can skip most computations for the unused components.
*/ */
boolean component_needed; /* do we need the value of this component? */ boolean component_needed; /* do we need the value of this component? */
/* These values are computed before starting a scan of the component. */ /* These values are computed before starting a scan of the component. */
/* The decompressor output side may not use these variables. */ /* The decompressor output side may not use these variables. */
int MCU_width; /* number of blocks per MCU, horizontally */ int MCU_width; /* number of blocks per MCU, horizontally */
int MCU_height; /* number of blocks per MCU, vertically */ int MCU_height; /* number of blocks per MCU, vertically */
int MCU_blocks; /* MCU_width * MCU_height */ int MCU_blocks; /* MCU_width * MCU_height */
int MCU_sample_width; /* MCU width in samples, MCU_width*DCT_[h_]scaled_size */ int MCU_sample_width; /* MCU width in samples, MCU_width*DCT_[h_]scaled_size */
int last_col_width; /* # of non-dummy blocks across in last MCU */ int last_col_width; /* # of non-dummy blocks across in last MCU */
int last_row_height; /* # of non-dummy blocks down in last MCU */ int last_row_height; /* # of non-dummy blocks down in last MCU */
/* Saved quantization table for component; NULL if none yet saved. /* Saved quantization table for component; NULL if none yet saved.
* See jdinput.c comments about the need for this information. * See jdinput.c comments about the need for this information.
@@ -190,10 +190,10 @@ typedef struct {
/* The script for encoding a multiple-scan file is an array of these: */ /* The script for encoding a multiple-scan file is an array of these: */
typedef struct { typedef struct {
int comps_in_scan; /* number of components encoded in this scan */ int comps_in_scan; /* number of components encoded in this scan */
int component_index[MAX_COMPS_IN_SCAN]; /* their SOF/comp_info[] indexes */ int component_index[MAX_COMPS_IN_SCAN]; /* their SOF/comp_info[] indexes */
int Ss, Se; /* progressive JPEG spectral selection parms */ int Ss, Se; /* progressive JPEG spectral selection parms */
int Ah, Al; /* progressive JPEG successive approx. parms */ int Ah, Al; /* progressive JPEG successive approx. parms */
} jpeg_scan_info; } jpeg_scan_info;
/* The decompressor can save APPn and COM markers in a list of these: */ /* The decompressor can save APPn and COM markers in a list of these: */
@@ -201,10 +201,10 @@ typedef struct {
typedef struct jpeg_marker_struct * jpeg_saved_marker_ptr; typedef struct jpeg_marker_struct * jpeg_saved_marker_ptr;
struct jpeg_marker_struct { struct jpeg_marker_struct {
jpeg_saved_marker_ptr next; /* next in list, or NULL */ jpeg_saved_marker_ptr next; /* next in list, or NULL */
UINT8 marker; /* marker code: JPEG_COM, or JPEG_APP0+n */ UINT8 marker; /* marker code: JPEG_COM, or JPEG_APP0+n */
unsigned int original_length; /* # bytes of data in the file */ unsigned int original_length; /* # bytes of data in the file */
unsigned int data_length; /* # bytes of data saved at data[] */ unsigned int data_length; /* # bytes of data saved at data[] */
JOCTET * data; /* the data contained in the marker */ JOCTET * data; /* the data contained in the marker */
/* the marker length word is not counted in data_length or original_length */ /* the marker length word is not counted in data_length or original_length */
}; };
@@ -215,28 +215,28 @@ struct jpeg_marker_struct {
#define JCS_ALPHA_EXTENSIONS 1 #define JCS_ALPHA_EXTENSIONS 1
typedef enum { typedef enum {
JCS_UNKNOWN, /* error/unspecified */ JCS_UNKNOWN, /* error/unspecified */
JCS_GRAYSCALE, /* monochrome */ JCS_GRAYSCALE, /* monochrome */
JCS_RGB, /* red/green/blue as specified by the RGB_RED, JCS_RGB, /* red/green/blue as specified by the RGB_RED,
RGB_GREEN, RGB_BLUE, and RGB_PIXELSIZE macros */ RGB_GREEN, RGB_BLUE, and RGB_PIXELSIZE macros */
JCS_YCbCr, /* Y/Cb/Cr (also known as YUV) */ JCS_YCbCr, /* Y/Cb/Cr (also known as YUV) */
JCS_CMYK, /* C/M/Y/K */ JCS_CMYK, /* C/M/Y/K */
JCS_YCCK, /* Y/Cb/Cr/K */ JCS_YCCK, /* Y/Cb/Cr/K */
JCS_EXT_RGB, /* red/green/blue */ JCS_EXT_RGB, /* red/green/blue */
JCS_EXT_RGBX, /* red/green/blue/x */ JCS_EXT_RGBX, /* red/green/blue/x */
JCS_EXT_BGR, /* blue/green/red */ JCS_EXT_BGR, /* blue/green/red */
JCS_EXT_BGRX, /* blue/green/red/x */ JCS_EXT_BGRX, /* blue/green/red/x */
JCS_EXT_XBGR, /* x/blue/green/red */ JCS_EXT_XBGR, /* x/blue/green/red */
JCS_EXT_XRGB, /* x/red/green/blue */ JCS_EXT_XRGB, /* x/red/green/blue */
/* When out_color_space it set to JCS_EXT_RGBX, JCS_EXT_BGRX, JCS_EXT_XBGR, /* When out_color_space it set to JCS_EXT_RGBX, JCS_EXT_BGRX, JCS_EXT_XBGR,
or JCS_EXT_XRGB during decompression, the X byte is undefined, and in or JCS_EXT_XRGB during decompression, the X byte is undefined, and in
order to ensure the best performance, libjpeg-turbo can set that byte to order to ensure the best performance, libjpeg-turbo can set that byte to
whatever value it wishes. Use the following colorspace constants to whatever value it wishes. Use the following colorspace constants to
ensure that the X byte is set to 0xFF, so that it can be interpreted as an ensure that the X byte is set to 0xFF, so that it can be interpreted as an
opaque alpha channel. */ opaque alpha channel. */
JCS_EXT_RGBA, /* red/green/blue/alpha */ JCS_EXT_RGBA, /* red/green/blue/alpha */
JCS_EXT_BGRA, /* blue/green/red/alpha */ JCS_EXT_BGRA, /* blue/green/red/alpha */
JCS_EXT_ABGR, /* alpha/blue/green/red */ JCS_EXT_ABGR, /* alpha/blue/green/red */
JCS_EXT_ARGB, /* alpha/red/green/blue */ JCS_EXT_ARGB, /* alpha/red/green/blue */
JCS_RGB565 /* 5-bit red/6-bit green/5-bit blue */ JCS_RGB565 /* 5-bit red/6-bit green/5-bit blue */
} J_COLOR_SPACE; } J_COLOR_SPACE;
@@ -244,43 +244,43 @@ typedef enum {
/* DCT/IDCT algorithm options. */ /* DCT/IDCT algorithm options. */
typedef enum { typedef enum {
JDCT_ISLOW, /* slow but accurate integer algorithm */ JDCT_ISLOW, /* slow but accurate integer algorithm */
JDCT_IFAST, /* faster, less accurate integer method */ JDCT_IFAST, /* faster, less accurate integer method */
JDCT_FLOAT /* floating-point: accurate, fast on fast HW */ JDCT_FLOAT /* floating-point: accurate, fast on fast HW */
} J_DCT_METHOD; } J_DCT_METHOD;
#ifndef JDCT_DEFAULT /* may be overridden in jconfig.h */ #ifndef JDCT_DEFAULT /* may be overridden in jconfig.h */
#define JDCT_DEFAULT JDCT_ISLOW #define JDCT_DEFAULT JDCT_ISLOW
#endif #endif
#ifndef JDCT_FASTEST /* may be overridden in jconfig.h */ #ifndef JDCT_FASTEST /* may be overridden in jconfig.h */
#define JDCT_FASTEST JDCT_IFAST #define JDCT_FASTEST JDCT_IFAST
#endif #endif
/* Dithering options for decompression. */ /* Dithering options for decompression. */
typedef enum { typedef enum {
JDITHER_NONE, /* no dithering */ JDITHER_NONE, /* no dithering */
JDITHER_ORDERED, /* simple ordered dither */ JDITHER_ORDERED, /* simple ordered dither */
JDITHER_FS /* Floyd-Steinberg error diffusion dither */ JDITHER_FS /* Floyd-Steinberg error diffusion dither */
} J_DITHER_MODE; } J_DITHER_MODE;
/* Common fields between JPEG compression and decompression master structs. */ /* Common fields between JPEG compression and decompression master structs. */
#define jpeg_common_fields \ #define jpeg_common_fields \
struct jpeg_error_mgr * err; /* Error handler module */\ struct jpeg_error_mgr * err; /* Error handler module */\
struct jpeg_memory_mgr * mem; /* Memory manager module */\ struct jpeg_memory_mgr * mem; /* Memory manager module */\
struct jpeg_progress_mgr * progress; /* Progress monitor, or NULL if none */\ struct jpeg_progress_mgr * progress; /* Progress monitor, or NULL if none */\
void * client_data; /* Available for use by application */\ void * client_data; /* Available for use by application */\
boolean is_decompressor; /* So common code can tell which is which */\ boolean is_decompressor; /* So common code can tell which is which */\
int global_state /* For checking call sequence validity */ int global_state /* For checking call sequence validity */
/* Routines that are to be used by both halves of the library are declared /* Routines that are to be used by both halves of the library are declared
* to receive a pointer to this structure. There are no actual instances of * to receive a pointer to this structure. There are no actual instances of
* jpeg_common_struct, only of jpeg_compress_struct and jpeg_decompress_struct. * jpeg_common_struct, only of jpeg_compress_struct and jpeg_decompress_struct.
*/ */
struct jpeg_common_struct { struct jpeg_common_struct {
jpeg_common_fields; /* Fields common to both master struct types */ jpeg_common_fields; /* Fields common to both master struct types */
/* Additional fields follow in an actual jpeg_compress_struct or /* Additional fields follow in an actual jpeg_compress_struct or
* jpeg_decompress_struct. All three structs must agree on these * jpeg_decompress_struct. All three structs must agree on these
* initial fields! (This would be a lot cleaner in C++.) * initial fields! (This would be a lot cleaner in C++.)
@@ -295,7 +295,7 @@ typedef struct jpeg_decompress_struct * j_decompress_ptr;
/* Master record for a compression instance */ /* Master record for a compression instance */
struct jpeg_compress_struct { struct jpeg_compress_struct {
jpeg_common_fields; /* Fields shared with jpeg_decompress_struct */ jpeg_common_fields; /* Fields shared with jpeg_decompress_struct */
/* Destination for compressed data */ /* Destination for compressed data */
struct jpeg_destination_mgr * dest; struct jpeg_destination_mgr * dest;
@@ -305,12 +305,12 @@ struct jpeg_compress_struct {
* be correct before you can even call jpeg_set_defaults(). * be correct before you can even call jpeg_set_defaults().
*/ */
JDIMENSION image_width; /* input image width */ JDIMENSION image_width; /* input image width */
JDIMENSION image_height; /* input image height */ JDIMENSION image_height; /* input image height */
int input_components; /* # of color components in input image */ int input_components; /* # of color components in input image */
J_COLOR_SPACE in_color_space; /* colorspace of input image */ J_COLOR_SPACE in_color_space; /* colorspace of input image */
double input_gamma; /* image gamma of input image */ double input_gamma; /* image gamma of input image */
/* Compression parameters --- these fields must be set before calling /* Compression parameters --- these fields must be set before calling
* jpeg_start_compress(). We recommend calling jpeg_set_defaults() to * jpeg_start_compress(). We recommend calling jpeg_set_defaults() to
@@ -323,8 +323,8 @@ struct jpeg_compress_struct {
#if JPEG_LIB_VERSION >= 70 #if JPEG_LIB_VERSION >= 70
unsigned int scale_num, scale_denom; /* fraction by which to scale image */ unsigned int scale_num, scale_denom; /* fraction by which to scale image */
JDIMENSION jpeg_width; /* scaled JPEG image width */ JDIMENSION jpeg_width; /* scaled JPEG image width */
JDIMENSION jpeg_height; /* scaled JPEG image height */ JDIMENSION jpeg_height; /* scaled JPEG image height */
/* Dimensions of actual JPEG image that will be written to file, /* Dimensions of actual JPEG image that will be written to file,
* derived from input dimensions by scaling factors above. * derived from input dimensions by scaling factors above.
* These fields are computed by jpeg_start_compress(). * These fields are computed by jpeg_start_compress().
@@ -333,9 +333,9 @@ struct jpeg_compress_struct {
*/ */
#endif #endif
int data_precision; /* bits of precision in image data */ int data_precision; /* bits of precision in image data */
int num_components; /* # of color components in JPEG image */ int num_components; /* # of color components in JPEG image */
J_COLOR_SPACE jpeg_color_space; /* colorspace of JPEG image */ J_COLOR_SPACE jpeg_color_space; /* colorspace of JPEG image */
jpeg_component_info * comp_info; jpeg_component_info * comp_info;
@@ -357,27 +357,29 @@ struct jpeg_compress_struct {
UINT8 arith_dc_U[NUM_ARITH_TBLS]; /* U values for DC arith-coding tables */ UINT8 arith_dc_U[NUM_ARITH_TBLS]; /* U values for DC arith-coding tables */
UINT8 arith_ac_K[NUM_ARITH_TBLS]; /* Kx values for AC arith-coding tables */ UINT8 arith_ac_K[NUM_ARITH_TBLS]; /* Kx values for AC arith-coding tables */
int num_scans; /* # of entries in scan_info array */ int num_scans; /* # of entries in scan_info array */
const jpeg_scan_info * scan_info; /* script for multi-scan file, or NULL */ const jpeg_scan_info * scan_info; /* script for multi-scan file, or NULL */
/* The default value of scan_info is NULL, which causes a single-scan /* The default value of scan_info is NULL, which causes a single-scan
* sequential JPEG file to be emitted. To create a multi-scan file, * sequential JPEG file to be emitted. To create a multi-scan file,
* set num_scans and scan_info to point to an array of scan definitions. * set num_scans and scan_info to point to an array of scan definitions.
*/ */
boolean raw_data_in; /* TRUE=caller supplies downsampled data */ boolean raw_data_in; /* TRUE=caller supplies downsampled data */
boolean arith_code; /* TRUE=arithmetic coding, FALSE=Huffman */ boolean arith_code; /* TRUE=arithmetic coding, FALSE=Huffman */
boolean optimize_coding; /* TRUE=optimize entropy encoding parms */ boolean optimize_coding; /* TRUE=optimize entropy encoding parms */
boolean CCIR601_sampling; /* TRUE=first samples are cosited */ boolean CCIR601_sampling; /* TRUE=first samples are cosited */
#if JPEG_LIB_VERSION >= 70 #if JPEG_LIB_VERSION >= 70
boolean do_fancy_downsampling; /* TRUE=apply fancy downsampling */ boolean do_fancy_downsampling; /* TRUE=apply fancy downsampling */
#endif #endif
int smoothing_factor; /* 1..100, or 0 for no input smoothing */ int smoothing_factor; /* 1..100, or 0 for no input smoothing */
J_DCT_METHOD dct_method; /* DCT algorithm selector */ J_DCT_METHOD dct_method; /* DCT algorithm selector */
boolean use_moz_defaults; /* TRUE=use Mozilla defaults */ boolean use_moz_defaults; /* TRUE=use Mozilla defaults */
boolean optimize_scans; /* TRUE=optimize progressive coding scans */ boolean optimize_scans; /* TRUE=optimize progressive coding scans */
boolean one_dc_scan; /* TRUE=use a single DC scan interleaving all components */ boolean one_dc_scan; /* TRUE=use a single DC scan interleaving all components */
boolean sep_dc_scan; /* TRUE=each DC scan is separate */
boolean trellis_quant; /* TRUE=use trellis quantization */ boolean trellis_quant; /* TRUE=use trellis quantization */
boolean trellis_quant_dc; /* TRUE=use trellis quant for DC coefficient */
boolean trellis_eob_opt; /* TRUE=optimize for sequences of EOB */ boolean trellis_eob_opt; /* TRUE=optimize for sequences of EOB */
boolean use_flat_quant_tbl; /* TRUE=use flat quantization table */ boolean use_flat_quant_tbl; /* TRUE=use flat quantization table */
boolean use_lambda_weight_tbl; /* TRUE=use lambda weighting table */ boolean use_lambda_weight_tbl; /* TRUE=use lambda weighting table */
@@ -408,28 +410,28 @@ struct jpeg_compress_struct {
* for each scan). * for each scan).
*/ */
unsigned int restart_interval; /* MCUs per restart, or 0 for no restart */ unsigned int restart_interval; /* MCUs per restart, or 0 for no restart */
int restart_in_rows; /* if > 0, MCU rows per restart interval */ int restart_in_rows; /* if > 0, MCU rows per restart interval */
/* Parameters controlling emission of special markers. */ /* Parameters controlling emission of special markers. */
boolean write_JFIF_header; /* should a JFIF marker be written? */ boolean write_JFIF_header; /* should a JFIF marker be written? */
UINT8 JFIF_major_version; /* What to write for the JFIF version number */ UINT8 JFIF_major_version; /* What to write for the JFIF version number */
UINT8 JFIF_minor_version; UINT8 JFIF_minor_version;
/* These three values are not used by the JPEG code, merely copied */ /* These three values are not used by the JPEG code, merely copied */
/* into the JFIF APP0 marker. density_unit can be 0 for unknown, */ /* into the JFIF APP0 marker. density_unit can be 0 for unknown, */
/* 1 for dots/inch, or 2 for dots/cm. Note that the pixel aspect */ /* 1 for dots/inch, or 2 for dots/cm. Note that the pixel aspect */
/* ratio is defined by X_density/Y_density even when density_unit=0. */ /* ratio is defined by X_density/Y_density even when density_unit=0. */
UINT8 density_unit; /* JFIF code for pixel size units */ UINT8 density_unit; /* JFIF code for pixel size units */
UINT16 X_density; /* Horizontal pixel density */ UINT16 X_density; /* Horizontal pixel density */
UINT16 Y_density; /* Vertical pixel density */ UINT16 Y_density; /* Vertical pixel density */
boolean write_Adobe_marker; /* should an Adobe marker be written? */ boolean write_Adobe_marker; /* should an Adobe marker be written? */
/* State variable: index of next scanline to be written to /* State variable: index of next scanline to be written to
* jpeg_write_scanlines(). Application may use this to control its * jpeg_write_scanlines(). Application may use this to control its
* processing loop, e.g., "while (next_scanline < image_height)". * processing loop, e.g., "while (next_scanline < image_height)".
*/ */
JDIMENSION next_scanline; /* 0 .. image_height-1 */ JDIMENSION next_scanline; /* 0 .. image_height-1 */
/* Remaining fields are known throughout compressor, but generally /* Remaining fields are known throughout compressor, but generally
* should not be touched by a surrounding application. * should not be touched by a surrounding application.
@@ -438,16 +440,16 @@ struct jpeg_compress_struct {
/* /*
* These fields are computed during compression startup * These fields are computed during compression startup
*/ */
boolean progressive_mode; /* TRUE if scan script uses progressive mode */ boolean progressive_mode; /* TRUE if scan script uses progressive mode */
int max_h_samp_factor; /* largest h_samp_factor */ int max_h_samp_factor; /* largest h_samp_factor */
int max_v_samp_factor; /* largest v_samp_factor */ int max_v_samp_factor; /* largest v_samp_factor */
#if JPEG_LIB_VERSION >= 70 #if JPEG_LIB_VERSION >= 70
int min_DCT_h_scaled_size; /* smallest DCT_h_scaled_size of any component */ int min_DCT_h_scaled_size; /* smallest DCT_h_scaled_size of any component */
int min_DCT_v_scaled_size; /* smallest DCT_v_scaled_size of any component */ int min_DCT_v_scaled_size; /* smallest DCT_v_scaled_size of any component */
#endif #endif
JDIMENSION total_iMCU_rows; /* # of iMCU rows to be input to coef ctlr */ JDIMENSION total_iMCU_rows; /* # of iMCU rows to be input to coef ctlr */
/* The coefficient controller receives data in units of MCU rows as defined /* The coefficient controller receives data in units of MCU rows as defined
* for fully interleaved scans (whether the JPEG file is interleaved or not). * for fully interleaved scans (whether the JPEG file is interleaved or not).
* There are v_samp_factor * DCTSIZE sample rows of each component in an * There are v_samp_factor * DCTSIZE sample rows of each component in an
@@ -458,24 +460,24 @@ struct jpeg_compress_struct {
* These fields are valid during any one scan. * These fields are valid during any one scan.
* They describe the components and MCUs actually appearing in the scan. * They describe the components and MCUs actually appearing in the scan.
*/ */
int comps_in_scan; /* # of JPEG components in this scan */ int comps_in_scan; /* # of JPEG components in this scan */
jpeg_component_info * cur_comp_info[MAX_COMPS_IN_SCAN]; jpeg_component_info * cur_comp_info[MAX_COMPS_IN_SCAN];
/* *cur_comp_info[i] describes component that appears i'th in SOS */ /* *cur_comp_info[i] describes component that appears i'th in SOS */
JDIMENSION MCUs_per_row; /* # of MCUs across the image */ JDIMENSION MCUs_per_row; /* # of MCUs across the image */
JDIMENSION MCU_rows_in_scan; /* # of MCU rows in the image */ JDIMENSION MCU_rows_in_scan; /* # of MCU rows in the image */
int blocks_in_MCU; /* # of DCT blocks per MCU */ int blocks_in_MCU; /* # of DCT blocks per MCU */
int MCU_membership[C_MAX_BLOCKS_IN_MCU]; int MCU_membership[C_MAX_BLOCKS_IN_MCU];
/* MCU_membership[i] is index in cur_comp_info of component owning */ /* MCU_membership[i] is index in cur_comp_info of component owning */
/* i'th block in an MCU */ /* i'th block in an MCU */
int Ss, Se, Ah, Al; /* progressive JPEG parameters for scan */ int Ss, Se, Ah, Al; /* progressive JPEG parameters for scan */
#if JPEG_LIB_VERSION >= 80 #if JPEG_LIB_VERSION >= 80
int block_size; /* the basic DCT block size: 1..16 */ int block_size; /* the basic DCT block size: 1..16 */
const int * natural_order; /* natural-order position array */ const int * natural_order; /* natural-order position array */
int lim_Se; /* min( Se, DCTSIZE2-1 ) */ int lim_Se; /* min( Se, DCTSIZE2-1 ) */
#endif #endif
/* /*
@@ -498,7 +500,7 @@ struct jpeg_compress_struct {
/* Master record for a decompression instance */ /* Master record for a decompression instance */
struct jpeg_decompress_struct { struct jpeg_decompress_struct {
jpeg_common_fields; /* Fields shared with jpeg_compress_struct */ jpeg_common_fields; /* Fields shared with jpeg_compress_struct */
/* Source of compressed data */ /* Source of compressed data */
struct jpeg_source_mgr * src; struct jpeg_source_mgr * src;
@@ -506,9 +508,9 @@ struct jpeg_decompress_struct {
/* Basic description of image --- filled in by jpeg_read_header(). */ /* Basic description of image --- filled in by jpeg_read_header(). */
/* Application may inspect these values to decide how to process image. */ /* Application may inspect these values to decide how to process image. */
JDIMENSION image_width; /* nominal image width (from SOF marker) */ JDIMENSION image_width; /* nominal image width (from SOF marker) */
JDIMENSION image_height; /* nominal image height */ JDIMENSION image_height; /* nominal image height */
int num_components; /* # of color components in JPEG image */ int num_components; /* # of color components in JPEG image */
J_COLOR_SPACE jpeg_color_space; /* colorspace of JPEG image */ J_COLOR_SPACE jpeg_color_space; /* colorspace of JPEG image */
/* Decompression processing parameters --- these fields must be set before /* Decompression processing parameters --- these fields must be set before
@@ -520,24 +522,24 @@ struct jpeg_decompress_struct {
unsigned int scale_num, scale_denom; /* fraction by which to scale image */ unsigned int scale_num, scale_denom; /* fraction by which to scale image */
double output_gamma; /* image gamma wanted in output */ double output_gamma; /* image gamma wanted in output */
boolean buffered_image; /* TRUE=multiple output passes */ boolean buffered_image; /* TRUE=multiple output passes */
boolean raw_data_out; /* TRUE=downsampled data wanted */ boolean raw_data_out; /* TRUE=downsampled data wanted */
J_DCT_METHOD dct_method; /* IDCT algorithm selector */ J_DCT_METHOD dct_method; /* IDCT algorithm selector */
boolean do_fancy_upsampling; /* TRUE=apply fancy upsampling */ boolean do_fancy_upsampling; /* TRUE=apply fancy upsampling */
boolean do_block_smoothing; /* TRUE=apply interblock smoothing */ boolean do_block_smoothing; /* TRUE=apply interblock smoothing */
boolean quantize_colors; /* TRUE=colormapped output wanted */ boolean quantize_colors; /* TRUE=colormapped output wanted */
/* the following are ignored if not quantize_colors: */ /* the following are ignored if not quantize_colors: */
J_DITHER_MODE dither_mode; /* type of color dithering to use */ J_DITHER_MODE dither_mode; /* type of color dithering to use */
boolean two_pass_quantize; /* TRUE=use two-pass color quantization */ boolean two_pass_quantize; /* TRUE=use two-pass color quantization */
int desired_number_of_colors; /* max # colors to use in created colormap */ int desired_number_of_colors; /* max # colors to use in created colormap */
/* these are significant only in buffered-image mode: */ /* these are significant only in buffered-image mode: */
boolean enable_1pass_quant; /* enable future use of 1-pass quantizer */ boolean enable_1pass_quant; /* enable future use of 1-pass quantizer */
boolean enable_external_quant;/* enable future use of external colormap */ boolean enable_external_quant;/* enable future use of external colormap */
boolean enable_2pass_quant; /* enable future use of 2-pass quantizer */ boolean enable_2pass_quant; /* enable future use of 2-pass quantizer */
/* Description of actual output image that will be returned to application. /* Description of actual output image that will be returned to application.
* These fields are computed by jpeg_start_decompress(). * These fields are computed by jpeg_start_decompress().
@@ -545,14 +547,14 @@ struct jpeg_decompress_struct {
* in advance of calling jpeg_start_decompress(). * in advance of calling jpeg_start_decompress().
*/ */
JDIMENSION output_width; /* scaled image width */ JDIMENSION output_width; /* scaled image width */
JDIMENSION output_height; /* scaled image height */ JDIMENSION output_height; /* scaled image height */
int out_color_components; /* # of color components in out_color_space */ int out_color_components; /* # of color components in out_color_space */
int output_components; /* # of color components returned */ int output_components; /* # of color components returned */
/* output_components is 1 (a colormap index) when quantizing colors; /* output_components is 1 (a colormap index) when quantizing colors;
* otherwise it equals out_color_components. * otherwise it equals out_color_components.
*/ */
int rec_outbuf_height; /* min recommended height of scanline buffer */ int rec_outbuf_height; /* min recommended height of scanline buffer */
/* If the buffer passed to jpeg_read_scanlines() is less than this many rows /* If the buffer passed to jpeg_read_scanlines() is less than this many rows
* high, space and time will be wasted due to unnecessary data copying. * high, space and time will be wasted due to unnecessary data copying.
* Usually rec_outbuf_height will be 1 or 2, at most 4. * Usually rec_outbuf_height will be 1 or 2, at most 4.
@@ -564,8 +566,8 @@ struct jpeg_decompress_struct {
* jpeg_start_decompress or jpeg_start_output. * jpeg_start_decompress or jpeg_start_output.
* The map has out_color_components rows and actual_number_of_colors columns. * The map has out_color_components rows and actual_number_of_colors columns.
*/ */
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 */
/* 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.
@@ -575,20 +577,20 @@ struct jpeg_decompress_struct {
* Application may use this to control its processing loop, e.g., * Application may use this to control its processing loop, e.g.,
* "while (output_scanline < output_height)". * "while (output_scanline < output_height)".
*/ */
JDIMENSION output_scanline; /* 0 .. output_height-1 */ JDIMENSION output_scanline; /* 0 .. output_height-1 */
/* Current input scan number and number of iMCU rows completed in scan. /* Current input scan number and number of iMCU rows completed in scan.
* These indicate the progress of the decompressor input side. * These indicate the progress of the decompressor input side.
*/ */
int input_scan_number; /* Number of SOS markers seen so far */ int input_scan_number; /* Number of SOS markers seen so far */
JDIMENSION input_iMCU_row; /* Number of iMCU rows completed */ JDIMENSION input_iMCU_row; /* Number of iMCU rows completed */
/* The "output scan number" is the notional scan being displayed by the /* The "output scan number" is the notional scan being displayed by the
* output side. The decompressor will not allow output scan/row number * output side. The decompressor will not allow output scan/row number
* to get ahead of input scan/row, but it can fall arbitrarily far behind. * to get ahead of input scan/row, but it can fall arbitrarily far behind.
*/ */
int output_scan_number; /* Nominal scan number being displayed */ int output_scan_number; /* Nominal scan number being displayed */
JDIMENSION output_iMCU_row; /* Number of iMCU rows read */ JDIMENSION output_iMCU_row; /* Number of iMCU rows read */
/* Current progression status. coef_bits[c][i] indicates the precision /* Current progression status. coef_bits[c][i] indicates the precision
* with which component c's DCT coefficient i (in zigzag order) is known. * with which component c's DCT coefficient i (in zigzag order) is known.
@@ -597,7 +599,7 @@ struct jpeg_decompress_struct {
* (thus, 0 at completion of the progression). * (thus, 0 at completion of the progression).
* This pointer is NULL when reading a non-progressive file. * This pointer is NULL when reading a non-progressive file.
*/ */
int (*coef_bits)[DCTSIZE2]; /* -1 or current Al value for each coef */ int (*coef_bits)[DCTSIZE2]; /* -1 or current Al value for each coef */
/* Internal JPEG parameters --- the application usually need not look at /* Internal JPEG parameters --- the application usually need not look at
* these fields. Note that the decompressor output side may not use * these fields. Note that the decompressor output side may not use
@@ -619,16 +621,16 @@ struct jpeg_decompress_struct {
* are given in SOF/SOS markers or defined to be reset by SOI. * are given in SOF/SOS markers or defined to be reset by SOI.
*/ */
int data_precision; /* bits of precision in image data */ int data_precision; /* bits of precision in image data */
jpeg_component_info * comp_info; jpeg_component_info * comp_info;
/* comp_info[i] describes component that appears i'th in SOF */ /* comp_info[i] describes component that appears i'th in SOF */
#if JPEG_LIB_VERSION >= 80 #if JPEG_LIB_VERSION >= 80
boolean is_baseline; /* TRUE if Baseline SOF0 encountered */ boolean is_baseline; /* TRUE if Baseline SOF0 encountered */
#endif #endif
boolean progressive_mode; /* TRUE if SOFn specifies progressive mode */ boolean progressive_mode; /* TRUE if SOFn specifies progressive mode */
boolean arith_code; /* TRUE=arithmetic coding, FALSE=Huffman */ boolean arith_code; /* TRUE=arithmetic coding, FALSE=Huffman */
UINT8 arith_dc_L[NUM_ARITH_TBLS]; /* L values for DC arith-coding tables */ UINT8 arith_dc_L[NUM_ARITH_TBLS]; /* L values for DC arith-coding tables */
UINT8 arith_dc_U[NUM_ARITH_TBLS]; /* U values for DC arith-coding tables */ UINT8 arith_dc_U[NUM_ARITH_TBLS]; /* U values for DC arith-coding tables */
@@ -639,17 +641,17 @@ struct jpeg_decompress_struct {
/* These fields record data obtained from optional markers recognized by /* These fields record data obtained from optional markers recognized by
* the JPEG library. * the JPEG library.
*/ */
boolean saw_JFIF_marker; /* TRUE iff a JFIF APP0 marker was found */ boolean saw_JFIF_marker; /* TRUE iff a JFIF APP0 marker was found */
/* Data copied from JFIF marker; only valid if saw_JFIF_marker is TRUE: */ /* Data copied from JFIF marker; only valid if saw_JFIF_marker is TRUE: */
UINT8 JFIF_major_version; /* JFIF version number */ UINT8 JFIF_major_version; /* JFIF version number */
UINT8 JFIF_minor_version; UINT8 JFIF_minor_version;
UINT8 density_unit; /* JFIF code for pixel size units */ UINT8 density_unit; /* JFIF code for pixel size units */
UINT16 X_density; /* Horizontal pixel density */ UINT16 X_density; /* Horizontal pixel density */
UINT16 Y_density; /* Vertical pixel density */ UINT16 Y_density; /* Vertical pixel density */
boolean saw_Adobe_marker; /* TRUE iff an Adobe APP14 marker was found */ boolean saw_Adobe_marker; /* TRUE iff an Adobe APP14 marker was found */
UINT8 Adobe_transform; /* Color transform code from Adobe marker */ UINT8 Adobe_transform; /* Color transform code from Adobe marker */
boolean CCIR601_sampling; /* TRUE=first samples are cosited */ boolean CCIR601_sampling; /* TRUE=first samples are cosited */
/* Aside from the specific data retained from APPn markers known to the /* Aside from the specific data retained from APPn markers known to the
* library, the uninterpreted contents of any or all APPn and COM markers * library, the uninterpreted contents of any or all APPn and COM markers
@@ -664,17 +666,17 @@ struct jpeg_decompress_struct {
/* /*
* These fields are computed during decompression startup * These fields are computed during decompression startup
*/ */
int max_h_samp_factor; /* largest h_samp_factor */ int max_h_samp_factor; /* largest h_samp_factor */
int max_v_samp_factor; /* largest v_samp_factor */ int max_v_samp_factor; /* largest v_samp_factor */
#if JPEG_LIB_VERSION >= 70 #if JPEG_LIB_VERSION >= 70
int min_DCT_h_scaled_size; /* smallest DCT_h_scaled_size of any component */ int min_DCT_h_scaled_size; /* smallest DCT_h_scaled_size of any component */
int min_DCT_v_scaled_size; /* smallest DCT_v_scaled_size of any component */ int min_DCT_v_scaled_size; /* smallest DCT_v_scaled_size of any component */
#else #else
int min_DCT_scaled_size; /* smallest DCT_scaled_size of any component */ int min_DCT_scaled_size; /* smallest DCT_scaled_size of any component */
#endif #endif
JDIMENSION total_iMCU_rows; /* # of iMCU rows in image */ JDIMENSION total_iMCU_rows; /* # of iMCU rows in image */
/* The coefficient controller's input and output progress is measured in /* The coefficient controller's input and output progress is measured in
* units of "iMCU" (interleaved MCU) rows. These are the same as MCU rows * units of "iMCU" (interleaved MCU) rows. These are the same as MCU rows
* in fully interleaved JPEG scans, but are used whether the scan is * in fully interleaved JPEG scans, but are used whether the scan is
@@ -690,26 +692,26 @@ struct jpeg_decompress_struct {
* They describe the components and MCUs actually appearing in the scan. * They describe the components and MCUs actually appearing in the scan.
* Note that the decompressor output side must not use these fields. * Note that the decompressor output side must not use these fields.
*/ */
int comps_in_scan; /* # of JPEG components in this scan */ int comps_in_scan; /* # of JPEG components in this scan */
jpeg_component_info * cur_comp_info[MAX_COMPS_IN_SCAN]; jpeg_component_info * cur_comp_info[MAX_COMPS_IN_SCAN];
/* *cur_comp_info[i] describes component that appears i'th in SOS */ /* *cur_comp_info[i] describes component that appears i'th in SOS */
JDIMENSION MCUs_per_row; /* # of MCUs across the image */ JDIMENSION MCUs_per_row; /* # of MCUs across the image */
JDIMENSION MCU_rows_in_scan; /* # of MCU rows in the image */ JDIMENSION MCU_rows_in_scan; /* # of MCU rows in the image */
int blocks_in_MCU; /* # of DCT blocks per MCU */ int blocks_in_MCU; /* # of DCT blocks per MCU */
int MCU_membership[D_MAX_BLOCKS_IN_MCU]; int MCU_membership[D_MAX_BLOCKS_IN_MCU];
/* MCU_membership[i] is index in cur_comp_info of component owning */ /* MCU_membership[i] is index in cur_comp_info of component owning */
/* i'th block in an MCU */ /* i'th block in an MCU */
int Ss, Se, Ah, Al; /* progressive JPEG parameters for scan */ int Ss, Se, Ah, Al; /* progressive JPEG parameters for scan */
#if JPEG_LIB_VERSION >= 80 #if JPEG_LIB_VERSION >= 80
/* These fields are derived from Se of first SOS marker. /* These fields are derived from Se of first SOS marker.
*/ */
int block_size; /* the basic DCT block size: 1..16 */ int block_size; /* the basic DCT block size: 1..16 */
const int * natural_order; /* natural-order position array for entropy decode */ const int * natural_order; /* natural-order position array for entropy decode */
int lim_Se; /* min( Se, DCTSIZE2-1 ) for entropy decode */ int lim_Se; /* min( Se, DCTSIZE2-1 ) for entropy decode */
#endif #endif
/* This field is shared between entropy decoder and marker parser. /* This field is shared between entropy decoder and marker parser.
@@ -754,7 +756,7 @@ struct jpeg_error_mgr {
void (*output_message) (j_common_ptr cinfo); void (*output_message) (j_common_ptr cinfo);
/* Format a message string for the most recent JPEG error or message */ /* Format a message string for the most recent JPEG error or message */
void (*format_message) (j_common_ptr cinfo, char * buffer); void (*format_message) (j_common_ptr cinfo, char * buffer);
#define JMSG_LENGTH_MAX 200 /* recommended size of format_message buffer */ #define JMSG_LENGTH_MAX 200 /* recommended size of format_message buffer */
/* Reset error state variables at start of a new image */ /* Reset error state variables at start of a new image */
void (*reset_error_mgr) (j_common_ptr cinfo); void (*reset_error_mgr) (j_common_ptr cinfo);
@@ -770,7 +772,7 @@ struct jpeg_error_mgr {
/* Standard state variables for error facility */ /* Standard state variables for error facility */
int trace_level; /* max msg_level that will be displayed */ int trace_level; /* max msg_level that will be displayed */
/* For recoverable corrupt-data errors, we emit a warning message, /* For recoverable corrupt-data errors, we emit a warning message,
* but keep going unless emit_message chooses to abort. emit_message * but keep going unless emit_message chooses to abort. emit_message
@@ -778,7 +780,7 @@ struct jpeg_error_mgr {
* can check for bad data by seeing if num_warnings is nonzero at the * can check for bad data by seeing if num_warnings is nonzero at the
* end of processing. * end of processing.
*/ */
long num_warnings; /* number of corrupt-data warnings */ long num_warnings; /* number of corrupt-data warnings */
/* These fields point to the table(s) of error message strings. /* These fields point to the table(s) of error message strings.
* An application can change the table pointer to switch to a different * An application can change the table pointer to switch to a different
@@ -796,8 +798,8 @@ struct jpeg_error_mgr {
* It contains strings numbered first_addon_message..last_addon_message. * It contains strings numbered first_addon_message..last_addon_message.
*/ */
const char * const * addon_message_table; /* Non-library errors */ const char * const * addon_message_table; /* Non-library errors */
int first_addon_message; /* code for first string in addon table */ int first_addon_message; /* code for first string in addon table */
int last_addon_message; /* code for last string in addon table */ int last_addon_message; /* code for last string in addon table */
}; };
@@ -806,18 +808,18 @@ struct jpeg_error_mgr {
struct jpeg_progress_mgr { struct jpeg_progress_mgr {
void (*progress_monitor) (j_common_ptr cinfo); void (*progress_monitor) (j_common_ptr cinfo);
long pass_counter; /* work units completed in this pass */ long pass_counter; /* work units completed in this pass */
long pass_limit; /* total number of work units in this pass */ long pass_limit; /* total number of work units in this pass */
int completed_passes; /* passes completed so far */ int completed_passes; /* passes completed so far */
int total_passes; /* total number of passes expected */ int total_passes; /* total number of passes expected */
}; };
/* Data destination object for compression */ /* Data destination object for compression */
struct jpeg_destination_mgr { struct jpeg_destination_mgr {
JOCTET * next_output_byte; /* => next byte to write in buffer */ JOCTET * next_output_byte; /* => next byte to write in buffer */
size_t free_in_buffer; /* # of byte spaces remaining in buffer */ size_t free_in_buffer; /* # of byte spaces remaining in buffer */
void (*init_destination) (j_compress_ptr cinfo); void (*init_destination) (j_compress_ptr cinfo);
boolean (*empty_output_buffer) (j_compress_ptr cinfo); boolean (*empty_output_buffer) (j_compress_ptr cinfo);
@@ -829,7 +831,7 @@ struct jpeg_destination_mgr {
struct jpeg_source_mgr { struct jpeg_source_mgr {
const JOCTET * next_input_byte; /* => next byte to read from buffer */ const JOCTET * next_input_byte; /* => next byte to read from buffer */
size_t bytes_in_buffer; /* # of bytes remaining in buffer */ size_t bytes_in_buffer; /* # of bytes remaining in buffer */
void (*init_source) (j_decompress_ptr cinfo); void (*init_source) (j_decompress_ptr cinfo);
boolean (*fill_input_buffer) (j_decompress_ptr cinfo); boolean (*fill_input_buffer) (j_decompress_ptr cinfo);
@@ -850,9 +852,9 @@ struct jpeg_source_mgr {
* successful. * successful.
*/ */
#define JPOOL_PERMANENT 0 /* lasts until master record is destroyed */ #define JPOOL_PERMANENT 0 /* lasts until master record is destroyed */
#define JPOOL_IMAGE 1 /* lasts until done with image/datastream */ #define JPOOL_IMAGE 1 /* lasts until done with image/datastream */
#define JPOOL_NUMPOOLS 2 #define JPOOL_NUMPOOLS 2
typedef struct jvirt_sarray_control * jvirt_sarray_ptr; typedef struct jvirt_sarray_control * jvirt_sarray_ptr;
typedef struct jvirt_barray_control * jvirt_barray_ptr; typedef struct jvirt_barray_control * jvirt_barray_ptr;
@@ -868,14 +870,14 @@ struct jpeg_memory_mgr {
JBLOCKARRAY (*alloc_barray) (j_common_ptr cinfo, int pool_id, JBLOCKARRAY (*alloc_barray) (j_common_ptr cinfo, int pool_id,
JDIMENSION blocksperrow, JDIMENSION numrows); JDIMENSION blocksperrow, JDIMENSION numrows);
jvirt_sarray_ptr (*request_virt_sarray) (j_common_ptr cinfo, int pool_id, jvirt_sarray_ptr (*request_virt_sarray) (j_common_ptr cinfo, int pool_id,
boolean pre_zero, boolean pre_zero,
JDIMENSION samplesperrow, JDIMENSION samplesperrow,
JDIMENSION numrows, JDIMENSION numrows,
JDIMENSION maxaccess); JDIMENSION maxaccess);
jvirt_barray_ptr (*request_virt_barray) (j_common_ptr cinfo, int pool_id, jvirt_barray_ptr (*request_virt_barray) (j_common_ptr cinfo, int pool_id,
boolean pre_zero, boolean pre_zero,
JDIMENSION blocksperrow, JDIMENSION blocksperrow,
JDIMENSION numrows, JDIMENSION numrows,
JDIMENSION maxaccess); JDIMENSION maxaccess);
void (*realize_virt_arrays) (j_common_ptr cinfo); void (*realize_virt_arrays) (j_common_ptr cinfo);
JSAMPARRAY (*access_virt_sarray) (j_common_ptr cinfo, jvirt_sarray_ptr ptr, JSAMPARRAY (*access_virt_sarray) (j_common_ptr cinfo, jvirt_sarray_ptr ptr,
@@ -917,10 +919,10 @@ EXTERN(struct jpeg_error_mgr *) jpeg_std_error (struct jpeg_error_mgr * err);
*/ */
#define jpeg_create_compress(cinfo) \ #define jpeg_create_compress(cinfo) \
jpeg_CreateCompress((cinfo), JPEG_LIB_VERSION, \ jpeg_CreateCompress((cinfo), JPEG_LIB_VERSION, \
(size_t) sizeof(struct jpeg_compress_struct)) (size_t) sizeof(struct jpeg_compress_struct))
#define jpeg_create_decompress(cinfo) \ #define jpeg_create_decompress(cinfo) \
jpeg_CreateDecompress((cinfo), JPEG_LIB_VERSION, \ jpeg_CreateDecompress((cinfo), JPEG_LIB_VERSION, \
(size_t) sizeof(struct jpeg_decompress_struct)) (size_t) sizeof(struct jpeg_decompress_struct))
EXTERN(void) jpeg_CreateCompress (j_compress_ptr cinfo, int version, EXTERN(void) jpeg_CreateCompress (j_compress_ptr cinfo, int version,
size_t structsize); size_t structsize);
EXTERN(void) jpeg_CreateDecompress (j_decompress_ptr cinfo, int version, EXTERN(void) jpeg_CreateDecompress (j_decompress_ptr cinfo, int version,
@@ -957,9 +959,10 @@ EXTERN(void) jpeg_default_qtables (j_compress_ptr cinfo,
boolean force_baseline); boolean force_baseline);
#endif #endif
EXTERN(void) jpeg_add_quant_table (j_compress_ptr cinfo, int which_tbl, EXTERN(void) jpeg_add_quant_table (j_compress_ptr cinfo, int which_tbl,
const unsigned int *basic_table, const unsigned int *basic_table,
int scale_factor, boolean force_baseline); int scale_factor, boolean force_baseline);
EXTERN(int) jpeg_quality_scaling (int quality); EXTERN(int) jpeg_quality_scaling (int quality);
EXTERN(float) jpeg_float_quality_scaling (float quality);
EXTERN(void) jpeg_simple_progression (j_compress_ptr cinfo); EXTERN(void) jpeg_simple_progression (j_compress_ptr cinfo);
EXTERN(void) jpeg_suppress_tables (j_compress_ptr cinfo, boolean suppress); EXTERN(void) jpeg_suppress_tables (j_compress_ptr cinfo, boolean suppress);
EXTERN(JQUANT_TBL *) jpeg_alloc_quant_table (j_common_ptr cinfo); EXTERN(JQUANT_TBL *) jpeg_alloc_quant_table (j_common_ptr cinfo);
@@ -969,7 +972,7 @@ EXTERN(JHUFF_TBL *) jpeg_alloc_huff_table (j_common_ptr cinfo);
EXTERN(void) jpeg_start_compress (j_compress_ptr cinfo, EXTERN(void) jpeg_start_compress (j_compress_ptr cinfo,
boolean write_all_tables); boolean write_all_tables);
EXTERN(JDIMENSION) jpeg_write_scanlines (j_compress_ptr cinfo, EXTERN(JDIMENSION) jpeg_write_scanlines (j_compress_ptr cinfo,
JSAMPARRAY scanlines, JSAMPARRAY scanlines,
JDIMENSION num_lines); JDIMENSION num_lines);
EXTERN(void) jpeg_finish_compress (j_compress_ptr cinfo); EXTERN(void) jpeg_finish_compress (j_compress_ptr cinfo);
@@ -996,9 +999,9 @@ EXTERN(void) jpeg_write_tables (j_compress_ptr cinfo);
/* Decompression startup: read start of JPEG datastream to see what's there */ /* Decompression startup: read start of JPEG datastream to see what's there */
EXTERN(int) jpeg_read_header (j_decompress_ptr cinfo, boolean require_image); EXTERN(int) jpeg_read_header (j_decompress_ptr cinfo, boolean require_image);
/* Return value is one of: */ /* Return value is one of: */
#define JPEG_SUSPENDED 0 /* Suspended due to lack of input data */ #define JPEG_SUSPENDED 0 /* Suspended due to lack of input data */
#define JPEG_HEADER_OK 1 /* Found valid image datastream */ #define JPEG_HEADER_OK 1 /* Found valid image datastream */
#define JPEG_HEADER_TABLES_ONLY 2 /* Found valid table-specs-only datastream */ #define JPEG_HEADER_TABLES_ONLY 2 /* Found valid table-specs-only datastream */
/* If you pass require_image = TRUE (normal case), you need not check for /* If you pass require_image = TRUE (normal case), you need not check for
* a TABLES_ONLY return code; an abbreviated file will cause an error exit. * a TABLES_ONLY return code; an abbreviated file will cause an error exit.
* JPEG_SUSPENDED is only possible if you use a data source module that can * JPEG_SUSPENDED is only possible if you use a data source module that can
@@ -1008,7 +1011,7 @@ EXTERN(int) jpeg_read_header (j_decompress_ptr cinfo, boolean require_image);
/* Main entry points for decompression */ /* Main entry points for decompression */
EXTERN(boolean) jpeg_start_decompress (j_decompress_ptr cinfo); EXTERN(boolean) jpeg_start_decompress (j_decompress_ptr cinfo);
EXTERN(JDIMENSION) jpeg_read_scanlines (j_decompress_ptr cinfo, EXTERN(JDIMENSION) jpeg_read_scanlines (j_decompress_ptr cinfo,
JSAMPARRAY scanlines, JSAMPARRAY scanlines,
JDIMENSION max_lines); JDIMENSION max_lines);
EXTERN(boolean) jpeg_finish_decompress (j_decompress_ptr cinfo); EXTERN(boolean) jpeg_finish_decompress (j_decompress_ptr cinfo);
@@ -1024,11 +1027,11 @@ EXTERN(boolean) jpeg_input_complete (j_decompress_ptr cinfo);
EXTERN(void) jpeg_new_colormap (j_decompress_ptr cinfo); EXTERN(void) jpeg_new_colormap (j_decompress_ptr cinfo);
EXTERN(int) jpeg_consume_input (j_decompress_ptr cinfo); EXTERN(int) jpeg_consume_input (j_decompress_ptr cinfo);
/* Return value is one of: */ /* Return value is one of: */
/* #define JPEG_SUSPENDED 0 Suspended due to lack of input data */ /* #define JPEG_SUSPENDED 0 Suspended due to lack of input data */
#define JPEG_REACHED_SOS 1 /* Reached start of new scan */ #define JPEG_REACHED_SOS 1 /* Reached start of new scan */
#define JPEG_REACHED_EOI 2 /* Reached end of image */ #define JPEG_REACHED_EOI 2 /* Reached end of image */
#define JPEG_ROW_COMPLETED 3 /* Completed one iMCU row */ #define JPEG_ROW_COMPLETED 3 /* Completed one iMCU row */
#define JPEG_SCAN_COMPLETED 4 /* Completed last iMCU row of a scan */ #define JPEG_SCAN_COMPLETED 4 /* Completed last iMCU row of a scan */
/* Precalculate output dimensions for current decompression parameters. */ /* Precalculate output dimensions for current decompression parameters. */
#if JPEG_LIB_VERSION >= 80 #if JPEG_LIB_VERSION >= 80
@@ -1075,10 +1078,10 @@ EXTERN(boolean) jpeg_resync_to_restart (j_decompress_ptr cinfo, int desired);
* are likely to want to use them. * are likely to want to use them.
*/ */
#define JPEG_RST0 0xD0 /* RST0 marker code */ #define JPEG_RST0 0xD0 /* RST0 marker code */
#define JPEG_EOI 0xD9 /* EOI marker code */ #define JPEG_EOI 0xD9 /* EOI marker code */
#define JPEG_APP0 0xE0 /* APP0 marker code */ #define JPEG_APP0 0xE0 /* APP0 marker code */
#define JPEG_COM 0xFE /* COM marker code */ #define JPEG_COM 0xFE /* COM marker code */
/* If we have a brain-damaged compiler that emits warnings (or worse, errors) /* If we have a brain-damaged compiler that emits warnings (or worse, errors)
@@ -1087,7 +1090,7 @@ EXTERN(boolean) jpeg_resync_to_restart (j_decompress_ptr cinfo, int desired);
*/ */
#ifdef INCOMPLETE_TYPES_BROKEN #ifdef INCOMPLETE_TYPES_BROKEN
#ifndef JPEG_INTERNALS /* will be defined in jpegint.h */ #ifndef JPEG_INTERNALS /* will be defined in jpegint.h */
struct jvirt_sarray_control { long dummy; }; struct jvirt_sarray_control { long dummy; };
struct jvirt_barray_control { long dummy; }; struct jvirt_barray_control { long dummy; };
struct jpeg_comp_master { long dummy; }; struct jpeg_comp_master { long dummy; };
@@ -1122,8 +1125,8 @@ struct jpeg_color_quantizer { long dummy; };
*/ */
#ifdef JPEG_INTERNALS #ifdef JPEG_INTERNALS
#include "jpegint.h" /* fetch private declarations */ #include "jpegint.h" /* fetch private declarations */
#include "jerror.h" /* fetch error codes too */ #include "jerror.h" /* fetch error codes too */
#endif #endif
#ifdef __cplusplus #ifdef __cplusplus

View File

@@ -104,11 +104,19 @@ int main(int argc, char *argv[]) {
yuv_size = luma_width*luma_height + 2*chroma_width*chroma_height; yuv_size = luma_width*luma_height + 2*chroma_width*chroma_height;
yuv_buffer = malloc(yuv_size); yuv_buffer = malloc(yuv_size);
if (!yuv_buffer) {
fprintf(stderr, "Memory allocation failure!\n");
return 1;
}
frame_width = (cinfo.output_width + (16 - 1)) & ~(16 - 1); frame_width = (cinfo.output_width + (16 - 1)) & ~(16 - 1);
frame_height = (cinfo.output_height + (16 - 1)) & ~(16 - 1); frame_height = (cinfo.output_height + (16 - 1)) & ~(16 - 1);
image_buffer = malloc(frame_width*16 + 2*(frame_width/2)*8); image_buffer = malloc(frame_width*16 + 2*(frame_width/2)*8);
if (!image_buffer) {
fprintf(stderr, "Memory allocation failure!\n");
return 1;
}
plane_pointer[0] = yrow_pointer; plane_pointer[0] = yrow_pointer;
plane_pointer[1] = cbrow_pointer; plane_pointer[1] = cbrow_pointer;

116
rdpng.c Normal file
View File

@@ -0,0 +1,116 @@
#include "cdjpeg.h" /* Common decls for cjpeg/djpeg applications */
#ifdef PNG_SUPPORTED
#include <png.h> /* if this fails, you need to install libpng-devel */
typedef struct png_source_struct {
struct cjpeg_source_struct pub;
png_structp png_ptr;
png_infop info_ptr;
JDIMENSION current_row;
} png_source_struct;
METHODDEF(void)
finish_input_png (j_compress_ptr cinfo, cjpeg_source_ptr sinfo);
METHODDEF(JDIMENSION)
get_pixel_rows_png (j_compress_ptr cinfo, cjpeg_source_ptr sinfo);
METHODDEF(void)
start_input_png (j_compress_ptr cinfo, cjpeg_source_ptr sinfo);
GLOBAL(cjpeg_source_ptr)
jinit_read_png(j_compress_ptr cinfo)
{
png_source_struct *source = (*cinfo->mem->alloc_small)((j_common_ptr) cinfo, JPOOL_IMAGE, sizeof(png_source_struct));
memset(source, 0, sizeof(*source));
/* Fill in method ptrs, except get_pixel_rows which start_input sets */
source->pub.start_input = start_input_png;
source->pub.finish_input = finish_input_png;
return &source->pub;
}
METHODDEF(void) error_input_png(png_structp png_ptr, png_const_charp msg) {
j_compress_ptr cinfo = png_get_error_ptr(png_ptr);
ERREXITS(cinfo, JERR_PNG_ERROR, msg);
}
METHODDEF(void)
start_input_png (j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
{
png_source_struct *source = (png_source_struct *)sinfo;
source->png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, cinfo, error_input_png, NULL);
source->info_ptr = png_create_info_struct(source->png_ptr);
if (!source->png_ptr || !source->info_ptr) {
ERREXITS(cinfo, JERR_PNG_ERROR, "Can't create read/info_struct");
return;
}
png_set_palette_to_rgb(source->png_ptr);
png_set_expand_gray_1_2_4_to_8(source->png_ptr);
png_set_strip_alpha(source->png_ptr);
png_set_interlace_handling(source->png_ptr);
png_init_io(source->png_ptr, source->pub.input_file);
png_read_info(source->png_ptr, source->info_ptr);
png_uint_32 width, height;
int bit_depth, color_type;
png_get_IHDR(source->png_ptr, source->info_ptr, &width, &height,
&bit_depth, &color_type, NULL, NULL, NULL);
if (color_type == PNG_COLOR_TYPE_GRAY) {
cinfo->in_color_space = JCS_GRAYSCALE;
cinfo->input_components = 1;
} else {
cinfo->in_color_space = JCS_RGB;
cinfo->input_components = 3;
}
cinfo->data_precision = 8;
cinfo->image_width = width;
cinfo->image_height = height;
double gamma = 0.45455;
if (!png_get_valid(source->png_ptr, source->info_ptr, PNG_INFO_sRGB)) {
png_get_gAMA(source->png_ptr, source->info_ptr, &gamma);
}
cinfo->input_gamma = gamma;
sinfo->get_pixel_rows = get_pixel_rows_png;
png_read_update_info(source->png_ptr, source->info_ptr);
png_size_t rowbytes = png_get_rowbytes(source->png_ptr, source->info_ptr);
source->pub.buffer = (*cinfo->mem->alloc_sarray)((j_common_ptr)cinfo, JPOOL_IMAGE, (JDIMENSION)rowbytes, 1);
source->pub.buffer_height = 1;
}
METHODDEF(JDIMENSION)
get_pixel_rows_png (j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
{
png_source_struct *source = (png_source_struct *)sinfo;
png_read_row(source->png_ptr, source->pub.buffer[0], NULL);
return 1;
}
METHODDEF(void)
finish_input_png (j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
{
png_source_struct *source = (png_source_struct *)sinfo;
png_read_end(source->png_ptr, source->info_ptr);
png_destroy_read_struct(&source->png_ptr, &source->info_ptr, NULL);
}
#endif

View File

@@ -9,15 +9,15 @@
* *
* This file contains routines to process some of cjpeg's more complicated * This file contains routines to process some of cjpeg's more complicated
* command-line switches. Switches processed here are: * command-line switches. Switches processed here are:
* -qtables file Read quantization tables from text file * -qtables file Read quantization tables from text file
* -scans file Read scan script from text file * -scans file Read scan script from text file
* -quality N[,N,...] Set quality ratings * -quality N[,N,...] Set quality ratings
* -qslots N[,N,...] Set component quantization table selectors * -qslots N[,N,...] Set component quantization table selectors
* -sample HxV[,HxV,...] Set component sampling factors * -sample HxV[,HxV,...] Set component sampling factors
*/ */
#include "cdjpeg.h" /* Common decls for cjpeg/djpeg applications */ #include "cdjpeg.h" /* Common decls for cjpeg/djpeg applications */
#include <ctype.h> /* to declare isdigit(), isspace() */ #include <ctype.h> /* to declare isdigit(), isspace() */
LOCAL(int) LOCAL(int)
@@ -108,15 +108,15 @@ read_quant_tables (j_compress_ptr cinfo, char * filename, boolean force_baseline
table[0] = (unsigned int) val; table[0] = (unsigned int) val;
for (i = 1; i < DCTSIZE2; i++) { for (i = 1; i < DCTSIZE2; i++) {
if (! read_text_integer(fp, &val, &termchar)) { if (! read_text_integer(fp, &val, &termchar)) {
fprintf(stderr, "Invalid table data in file %s\n", filename); fprintf(stderr, "Invalid table data in file %s\n", filename);
fclose(fp); fclose(fp);
return FALSE; return FALSE;
} }
table[i] = (unsigned int) val; table[i] = (unsigned int) val;
} }
#if JPEG_LIB_VERSION >= 70 #if JPEG_LIB_VERSION >= 70
jpeg_add_quant_table(cinfo, tblno, table, cinfo->q_scale_factor[tblno], jpeg_add_quant_table(cinfo, tblno, table, cinfo->q_scale_factor[tblno],
force_baseline); force_baseline);
#else #else
jpeg_add_quant_table(cinfo, tblno, table, q_scale_factor[tblno], jpeg_add_quant_table(cinfo, tblno, table, q_scale_factor[tblno],
force_baseline); force_baseline);
@@ -150,7 +150,7 @@ read_scan_integer (FILE * file, long * result, int * termchar)
ch = *termchar; ch = *termchar;
while (ch != EOF && isspace(ch)) while (ch != EOF && isspace(ch))
ch = text_getc(file); ch = text_getc(file);
if (isdigit(ch)) { /* oops, put it back */ if (isdigit(ch)) { /* oops, put it back */
if (ungetc(ch, file) == EOF) if (ungetc(ch, file) == EOF)
return FALSE; return FALSE;
ch = ' '; ch = ' ';
@@ -188,7 +188,7 @@ read_scan_script (j_compress_ptr cinfo, char * filename)
int scanno, ncomps, termchar; int scanno, ncomps, termchar;
long val; long val;
jpeg_scan_info * scanptr; jpeg_scan_info * scanptr;
#define MAX_SCANS 100 /* quite arbitrary limit */ #define MAX_SCANS 100 /* quite arbitrary limit */
jpeg_scan_info scans[MAX_SCANS]; jpeg_scan_info scans[MAX_SCANS];
if ((fp = fopen(filename, "r")) == NULL) { if ((fp = fopen(filename, "r")) == NULL) {
@@ -208,29 +208,29 @@ read_scan_script (j_compress_ptr cinfo, char * filename)
ncomps = 1; ncomps = 1;
while (termchar == ' ') { while (termchar == ' ') {
if (ncomps >= MAX_COMPS_IN_SCAN) { if (ncomps >= MAX_COMPS_IN_SCAN) {
fprintf(stderr, "Too many components in one scan in file %s\n", fprintf(stderr, "Too many components in one scan in file %s\n",
filename); filename);
fclose(fp); fclose(fp);
return FALSE; return FALSE;
} }
if (! read_scan_integer(fp, &val, &termchar)) if (! read_scan_integer(fp, &val, &termchar))
goto bogus; goto bogus;
scanptr->component_index[ncomps] = (int) val; scanptr->component_index[ncomps] = (int) val;
ncomps++; ncomps++;
} }
scanptr->comps_in_scan = ncomps; scanptr->comps_in_scan = ncomps;
if (termchar == ':') { if (termchar == ':') {
if (! read_scan_integer(fp, &val, &termchar) || termchar != ' ') if (! read_scan_integer(fp, &val, &termchar) || termchar != ' ')
goto bogus; goto bogus;
scanptr->Ss = (int) val; scanptr->Ss = (int) val;
if (! read_scan_integer(fp, &val, &termchar) || termchar != ' ') if (! read_scan_integer(fp, &val, &termchar) || termchar != ' ')
goto bogus; goto bogus;
scanptr->Se = (int) val; scanptr->Se = (int) val;
if (! read_scan_integer(fp, &val, &termchar) || termchar != ' ') if (! read_scan_integer(fp, &val, &termchar) || termchar != ' ')
goto bogus; goto bogus;
scanptr->Ah = (int) val; scanptr->Ah = (int) val;
if (! read_scan_integer(fp, &val, &termchar)) if (! read_scan_integer(fp, &val, &termchar))
goto bogus; goto bogus;
scanptr->Al = (int) val; scanptr->Al = (int) val;
} else { } else {
/* set non-progressive parameters */ /* set non-progressive parameters */
@@ -320,11 +320,11 @@ jpeg_default_qtables (j_compress_ptr cinfo, boolean force_baseline)
jpeg_add_quant_table(cinfo, 1, flat_quant_tbl, jpeg_add_quant_table(cinfo, 1, flat_quant_tbl,
q_scale_factor[1], force_baseline); q_scale_factor[1], force_baseline);
} else { } else {
jpeg_add_quant_table(cinfo, 0, std_luminance_quant_tbl, jpeg_add_quant_table(cinfo, 0, std_luminance_quant_tbl,
q_scale_factor[0], force_baseline); q_scale_factor[0], force_baseline);
jpeg_add_quant_table(cinfo, 1, std_chrominance_quant_tbl, jpeg_add_quant_table(cinfo, 1, std_chrominance_quant_tbl,
q_scale_factor[1], force_baseline); q_scale_factor[1], force_baseline);
} }
} }
#endif #endif
@@ -336,31 +336,31 @@ set_quality_ratings (j_compress_ptr cinfo, char *arg, boolean force_baseline)
* If there are more q-table slots than parameters, the last value is replicated. * If there are more q-table slots than parameters, the last value is replicated.
*/ */
{ {
int val = 75; /* default value */ float val = 75.f; /* default value */
int tblno; int tblno;
char ch; char ch;
for (tblno = 0; tblno < NUM_QUANT_TBLS; tblno++) { for (tblno = 0; tblno < NUM_QUANT_TBLS; tblno++) {
if (*arg) { if (*arg) {
ch = ','; /* if not set by sscanf, will be ',' */ ch = ','; /* if not set by sscanf, will be ',' */
if (sscanf(arg, "%d%c", &val, &ch) < 1) if (sscanf(arg, "%f%c", &val, &ch) < 1)
return FALSE; return FALSE;
if (ch != ',') /* syntax check */ if (ch != ',') /* syntax check */
return FALSE; return FALSE;
/* Convert user 0-100 rating to percentage scaling */ /* Convert user 0-100 rating to percentage scaling */
#if JPEG_LIB_VERSION >= 70 #if JPEG_LIB_VERSION >= 70
cinfo->q_scale_factor[tblno] = jpeg_quality_scaling(val); cinfo->q_scale_factor[tblno] = jpeg_float_quality_scaling(val);
#else #else
q_scale_factor[tblno] = jpeg_quality_scaling(val); q_scale_factor[tblno] = jpeg_float_quality_scaling(val);
#endif #endif
while (*arg && *arg++ != ',') /* advance to next segment of arg string */ while (*arg && *arg++ != ',') /* advance to next segment of arg string */
; ;
} else { } else {
/* reached end of parameter, set remaining factors to last value */ /* reached end of parameter, set remaining factors to last value */
#if JPEG_LIB_VERSION >= 70 #if JPEG_LIB_VERSION >= 70
cinfo->q_scale_factor[tblno] = jpeg_quality_scaling(val); cinfo->q_scale_factor[tblno] = jpeg_float_quality_scaling(val);
#else #else
q_scale_factor[tblno] = jpeg_quality_scaling(val); q_scale_factor[tblno] = jpeg_float_quality_scaling(val);
#endif #endif
} }
} }
@@ -376,25 +376,25 @@ set_quant_slots (j_compress_ptr cinfo, char *arg)
* If there are more components than parameters, the last value is replicated. * If there are more components than parameters, the last value is replicated.
*/ */
{ {
int val = 0; /* default table # */ int val = 0; /* default table # */
int ci; int ci;
char ch; char ch;
for (ci = 0; ci < MAX_COMPONENTS; ci++) { for (ci = 0; ci < MAX_COMPONENTS; ci++) {
if (*arg) { if (*arg) {
ch = ','; /* if not set by sscanf, will be ',' */ ch = ','; /* if not set by sscanf, will be ',' */
if (sscanf(arg, "%d%c", &val, &ch) < 1) if (sscanf(arg, "%d%c", &val, &ch) < 1)
return FALSE; return FALSE;
if (ch != ',') /* syntax check */ if (ch != ',') /* syntax check */
return FALSE; return FALSE;
if (val < 0 || val >= NUM_QUANT_TBLS) { if (val < 0 || val >= NUM_QUANT_TBLS) {
fprintf(stderr, "JPEG quantization tables are numbered 0..%d\n", fprintf(stderr, "JPEG quantization tables are numbered 0..%d\n",
NUM_QUANT_TBLS-1); NUM_QUANT_TBLS-1);
return FALSE; return FALSE;
} }
cinfo->comp_info[ci].quant_tbl_no = val; cinfo->comp_info[ci].quant_tbl_no = val;
while (*arg && *arg++ != ',') /* advance to next segment of arg string */ while (*arg && *arg++ != ',') /* advance to next segment of arg string */
; ;
} else { } else {
/* reached end of parameter, set remaining components to last table */ /* reached end of parameter, set remaining components to last table */
cinfo->comp_info[ci].quant_tbl_no = val; cinfo->comp_info[ci].quant_tbl_no = val;
@@ -416,19 +416,19 @@ set_sample_factors (j_compress_ptr cinfo, char *arg)
for (ci = 0; ci < MAX_COMPONENTS; ci++) { for (ci = 0; ci < MAX_COMPONENTS; ci++) {
if (*arg) { if (*arg) {
ch2 = ','; /* if not set by sscanf, will be ',' */ ch2 = ','; /* if not set by sscanf, will be ',' */
if (sscanf(arg, "%d%c%d%c", &val1, &ch1, &val2, &ch2) < 3) if (sscanf(arg, "%d%c%d%c", &val1, &ch1, &val2, &ch2) < 3)
return FALSE; return FALSE;
if ((ch1 != 'x' && ch1 != 'X') || ch2 != ',') /* syntax check */ if ((ch1 != 'x' && ch1 != 'X') || ch2 != ',') /* syntax check */
return FALSE; return FALSE;
if (val1 <= 0 || val1 > 4 || val2 <= 0 || val2 > 4) { if (val1 <= 0 || val1 > 4 || val2 <= 0 || val2 > 4) {
fprintf(stderr, "JPEG sampling factors must be 1..4\n"); fprintf(stderr, "JPEG sampling factors must be 1..4\n");
return FALSE; return FALSE;
} }
cinfo->comp_info[ci].h_samp_factor = val1; cinfo->comp_info[ci].h_samp_factor = val1;
cinfo->comp_info[ci].v_samp_factor = val2; cinfo->comp_info[ci].v_samp_factor = val2;
while (*arg && *arg++ != ',') /* advance to next segment of arg string */ while (*arg && *arg++ != ',') /* advance to next segment of arg string */
; ;
} else { } else {
/* reached end of parameter, set remaining components to 1x1 sampling */ /* reached end of parameter, set remaining components to 1x1 sampling */
cinfo->comp_info[ci].h_samp_factor = 1; cinfo->comp_info[ci].h_samp_factor = 1;

View File

@@ -41,11 +41,9 @@
/* Supplementary macro for setting function attributes */ /* Supplementary macro for setting function attributes */
.macro asm_function fname .macro asm_function fname
#ifdef __APPLE__ #ifdef __APPLE__
.func _\fname
.globl _\fname .globl _\fname
_\fname: _\fname:
#else #else
.func \fname
.global \fname .global \fname
#ifdef __ELF__ #ifdef __ELF__
.hidden \fname .hidden \fname
@@ -670,7 +668,6 @@ asm_function jsimd_idct_islow_neon
.unreq ROW6R .unreq ROW6R
.unreq ROW7L .unreq ROW7L
.unreq ROW7R .unreq ROW7R
.endfunc
/*****************************************************************************/ /*****************************************************************************/
@@ -895,7 +892,6 @@ asm_function jsimd_idct_ifast_neon
.unreq TMP2 .unreq TMP2
.unreq TMP3 .unreq TMP3
.unreq TMP4 .unreq TMP4
.endfunc
/*****************************************************************************/ /*****************************************************************************/
@@ -1108,7 +1104,6 @@ asm_function jsimd_idct_4x4_neon
.unreq TMP2 .unreq TMP2
.unreq TMP3 .unreq TMP3
.unreq TMP4 .unreq TMP4
.endfunc
.purgem idct_helper .purgem idct_helper
@@ -1263,7 +1258,6 @@ asm_function jsimd_idct_2x2_neon
.unreq OUTPUT_COL .unreq OUTPUT_COL
.unreq TMP1 .unreq TMP1
.unreq TMP2 .unreq TMP2
.endfunc
.purgem idct_helper .purgem idct_helper
@@ -1547,7 +1541,6 @@ asm_function jsimd_ycc_\colorid\()_convert_neon
.unreq U .unreq U
.unreq V .unreq V
.unreq N .unreq N
.endfunc
.purgem do_yuv_to_rgb .purgem do_yuv_to_rgb
.purgem do_yuv_to_rgb_stage1 .purgem do_yuv_to_rgb_stage1
@@ -1858,7 +1851,6 @@ asm_function jsimd_\colorid\()_ycc_convert_neon
.unreq U .unreq U
.unreq V .unreq V
.unreq N .unreq N
.endfunc
.purgem do_rgb_to_yuv .purgem do_rgb_to_yuv
.purgem do_rgb_to_yuv_stage1 .purgem do_rgb_to_yuv_stage1
@@ -1940,7 +1932,6 @@ asm_function jsimd_convsamp_neon
.unreq TMP2 .unreq TMP2
.unreq TMP3 .unreq TMP3
.unreq TMP4 .unreq TMP4
.endfunc
/*****************************************************************************/ /*****************************************************************************/
@@ -2064,7 +2055,6 @@ asm_function jsimd_fdct_ifast_neon
.unreq DATA .unreq DATA
.unreq TMP .unreq TMP
.endfunc
/*****************************************************************************/ /*****************************************************************************/
@@ -2166,7 +2156,6 @@ asm_function jsimd_quantize_neon
.unreq CORRECTION .unreq CORRECTION
.unreq SHIFT .unreq SHIFT
.unreq LOOP_COUNT .unreq LOOP_COUNT
.endfunc
/*****************************************************************************/ /*****************************************************************************/
@@ -2401,7 +2390,6 @@ asm_function jsimd_h2v1_fancy_upsample_neon
.unreq WIDTH .unreq WIDTH
.unreq TMP .unreq TMP
.endfunc
.purgem upsample16 .purgem upsample16
.purgem upsample32 .purgem upsample32

View File

@@ -179,6 +179,11 @@ int main(int argc, char *argv[]) {
} }
yuv_buffer = malloc(yuv_size); yuv_buffer = malloc(yuv_size);
if (!yuv_buffer) {
fprintf(stderr, "Memory allocation failure!\n");
return 1;
}
if (fread(yuv_buffer, yuv_size, 1, yuv_fd) != 1) { if (fread(yuv_buffer, yuv_size, 1, yuv_fd) != 1) {
fprintf(stderr, "Error reading yuv file\n"); fprintf(stderr, "Error reading yuv file\n");
}; };
@@ -190,6 +195,10 @@ int main(int argc, char *argv[]) {
image_buffer = image_buffer =
malloc(frame_width*frame_height + 2*(frame_width/2)*(frame_height/2)); malloc(frame_width*frame_height + 2*(frame_width/2)*(frame_height/2));
if (!image_buffer) {
fprintf(stderr, "Memory allocation failure!\n");
return 1;
}
extend_edge(image_buffer, frame_width, frame_height, extend_edge(image_buffer, frame_width, frame_height,
yuv_buffer, luma_width, luma_height, chroma_width, chroma_height); yuv_buffer, luma_width, luma_height, chroma_width, chroma_height);
@@ -202,6 +211,7 @@ int main(int argc, char *argv[]) {
jpg_fd = fopen(jpg_path, "wb"); jpg_fd = fopen(jpg_path, "wb");
if (!jpg_fd) { if (!jpg_fd) {
fprintf(stderr, "Invalid path to JPEG file!\n"); fprintf(stderr, "Invalid path to JPEG file!\n");
free(image_buffer);
return 1; return 1;
} }