From cc7150e281999ac2642e21f13e2c160f68b1d675 Mon Sep 17 00:00:00 2001 From: "Thomas G. Lane" Date: Thu, 18 Feb 1993 00:00:00 +0000 Subject: [PATCH] The Independent JPEG Group's JPEG software v4a --- CHANGELOG | 24 ++++++ README | 14 ++-- SETUP | 52 ++++++++++--- USAGE | 10 ++- djpeg.1 | 8 +- example.c | 2 +- jcdeflts.c | 6 +- jchuff.c | 19 ++--- jcmain.c | 97 ++++++++++++++++------- jcmcu.c | 44 +++++++---- jconfig.h | 6 +- jdcolor.c | 12 ++- jddeflts.c | 24 +++++- jdhuff.c | 191 +++++++++++++++++++++++++++++++-------------- jdmain.c | 99 ++++++++++++++++------- jdmaster.c | 35 +++++---- jdmcu.c | 11 ++- jdpipe.c | 14 +++- jinclude.h | 2 +- jmemdos.c | 75 +++++++++++------- jmemmgr.c | 2 +- jpegdata.h | 51 +++++++++--- jquant1.c | 141 +++++++++++++++++++-------------- jquant2.c | 212 +++++++++++++++++++++++++++++--------------------- jrdjfif.c | 54 +++++++++---- jrdppm.c | 2 +- jversion.h | 6 +- jwrgif.c | 6 +- jwrjfif.c | 27 ++++++- jwrppm.c | 4 +- jwrrle.c | 4 +- jwrtarga.c | 4 +- makefile.ansi | 3 +- makefile.bcc | 18 +++-- makefile.icc | 141 +++++++++++++++++++++++++++++++++ makefile.manx | 9 ++- makefile.mc5 | 3 +- makefile.mc6 | 21 +++-- makefile.mms | 3 +- makefile.sas | 37 +++++---- makefile.unix | 3 +- makljpeg.icc | 38 +++++++++ 42 files changed, 1083 insertions(+), 451 deletions(-) create mode 100644 makefile.icc create mode 100644 makljpeg.icc diff --git a/CHANGELOG b/CHANGELOG index 02c63dc..ccbc6ea 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,5 +1,29 @@ CHANGELOG for Independent JPEG Group's JPEG software + +Version 4A 18-Feb-93 +-------------------- + +Substantial speedup for grayscale output from color JPEG file (suppress +processing of chrominance components). Lesser speedups in Huffman decoding +and in compression quantization. + +Can switch stdin/stdout to binary mode with either fdopen() or setmode(); +this allows use of one-file command line style on a wider range of systems. +Also added -outfile switch so that makefile test scripts don't have to depend +on the command line style. + +New makefile.icc for Code Builder; makefile.sas is updated for SAS C 6.x. + +Hook added to allow surrounding application to read and write COM (comment) +blocks. + +Bugfixes (DOS only): jmemdos.c code for accessing expanded memory only worked +if struct fields are packed on byte boundaries. This is not true by default +for Microsoft C. Furthermore, Microsoft C needs an _fheapmin() call to clean +up the far heap correctly. + + Version 4 10-Dec-92 -------------------- diff --git a/README b/README index 9223de2..99c4d36 100644 --- a/README +++ b/README @@ -1,10 +1,10 @@ The Independent JPEG Group's JPEG software ========================================== -README for release 4 of 10-Dec-92 -================================= +README for release 4A of 18-Feb-93 +================================== -This distribution contains the fourth public release of the Independent JPEG +This distribution contains a BETA TEST release of the Independent JPEG Group's free JPEG software. You are welcome to redistribute this software and to use it for any purpose, subject to the conditions under LEGAL ISSUES, below. @@ -24,8 +24,9 @@ larger programs) should contact jpeg-info@uunet.uu.net to be added to our electronic mailing list. Mailing list members are notified of updates and have a chance to participate in technical discussions, etc. -This software is the work of Tom Lane, Philip Gladstone, Luis Ortiz, -Lee Crocker, Ge' Weijers, and other members of the Independent JPEG Group. +This software is the work of Tom Lane, Philip Gladstone, Luis Ortiz, Lee +Crocker, George Phillips, Ge' Weijers, and other members of the Independent +JPEG Group. DISCLAIMER @@ -107,6 +108,9 @@ products; no royalty is required. ARCHIVE LOCATIONS ================= +[Version 4A is a beta-test release and will not be publicly archived. +The following paragraphs refer to the most recent official release.] + The "official" archive site for this software is ftp.uu.net (Internet address 137.39.1.9 or 192.48.96.9). The most recent released version can always be found there in directory graphics/jpeg. This particular version diff --git a/SETUP b/SETUP index dd633ae..85f0184 100644 --- a/SETUP +++ b/SETUP @@ -34,6 +34,7 @@ distribution: makefile.mc5: for Microsoft C 5.x under MS-DOS. makefile.mc6: for Microsoft C 6.x and up under MS-DOS. makefile.bcc: for Borland C (Turbo C) under MS-DOS. + makefile.icc: for Intel's Code Builder C under MS-DOS. makefile.manx: for Manx Aztec C on Amigas. makefile.sas: for SAS C on Amigas. makcjpeg.st: project file for Atari ST/STE/TT Pure C or Turbo C. @@ -101,7 +102,10 @@ If it's not defined, the output image goes to standard output, and the input can optionally come from standard input. You MUST use two-file style on any system that doesn't cope well with binary data fed through stdin/stdout; this is true for most MS-DOS compilers, for example. If you're not on a Unix -system, it's probably safest to assume you need two-file style. +system, it's probably safest to assume you need two-file style. (But if your +compiler provides either the Posix-standard fdopen() library routine or a +Microsoft-compatible setmode() routine, you can use the Unix command line +style, by defining USE_FDOPEN or USE_SETMODE respectively.) STEP 3: SELECT SYSTEM-DEPENDENT FILES @@ -197,8 +201,13 @@ generate duplicates of the testimg.* files then you probably have working programs. With most of the makefiles, "make test" will perform the necessary -comparisons. If you're using a makefile that doesn't provide this option, run -djpeg and cjpeg to generate testout.ppm, testout.gif, and testout.jpg, then +comparisons. If you started with makefile.ansi or makefile.unix, and you +defined TWO_FILE_COMMANDLINE, then change the makefile's test script to use +two-file syntax (i.e., delete the ">" character from the invocations of cjpeg +and djpeg). The other makefiles will work with either command-line syntax. + +If you're using a makefile that doesn't provide the test option, run djpeg and +cjpeg by hand to generate testout.ppm, testout.gif, and testout.jpg, then compare these to testimg.* with whatever binary file comparison tool you have. The files should be bit-for-bit identical. @@ -206,6 +215,13 @@ If the cjpeg test run fails with "Missing Huffman code table entry", it's a good bet that you needed to define RIGHT_SHIFT_IS_UNSIGNED. Go back to step 2 and run ckconfig.c. (This is a good plan for any other test failure, too.) +If you are using Unix (one-file) command line style on a non-Unix system, +it's a good idea to check that binary I/O through stdin/stdout actually works. +You should get the same results from "djpeg out.ppm" as from +"djpeg -outfile out.ppm testorig.jpg". Note that the non-Unix makefiles use +the latter style and therefore do not exercise stdin/stdout. If this test +fails, try recompiling jcmain.c & jdmain.c with USE_SETMODE and/or USE_FDOPEN. + If your choice of jmemsys.c was anything other than jmemnobs.c, you should test that temporary-file usage works. Try "djpeg -gif -max 0 testorig.jpg" and make sure its output matches testimg.gif. If you have any really large @@ -227,7 +243,10 @@ corresponding manual directory. (The makefiles don't support this step since there's such a wide variety of installation procedures on different systems.) To learn to use the programs, read the file USAGE (or manual pages cjpeg(1) -and djpeg(1) on Unix). +and djpeg(1) on Unix). Note that the man pages cjpeg.1/djpeg.1 only describe +the Unix-style command line syntax; if you want to use these files with a +version that uses two-file command line syntax, you'll have to modify the text +accordingly. The USAGE file describes both styles. OPTIMIZATION @@ -373,7 +392,7 @@ compiler bug in Cray's Standard C versions prior to 3.1. You'll need to insert a line reading "#pragma novector" just before the loop for (i = 1; i <= (int) htbl->bits[l]; i++) huffsize[p++] = (char) l; -in fix_huff_tbl (in V3, line 42 of jchuff.c and line 38 of jdhuff.c). The +in fix_huff_tbl (in V4A, line 42 of jchuff.c and line 39 of jdhuff.c). The usual symptom of not adding this line is a core-dump. See Cray's SPR 48222. @@ -461,9 +480,13 @@ jmemdos.c. Use jmemnobs.c if the environment supplies adequate virtual memory, otherwise use jmemansi.c or jmemname.c. Most MS-DOS compilers treat stdin/stdout as text files, so you must use -two-file command line style. But if your compiler has the setmode() library -routine, you can define USE_SETMODE to get one-file style. (Don't forget to -change the "make test" script in the Makefile if you do so.) +two-file command line style. But if your compiler has either fdopen() or +setmode(), you can use one-file style if you like. To do this, define +USE_FDOPEN or USE_SETMODE so that stdin/stdout will be set to binary mode. +(USE_SETMODE seems to work with more DOS compilers than USE_FDOPEN.) You +should test that I/O through stdin/stdout produces the same results as I/O +to explicitly named files... the "make test" procedures in the DOS-specific +makefiles do NOT use stdin/stdout. If you add more switches to CFLAGS in the DOS-specific makefiles, you are likely to run up against DOS' 128-byte command line length limit. In that @@ -482,16 +505,18 @@ Some versions of Borland's MAKE erroneously display the warning message about creating jmemsys.c, even after you have done so. If this happens to you, delete the four lines beginning with "jmemsys.c:" from the Makefile. +If you want one-file command line style, define USE_SETMODE. fdopen() does +not work correctly. + MS-DOS, DJGPP: Use makefile.ansi and jmemnobs.c, and put "-UMSDOS" in CFLAGS to undo the compiler's automatic definition of MSDOS. Also put either "-DUSE_SETMODE" or "-DTWO_FILE_COMMANDLINE" in CFLAGS, depending on whether you prefer one-file -or two-file command line style. (If you choose two-file style, change the -"make test" section of the Makefile accordingly.) You'll also need to put the -object-file lists into response files in order to circumvent DOS's 128-byte -command line length limit at the final linking step. +or two-file command line style. You'll also need to put the object-file lists +into response files in order to circumvent DOS's 128-byte command line length +limit at the final linking step. MS-DOS, Microsoft C: @@ -507,6 +532,9 @@ optimization (remove -O from CFLAGS). That problem seems to have been fixed in 6.00A and later versions. 6.00A still generates a bogus "conditional expression is constant" warning in jrdppm.c, but the emitted code seems OK. +If you want one-file command line style, define USE_SETMODE. fdopen() does +not work correctly, at least not in 6.00A. + SGI: diff --git a/USAGE b/USAGE index ebce6df..76044f8 100644 --- a/USAGE +++ b/USAGE @@ -52,6 +52,12 @@ style is a little more foolproof, and it loses no functionality if you don't have pipes. (You can get this style on Unix too, if you prefer, by defining TWO_FILE_COMMANDLINE when you compile the programs; see SETUP.) +You can also say: + cjpeg [switches] -outfile jpegfile imagefile +or + djpeg [switches] -outfile imagefile jpegfile +This syntax works on all systems, so it is useful for scripts. + The currently supported image file formats are: PPM (PBMPLUS color format), PGM (PBMPLUS gray-scale format), GIF, Targa, and RLE (Utah Raster Toolkit format). (RLE is supported only if the URT library is available.) @@ -212,8 +218,8 @@ The basic command line switches for djpeg are: Switches for advanced users: - -blocksmooth Perform cross-block smoothing. This is quite - memory-intensive and only seems to improve the image + -blocksmooth Perform cross-block smoothing. This is slow, quite + memory-intensive, and only seems to improve the image at very low quality settings (-quality 10 to 20 or so). At normal quality settings it may make things worse. diff --git a/djpeg.1 b/djpeg.1 index be5a815..7f45074 100644 --- a/djpeg.1 +++ b/djpeg.1 @@ -1,4 +1,4 @@ -.TH DJPEG 1 "2 August 1992" +.TH DJPEG 1 "17 February 1993" .SH NAME djpeg \- decompress a JPEG file to an image file .SH SYNOPSIS @@ -107,9 +107,9 @@ is specified; otherwise, 24-bit full-color format is emitted. Switches for advanced users: .TP .B \-blocksmooth -Perform cross-block smoothing. This is quite memory-intensive and only seems -to improve the image at very low quality settings (\fB\-quality\fR 10 to 20 or -so). At normal quality settings it may make the image worse. +Perform cross-block smoothing. This is slow, quite memory-intensive, and only +seems to improve the image at very low quality settings (\fB\-quality\fR 10 to +20 or so). At normal quality settings it may make the image worse. .TP .B \-grayscale Force gray-scale output even if JPEG file is color. diff --git a/example.c b/example.c index 3e7a5dd..666dd6f 100644 --- a/example.c +++ b/example.c @@ -340,7 +340,7 @@ error_exit (const char *msgtext) * Colormapped mode is also useful for reducing grayscale output to a small * number of gray levels: when using the 1-pass quantizer on grayscale data, * the colormap entries will be evenly spaced from 0 to MAX_JSAMPLE, so you - * can regard the indexes are directly representing gray levels at reduced + * can regard the indexes as directly representing gray levels at reduced * precision. In any other case, you should not depend on the colormap * entries having any particular order. * To get colormapped output, set cinfo->quantize_colors to TRUE and set diff --git a/jcdeflts.c b/jcdeflts.c index 48f4ed4..eddba20 100644 --- a/jcdeflts.c +++ b/jcdeflts.c @@ -1,7 +1,7 @@ /* * jcdeflts.c * - * Copyright (C) 1991, 1992, Thomas G. Lane. + * Copyright (C) 1991, 1992, 1993, Thomas G. Lane. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * @@ -298,9 +298,11 @@ j_c_defaults (compress_info_ptr cinfo, int quality, boolean force_baseline) cinfo->input_gamma = 1.0; /* no gamma correction by default */ + cinfo->write_JFIF_header = TRUE; /* write a JFIF marker */ + cinfo->comment_text = NULL; /* but no COM block */ + /* Prepare three color components; first is luminance which is also usable */ /* for grayscale. The others are assumed to be UV or similar chrominance. */ - cinfo->write_JFIF_header = TRUE; cinfo->jpeg_color_space = CS_YCbCr; cinfo->num_components = 3; cinfo->comp_info = (jpeg_component_info *) diff --git a/jchuff.c b/jchuff.c index 3f657db..9eb558a 100644 --- a/jchuff.c +++ b/jchuff.c @@ -1,7 +1,7 @@ /* * jchuff.c * - * Copyright (C) 1991, 1992, Thomas G. Lane. + * Copyright (C) 1991, 1992, 1993, Thomas G. Lane. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * @@ -66,15 +66,12 @@ fix_huff_tbl (HUFF_TBL * htbl) /* Set any codeless symbols to have code length 0; * this allows emit_bits to detect any attempt to emit such symbols. */ - MEMZERO(htbl->ehufsi, SIZEOF(htbl->ehufsi)); + MEMZERO(htbl->priv.enc.ehufsi, SIZEOF(htbl->priv.enc.ehufsi)); for (p = 0; p < lastp; p++) { - htbl->ehufco[htbl->huffval[p]] = huffcode[p]; - htbl->ehufsi[htbl->huffval[p]] = huffsize[p]; + htbl->priv.enc.ehufco[htbl->huffval[p]] = huffcode[p]; + htbl->priv.enc.ehufsi[htbl->huffval[p]] = huffsize[p]; } - - /* We don't bother to fill in the decoding tables mincode[], maxcode[], */ - /* and valptr[], since they are not used for encoding. */ } @@ -179,7 +176,7 @@ encode_one_block (JBLOCK block, HUFF_TBL *dctbl, HUFF_TBL *actbl) } /* Emit the Huffman-coded symbol for the number of bits */ - emit_bits(dctbl->ehufco[nbits], dctbl->ehufsi[nbits]); + emit_bits(dctbl->priv.enc.ehufco[nbits], dctbl->priv.enc.ehufsi[nbits]); /* Emit that number of bits of the value, if positive, */ /* or the complement of its magnitude, if negative. */ @@ -196,7 +193,7 @@ encode_one_block (JBLOCK block, HUFF_TBL *dctbl, HUFF_TBL *actbl) } else { /* if run length > 15, must emit special run-length-16 codes (0xF0) */ while (r > 15) { - emit_bits(actbl->ehufco[0xF0], actbl->ehufsi[0xF0]); + emit_bits(actbl->priv.enc.ehufco[0xF0], actbl->priv.enc.ehufsi[0xF0]); r -= 16; } @@ -214,7 +211,7 @@ encode_one_block (JBLOCK block, HUFF_TBL *dctbl, HUFF_TBL *actbl) /* Emit Huffman symbol for run length / number of bits */ i = (r << 4) + nbits; - emit_bits(actbl->ehufco[i], actbl->ehufsi[i]); + emit_bits(actbl->priv.enc.ehufco[i], actbl->priv.enc.ehufsi[i]); /* Emit that number of bits of the value, if positive, */ /* or the complement of its magnitude, if negative. */ @@ -226,7 +223,7 @@ encode_one_block (JBLOCK block, HUFF_TBL *dctbl, HUFF_TBL *actbl) /* If the last coef(s) were zero, emit an end-of-block code */ if (r > 0) - emit_bits(actbl->ehufco[0], actbl->ehufsi[0]); + emit_bits(actbl->priv.enc.ehufco[0], actbl->priv.enc.ehufsi[0]); } diff --git a/jcmain.c b/jcmain.c index fd6d831..03d24fc 100644 --- a/jcmain.c +++ b/jcmain.c @@ -1,7 +1,7 @@ /* * jcmain.c * - * Copyright (C) 1991, 1992, Thomas G. Lane. + * Copyright (C) 1991, 1992, 1993, Thomas G. Lane. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * @@ -18,6 +18,9 @@ * The second style is convenient on Unix but is unhelpful on systems that * don't support pipes. Also, you MUST use the first style if your system * doesn't do binary I/O to stdin/stdout. + * To simplify script writing, the "-outfile" switch is provided. The syntax + * cjpeg [options] -outfile outputfile inputfile + * works regardless of which command line style is used. */ #include "jinclude.h" @@ -218,6 +221,7 @@ progress_monitor (compress_info_ptr cinfo, long loopcounter, long looplimit) static char * progname; /* program name for error messages */ +static char * outfilename; /* for -outfile switch */ LOCAL void @@ -448,6 +452,7 @@ parse_switches (compress_info_ptr cinfo, int last_file_arg_seen, */ j_c_defaults(cinfo, 75, FALSE); /* default quality level = 75 */ is_targa = FALSE; + outfilename = NULL; /* Scan command line options, adjust parameters */ @@ -455,8 +460,10 @@ parse_switches (compress_info_ptr cinfo, int last_file_arg_seen, arg = argv[argn]; if (*arg != '-') { /* Not a switch, must be a file name argument */ - if (argn <= last_file_arg_seen) - continue; /* ignore it if previously processed */ + if (argn <= last_file_arg_seen) { + outfilename = NULL; /* -outfile applies to just one input file */ + continue; /* ignore this name if previously processed */ + } break; /* else done parsing switches */ } arg++; /* advance past switch marker character */ @@ -516,6 +523,12 @@ parse_switches (compress_info_ptr cinfo, int last_file_arg_seen, exit(EXIT_FAILURE); #endif + } else if (keymatch(arg, "outfile", 3)) { + /* Set output file name. */ + if (++argn >= argc) /* advance to next argument */ + usage(); + outfilename = argv[argn]; /* save it away for later use */ + } else if (keymatch(arg, "quality", 1)) { /* Quality factor (quantization table scaling factor). */ int val; @@ -624,47 +637,75 @@ main (int argc, char **argv) #endif #endif - /* Scan command line: set up compression parameters, input & output files. */ + /* Scan command line: set up compression parameters, find file names. */ file_index = parse_switches(&cinfo, 0, argc, argv); #ifdef TWO_FILE_COMMANDLINE - - if (file_index != argc-2) { - fprintf(stderr, "%s: must name one input and one output file\n", progname); - usage(); + /* Must have either -outfile switch or explicit output file name */ + if (outfilename == NULL) { + if (file_index != argc-2) { + fprintf(stderr, "%s: must name one input and one output file\n", + progname); + usage(); + } + outfilename = argv[file_index+1]; + } else { + if (file_index != argc-1) { + fprintf(stderr, "%s: must name one input and one output file\n", + progname); + usage(); + } } - if ((cinfo.input_file = fopen(argv[file_index], READ_BINARY)) == NULL) { - fprintf(stderr, "%s: can't open %s\n", progname, argv[file_index]); - exit(EXIT_FAILURE); - } - if ((cinfo.output_file = fopen(argv[file_index+1], WRITE_BINARY)) == NULL) { - fprintf(stderr, "%s: can't open %s\n", progname, argv[file_index+1]); - exit(EXIT_FAILURE); - } - -#else /* not TWO_FILE_COMMANDLINE -- use Unix style */ - - cinfo.input_file = stdin; /* default input file */ - cinfo.output_file = stdout; /* always the output file */ - -#ifdef USE_SETMODE /* need to hack file mode? */ - setmode(fileno(stdin), O_BINARY); - setmode(fileno(stdout), O_BINARY); -#endif - +#else + /* Unix style: expect zero or one file name */ if (file_index < argc-1) { fprintf(stderr, "%s: only one input file\n", progname); usage(); } +#endif /* TWO_FILE_COMMANDLINE */ + + /* Open the input file. */ if (file_index < argc) { if ((cinfo.input_file = fopen(argv[file_index], READ_BINARY)) == NULL) { fprintf(stderr, "%s: can't open %s\n", progname, argv[file_index]); exit(EXIT_FAILURE); } + } else { + /* default input file is stdin */ +#ifdef USE_SETMODE /* need to hack file mode? */ + setmode(fileno(stdin), O_BINARY); +#endif +#ifdef USE_FDOPEN /* need to re-open in binary mode? */ + if ((cinfo.input_file = fdopen(fileno(stdin), READ_BINARY)) == NULL) { + fprintf(stderr, "%s: can't open stdin\n", progname); + exit(EXIT_FAILURE); + } +#else + cinfo.input_file = stdin; +#endif } -#endif /* TWO_FILE_COMMANDLINE */ + /* Open the output file. */ + if (outfilename != NULL) { + if ((cinfo.output_file = fopen(outfilename, WRITE_BINARY)) == NULL) { + fprintf(stderr, "%s: can't open %s\n", progname, outfilename); + exit(EXIT_FAILURE); + } + } else { + /* default output file is stdout */ +#ifdef USE_SETMODE /* need to hack file mode? */ + setmode(fileno(stdout), O_BINARY); +#endif +#ifdef USE_FDOPEN /* need to re-open in binary mode? */ + if ((cinfo.output_file = fdopen(fileno(stdout), WRITE_BINARY)) == NULL) { + fprintf(stderr, "%s: can't open stdout\n", progname); + exit(EXIT_FAILURE); + } +#else + cinfo.output_file = stdout; +#endif + } /* Figure out the input file format, and set up to read it. */ select_file_type(&cinfo); diff --git a/jcmcu.c b/jcmcu.c index e921b49..524a54f 100644 --- a/jcmcu.c +++ b/jcmcu.c @@ -32,7 +32,7 @@ static int dctcoefcount; /* This will probably overflow on a 16-bit-int machine /* ZAG[i] is the natural-order position of the i'th element of zigzag order. */ -static const short ZAG[DCTSIZE2] = { +static const int ZAG[DCTSIZE2] = { 0, 1, 8, 16, 9, 2, 3, 10, 17, 24, 32, 25, 18, 11, 4, 5, 12, 19, 26, 33, 40, 48, 41, 34, @@ -58,9 +58,6 @@ extract_block (JSAMPARRAY input_data, int start_row, long start_col, { register JSAMPROW elemptr; register DCTELEM *localblkptr = block; -#if DCTSIZE != 8 - register int elemc; -#endif register int elemr; for (elemr = DCTSIZE; elemr > 0; elemr--) { @@ -75,8 +72,10 @@ extract_block (JSAMPARRAY input_data, int start_row, long start_col, *localblkptr++ = (DCTELEM) (GETJSAMPLE(*elemptr++) - CENTERJSAMPLE); *localblkptr++ = (DCTELEM) (GETJSAMPLE(*elemptr++) - CENTERJSAMPLE); #else - for (elemc = DCTSIZE; elemc > 0; elemc--) { - *localblkptr++ = (DCTELEM) (GETJSAMPLE(*elemptr++) - CENTERJSAMPLE); + { register int elemc; + for (elemc = DCTSIZE; elemc > 0; elemc--) { + *localblkptr++ = (DCTELEM) (GETJSAMPLE(*elemptr++) - CENTERJSAMPLE); + } } #endif } @@ -89,22 +88,39 @@ extract_block (JSAMPARRAY input_data, int start_row, long start_col, j_fwd_dct(block); { register JCOEF temp; - register short i; + register QUANT_VAL qval; + register int i; for (i = 0; i < DCTSIZE2; i++) { + qval = *quanttbl++; temp = (JCOEF) block[ZAG[i]]; - /* divide by *quanttbl, ensuring proper rounding */ + /* Divide the coefficient value by qval, ensuring proper rounding. + * Since C does not specify the direction of rounding for negative + * quotients, we have to force the dividend positive for portability. + * + * In most files, at least half of the output values will be zero + * (at default quantization settings, more like three-quarters...) + * so we should ensure that this case is fast. On many machines, + * a comparison is enough cheaper than a divide to make a special test + * a win. Since both inputs will be nonnegative, we need only test + * for a < b to discover whether a/b is 0. + * If your machine's division is fast enough, define FAST_DIVIDE. + */ +#ifdef FAST_DIVIDE +#define DIVIDE_BY(a,b) a /= b +#else +#define DIVIDE_BY(a,b) (a >= b) ? (a /= b) : (a = 0) +#endif if (temp < 0) { temp = -temp; - temp += *quanttbl>>1; - temp /= *quanttbl; + temp += qval>>1; /* for rounding */ + DIVIDE_BY(temp, qval); temp = -temp; } else { - temp += *quanttbl>>1; - temp /= *quanttbl; + temp += qval>>1; /* for rounding */ + DIVIDE_BY(temp, qval); } *output_data++ = temp; - quanttbl++; } } @@ -112,7 +128,7 @@ extract_block (JSAMPARRAY input_data, int start_row, long start_col, j_rev_dct(block); { register int diff; - register short i; + register int i; for (i = 0; i < DCTSIZE2; i++) { diff = block[i] - svblock[i]; diff --git a/jconfig.h b/jconfig.h index aeb29fe..60ca005 100644 --- a/jconfig.h +++ b/jconfig.h @@ -1,7 +1,7 @@ /* * jconfig.h * - * Copyright (C) 1991, 1992, Thomas G. Lane. + * Copyright (C) 1991, 1992, 1993, Thomas G. Lane. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * @@ -106,10 +106,12 @@ */ #ifdef MSDOS /* two-file style is needed for PCs */ -#ifndef USE_SETMODE /* unless you have setmode() */ +#ifndef USE_FDOPEN /* unless you have fdopen() or setmode() */ +#ifndef USE_SETMODE #define TWO_FILE_COMMANDLINE #endif #endif +#endif #ifdef THINK_C /* it's needed for Macintosh too */ #define TWO_FILE_COMMANDLINE #endif diff --git a/jdcolor.c b/jdcolor.c index fad9c73..f651c04 100644 --- a/jdcolor.c +++ b/jdcolor.c @@ -1,7 +1,7 @@ /* * jdcolor.c * - * Copyright (C) 1991, 1992, Thomas G. Lane. + * Copyright (C) 1991, 1992, 1993, Thomas G. Lane. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * @@ -223,6 +223,8 @@ null_term (decompress_info_ptr cinfo) GLOBAL void jseldcolor (decompress_info_ptr cinfo) { + int ci; + /* Make sure num_components agrees with jpeg_color_space */ switch (cinfo->jpeg_color_space) { case CS_GRAYSCALE: @@ -247,7 +249,10 @@ jseldcolor (decompress_info_ptr cinfo) break; } - /* Set color_out_comps and conversion method based on requested space */ + /* Set color_out_comps and conversion method based on requested space. */ + /* Also clear the component_needed flags for any unused components, */ + /* so that earlier pipeline stages can avoid useless computation. */ + switch (cinfo->out_color_space) { case CS_GRAYSCALE: cinfo->color_out_comps = 1; @@ -257,6 +262,9 @@ jseldcolor (decompress_info_ptr cinfo) cinfo->methods->color_convert = grayscale_convert; cinfo->methods->colorout_init = null_init; cinfo->methods->colorout_term = null_term; + /* For color->grayscale conversion, only the Y (0) component is needed */ + for (ci = 1; ci < cinfo->num_components; ci++) + cinfo->cur_comp_info[ci]->component_needed = FALSE; } else ERREXIT(cinfo->emethods, "Unsupported color conversion request"); break; diff --git a/jddeflts.c b/jddeflts.c index fde74d1..b8f1229 100644 --- a/jddeflts.c +++ b/jddeflts.c @@ -1,7 +1,7 @@ /* * jddeflts.c * - * Copyright (C) 1991, 1992, Thomas G. Lane. + * Copyright (C) 1991, 1992, 1993, Thomas G. Lane. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * @@ -42,6 +42,25 @@ progress_monitor (decompress_info_ptr cinfo, long loopcounter, long looplimit) } +/* Default comment-block processing routine. + * This can be overridden by an application that wishes to examine + * COM blocks found in the JPEG file. The default routine does nothing. + * CAUTION: the comment processing routine MUST call JGETC() exactly + * comment_length times to read the comment data, whether it intends + * to do anything with the data or not! + * Keep in mind that (a) there may be more than one COM block in a file; + * (b) there's no guarantee that what's in the block is ASCII data. + */ + +METHODDEF void +process_comment (decompress_info_ptr cinfo, long comment_length) +{ + while (comment_length-- > 0) { + (void) JGETC(cinfo); + } +} + + /* * Reload the input buffer after it's been emptied, and return the next byte. * See the JGETC macro for calling conditions. Note in particular that @@ -160,4 +179,7 @@ j_d_defaults (decompress_info_ptr cinfo, boolean standard_buffering) /* Install default do-nothing progress monitoring method. */ cinfo->methods->progress_monitor = progress_monitor; + + /* Install default comment-block processing method. */ + cinfo->methods->process_comment = process_comment; } diff --git a/jdhuff.c b/jdhuff.c index cdc9bd7..3ac46cf 100644 --- a/jdhuff.c +++ b/jdhuff.c @@ -1,7 +1,7 @@ /* * jdhuff.c * - * Copyright (C) 1991, 1992, Thomas G. Lane. + * Copyright (C) 1991, 1992, 1993, Thomas G. Lane. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * @@ -26,6 +26,7 @@ fix_huff_tbl (HUFF_TBL * htbl) /* Compute derived values for a Huffman table */ { int p, i, l, si; + int lookbits, ctr; char huffsize[257]; UINT16 huffcode[257]; UINT16 code; @@ -55,23 +56,43 @@ fix_huff_tbl (HUFF_TBL * htbl) si++; } - /* We don't bother to fill in the encoding tables ehufco[] and ehufsi[], */ - /* since they are not used for decoding. */ - - /* Figure F.15: generate decoding tables */ + /* Figure F.15: generate decoding tables for bit-sequential decoding */ p = 0; for (l = 1; l <= 16; l++) { if (htbl->bits[l]) { - htbl->valptr[l] = p; /* huffval[] index of 1st sym of code len l */ - htbl->mincode[l] = huffcode[p]; /* minimum code of length l */ + htbl->priv.dec.valptr[l] = p; /* huffval[] index of 1st symbol of code length l */ + htbl->priv.dec.mincode[l] = huffcode[p]; /* minimum code of length l */ p += htbl->bits[l]; - htbl->maxcode[l] = huffcode[p-1]; /* maximum code of length l */ + htbl->priv.dec.maxcode[l] = huffcode[p-1]; /* maximum code of length l */ } else { - htbl->maxcode[l] = -1; + htbl->priv.dec.maxcode[l] = -1; /* -1 if no codes of this length */ + } + } + htbl->priv.dec.maxcode[17] = 0xFFFFFL; /* ensures huff_DECODE terminates */ + + /* Compute lookahead tables to speed up decoding. + * First we set all the table entries to 0, indicating "too long"; + * then we iterate through the Huffman codes that are short enough and + * fill in all the entries that correspond to bit sequences starting + * with that code. + */ + + MEMZERO(htbl->priv.dec.look_nbits, SIZEOF(htbl->priv.dec.look_nbits)); + + p = 0; + for (l = 1; l <= HUFF_LOOKAHEAD; l++) { + for (i = 1; i <= (int) htbl->bits[l]; i++, p++) { + /* l = current code's length, p = its index in huffcode[] & huffval[]. */ + /* Generate left-justified code followed by all possible bit sequences */ + lookbits = huffcode[p] << (HUFF_LOOKAHEAD-l); + for (ctr = 1 << (HUFF_LOOKAHEAD-l); ctr > 0; ctr--) { + htbl->priv.dec.look_nbits[lookbits] = l; + htbl->priv.dec.look_sym[lookbits] = htbl->huffval[p]; + lookbits++; + } } } - htbl->maxcode[17] = 0xFFFFFL; /* ensures huff_DECODE terminates */ } @@ -82,11 +103,13 @@ fix_huff_tbl (HUFF_TBL * htbl) * * We read source bytes into get_buffer and dole out bits as needed. * If get_buffer already contains enough bits, they are fetched in-line - * by the macros get_bits() and get_bit(). When there aren't enough bits, - * fill_bit_buffer is called; it will attempt to fill get_buffer to the - * "high water mark", then extract the desired number of bits. The idea, - * of course, is to minimize the function-call overhead cost of entering - * fill_bit_buffer. + * by the macros check_bit_buffer and get_bits. When there aren't enough + * bits, fill_bit_buffer is called; it will attempt to fill get_buffer to + * the "high water mark" (not just to the number of bits needed; this reduces + * the function-call overhead cost of entering fill_bit_buffer). + * On return, fill_bit_buffer guarantees that get_buffer contains at least + * the requested number of bits --- dummy zeroes are inserted if necessary. + * * On most machines MIN_GET_BITS should be 25 to allow the full 32-bit width * of get_buffer to be used. (On machines with wider words, an even larger * buffer could be used.) However, on some machines 32-bit shifts are @@ -102,16 +125,13 @@ fix_huff_tbl (HUFF_TBL * htbl) #define MIN_GET_BITS 25 /* max value for 32-bit get_buffer */ #endif -static const int bmask[16] = /* bmask[n] is mask for n rightmost bits */ - { 0, 0x0001, 0x0003, 0x0007, 0x000F, 0x001F, 0x003F, 0x007F, 0x00FF, - 0x01FF, 0x03FF, 0x07FF, 0x0FFF, 0x1FFF, 0x3FFF, 0x7FFF }; - -LOCAL int +LOCAL void fill_bit_buffer (int nbits) -/* Load up the bit buffer and do get_bits(nbits) */ +/* Load up the bit buffer to a depth of at least nbits */ { /* Attempt to load at least MIN_GET_BITS bits into get_buffer. */ + /* (It is assumed that no request will be for more than that many bits.) */ while (bits_left < MIN_GET_BITS) { register int c = JGETC(dcinfo); @@ -128,10 +148,11 @@ fill_bit_buffer (int nbits) if (bits_left >= nbits) break; /* Uh-oh. Report corrupted data to user and stuff zeroes into - * the data stream, so we can produce some kind of image. + * the data stream, so that we can produce some kind of image. * Note that this will be repeated for each byte demanded for the * rest of the segment; this is a bit slow but not unreasonably so. - * The main thing is to avoid getting a zillion warnings, hence: + * The main thing is to avoid getting a zillion warnings, hence + * we use a flag to ensure that only one warning appears. */ if (! printed_eod) { WARNMS(dcinfo->emethods, "Corrupt JPEG data: premature end of data segment"); @@ -145,40 +166,81 @@ fill_bit_buffer (int nbits) get_buffer = (get_buffer << 8) | c; bits_left += 8; } - - /* Having filled get_buffer, extract desired bits (this simplifies macros) */ - bits_left -= nbits; - return ((int) (get_buffer >> bits_left)) & bmask[nbits]; } -/* Macros to make things go at some speed! */ -/* NB: parameter to get_bits should be simple variable, not expression */ +/* + * These macros provide the in-line portion of bit fetching. + * Correct usage is: + * check_bit_buffer(n); ensure there are N bits in get_buffer + * val = get_bits(n); fetch N bits + * The value n should be a simple variable, not an expression, because it + * is evaluated multiple times. + * peek_bits() fetches next N bits without removing them from the buffer. + */ + +#define check_bit_buffer(nbits) \ + { if (bits_left < (nbits)) fill_bit_buffer(nbits); } #define get_bits(nbits) \ - (bits_left >= (nbits) ? \ - ((int) (get_buffer >> (bits_left -= (nbits)))) & bmask[nbits] : \ - fill_bit_buffer(nbits)) + (((int) (get_buffer >> (bits_left -= (nbits)))) & ((1<<(nbits))-1)) -#define get_bit() \ - (bits_left ? \ - ((int) (get_buffer >> (--bits_left))) & 1 : \ - fill_bit_buffer(1)) +#define peek_bits(nbits) \ + (((int) (get_buffer >> (bits_left - (nbits)))) & ((1<<(nbits))-1)) -/* Figure F.16: extract next coded symbol from input stream */ +/* + * Routines to extract next Huffman-coded symbol from input bit stream. + * We use a lookahead table to process codes of up to HUFF_LOOKAHEAD bits + * without looping. Usually, more than 95% of the Huffman codes will be 8 + * or fewer bits long. The few overlength codes are handled with a loop. + * The primary case is made a macro for speed reasons; the secondary + * routine slow_DECODE is rarely entered and need not be inline code. + * + * Notes about the huff_DECODE macro: + * 1. The first if-test is coded to call fill_bit_buffer only when necessary. + * 2. If the lookahead succeeds, we need only decrement bits_left to remove + * the proper number of bits from get_buffer. + * 3. If the lookahead table contains no entry, the next code must be + * more than HUFF_LOOKAHEAD bits long. + * 4. Near the end of the data segment, we may fail to get enough bits + * for a lookahead. In that case, we do it the hard way. + */ + +#define huff_DECODE(htbl,result) \ +{ register int nb, look; \ + if (bits_left >= HUFF_LOOKAHEAD || \ + (fill_bit_buffer(0), bits_left >= HUFF_LOOKAHEAD)) { \ + look = peek_bits(HUFF_LOOKAHEAD); \ + if ((nb = htbl->priv.dec.look_nbits[look]) != 0) { \ + bits_left -= nb; \ + result = htbl->priv.dec.look_sym[look]; \ + } else \ + result = slow_DECODE(htbl, HUFF_LOOKAHEAD+1); \ + } else \ + result = slow_DECODE(htbl, 1); \ +} + -INLINE LOCAL int -huff_DECODE (HUFF_TBL * htbl) +slow_DECODE (HUFF_TBL * htbl, int min_bits) { - register int l; + register int l = min_bits; register INT32 code; - - code = get_bit(); - l = 1; - while (code > htbl->maxcode[l]) { - code = (code << 1) | get_bit(); + + /* huff_DECODE has determined that the code is at least min_bits */ + /* bits long, so fetch that many bits in one swoop. */ + + check_bit_buffer(l); + code = get_bits(l); + + /* Collect the rest of the Huffman code one bit at a time. */ + /* This is per Figure F.16 in the JPEG spec. */ + + while (code > htbl->priv.dec.maxcode[l]) { + code <<= 1; + check_bit_buffer(1); + code |= get_bits(1); l++; } @@ -189,11 +251,20 @@ huff_DECODE (HUFF_TBL * htbl) return 0; /* fake a zero as the safest result */ } - return htbl->huffval[ htbl->valptr[l] + ((int) (code - htbl->mincode[l])) ]; + return htbl->huffval[ htbl->priv.dec.valptr[l] + + ((int) (code - htbl->priv.dec.mincode[l])) ]; } -/* Figure F.12: extend sign bit */ +/* Figure F.12: extend sign bit. + * On some machines, a shift and add will be faster than a table lookup. + */ + +#ifdef AVOID_TABLES + +#define huff_EXTEND(x,s) ((x) < (1<<((s)-1)) ? (x) + (((-1)<<(s)) + 1) : (x)) + +#else #define huff_EXTEND(x,s) ((x) < extend_test[s] ? (x) + extend_offset[s] : (x)) @@ -207,6 +278,8 @@ static const int extend_offset[16] = /* entry n is (-1 << n) + 1 */ ((-1)<<9) + 1, ((-1)<<10) + 1, ((-1)<<11) + 1, ((-1)<<12) + 1, ((-1)<<13) + 1, ((-1)<<14) + 1, ((-1)<<15) + 1 }; +#endif /* AVOID_TABLES */ + /* * Initialize for a Huffman-compressed scan. @@ -214,7 +287,7 @@ static const int extend_offset[16] = /* entry n is (-1 << n) + 1 */ */ METHODDEF void -huff_decoder_init (decompress_info_ptr cinfo) +decoder_init (decompress_info_ptr cinfo) { short ci; jpeg_component_info * compptr; @@ -294,7 +367,7 @@ process_restart (decompress_info_ptr cinfo) /* ZAG[i] is the natural-order position of the i'th element of zigzag order. - * If the incoming data is corrupted, huff_decode_mcu could attempt to + * If the incoming data is corrupted, decode_mcu could attempt to * reference values beyond the end of the array. To avoid a wild store, * we put some extra zeroes after the real entries. */ @@ -324,7 +397,7 @@ static const short ZAG[DCTSIZE2+16] = { */ METHODDEF void -huff_decode_mcu (decompress_info_ptr cinfo, JBLOCKROW *MCU_data) +decode_mcu (decompress_info_ptr cinfo, JBLOCKROW *MCU_data) { register int s, k, r; short blkn, ci; @@ -354,8 +427,9 @@ huff_decode_mcu (decompress_info_ptr cinfo, JBLOCKROW *MCU_data) /* Decode a single block's worth of coefficients */ /* Section F.2.2.1: decode the DC coefficient difference */ - s = huff_DECODE(dctbl); + huff_DECODE(dctbl, s); if (s) { + check_bit_buffer(s); r = get_bits(s); s = huff_EXTEND(r, s); } @@ -369,13 +443,14 @@ huff_decode_mcu (decompress_info_ptr cinfo, JBLOCKROW *MCU_data) /* Section F.2.2.2: decode the AC coefficients */ /* Since zero values are skipped, output area must be zeroed beforehand */ for (k = 1; k < DCTSIZE2; k++) { - r = huff_DECODE(actbl); + huff_DECODE(actbl, s); - s = r & 15; - r = r >> 4; + r = s >> 4; + s &= 15; if (s) { k += r; + check_bit_buffer(s); r = get_bits(s); s = huff_EXTEND(r, s); /* Descale coefficient and output in natural (dezigzagged) order */ @@ -395,7 +470,7 @@ huff_decode_mcu (decompress_info_ptr cinfo, JBLOCKROW *MCU_data) */ METHODDEF void -huff_decoder_term (decompress_info_ptr cinfo) +decoder_term (decompress_info_ptr cinfo) { /* No work needed */ } @@ -409,8 +484,8 @@ GLOBAL void jseldhuffman (decompress_info_ptr cinfo) { if (! cinfo->arith_code) { - cinfo->methods->entropy_decode_init = huff_decoder_init; - cinfo->methods->entropy_decode = huff_decode_mcu; - cinfo->methods->entropy_decode_term = huff_decoder_term; + cinfo->methods->entropy_decode_init = decoder_init; + cinfo->methods->entropy_decode = decode_mcu; + cinfo->methods->entropy_decode_term = decoder_term; } } diff --git a/jdmain.c b/jdmain.c index 4991653..efb93ea 100644 --- a/jdmain.c +++ b/jdmain.c @@ -1,7 +1,7 @@ /* * jdmain.c * - * Copyright (C) 1991, 1992, Thomas G. Lane. + * Copyright (C) 1991, 1992, 1993, Thomas G. Lane. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * @@ -18,6 +18,9 @@ * The second style is convenient on Unix but is unhelpful on systems that * don't support pipes. Also, you MUST use the first style if your system * doesn't do binary I/O to stdin/stdout. + * To simplify script writing, the "-outfile" switch is provided. The syntax + * djpeg [options] -outfile outputfile inputfile + * works regardless of which command line style is used. */ #include "jinclude.h" @@ -186,6 +189,7 @@ progress_monitor (decompress_info_ptr cinfo, long loopcounter, long looplimit) static char * progname; /* program name for error messages */ +static char * outfilename; /* for -outfile switch */ LOCAL void @@ -280,6 +284,7 @@ parse_switches (decompress_info_ptr cinfo, int last_file_arg_seen, /* Set up default JPEG parameters. */ j_d_defaults(cinfo, TRUE); requested_fmt = DEFAULT_FMT; /* set default output file format */ + outfilename = NULL; /* Scan command line options, adjust parameters */ @@ -287,8 +292,10 @@ parse_switches (decompress_info_ptr cinfo, int last_file_arg_seen, arg = argv[argn]; if (*arg != '-') { /* Not a switch, must be a file name argument */ - if (argn <= last_file_arg_seen) - continue; /* ignore it if previously processed */ + if (argn <= last_file_arg_seen) { + outfilename = NULL; /* -outfile applies to just one input file */ + continue; /* ignore this name if previously processed */ + } break; /* else done parsing switches */ } arg++; /* advance past switch marker character */ @@ -346,7 +353,13 @@ parse_switches (decompress_info_ptr cinfo, int last_file_arg_seen, /* Use fast one-pass quantization. */ cinfo->two_pass_quantize = FALSE; - } else if (keymatch(arg, "pnm", 1)) { + } else if (keymatch(arg, "outfile", 3)) { + /* Set output file name. */ + if (++argn >= argc) /* advance to next argument */ + usage(); + outfilename = argv[argn]; /* save it away for later use */ + + } else if (keymatch(arg, "pnm", 1) || keymatch(arg, "ppm", 1)) { /* PPM/PGM output format. */ requested_fmt = FMT_PPM; @@ -399,47 +412,75 @@ main (int argc, char **argv) #endif #endif - /* Scan command line: set up compression parameters, input & output files. */ + /* Scan command line: set up compression parameters, find file names. */ file_index = parse_switches(&cinfo, 0, argc, argv); #ifdef TWO_FILE_COMMANDLINE - - if (file_index != argc-2) { - fprintf(stderr, "%s: must name one input and one output file\n", progname); - usage(); + /* Must have either -outfile switch or explicit output file name */ + if (outfilename == NULL) { + if (file_index != argc-2) { + fprintf(stderr, "%s: must name one input and one output file\n", + progname); + usage(); + } + outfilename = argv[file_index+1]; + } else { + if (file_index != argc-1) { + fprintf(stderr, "%s: must name one input and one output file\n", + progname); + usage(); + } } - if ((cinfo.input_file = fopen(argv[file_index], READ_BINARY)) == NULL) { - fprintf(stderr, "%s: can't open %s\n", progname, argv[file_index]); - exit(EXIT_FAILURE); - } - if ((cinfo.output_file = fopen(argv[file_index+1], WRITE_BINARY)) == NULL) { - fprintf(stderr, "%s: can't open %s\n", progname, argv[file_index+1]); - exit(EXIT_FAILURE); - } - -#else /* not TWO_FILE_COMMANDLINE -- use Unix style */ - - cinfo.input_file = stdin; /* default input file */ - cinfo.output_file = stdout; /* always the output file */ - -#ifdef USE_SETMODE /* need to hack file mode? */ - setmode(fileno(stdin), O_BINARY); - setmode(fileno(stdout), O_BINARY); -#endif - +#else + /* Unix style: expect zero or one file name */ if (file_index < argc-1) { fprintf(stderr, "%s: only one input file\n", progname); usage(); } +#endif /* TWO_FILE_COMMANDLINE */ + + /* Open the input file. */ if (file_index < argc) { if ((cinfo.input_file = fopen(argv[file_index], READ_BINARY)) == NULL) { fprintf(stderr, "%s: can't open %s\n", progname, argv[file_index]); exit(EXIT_FAILURE); } + } else { + /* default input file is stdin */ +#ifdef USE_SETMODE /* need to hack file mode? */ + setmode(fileno(stdin), O_BINARY); +#endif +#ifdef USE_FDOPEN /* need to re-open in binary mode? */ + if ((cinfo.input_file = fdopen(fileno(stdin), READ_BINARY)) == NULL) { + fprintf(stderr, "%s: can't open stdin\n", progname); + exit(EXIT_FAILURE); + } +#else + cinfo.input_file = stdin; +#endif } -#endif /* TWO_FILE_COMMANDLINE */ + /* Open the output file. */ + if (outfilename != NULL) { + if ((cinfo.output_file = fopen(outfilename, WRITE_BINARY)) == NULL) { + fprintf(stderr, "%s: can't open %s\n", progname, outfilename); + exit(EXIT_FAILURE); + } + } else { + /* default output file is stdout */ +#ifdef USE_SETMODE /* need to hack file mode? */ + setmode(fileno(stdout), O_BINARY); +#endif +#ifdef USE_FDOPEN /* need to re-open in binary mode? */ + if ((cinfo.output_file = fdopen(fileno(stdout), WRITE_BINARY)) == NULL) { + fprintf(stderr, "%s: can't open stdout\n", progname); + exit(EXIT_FAILURE); + } +#else + cinfo.output_file = stdout; +#endif + } /* Set up to read a JFIF or baseline-JPEG file. */ /* A smarter UI would inspect the first few bytes of the input file */ diff --git a/jdmaster.c b/jdmaster.c index 7a4a147..a490d4d 100644 --- a/jdmaster.c +++ b/jdmaster.c @@ -1,7 +1,7 @@ /* * jdmaster.c * - * Copyright (C) 1991, 1992, Thomas G. Lane. + * Copyright (C) 1991, 1992, 1993, Thomas G. Lane. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * @@ -31,22 +31,8 @@ d_initial_method_selection (decompress_info_ptr cinfo) /* JPEG file scanning method selection is already done. */ /* So is output file format selection (both are done by user interface). */ - /* Entropy decoding: either Huffman or arithmetic coding. */ -#ifdef D_ARITH_CODING_SUPPORTED - jseldarithmetic(cinfo); -#else - if (cinfo->arith_code) { - ERREXIT(cinfo->emethods, "Arithmetic coding not supported"); - } -#endif - jseldhuffman(cinfo); - /* Cross-block smoothing */ -#ifdef BLOCK_SMOOTHING_SUPPORTED - jselbsmooth(cinfo); -#else - cinfo->do_block_smoothing = FALSE; -#endif /* Gamma and color space conversion */ + /* NB: this may change the component_needed flags */ jseldcolor(cinfo); /* Color quantization selection rules */ @@ -77,6 +63,23 @@ d_initial_method_selection (decompress_info_ptr cinfo) jsel2quantize(cinfo); #endif + /* Cross-block smoothing */ +#ifdef BLOCK_SMOOTHING_SUPPORTED + jselbsmooth(cinfo); +#else + cinfo->do_block_smoothing = FALSE; +#endif + + /* Entropy decoding: either Huffman or arithmetic coding. */ +#ifdef D_ARITH_CODING_SUPPORTED + jseldarithmetic(cinfo); +#else + if (cinfo->arith_code) { + ERREXIT(cinfo->emethods, "Arithmetic coding not supported"); + } +#endif + jseldhuffman(cinfo); + /* Pipeline control */ jseldpipeline(cinfo); /* Overall control (that's me!) */ diff --git a/jdmcu.c b/jdmcu.c index 3927055..951bb7e 100644 --- a/jdmcu.c +++ b/jdmcu.c @@ -1,7 +1,7 @@ /* * jdmcu.c * - * Copyright (C) 1991, 1992, Thomas G. Lane. + * Copyright (C) 1991, 1992, 1993, Thomas G. Lane. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * @@ -102,14 +102,19 @@ reverse_DCT (decompress_info_ptr cinfo, DCTBLOCK block; JBLOCKROW browptr; JSAMPARRAY srowptr; + jpeg_component_info * compptr; long blocksperrow, bi; short numrows, ri; short ci; for (ci = 0; ci < cinfo->comps_in_scan; ci++) { + compptr = cinfo->cur_comp_info[ci]; + /* don't bother to IDCT an uninteresting component */ + if (! compptr->component_needed) + continue; /* calculate size of an MCU row in this component */ - blocksperrow = cinfo->cur_comp_info[ci]->downsampled_width / DCTSIZE; - numrows = cinfo->cur_comp_info[ci]->MCU_height; + blocksperrow = compptr->downsampled_width / DCTSIZE; + numrows = compptr->MCU_height; /* iterate through all blocks in MCU row */ for (ri = 0; ri < numrows; ri++) { browptr = coeff_data[ci][ri]; diff --git a/jdpipe.c b/jdpipe.c index b87336f..26f1f69 100644 --- a/jdpipe.c +++ b/jdpipe.c @@ -1,7 +1,7 @@ /* * jdpipe.c * - * Copyright (C) 1991, 1992, Thomas G. Lane. + * Copyright (C) 1991, 1992, 1993, Thomas G. Lane. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * @@ -362,6 +362,10 @@ expand (decompress_info_ptr cinfo, for (ci = 0; ci < cinfo->comps_in_scan; ci++) { compptr = cinfo->cur_comp_info[ci]; + /* don't bother to upsample an uninteresting component */ + if (! compptr->component_needed) + continue; + vs = compptr->v_samp_factor; /* row group height */ if (above >= 0) @@ -474,6 +478,10 @@ smooth_mcu_row (decompress_info_ptr cinfo, for (ci = 0; ci < cinfo->comps_in_scan; ci++) { compptr = cinfo->cur_comp_info[ci]; + /* don't bother to smooth an uninteresting component */ + if (! compptr->component_needed) + continue; + last = compptr->MCU_height - 1; if (above == NULL) @@ -593,6 +601,7 @@ simple_dcontroller (decompress_info_ptr cinfo) cinfo->total_passes++; /* Allocate working memory: */ + prepare_range_limit_table(cinfo); /* coeff_data holds a single MCU row of coefficient blocks */ coeff_data = alloc_MCU_row(cinfo); /* if doing cross-block smoothing, need extra space for its input */ @@ -611,7 +620,6 @@ simple_dcontroller (decompress_info_ptr cinfo) /* output_workspace is the color-processed data */ output_workspace = alloc_sampimage(cinfo, (int) cinfo->final_out_comps, (long) rows_in_mem, fullsize_width); - prepare_range_limit_table(cinfo); /* Tell the memory manager to instantiate big arrays. * We don't need any big arrays in this controller, @@ -773,10 +781,10 @@ complex_dcontroller (decompress_info_ptr cinfo) (long) (cinfo->max_h_samp_factor * DCTSIZE)); /* Allocate all working memory that doesn't depend on scan info */ + prepare_range_limit_table(cinfo); /* output_workspace is the color-processed data */ output_workspace = alloc_sampimage(cinfo, (int) cinfo->final_out_comps, (long) rows_in_mem, fullsize_width); - prepare_range_limit_table(cinfo); /* Get a big image: fullsize_image is sample data after upsampling. */ fullsize_image = (big_sarray_ptr *) (*cinfo->emethods->alloc_small) diff --git a/jinclude.h b/jinclude.h index c8a529f..8e8d185 100644 --- a/jinclude.h +++ b/jinclude.h @@ -1,7 +1,7 @@ /* * jinclude.h * - * Copyright (C) 1991, 1992, Thomas G. Lane. + * Copyright (C) 1991, 1992, 1993, Thomas G. Lane. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * diff --git a/jmemdos.c b/jmemdos.c index 8190273..30f6a2e 100644 --- a/jmemdos.c +++ b/jmemdos.c @@ -13,6 +13,8 @@ * if you compile in a small-data memory model; it should NOT be defined if * you use a large-data memory model. This file is not recommended if you * are using a flat-memory-space 386 environment such as DJGCC or Watcom C. + * Also, this code will NOT work if struct fields are aligned on greater than + * 2-byte boundaries. * * Based on code contributed by Ge' Weijers. */ @@ -447,21 +449,35 @@ open_xms_store (backing_store_ptr info, long total_bytes_needed) #if EMS_SUPPORTED -typedef union { /* either offset/page or real-mode pointer */ - struct { unsigned short offset, page; } ems; - void far * ptr; - } EMSPTR; +/* The EMS move specification structure requires word and long fields aligned + * at odd byte boundaries. Some compilers will align struct fields at even + * byte boundaries. While it's usually possible to force byte alignment, + * that causes an overall performance penalty and may pose problems in merging + * JPEG into a larger application. Instead we accept some rather dirty code + * here. Note this code would fail if the hardware did not allow odd-byte + * word & long accesses, but all 80x86 CPUs do. + */ -typedef struct { /* EMS move specification structure */ - long length; - char src_type; /* 1 = EMS, 0 = conventional memory */ - EMSH src_handle; /* use 0 if conventional memory */ - EMSPTR src; - char dst_type; - EMSH dst_handle; - EMSPTR dst; +typedef void far * EMSPTR; + +typedef union { /* EMS move specification structure */ + long length; /* It's easy to access first 4 bytes */ + char bytes[18]; /* Misaligned fields in here! */ } EMSspec; +/* Macros for accessing misaligned fields */ +#define FIELD_AT(spec,offset,type) (*((type *) &(spec.bytes[offset]))) +#define SRC_TYPE(spec) FIELD_AT(spec,4,char) +#define SRC_HANDLE(spec) FIELD_AT(spec,5,EMSH) +#define SRC_OFFSET(spec) FIELD_AT(spec,7,unsigned short) +#define SRC_PAGE(spec) FIELD_AT(spec,9,unsigned short) +#define SRC_PTR(spec) FIELD_AT(spec,7,EMSPTR) +#define DST_TYPE(spec) FIELD_AT(spec,11,char) +#define DST_HANDLE(spec) FIELD_AT(spec,12,EMSH) +#define DST_OFFSET(spec) FIELD_AT(spec,14,unsigned short) +#define DST_PAGE(spec) FIELD_AT(spec,16,unsigned short) +#define DST_PTR(spec) FIELD_AT(spec,14,EMSPTR) + #define EMSPAGESIZE 16384L /* gospel, see the EMS specs */ #define HIBYTE(W) (((W) >> 8) & 0xFF) @@ -476,13 +492,13 @@ read_ems_store (backing_store_ptr info, void FAR * buffer_address, EMSspec spec; spec.length = byte_count; - spec.src_type = 1; - spec.src_handle = info->handle.ems_handle; - spec.src.ems.page = (unsigned short) (file_offset / EMSPAGESIZE); - spec.src.ems.offset = (unsigned short) (file_offset % EMSPAGESIZE); - spec.dst_type = 0; - spec.dst_handle = 0; - spec.dst.ptr = buffer_address; + SRC_TYPE(spec) = 1; + SRC_HANDLE(spec) = info->handle.ems_handle; + SRC_PAGE(spec) = (unsigned short) (file_offset / EMSPAGESIZE); + SRC_OFFSET(spec) = (unsigned short) (file_offset % EMSPAGESIZE); + DST_TYPE(spec) = 0; + DST_HANDLE(spec) = 0; + DST_PTR(spec) = buffer_address; ctx.ds_si = (void far *) & spec; ctx.ax = 0x5700; /* move memory region */ @@ -500,13 +516,13 @@ write_ems_store (backing_store_ptr info, void FAR * buffer_address, EMSspec spec; spec.length = byte_count; - spec.src_type = 0; - spec.src_handle = 0; - spec.src.ptr = buffer_address; - spec.dst_type = 1; - spec.dst_handle = info->handle.ems_handle; - spec.dst.ems.page = (unsigned short) (file_offset / EMSPAGESIZE); - spec.dst.ems.offset = (unsigned short) (file_offset % EMSPAGESIZE); + SRC_TYPE(spec) = 0; + SRC_HANDLE(spec) = 0; + SRC_PTR(spec) = buffer_address; + DST_TYPE(spec) = 1; + DST_HANDLE(spec) = info->handle.ems_handle; + DST_PAGE(spec) = (unsigned short) (file_offset / EMSPAGESIZE); + DST_OFFSET(spec) = (unsigned short) (file_offset % EMSPAGESIZE); ctx.ds_si = (void far *) & spec; ctx.ax = 0x5700; /* move memory region */ @@ -609,5 +625,10 @@ jmem_init (external_methods_ptr emethods) GLOBAL void jmem_term (void) { - /* no work */ + /* Microsoft C, at least in v6.00A, will not successfully reclaim freed + * blocks of size > 32Kbytes unless we give it a kick in the rear, like so: + */ +#ifdef NEED_FHEAPMIN + _fheapmin(); +#endif } diff --git a/jmemmgr.c b/jmemmgr.c index 77b0253..f41e847 100644 --- a/jmemmgr.c +++ b/jmemmgr.c @@ -297,7 +297,7 @@ free_medium (void FAR *ptr) hdr--; /* point back to header */ /* Remove item from list -- linear search is fast enough */ - llink = &medium_list; + llink = (medium_ptr FAR *) &medium_list; while (*llink != hdr) { if (*llink == NULL) ERREXIT(methods, "Bogus free_medium request"); diff --git a/jpegdata.h b/jpegdata.h index a8ce18d..8e0b886 100644 --- a/jpegdata.h +++ b/jpegdata.h @@ -1,7 +1,7 @@ /* * jpegdata.h * - * Copyright (C) 1991, 1992, Thomas G. Lane. + * Copyright (C) 1991, 1992, 1993, Thomas G. Lane. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * @@ -165,6 +165,10 @@ typedef struct { /* Basic info about one component */ /* the MCU dimensions; these are the working dimensions of the array */ /* as it is passed through the DCT or IDCT step. NOTE: these values */ /* differ depending on whether the component is interleaved or not!! */ + /* This flag is used only for decompression. In cases where some of the */ + /* components will be ignored (eg grayscale output from YCbCr image), */ + /* we can skip IDCT etc. computations for the unused components. */ + boolean component_needed; /* do we need the value of this component? */ } jpeg_component_info; @@ -184,7 +188,12 @@ typedef QUANT_VAL QUANT_TBL[DCTSIZE2]; /* A quantization table */ typedef QUANT_VAL * QUANT_TBL_PTR; /* pointer to same */ -typedef struct { /* A Huffman coding table */ +/* Huffman coding tables. + */ + +#define HUFF_LOOKAHEAD 8 /* # of bits of lookahead */ + +typedef struct { /* These two fields directly represent the contents of a JPEG DHT marker */ UINT8 bits[17]; /* bits[k] = # of symbols with codes of */ /* length k bits; bits[0] is unused */ @@ -195,16 +204,29 @@ typedef struct { /* A Huffman coding table */ boolean sent_table; /* TRUE when table has been output */ /* The remaining fields are computed from the above to allow more efficient * coding and decoding. These fields should be considered private to the - * Huffman compression & decompression modules. + * Huffman compression & decompression modules. We use a union since only + * one set of fields is needed at a time. */ - /* encoding tables: */ - UINT16 ehufco[256]; /* code for each symbol */ - char ehufsi[256]; /* length of code for each symbol */ - /* decoding tables: (element [0] of each array is unused) */ - UINT16 mincode[17]; /* smallest code of length k */ - INT32 maxcode[18]; /* largest code of length k (-1 if none) */ - /* (maxcode[17] is a sentinel to ensure huff_DECODE terminates) */ - short valptr[17]; /* huffval[] index of 1st symbol of length k */ + union { + struct { /* encoding tables: */ + UINT16 ehufco[256]; /* code for each symbol */ + char ehufsi[256]; /* length of code for each symbol */ + } enc; + struct { /* decoding tables: */ + /* Basic tables: (element [0] of each array is unused) */ + INT32 mincode[17]; /* smallest code of length k */ + INT32 maxcode[18]; /* largest code of length k (-1 if none) */ + /* (maxcode[17] is a sentinel to ensure huff_DECODE terminates) */ + int valptr[17]; /* huffval[] index of 1st symbol of length k */ + /* Lookahead tables: indexed by the next HUFF_LOOKAHEAD bits of + * the input data stream. If the next Huffman code is no more + * than HUFF_LOOKAHEAD bits long, we can obtain its length and + * the corresponding symbol directly from these tables. + */ + int look_nbits[1<image_width + 2L) * SIZEOF(FSERROR)); for (i = 0; i < cinfo->color_out_comps; i++) { - evenrowerrs[i] = (FSERRPTR) (*cinfo->emethods->alloc_medium) (arraysize); - oddrowerrs[i] = (FSERRPTR) (*cinfo->emethods->alloc_medium) (arraysize); - /* we only need to zero the forward contribution for current row. */ - jzero_far((void FAR *) evenrowerrs[i], arraysize); + fserrors[i] = (FSERRPTR) (*cinfo->emethods->alloc_medium) (arraysize); + /* Initialize the propagated errors to zero. */ + jzero_far((void FAR *) fserrors[i], arraysize); } on_odd_row = FALSE; } @@ -426,6 +427,9 @@ color_quantize3 (decompress_info_ptr cinfo, int num_rows, register JSAMPROW ptr0, ptr1, ptr2, ptrout; register long col; int row; + JSAMPROW colorindex0 = colorindex[0]; + JSAMPROW colorindex1 = colorindex[1]; + JSAMPROW colorindex2 = colorindex[2]; long width = cinfo->image_width; for (row = 0; row < num_rows; row++) { @@ -435,9 +439,9 @@ color_quantize3 (decompress_info_ptr cinfo, int num_rows, ptr2 = input_buffer[2]; ptrout = output_data[row]; for (col = width; col > 0; col--) { - pixcode = GETJSAMPLE(colorindex[0][GETJSAMPLE(*ptr0++)]); - pixcode += GETJSAMPLE(colorindex[1][GETJSAMPLE(*ptr1++)]); - pixcode += GETJSAMPLE(colorindex[2][GETJSAMPLE(*ptr2++)]); + pixcode = GETJSAMPLE(colorindex0[GETJSAMPLE(*ptr0++)]); + pixcode += GETJSAMPLE(colorindex1[GETJSAMPLE(*ptr1++)]); + pixcode += GETJSAMPLE(colorindex2[GETJSAMPLE(*ptr2++)]); *ptrout++ = (JSAMPLE) pixcode; } } @@ -449,21 +453,24 @@ color_quantize_dither (decompress_info_ptr cinfo, int num_rows, JSAMPIMAGE input_data, JSAMPARRAY output_data) /* General case, with Floyd-Steinberg dithering */ { - register FSERROR val; - FSERROR two_val; - register FSERRPTR thisrowerr, nextrowerr; + register LOCFSERROR cur; /* current error or pixel value */ + LOCFSERROR belowerr; /* error for pixel below cur */ + LOCFSERROR bpreverr; /* error for below/prev col */ + LOCFSERROR bnexterr; /* error for below/next col */ + LOCFSERROR delta; + register FSERRPTR errorptr; /* => fserrors[] at column before current */ register JSAMPROW input_ptr; register JSAMPROW output_ptr; - JSAMPLE *range_limit = cinfo->sample_range_limit; JSAMPROW colorindex_ci; JSAMPROW colormap_ci; - register int pixcode; + int pixcode; int dir; /* 1 for left-to-right, -1 for right-to-left */ int ci; int nc = cinfo->color_out_comps; int row; long col_counter; long width = cinfo->image_width; + JSAMPLE *range_limit = cinfo->sample_range_limit; SHIFT_TEMPS for (row = 0; row < num_rows; row++) { @@ -472,56 +479,74 @@ color_quantize_dither (decompress_info_ptr cinfo, int num_rows, jzero_far((void FAR *) output_data[row], (size_t) (width * SIZEOF(JSAMPLE))); for (ci = 0; ci < nc; ci++) { + input_ptr = input_buffer[ci]; + output_ptr = output_data[row]; if (on_odd_row) { /* work right to left in this row */ + input_ptr += width - 1; /* so point to rightmost pixel */ + output_ptr += width - 1; dir = -1; - input_ptr = input_buffer[ci] + (width-1); - output_ptr = output_data[row] + (width-1); - thisrowerr = oddrowerrs[ci] + 1; - nextrowerr = evenrowerrs[ci] + width; + errorptr = fserrors[ci] + (width+1); /* point to entry after last column */ } else { /* work left to right in this row */ dir = 1; - input_ptr = input_buffer[ci]; - output_ptr = output_data[row]; - thisrowerr = evenrowerrs[ci] + 1; - nextrowerr = oddrowerrs[ci] + width; + errorptr = fserrors[ci]; /* point to entry before first real column */ } colorindex_ci = colorindex[ci]; colormap_ci = colormap[ci]; - *nextrowerr = 0; /* need only initialize this one entry */ + /* Preset error values: no error propagated to first pixel from left */ + cur = 0; + /* and no error propagated to row below yet */ + belowerr = bpreverr = 0; + for (col_counter = width; col_counter > 0; col_counter--) { - /* Get accumulated error for this component, round to integer. + /* cur holds the error propagated from the previous pixel on the + * current line. Add the error propagated from the previous line + * to form the complete error correction term for this pixel, and + * round the error term (which is expressed * 16) to an integer. * RIGHT_SHIFT rounds towards minus infinity, so adding 8 is correct * for either sign of the error value. + * Note: errorptr points to *previous* column's array entry. */ - val = RIGHT_SHIFT(*thisrowerr + 8, 4); - /* Compute pixel value + error compensation, range-limit to - * 0..MAXJSAMPLE. Note max error value is +- MAXJSAMPLE. + cur = RIGHT_SHIFT(cur + errorptr[dir] + 8, 4); + /* Form pixel value + error, and range-limit to 0..MAXJSAMPLE. + * The maximum error is +- MAXJSAMPLE; this sets the required size + * of the range_limit array. */ - val = GETJSAMPLE(range_limit[GETJSAMPLE(*input_ptr) + val]); + cur += GETJSAMPLE(*input_ptr); + cur = GETJSAMPLE(range_limit[cur]); /* Select output value, accumulate into output code for this pixel */ - pixcode = GETJSAMPLE(*output_ptr) + GETJSAMPLE(colorindex_ci[val]); - *output_ptr = (JSAMPLE) pixcode; + pixcode = GETJSAMPLE(colorindex_ci[cur]); + *output_ptr += (JSAMPLE) pixcode; /* Compute actual representation error at this pixel */ - /* Note: we can do this even though we don't yet have the final */ - /* value of pixcode, because the colormap is orthogonal. */ - val -= GETJSAMPLE(colormap_ci[pixcode]); - /* Propagate error to (same component of) adjacent pixels */ - /* Remember that nextrowerr entries are in reverse order! */ - two_val = val * 2; - nextrowerr[-1] = val; /* not +=, since not initialized yet */ - val += two_val; /* form error * 3 */ - nextrowerr[ 1] += val; - val += two_val; /* form error * 5 */ - nextrowerr[ 0] += val; - val += two_val; /* form error * 7 */ - thisrowerr[ 1] += val; + /* Note: we can do this even though we don't have the final */ + /* pixel code, because the colormap is orthogonal. */ + cur -= GETJSAMPLE(colormap_ci[pixcode]); + /* Compute error fractions to be propagated to adjacent pixels. + * Add these into the running sums, and simultaneously shift the + * next-line error sums left by 1 column. + */ + bnexterr = cur; + delta = cur * 2; + cur += delta; /* form error * 3 */ + errorptr[0] = (FSERROR) (bpreverr + cur); + cur += delta; /* form error * 5 */ + bpreverr = belowerr + cur; + belowerr = bnexterr; + cur += delta; /* form error * 7 */ + /* At this point cur contains the 7/16 error value to be propagated + * to the next pixel on the current line, and all the errors for the + * next line have been shifted over. We are therefore ready to move on. + */ input_ptr += dir; /* advance input ptr to next column */ output_ptr += dir; /* advance output ptr to next column */ - thisrowerr++; /* cur-row error ptr advances to right */ - nextrowerr--; /* next-row error ptr advances to left */ + errorptr += dir; /* advance errorptr to current column */ } + /* Post-loop cleanup: we must unload the final error value into the + * final fserrors[] entry. Note we need not unload belowerr because + * it is for the dummy column before or after the actual array. + */ + errorptr[0] = (FSERROR) bpreverr; /* unload prev err into array */ } on_odd_row = (on_odd_row ? FALSE : TRUE); } diff --git a/jquant2.c b/jquant2.c index c5c4110..4f3b191 100644 --- a/jquant2.c +++ b/jquant2.c @@ -1,7 +1,7 @@ /* * jquant2.c * - * Copyright (C) 1991, 1992, Thomas G. Lane. + * Copyright (C) 1991, 1992, 1993, Thomas G. Lane. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * @@ -875,36 +875,39 @@ pass2_nodither (decompress_info_ptr cinfo, int num_rows, /* Declarations for Floyd-Steinberg dithering. * - * Errors are accumulated into the arrays evenrowerrs[] and oddrowerrs[]. - * These have resolutions of 1/16th of a pixel count. The error at a given - * pixel is propagated to its unprocessed neighbors using the standard F-S - * fractions, + * Errors are accumulated into the array fserrors[], at a resolution of + * 1/16th of a pixel count. The error at a given pixel is propagated + * to its not-yet-processed neighbors using the standard F-S fractions, * ... (here) 7/16 * 3/16 5/16 1/16 * We work left-to-right on even rows, right-to-left on odd rows. * - * Each of the arrays has (#columns + 2) entries; the extra entry - * at each end saves us from special-casing the first and last pixels. - * Each entry is three values long. - * In evenrowerrs[], the entries for a component are stored left-to-right, but - * in oddrowerrs[] they are stored right-to-left. This means we always - * process the current row's error entries in increasing order and the next - * row's error entries in decreasing order, regardless of whether we are - * working L-to-R or R-to-L in the pixel data! + * We can get away with a single array (holding one row's worth of errors) + * by using it to store the current row's errors at pixel columns not yet + * processed, but the next row's errors at columns already processed. We + * need only a few extra variables to hold the errors immediately around the + * current column. (If we are lucky, those variables are in registers, but + * even if not, they're probably cheaper to access than array elements are.) + * + * The fserrors[] array has (#columns + 2) entries; the extra entry at + * each end saves us from special-casing the first and last pixels. + * Each entry is three values long, one value for each color component. * * Note: on a wide image, we might not have enough room in a PC's near data - * segment to hold the error arrays; so they are allocated with alloc_medium. + * segment to hold the error array; so it is allocated with alloc_medium. */ #ifdef EIGHT_BIT_SAMPLES typedef INT16 FSERROR; /* 16 bits should be enough */ +typedef int LOCFSERROR; /* use 'int' for calculation temps */ #else -typedef INT32 FSERROR; /* may need more than 16 bits? */ +typedef INT32 FSERROR; /* may need more than 16 bits */ +typedef INT32 LOCFSERROR; /* be sure calculation temps are big enough */ #endif typedef FSERROR FAR *FSERRPTR; /* pointer to error array (in FAR storage!) */ -static FSERRPTR evenrowerrs, oddrowerrs; /* current-row and next-row errors */ +static FSERRPTR fserrors; /* accumulated errors */ static boolean on_odd_row; /* flag to remember which row we are on */ @@ -913,18 +916,15 @@ pass2_dither (decompress_info_ptr cinfo, int num_rows, JSAMPIMAGE image_data, JSAMPARRAY output_workspace) /* This version performs Floyd-Steinberg dithering */ { -#ifdef EIGHT_BIT_SAMPLES - register int c0, c1, c2; - int two_val; -#else - register FSERROR c0, c1, c2; - FSERROR two_val; -#endif - register FSERRPTR thisrowerr, nextrowerr; - JSAMPROW ptr0, ptr1, ptr2, outptr; + register LOCFSERROR cur0, cur1, cur2; /* current error or pixel value */ + LOCFSERROR belowerr0, belowerr1, belowerr2; /* error for pixel below cur */ + LOCFSERROR bpreverr0, bpreverr1, bpreverr2; /* error for below/prev col */ + register FSERRPTR errorptr; /* => fserrors[] at column before current */ + JSAMPROW ptr0, ptr1, ptr2; /* => current input pixel */ + JSAMPROW outptr; /* => current output pixel */ histptr cachep; - register int pixcode; - int dir; + int dir; /* +1 or -1 depending on direction */ + int dir3; /* 3*dir, for advancing errorptr */ int row; long col; long width = cinfo->image_width; @@ -942,85 +942,111 @@ pass2_dither (decompress_info_ptr cinfo, int num_rows, outptr = output_workspace[row]; if (on_odd_row) { /* work right to left in this row */ - ptr0 += width - 1; + ptr0 += width - 1; /* so point to rightmost pixel */ ptr1 += width - 1; ptr2 += width - 1; outptr += width - 1; dir = -1; - thisrowerr = oddrowerrs + 3; - nextrowerr = evenrowerrs + width*3; + dir3 = -3; + errorptr = fserrors + (width+1)*3; /* point to entry after last column */ on_odd_row = FALSE; /* flip for next time */ } else { /* work left to right in this row */ dir = 1; - thisrowerr = evenrowerrs + 3; - nextrowerr = oddrowerrs + width*3; + dir3 = 3; + errorptr = fserrors; /* point to entry before first real column */ on_odd_row = TRUE; /* flip for next time */ } - /* need only initialize this one entry in nextrowerr */ - nextrowerr[0] = nextrowerr[1] = nextrowerr[2] = 0; + /* Preset error values: no error propagated to first pixel from left */ + cur0 = cur1 = cur2 = 0; + /* and no error propagated to row below yet */ + belowerr0 = belowerr1 = belowerr2 = 0; + bpreverr0 = bpreverr1 = bpreverr2 = 0; + for (col = width; col > 0; col--) { - /* For each component, get accumulated error and round to integer; - * form pixel value + error, and range-limit to 0..MAXJSAMPLE. + /* curN holds the error propagated from the previous pixel on the + * current line. Add the error propagated from the previous line + * to form the complete error correction term for this pixel, and + * round the error term (which is expressed * 16) to an integer. * RIGHT_SHIFT rounds towards minus infinity, so adding 8 is correct - * for either sign of the error value. Max error is +- MAXJSAMPLE. + * for either sign of the error value. + * Note: errorptr points to *previous* column's array entry. */ - c0 = RIGHT_SHIFT(thisrowerr[0] + 8, 4); - c1 = RIGHT_SHIFT(thisrowerr[1] + 8, 4); - c2 = RIGHT_SHIFT(thisrowerr[2] + 8, 4); - c0 += GETJSAMPLE(*ptr0); - c1 += GETJSAMPLE(*ptr1); - c2 += GETJSAMPLE(*ptr2); - c0 = GETJSAMPLE(range_limit[c0]); - c1 = GETJSAMPLE(range_limit[c1]); - c2 = GETJSAMPLE(range_limit[c2]); + cur0 = RIGHT_SHIFT(cur0 + errorptr[dir3+0] + 8, 4); + cur1 = RIGHT_SHIFT(cur1 + errorptr[dir3+1] + 8, 4); + cur2 = RIGHT_SHIFT(cur2 + errorptr[dir3+2] + 8, 4); + /* Form pixel value + error, and range-limit to 0..MAXJSAMPLE. + * The maximum error is +- MAXJSAMPLE; this sets the required size + * of the range_limit array. + */ + cur0 += GETJSAMPLE(*ptr0); + cur1 += GETJSAMPLE(*ptr1); + cur2 += GETJSAMPLE(*ptr2); + cur0 = GETJSAMPLE(range_limit[cur0]); + cur1 = GETJSAMPLE(range_limit[cur1]); + cur2 = GETJSAMPLE(range_limit[cur2]); /* Index into the cache with adjusted pixel value */ - cachep = & histogram[c0 >> Y_SHIFT][c1 >> C_SHIFT][c2 >> C_SHIFT]; + cachep = & histogram[cur0 >> Y_SHIFT][cur1 >> C_SHIFT][cur2 >> C_SHIFT]; /* If we have not seen this color before, find nearest colormap */ /* entry and update the cache */ if (*cachep == 0) - fill_inverse_cmap(cinfo, c0 >> Y_SHIFT, c1 >> C_SHIFT, c2 >> C_SHIFT); + fill_inverse_cmap(cinfo, cur0>>Y_SHIFT, cur1>>C_SHIFT, cur2>>C_SHIFT); /* Now emit the colormap index for this cell */ - pixcode = *cachep - 1; - *outptr = (JSAMPLE) pixcode; - /* Compute representation error for this pixel */ - c0 -= GETJSAMPLE(colormap0[pixcode]); - c1 -= GETJSAMPLE(colormap1[pixcode]); - c2 -= GETJSAMPLE(colormap2[pixcode]); - /* Propagate error to adjacent pixels */ - /* Remember that nextrowerr entries are in reverse order! */ - two_val = c0 * 2; - nextrowerr[0-3] = c0; /* not +=, since not initialized yet */ - c0 += two_val; /* form error * 3 */ - nextrowerr[0+3] += c0; - c0 += two_val; /* form error * 5 */ - nextrowerr[0 ] += c0; - c0 += two_val; /* form error * 7 */ - thisrowerr[0+3] += c0; - two_val = c1 * 2; - nextrowerr[1-3] = c1; /* not +=, since not initialized yet */ - c1 += two_val; /* form error * 3 */ - nextrowerr[1+3] += c1; - c1 += two_val; /* form error * 5 */ - nextrowerr[1 ] += c1; - c1 += two_val; /* form error * 7 */ - thisrowerr[1+3] += c1; - two_val = c2 * 2; - nextrowerr[2-3] = c2; /* not +=, since not initialized yet */ - c2 += two_val; /* form error * 3 */ - nextrowerr[2+3] += c2; - c2 += two_val; /* form error * 5 */ - nextrowerr[2 ] += c2; - c2 += two_val; /* form error * 7 */ - thisrowerr[2+3] += c2; - /* Advance to next column */ - ptr0 += dir; + { register int pixcode = *cachep - 1; + *outptr = (JSAMPLE) pixcode; + /* Compute representation error for this pixel */ + cur0 -= GETJSAMPLE(colormap0[pixcode]); + cur1 -= GETJSAMPLE(colormap1[pixcode]); + cur2 -= GETJSAMPLE(colormap2[pixcode]); + } + /* Compute error fractions to be propagated to adjacent pixels. + * Add these into the running sums, and simultaneously shift the + * next-line error sums left by 1 column. + */ + { register LOCFSERROR bnexterr, delta; + + bnexterr = cur0; /* Process component 0 */ + delta = cur0 * 2; + cur0 += delta; /* form error * 3 */ + errorptr[0] = (FSERROR) (bpreverr0 + cur0); + cur0 += delta; /* form error * 5 */ + bpreverr0 = belowerr0 + cur0; + belowerr0 = bnexterr; + cur0 += delta; /* form error * 7 */ + bnexterr = cur1; /* Process component 1 */ + delta = cur1 * 2; + cur1 += delta; /* form error * 3 */ + errorptr[1] = (FSERROR) (bpreverr1 + cur1); + cur1 += delta; /* form error * 5 */ + bpreverr1 = belowerr1 + cur1; + belowerr1 = bnexterr; + cur1 += delta; /* form error * 7 */ + bnexterr = cur2; /* Process component 2 */ + delta = cur2 * 2; + cur2 += delta; /* form error * 3 */ + errorptr[2] = (FSERROR) (bpreverr2 + cur2); + cur2 += delta; /* form error * 5 */ + bpreverr2 = belowerr2 + cur2; + belowerr2 = bnexterr; + cur2 += delta; /* form error * 7 */ + } + /* At this point curN contains the 7/16 error value to be propagated + * to the next pixel on the current line, and all the errors for the + * next line have been shifted over. We are therefore ready to move on. + */ + ptr0 += dir; /* Advance pixel pointers to next column */ ptr1 += dir; ptr2 += dir; outptr += dir; - thisrowerr += 3; /* cur-row error ptr advances to right */ - nextrowerr -= 3; /* next-row error ptr advances to left */ + errorptr += dir3; /* advance errorptr to current column */ } + /* Post-loop cleanup: we must unload the final error values into the + * final fserrors[] entry. Note we need not unload belowerrN because + * it is for the dummy column before or after the actual array. + */ + errorptr[0] = (FSERROR) bpreverr0; /* unload prev errs into array */ + errorptr[1] = (FSERROR) bpreverr1; + errorptr[2] = (FSERROR) bpreverr2; } /* Emit converted rows to the output file */ (*cinfo->methods->put_pixel_rows) (cinfo, num_rows, &output_workspace); @@ -1067,12 +1093,12 @@ color_quant_init (decompress_info_ptr cinfo) /* Allocate Floyd-Steinberg workspace if necessary */ /* This isn't needed until pass 2, but again it is FAR storage. */ if (cinfo->use_dithering) { - size_t arraysize = (size_t) ((cinfo->image_width + 2L) * 3L * SIZEOF(FSERROR)); + size_t arraysize = (size_t) ((cinfo->image_width + 2L) * + (3 * SIZEOF(FSERROR))); - evenrowerrs = (FSERRPTR) (*cinfo->emethods->alloc_medium) (arraysize); - oddrowerrs = (FSERRPTR) (*cinfo->emethods->alloc_medium) (arraysize); - /* we only need to zero the forward contribution for current row. */ - jzero_far((void FAR *) evenrowerrs, arraysize); + fserrors = (FSERRPTR) (*cinfo->emethods->alloc_medium) (arraysize); + /* Initialize the propagated errors to zero. */ + jzero_far((void FAR *) fserrors, arraysize); on_odd_row = FALSE; } @@ -1157,6 +1183,14 @@ jsel2quantize (decompress_info_ptr cinfo) cinfo->methods->color_quant_doit = color_quant_doit; cinfo->methods->color_quant_term = color_quant_term; cinfo->methods->color_quantize = color_quantize; + /* Quantized grayscale output is normally done by jquant1.c (which will do + * a much better job of it). But if the program is configured with only + * 2-pass quantization, then I have to do the job. In this situation, + * jseldcolor's clearing of the Cb/Cr component_needed flags is incorrect, + * because I will look at those components before conversion. + */ + cinfo->cur_comp_info[1]->component_needed = TRUE; + cinfo->cur_comp_info[2]->component_needed = TRUE; } } diff --git a/jrdjfif.c b/jrdjfif.c index 9d63d4d..b6bd57c 100644 --- a/jrdjfif.c +++ b/jrdjfif.c @@ -1,7 +1,7 @@ /* * jrdjfif.c * - * Copyright (C) 1991, 1992, Thomas G. Lane. + * Copyright (C) 1991, 1992, 1993, Thomas G. Lane. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * @@ -178,6 +178,8 @@ get_dht (decompress_info_ptr cinfo) count += bits[i]; } + length -= 1 + 16; + TRACEMS8(cinfo->emethods, 2, " %3d %3d %3d %3d %3d %3d %3d %3d", bits[1], bits[2], bits[3], bits[4], bits[5], bits[6], bits[7], bits[8]); @@ -185,13 +187,13 @@ get_dht (decompress_info_ptr cinfo) bits[9], bits[10], bits[11], bits[12], bits[13], bits[14], bits[15], bits[16]); - if (count > 256) + if (count > 256 || ((INT32) count) > length) ERREXIT(cinfo->emethods, "Bogus DHT counts"); for (i = 0; i < count; i++) huffval[i] = (UINT8) JGETC(cinfo); - length -= 1 + 16 + count; + length -= count; if (index & 0x10) { /* AC table definition */ index -= 0x10; @@ -357,11 +359,26 @@ get_app0 (decompress_info_ptr cinfo) TRACEMS1(cinfo->emethods, 1, "Short APP0 marker, length %u", (int) length); } - while (length-- > 0) /* skip any remaining data */ + while (--length >= 0) /* skip any remaining data */ (void) JGETC(cinfo); } +LOCAL void +get_com (decompress_info_ptr cinfo) +/* Process a COM marker */ +/* Actually we just pass this off to an application-supplied routine */ +{ + INT32 length; + + length = get_2bytes(cinfo) - 2; + + TRACEMS1(cinfo->emethods, 1, "Comment, length %u", (int) length); + + (*cinfo->methods->process_comment) (cinfo, (long) length); +} + + LOCAL void get_sof (decompress_info_ptr cinfo, int code) /* Process a SOFn marker */ @@ -417,7 +434,8 @@ get_sof (decompress_info_ptr cinfo, int code) compptr->h_samp_factor = (c >> 4) & 15; compptr->v_samp_factor = (c ) & 15; compptr->quant_tbl_no = JGETC(cinfo); - + compptr->component_needed = TRUE; /* assume all components are wanted */ + TRACEMS4(cinfo->emethods, 1, " Component %d: %dhx%dv q=%d", compptr->component_id, compptr->h_samp_factor, compptr->v_samp_factor, compptr->quant_tbl_no); @@ -526,14 +544,14 @@ next_marker (decompress_info_ptr cinfo) } -LOCAL JPEG_MARKER +LOCAL int process_tables (decompress_info_ptr cinfo) /* Scan and process JPEG markers that can appear in any order */ /* Return when an SOI, EOI, SOFn, or SOS is found */ { int c; - while (TRUE) { + for (;;) { c = next_marker(cinfo); switch (c) { @@ -554,7 +572,7 @@ process_tables (decompress_info_ptr cinfo) case M_SOI: case M_EOI: case M_SOS: - return ((JPEG_MARKER) c); + return c; case M_DHT: get_dht(cinfo); @@ -575,6 +593,10 @@ process_tables (decompress_info_ptr cinfo) case M_APP0: get_app0(cinfo); break; + + case M_COM: + get_com(cinfo); + break; case M_RST0: /* these are all parameterless */ case M_RST1: @@ -588,7 +610,7 @@ process_tables (decompress_info_ptr cinfo) TRACEMS1(cinfo->emethods, 1, "Unexpected marker 0x%02x", c); break; - default: /* must be DNL, DHP, EXP, APPn, JPGn, COM, or RESn */ + default: /* must be DNL, DHP, EXP, APPn, JPGn, or RESn */ skip_variable(cinfo, c); break; } @@ -611,7 +633,7 @@ read_file_header (decompress_info_ptr cinfo) * nonstandard headers in front of the SOI, it must skip over them itself * before calling jpeg_decompress(). */ - if (JGETC(cinfo) != 0xFF || JGETC(cinfo) != M_SOI) + if (JGETC(cinfo) != 0xFF || JGETC(cinfo) != (int) M_SOI) ERREXIT(cinfo->emethods, "Not a JPEG file"); get_soi(cinfo); /* OK, process SOI */ @@ -759,16 +781,16 @@ resync_to_restart (decompress_info_ptr cinfo, int marker) marker, desired); /* Outer loop handles repeated decision after scanning forward. */ for (;;) { - if (marker < M_SOF0) + if (marker < (int) M_SOF0) action = 2; /* invalid marker */ - else if (marker < M_RST0 || marker > M_RST7) + else if (marker < (int) M_RST0 || marker > (int) M_RST7) action = 3; /* valid non-restart marker */ else { - if (marker == (M_RST0 + ((desired+1) & 7)) || - marker == (M_RST0 + ((desired+2) & 7))) + if (marker == ((int) M_RST0 + ((desired+1) & 7)) || + marker == ((int) M_RST0 + ((desired+2) & 7))) action = 3; /* one of the next two expected restarts */ - else if (marker == (M_RST0 + ((desired-1) & 7)) || - marker == (M_RST0 + ((desired-2) & 7))) + else if (marker == ((int) M_RST0 + ((desired-1) & 7)) || + marker == ((int) M_RST0 + ((desired-2) & 7))) action = 2; /* a prior restart, so advance */ else action = 1; /* desired restart or too far away */ diff --git a/jrdppm.c b/jrdppm.c index ad637af..b17dcf7 100644 --- a/jrdppm.c +++ b/jrdppm.c @@ -105,7 +105,7 @@ read_pbm_integer (compress_info_ptr cinfo) ch = pbm_getc(cinfo->input_file); if (ch == EOF) ERREXIT(cinfo->emethods, "Premature EOF in PPM file"); - } while (ch == ' ' || ch == '\t' || ch == '\n'); + } while (ch == ' ' || ch == '\t' || ch == '\n' || ch == '\r'); if (ch < '0' || ch > '9') ERREXIT(cinfo->emethods, "Bogus data in PPM file"); diff --git a/jversion.h b/jversion.h index 1f0171e..4946670 100644 --- a/jversion.h +++ b/jversion.h @@ -1,7 +1,7 @@ /* * jversion.h * - * Copyright (C) 1991, 1992, Thomas G. Lane. + * Copyright (C) 1991, 1992, 1993, Thomas G. Lane. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * @@ -9,6 +9,6 @@ */ -#define JVERSION "4 10-Dec-92" +#define JVERSION "4A 18-Feb-93" -#define JCOPYRIGHT "Copyright (C) 1992, Thomas G. Lane" +#define JCOPYRIGHT "Copyright (C) 1993, Thomas G. Lane" diff --git a/jwrgif.c b/jwrgif.c index 612a22c..5519d94 100644 --- a/jwrgif.c +++ b/jwrgif.c @@ -1,7 +1,7 @@ /* * jwrgif.c * - * Copyright (C) 1991, 1992, Thomas G. Lane. + * Copyright (C) 1991, 1992, 1993, Thomas G. Lane. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * @@ -100,7 +100,7 @@ flush_packet (void) packetbuf[0] = (char) bytesinpkt++; if (JFWRITE(dcinfo->output_file, packetbuf, bytesinpkt) != (size_t) bytesinpkt) - ERREXIT(dcinfo->emethods, "Output file write error"); + ERREXIT(dcinfo->emethods, "Output file write error --- out of disk space?"); bytesinpkt = 0; } } @@ -451,7 +451,7 @@ output_term (decompress_info_ptr cinfo) /* Make sure we wrote the output file OK */ fflush(cinfo->output_file); if (ferror(cinfo->output_file)) - ERREXIT(cinfo->emethods, "Output file write error"); + ERREXIT(cinfo->emethods, "Output file write error --- out of disk space?"); /* Free space */ /* no work (we let free_all release the workspace) */ } diff --git a/jwrjfif.c b/jwrjfif.c index 5bd7afb..f3daba0 100644 --- a/jwrjfif.c +++ b/jwrjfif.c @@ -1,7 +1,7 @@ /* * jwrjfif.c * - * Copyright (C) 1991, 1992, Thomas G. Lane. + * Copyright (C) 1991, 1992, 1993, Thomas G. Lane. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * @@ -38,13 +38,13 @@ #define WRITE_BYTES(cinfo,dataptr,datacount) \ { if (JFWRITE(cinfo->output_file, dataptr, datacount) \ != (size_t) (datacount)) \ - ERREXIT(cinfo->emethods, "Output file write error"); } + ERREXIT(cinfo->emethods, "Output file write error --- out of disk space?"); } /* Clean up and verify successful output */ #define CHECK_OUTPUT(cinfo) \ { fflush(cinfo->output_file); \ if (ferror(cinfo->output_file)) \ - ERREXIT(cinfo->emethods, "Output file write error"); } + ERREXIT(cinfo->emethods, "Output file write error --- out of disk space?"); } /* End of stdio-specific code. */ @@ -328,6 +328,23 @@ emit_jfif_app0 (compress_info_ptr cinfo) } +LOCAL void +emit_com (compress_info_ptr cinfo, char * dataptr, size_t datalen) +/* Emit a COM marker */ +{ + if ((unsigned) datalen <= (unsigned) 65533) { /* safety check */ + emit_marker(cinfo, M_COM); + + emit_2bytes(cinfo, (int) (datalen + 2)); /* length */ + + while (datalen--) { + emit_byte(cinfo, *dataptr); + dataptr++; + } + } +} + + /* * Write the file header. */ @@ -345,6 +362,10 @@ write_file_header (compress_info_ptr cinfo) if (cinfo->write_JFIF_header) /* next an optional JFIF APP0 */ emit_jfif_app0(cinfo); + if (cinfo->comment_text != NULL) /* and an optional COM block */ + emit_com(cinfo, cinfo->comment_text, + (size_t) (strlen(cinfo->comment_text))); + /* Emit DQT for each quantization table. */ /* Note that doing it here means we can't adjust the QTs on-the-fly. */ /* If we did want to do that, we'd have a problem with checking precision */ diff --git a/jwrppm.c b/jwrppm.c index 5d9f60b..a6d10e3 100644 --- a/jwrppm.c +++ b/jwrppm.c @@ -1,7 +1,7 @@ /* * jwrppm.c * - * Copyright (C) 1991, 1992, Thomas G. Lane. + * Copyright (C) 1991, 1992, 1993, Thomas G. Lane. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * @@ -313,7 +313,7 @@ output_term (decompress_info_ptr cinfo) /* we let free_all release any workspace */ fflush(cinfo->output_file); if (ferror(cinfo->output_file)) - ERREXIT(cinfo->emethods, "Output file write error"); + ERREXIT(cinfo->emethods, "Output file write error --- out of disk space?"); } diff --git a/jwrrle.c b/jwrrle.c index 4fec56e..0c8718e 100644 --- a/jwrrle.c +++ b/jwrrle.c @@ -1,7 +1,7 @@ /* * jwrrle.c * - * Copyright (C) 1991, 1992, Thomas G. Lane. + * Copyright (C) 1991, 1992, 1993, Thomas G. Lane. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * @@ -208,7 +208,7 @@ output_term (decompress_info_ptr cinfo) rle_puteof(&header); fflush(cinfo->output_file); if (ferror(cinfo->output_file)) - ERREXIT(cinfo->emethods, "Output file write error"); + ERREXIT(cinfo->emethods, "Output file write error --- out of disk space?"); /* Release memory */ /* no work (we let free_all release the workspace) */ diff --git a/jwrtarga.c b/jwrtarga.c index 009d0bb..4c952cb 100644 --- a/jwrtarga.c +++ b/jwrtarga.c @@ -1,7 +1,7 @@ /* * jwrtarga.c * - * Copyright (C) 1991, 1992, Thomas G. Lane. + * Copyright (C) 1991, 1992, 1993, Thomas G. Lane. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * @@ -319,7 +319,7 @@ output_term (decompress_info_ptr cinfo) /* No work except to make sure we wrote the output file OK */ fflush(cinfo->output_file); if (ferror(cinfo->output_file)) - ERREXIT(cinfo->emethods, "Output file write error"); + ERREXIT(cinfo->emethods, "Output file write error --- out of disk space?"); } diff --git a/makefile.ansi b/makefile.ansi index 59bba3b..86e3118 100644 --- a/makefile.ansi +++ b/makefile.ansi @@ -54,7 +54,8 @@ INCLUDES= jinclude.h jconfig.h jpegdata.h jversion.h jmemsys.h DOCS= README SETUP USAGE CHANGELOG cjpeg.1 djpeg.1 architecture codingrules MAKEFILES= makefile.ansi makefile.unix makefile.manx makefile.sas \ makcjpeg.st makdjpeg.st makljpeg.st makefile.mc5 makefile.mc6 \ - makefile.bcc makefile.mms makefile.vms makvms.opt + makefile.bcc makefile.icc makljpeg.icc makefile.mms makefile.vms \ + makvms.opt OTHERFILES= ansi2knr.c ckconfig.c example.c TESTFILES= testorig.jpg testimg.ppm testimg.gif testimg.jpg DISTFILES= $(DOCS) $(MAKEFILES) $(SOURCES) $(SYSDEPFILES) $(INCLUDES) \ diff --git a/makefile.bcc b/makefile.bcc index 8540afc..e404fb8 100644 --- a/makefile.bcc +++ b/makefile.bcc @@ -23,6 +23,9 @@ CFLAGS= -DHAVE_STDC -DINCLUDES_ARE_ANSI \ # -DINCOMPLETE_TYPES_BROKEN suppresses bogus warning about undefined structures # -w-par suppresses warnings about unused function parameters # -O2 enables full code optimization (for pre-3.0 Borland C++, use -O -G -Z) +# If you run up against DOS' 128-character limit on command line length, +# you can get rid of some of the -D switches by adding equivalent #define +# commands to the head of jinclude.h. # Link-time cc options: LDFLAGS= -ms @@ -50,7 +53,8 @@ INCLUDES= jinclude.h jconfig.h jpegdata.h jversion.h jmemsys.h DOCS= README SETUP USAGE CHANGELOG cjpeg.1 djpeg.1 architecture codingrules MAKEFILES= makefile.ansi makefile.unix makefile.manx makefile.sas \ makcjpeg.st makdjpeg.st makljpeg.st makefile.mc5 makefile.mc6 \ - makefile.bcc makefile.mms makefile.vms makvms.opt + makefile.bcc makefile.icc makljpeg.icc makefile.mms makefile.vms \ + makvms.opt OTHERFILES= ansi2knr.c ckconfig.c example.c TESTFILES= testorig.jpg testimg.ppm testimg.gif testimg.jpg DISTFILES= $(DOCS) $(MAKEFILES) $(SOURCES) $(SYSDEPFILES) $(INCLUDES) \ @@ -119,12 +123,12 @@ clean: test: del testout.* - djpeg testorig.jpg testout.ppm - djpeg -gif testorig.jpg testout.gif - cjpeg testimg.ppm testout.jpg - fc testimg.ppm testout.ppm - fc testimg.gif testout.gif - fc testimg.jpg testout.jpg + djpeg -outfile testout.ppm testorig.jpg + djpeg -gif -outfile testout.gif testorig.jpg + cjpeg -outfile testout.jpg testimg.ppm + fc /b testimg.ppm testout.ppm + fc /b testimg.gif testout.gif + fc /b testimg.jpg testout.jpg jbsmooth.obj : jbsmooth.c jinclude.h jconfig.h jpegdata.h diff --git a/makefile.icc b/makefile.icc new file mode 100644 index 0000000..1f0d6fc --- /dev/null +++ b/makefile.icc @@ -0,0 +1,141 @@ +# Makefile for Independent JPEG Group's software + +# This makefile is for Intel's Code Builder 32-bit DOS/Windows compiler. +# Thanks to Bailey Brown. + +# Read SETUP instructions before saying "make" !! + +# The name of your C compiler: +CC= icc + +# You may want to adjust these cc options: +CFLAGS= /O3 /Ll /DTWO_FILE_COMMANDLINE + +# Link-time cc options: +LDFLAGS= /F /xregion=4M +# /F removes floating-point support, which we don't need. +# /xregionsize sets virtual memory region size. + +# To link any special libraries, add the necessary -l commands here. +LDLIBS= + +# miscellaneous OS-dependent stuff +# linker +LN= $(CC) +# library (.lib) file creation command +AR= lib32 + + +# source files (independently compilable files) +SOURCES= jbsmooth.c jcarith.c jccolor.c jcdeflts.c jcexpand.c jchuff.c \ + jcmain.c jcmaster.c jcmcu.c jcpipe.c jcsample.c jdarith.c jdcolor.c \ + jddeflts.c jdhuff.c jdmain.c jdmaster.c jdmcu.c jdpipe.c jdsample.c \ + jerror.c jquant1.c jquant2.c jfwddct.c jrevdct.c jutils.c jmemmgr.c \ + jrdjfif.c jrdgif.c jrdppm.c jrdrle.c jrdtarga.c jwrjfif.c jwrgif.c \ + jwrppm.c jwrrle.c jwrtarga.c +# virtual source files (not present in distribution file, see SETUP) +VIRTSOURCES= jmemsys.c +# system-dependent implementations of virtual source files +SYSDEPFILES= jmemansi.c jmemname.c jmemnobs.c jmemdos.c jmemdos.h \ + jmemdosa.asm +# files included by source files +INCLUDES= jinclude.h jconfig.h jpegdata.h jversion.h jmemsys.h +# documentation, test, and support files +DOCS= README SETUP USAGE CHANGELOG cjpeg.1 djpeg.1 architecture codingrules +MAKEFILES= makefile.ansi makefile.unix makefile.manx makefile.sas \ + makcjpeg.st makdjpeg.st makljpeg.st makefile.mc5 makefile.mc6 \ + makefile.bcc makefile.icc makljpeg.icc makefile.mms makefile.vms \ + makvms.opt +OTHERFILES= ansi2knr.c ckconfig.c example.c +TESTFILES= testorig.jpg testimg.ppm testimg.gif testimg.jpg +DISTFILES= $(DOCS) $(MAKEFILES) $(SOURCES) $(SYSDEPFILES) $(INCLUDES) \ + $(OTHERFILES) $(TESTFILES) +# objectfiles common to cjpeg and djpeg +COMOBJECTS= jutils.obj jerror.obj jmemmgr.obj jmemsys.obj +# compression objectfiles +CLIBOBJECTS= jcmaster.obj jcdeflts.obj jcarith.obj jccolor.obj jcexpand.obj \ + jchuff.obj jcmcu.obj jcpipe.obj jcsample.obj jfwddct.obj \ + jwrjfif.obj jrdgif.obj jrdppm.obj jrdrle.obj jrdtarga.obj +COBJECTS= jcmain.obj $(CLIBOBJECTS) $(COMOBJECTS) +# decompression objectfiles +DLIBOBJECTS= jdmaster.obj jddeflts.obj jbsmooth.obj jdarith.obj jdcolor.obj \ + jdhuff.obj jdmcu.obj jdpipe.obj jdsample.obj jquant1.obj \ + jquant2.obj jrevdct.obj jrdjfif.obj jwrgif.obj jwrppm.obj \ + jwrrle.obj jwrtarga.obj +DOBJECTS= jdmain.obj $(DLIBOBJECTS) $(COMOBJECTS) +# These objectfiles are included in libjpeg.lib +LIBOBJECTS= $(CLIBOBJECTS) $(DLIBOBJECTS) $(COMOBJECTS) + + +all: cjpeg.exe djpeg.exe +# By default, libjpeg.lib is not built unless you explicitly request it. +# You can add libjpeg.lib to the line above if you want it built by default. + + +cjpeg.exe: $(COBJECTS) + echo $(COBJECTS) >cjpeg.rsp + $(LN) $(LDFLAGS) /ecjpeg.exe @cjpeg.rsp $(LDLIBS) + +djpeg.exe: $(DOBJECTS) + echo $(DOBJECTS) >djpeg.rsp + $(LN) $(LDFLAGS) /edjpeg.exe @djpeg.rsp $(LDLIBS) + +# libjpeg.lib is useful if you are including the JPEG software in a larger +# program; you'd include it in your link, rather than the individual modules. +libjpeg.lib: $(LIBOBJECTS) + del libjpeg.lib + $(AR) libjpeg.lib nobackup batch 128 chars RFILE = libjpeg.ans @@ -44,7 +48,8 @@ INCLUDES= jinclude.h jconfig.h jpegdata.h jversion.h jmemsys.h DOCS= README SETUP USAGE CHANGELOG cjpeg.1 djpeg.1 architecture codingrules MAKEFILES= makefile.ansi makefile.unix makefile.manx makefile.sas \ makcjpeg.st makdjpeg.st makljpeg.st makefile.mc5 makefile.mc6 \ - makefile.bcc makefile.mms makefile.vms makvms.opt + makefile.bcc makefile.icc makljpeg.icc makefile.mms makefile.vms \ + makvms.opt OTHERFILES= ansi2knr.c ckconfig.c example.c TESTFILES= testorig.jpg testimg.ppm testimg.gif testimg.jpg DISTFILES= $(DOCS) $(MAKEFILES) $(SOURCES) $(SYSDEPFILES) $(INCLUDES) \ @@ -112,12 +117,12 @@ clean: test: del testout.* - djpeg testorig.jpg testout.ppm - djpeg -gif testorig.jpg testout.gif - cjpeg testimg.ppm testout.jpg - fc testimg.ppm testout.ppm - fc testimg.gif testout.gif - fc testimg.jpg testout.jpg + djpeg -outfile testout.ppm testorig.jpg + djpeg -gif -outfile testout.gif testorig.jpg + cjpeg -outfile testout.jpg testimg.ppm + fc /b testimg.ppm testout.ppm + fc /b testimg.gif testout.gif + fc /b testimg.jpg testout.jpg jbsmooth.obj : jbsmooth.c jinclude.h jconfig.h jpegdata.h diff --git a/makefile.mms b/makefile.mms index 690e96d..57818b6 100644 --- a/makefile.mms +++ b/makefile.mms @@ -28,7 +28,8 @@ INCLUDES= jinclude.h jconfig.h jpegdata.h jversion.h jmemsys.h DOCS= README SETUP USAGE CHANGELOG cjpeg.1 djpeg.1 architecture codingrules MAKEFILES= makefile.ansi makefile.unix makefile.manx makefile.sas \ makcjpeg.st makdjpeg.st makljpeg.st makefile.mc5 makefile.mc6 \ - makefile.bcc makefile.mms makefile.vms makvms.opt + makefile.bcc makefile.icc makljpeg.icc makefile.mms makefile.vms \ + makvms.opt OTHERFILES= ansi2knr.c ckconfig.c example.c TESTFILES= testorig.jpg testimg.ppm testimg.gif testimg.jpg DISTFILES= $(DOCS) $(MAKEFILES) $(SOURCES) $(SYSDEPFILES) $(INCLUDES) \ diff --git a/makefile.sas b/makefile.sas index 458251a..7da8570 100644 --- a/makefile.sas +++ b/makefile.sas @@ -1,37 +1,41 @@ # Makefile for Independent JPEG Group's software -# This makefile is for Amiga systems using SAS C 5.10b. -# Use jmemname.c as the system-dependent memory manager. -# Contributed by Ed Hanway (sisd!jeh@uunet.uu.net). +# This makefile is for Amiga systems using SAS C 6.0 and up. +# Thanks to Ed Hanway, Mark Rinfret, and Jim Zepeda. # Read SETUP instructions before saying "make" !! +# Use jmemname.c as the system-dependent memory manager. # The name of your C compiler: -CC= lc +CC= sc # Uncomment the following lines for generic 680x0 version -ARCHFLAGS= +ARCHFLAGS= cpu=any SUFFIX= # Uncomment the following lines for 68030-only version -#ARCHFLAGS= -m3 +#ARCHFLAGS= cpu=68030 #SUFFIX=.030 # You may need to adjust these cc options: -CFLAGS= -v -b -rr -O -j104 $(ARCHFLAGS) -DHAVE_STDC -DINCLUDES_ARE_ANSI \ - -DAMIGA -DTWO_FILE_COMMANDLINE -DINCOMPLETE_TYPES_BROKEN \ - -DNO_MKTEMP -DNEED_SIGNAL_CATCHER -DSHORTxSHORT_32 -# -j104 disables warnings for mismatched const qualifiers +CFLAGS= nostackcheck data=near parms=register optimize $(ARCHFLAGS) \ + ignore=104 ignore=304 ignore=306 \ + define HAVE_STDC define INCLUDES_ARE_ANSI \ + define AMIGA define TWO_FILE_COMMANDLINE \ + define NO_MKTEMP define NEED_SIGNAL_CATCHER define SHORTxSHORT_32 +# ignore=104 disables warnings for mismatched const qualifiers +# ignore=304 disables warnings for variables being optimized out +# ignore=306 disables warnings for the inlining of functions # Link-time cc options: LDFLAGS= SC SD ND BATCH # To link any special libraries, add the necessary commands here. -LDLIBS= LIB LIB:lcr.lib +LDLIBS= LIB LIB:scm.lib LIB:sc.lib # miscellaneous OS-dependent stuff # linker -LN= blink +LN= slink # file deletion command RM= delete quiet # library (.lib) file creation command @@ -56,7 +60,8 @@ INCLUDES= jinclude.h jconfig.h jpegdata.h jversion.h jmemsys.h DOCS= README SETUP USAGE CHANGELOG cjpeg.1 djpeg.1 architecture codingrules MAKEFILES= makefile.ansi makefile.unix makefile.manx makefile.sas \ makcjpeg.st makdjpeg.st makljpeg.st makefile.mc5 makefile.mc6 \ - makefile.bcc makefile.mms makefile.vms makvms.opt + makefile.bcc makefile.icc makljpeg.icc makefile.mms makefile.vms \ + makvms.opt OTHERFILES= ansi2knr.c ckconfig.c example.c TESTFILES= testorig.jpg testimg.ppm testimg.gif testimg.jpg DISTFILES= $(DOCS) $(MAKEFILES) $(SOURCES) $(SYSDEPFILES) $(INCLUDES) \ @@ -119,9 +124,9 @@ distribute: test: cjpeg djpeg -$(RM) testout.ppm testout.gif testout.jpg - djpeg testorig.jpg testout.ppm - djpeg -gif testorig.jpg testout.gif - cjpeg testimg.ppm testout.jpg + djpeg -outfile testout.ppm testorig.jpg + djpeg -gif -outfile testout.gif testorig.jpg + cjpeg -outfile testout.jpg testimg.ppm cmp testimg.ppm testout.ppm cmp testimg.gif testout.gif cmp testimg.jpg testout.jpg diff --git a/makefile.unix b/makefile.unix index 0681c92..6e6699b 100644 --- a/makefile.unix +++ b/makefile.unix @@ -56,7 +56,8 @@ INCLUDES= jinclude.h jconfig.h jpegdata.h jversion.h jmemsys.h DOCS= README SETUP USAGE CHANGELOG cjpeg.1 djpeg.1 architecture codingrules MAKEFILES= makefile.ansi makefile.unix makefile.manx makefile.sas \ makcjpeg.st makdjpeg.st makljpeg.st makefile.mc5 makefile.mc6 \ - makefile.bcc makefile.mms makefile.vms makvms.opt + makefile.bcc makefile.icc makljpeg.icc makefile.mms makefile.vms \ + makvms.opt OTHERFILES= ansi2knr.c ckconfig.c example.c TESTFILES= testorig.jpg testimg.ppm testimg.gif testimg.jpg DISTFILES= $(DOCS) $(MAKEFILES) $(SOURCES) $(SYSDEPFILES) $(INCLUDES) \ diff --git a/makljpeg.icc b/makljpeg.icc new file mode 100644 index 0000000..1c34db8 --- /dev/null +++ b/makljpeg.icc @@ -0,0 +1,38 @@ +add jcmaster.obj +add jcdeflts.obj +add jcarith.obj +add jccolor.obj +add jcexpand.obj +add jchuff.obj +add jcmcu.obj +add jcpipe.obj +add jcsample.obj +add jfwddct.obj +add jwrjfif.obj +add jrdgif.obj +add jrdppm.obj +add jrdrle.obj +add jrdtarga.obj +add jdmaster.obj +add jddeflts.obj +add jbsmooth.obj +add jdarith.obj +add jdcolor.obj +add jdhuff.obj +add jdmcu.obj +add jdpipe.obj +add jdsample.obj +add jquant1.obj +add jquant2.obj +add jrevdct.obj +add jrdjfif.obj +add jwrgif.obj +add jwrppm.obj +add jwrrle.obj +add jwrtarga.obj +add jutils.obj +add jerror.obj +add jmemmgr.obj +add jmemsys.obj +update +quit