Skip to content

Commit

Permalink
Add option for setting luminance & chrominance quality independently …
Browse files Browse the repository at this point in the history
…(currently only works if using libjpeg v7 or v8 code base)

git-svn-id: svn+ssh://svn.code.sf.net/p/libjpeg-turbo/code/trunk@248 632fc199-4ca6-4c93-a231-07263d6284db
  • Loading branch information
dcommander committed Oct 10, 2010
2 parents 2cdd2ae + a4ecaac commit 294079c
Show file tree
Hide file tree
Showing 4 changed files with 98 additions and 30 deletions.
5 changes: 4 additions & 1 deletion cdjpeg.h
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,7 @@ typedef struct cdjpeg_progress_mgr * cd_progress_ptr;
#define jinit_write_targa jIWrTarga
#define read_quant_tables RdQTables
#define read_scan_script RdScnScript
#define set_quality_ratings SetQRates
#define set_quant_slots SetQSlots
#define set_sample_factors SetSFacts
#define read_color_map RdCMap
Expand Down Expand Up @@ -131,8 +132,10 @@ EXTERN(djpeg_dest_ptr) jinit_write_targa JPP((j_decompress_ptr cinfo));
/* cjpeg support routines (in rdswitch.c) */

EXTERN(boolean) read_quant_tables JPP((j_compress_ptr cinfo, char * filename,
int scale_factor, boolean force_baseline));
boolean force_baseline));
EXTERN(boolean) read_scan_script JPP((j_compress_ptr cinfo, char * filename));
EXTERN(boolean) set_quality_ratings JPP((j_compress_ptr cinfo, char *arg,
boolean force_baseline));
EXTERN(boolean) set_quant_slots JPP((j_compress_ptr cinfo, char *arg));
EXTERN(boolean) set_sample_factors JPP((j_compress_ptr cinfo, char *arg));

Expand Down
40 changes: 31 additions & 9 deletions cjpeg.1
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
.TH CJPEG 1 "20 March 1998"
.TH CJPEG 1 "30 December 2009"
.SH NAME
cjpeg \- compress an image file to a JPEG file
.SH SYNOPSIS
Expand Down Expand Up @@ -36,7 +36,7 @@ though for brevity these are not mentioned below.
.PP
The basic switches are:
.TP
.BI \-quality " N"
.BI \-quality " N[,...]"
Scale quantization tables to adjust image quality. Quality is 0 (worst) to
100 (best); default is 75. (See below for more info.)
.TP
Expand Down Expand Up @@ -109,6 +109,34 @@ other JPEG programs may be unable to decode the resulting file. Use
if you need to ensure compatibility at low quality values.)
.PP
The
.B \-quality
option has been extended in IJG version 7 for support of separate quality
settings for luminance and chrominance (or in general, for every provided
quantization table slot). This feature is useful for high-quality
applications which cannot accept the damage of color data by coarse
subsampling settings. You can now easily reduce the color data amount more
smoothly with finer control without separate subsampling. The resulting file
is fully compliant with standard JPEG decoders.
Note that the
.B \-quality
ratings refer to the quantization table slots, and that the last value is
replicated if there are more q-table slots than parameters. The default
q-table slots are 0 for luminance and 1 for chrominance with default tables as
given in the JPEG standard. This is compatible with the old behaviour in case
that only one parameter is given, which is then used for both luminance and
chrominance (slots 0 and 1). More or custom quantization tables can be set
with
.B \-qtables
and assigned to components with
.B \-qslots
parameter (see the "wizard" switches below).
.B Caution:
You must explicitly add
.BI \-sample " 1x1"
for efficient separate color
quality selection, since the default value used by library is 2x2!
.PP
The
.B \-progressive
switch creates a "progressive JPEG" file. In this type of JPEG file, the data
is stored in multiple scans of increasing quality. If the file is being
Expand All @@ -117,9 +145,6 @@ scan to display a low-quality image very quickly, and can then improve the
display with each subsequent scan. The final image is exactly equivalent to a
standard JPEG file of the same quality setting, and the total file size is
about the same --- often a little smaller.
.B Caution:
progressive JPEG is not yet widely implemented, so many decoders will be
unable to view a progressive JPEG file at all.
.PP
Switches for advanced users:
.TP
Expand Down Expand Up @@ -279,14 +304,11 @@ Independent JPEG Group
Arithmetic coding is not supported for legal reasons.
.PP
GIF input files are no longer supported, to avoid the Unisys LZW patent.
Use a Unisys-licensed program if you need to read a GIF file. (Conversion
of GIF files to JPEG is usually a bad idea anyway.)
(Conversion of GIF files to JPEG is usually a bad idea anyway.)
.PP
Not all variants of BMP and Targa file formats are supported.
.PP
The
.B \-targa
switch is not a bug, it's a feature. (It would be a bug if the Targa format
designers had not been clueless.)
.PP
Still not as fast as we'd like.
28 changes: 11 additions & 17 deletions cjpeg.c
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
* cjpeg.c
*
* Copyright (C) 1991-1998, Thomas G. Lane.
* Modified 2003-2008 by Guido Vollbeding.
* Copyright (C) 2010, D. R. Commander.
* This file is part of the Independent JPEG Group's software.
* For conditions of distribution and use, see the accompanying README file.
Expand Down Expand Up @@ -151,7 +152,7 @@ usage (void)
#endif

fprintf(stderr, "Switches (names may be abbreviated):\n");
fprintf(stderr, " -quality N Compression quality (0..100; 5-95 is useful range)\n");
fprintf(stderr, " -quality N[,...] Compression quality (0..100; 5-95 is useful range)\n");
fprintf(stderr, " -grayscale Create monochrome JPEG file\n");
#ifdef ENTROPY_OPT_SUPPORTED
fprintf(stderr, " -optimize Optimize Huffman table (smaller file, but slow compression)\n");
Expand Down Expand Up @@ -211,21 +212,16 @@ parse_switches (j_compress_ptr cinfo, int argc, char **argv,
{
int argn;
char * arg;
int quality; /* -quality parameter */
int q_scale_factor; /* scaling percentage for -qtables */
boolean force_baseline;
boolean simple_progressive;
char * qualityarg = NULL; /* saves -quality parm if any */
char * qtablefile = NULL; /* saves -qtables filename if any */
char * qslotsarg = NULL; /* saves -qslots parm if any */
char * samplearg = NULL; /* saves -sample parm if any */
char * scansarg = NULL; /* saves -scans parm if any */

/* Set up default JPEG parameters. */
/* Note that default -quality level need not, and does not,
* match the default scaling for an explicit -qtables argument.
*/
quality = 75; /* default -quality value */
q_scale_factor = 100; /* default to no scaling for -qtables */

force_baseline = FALSE; /* by default, allow 16-bit quantizers */
simple_progressive = FALSE;
is_targa = FALSE;
Expand Down Expand Up @@ -333,13 +329,10 @@ parse_switches (j_compress_ptr cinfo, int argc, char **argv,
#endif

} else if (keymatch(arg, "quality", 1)) {
/* Quality factor (quantization table scaling factor). */
/* Quality ratings (quantization table scaling factors). */
if (++argn >= argc) /* advance to next argument */
usage();
if (sscanf(argv[argn], "%d", &quality) != 1)
usage();
/* Change scale factor in case -qtables is present. */
q_scale_factor = jpeg_quality_scaling(quality);
qualityarg = argv[argn];

} else if (keymatch(arg, "qslots", 2)) {
/* Quantization table slot numbers. */
Expand Down Expand Up @@ -387,7 +380,7 @@ parse_switches (j_compress_ptr cinfo, int argc, char **argv,
* default sampling factors.
*/

} else if (keymatch(arg, "scans", 2)) {
} else if (keymatch(arg, "scans", 4)) {
/* Set scan script. */
#ifdef C_MULTISCAN_FILES_SUPPORTED
if (++argn >= argc) /* advance to next argument */
Expand Down Expand Up @@ -427,11 +420,12 @@ parse_switches (j_compress_ptr cinfo, int argc, char **argv,

/* Set quantization tables for selected quality. */
/* Some or all may be overridden if -qtables is present. */
jpeg_set_quality(cinfo, quality, force_baseline);
if (qualityarg != NULL) /* process -quality if it was present */
if (! set_quality_ratings(cinfo, qualityarg, force_baseline))
usage();

if (qtablefile != NULL) /* process -qtables if it was present */
if (! read_quant_tables(cinfo, qtablefile,
q_scale_factor, force_baseline))
if (! read_quant_tables(cinfo, qtablefile, force_baseline))
usage();

if (qslotsarg != NULL) /* process -qslots if it was present */
Expand Down
55 changes: 52 additions & 3 deletions rdswitch.c
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
* command-line switches. Switches processed here are:
* -qtables file Read quantization tables from text file
* -scans file Read scan script from text file
* -quality N[,N,...] Set quality ratings
* -qslots N[,N,...] Set component quantization table selectors
* -sample HxV[,HxV,...] Set component sampling factors
*/
Expand Down Expand Up @@ -69,9 +70,12 @@ read_text_integer (FILE * file, long * result, int * termchar)
}


#if JPEG_LIB_VERSION < 70
static int q_scale_factor = 100;
#endif

GLOBAL(boolean)
read_quant_tables (j_compress_ptr cinfo, char * filename,
int scale_factor, boolean force_baseline)
read_quant_tables (j_compress_ptr cinfo, char * filename, boolean force_baseline)
/* Read a set of quantization tables from the specified file.
* The file is plain ASCII text: decimal numbers with whitespace between.
* Comments preceded by '#' may be included in the file.
Expand Down Expand Up @@ -108,7 +112,12 @@ read_quant_tables (j_compress_ptr cinfo, char * filename,
}
table[i] = (unsigned int) val;
}
jpeg_add_quant_table(cinfo, tblno, table, scale_factor, force_baseline);
#if JPEG_LIB_VERSION >= 70
jpeg_add_quant_table(cinfo, tblno, table, cinfo->q_scale_factor[tblno],
force_baseline);
#else
jpeg_add_quant_table(cinfo, tblno, table, q_scale_factor, force_baseline);
#endif
tblno++;
}

Expand Down Expand Up @@ -262,6 +271,46 @@ read_scan_script (j_compress_ptr cinfo, char * filename)
#endif /* C_MULTISCAN_FILES_SUPPORTED */


GLOBAL(boolean)
set_quality_ratings (j_compress_ptr cinfo, char *arg, boolean force_baseline)
/* Process a quality-ratings parameter string, of the form
* N[,N,...]
* If there are more q-table slots than parameters, the last value is replicated.
*/
{
int val = 75; /* default value */
int tblno;
char ch;

for (tblno = 0; tblno < NUM_QUANT_TBLS; tblno++) {
if (*arg) {
ch = ','; /* if not set by sscanf, will be ',' */
if (sscanf(arg, "%d%c", &val, &ch) < 1)
return FALSE;
if (ch != ',') /* syntax check */
return FALSE;
/* Convert user 0-100 rating to percentage scaling */
#if JPEG_LIB_VERSION >= 70
cinfo->q_scale_factor[tblno] = jpeg_quality_scaling(val);
#endif
while (*arg && *arg++ != ',') /* advance to next segment of arg string */
;
} else {
/* reached end of parameter, set remaining factors to last value */
#if JPEG_LIB_VERSION >= 70
cinfo->q_scale_factor[tblno] = jpeg_quality_scaling(val);
#endif
}
}
#if JPEG_LIB_VERSION >= 70
jpeg_default_qtables(cinfo, force_baseline);
#else
jpeg_set_quality(cinfo, val, force_baseline);
#endif
return TRUE;
}


GLOBAL(boolean)
set_quant_slots (j_compress_ptr cinfo, char *arg)
/* Process a quantization-table-selectors parameter string, of the form
Expand Down

0 comments on commit 294079c

Please sign in to comment.