mirror of
https://github.com/ultimatepp/ultimatepp.git
synced 2026-08-25 14:22:54 -06:00
plugin/jpeg: Upgraded to 9f
This commit is contained in:
parent
c030c504a2
commit
98cfda4a9c
28 changed files with 375 additions and 5029 deletions
|
|
@ -1,181 +0,0 @@
|
|||
/*
|
||||
* cdjpeg.c
|
||||
*
|
||||
* Copyright (C) 1991-1997, 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.
|
||||
*
|
||||
* This file contains common support routines used by the IJG application
|
||||
* programs (cjpeg, djpeg, jpegtran).
|
||||
*/
|
||||
|
||||
#include "cdjpeg.h" /* Common decls for cjpeg/djpeg applications */
|
||||
#include <ctype.h> /* to declare isupper(), tolower() */
|
||||
#ifdef NEED_SIGNAL_CATCHER
|
||||
#include <signal.h> /* to declare signal() */
|
||||
#endif
|
||||
#ifdef USE_SETMODE
|
||||
#include <fcntl.h> /* to declare setmode()'s parameter macros */
|
||||
/* If you have setmode() but not <io.h>, just delete this line: */
|
||||
#include <io.h> /* to declare setmode() */
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* Signal catcher to ensure that temporary files are removed before aborting.
|
||||
* NB: for Amiga Manx C this is actually a global routine named _abort();
|
||||
* we put "#define signal_catcher _abort" in jconfig.h. Talk about bogus...
|
||||
*/
|
||||
|
||||
#ifdef NEED_SIGNAL_CATCHER
|
||||
|
||||
static j_common_ptr sig_cinfo;
|
||||
|
||||
void /* must be global for Manx C */
|
||||
signal_catcher (int signum)
|
||||
{
|
||||
if (sig_cinfo != NULL) {
|
||||
if (sig_cinfo->err != NULL) /* turn off trace output */
|
||||
sig_cinfo->err->trace_level = 0;
|
||||
jpeg_destroy(sig_cinfo); /* clean up memory allocation & temp files */
|
||||
}
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
|
||||
GLOBAL(void)
|
||||
enable_signal_catcher (j_common_ptr cinfo)
|
||||
{
|
||||
sig_cinfo = cinfo;
|
||||
#ifdef SIGINT /* not all systems have SIGINT */
|
||||
signal(SIGINT, signal_catcher);
|
||||
#endif
|
||||
#ifdef SIGTERM /* not all systems have SIGTERM */
|
||||
signal(SIGTERM, signal_catcher);
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* Optional progress monitor: display a percent-done figure on stderr.
|
||||
*/
|
||||
|
||||
#ifdef PROGRESS_REPORT
|
||||
|
||||
METHODDEF(void)
|
||||
progress_monitor (j_common_ptr cinfo)
|
||||
{
|
||||
cd_progress_ptr prog = (cd_progress_ptr) cinfo->progress;
|
||||
int total_passes = prog->pub.total_passes + prog->total_extra_passes;
|
||||
int percent_done = (int) (prog->pub.pass_counter*100L/prog->pub.pass_limit);
|
||||
|
||||
if (percent_done != prog->percent_done) {
|
||||
prog->percent_done = percent_done;
|
||||
if (total_passes > 1) {
|
||||
fprintf(stderr, "\rPass %d/%d: %3d%% ",
|
||||
prog->pub.completed_passes + prog->completed_extra_passes + 1,
|
||||
total_passes, percent_done);
|
||||
} else {
|
||||
fprintf(stderr, "\r %3d%% ", percent_done);
|
||||
}
|
||||
fflush(stderr);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
GLOBAL(void)
|
||||
start_progress_monitor (j_common_ptr cinfo, cd_progress_ptr progress)
|
||||
{
|
||||
/* Enable progress display, unless trace output is on */
|
||||
if (cinfo->err->trace_level == 0) {
|
||||
progress->pub.progress_monitor = progress_monitor;
|
||||
progress->completed_extra_passes = 0;
|
||||
progress->total_extra_passes = 0;
|
||||
progress->percent_done = -1;
|
||||
cinfo->progress = &progress->pub;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
GLOBAL(void)
|
||||
end_progress_monitor (j_common_ptr cinfo)
|
||||
{
|
||||
/* Clear away progress display */
|
||||
if (cinfo->err->trace_level == 0) {
|
||||
fprintf(stderr, "\r \r");
|
||||
fflush(stderr);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* Case-insensitive matching of possibly-abbreviated keyword switches.
|
||||
* keyword is the constant keyword (must be lower case already),
|
||||
* minchars is length of minimum legal abbreviation.
|
||||
*/
|
||||
|
||||
GLOBAL(boolean)
|
||||
keymatch (char * arg, const char * keyword, int minchars)
|
||||
{
|
||||
register int ca, ck;
|
||||
register int nmatched = 0;
|
||||
|
||||
while ((ca = *arg++) != '\0') {
|
||||
if ((ck = *keyword++) == '\0')
|
||||
return FALSE; /* arg longer than keyword, no good */
|
||||
if (isupper(ca)) /* force arg to lcase (assume ck is already) */
|
||||
ca = tolower(ca);
|
||||
if (ca != ck)
|
||||
return FALSE; /* no good */
|
||||
nmatched++; /* count matched characters */
|
||||
}
|
||||
/* reached end of argument; fail if it's too short for unique abbrev */
|
||||
if (nmatched < minchars)
|
||||
return FALSE;
|
||||
return TRUE; /* A-OK */
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Routines to establish binary I/O mode for stdin and stdout.
|
||||
* Non-Unix systems often require some hacking to get out of text mode.
|
||||
*/
|
||||
|
||||
GLOBAL(FILE *)
|
||||
read_stdin (void)
|
||||
{
|
||||
FILE * input_file = 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 ((input_file = fdopen(fileno(stdin), READ_BINARY)) == NULL) {
|
||||
fprintf(stderr, "Cannot reopen stdin\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
#endif
|
||||
return input_file;
|
||||
}
|
||||
|
||||
|
||||
GLOBAL(FILE *)
|
||||
write_stdout (void)
|
||||
{
|
||||
FILE * output_file = 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 ((output_file = fdopen(fileno(stdout), WRITE_BINARY)) == NULL) {
|
||||
fprintf(stderr, "Cannot reopen stdout\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
#endif
|
||||
return output_file;
|
||||
}
|
||||
|
|
@ -2,7 +2,7 @@
|
|||
* alternate cjpeg.c
|
||||
*
|
||||
* Copyright (C) 1991-1998, Thomas G. Lane.
|
||||
* Modified 2009-2020 by Guido Vollbeding.
|
||||
* Modified 2009-2023 by Guido Vollbeding.
|
||||
* This file is part of the Independent JPEG Group's software.
|
||||
* For conditions of distribution and use, see the accompanying README file.
|
||||
*
|
||||
|
|
@ -72,7 +72,7 @@ unused_dos_memory (void)
|
|||
|
||||
#endif /* MSDOS */
|
||||
|
||||
#ifdef ATARI /* For Atari ST/STE/TT, Pure C or Turbo C */
|
||||
#ifdef ATARI /* For Atari ST/Mega/STE/TT/Falcon, Pure C or Turbo C */
|
||||
|
||||
#include <ext.h>
|
||||
|
||||
|
|
|
|||
|
|
@ -1,402 +0,0 @@
|
|||
/*
|
||||
* ckconfig.c
|
||||
*
|
||||
* Copyright (C) 1991-1994, 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This program is intended to help you determine how to configure the JPEG
|
||||
* software for installation on a particular system. The idea is to try to
|
||||
* compile and execute this program. If your compiler fails to compile the
|
||||
* program, make changes as indicated in the comments below. Once you can
|
||||
* compile the program, run it, and it will produce a "jconfig.h" file for
|
||||
* your system.
|
||||
*
|
||||
* As a general rule, each time you try to compile this program,
|
||||
* pay attention only to the *first* error message you get from the compiler.
|
||||
* Many C compilers will issue lots of spurious error messages once they
|
||||
* have gotten confused. Go to the line indicated in the first error message,
|
||||
* and read the comments preceding that line to see what to change.
|
||||
*
|
||||
* Almost all of the edits you may need to make to this program consist of
|
||||
* changing a line that reads "#define SOME_SYMBOL" to "#undef SOME_SYMBOL",
|
||||
* or vice versa. This is called defining or undefining that symbol.
|
||||
*/
|
||||
|
||||
|
||||
/* First we must see if your system has the include files we need.
|
||||
* We start out with the assumption that your system has all the ANSI-standard
|
||||
* include files. If you get any error trying to include one of these files,
|
||||
* undefine the corresponding HAVE_xxx symbol.
|
||||
*/
|
||||
|
||||
#define HAVE_STDDEF_H /* replace 'define' by 'undef' if error here */
|
||||
#ifdef HAVE_STDDEF_H /* next line will be skipped if you undef... */
|
||||
#include <stddef.h>
|
||||
#endif
|
||||
|
||||
#define HAVE_STDLIB_H /* same thing for stdlib.h */
|
||||
#ifdef HAVE_STDLIB_H
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
|
||||
#include <stdio.h> /* If you ain't got this, you ain't got C. */
|
||||
|
||||
/* We have to see if your string functions are defined by
|
||||
* strings.h (old BSD convention) or string.h (everybody else).
|
||||
* We try the non-BSD convention first; define NEED_BSD_STRINGS
|
||||
* if the compiler says it can't find string.h.
|
||||
*/
|
||||
|
||||
#undef NEED_BSD_STRINGS
|
||||
|
||||
#ifdef NEED_BSD_STRINGS
|
||||
#include <strings.h>
|
||||
#else
|
||||
#include <string.h>
|
||||
#endif
|
||||
|
||||
/* On some systems (especially older Unix machines), type size_t is
|
||||
* defined only in the include file <sys/types.h>. If you get a failure
|
||||
* on the size_t test below, try defining NEED_SYS_TYPES_H.
|
||||
*/
|
||||
|
||||
#undef NEED_SYS_TYPES_H /* start by assuming we don't need it */
|
||||
#ifdef NEED_SYS_TYPES_H
|
||||
#include <sys/types.h>
|
||||
#endif
|
||||
|
||||
|
||||
/* Usually type size_t is defined in one of the include files we've included
|
||||
* above. If not, you'll get an error on the "typedef size_t my_size_t;" line.
|
||||
* In that case, first try defining NEED_SYS_TYPES_H just above.
|
||||
* If that doesn't work, you'll have to search through your system library
|
||||
* to figure out which include file defines "size_t". Look for a line that
|
||||
* says "typedef something-or-other size_t;". Then, change the line below
|
||||
* that says "#include <someincludefile.h>" to instead include the file
|
||||
* you found size_t in, and define NEED_SPECIAL_INCLUDE. If you can't find
|
||||
* type size_t anywhere, try replacing "#include <someincludefile.h>" with
|
||||
* "typedef unsigned int size_t;".
|
||||
*/
|
||||
|
||||
#undef NEED_SPECIAL_INCLUDE /* assume we DON'T need it, for starters */
|
||||
|
||||
#ifdef NEED_SPECIAL_INCLUDE
|
||||
#include <someincludefile.h>
|
||||
#endif
|
||||
|
||||
typedef size_t my_size_t; /* The payoff: do we have size_t now? */
|
||||
|
||||
|
||||
/* The next question is whether your compiler supports ANSI-style function
|
||||
* prototypes. You need to know this in order to choose between using
|
||||
* makefile.ansi and using makefile.unix.
|
||||
* The #define line below is set to assume you have ANSI function prototypes.
|
||||
* If you get an error in this group of lines, undefine HAVE_PROTOTYPES.
|
||||
*/
|
||||
|
||||
#define HAVE_PROTOTYPES
|
||||
|
||||
#ifdef HAVE_PROTOTYPES
|
||||
int testfunction (int arg1, int * arg2); /* check prototypes */
|
||||
|
||||
struct methods_struct { /* check method-pointer declarations */
|
||||
int (*error_exit) (char *msgtext);
|
||||
int (*trace_message) (char *msgtext);
|
||||
int (*another_method) (void);
|
||||
};
|
||||
|
||||
int testfunction (int arg1, int * arg2) /* check definitions */
|
||||
{
|
||||
return arg2[arg1];
|
||||
}
|
||||
|
||||
int test2function (void) /* check void arg list */
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/* Now we want to find out if your compiler knows what "unsigned char" means.
|
||||
* If you get an error on the "unsigned char un_char;" line,
|
||||
* then undefine HAVE_UNSIGNED_CHAR.
|
||||
*/
|
||||
|
||||
#define HAVE_UNSIGNED_CHAR
|
||||
|
||||
#ifdef HAVE_UNSIGNED_CHAR
|
||||
unsigned char un_char;
|
||||
#endif
|
||||
|
||||
|
||||
/* Now we want to find out if your compiler knows what "unsigned short" means.
|
||||
* If you get an error on the "unsigned short un_short;" line,
|
||||
* then undefine HAVE_UNSIGNED_SHORT.
|
||||
*/
|
||||
|
||||
#define HAVE_UNSIGNED_SHORT
|
||||
|
||||
#ifdef HAVE_UNSIGNED_SHORT
|
||||
unsigned short un_short;
|
||||
#endif
|
||||
|
||||
|
||||
/* Now we want to find out if your compiler understands type "void".
|
||||
* If you get an error anywhere in here, undefine HAVE_VOID.
|
||||
*/
|
||||
|
||||
#define HAVE_VOID
|
||||
|
||||
#ifdef HAVE_VOID
|
||||
/* Caution: a C++ compiler will insist on complete prototypes */
|
||||
typedef void * void_ptr; /* check void * */
|
||||
#ifdef HAVE_PROTOTYPES /* check ptr to function returning void */
|
||||
typedef void (*void_func) (int a, int b);
|
||||
#else
|
||||
typedef void (*void_func) ();
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_PROTOTYPES /* check void function result */
|
||||
void test3function (void_ptr arg1, void_func arg2)
|
||||
#else
|
||||
void test3function (arg1, arg2)
|
||||
void_ptr arg1;
|
||||
void_func arg2;
|
||||
#endif
|
||||
{
|
||||
char * locptr = (char *) arg1; /* check casting to and from void * */
|
||||
arg1 = (void *) locptr;
|
||||
(*arg2) (1, 2); /* check call of fcn returning void */
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/* Now we want to find out if your compiler knows what "const" means.
|
||||
* If you get an error here, undefine HAVE_CONST.
|
||||
*/
|
||||
|
||||
#define HAVE_CONST
|
||||
|
||||
#ifdef HAVE_CONST
|
||||
static const int carray[3] = {1, 2, 3};
|
||||
|
||||
#ifdef HAVE_PROTOTYPES
|
||||
int test4function (const int arg1)
|
||||
#else
|
||||
int test4function (arg1)
|
||||
const int arg1;
|
||||
#endif
|
||||
{
|
||||
return carray[arg1];
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/* If you get an error or warning about this structure definition,
|
||||
* define INCOMPLETE_TYPES_BROKEN.
|
||||
*/
|
||||
|
||||
#undef INCOMPLETE_TYPES_BROKEN
|
||||
|
||||
#ifndef INCOMPLETE_TYPES_BROKEN
|
||||
typedef struct undefined_structure * undef_struct_ptr;
|
||||
#endif
|
||||
|
||||
|
||||
/* If you get an error about duplicate names,
|
||||
* define NEED_SHORT_EXTERNAL_NAMES.
|
||||
*/
|
||||
|
||||
#undef NEED_SHORT_EXTERNAL_NAMES
|
||||
|
||||
#ifndef NEED_SHORT_EXTERNAL_NAMES
|
||||
|
||||
int possibly_duplicate_function ()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int possibly_dupli_function ()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/************************************************************************
|
||||
* OK, that's it. You should not have to change anything beyond this
|
||||
* point in order to compile and execute this program. (You might get
|
||||
* some warnings, but you can ignore them.)
|
||||
* When you run the program, it will make a couple more tests that it
|
||||
* can do automatically, and then it will create jconfig.h and print out
|
||||
* any additional suggestions it has.
|
||||
************************************************************************
|
||||
*/
|
||||
|
||||
|
||||
#ifdef HAVE_PROTOTYPES
|
||||
int is_char_signed (int arg)
|
||||
#else
|
||||
int is_char_signed (arg)
|
||||
int arg;
|
||||
#endif
|
||||
{
|
||||
if (arg == 189) { /* expected result for unsigned char */
|
||||
return 0; /* type char is unsigned */
|
||||
}
|
||||
else if (arg != -67) { /* expected result for signed char */
|
||||
printf("Hmm, it seems 'char' is not eight bits wide on your machine.\n");
|
||||
printf("I fear the JPEG software will not work at all.\n\n");
|
||||
}
|
||||
return 1; /* assume char is signed otherwise */
|
||||
}
|
||||
|
||||
|
||||
#ifdef HAVE_PROTOTYPES
|
||||
int is_shifting_signed (long arg)
|
||||
#else
|
||||
int is_shifting_signed (arg)
|
||||
long arg;
|
||||
#endif
|
||||
/* See whether right-shift on a long is signed or not. */
|
||||
{
|
||||
long res = arg >> 4;
|
||||
|
||||
if (res == -0x7F7E80CL) { /* expected result for signed shift */
|
||||
return 1; /* right shift is signed */
|
||||
}
|
||||
/* see if unsigned-shift hack will fix it. */
|
||||
/* we can't just test exact value since it depends on width of long... */
|
||||
res |= (~0L) << (32-4);
|
||||
if (res == -0x7F7E80CL) { /* expected result now? */
|
||||
return 0; /* right shift is unsigned */
|
||||
}
|
||||
printf("Right shift isn't acting as I expect it to.\n");
|
||||
printf("I fear the JPEG software will not work at all.\n\n");
|
||||
return 0; /* try it with unsigned anyway */
|
||||
}
|
||||
|
||||
|
||||
#ifdef HAVE_PROTOTYPES
|
||||
int main (int argc, char ** argv)
|
||||
#else
|
||||
int main (argc, argv)
|
||||
int argc;
|
||||
char ** argv;
|
||||
#endif
|
||||
{
|
||||
char signed_char_check = (char) (-67);
|
||||
FILE *outfile;
|
||||
|
||||
/* Attempt to write jconfig.h */
|
||||
if ((outfile = fopen("jconfig.h", "w")) == NULL) {
|
||||
printf("Failed to write jconfig.h\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Write out all the info */
|
||||
fprintf(outfile, "/* jconfig.h --- generated by ckconfig.c */\n");
|
||||
fprintf(outfile, "/* see jconfig.txt for explanations */\n\n");
|
||||
#ifdef HAVE_PROTOTYPES
|
||||
fprintf(outfile, "#define HAVE_PROTOTYPES\n");
|
||||
#else
|
||||
fprintf(outfile, "#undef HAVE_PROTOTYPES\n");
|
||||
#endif
|
||||
#ifdef HAVE_UNSIGNED_CHAR
|
||||
fprintf(outfile, "#define HAVE_UNSIGNED_CHAR\n");
|
||||
#else
|
||||
fprintf(outfile, "#undef HAVE_UNSIGNED_CHAR\n");
|
||||
#endif
|
||||
#ifdef HAVE_UNSIGNED_SHORT
|
||||
fprintf(outfile, "#define HAVE_UNSIGNED_SHORT\n");
|
||||
#else
|
||||
fprintf(outfile, "#undef HAVE_UNSIGNED_SHORT\n");
|
||||
#endif
|
||||
#ifdef HAVE_VOID
|
||||
fprintf(outfile, "/* #define void char */\n");
|
||||
#else
|
||||
fprintf(outfile, "#define void char\n");
|
||||
#endif
|
||||
#ifdef HAVE_CONST
|
||||
fprintf(outfile, "/* #define const */\n");
|
||||
#else
|
||||
fprintf(outfile, "#define const\n");
|
||||
#endif
|
||||
if (is_char_signed((int) signed_char_check))
|
||||
fprintf(outfile, "#undef CHAR_IS_UNSIGNED\n");
|
||||
else
|
||||
fprintf(outfile, "#define CHAR_IS_UNSIGNED\n");
|
||||
#ifdef HAVE_STDDEF_H
|
||||
fprintf(outfile, "#define HAVE_STDDEF_H\n");
|
||||
#else
|
||||
fprintf(outfile, "#undef HAVE_STDDEF_H\n");
|
||||
#endif
|
||||
#ifdef HAVE_STDLIB_H
|
||||
fprintf(outfile, "#define HAVE_STDLIB_H\n");
|
||||
#else
|
||||
fprintf(outfile, "#undef HAVE_STDLIB_H\n");
|
||||
#endif
|
||||
#ifdef NEED_BSD_STRINGS
|
||||
fprintf(outfile, "#define NEED_BSD_STRINGS\n");
|
||||
#else
|
||||
fprintf(outfile, "#undef NEED_BSD_STRINGS\n");
|
||||
#endif
|
||||
#ifdef NEED_SYS_TYPES_H
|
||||
fprintf(outfile, "#define NEED_SYS_TYPES_H\n");
|
||||
#else
|
||||
fprintf(outfile, "#undef NEED_SYS_TYPES_H\n");
|
||||
#endif
|
||||
fprintf(outfile, "#undef NEED_FAR_POINTERS\n");
|
||||
#ifdef NEED_SHORT_EXTERNAL_NAMES
|
||||
fprintf(outfile, "#define NEED_SHORT_EXTERNAL_NAMES\n");
|
||||
#else
|
||||
fprintf(outfile, "#undef NEED_SHORT_EXTERNAL_NAMES\n");
|
||||
#endif
|
||||
#ifdef INCOMPLETE_TYPES_BROKEN
|
||||
fprintf(outfile, "#define INCOMPLETE_TYPES_BROKEN\n");
|
||||
#else
|
||||
fprintf(outfile, "#undef INCOMPLETE_TYPES_BROKEN\n");
|
||||
#endif
|
||||
fprintf(outfile, "\n#ifdef JPEG_INTERNALS\n\n");
|
||||
if (is_shifting_signed(-0x7F7E80B1L))
|
||||
fprintf(outfile, "#undef RIGHT_SHIFT_IS_UNSIGNED\n");
|
||||
else
|
||||
fprintf(outfile, "#define RIGHT_SHIFT_IS_UNSIGNED\n");
|
||||
fprintf(outfile, "\n#endif /* JPEG_INTERNALS */\n");
|
||||
fprintf(outfile, "\n#ifdef JPEG_CJPEG_DJPEG\n\n");
|
||||
fprintf(outfile, "#define BMP_SUPPORTED /* BMP image file format */\n");
|
||||
fprintf(outfile, "#define GIF_SUPPORTED /* GIF image file format */\n");
|
||||
fprintf(outfile, "#define PPM_SUPPORTED /* PBMPLUS PPM/PGM image file format */\n");
|
||||
fprintf(outfile, "#undef RLE_SUPPORTED /* Utah RLE image file format */\n");
|
||||
fprintf(outfile, "#define TARGA_SUPPORTED /* Targa image file format */\n\n");
|
||||
fprintf(outfile, "#undef TWO_FILE_COMMANDLINE /* You may need this on non-Unix systems */\n");
|
||||
fprintf(outfile, "#undef NEED_SIGNAL_CATCHER /* Define this if you use jmemname.c */\n");
|
||||
fprintf(outfile, "#undef DONT_USE_B_MODE\n");
|
||||
fprintf(outfile, "/* #define PROGRESS_REPORT */ /* optional */\n");
|
||||
fprintf(outfile, "\n#endif /* JPEG_CJPEG_DJPEG */\n");
|
||||
|
||||
/* Close the jconfig.h file */
|
||||
fclose(outfile);
|
||||
|
||||
/* User report */
|
||||
printf("Configuration check for Independent JPEG Group's software done.\n");
|
||||
printf("\nI have written the jconfig.h file for you.\n\n");
|
||||
#ifdef HAVE_PROTOTYPES
|
||||
printf("You should use makefile.ansi as the starting point for your Makefile.\n");
|
||||
#else
|
||||
printf("You should use makefile.unix as the starting point for your Makefile.\n");
|
||||
#endif
|
||||
|
||||
#ifdef NEED_SPECIAL_INCLUDE
|
||||
printf("\nYou'll need to change jconfig.h to include the system include file\n");
|
||||
printf("that you found type size_t in, or add a direct definition of type\n");
|
||||
printf("size_t if that's what you used. Just add it to the end.\n");
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -1,631 +0,0 @@
|
|||
/*
|
||||
* djpeg.c
|
||||
*
|
||||
* Copyright (C) 1991-1997, Thomas G. Lane.
|
||||
* Modified 2009-2019 by Guido Vollbeding.
|
||||
* This file is part of the Independent JPEG Group's software.
|
||||
* For conditions of distribution and use, see the accompanying README file.
|
||||
*
|
||||
* This file contains a command-line user interface for the JPEG decompressor.
|
||||
* It should work on any system with Unix- or MS-DOS-style command lines.
|
||||
*
|
||||
* Two different command line styles are permitted, depending on the
|
||||
* compile-time switch TWO_FILE_COMMANDLINE:
|
||||
* djpeg [options] inputfile outputfile
|
||||
* djpeg [options] [inputfile]
|
||||
* In the second style, output is always to standard output, which you'd
|
||||
* normally redirect to a file or pipe to some other program. Input is
|
||||
* either from a named file or from standard input (typically redirected).
|
||||
* 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 "cdjpeg.h" /* Common decls for cjpeg/djpeg applications */
|
||||
#include "jversion.h" /* for version message */
|
||||
|
||||
#include <ctype.h> /* to declare isprint() */
|
||||
|
||||
#ifdef USE_CCOMMAND /* command-line reader for Macintosh */
|
||||
#ifdef __MWERKS__
|
||||
#include <SIOUX.h> /* Metrowerks needs this */
|
||||
#include <console.h> /* ... and this */
|
||||
#endif
|
||||
#ifdef THINK_C
|
||||
#include <console.h> /* Think declares it here */
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
/* Create the add-on message string table. */
|
||||
|
||||
#define JMESSAGE(code,string) string ,
|
||||
|
||||
static const char * const cdjpeg_message_table[] = {
|
||||
#include "cderror.h"
|
||||
NULL
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* This list defines the known output image formats
|
||||
* (not all of which need be supported by a given version).
|
||||
* You can change the default output format by defining DEFAULT_FMT;
|
||||
* indeed, you had better do so if you undefine PPM_SUPPORTED.
|
||||
*/
|
||||
|
||||
typedef enum {
|
||||
FMT_BMP, /* BMP format (Windows flavor) */
|
||||
FMT_GIF, /* GIF format (LZW compressed) */
|
||||
FMT_GIF0, /* GIF format (uncompressed) */
|
||||
FMT_OS2, /* BMP format (OS/2 flavor) */
|
||||
FMT_PPM, /* PPM/PGM (PBMPLUS formats) */
|
||||
FMT_RLE, /* RLE format */
|
||||
FMT_TARGA, /* Targa format */
|
||||
FMT_TIFF /* TIFF format */
|
||||
} IMAGE_FORMATS;
|
||||
|
||||
#ifndef DEFAULT_FMT /* so can override from CFLAGS in Makefile */
|
||||
#define DEFAULT_FMT FMT_PPM
|
||||
#endif
|
||||
|
||||
static IMAGE_FORMATS requested_fmt;
|
||||
|
||||
|
||||
/*
|
||||
* Argument-parsing code.
|
||||
* The switch parser is designed to be useful with DOS-style command line
|
||||
* syntax, ie, intermixed switches and file names, where only the switches
|
||||
* to the left of a given file name affect processing of that file.
|
||||
* The main program in this file doesn't actually use this capability...
|
||||
*/
|
||||
|
||||
|
||||
static const char * progname; /* program name for error messages */
|
||||
static char * outfilename; /* for -outfile switch */
|
||||
|
||||
|
||||
LOCAL(void)
|
||||
usage (void)
|
||||
/* complain about bad command line */
|
||||
{
|
||||
fprintf(stderr, "usage: %s [switches] ", progname);
|
||||
#ifdef TWO_FILE_COMMANDLINE
|
||||
fprintf(stderr, "inputfile outputfile\n");
|
||||
#else
|
||||
fprintf(stderr, "[inputfile]\n");
|
||||
#endif
|
||||
|
||||
fprintf(stderr, "Switches (names may be abbreviated):\n");
|
||||
fprintf(stderr, " -colors N Reduce image to no more than N colors\n");
|
||||
fprintf(stderr, " -fast Fast, low-quality processing\n");
|
||||
fprintf(stderr, " -grayscale Force grayscale output\n");
|
||||
fprintf(stderr, " -rgb Force RGB output\n");
|
||||
#ifdef IDCT_SCALING_SUPPORTED
|
||||
fprintf(stderr, " -scale M/N Scale output image by fraction M/N, eg, 1/8\n");
|
||||
#endif
|
||||
#ifdef BMP_SUPPORTED
|
||||
fprintf(stderr, " -bmp Select BMP output format (Windows style)%s\n",
|
||||
(DEFAULT_FMT == FMT_BMP ? " (default)" : ""));
|
||||
#endif
|
||||
#ifdef GIF_SUPPORTED
|
||||
fprintf(stderr, " -gif Select GIF output format (LZW compressed)%s\n",
|
||||
(DEFAULT_FMT == FMT_GIF ? " (default)" : ""));
|
||||
fprintf(stderr, " -gif0 Select GIF output format (uncompressed)%s\n",
|
||||
(DEFAULT_FMT == FMT_GIF0 ? " (default)" : ""));
|
||||
#endif
|
||||
#ifdef BMP_SUPPORTED
|
||||
fprintf(stderr, " -os2 Select BMP output format (OS/2 style)%s\n",
|
||||
(DEFAULT_FMT == FMT_OS2 ? " (default)" : ""));
|
||||
#endif
|
||||
#ifdef PPM_SUPPORTED
|
||||
fprintf(stderr, " -pnm Select PBMPLUS (PPM/PGM) output format%s\n",
|
||||
(DEFAULT_FMT == FMT_PPM ? " (default)" : ""));
|
||||
#endif
|
||||
#ifdef RLE_SUPPORTED
|
||||
fprintf(stderr, " -rle Select Utah RLE output format%s\n",
|
||||
(DEFAULT_FMT == FMT_RLE ? " (default)" : ""));
|
||||
#endif
|
||||
#ifdef TARGA_SUPPORTED
|
||||
fprintf(stderr, " -targa Select Targa output format%s\n",
|
||||
(DEFAULT_FMT == FMT_TARGA ? " (default)" : ""));
|
||||
#endif
|
||||
fprintf(stderr, "Switches for advanced users:\n");
|
||||
#ifdef DCT_ISLOW_SUPPORTED
|
||||
fprintf(stderr, " -dct int Use integer DCT method%s\n",
|
||||
(JDCT_DEFAULT == JDCT_ISLOW ? " (default)" : ""));
|
||||
#endif
|
||||
#ifdef DCT_IFAST_SUPPORTED
|
||||
fprintf(stderr, " -dct fast Use fast integer DCT (less accurate)%s\n",
|
||||
(JDCT_DEFAULT == JDCT_IFAST ? " (default)" : ""));
|
||||
#endif
|
||||
#ifdef DCT_FLOAT_SUPPORTED
|
||||
fprintf(stderr, " -dct float Use floating-point DCT method%s\n",
|
||||
(JDCT_DEFAULT == JDCT_FLOAT ? " (default)" : ""));
|
||||
#endif
|
||||
fprintf(stderr, " -dither fs Use F-S dithering (default)\n");
|
||||
fprintf(stderr, " -dither none Don't use dithering in quantization\n");
|
||||
fprintf(stderr, " -dither ordered Use ordered dither (medium speed, quality)\n");
|
||||
#ifdef QUANT_2PASS_SUPPORTED
|
||||
fprintf(stderr, " -map FILE Map to colors used in named image file\n");
|
||||
#endif
|
||||
fprintf(stderr, " -nosmooth Don't use high-quality upsampling\n");
|
||||
#ifdef QUANT_1PASS_SUPPORTED
|
||||
fprintf(stderr, " -onepass Use 1-pass quantization (fast, low quality)\n");
|
||||
#endif
|
||||
fprintf(stderr, " -maxmemory N Maximum memory to use (in kbytes)\n");
|
||||
fprintf(stderr, " -outfile name Specify name for output file\n");
|
||||
fprintf(stderr, " -verbose or -debug Emit debug output\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
|
||||
LOCAL(int)
|
||||
parse_switches (j_decompress_ptr cinfo, int argc, char **argv,
|
||||
int last_file_arg_seen, boolean for_real)
|
||||
/* Parse optional switches.
|
||||
* Returns argv[] index of first file-name argument (== argc if none).
|
||||
* Any file names with indexes <= last_file_arg_seen are ignored;
|
||||
* they have presumably been processed in a previous iteration.
|
||||
* (Pass 0 for last_file_arg_seen on the first or only iteration.)
|
||||
* for_real is FALSE on the first (dummy) pass; we may skip any expensive
|
||||
* processing.
|
||||
*/
|
||||
{
|
||||
int argn;
|
||||
char * arg;
|
||||
|
||||
/* Set up default JPEG parameters. */
|
||||
requested_fmt = DEFAULT_FMT; /* set default output file format */
|
||||
outfilename = NULL;
|
||||
cinfo->err->trace_level = 0;
|
||||
|
||||
/* Scan command line options, adjust parameters */
|
||||
|
||||
for (argn = 1; argn < argc; argn++) {
|
||||
arg = argv[argn];
|
||||
if (*arg != '-') {
|
||||
/* Not a switch, must be a file name argument */
|
||||
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 */
|
||||
|
||||
if (keymatch(arg, "bmp", 1)) {
|
||||
/* BMP output format (Windows flavor). */
|
||||
requested_fmt = FMT_BMP;
|
||||
|
||||
} else if (keymatch(arg, "colors", 1) || keymatch(arg, "colours", 1) ||
|
||||
keymatch(arg, "quantize", 1) || keymatch(arg, "quantise", 1)) {
|
||||
/* Do color quantization. */
|
||||
int val;
|
||||
|
||||
if (++argn >= argc) /* advance to next argument */
|
||||
usage();
|
||||
if (sscanf(argv[argn], "%d", &val) != 1)
|
||||
usage();
|
||||
cinfo->desired_number_of_colors = val;
|
||||
cinfo->quantize_colors = TRUE;
|
||||
|
||||
} else if (keymatch(arg, "dct", 2)) {
|
||||
/* Select IDCT algorithm. */
|
||||
if (++argn >= argc) /* advance to next argument */
|
||||
usage();
|
||||
if (keymatch(argv[argn], "int", 1)) {
|
||||
cinfo->dct_method = JDCT_ISLOW;
|
||||
} else if (keymatch(argv[argn], "fast", 2)) {
|
||||
cinfo->dct_method = JDCT_IFAST;
|
||||
} else if (keymatch(argv[argn], "float", 2)) {
|
||||
cinfo->dct_method = JDCT_FLOAT;
|
||||
} else
|
||||
usage();
|
||||
|
||||
} else if (keymatch(arg, "dither", 2)) {
|
||||
/* Select dithering algorithm. */
|
||||
if (++argn >= argc) /* advance to next argument */
|
||||
usage();
|
||||
if (keymatch(argv[argn], "fs", 2)) {
|
||||
cinfo->dither_mode = JDITHER_FS;
|
||||
} else if (keymatch(argv[argn], "none", 2)) {
|
||||
cinfo->dither_mode = JDITHER_NONE;
|
||||
} else if (keymatch(argv[argn], "ordered", 2)) {
|
||||
cinfo->dither_mode = JDITHER_ORDERED;
|
||||
} else
|
||||
usage();
|
||||
|
||||
} else if (keymatch(arg, "debug", 1) || keymatch(arg, "verbose", 1)) {
|
||||
/* Enable debug printouts. */
|
||||
/* On first -d, print version identification */
|
||||
static boolean printed_version = FALSE;
|
||||
|
||||
if (! printed_version) {
|
||||
fprintf(stderr, "Independent JPEG Group's DJPEG, version %s\n%s\n",
|
||||
JVERSION, JCOPYRIGHT);
|
||||
printed_version = TRUE;
|
||||
}
|
||||
cinfo->err->trace_level++;
|
||||
|
||||
} else if (keymatch(arg, "fast", 1)) {
|
||||
/* Select recommended processing options for quick-and-dirty output. */
|
||||
cinfo->two_pass_quantize = FALSE;
|
||||
cinfo->dither_mode = JDITHER_ORDERED;
|
||||
if (! cinfo->quantize_colors) /* don't override an earlier -colors */
|
||||
cinfo->desired_number_of_colors = 216;
|
||||
cinfo->dct_method = JDCT_FASTEST;
|
||||
cinfo->do_fancy_upsampling = FALSE;
|
||||
|
||||
} else if (keymatch(arg, "gif", 1)) {
|
||||
/* GIF output format (LZW compressed). */
|
||||
requested_fmt = FMT_GIF;
|
||||
|
||||
} else if (keymatch(arg, "gif0", 4)) {
|
||||
/* GIF output format (uncompressed). */
|
||||
requested_fmt = FMT_GIF0;
|
||||
|
||||
} else if (keymatch(arg, "grayscale", 2) || keymatch(arg, "greyscale",2)) {
|
||||
/* Force monochrome output. */
|
||||
cinfo->out_color_space = JCS_GRAYSCALE;
|
||||
|
||||
} else if (keymatch(arg, "rgb", 3)) {
|
||||
/* Force RGB output. */
|
||||
cinfo->out_color_space = JCS_RGB;
|
||||
|
||||
} else if (keymatch(arg, "map", 3)) {
|
||||
/* Quantize to a color map taken from an input file. */
|
||||
if (++argn >= argc) /* advance to next argument */
|
||||
usage();
|
||||
if (for_real) { /* too expensive to do twice! */
|
||||
#ifdef QUANT_2PASS_SUPPORTED /* otherwise can't quantize to supplied map */
|
||||
FILE * mapfile;
|
||||
|
||||
if ((mapfile = fopen(argv[argn], READ_BINARY)) == NULL) {
|
||||
fprintf(stderr, "%s: can't open %s\n", progname, argv[argn]);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
read_color_map(cinfo, mapfile);
|
||||
fclose(mapfile);
|
||||
cinfo->quantize_colors = TRUE;
|
||||
#else
|
||||
ERREXIT(cinfo, JERR_NOT_COMPILED);
|
||||
#endif
|
||||
}
|
||||
|
||||
} else if (keymatch(arg, "maxmemory", 3)) {
|
||||
/* Maximum memory in Kb (or Mb with 'm'). */
|
||||
long lval;
|
||||
char ch = 'x';
|
||||
|
||||
if (++argn >= argc) /* advance to next argument */
|
||||
usage();
|
||||
if (sscanf(argv[argn], "%ld%c", &lval, &ch) < 1)
|
||||
usage();
|
||||
if (ch == 'm' || ch == 'M')
|
||||
lval *= 1000L;
|
||||
cinfo->mem->max_memory_to_use = lval * 1000L;
|
||||
|
||||
} else if (keymatch(arg, "nosmooth", 3)) {
|
||||
/* Suppress fancy upsampling. */
|
||||
cinfo->do_fancy_upsampling = FALSE;
|
||||
|
||||
} else if (keymatch(arg, "onepass", 3)) {
|
||||
/* Use fast one-pass quantization. */
|
||||
cinfo->two_pass_quantize = FALSE;
|
||||
|
||||
} else if (keymatch(arg, "os2", 3)) {
|
||||
/* BMP output format (OS/2 flavor). */
|
||||
requested_fmt = FMT_OS2;
|
||||
|
||||
} else if (keymatch(arg, "outfile", 4)) {
|
||||
/* 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;
|
||||
|
||||
} else if (keymatch(arg, "rle", 1)) {
|
||||
/* RLE output format. */
|
||||
requested_fmt = FMT_RLE;
|
||||
|
||||
} else if (keymatch(arg, "scale", 1)) {
|
||||
/* Scale the output image by a fraction M/N. */
|
||||
if (++argn >= argc) /* advance to next argument */
|
||||
usage();
|
||||
if (sscanf(argv[argn], "%u/%u",
|
||||
&cinfo->scale_num, &cinfo->scale_denom) < 1)
|
||||
usage();
|
||||
|
||||
} else if (keymatch(arg, "targa", 1)) {
|
||||
/* Targa output format. */
|
||||
requested_fmt = FMT_TARGA;
|
||||
|
||||
} else {
|
||||
usage(); /* bogus switch */
|
||||
}
|
||||
}
|
||||
|
||||
return argn; /* return index of next arg (file name) */
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Marker processor for COM and interesting APPn markers.
|
||||
* This replaces the library's built-in processor, which just skips the marker.
|
||||
* We want to print out the marker as text, to the extent possible.
|
||||
* Note this code relies on a non-suspending data source.
|
||||
*/
|
||||
|
||||
LOCAL(unsigned int)
|
||||
jpeg_getc (j_decompress_ptr cinfo)
|
||||
/* Read next byte */
|
||||
{
|
||||
struct jpeg_source_mgr * datasrc = cinfo->src;
|
||||
|
||||
if (datasrc->bytes_in_buffer == 0) {
|
||||
if (! (*datasrc->fill_input_buffer) (cinfo))
|
||||
ERREXIT(cinfo, JERR_CANT_SUSPEND);
|
||||
}
|
||||
datasrc->bytes_in_buffer--;
|
||||
return GETJOCTET(*datasrc->next_input_byte++);
|
||||
}
|
||||
|
||||
|
||||
METHODDEF(boolean)
|
||||
print_text_marker (j_decompress_ptr cinfo)
|
||||
{
|
||||
boolean traceit = (cinfo->err->trace_level >= 1);
|
||||
INT32 length;
|
||||
unsigned int ch;
|
||||
unsigned int lastch = 0;
|
||||
|
||||
length = jpeg_getc(cinfo) << 8;
|
||||
length += jpeg_getc(cinfo);
|
||||
length -= 2; /* discount the length word itself */
|
||||
|
||||
if (traceit) {
|
||||
if (cinfo->unread_marker == JPEG_COM)
|
||||
fprintf(stderr, "Comment, length %ld:\n", (long) length);
|
||||
else /* assume it is an APPn otherwise */
|
||||
fprintf(stderr, "APP%d, length %ld:\n",
|
||||
cinfo->unread_marker - JPEG_APP0, (long) length);
|
||||
}
|
||||
|
||||
while (--length >= 0) {
|
||||
ch = jpeg_getc(cinfo);
|
||||
if (traceit) {
|
||||
/* Emit the character in a readable form.
|
||||
* Nonprintables are converted to \nnn form,
|
||||
* while \ is converted to \\.
|
||||
* Newlines in CR, CR/LF, or LF form will be printed as one newline.
|
||||
*/
|
||||
if (ch == '\r') {
|
||||
fprintf(stderr, "\n");
|
||||
} else if (ch == '\n') {
|
||||
if (lastch != '\r')
|
||||
fprintf(stderr, "\n");
|
||||
} else if (ch == '\\') {
|
||||
fprintf(stderr, "\\\\");
|
||||
} else if (isprint(ch)) {
|
||||
putc(ch, stderr);
|
||||
} else {
|
||||
fprintf(stderr, "\\%03o", ch);
|
||||
}
|
||||
lastch = ch;
|
||||
}
|
||||
}
|
||||
|
||||
if (traceit)
|
||||
fprintf(stderr, "\n");
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* The main program.
|
||||
*/
|
||||
|
||||
int
|
||||
main (int argc, char **argv)
|
||||
{
|
||||
struct jpeg_decompress_struct cinfo;
|
||||
struct jpeg_error_mgr jerr;
|
||||
#ifdef PROGRESS_REPORT
|
||||
struct cdjpeg_progress_mgr progress;
|
||||
#endif
|
||||
int file_index;
|
||||
djpeg_dest_ptr dest_mgr = NULL;
|
||||
FILE * input_file;
|
||||
FILE * output_file;
|
||||
JDIMENSION num_scanlines;
|
||||
|
||||
/* On Mac, fetch a command line. */
|
||||
#ifdef USE_CCOMMAND
|
||||
argc = ccommand(&argv);
|
||||
#endif
|
||||
|
||||
progname = argv[0];
|
||||
if (progname == NULL || progname[0] == 0)
|
||||
progname = "djpeg"; /* in case C library doesn't provide it */
|
||||
|
||||
/* Initialize the JPEG decompression object with default error handling. */
|
||||
cinfo.err = jpeg_std_error(&jerr);
|
||||
jpeg_create_decompress(&cinfo);
|
||||
/* Add some application-specific error messages (from cderror.h) */
|
||||
jerr.addon_message_table = cdjpeg_message_table;
|
||||
jerr.first_addon_message = JMSG_FIRSTADDONCODE;
|
||||
jerr.last_addon_message = JMSG_LASTADDONCODE;
|
||||
|
||||
/* Insert custom marker processor for COM and APP12.
|
||||
* APP12 is used by some digital camera makers for textual info,
|
||||
* so we provide the ability to display it as text.
|
||||
* If you like, additional APPn marker types can be selected for display,
|
||||
* but don't try to override APP0 or APP14 this way (see libjpeg.txt).
|
||||
*/
|
||||
jpeg_set_marker_processor(&cinfo, JPEG_COM, print_text_marker);
|
||||
jpeg_set_marker_processor(&cinfo, JPEG_APP0+12, print_text_marker);
|
||||
|
||||
/* Now safe to enable signal catcher. */
|
||||
#ifdef NEED_SIGNAL_CATCHER
|
||||
enable_signal_catcher((j_common_ptr) &cinfo);
|
||||
#endif
|
||||
|
||||
/* Scan command line to find file names. */
|
||||
/* It is convenient to use just one switch-parsing routine, but the switch
|
||||
* values read here are ignored; we will rescan the switches after opening
|
||||
* the input file.
|
||||
* (Exception: tracing level set here controls verbosity for COM markers
|
||||
* found during jpeg_read_header...)
|
||||
*/
|
||||
|
||||
file_index = parse_switches(&cinfo, argc, argv, 0, FALSE);
|
||||
|
||||
#ifdef TWO_FILE_COMMANDLINE
|
||||
/* 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();
|
||||
}
|
||||
}
|
||||
#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 ((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 */
|
||||
input_file = read_stdin();
|
||||
}
|
||||
|
||||
/* Open the output file. */
|
||||
if (outfilename != NULL) {
|
||||
if ((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 */
|
||||
output_file = write_stdout();
|
||||
}
|
||||
|
||||
#ifdef PROGRESS_REPORT
|
||||
start_progress_monitor((j_common_ptr) &cinfo, &progress);
|
||||
#endif
|
||||
|
||||
/* Specify data source for decompression */
|
||||
jpeg_stdio_src(&cinfo, input_file);
|
||||
|
||||
/* Read file header, set default decompression parameters */
|
||||
(void) jpeg_read_header(&cinfo, TRUE);
|
||||
|
||||
/* Adjust default decompression parameters by re-parsing the options */
|
||||
file_index = parse_switches(&cinfo, argc, argv, 0, TRUE);
|
||||
|
||||
/* Initialize the output module now to let it override any crucial
|
||||
* option settings (for instance, GIF wants to force color quantization).
|
||||
*/
|
||||
switch (requested_fmt) {
|
||||
#ifdef BMP_SUPPORTED
|
||||
case FMT_BMP:
|
||||
dest_mgr = jinit_write_bmp(&cinfo, FALSE);
|
||||
break;
|
||||
case FMT_OS2:
|
||||
dest_mgr = jinit_write_bmp(&cinfo, TRUE);
|
||||
break;
|
||||
#endif
|
||||
#ifdef GIF_SUPPORTED
|
||||
case FMT_GIF:
|
||||
dest_mgr = jinit_write_gif(&cinfo, TRUE);
|
||||
break;
|
||||
case FMT_GIF0:
|
||||
dest_mgr = jinit_write_gif(&cinfo, FALSE);
|
||||
break;
|
||||
#endif
|
||||
#ifdef PPM_SUPPORTED
|
||||
case FMT_PPM:
|
||||
dest_mgr = jinit_write_ppm(&cinfo);
|
||||
break;
|
||||
#endif
|
||||
#ifdef RLE_SUPPORTED
|
||||
case FMT_RLE:
|
||||
dest_mgr = jinit_write_rle(&cinfo);
|
||||
break;
|
||||
#endif
|
||||
#ifdef TARGA_SUPPORTED
|
||||
case FMT_TARGA:
|
||||
dest_mgr = jinit_write_targa(&cinfo);
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
ERREXIT(&cinfo, JERR_UNSUPPORTED_FORMAT);
|
||||
}
|
||||
dest_mgr->output_file = output_file;
|
||||
|
||||
/* Start decompressor */
|
||||
(void) jpeg_start_decompress(&cinfo);
|
||||
|
||||
/* Write output file header */
|
||||
(*dest_mgr->start_output) (&cinfo, dest_mgr);
|
||||
|
||||
/* Process data */
|
||||
while (cinfo.output_scanline < cinfo.output_height) {
|
||||
num_scanlines = jpeg_read_scanlines(&cinfo, dest_mgr->buffer,
|
||||
dest_mgr->buffer_height);
|
||||
(*dest_mgr->put_pixel_rows) (&cinfo, dest_mgr, num_scanlines);
|
||||
}
|
||||
|
||||
#ifdef PROGRESS_REPORT
|
||||
/* Hack: count final pass as done in case finish_output does an extra pass.
|
||||
* The library won't have updated completed_passes.
|
||||
*/
|
||||
progress.pub.completed_passes = progress.pub.total_passes;
|
||||
#endif
|
||||
|
||||
/* Finish decompression and release memory.
|
||||
* I must do it in this order because output module has allocated memory
|
||||
* of lifespan JPOOL_IMAGE; it needs to finish before releasing memory.
|
||||
*/
|
||||
(*dest_mgr->finish_output) (&cinfo, dest_mgr);
|
||||
(void) jpeg_finish_decompress(&cinfo);
|
||||
jpeg_destroy_decompress(&cinfo);
|
||||
|
||||
/* Close files, if we opened them */
|
||||
if (input_file != stdin)
|
||||
fclose(input_file);
|
||||
if (output_file != stdout)
|
||||
fclose(output_file);
|
||||
|
||||
#ifdef PROGRESS_REPORT
|
||||
end_progress_monitor((j_common_ptr) &cinfo);
|
||||
#endif
|
||||
|
||||
/* All done. */
|
||||
exit(jerr.num_warnings ? EXIT_WARNING : EXIT_SUCCESS);
|
||||
return 0; /* suppress no-return-value warnings */
|
||||
}
|
||||
|
|
@ -2,7 +2,7 @@
|
|||
* alternate djpeg.c
|
||||
*
|
||||
* Copyright (C) 1991-1997, Thomas G. Lane.
|
||||
* Modified 2009-2020 by Guido Vollbeding.
|
||||
* Modified 2009-2023 by Guido Vollbeding.
|
||||
* This file is part of the Independent JPEG Group's software.
|
||||
* For conditions of distribution and use, see the accompanying README file.
|
||||
*
|
||||
|
|
@ -74,7 +74,7 @@ unused_dos_memory (void)
|
|||
|
||||
#endif /* MSDOS */
|
||||
|
||||
#ifdef ATARI /* For Atari ST/STE/TT, Pure C or Turbo C */
|
||||
#ifdef ATARI /* For Atari ST/Mega/STE/TT/Falcon, Pure C or Turbo C */
|
||||
|
||||
#include <ext.h>
|
||||
|
||||
|
|
|
|||
|
|
@ -1,433 +0,0 @@
|
|||
/*
|
||||
* example.c
|
||||
*
|
||||
* This file illustrates how to use the IJG code as a subroutine library
|
||||
* to read or write JPEG image files. You should look at this code in
|
||||
* conjunction with the documentation file libjpeg.txt.
|
||||
*
|
||||
* This code will not do anything useful as-is, but it may be helpful as a
|
||||
* skeleton for constructing routines that call the JPEG library.
|
||||
*
|
||||
* We present these routines in the same coding style used in the JPEG code
|
||||
* (ANSI function definitions, etc); but you are of course free to code your
|
||||
* routines in a different style if you prefer.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
/*
|
||||
* Include file for users of JPEG library.
|
||||
* You will need to have included system headers that define at least
|
||||
* the typedefs FILE and size_t before you can include jpeglib.h.
|
||||
* (stdio.h is sufficient on ANSI-conforming systems.)
|
||||
* You may also wish to include "jerror.h".
|
||||
*/
|
||||
|
||||
#include "jpeglib.h"
|
||||
|
||||
/*
|
||||
* <setjmp.h> is used for the optional error recovery mechanism shown in
|
||||
* the second part of the example.
|
||||
*/
|
||||
|
||||
#include <setjmp.h>
|
||||
|
||||
|
||||
|
||||
/******************** JPEG COMPRESSION SAMPLE INTERFACE *******************/
|
||||
|
||||
/* This half of the example shows how to feed data into the JPEG compressor.
|
||||
* We present a minimal version that does not worry about refinements such
|
||||
* as error recovery (the JPEG code will just exit() if it gets an error).
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* IMAGE DATA FORMATS:
|
||||
*
|
||||
* The standard input image format is a rectangular array of pixels, with
|
||||
* each pixel having the same number of "component" values (color channels).
|
||||
* Each pixel row is an array of JSAMPLEs (which typically are unsigned chars).
|
||||
* If you are working with color data, then the color values for each pixel
|
||||
* must be adjacent in the row; for example, R,G,B,R,G,B,R,G,B,... for 24-bit
|
||||
* RGB color.
|
||||
*
|
||||
* For this example, we'll assume that this data structure matches the way
|
||||
* our application has stored the image in memory, so we can just pass a
|
||||
* pointer to our image buffer. In particular, let's say that the image is
|
||||
* RGB color and is described by:
|
||||
*/
|
||||
|
||||
extern JSAMPLE * image_buffer; /* Points to large array of R,G,B-order data */
|
||||
extern int image_height; /* Number of rows in image */
|
||||
extern int image_width; /* Number of columns in image */
|
||||
|
||||
|
||||
/*
|
||||
* Sample routine for JPEG compression. We assume that the target file name
|
||||
* and a compression quality factor are passed in.
|
||||
*/
|
||||
|
||||
GLOBAL(void)
|
||||
write_JPEG_file (char * filename, int quality)
|
||||
{
|
||||
/* This struct contains the JPEG compression parameters and pointers to
|
||||
* working space (which is allocated as needed by the JPEG library).
|
||||
* It is possible to have several such structures, representing multiple
|
||||
* compression/decompression processes, in existence at once. We refer
|
||||
* to any one struct (and its associated working data) as a "JPEG object".
|
||||
*/
|
||||
struct jpeg_compress_struct cinfo;
|
||||
/* This struct represents a JPEG error handler. It is declared separately
|
||||
* because applications often want to supply a specialized error handler
|
||||
* (see the second half of this file for an example). But here we just
|
||||
* take the easy way out and use the standard error handler, which will
|
||||
* print a message on stderr and call exit() if compression fails.
|
||||
* Note that this struct must live as long as the main JPEG parameter
|
||||
* struct, to avoid dangling-pointer problems.
|
||||
*/
|
||||
struct jpeg_error_mgr jerr;
|
||||
/* More stuff */
|
||||
FILE * outfile; /* target file */
|
||||
JSAMPROW row_pointer[1]; /* pointer to JSAMPLE row[s] */
|
||||
int row_stride; /* physical row width in image buffer */
|
||||
|
||||
/* Step 1: allocate and initialize JPEG compression object */
|
||||
|
||||
/* We have to set up the error handler first, in case the initialization
|
||||
* step fails. (Unlikely, but it could happen if you are out of memory.)
|
||||
* This routine fills in the contents of struct jerr, and returns jerr's
|
||||
* address which we place into the link field in cinfo.
|
||||
*/
|
||||
cinfo.err = jpeg_std_error(&jerr);
|
||||
/* Now we can initialize the JPEG compression object. */
|
||||
jpeg_create_compress(&cinfo);
|
||||
|
||||
/* Step 2: specify data destination (eg, a file) */
|
||||
/* Note: steps 2 and 3 can be done in either order. */
|
||||
|
||||
/* Here we use the library-supplied code to send compressed data to a
|
||||
* stdio stream. You can also write your own code to do something else.
|
||||
* VERY IMPORTANT: use "b" option to fopen() if you are on a machine that
|
||||
* requires it in order to write binary files.
|
||||
*/
|
||||
if ((outfile = fopen(filename, "wb")) == NULL) {
|
||||
fprintf(stderr, "can't open %s\n", filename);
|
||||
exit(1);
|
||||
}
|
||||
jpeg_stdio_dest(&cinfo, outfile);
|
||||
|
||||
/* Step 3: set parameters for compression */
|
||||
|
||||
/* First we supply a description of the input image.
|
||||
* Four fields of the cinfo struct must be filled in:
|
||||
*/
|
||||
cinfo.image_width = image_width; /* image width and height, in pixels */
|
||||
cinfo.image_height = image_height;
|
||||
cinfo.input_components = 3; /* # of color components per pixel */
|
||||
cinfo.in_color_space = JCS_RGB; /* colorspace of input image */
|
||||
/* Now use the library's routine to set default compression parameters.
|
||||
* (You must set at least cinfo.in_color_space before calling this,
|
||||
* since the defaults depend on the source color space.)
|
||||
*/
|
||||
jpeg_set_defaults(&cinfo);
|
||||
/* Now you can set any non-default parameters you wish to.
|
||||
* Here we just illustrate the use of quality (quantization table) scaling:
|
||||
*/
|
||||
jpeg_set_quality(&cinfo, quality, TRUE /* limit to baseline-JPEG values */);
|
||||
|
||||
/* Step 4: Start compressor */
|
||||
|
||||
/* TRUE ensures that we will write a complete interchange-JPEG file.
|
||||
* Pass TRUE unless you are very sure of what you're doing.
|
||||
*/
|
||||
jpeg_start_compress(&cinfo, TRUE);
|
||||
|
||||
/* Step 5: while (scan lines remain to be written) */
|
||||
/* jpeg_write_scanlines(...); */
|
||||
|
||||
/* Here we use the library's state variable cinfo.next_scanline as the
|
||||
* loop counter, so that we don't have to keep track ourselves.
|
||||
* To keep things simple, we pass one scanline per call; you can pass
|
||||
* more if you wish, though.
|
||||
*/
|
||||
row_stride = image_width * 3; /* JSAMPLEs per row in image_buffer */
|
||||
|
||||
while (cinfo.next_scanline < cinfo.image_height) {
|
||||
/* jpeg_write_scanlines expects an array of pointers to scanlines.
|
||||
* Here the array is only one element long, but you could pass
|
||||
* more than one scanline at a time if that's more convenient.
|
||||
*/
|
||||
row_pointer[0] = & image_buffer[cinfo.next_scanline * row_stride];
|
||||
(void) jpeg_write_scanlines(&cinfo, row_pointer, 1);
|
||||
}
|
||||
|
||||
/* Step 6: Finish compression */
|
||||
|
||||
jpeg_finish_compress(&cinfo);
|
||||
/* After finish_compress, we can close the output file. */
|
||||
fclose(outfile);
|
||||
|
||||
/* Step 7: release JPEG compression object */
|
||||
|
||||
/* This is an important step since it will release a good deal of memory. */
|
||||
jpeg_destroy_compress(&cinfo);
|
||||
|
||||
/* And we're done! */
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* SOME FINE POINTS:
|
||||
*
|
||||
* In the above loop, we ignored the return value of jpeg_write_scanlines,
|
||||
* which is the number of scanlines actually written. We could get away
|
||||
* with this because we were only relying on the value of cinfo.next_scanline,
|
||||
* which will be incremented correctly. If you maintain additional loop
|
||||
* variables then you should be careful to increment them properly.
|
||||
* Actually, for output to a stdio stream you needn't worry, because
|
||||
* then jpeg_write_scanlines will write all the lines passed (or else exit
|
||||
* with a fatal error). Partial writes can only occur if you use a data
|
||||
* destination module that can demand suspension of the compressor.
|
||||
* (If you don't know what that's for, you don't need it.)
|
||||
*
|
||||
* If the compressor requires full-image buffers (for entropy-coding
|
||||
* optimization or a multi-scan JPEG file), it will create temporary
|
||||
* files for anything that doesn't fit within the maximum-memory setting.
|
||||
* (Note that temp files are NOT needed if you use the default parameters.)
|
||||
* On some systems you may need to set up a signal handler to ensure that
|
||||
* temporary files are deleted if the program is interrupted. See libjpeg.txt.
|
||||
*
|
||||
* Scanlines MUST be supplied in top-to-bottom order if you want your JPEG
|
||||
* files to be compatible with everyone else's. If you cannot readily read
|
||||
* your data in that order, you'll need an intermediate array to hold the
|
||||
* image. See rdtarga.c or rdbmp.c for examples of handling bottom-to-top
|
||||
* source data using the JPEG code's internal virtual-array mechanisms.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
/******************** JPEG DECOMPRESSION SAMPLE INTERFACE *******************/
|
||||
|
||||
/* This half of the example shows how to read data from the JPEG decompressor.
|
||||
* It's a bit more refined than the above, in that we show:
|
||||
* (a) how to modify the JPEG library's standard error-reporting behavior;
|
||||
* (b) how to allocate workspace using the library's memory manager.
|
||||
*
|
||||
* Just to make this example a little different from the first one, we'll
|
||||
* assume that we do not intend to put the whole image into an in-memory
|
||||
* buffer, but to send it line-by-line someplace else. We need a one-
|
||||
* scanline-high JSAMPLE array as a work buffer, and we will let the JPEG
|
||||
* memory manager allocate it for us. This approach is actually quite useful
|
||||
* because we don't need to remember to deallocate the buffer separately: it
|
||||
* will go away automatically when the JPEG object is cleaned up.
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* ERROR HANDLING:
|
||||
*
|
||||
* The JPEG library's standard error handler (jerror.c) is divided into
|
||||
* several "methods" which you can override individually. This lets you
|
||||
* adjust the behavior without duplicating a lot of code, which you might
|
||||
* have to update with each future release.
|
||||
*
|
||||
* Our example here shows how to override the "error_exit" method so that
|
||||
* control is returned to the library's caller when a fatal error occurs,
|
||||
* rather than calling exit() as the standard error_exit method does.
|
||||
*
|
||||
* We use C's setjmp/longjmp facility to return control. This means that the
|
||||
* routine which calls the JPEG library must first execute a setjmp() call to
|
||||
* establish the return point. We want the replacement error_exit to do a
|
||||
* longjmp(). But we need to make the setjmp buffer accessible to the
|
||||
* error_exit routine. To do this, we make a private extension of the
|
||||
* standard JPEG error handler object. (If we were using C++, we'd say we
|
||||
* were making a subclass of the regular error handler.)
|
||||
*
|
||||
* Here's the extended error handler struct:
|
||||
*/
|
||||
|
||||
struct my_error_mgr {
|
||||
struct jpeg_error_mgr pub; /* "public" fields */
|
||||
|
||||
jmp_buf setjmp_buffer; /* for return to caller */
|
||||
};
|
||||
|
||||
typedef struct my_error_mgr * my_error_ptr;
|
||||
|
||||
/*
|
||||
* Here's the routine that will replace the standard error_exit method:
|
||||
*/
|
||||
|
||||
METHODDEF(void)
|
||||
my_error_exit (j_common_ptr cinfo)
|
||||
{
|
||||
/* cinfo->err really points to a my_error_mgr struct, so coerce pointer */
|
||||
my_error_ptr myerr = (my_error_ptr) cinfo->err;
|
||||
|
||||
/* Always display the message. */
|
||||
/* We could postpone this until after returning, if we chose. */
|
||||
(*cinfo->err->output_message) (cinfo);
|
||||
|
||||
/* Return control to the setjmp point */
|
||||
longjmp(myerr->setjmp_buffer, 1);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Sample routine for JPEG decompression. We assume that the source file name
|
||||
* is passed in. We want to return 1 on success, 0 on error.
|
||||
*/
|
||||
|
||||
|
||||
GLOBAL(int)
|
||||
read_JPEG_file (char * filename)
|
||||
{
|
||||
/* This struct contains the JPEG decompression parameters and pointers to
|
||||
* working space (which is allocated as needed by the JPEG library).
|
||||
*/
|
||||
struct jpeg_decompress_struct cinfo;
|
||||
/* We use our private extension JPEG error handler.
|
||||
* Note that this struct must live as long as the main JPEG parameter
|
||||
* struct, to avoid dangling-pointer problems.
|
||||
*/
|
||||
struct my_error_mgr jerr;
|
||||
/* More stuff */
|
||||
FILE * infile; /* source file */
|
||||
JSAMPARRAY buffer; /* Output row buffer */
|
||||
int row_stride; /* physical row width in output buffer */
|
||||
|
||||
/* In this example we want to open the input file before doing anything else,
|
||||
* so that the setjmp() error recovery below can assume the file is open.
|
||||
* VERY IMPORTANT: use "b" option to fopen() if you are on a machine that
|
||||
* requires it in order to read binary files.
|
||||
*/
|
||||
|
||||
if ((infile = fopen(filename, "rb")) == NULL) {
|
||||
fprintf(stderr, "can't open %s\n", filename);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Step 1: allocate and initialize JPEG decompression object */
|
||||
|
||||
/* We set up the normal JPEG error routines, then override error_exit. */
|
||||
cinfo.err = jpeg_std_error(&jerr.pub);
|
||||
jerr.pub.error_exit = my_error_exit;
|
||||
/* Establish the setjmp return context for my_error_exit to use. */
|
||||
if (setjmp(jerr.setjmp_buffer)) {
|
||||
/* If we get here, the JPEG code has signaled an error.
|
||||
* We need to clean up the JPEG object, close the input file, and return.
|
||||
*/
|
||||
jpeg_destroy_decompress(&cinfo);
|
||||
fclose(infile);
|
||||
return 0;
|
||||
}
|
||||
/* Now we can initialize the JPEG decompression object. */
|
||||
jpeg_create_decompress(&cinfo);
|
||||
|
||||
/* Step 2: specify data source (eg, a file) */
|
||||
|
||||
jpeg_stdio_src(&cinfo, infile);
|
||||
|
||||
/* Step 3: read file parameters with jpeg_read_header() */
|
||||
|
||||
(void) jpeg_read_header(&cinfo, TRUE);
|
||||
/* We can ignore the return value from jpeg_read_header since
|
||||
* (a) suspension is not possible with the stdio data source, and
|
||||
* (b) we passed TRUE to reject a tables-only JPEG file as an error.
|
||||
* See libjpeg.txt for more info.
|
||||
*/
|
||||
|
||||
/* Step 4: set parameters for decompression */
|
||||
|
||||
/* In this example, we don't need to change any of the defaults set by
|
||||
* jpeg_read_header(), so we do nothing here.
|
||||
*/
|
||||
|
||||
/* Step 5: Start decompressor */
|
||||
|
||||
(void) jpeg_start_decompress(&cinfo);
|
||||
/* We can ignore the return value since suspension is not possible
|
||||
* with the stdio data source.
|
||||
*/
|
||||
|
||||
/* We may need to do some setup of our own at this point before reading
|
||||
* the data. After jpeg_start_decompress() we have the correct scaled
|
||||
* output image dimensions available, as well as the output colormap
|
||||
* if we asked for color quantization.
|
||||
* In this example, we need to make an output work buffer of the right size.
|
||||
*/
|
||||
/* JSAMPLEs per row in output buffer */
|
||||
row_stride = cinfo.output_width * cinfo.output_components;
|
||||
/* Make a one-row-high sample array that will go away when done with image */
|
||||
buffer = (*cinfo.mem->alloc_sarray)
|
||||
((j_common_ptr) &cinfo, JPOOL_IMAGE, row_stride, 1);
|
||||
|
||||
/* Step 6: while (scan lines remain to be read) */
|
||||
/* jpeg_read_scanlines(...); */
|
||||
|
||||
/* Here we use the library's state variable cinfo.output_scanline as the
|
||||
* loop counter, so that we don't have to keep track ourselves.
|
||||
*/
|
||||
while (cinfo.output_scanline < cinfo.output_height) {
|
||||
/* jpeg_read_scanlines expects an array of pointers to scanlines.
|
||||
* Here the array is only one element long, but you could ask for
|
||||
* more than one scanline at a time if that's more convenient.
|
||||
*/
|
||||
(void) jpeg_read_scanlines(&cinfo, buffer, 1);
|
||||
/* Assume put_scanline_someplace wants a pointer and sample count. */
|
||||
put_scanline_someplace(buffer[0], row_stride);
|
||||
}
|
||||
|
||||
/* Step 7: Finish decompression */
|
||||
|
||||
(void) jpeg_finish_decompress(&cinfo);
|
||||
/* We can ignore the return value since suspension is not possible
|
||||
* with the stdio data source.
|
||||
*/
|
||||
|
||||
/* Step 8: Release JPEG decompression object */
|
||||
|
||||
/* This is an important step since it will release a good deal of memory. */
|
||||
jpeg_destroy_decompress(&cinfo);
|
||||
|
||||
/* After finish_decompress, we can close the input file.
|
||||
* Here we postpone it until after no more JPEG errors are possible,
|
||||
* so as to simplify the setjmp error logic above. (Actually, I don't
|
||||
* think that jpeg_destroy can do an error exit, but why assume anything...)
|
||||
*/
|
||||
fclose(infile);
|
||||
|
||||
/* At this point you may want to check to see whether any corrupt-data
|
||||
* warnings occurred (test whether jerr.pub.num_warnings is nonzero).
|
||||
*/
|
||||
|
||||
/* And we're done! */
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* SOME FINE POINTS:
|
||||
*
|
||||
* In the above code, we ignored the return value of jpeg_read_scanlines,
|
||||
* which is the number of scanlines actually read. We could get away with
|
||||
* this because we asked for only one line at a time and we weren't using
|
||||
* a suspending data source. See libjpeg.txt for more info.
|
||||
*
|
||||
* We cheated a bit by calling alloc_sarray() after jpeg_start_decompress();
|
||||
* we should have done it beforehand to ensure that the space would be
|
||||
* counted against the JPEG max_memory setting. In some systems the above
|
||||
* code would risk an out-of-memory error. However, in general we don't
|
||||
* know the output image dimensions before jpeg_start_decompress(), unless we
|
||||
* call jpeg_calc_output_dimensions(). See libjpeg.txt for more about this.
|
||||
*
|
||||
* Scanlines are returned in the same order as they appear in the JPEG file,
|
||||
* which is standardly top-to-bottom. If you must emit data bottom-to-top,
|
||||
* you can use one of the virtual arrays provided by the JPEG memory manager
|
||||
* to invert the data. See wrbmp.c for an example.
|
||||
*
|
||||
* As with compression, some operating modes may require temporary files.
|
||||
* On some systems you may need to set up a signal handler to ensure that
|
||||
* temporary files are deleted if the program is interrupted. See libjpeg.txt.
|
||||
*/
|
||||
|
|
@ -2,7 +2,7 @@
|
|||
* jccoefct.c
|
||||
*
|
||||
* Copyright (C) 1994-1997, Thomas G. Lane.
|
||||
* Modified 2003-2020 by Guido Vollbeding.
|
||||
* Modified 2003-2022 by Guido Vollbeding.
|
||||
* This file is part of the Independent JPEG Group's software.
|
||||
* For conditions of distribution and use, see the accompanying README file.
|
||||
*
|
||||
|
|
@ -41,9 +41,9 @@ typedef struct {
|
|||
int MCU_rows_per_iMCU_row; /* number of such rows needed */
|
||||
|
||||
/* For single-pass compression, it's sufficient to buffer just one MCU
|
||||
* (although this may prove a bit slow in practice). We append a
|
||||
* workspace of C_MAX_BLOCKS_IN_MCU coefficient blocks, and reuse it
|
||||
* for each MCU constructed and sent.
|
||||
* (although this may prove a bit slow in practice).
|
||||
* We append a workspace of C_MAX_BLOCKS_IN_MCU coefficient blocks,
|
||||
* and reuse it for each MCU constructed and sent.
|
||||
* In multi-pass modes, this array points to the current MCU's blocks
|
||||
* within the virtual arrays.
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
* jccolor.c
|
||||
*
|
||||
* Copyright (C) 1991-1996, Thomas G. Lane.
|
||||
* Modified 2011-2019 by Guido Vollbeding.
|
||||
* Modified 2011-2023 by Guido Vollbeding.
|
||||
* This file is part of the Independent JPEG Group's software.
|
||||
* For conditions of distribution and use, see the accompanying README file.
|
||||
*
|
||||
|
|
@ -40,10 +40,10 @@ typedef my_color_converter * my_cconvert_ptr;
|
|||
* Note that the derived conversion coefficients given in some of these
|
||||
* documents are imprecise. The general conversion equations are
|
||||
* Y = Kr * R + (1 - Kr - Kb) * G + Kb * B
|
||||
* Cb = 0.5 * (B - Y) / (1 - Kb)
|
||||
* Cr = 0.5 * (R - Y) / (1 - Kr)
|
||||
* Cb = (B - Y) / (1 - Kb) / K
|
||||
* Cr = (R - Y) / (1 - Kr) / K
|
||||
* With Kr = 0.299 and Kb = 0.114 (derived according to SMPTE RP 177-1993
|
||||
* from the 1953 FCC NTSC primaries and CIE Illuminant C),
|
||||
* from the 1953 FCC NTSC primaries and CIE Illuminant C), K = 2 for sYCC,
|
||||
* the conversion equations to be implemented are therefore
|
||||
* Y = 0.299 * R + 0.587 * G + 0.114 * B
|
||||
* Cb = -0.168735892 * R - 0.331264108 * G + 0.5 * B + CENTERJSAMPLE
|
||||
|
|
@ -62,8 +62,8 @@ typedef my_color_converter * my_cconvert_ptr;
|
|||
* by precalculating the constants times R,G,B for all possible values.
|
||||
* For 8-bit JSAMPLEs this is very reasonable (only 256 entries per table);
|
||||
* for 9-bit to 12-bit samples it is still acceptable. It's not very
|
||||
* reasonable for 16-bit samples, but if you want lossless storage you
|
||||
* shouldn't be changing colorspace anyway.
|
||||
* reasonable for 16-bit samples, but if you want lossless storage
|
||||
* you shouldn't be changing colorspace anyway.
|
||||
* The CENTERJSAMPLE offsets and the rounding fudge-factor of 0.5 are included
|
||||
* in the tables to save adding them separately in the inner loop.
|
||||
*/
|
||||
|
|
@ -110,16 +110,16 @@ rgb_ycc_start (j_compress_ptr cinfo)
|
|||
for (i = 0; i <= MAXJSAMPLE; i++) {
|
||||
rgb_ycc_tab[i+R_Y_OFF] = FIX(0.299) * i;
|
||||
rgb_ycc_tab[i+G_Y_OFF] = FIX(0.587) * i;
|
||||
rgb_ycc_tab[i+B_Y_OFF] = FIX(0.114) * i + ONE_HALF;
|
||||
rgb_ycc_tab[i+B_Y_OFF] = FIX(0.114) * i + ONE_HALF;
|
||||
rgb_ycc_tab[i+R_CB_OFF] = (- FIX(0.168735892)) * i;
|
||||
rgb_ycc_tab[i+G_CB_OFF] = (- FIX(0.331264108)) * i;
|
||||
/* We use a rounding fudge-factor of 0.5-epsilon for Cb and Cr.
|
||||
* This ensures that the maximum output will round to MAXJSAMPLE
|
||||
* not MAXJSAMPLE+1, and thus that we don't have to range-limit.
|
||||
*/
|
||||
rgb_ycc_tab[i+B_CB_OFF] = FIX(0.5) * i + CBCR_OFFSET + ONE_HALF-1;
|
||||
rgb_ycc_tab[i+B_CB_OFF] = (i << (SCALEBITS-1)) + CBCR_OFFSET + ONE_HALF-1;
|
||||
/* B=>Cb and R=>Cr tables are the same
|
||||
rgb_ycc_tab[i+R_CR_OFF] = FIX(0.5) * i + CBCR_OFFSET + ONE_HALF-1;
|
||||
rgb_ycc_tab[i+R_CR_OFF] = (i << (SCALEBITS-1)) + CBCR_OFFSET + ONE_HALF-1;
|
||||
*/
|
||||
rgb_ycc_tab[i+G_CR_OFF] = (- FIX(0.418687589)) * i;
|
||||
rgb_ycc_tab[i+B_CR_OFF] = (- FIX(0.081312411)) * i;
|
||||
|
|
@ -190,8 +190,8 @@ rgb_ycc_convert (j_compress_ptr cinfo,
|
|||
|
||||
/*
|
||||
* Convert some rows of samples to the JPEG colorspace.
|
||||
* This version handles RGB->grayscale conversion, which is the same
|
||||
* as the RGB->Y portion of RGB->YCbCr.
|
||||
* This version handles RGB->grayscale conversion,
|
||||
* which is the same as the RGB->Y portion of RGB->YCbCr.
|
||||
* We assume rgb_ycc_start has been called (we only use the Y tables).
|
||||
*/
|
||||
|
||||
|
|
@ -201,7 +201,7 @@ rgb_gray_convert (j_compress_ptr cinfo,
|
|||
JDIMENSION output_row, int num_rows)
|
||||
{
|
||||
my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert;
|
||||
register int r, g, b;
|
||||
register INT32 y;
|
||||
register INT32 * ctab = cconvert->rgb_ycc_tab;
|
||||
register JSAMPROW inptr;
|
||||
register JSAMPROW outptr;
|
||||
|
|
@ -212,14 +212,11 @@ rgb_gray_convert (j_compress_ptr cinfo,
|
|||
inptr = *input_buf++;
|
||||
outptr = output_buf[0][output_row++];
|
||||
for (col = 0; col < num_cols; col++) {
|
||||
r = GETJSAMPLE(inptr[RGB_RED]);
|
||||
g = GETJSAMPLE(inptr[RGB_GREEN]);
|
||||
b = GETJSAMPLE(inptr[RGB_BLUE]);
|
||||
y = ctab[R_Y_OFF + GETJSAMPLE(inptr[RGB_RED])];
|
||||
y += ctab[G_Y_OFF + GETJSAMPLE(inptr[RGB_GREEN])];
|
||||
y += ctab[B_Y_OFF + GETJSAMPLE(inptr[RGB_BLUE])];
|
||||
inptr += RGB_PIXELSIZE;
|
||||
/* Y */
|
||||
outptr[col] = (JSAMPLE)
|
||||
((ctab[r+R_Y_OFF] + ctab[g+G_Y_OFF] + ctab[b+B_Y_OFF])
|
||||
>> SCALEBITS);
|
||||
outptr[col] = (JSAMPLE) (y >> SCALEBITS);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
* jchuff.c
|
||||
*
|
||||
* Copyright (C) 1991-1997, Thomas G. Lane.
|
||||
* Modified 2006-2020 by Guido Vollbeding.
|
||||
* Modified 2006-2023 by Guido Vollbeding.
|
||||
* This file is part of the Independent JPEG Group's software.
|
||||
* For conditions of distribution and use, see the accompanying README file.
|
||||
*
|
||||
|
|
@ -26,17 +26,11 @@
|
|||
|
||||
|
||||
/* The legal range of a DCT coefficient is
|
||||
* -1024 .. +1023 for 8-bit data;
|
||||
* -16384 .. +16383 for 12-bit data.
|
||||
* Hence the magnitude should always fit in 10 or 14 bits respectively.
|
||||
* -1024 .. +1023 for 8-bit sample data precision;
|
||||
* -16384 .. +16383 for 12-bit sample data precision.
|
||||
* Hence the magnitude should always fit in sample data precision + 2 bits.
|
||||
*/
|
||||
|
||||
#if BITS_IN_JSAMPLE == 8
|
||||
#define MAX_COEF_BITS 10
|
||||
#else
|
||||
#define MAX_COEF_BITS 14
|
||||
#endif
|
||||
|
||||
/* Derived data constructed for each Huffman table */
|
||||
|
||||
typedef struct {
|
||||
|
|
@ -547,6 +541,7 @@ encode_mcu_DC_first (j_compress_ptr cinfo, JBLOCKARRAY MCU_data)
|
|||
huff_entropy_ptr entropy = (huff_entropy_ptr) cinfo->entropy;
|
||||
register int temp, temp2;
|
||||
register int nbits;
|
||||
int max_coef_bits;
|
||||
int blkn, ci, tbl;
|
||||
ISHIFT_TEMPS
|
||||
|
||||
|
|
@ -558,6 +553,9 @@ encode_mcu_DC_first (j_compress_ptr cinfo, JBLOCKARRAY MCU_data)
|
|||
if (entropy->restarts_to_go == 0)
|
||||
emit_restart_e(entropy, entropy->next_restart_num);
|
||||
|
||||
/* Since we're encoding a difference, the range limit is twice as much. */
|
||||
max_coef_bits = cinfo->data_precision + 3;
|
||||
|
||||
/* Encode the MCU data blocks */
|
||||
for (blkn = 0; blkn < cinfo->blocks_in_MCU; blkn++) {
|
||||
ci = cinfo->MCU_membership[blkn];
|
||||
|
|
@ -569,12 +567,17 @@ encode_mcu_DC_first (j_compress_ptr cinfo, JBLOCKARRAY MCU_data)
|
|||
temp = IRIGHT_SHIFT((int) (MCU_data[blkn][0][0]), cinfo->Al);
|
||||
|
||||
/* DC differences are figured on the point-transformed values. */
|
||||
temp2 = temp - entropy->saved.last_dc_val[ci];
|
||||
if ((temp2 = temp - entropy->saved.last_dc_val[ci]) == 0) {
|
||||
/* Count/emit the Huffman-coded symbol for the number of bits */
|
||||
emit_dc_symbol(entropy, tbl, 0);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
entropy->saved.last_dc_val[ci] = temp;
|
||||
|
||||
/* Encode the DC coefficient difference per section G.1.2.1 */
|
||||
temp = temp2;
|
||||
if (temp < 0) {
|
||||
if ((temp = temp2) < 0) {
|
||||
temp = -temp; /* temp is abs value of input */
|
||||
/* For a negative input, want temp2 = bitwise complement of abs(input) */
|
||||
/* This code assumes we are on a two's complement machine */
|
||||
|
|
@ -583,14 +586,10 @@ encode_mcu_DC_first (j_compress_ptr cinfo, JBLOCKARRAY MCU_data)
|
|||
|
||||
/* Find the number of bits needed for the magnitude of the coefficient */
|
||||
nbits = 0;
|
||||
while (temp) {
|
||||
nbits++;
|
||||
temp >>= 1;
|
||||
}
|
||||
/* Check for out-of-range coefficient values.
|
||||
* Since we're encoding a difference, the range limit is twice as much.
|
||||
*/
|
||||
if (nbits > MAX_COEF_BITS+1)
|
||||
do nbits++; /* there must be at least one 1 bit */
|
||||
while ((temp >>= 1));
|
||||
/* Check for out-of-range coefficient values */
|
||||
if (nbits > max_coef_bits)
|
||||
ERREXIT(cinfo, JERR_BAD_DCT_COEF);
|
||||
|
||||
/* Count/emit the Huffman-coded symbol for the number of bits */
|
||||
|
|
@ -598,8 +597,7 @@ encode_mcu_DC_first (j_compress_ptr cinfo, JBLOCKARRAY MCU_data)
|
|||
|
||||
/* Emit that number of bits of the value, if positive, */
|
||||
/* or the complement of its magnitude, if negative. */
|
||||
if (nbits) /* emit_bits rejects calls with size 0 */
|
||||
emit_bits_e(entropy, (unsigned int) temp2, nbits);
|
||||
emit_bits_e(entropy, (unsigned int) temp2, nbits);
|
||||
}
|
||||
|
||||
cinfo->dest->next_output_byte = entropy->next_output_byte;
|
||||
|
|
@ -633,7 +631,7 @@ encode_mcu_AC_first (j_compress_ptr cinfo, JBLOCKARRAY MCU_data)
|
|||
register int temp, temp2;
|
||||
register int nbits;
|
||||
register int r, k;
|
||||
int Se, Al;
|
||||
int Se, Al, max_coef_bits;
|
||||
|
||||
entropy->next_output_byte = cinfo->dest->next_output_byte;
|
||||
entropy->free_in_buffer = cinfo->dest->free_in_buffer;
|
||||
|
|
@ -646,6 +644,7 @@ encode_mcu_AC_first (j_compress_ptr cinfo, JBLOCKARRAY MCU_data)
|
|||
Se = cinfo->Se;
|
||||
Al = cinfo->Al;
|
||||
natural_order = cinfo->natural_order;
|
||||
max_coef_bits = cinfo->data_precision + 2;
|
||||
|
||||
/* Encode the MCU data block */
|
||||
block = MCU_data[0];
|
||||
|
|
@ -666,18 +665,23 @@ encode_mcu_AC_first (j_compress_ptr cinfo, JBLOCKARRAY MCU_data)
|
|||
*/
|
||||
if (temp < 0) {
|
||||
temp = -temp; /* temp is abs value of input */
|
||||
temp >>= Al; /* apply the point transform */
|
||||
/* Apply the point transform, and watch out for case */
|
||||
/* that nonzero coef is zero after point transform. */
|
||||
if ((temp >>= Al) == 0) {
|
||||
r++;
|
||||
continue;
|
||||
}
|
||||
/* For a negative coef, want temp2 = bitwise complement of abs(coef) */
|
||||
temp2 = ~temp;
|
||||
} else {
|
||||
temp >>= Al; /* apply the point transform */
|
||||
/* Apply the point transform, and watch out for case */
|
||||
/* that nonzero coef is zero after point transform. */
|
||||
if ((temp >>= Al) == 0) {
|
||||
r++;
|
||||
continue;
|
||||
}
|
||||
temp2 = temp;
|
||||
}
|
||||
/* Watch out for case that nonzero coef is zero after point transform */
|
||||
if (temp == 0) {
|
||||
r++;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Emit any pending EOBRUN */
|
||||
if (entropy->EOBRUN > 0)
|
||||
|
|
@ -689,11 +693,11 @@ encode_mcu_AC_first (j_compress_ptr cinfo, JBLOCKARRAY MCU_data)
|
|||
}
|
||||
|
||||
/* Find the number of bits needed for the magnitude of the coefficient */
|
||||
nbits = 1; /* there must be at least one 1 bit */
|
||||
while ((temp >>= 1))
|
||||
nbits++;
|
||||
nbits = 0;
|
||||
do nbits++; /* there must be at least one 1 bit */
|
||||
while ((temp >>= 1));
|
||||
/* Check for out-of-range coefficient values */
|
||||
if (nbits > MAX_COEF_BITS)
|
||||
if (nbits > max_coef_bits)
|
||||
ERREXIT(cinfo, JERR_BAD_DCT_COEF);
|
||||
|
||||
/* Count/emit Huffman symbol for run length / number of bits */
|
||||
|
|
@ -916,83 +920,89 @@ encode_one_block (working_state * state, JCOEFPTR block, int last_dc_val,
|
|||
register int nbits;
|
||||
register int r, k;
|
||||
int Se = state->cinfo->lim_Se;
|
||||
int max_coef_bits = state->cinfo->data_precision + 3;
|
||||
const int * natural_order = state->cinfo->natural_order;
|
||||
|
||||
/* Encode the DC coefficient difference per section F.1.2.1 */
|
||||
|
||||
temp = temp2 = block[0] - last_dc_val;
|
||||
if ((temp = block[0] - last_dc_val) == 0) {
|
||||
/* Emit the Huffman-coded symbol for the number of bits */
|
||||
if (! emit_bits_s(state, dctbl->ehufco[0], dctbl->ehufsi[0]))
|
||||
return FALSE;
|
||||
} else {
|
||||
if ((temp2 = temp) < 0) {
|
||||
temp = -temp; /* temp is abs value of input */
|
||||
/* For a negative input, want temp2 = bitwise complement of abs(input) */
|
||||
/* This code assumes we are on a two's complement machine */
|
||||
temp2--;
|
||||
}
|
||||
|
||||
if (temp < 0) {
|
||||
temp = -temp; /* temp is abs value of input */
|
||||
/* For a negative input, want temp2 = bitwise complement of abs(input) */
|
||||
/* This code assumes we are on a two's complement machine */
|
||||
temp2--;
|
||||
}
|
||||
/* Find the number of bits needed for the magnitude of the coefficient */
|
||||
nbits = 0;
|
||||
do nbits++; /* there must be at least one 1 bit */
|
||||
while ((temp >>= 1));
|
||||
/* Check for out-of-range coefficient values.
|
||||
* Since we're encoding a difference, the range limit is twice as much.
|
||||
*/
|
||||
if (nbits > max_coef_bits)
|
||||
ERREXIT(state->cinfo, JERR_BAD_DCT_COEF);
|
||||
|
||||
/* Find the number of bits needed for the magnitude of the coefficient */
|
||||
nbits = 0;
|
||||
while (temp) {
|
||||
nbits++;
|
||||
temp >>= 1;
|
||||
}
|
||||
/* Check for out-of-range coefficient values.
|
||||
* Since we're encoding a difference, the range limit is twice as much.
|
||||
*/
|
||||
if (nbits > MAX_COEF_BITS+1)
|
||||
ERREXIT(state->cinfo, JERR_BAD_DCT_COEF);
|
||||
/* Emit the Huffman-coded symbol for the number of bits */
|
||||
if (! emit_bits_s(state, dctbl->ehufco[nbits], dctbl->ehufsi[nbits]))
|
||||
return FALSE;
|
||||
|
||||
/* Emit the Huffman-coded symbol for the number of bits */
|
||||
if (! emit_bits_s(state, dctbl->ehufco[nbits], dctbl->ehufsi[nbits]))
|
||||
return FALSE;
|
||||
|
||||
/* Emit that number of bits of the value, if positive, */
|
||||
/* or the complement of its magnitude, if negative. */
|
||||
if (nbits) /* emit_bits rejects calls with size 0 */
|
||||
/* Emit that number of bits of the value, if positive, */
|
||||
/* or the complement of its magnitude, if negative. */
|
||||
if (! emit_bits_s(state, (unsigned int) temp2, nbits))
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Encode the AC coefficients per section F.1.2.2 */
|
||||
|
||||
r = 0; /* r = run length of zeros */
|
||||
|
||||
for (k = 1; k <= Se; k++) {
|
||||
if ((temp2 = block[natural_order[k]]) == 0) {
|
||||
if ((temp = block[natural_order[k]]) == 0) {
|
||||
r++;
|
||||
} else {
|
||||
/* if run length > 15, must emit special run-length-16 codes (0xF0) */
|
||||
while (r > 15) {
|
||||
if (! emit_bits_s(state, actbl->ehufco[0xF0], actbl->ehufsi[0xF0]))
|
||||
return FALSE;
|
||||
r -= 16;
|
||||
}
|
||||
|
||||
temp = temp2;
|
||||
if (temp < 0) {
|
||||
temp = -temp; /* temp is abs value of input */
|
||||
/* This code assumes we are on a two's complement machine */
|
||||
temp2--;
|
||||
}
|
||||
|
||||
/* Find the number of bits needed for the magnitude of the coefficient */
|
||||
nbits = 1; /* there must be at least one 1 bit */
|
||||
while ((temp >>= 1))
|
||||
nbits++;
|
||||
/* Check for out-of-range coefficient values */
|
||||
if (nbits > MAX_COEF_BITS)
|
||||
ERREXIT(state->cinfo, JERR_BAD_DCT_COEF);
|
||||
|
||||
/* Emit Huffman symbol for run length / number of bits */
|
||||
temp = (r << 4) + nbits;
|
||||
if (! emit_bits_s(state, actbl->ehufco[temp], actbl->ehufsi[temp]))
|
||||
return FALSE;
|
||||
|
||||
/* Emit that number of bits of the value, if positive, */
|
||||
/* or the complement of its magnitude, if negative. */
|
||||
if (! emit_bits_s(state, (unsigned int) temp2, nbits))
|
||||
return FALSE;
|
||||
|
||||
r = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* if run length > 15, must emit special run-length-16 codes (0xF0) */
|
||||
while (r > 15) {
|
||||
if (! emit_bits_s(state, actbl->ehufco[0xF0], actbl->ehufsi[0xF0]))
|
||||
return FALSE;
|
||||
r -= 16;
|
||||
}
|
||||
|
||||
if ((temp2 = temp) < 0) {
|
||||
temp = -temp; /* temp is abs value of input */
|
||||
/* For a negative coef, want temp2 = bitwise complement of abs(coef) */
|
||||
/* This code assumes we are on a two's complement machine */
|
||||
temp2--;
|
||||
}
|
||||
|
||||
/* Find the number of bits needed for the magnitude of the coefficient */
|
||||
nbits = 0;
|
||||
do nbits++; /* there must be at least one 1 bit */
|
||||
while ((temp >>= 1));
|
||||
/* Check for out-of-range coefficient values.
|
||||
* Use ">=" instead of ">" so can use the
|
||||
* same one larger limit from DC check here.
|
||||
*/
|
||||
if (nbits >= max_coef_bits)
|
||||
ERREXIT(state->cinfo, JERR_BAD_DCT_COEF);
|
||||
|
||||
/* Emit Huffman symbol for run length / number of bits */
|
||||
temp = (r << 4) + nbits;
|
||||
if (! emit_bits_s(state, actbl->ehufco[temp], actbl->ehufsi[temp]))
|
||||
return FALSE;
|
||||
|
||||
/* Emit that number of bits of the value, if positive, */
|
||||
/* or the complement of its magnitude, if negative. */
|
||||
if (! emit_bits_s(state, (unsigned int) temp2, nbits))
|
||||
return FALSE;
|
||||
|
||||
r = 0; /* reset zero run length */
|
||||
}
|
||||
|
||||
/* If the last coef(s) were zero, emit an end-of-block code */
|
||||
|
|
@ -1122,28 +1132,31 @@ htest_one_block (j_compress_ptr cinfo, JCOEFPTR block, int last_dc_val,
|
|||
register int nbits;
|
||||
register int r, k;
|
||||
int Se = cinfo->lim_Se;
|
||||
int max_coef_bits = cinfo->data_precision + 3;
|
||||
const int * natural_order = cinfo->natural_order;
|
||||
|
||||
/* Encode the DC coefficient difference per section F.1.2.1 */
|
||||
|
||||
temp = block[0] - last_dc_val;
|
||||
if (temp < 0)
|
||||
temp = -temp;
|
||||
if ((temp = block[0] - last_dc_val) == 0) {
|
||||
/* Count the Huffman symbol for the number of bits */
|
||||
dc_counts[0]++;
|
||||
} else {
|
||||
if (temp < 0)
|
||||
temp = -temp; /* temp is abs value of input */
|
||||
|
||||
/* Find the number of bits needed for the magnitude of the coefficient */
|
||||
nbits = 0;
|
||||
while (temp) {
|
||||
nbits++;
|
||||
temp >>= 1;
|
||||
/* Find the number of bits needed for the magnitude of the coefficient */
|
||||
nbits = 0;
|
||||
do nbits++; /* there must be at least one 1 bit */
|
||||
while ((temp >>= 1));
|
||||
/* Check for out-of-range coefficient values.
|
||||
* Since we're encoding a difference, the range limit is twice as much.
|
||||
*/
|
||||
if (nbits > max_coef_bits)
|
||||
ERREXIT(cinfo, JERR_BAD_DCT_COEF);
|
||||
|
||||
/* Count the Huffman symbol for the number of bits */
|
||||
dc_counts[nbits]++;
|
||||
}
|
||||
/* Check for out-of-range coefficient values.
|
||||
* Since we're encoding a difference, the range limit is twice as much.
|
||||
*/
|
||||
if (nbits > MAX_COEF_BITS+1)
|
||||
ERREXIT(cinfo, JERR_BAD_DCT_COEF);
|
||||
|
||||
/* Count the Huffman symbol for the number of bits */
|
||||
dc_counts[nbits]++;
|
||||
|
||||
/* Encode the AC coefficients per section F.1.2.2 */
|
||||
|
||||
|
|
@ -1152,30 +1165,33 @@ htest_one_block (j_compress_ptr cinfo, JCOEFPTR block, int last_dc_val,
|
|||
for (k = 1; k <= Se; k++) {
|
||||
if ((temp = block[natural_order[k]]) == 0) {
|
||||
r++;
|
||||
} else {
|
||||
/* if run length > 15, must emit special run-length-16 codes (0xF0) */
|
||||
while (r > 15) {
|
||||
ac_counts[0xF0]++;
|
||||
r -= 16;
|
||||
}
|
||||
|
||||
/* Find the number of bits needed for the magnitude of the coefficient */
|
||||
if (temp < 0)
|
||||
temp = -temp;
|
||||
|
||||
/* Find the number of bits needed for the magnitude of the coefficient */
|
||||
nbits = 1; /* there must be at least one 1 bit */
|
||||
while ((temp >>= 1))
|
||||
nbits++;
|
||||
/* Check for out-of-range coefficient values */
|
||||
if (nbits > MAX_COEF_BITS)
|
||||
ERREXIT(cinfo, JERR_BAD_DCT_COEF);
|
||||
|
||||
/* Count Huffman symbol for run length / number of bits */
|
||||
ac_counts[(r << 4) + nbits]++;
|
||||
|
||||
r = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* if run length > 15, must emit special run-length-16 codes (0xF0) */
|
||||
while (r > 15) {
|
||||
ac_counts[0xF0]++;
|
||||
r -= 16;
|
||||
}
|
||||
|
||||
if (temp < 0)
|
||||
temp = -temp; /* temp is abs value of input */
|
||||
|
||||
/* Find the number of bits needed for the magnitude of the coefficient */
|
||||
nbits = 0;
|
||||
do nbits++; /* there must be at least one 1 bit */
|
||||
while ((temp >>= 1));
|
||||
/* Check for out-of-range coefficient values.
|
||||
* Use ">=" instead of ">" so can use the
|
||||
* same one larger limit from DC check here.
|
||||
*/
|
||||
if (nbits >= max_coef_bits)
|
||||
ERREXIT(cinfo, JERR_BAD_DCT_COEF);
|
||||
|
||||
/* Count Huffman symbol for run length / number of bits */
|
||||
ac_counts[(r << 4) + nbits]++;
|
||||
|
||||
r = 0; /* reset zero run length */
|
||||
}
|
||||
|
||||
/* If the last coef(s) were zero, emit an end-of-block code */
|
||||
|
|
|
|||
|
|
@ -1,6 +1,8 @@
|
|||
/* jconfig.vc --- jconfig.h for Microsoft Visual C++ on Windows 9x or NT. */
|
||||
/* This file also works for Borland C++ 32-bit (bcc32) on Windows 9x or NT. */
|
||||
/* see jconfig.txt for explanations */
|
||||
/* jconfig.vc --- jconfig.h for Microsoft Visual C++ on Windows 9x or NT.
|
||||
* This file also works for Borland/Embarcadero C++ for Win32 or Win64
|
||||
* (CLI: bcc32, bcc32c, bcc32x, bcc64; GUI IDE: C++Builder/RAD Studio).
|
||||
* See jconfig.txt for explanations.
|
||||
*/
|
||||
|
||||
#define HAVE_PROTOTYPES
|
||||
#define HAVE_UNSIGNED_CHAR
|
||||
|
|
@ -29,6 +31,17 @@
|
|||
#endif
|
||||
#define HAVE_BOOLEAN /* prevent jmorecfg.h from redefining it */
|
||||
|
||||
/* Define custom RGB color order, prevent jmorecfg.h from redefinition */
|
||||
#undef JPEG_HAVE_RGB_CUSTOM
|
||||
/* Use Windows custom BGR color order defined in jmorecfg.h */
|
||||
#undef JPEG_USE_RGB_CUSTOM
|
||||
|
||||
/* Define custom file I/O functions, prevent jinclude.h from redefinition */
|
||||
#undef JPEG_HAVE_FILE_IO_CUSTOM
|
||||
/* Use Delphi custom file I/O functions defined in jinclude.h */
|
||||
#undef JPEG_USE_FILE_IO_CUSTOM
|
||||
|
||||
|
||||
#ifdef JPEG_INTERNALS
|
||||
|
||||
#undef RIGHT_SHIFT_IS_UNSIGNED
|
||||
|
|
@ -44,7 +57,7 @@
|
|||
#define TARGA_SUPPORTED /* Targa image file format */
|
||||
|
||||
#define TWO_FILE_COMMANDLINE /* optional */
|
||||
#define USE_SETMODE /* Microsoft has setmode() */
|
||||
#define USE_SETMODE /* Microsoft/Borland/Embarcadero have setmode() */
|
||||
#undef NEED_SIGNAL_CATCHER
|
||||
#undef DONT_USE_B_MODE
|
||||
#undef PROGRESS_REPORT /* optional */
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
* jdatadst.c
|
||||
*
|
||||
* Copyright (C) 1994-1996, Thomas G. Lane.
|
||||
* Modified 2009-2019 by Guido Vollbeding.
|
||||
* Modified 2009-2022 by Guido Vollbeding.
|
||||
* This file is part of the Independent JPEG Group's software.
|
||||
* For conditions of distribution and use, see the accompanying README file.
|
||||
*
|
||||
|
|
@ -28,17 +28,17 @@ extern void free JPP((void *ptr));
|
|||
|
||||
/* Expanded data destination object for stdio output */
|
||||
|
||||
#define OUTPUT_BUF_SIZE 4096 /* choose an efficiently fwrite'able size */
|
||||
|
||||
typedef struct {
|
||||
struct jpeg_destination_mgr pub; /* public fields */
|
||||
|
||||
FILE * outfile; /* target stream */
|
||||
JOCTET * buffer; /* start of buffer */
|
||||
JOCTET buffer[OUTPUT_BUF_SIZE]; /* output buffer */
|
||||
} my_destination_mgr;
|
||||
|
||||
typedef my_destination_mgr * my_dest_ptr;
|
||||
|
||||
#define OUTPUT_BUF_SIZE 4096 /* choose an efficiently fwrite'able size */
|
||||
|
||||
|
||||
/* Expanded data destination object for memory output */
|
||||
|
||||
|
|
@ -65,10 +65,6 @@ init_destination (j_compress_ptr cinfo)
|
|||
{
|
||||
my_dest_ptr dest = (my_dest_ptr) cinfo->dest;
|
||||
|
||||
/* Allocate the output buffer --- it will be released when done with image */
|
||||
dest->buffer = (JOCTET *) (*cinfo->mem->alloc_small)
|
||||
((j_common_ptr) cinfo, JPOOL_IMAGE, OUTPUT_BUF_SIZE * SIZEOF(JOCTET));
|
||||
|
||||
dest->pub.next_output_byte = dest->buffer;
|
||||
dest->pub.free_in_buffer = OUTPUT_BUF_SIZE;
|
||||
}
|
||||
|
|
@ -187,8 +183,8 @@ term_mem_destination (j_compress_ptr cinfo)
|
|||
|
||||
/*
|
||||
* Prepare for output to a stdio stream.
|
||||
* The caller must have already opened the stream, and is responsible
|
||||
* for closing it after finishing compression.
|
||||
* The caller must have already opened the stream,
|
||||
* and is responsible for closing it after finishing compression.
|
||||
*/
|
||||
|
||||
GLOBAL(void)
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
* jdatasrc.c
|
||||
*
|
||||
* Copyright (C) 1994-1996, Thomas G. Lane.
|
||||
* Modified 2009-2019 by Guido Vollbeding.
|
||||
* Modified 2009-2022 by Guido Vollbeding.
|
||||
* This file is part of the Independent JPEG Group's software.
|
||||
* For conditions of distribution and use, see the accompanying README file.
|
||||
*
|
||||
|
|
@ -23,18 +23,18 @@
|
|||
|
||||
/* Expanded data source object for stdio input */
|
||||
|
||||
#define INPUT_BUF_SIZE 4096 /* choose an efficiently fread'able size */
|
||||
|
||||
typedef struct {
|
||||
struct jpeg_source_mgr pub; /* public fields */
|
||||
|
||||
FILE * infile; /* source stream */
|
||||
JOCTET * buffer; /* start of buffer */
|
||||
JOCTET buffer[INPUT_BUF_SIZE]; /* input buffer */
|
||||
boolean start_of_file; /* have we gotten any data yet? */
|
||||
} my_source_mgr;
|
||||
|
||||
typedef my_source_mgr * my_src_ptr;
|
||||
|
||||
#define INPUT_BUF_SIZE 4096 /* choose an efficiently fread'able size */
|
||||
|
||||
|
||||
/*
|
||||
* Initialize source --- called by jpeg_read_header
|
||||
|
|
@ -204,8 +204,8 @@ term_source (j_decompress_ptr cinfo)
|
|||
|
||||
/*
|
||||
* Prepare for input from a stdio stream.
|
||||
* The caller must have already opened the stream, and is responsible
|
||||
* for closing it after finishing decompression.
|
||||
* The caller must have already opened the stream,
|
||||
* and is responsible for closing it after finishing decompression.
|
||||
*/
|
||||
|
||||
GLOBAL(void)
|
||||
|
|
@ -213,19 +213,16 @@ jpeg_stdio_src (j_decompress_ptr cinfo, FILE * infile)
|
|||
{
|
||||
my_src_ptr src;
|
||||
|
||||
/* The source object and input buffer are made permanent so that a series
|
||||
* of JPEG images can be read from the same file by calling jpeg_stdio_src
|
||||
* only before the first one. (If we discarded the buffer at the end of
|
||||
* one image, we'd likely lose the start of the next one.)
|
||||
/* The source object including the input buffer is made permanent so that
|
||||
* a series of JPEG images can be read from the same file by calling
|
||||
* jpeg_stdio_src only before the first one. (If we discarded the buffer
|
||||
* at the end of one image, we'd likely lose the start of the next one.)
|
||||
* This makes it unsafe to use this manager and a different source
|
||||
* manager serially with the same JPEG object. Caveat programmer.
|
||||
*/
|
||||
if (cinfo->src == NULL) { /* first time for this JPEG object? */
|
||||
cinfo->src = (struct jpeg_source_mgr *) (*cinfo->mem->alloc_small)
|
||||
((j_common_ptr) cinfo, JPOOL_PERMANENT, SIZEOF(my_source_mgr));
|
||||
src = (my_src_ptr) cinfo->src;
|
||||
src->buffer = (JOCTET *) (*cinfo->mem->alloc_small)
|
||||
((j_common_ptr) cinfo, JPOOL_PERMANENT, INPUT_BUF_SIZE * SIZEOF(JOCTET));
|
||||
}
|
||||
|
||||
src = (my_src_ptr) cinfo->src;
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
* jdcolor.c
|
||||
*
|
||||
* Copyright (C) 1991-1997, Thomas G. Lane.
|
||||
* Modified 2011-2020 by Guido Vollbeding.
|
||||
* Modified 2011-2023 by Guido Vollbeding.
|
||||
* This file is part of the Independent JPEG Group's software.
|
||||
* For conditions of distribution and use, see the accompanying README file.
|
||||
*
|
||||
|
|
@ -32,7 +32,9 @@ typedef struct {
|
|||
INT32 * Cb_g_tab; /* => table for Cb to G conversion */
|
||||
|
||||
/* Private state for RGB->Y conversion */
|
||||
INT32 * rgb_y_tab; /* => table for RGB to Y conversion */
|
||||
INT32 * R_y_tab; /* => table for R to Y conversion */
|
||||
INT32 * G_y_tab; /* => table for G to Y conversion */
|
||||
INT32 * B_y_tab; /* => table for B to Y conversion */
|
||||
} my_color_deconverter;
|
||||
|
||||
typedef my_color_deconverter * my_cconvert_ptr;
|
||||
|
|
@ -87,29 +89,17 @@ typedef my_color_deconverter * my_cconvert_ptr;
|
|||
* by precalculating the constants times Cb and Cr for all possible values.
|
||||
* For 8-bit JSAMPLEs this is very reasonable (only 256 entries per table);
|
||||
* for 9-bit to 12-bit samples it is still acceptable. It's not very
|
||||
* reasonable for 16-bit samples, but if you want lossless storage you
|
||||
* shouldn't be changing colorspace anyway.
|
||||
* The Cr=>R and Cb=>B values can be rounded to integers in advance; the
|
||||
* values for the G calculation are left scaled up, since we must add them
|
||||
* together before rounding.
|
||||
* reasonable for 16-bit samples, but if you want lossless storage
|
||||
* you shouldn't be changing colorspace anyway.
|
||||
* The Cr=>R and Cb=>B values can be rounded to integers in advance;
|
||||
* the values for the G calculation are left scaled up,
|
||||
* since we must add them together before rounding.
|
||||
*/
|
||||
|
||||
#define SCALEBITS 16 /* speediest right-shift on some machines */
|
||||
#define ONE_HALF ((INT32) 1 << (SCALEBITS-1))
|
||||
#define FIX(x) ((INT32) ((x) * (1L<<SCALEBITS) + 0.5))
|
||||
|
||||
/* We allocate one big table for RGB->Y conversion and divide it up into
|
||||
* three parts, instead of doing three alloc_small requests. This lets us
|
||||
* use a single table base address, which can be held in a register in the
|
||||
* inner loops on many machines (more than can hold all three addresses,
|
||||
* anyway).
|
||||
*/
|
||||
|
||||
#define R_Y_OFF 0 /* offset to R => Y section */
|
||||
#define G_Y_OFF (1*(MAXJSAMPLE+1)) /* offset to G => Y section */
|
||||
#define B_Y_OFF (2*(MAXJSAMPLE+1)) /* etc. */
|
||||
#define TABLE_SIZE (3*(MAXJSAMPLE+1))
|
||||
|
||||
|
||||
/*
|
||||
* Initialize tables for YCbCr->RGB and BG_YCC->RGB colorspace conversion.
|
||||
|
|
@ -249,17 +239,19 @@ LOCAL(void)
|
|||
build_rgb_y_table (j_decompress_ptr cinfo)
|
||||
{
|
||||
my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert;
|
||||
INT32 * rgb_y_tab;
|
||||
INT32 i;
|
||||
|
||||
/* Allocate and fill in the conversion tables. */
|
||||
cconvert->rgb_y_tab = rgb_y_tab = (INT32 *) (*cinfo->mem->alloc_small)
|
||||
((j_common_ptr) cinfo, JPOOL_IMAGE, TABLE_SIZE * SIZEOF(INT32));
|
||||
cconvert->R_y_tab = (INT32 *) (*cinfo->mem->alloc_small)
|
||||
((j_common_ptr) cinfo, JPOOL_IMAGE, (MAXJSAMPLE+1) * SIZEOF(INT32));
|
||||
cconvert->G_y_tab = (INT32 *) (*cinfo->mem->alloc_small)
|
||||
((j_common_ptr) cinfo, JPOOL_IMAGE, (MAXJSAMPLE+1) * SIZEOF(INT32));
|
||||
cconvert->B_y_tab = (INT32 *) (*cinfo->mem->alloc_small)
|
||||
((j_common_ptr) cinfo, JPOOL_IMAGE, (MAXJSAMPLE+1) * SIZEOF(INT32));
|
||||
|
||||
for (i = 0; i <= MAXJSAMPLE; i++) {
|
||||
rgb_y_tab[i+R_Y_OFF] = FIX(0.299) * i;
|
||||
rgb_y_tab[i+G_Y_OFF] = FIX(0.587) * i;
|
||||
rgb_y_tab[i+B_Y_OFF] = FIX(0.114) * i + ONE_HALF;
|
||||
cconvert->R_y_tab[i] = FIX(0.299) * i;
|
||||
cconvert->G_y_tab[i] = FIX(0.587) * i;
|
||||
cconvert->B_y_tab[i] = FIX(0.114) * i + ONE_HALF;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -274,8 +266,10 @@ rgb_gray_convert (j_decompress_ptr cinfo,
|
|||
JSAMPARRAY output_buf, int num_rows)
|
||||
{
|
||||
my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert;
|
||||
register int r, g, b;
|
||||
register INT32 * ctab = cconvert->rgb_y_tab;
|
||||
register INT32 y;
|
||||
register INT32 * Rytab = cconvert->R_y_tab;
|
||||
register INT32 * Gytab = cconvert->G_y_tab;
|
||||
register INT32 * Bytab = cconvert->B_y_tab;
|
||||
register JSAMPROW outptr;
|
||||
register JSAMPROW inptr0, inptr1, inptr2;
|
||||
register JDIMENSION col;
|
||||
|
|
@ -288,13 +282,10 @@ rgb_gray_convert (j_decompress_ptr cinfo,
|
|||
input_row++;
|
||||
outptr = *output_buf++;
|
||||
for (col = 0; col < num_cols; col++) {
|
||||
r = GETJSAMPLE(inptr0[col]);
|
||||
g = GETJSAMPLE(inptr1[col]);
|
||||
b = GETJSAMPLE(inptr2[col]);
|
||||
/* Y */
|
||||
outptr[col] = (JSAMPLE)
|
||||
((ctab[r+R_Y_OFF] + ctab[g+G_Y_OFF] + ctab[b+B_Y_OFF])
|
||||
>> SCALEBITS);
|
||||
y = Rytab[GETJSAMPLE(inptr0[col])];
|
||||
y += Gytab[GETJSAMPLE(inptr1[col])];
|
||||
y += Bytab[GETJSAMPLE(inptr2[col])];
|
||||
outptr[col] = (JSAMPLE) (y >> SCALEBITS);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -354,7 +345,10 @@ rgb1_gray_convert (j_decompress_ptr cinfo,
|
|||
{
|
||||
my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert;
|
||||
register int r, g, b;
|
||||
register INT32 * ctab = cconvert->rgb_y_tab;
|
||||
register INT32 y;
|
||||
register INT32 * Rytab = cconvert->R_y_tab;
|
||||
register INT32 * Gytab = cconvert->G_y_tab;
|
||||
register INT32 * Bytab = cconvert->B_y_tab;
|
||||
register JSAMPROW outptr;
|
||||
register JSAMPROW inptr0, inptr1, inptr2;
|
||||
register JDIMENSION col;
|
||||
|
|
@ -373,12 +367,10 @@ rgb1_gray_convert (j_decompress_ptr cinfo,
|
|||
/* Assume that MAXJSAMPLE+1 is a power of 2, so that the MOD
|
||||
* (modulo) operator is equivalent to the bitmask operator AND.
|
||||
*/
|
||||
r = (r + g - CENTERJSAMPLE) & MAXJSAMPLE;
|
||||
b = (b + g - CENTERJSAMPLE) & MAXJSAMPLE;
|
||||
/* Y */
|
||||
outptr[col] = (JSAMPLE)
|
||||
((ctab[r+R_Y_OFF] + ctab[g+G_Y_OFF] + ctab[b+B_Y_OFF])
|
||||
>> SCALEBITS);
|
||||
y = Rytab[(r + g - CENTERJSAMPLE) & MAXJSAMPLE];
|
||||
y += Gytab[g];
|
||||
y += Bytab[(b + g - CENTERJSAMPLE) & MAXJSAMPLE];
|
||||
outptr[col] = (JSAMPLE) (y >> SCALEBITS);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -565,8 +557,10 @@ cmyk_yk_convert (j_decompress_ptr cinfo,
|
|||
JSAMPARRAY output_buf, int num_rows)
|
||||
{
|
||||
my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert;
|
||||
register int r, g, b;
|
||||
register INT32 * ctab = cconvert->rgb_y_tab;
|
||||
register INT32 y;
|
||||
register INT32 * Rytab = cconvert->R_y_tab;
|
||||
register INT32 * Gytab = cconvert->G_y_tab;
|
||||
register INT32 * Bytab = cconvert->B_y_tab;
|
||||
register JSAMPROW outptr;
|
||||
register JSAMPROW inptr0, inptr1, inptr2, inptr3;
|
||||
register JDIMENSION col;
|
||||
|
|
@ -580,13 +574,10 @@ cmyk_yk_convert (j_decompress_ptr cinfo,
|
|||
input_row++;
|
||||
outptr = *output_buf++;
|
||||
for (col = 0; col < num_cols; col++) {
|
||||
r = MAXJSAMPLE - GETJSAMPLE(inptr0[col]);
|
||||
g = MAXJSAMPLE - GETJSAMPLE(inptr1[col]);
|
||||
b = MAXJSAMPLE - GETJSAMPLE(inptr2[col]);
|
||||
/* Y */
|
||||
outptr[0] = (JSAMPLE)
|
||||
((ctab[r+R_Y_OFF] + ctab[g+G_Y_OFF] + ctab[b+B_Y_OFF])
|
||||
>> SCALEBITS);
|
||||
y = Rytab[MAXJSAMPLE - GETJSAMPLE(inptr0[col])];
|
||||
y += Gytab[MAXJSAMPLE - GETJSAMPLE(inptr1[col])];
|
||||
y += Bytab[MAXJSAMPLE - GETJSAMPLE(inptr2[col])];
|
||||
outptr[0] = (JSAMPLE) (y >> SCALEBITS);
|
||||
/* K passes through unchanged */
|
||||
outptr[1] = inptr3[col]; /* don't need GETJSAMPLE here */
|
||||
outptr += 2;
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
* jdct.h
|
||||
*
|
||||
* Copyright (C) 1994-1996, Thomas G. Lane.
|
||||
* Modified 2002-2019 by Guido Vollbeding.
|
||||
* Modified 2002-2023 by Guido Vollbeding.
|
||||
* This file is part of the Independent JPEG Group's software.
|
||||
* For conditions of distribution and use, see the accompanying README file.
|
||||
*
|
||||
|
|
@ -158,7 +158,7 @@ typedef FAST_FLOAT FLOAT_MULT_TYPE; /* preferred floating type */
|
|||
#define jpeg_idct_6x12 jRD6x12
|
||||
#define jpeg_idct_5x10 jRD5x10
|
||||
#define jpeg_idct_4x8 jRD4x8
|
||||
#define jpeg_idct_3x6 jRD3x8
|
||||
#define jpeg_idct_3x6 jRD3x6
|
||||
#define jpeg_idct_2x4 jRD2x4
|
||||
#define jpeg_idct_1x2 jRD1x2
|
||||
#endif /* NEED_SHORT_EXTERNAL_NAMES */
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
* jdmerge.c
|
||||
*
|
||||
* Copyright (C) 1994-1996, Thomas G. Lane.
|
||||
* Modified 2013-2020 by Guido Vollbeding.
|
||||
* Modified 2013-2022 by Guido Vollbeding.
|
||||
* This file is part of the Independent JPEG Group's software.
|
||||
* For conditions of distribution and use, see the accompanying README file.
|
||||
*
|
||||
|
|
@ -20,17 +20,17 @@
|
|||
* B = Y + K4 * Cb
|
||||
* only the Y term varies among the group of pixels corresponding to a pair
|
||||
* of chroma samples, so the rest of the terms can be calculated just once.
|
||||
* At typical sampling ratios, this eliminates half or three-quarters of the
|
||||
* multiplications needed for color conversion.
|
||||
* At typical sampling ratios, this eliminates half or three-quarters
|
||||
* of the multiplications needed for color conversion.
|
||||
*
|
||||
* This file currently provides implementations for the following cases:
|
||||
* YCC => RGB color conversion only (YCbCr or BG_YCC).
|
||||
* Sampling ratios of 2h1v or 2h2v.
|
||||
* No scaling needed at upsample time.
|
||||
* Corner-aligned (non-CCIR601) sampling alignment.
|
||||
* Other special cases could be added, but in most applications these are
|
||||
* the only common cases. (For uncommon cases we fall back on the more
|
||||
* general code in jdsample.c and jdcolor.c.)
|
||||
* Other special cases could be added, but in most applications these
|
||||
* are the only common cases. (For uncommon cases we fall back on
|
||||
* the more general code in jdsample.c and jdcolor.c.)
|
||||
*/
|
||||
|
||||
#define JPEG_INTERNALS
|
||||
|
|
@ -286,9 +286,9 @@ h2v1_merged_upsample (j_decompress_ptr cinfo,
|
|||
/* Do the chroma part of the calculation */
|
||||
cb = GETJSAMPLE(*inptr1++);
|
||||
cr = GETJSAMPLE(*inptr2++);
|
||||
cred = Crrtab[cr];
|
||||
cgreen = (int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS);
|
||||
cblue = Cbbtab[cb];
|
||||
cred = Crrtab[cr];
|
||||
/* Fetch 2 Y values and emit 2 pixels */
|
||||
y = GETJSAMPLE(*inptr0++);
|
||||
outptr[RGB_RED] = range_limit[y + cred];
|
||||
|
|
@ -303,15 +303,14 @@ h2v1_merged_upsample (j_decompress_ptr cinfo,
|
|||
}
|
||||
/* If image width is odd, do the last output column separately */
|
||||
if (cinfo->output_width & 1) {
|
||||
y = GETJSAMPLE(*inptr0);
|
||||
cb = GETJSAMPLE(*inptr1);
|
||||
cr = GETJSAMPLE(*inptr2);
|
||||
cred = Crrtab[cr];
|
||||
cgreen = (int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS);
|
||||
cblue = Cbbtab[cb];
|
||||
y = GETJSAMPLE(*inptr0);
|
||||
outptr[RGB_RED] = range_limit[y + cred];
|
||||
outptr[RGB_GREEN] = range_limit[y + cgreen];
|
||||
outptr[RGB_BLUE] = range_limit[y + cblue];
|
||||
outptr[RGB_RED] = range_limit[y + Crrtab[cr]];
|
||||
outptr[RGB_GREEN] = range_limit[y +
|
||||
((int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr],
|
||||
SCALEBITS))];
|
||||
outptr[RGB_BLUE] = range_limit[y + Cbbtab[cb]];
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -350,9 +349,9 @@ h2v2_merged_upsample (j_decompress_ptr cinfo,
|
|||
/* Do the chroma part of the calculation */
|
||||
cb = GETJSAMPLE(*inptr1++);
|
||||
cr = GETJSAMPLE(*inptr2++);
|
||||
cred = Crrtab[cr];
|
||||
cgreen = (int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS);
|
||||
cblue = Cbbtab[cb];
|
||||
cred = Crrtab[cr];
|
||||
/* Fetch 4 Y values and emit 4 pixels */
|
||||
y = GETJSAMPLE(*inptr00++);
|
||||
outptr0[RGB_RED] = range_limit[y + cred];
|
||||
|
|
@ -379,9 +378,9 @@ h2v2_merged_upsample (j_decompress_ptr cinfo,
|
|||
if (cinfo->output_width & 1) {
|
||||
cb = GETJSAMPLE(*inptr1);
|
||||
cr = GETJSAMPLE(*inptr2);
|
||||
cred = Crrtab[cr];
|
||||
cgreen = (int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS);
|
||||
cblue = Cbbtab[cb];
|
||||
cred = Crrtab[cr];
|
||||
y = GETJSAMPLE(*inptr00);
|
||||
outptr0[RGB_RED] = range_limit[y + cred];
|
||||
outptr0[RGB_GREEN] = range_limit[y + cgreen];
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
* jinclude.h
|
||||
*
|
||||
* Copyright (C) 1991-1994, Thomas G. Lane.
|
||||
* Modified 2017 by Guido Vollbeding.
|
||||
* Modified 2017-2022 by Guido Vollbeding.
|
||||
* This file is part of the Independent JPEG Group's software.
|
||||
* For conditions of distribution and use, see the accompanying README file.
|
||||
*
|
||||
|
|
@ -11,8 +11,8 @@
|
|||
* care of by the standard jconfig symbols, but on really weird systems
|
||||
* you may have to edit this file.)
|
||||
*
|
||||
* NOTE: this file is NOT intended to be included by applications using the
|
||||
* JPEG library. Most applications need only include jpeglib.h.
|
||||
* NOTE: this file is NOT intended to be included by applications using
|
||||
* the JPEG library. Most applications need only include jpeglib.h.
|
||||
*/
|
||||
|
||||
|
||||
|
|
@ -87,11 +87,71 @@
|
|||
*
|
||||
* Furthermore, macros are provided for fflush() and ferror() in order
|
||||
* to facilitate adaption by applications using an own FILE class.
|
||||
*
|
||||
* You can define your own custom file I/O functions in jconfig.h and
|
||||
* #define JPEG_HAVE_FILE_IO_CUSTOM there to prevent redefinition here.
|
||||
*
|
||||
* You can #define JPEG_USE_FILE_IO_CUSTOM in jconfig.h to use custom file
|
||||
* I/O functions implemented in Delphi VCL (Visual Component Library)
|
||||
* in Vcl.Imaging.jpeg.pas for the TJPEGImage component utilizing
|
||||
* the Delphi RTL (Run-Time Library) TMemoryStream component:
|
||||
*
|
||||
* procedure jpeg_stdio_src(var cinfo: jpeg_decompress_struct;
|
||||
* input_file: TStream); external;
|
||||
*
|
||||
* procedure jpeg_stdio_dest(var cinfo: jpeg_compress_struct;
|
||||
* output_file: TStream); external;
|
||||
*
|
||||
* function jfread(var buf; recsize, reccount: Integer; S: TStream): Integer;
|
||||
* begin
|
||||
* Result := S.Read(buf, recsize * reccount);
|
||||
* end;
|
||||
*
|
||||
* function jfwrite(const buf; recsize, reccount: Integer; S: TStream): Integer;
|
||||
* begin
|
||||
* Result := S.Write(buf, recsize * reccount);
|
||||
* end;
|
||||
*
|
||||
* function jfflush(S: TStream): Integer;
|
||||
* begin
|
||||
* Result := 0;
|
||||
* end;
|
||||
*
|
||||
* function jferror(S: TStream): Integer;
|
||||
* begin
|
||||
* Result := 0;
|
||||
* end;
|
||||
*
|
||||
* TMemoryStream of Delphi RTL has the distinctive feature to provide dynamic
|
||||
* memory buffer management with a file/stream-based interface, particularly for
|
||||
* the write (output) operation, which is easier to apply compared with direct
|
||||
* implementations as given in jdatadst.c for memory destination. Those direct
|
||||
* implementations of dynamic memory write tend to be more difficult to use,
|
||||
* so providing an option like TMemoryStream may be a useful alternative.
|
||||
*
|
||||
* The CFile/CMemFile classes of the Microsoft Foundation Class (MFC) Library
|
||||
* may be used in a similar fashion.
|
||||
*/
|
||||
|
||||
#ifndef JPEG_HAVE_FILE_IO_CUSTOM
|
||||
#ifdef JPEG_USE_FILE_IO_CUSTOM
|
||||
extern size_t jfread(void * __ptr, size_t __size, size_t __n, FILE * __stream);
|
||||
extern size_t jfwrite(const void * __ptr, size_t __size, size_t __n, FILE * __stream);
|
||||
extern int jfflush(FILE * __stream);
|
||||
extern int jferror(FILE * __fp);
|
||||
|
||||
#define JFREAD(file,buf,sizeofbuf) \
|
||||
((size_t) jfread((void *) (buf), (size_t) 1, (size_t) (sizeofbuf), (file)))
|
||||
#define JFWRITE(file,buf,sizeofbuf) \
|
||||
((size_t) jfwrite((const void *) (buf), (size_t) 1, (size_t) (sizeofbuf), (file)))
|
||||
#define JFFLUSH(file) jfflush(file)
|
||||
#define JFERROR(file) jferror(file)
|
||||
#else
|
||||
#define JFREAD(file,buf,sizeofbuf) \
|
||||
((size_t) fread((void *) (buf), (size_t) 1, (size_t) (sizeofbuf), (file)))
|
||||
#define JFWRITE(file,buf,sizeofbuf) \
|
||||
((size_t) fwrite((const void *) (buf), (size_t) 1, (size_t) (sizeofbuf), (file)))
|
||||
#define JFFLUSH(file) fflush(file)
|
||||
#define JFERROR(file) ferror(file)
|
||||
#endif
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -73,12 +73,10 @@ jpeg_free_large (j_common_ptr cinfo, void FAR * object, size_t sizeofobject)
|
|||
* a slop factor of 5% or so.
|
||||
*/
|
||||
|
||||
#ifdef DEFAULT_MAX_MEM /* so can override from makefile */
|
||||
#undef DEFAULT_MAX_MEM
|
||||
#ifndef DEFAULT_MAX_MEM /* so can override from makefile */
|
||||
#define DEFAULT_MAX_MEM 1000000L /* default: one megabyte */
|
||||
#endif
|
||||
|
||||
#define DEFAULT_MAX_MEM 100000000L //U++: Let us have this fixed at 100MB...
|
||||
|
||||
GLOBAL(long)
|
||||
jpeg_mem_available (j_common_ptr cinfo, long min_bytes_needed,
|
||||
long max_bytes_needed, long already_allocated)
|
||||
|
|
|
|||
|
|
@ -1,638 +0,0 @@
|
|||
/*
|
||||
* jmemdos.c
|
||||
*
|
||||
* Copyright (C) 1992-1997, 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.
|
||||
*
|
||||
* This file provides an MS-DOS-compatible implementation of the system-
|
||||
* dependent portion of the JPEG memory manager. Temporary data can be
|
||||
* stored in extended or expanded memory as well as in regular DOS files.
|
||||
*
|
||||
* If you use this file, you must be sure that NEED_FAR_POINTERS is defined
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* If you have both extended and expanded memory, you may want to change the
|
||||
* order in which they are tried in jopen_backing_store. On a 286 machine
|
||||
* expanded memory is usually faster, since extended memory access involves
|
||||
* an expensive protected-mode-and-back switch. On 386 and better, extended
|
||||
* memory is usually faster. As distributed, the code tries extended memory
|
||||
* first (what? not everyone has a 386? :-).
|
||||
*
|
||||
* You can disable use of extended/expanded memory entirely by altering these
|
||||
* definitions or overriding them from the Makefile (eg, -DEMS_SUPPORTED=0).
|
||||
*/
|
||||
|
||||
#ifndef XMS_SUPPORTED
|
||||
#define XMS_SUPPORTED 1
|
||||
#endif
|
||||
#ifndef EMS_SUPPORTED
|
||||
#define EMS_SUPPORTED 1
|
||||
#endif
|
||||
|
||||
|
||||
#define JPEG_INTERNALS
|
||||
#include "jinclude.h"
|
||||
#include "jpeglib.h"
|
||||
#include "jmemsys.h" /* import the system-dependent declarations */
|
||||
|
||||
#ifndef HAVE_STDLIB_H /* <stdlib.h> should declare these */
|
||||
extern void * malloc JPP((size_t size));
|
||||
extern void free JPP((void *ptr));
|
||||
extern char * getenv JPP((const char * name));
|
||||
#endif
|
||||
|
||||
#ifdef NEED_FAR_POINTERS
|
||||
|
||||
#ifdef __TURBOC__
|
||||
/* These definitions work for Borland C (Turbo C) */
|
||||
#include <alloc.h> /* need farmalloc(), farfree() */
|
||||
#define far_malloc(x) farmalloc(x)
|
||||
#define far_free(x) farfree(x)
|
||||
#else
|
||||
/* These definitions work for Microsoft C and compatible compilers */
|
||||
#include <malloc.h> /* need _fmalloc(), _ffree() */
|
||||
#define far_malloc(x) _fmalloc(x)
|
||||
#define far_free(x) _ffree(x)
|
||||
#endif
|
||||
|
||||
#else /* not NEED_FAR_POINTERS */
|
||||
|
||||
#define far_malloc(x) malloc(x)
|
||||
#define far_free(x) free(x)
|
||||
|
||||
#endif /* NEED_FAR_POINTERS */
|
||||
|
||||
#ifdef DONT_USE_B_MODE /* define mode parameters for fopen() */
|
||||
#define READ_BINARY "r"
|
||||
#else
|
||||
#define READ_BINARY "rb"
|
||||
#endif
|
||||
|
||||
#ifndef USE_MSDOS_MEMMGR /* make sure user got configuration right */
|
||||
You forgot to define USE_MSDOS_MEMMGR in jconfig.h. /* deliberate syntax error */
|
||||
#endif
|
||||
|
||||
#if MAX_ALLOC_CHUNK >= 65535L /* make sure jconfig.h got this right */
|
||||
MAX_ALLOC_CHUNK should be less than 64K. /* deliberate syntax error */
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* Declarations for assembly-language support routines (see jmemdosa.asm).
|
||||
*
|
||||
* The functions are declared "far" as are all their pointer arguments;
|
||||
* this ensures the assembly source code will work regardless of the
|
||||
* compiler memory model. We assume "short" is 16 bits, "long" is 32.
|
||||
*/
|
||||
|
||||
typedef void far * XMSDRIVER; /* actually a pointer to code */
|
||||
typedef struct { /* registers for calling XMS driver */
|
||||
unsigned short ax, dx, bx;
|
||||
void far * ds_si;
|
||||
} XMScontext;
|
||||
typedef struct { /* registers for calling EMS driver */
|
||||
unsigned short ax, dx, bx;
|
||||
void far * ds_si;
|
||||
} EMScontext;
|
||||
|
||||
extern short far jdos_open JPP((short far * handle, char far * filename));
|
||||
extern short far jdos_close JPP((short handle));
|
||||
extern short far jdos_seek JPP((short handle, long offset));
|
||||
extern short far jdos_read JPP((short handle, void far * buffer,
|
||||
unsigned short count));
|
||||
extern short far jdos_write JPP((short handle, void far * buffer,
|
||||
unsigned short count));
|
||||
extern void far jxms_getdriver JPP((XMSDRIVER far *));
|
||||
extern void far jxms_calldriver JPP((XMSDRIVER, XMScontext far *));
|
||||
extern short far jems_available JPP((void));
|
||||
extern void far jems_calldriver JPP((EMScontext far *));
|
||||
|
||||
|
||||
/*
|
||||
* Selection of a file name for a temporary file.
|
||||
* This is highly system-dependent, and you may want to customize it.
|
||||
*/
|
||||
|
||||
static int next_file_num; /* to distinguish among several temp files */
|
||||
|
||||
LOCAL(void)
|
||||
select_file_name (char * fname)
|
||||
{
|
||||
const char * env;
|
||||
char * ptr;
|
||||
FILE * tfile;
|
||||
|
||||
/* Keep generating file names till we find one that's not in use */
|
||||
for (;;) {
|
||||
/* Get temp directory name from environment TMP or TEMP variable;
|
||||
* if none, use "."
|
||||
*/
|
||||
if ((env = (const char *) getenv("TMP")) == NULL)
|
||||
if ((env = (const char *) getenv("TEMP")) == NULL)
|
||||
env = ".";
|
||||
if (*env == '\0') /* null string means "." */
|
||||
env = ".";
|
||||
ptr = fname; /* copy name to fname */
|
||||
while (*env != '\0')
|
||||
*ptr++ = *env++;
|
||||
if (ptr[-1] != '\\' && ptr[-1] != '/')
|
||||
*ptr++ = '\\'; /* append backslash if not in env variable */
|
||||
/* Append a suitable file name */
|
||||
next_file_num++; /* advance counter */
|
||||
sprintf(ptr, "JPG%03d.TMP", next_file_num);
|
||||
/* Probe to see if file name is already in use */
|
||||
if ((tfile = fopen(fname, READ_BINARY)) == NULL)
|
||||
break;
|
||||
fclose(tfile); /* oops, it's there; close tfile & try again */
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Near-memory allocation and freeing are controlled by the regular library
|
||||
* routines malloc() and free().
|
||||
*/
|
||||
|
||||
GLOBAL(void *)
|
||||
jpeg_get_small (j_common_ptr cinfo, size_t sizeofobject)
|
||||
{
|
||||
return (void *) malloc(sizeofobject);
|
||||
}
|
||||
|
||||
GLOBAL(void)
|
||||
jpeg_free_small (j_common_ptr cinfo, void * object, size_t sizeofobject)
|
||||
{
|
||||
free(object);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* "Large" objects are allocated in far memory, if possible
|
||||
*/
|
||||
|
||||
GLOBAL(void FAR *)
|
||||
jpeg_get_large (j_common_ptr cinfo, size_t sizeofobject)
|
||||
{
|
||||
return (void FAR *) far_malloc(sizeofobject);
|
||||
}
|
||||
|
||||
GLOBAL(void)
|
||||
jpeg_free_large (j_common_ptr cinfo, void FAR * object, size_t sizeofobject)
|
||||
{
|
||||
far_free(object);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* This routine computes the total memory space available for allocation.
|
||||
* It's impossible to do this in a portable way; our current solution is
|
||||
* to make the user tell us (with a default value set at compile time).
|
||||
* If you can actually get the available space, it's a good idea to subtract
|
||||
* a slop factor of 5% or so.
|
||||
*/
|
||||
|
||||
#ifndef DEFAULT_MAX_MEM /* so can override from makefile */
|
||||
#define DEFAULT_MAX_MEM 300000L /* for total usage about 450K */
|
||||
#endif
|
||||
|
||||
GLOBAL(long)
|
||||
jpeg_mem_available (j_common_ptr cinfo, long min_bytes_needed,
|
||||
long max_bytes_needed, long already_allocated)
|
||||
{
|
||||
return cinfo->mem->max_memory_to_use - already_allocated;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Backing store (temporary file) management.
|
||||
* Backing store objects are only used when the value returned by
|
||||
* jpeg_mem_available is less than the total space needed. You can dispense
|
||||
* with these routines if you have plenty of virtual memory; see jmemnobs.c.
|
||||
*/
|
||||
|
||||
/*
|
||||
* For MS-DOS we support three types of backing storage:
|
||||
* 1. Conventional DOS files. We access these by direct DOS calls rather
|
||||
* than via the stdio package. This provides a bit better performance,
|
||||
* but the real reason is that the buffers to be read or written are FAR.
|
||||
* The stdio library for small-data memory models can't cope with that.
|
||||
* 2. Extended memory, accessed per the XMS V2.0 specification.
|
||||
* 3. Expanded memory, accessed per the LIM/EMS 4.0 specification.
|
||||
* You'll need copies of those specs to make sense of the related code.
|
||||
* The specs are available by Internet FTP from the SIMTEL archives
|
||||
* (oak.oakland.edu and its various mirror sites). See files
|
||||
* pub/msdos/microsoft/xms20.arc and pub/msdos/info/limems41.zip.
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* Access methods for a DOS file.
|
||||
*/
|
||||
|
||||
|
||||
METHODDEF(void)
|
||||
read_file_store (j_common_ptr cinfo, backing_store_ptr info,
|
||||
void FAR * buffer_address,
|
||||
long file_offset, long byte_count)
|
||||
{
|
||||
if (jdos_seek(info->handle.file_handle, file_offset))
|
||||
ERREXIT(cinfo, JERR_TFILE_SEEK);
|
||||
/* Since MAX_ALLOC_CHUNK is less than 64K, byte_count will be too. */
|
||||
if (byte_count > 65535L) /* safety check */
|
||||
ERREXIT(cinfo, JERR_BAD_ALLOC_CHUNK);
|
||||
if (jdos_read(info->handle.file_handle, buffer_address,
|
||||
(unsigned short) byte_count))
|
||||
ERREXIT(cinfo, JERR_TFILE_READ);
|
||||
}
|
||||
|
||||
|
||||
METHODDEF(void)
|
||||
write_file_store (j_common_ptr cinfo, backing_store_ptr info,
|
||||
void FAR * buffer_address,
|
||||
long file_offset, long byte_count)
|
||||
{
|
||||
if (jdos_seek(info->handle.file_handle, file_offset))
|
||||
ERREXIT(cinfo, JERR_TFILE_SEEK);
|
||||
/* Since MAX_ALLOC_CHUNK is less than 64K, byte_count will be too. */
|
||||
if (byte_count > 65535L) /* safety check */
|
||||
ERREXIT(cinfo, JERR_BAD_ALLOC_CHUNK);
|
||||
if (jdos_write(info->handle.file_handle, buffer_address,
|
||||
(unsigned short) byte_count))
|
||||
ERREXIT(cinfo, JERR_TFILE_WRITE);
|
||||
}
|
||||
|
||||
|
||||
METHODDEF(void)
|
||||
close_file_store (j_common_ptr cinfo, backing_store_ptr info)
|
||||
{
|
||||
jdos_close(info->handle.file_handle); /* close the file */
|
||||
remove(info->temp_name); /* delete the file */
|
||||
/* If your system doesn't have remove(), try unlink() instead.
|
||||
* remove() is the ANSI-standard name for this function, but
|
||||
* unlink() was more common in pre-ANSI systems.
|
||||
*/
|
||||
TRACEMSS(cinfo, 1, JTRC_TFILE_CLOSE, info->temp_name);
|
||||
}
|
||||
|
||||
|
||||
LOCAL(boolean)
|
||||
open_file_store (j_common_ptr cinfo, backing_store_ptr info,
|
||||
long total_bytes_needed)
|
||||
{
|
||||
short handle;
|
||||
|
||||
select_file_name(info->temp_name);
|
||||
if (jdos_open((short far *) & handle, (char far *) info->temp_name)) {
|
||||
/* might as well exit since jpeg_open_backing_store will fail anyway */
|
||||
ERREXITS(cinfo, JERR_TFILE_CREATE, info->temp_name);
|
||||
return FALSE;
|
||||
}
|
||||
info->handle.file_handle = handle;
|
||||
info->read_backing_store = read_file_store;
|
||||
info->write_backing_store = write_file_store;
|
||||
info->close_backing_store = close_file_store;
|
||||
TRACEMSS(cinfo, 1, JTRC_TFILE_OPEN, info->temp_name);
|
||||
return TRUE; /* succeeded */
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Access methods for extended memory.
|
||||
*/
|
||||
|
||||
#if XMS_SUPPORTED
|
||||
|
||||
static XMSDRIVER xms_driver; /* saved address of XMS driver */
|
||||
|
||||
typedef union { /* either long offset or real-mode pointer */
|
||||
long offset;
|
||||
void far * ptr;
|
||||
} XMSPTR;
|
||||
|
||||
typedef struct { /* XMS move specification structure */
|
||||
long length;
|
||||
XMSH src_handle;
|
||||
XMSPTR src;
|
||||
XMSH dst_handle;
|
||||
XMSPTR dst;
|
||||
} XMSspec;
|
||||
|
||||
#define ODD(X) (((X) & 1L) != 0)
|
||||
|
||||
|
||||
METHODDEF(void)
|
||||
read_xms_store (j_common_ptr cinfo, backing_store_ptr info,
|
||||
void FAR * buffer_address,
|
||||
long file_offset, long byte_count)
|
||||
{
|
||||
XMScontext ctx;
|
||||
XMSspec spec;
|
||||
char endbuffer[2];
|
||||
|
||||
/* The XMS driver can't cope with an odd length, so handle the last byte
|
||||
* specially if byte_count is odd. We don't expect this to be common.
|
||||
*/
|
||||
|
||||
spec.length = byte_count & (~ 1L);
|
||||
spec.src_handle = info->handle.xms_handle;
|
||||
spec.src.offset = file_offset;
|
||||
spec.dst_handle = 0;
|
||||
spec.dst.ptr = buffer_address;
|
||||
|
||||
ctx.ds_si = (void far *) & spec;
|
||||
ctx.ax = 0x0b00; /* EMB move */
|
||||
jxms_calldriver(xms_driver, (XMScontext far *) & ctx);
|
||||
if (ctx.ax != 1)
|
||||
ERREXIT(cinfo, JERR_XMS_READ);
|
||||
|
||||
if (ODD(byte_count)) {
|
||||
read_xms_store(cinfo, info, (void FAR *) endbuffer,
|
||||
file_offset + byte_count - 1L, 2L);
|
||||
((char FAR *) buffer_address)[byte_count - 1L] = endbuffer[0];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
METHODDEF(void)
|
||||
write_xms_store (j_common_ptr cinfo, backing_store_ptr info,
|
||||
void FAR * buffer_address,
|
||||
long file_offset, long byte_count)
|
||||
{
|
||||
XMScontext ctx;
|
||||
XMSspec spec;
|
||||
char endbuffer[2];
|
||||
|
||||
/* The XMS driver can't cope with an odd length, so handle the last byte
|
||||
* specially if byte_count is odd. We don't expect this to be common.
|
||||
*/
|
||||
|
||||
spec.length = byte_count & (~ 1L);
|
||||
spec.src_handle = 0;
|
||||
spec.src.ptr = buffer_address;
|
||||
spec.dst_handle = info->handle.xms_handle;
|
||||
spec.dst.offset = file_offset;
|
||||
|
||||
ctx.ds_si = (void far *) & spec;
|
||||
ctx.ax = 0x0b00; /* EMB move */
|
||||
jxms_calldriver(xms_driver, (XMScontext far *) & ctx);
|
||||
if (ctx.ax != 1)
|
||||
ERREXIT(cinfo, JERR_XMS_WRITE);
|
||||
|
||||
if (ODD(byte_count)) {
|
||||
read_xms_store(cinfo, info, (void FAR *) endbuffer,
|
||||
file_offset + byte_count - 1L, 2L);
|
||||
endbuffer[0] = ((char FAR *) buffer_address)[byte_count - 1L];
|
||||
write_xms_store(cinfo, info, (void FAR *) endbuffer,
|
||||
file_offset + byte_count - 1L, 2L);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
METHODDEF(void)
|
||||
close_xms_store (j_common_ptr cinfo, backing_store_ptr info)
|
||||
{
|
||||
XMScontext ctx;
|
||||
|
||||
ctx.dx = info->handle.xms_handle;
|
||||
ctx.ax = 0x0a00;
|
||||
jxms_calldriver(xms_driver, (XMScontext far *) & ctx);
|
||||
TRACEMS1(cinfo, 1, JTRC_XMS_CLOSE, info->handle.xms_handle);
|
||||
/* we ignore any error return from the driver */
|
||||
}
|
||||
|
||||
|
||||
LOCAL(boolean)
|
||||
open_xms_store (j_common_ptr cinfo, backing_store_ptr info,
|
||||
long total_bytes_needed)
|
||||
{
|
||||
XMScontext ctx;
|
||||
|
||||
/* Get address of XMS driver */
|
||||
jxms_getdriver((XMSDRIVER far *) & xms_driver);
|
||||
if (xms_driver == NULL)
|
||||
return FALSE; /* no driver to be had */
|
||||
|
||||
/* Get version number, must be >= 2.00 */
|
||||
ctx.ax = 0x0000;
|
||||
jxms_calldriver(xms_driver, (XMScontext far *) & ctx);
|
||||
if (ctx.ax < (unsigned short) 0x0200)
|
||||
return FALSE;
|
||||
|
||||
/* Try to get space (expressed in kilobytes) */
|
||||
ctx.dx = (unsigned short) ((total_bytes_needed + 1023L) >> 10);
|
||||
ctx.ax = 0x0900;
|
||||
jxms_calldriver(xms_driver, (XMScontext far *) & ctx);
|
||||
if (ctx.ax != 1)
|
||||
return FALSE;
|
||||
|
||||
/* Succeeded, save the handle and away we go */
|
||||
info->handle.xms_handle = ctx.dx;
|
||||
info->read_backing_store = read_xms_store;
|
||||
info->write_backing_store = write_xms_store;
|
||||
info->close_backing_store = close_xms_store;
|
||||
TRACEMS1(cinfo, 1, JTRC_XMS_OPEN, ctx.dx);
|
||||
return TRUE; /* succeeded */
|
||||
}
|
||||
|
||||
#endif /* XMS_SUPPORTED */
|
||||
|
||||
|
||||
/*
|
||||
* Access methods for expanded memory.
|
||||
*/
|
||||
|
||||
#if EMS_SUPPORTED
|
||||
|
||||
/* 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 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)
|
||||
#define LOBYTE(W) ((W) & 0xFF)
|
||||
|
||||
|
||||
METHODDEF(void)
|
||||
read_ems_store (j_common_ptr cinfo, backing_store_ptr info,
|
||||
void FAR * buffer_address,
|
||||
long file_offset, long byte_count)
|
||||
{
|
||||
EMScontext ctx;
|
||||
EMSspec spec;
|
||||
|
||||
spec.length = byte_count;
|
||||
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 */
|
||||
jems_calldriver((EMScontext far *) & ctx);
|
||||
if (HIBYTE(ctx.ax) != 0)
|
||||
ERREXIT(cinfo, JERR_EMS_READ);
|
||||
}
|
||||
|
||||
|
||||
METHODDEF(void)
|
||||
write_ems_store (j_common_ptr cinfo, backing_store_ptr info,
|
||||
void FAR * buffer_address,
|
||||
long file_offset, long byte_count)
|
||||
{
|
||||
EMScontext ctx;
|
||||
EMSspec spec;
|
||||
|
||||
spec.length = byte_count;
|
||||
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 */
|
||||
jems_calldriver((EMScontext far *) & ctx);
|
||||
if (HIBYTE(ctx.ax) != 0)
|
||||
ERREXIT(cinfo, JERR_EMS_WRITE);
|
||||
}
|
||||
|
||||
|
||||
METHODDEF(void)
|
||||
close_ems_store (j_common_ptr cinfo, backing_store_ptr info)
|
||||
{
|
||||
EMScontext ctx;
|
||||
|
||||
ctx.ax = 0x4500;
|
||||
ctx.dx = info->handle.ems_handle;
|
||||
jems_calldriver((EMScontext far *) & ctx);
|
||||
TRACEMS1(cinfo, 1, JTRC_EMS_CLOSE, info->handle.ems_handle);
|
||||
/* we ignore any error return from the driver */
|
||||
}
|
||||
|
||||
|
||||
LOCAL(boolean)
|
||||
open_ems_store (j_common_ptr cinfo, backing_store_ptr info,
|
||||
long total_bytes_needed)
|
||||
{
|
||||
EMScontext ctx;
|
||||
|
||||
/* Is EMS driver there? */
|
||||
if (! jems_available())
|
||||
return FALSE;
|
||||
|
||||
/* Get status, make sure EMS is OK */
|
||||
ctx.ax = 0x4000;
|
||||
jems_calldriver((EMScontext far *) & ctx);
|
||||
if (HIBYTE(ctx.ax) != 0)
|
||||
return FALSE;
|
||||
|
||||
/* Get version, must be >= 4.0 */
|
||||
ctx.ax = 0x4600;
|
||||
jems_calldriver((EMScontext far *) & ctx);
|
||||
if (HIBYTE(ctx.ax) != 0 || LOBYTE(ctx.ax) < 0x40)
|
||||
return FALSE;
|
||||
|
||||
/* Try to allocate requested space */
|
||||
ctx.ax = 0x4300;
|
||||
ctx.bx = (unsigned short) ((total_bytes_needed + EMSPAGESIZE-1L) / EMSPAGESIZE);
|
||||
jems_calldriver((EMScontext far *) & ctx);
|
||||
if (HIBYTE(ctx.ax) != 0)
|
||||
return FALSE;
|
||||
|
||||
/* Succeeded, save the handle and away we go */
|
||||
info->handle.ems_handle = ctx.dx;
|
||||
info->read_backing_store = read_ems_store;
|
||||
info->write_backing_store = write_ems_store;
|
||||
info->close_backing_store = close_ems_store;
|
||||
TRACEMS1(cinfo, 1, JTRC_EMS_OPEN, ctx.dx);
|
||||
return TRUE; /* succeeded */
|
||||
}
|
||||
|
||||
#endif /* EMS_SUPPORTED */
|
||||
|
||||
|
||||
/*
|
||||
* Initial opening of a backing-store object.
|
||||
*/
|
||||
|
||||
GLOBAL(void)
|
||||
jpeg_open_backing_store (j_common_ptr cinfo, backing_store_ptr info,
|
||||
long total_bytes_needed)
|
||||
{
|
||||
/* Try extended memory, then expanded memory, then regular file. */
|
||||
#if XMS_SUPPORTED
|
||||
if (open_xms_store(cinfo, info, total_bytes_needed))
|
||||
return;
|
||||
#endif
|
||||
#if EMS_SUPPORTED
|
||||
if (open_ems_store(cinfo, info, total_bytes_needed))
|
||||
return;
|
||||
#endif
|
||||
if (open_file_store(cinfo, info, total_bytes_needed))
|
||||
return;
|
||||
ERREXITS(cinfo, JERR_TFILE_CREATE, "");
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* These routines take care of any system-dependent initialization and
|
||||
* cleanup required.
|
||||
*/
|
||||
|
||||
GLOBAL(long)
|
||||
jpeg_mem_init (j_common_ptr cinfo)
|
||||
{
|
||||
next_file_num = 0; /* initialize temp file name generator */
|
||||
return DEFAULT_MAX_MEM; /* default for max_memory_to_use */
|
||||
}
|
||||
|
||||
GLOBAL(void)
|
||||
jpeg_mem_term (j_common_ptr cinfo)
|
||||
{
|
||||
/* 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
|
||||
}
|
||||
|
|
@ -1,289 +0,0 @@
|
|||
/*
|
||||
* jmemmac.c
|
||||
*
|
||||
* Copyright (C) 1992-1997, 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.
|
||||
*
|
||||
* jmemmac.c provides an Apple Macintosh implementation of the system-
|
||||
* dependent portion of the JPEG memory manager.
|
||||
*
|
||||
* If you use jmemmac.c, then you must define USE_MAC_MEMMGR in the
|
||||
* JPEG_INTERNALS part of jconfig.h.
|
||||
*
|
||||
* jmemmac.c uses the Macintosh toolbox routines NewPtr and DisposePtr
|
||||
* instead of malloc and free. It accurately determines the amount of
|
||||
* memory available by using CompactMem. Notice that if left to its
|
||||
* own devices, this code can chew up all available space in the
|
||||
* application's zone, with the exception of the rather small "slop"
|
||||
* factor computed in jpeg_mem_available(). The application can ensure
|
||||
* that more space is left over by reducing max_memory_to_use.
|
||||
*
|
||||
* Large images are swapped to disk using temporary files and System 7.0+'s
|
||||
* temporary folder functionality.
|
||||
*
|
||||
* Note that jmemmac.c depends on two features of MacOS that were first
|
||||
* introduced in System 7: FindFolder and the FSSpec-based calls.
|
||||
* If your application uses jmemmac.c and is run under System 6 or earlier,
|
||||
* and the jpeg library decides it needs a temporary file, it will abort,
|
||||
* printing error messages about requiring System 7. (If no temporary files
|
||||
* are created, it will run fine.)
|
||||
*
|
||||
* If you want to use jmemmac.c in an application that might be used with
|
||||
* System 6 or earlier, then you should remove dependencies on FindFolder
|
||||
* and the FSSpec calls. You will need to replace FindFolder with some
|
||||
* other mechanism for finding a place to put temporary files, and you
|
||||
* should replace the FSSpec calls with their HFS equivalents:
|
||||
*
|
||||
* FSpDelete -> HDelete
|
||||
* FSpGetFInfo -> HGetFInfo
|
||||
* FSpCreate -> HCreate
|
||||
* FSpOpenDF -> HOpen *** Note: not HOpenDF ***
|
||||
* FSMakeFSSpec -> (fill in spec by hand.)
|
||||
*
|
||||
* (Use HOpen instead of HOpenDF. HOpen is just a glue-interface to PBHOpen,
|
||||
* which is on all HFS macs. HOpenDF is a System 7 addition which avoids the
|
||||
* ages-old problem of names starting with a period.)
|
||||
*
|
||||
* Contributed by Sam Bushell (jsam@iagu.on.net) and
|
||||
* Dan Gildor (gyld@in-touch.com).
|
||||
*/
|
||||
|
||||
#define JPEG_INTERNALS
|
||||
#include "jinclude.h"
|
||||
#include "jpeglib.h"
|
||||
#include "jmemsys.h" /* import the system-dependent declarations */
|
||||
|
||||
#ifndef USE_MAC_MEMMGR /* make sure user got configuration right */
|
||||
You forgot to define USE_MAC_MEMMGR in jconfig.h. /* deliberate syntax error */
|
||||
#endif
|
||||
|
||||
#include <Memory.h> /* we use the MacOS memory manager */
|
||||
#include <Files.h> /* we use the MacOS File stuff */
|
||||
#include <Folders.h> /* we use the MacOS HFS stuff */
|
||||
#include <Script.h> /* for smSystemScript */
|
||||
#include <Gestalt.h> /* we use Gestalt to test for specific functionality */
|
||||
|
||||
#ifndef TEMP_FILE_NAME /* can override from jconfig.h or Makefile */
|
||||
#define TEMP_FILE_NAME "JPG%03d.TMP"
|
||||
#endif
|
||||
|
||||
static int next_file_num; /* to distinguish among several temp files */
|
||||
|
||||
|
||||
/*
|
||||
* Memory allocation and freeing are controlled by the MacOS library
|
||||
* routines NewPtr() and DisposePtr(), which allocate fixed-address
|
||||
* storage. Unfortunately, the IJG library isn't smart enough to cope
|
||||
* with relocatable storage.
|
||||
*/
|
||||
|
||||
GLOBAL(void *)
|
||||
jpeg_get_small (j_common_ptr cinfo, size_t sizeofobject)
|
||||
{
|
||||
return (void *) NewPtr(sizeofobject);
|
||||
}
|
||||
|
||||
GLOBAL(void)
|
||||
jpeg_free_small (j_common_ptr cinfo, void * object, size_t sizeofobject)
|
||||
{
|
||||
DisposePtr((Ptr) object);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* "Large" objects are treated the same as "small" ones.
|
||||
* NB: we include FAR keywords in the routine declarations simply for
|
||||
* consistency with the rest of the IJG code; FAR should expand to empty
|
||||
* on rational architectures like the Mac.
|
||||
*/
|
||||
|
||||
GLOBAL(void FAR *)
|
||||
jpeg_get_large (j_common_ptr cinfo, size_t sizeofobject)
|
||||
{
|
||||
return (void FAR *) NewPtr(sizeofobject);
|
||||
}
|
||||
|
||||
GLOBAL(void)
|
||||
jpeg_free_large (j_common_ptr cinfo, void FAR * object, size_t sizeofobject)
|
||||
{
|
||||
DisposePtr((Ptr) object);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* This routine computes the total memory space available for allocation.
|
||||
*/
|
||||
|
||||
GLOBAL(long)
|
||||
jpeg_mem_available (j_common_ptr cinfo, long min_bytes_needed,
|
||||
long max_bytes_needed, long already_allocated)
|
||||
{
|
||||
long limit = cinfo->mem->max_memory_to_use - already_allocated;
|
||||
long slop, mem;
|
||||
|
||||
/* Don't ask for more than what application has told us we may use */
|
||||
if (max_bytes_needed > limit && limit > 0)
|
||||
max_bytes_needed = limit;
|
||||
/* Find whether there's a big enough free block in the heap.
|
||||
* CompactMem tries to create a contiguous block of the requested size,
|
||||
* and then returns the size of the largest free block (which could be
|
||||
* much more or much less than we asked for).
|
||||
* We add some slop to ensure we don't use up all available memory.
|
||||
*/
|
||||
slop = max_bytes_needed / 16 + 32768L;
|
||||
mem = CompactMem(max_bytes_needed + slop) - slop;
|
||||
if (mem < 0)
|
||||
mem = 0; /* sigh, couldn't even get the slop */
|
||||
/* Don't take more than the application says we can have */
|
||||
if (mem > limit && limit > 0)
|
||||
mem = limit;
|
||||
return mem;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Backing store (temporary file) management.
|
||||
* Backing store objects are only used when the value returned by
|
||||
* jpeg_mem_available is less than the total space needed. You can dispense
|
||||
* with these routines if you have plenty of virtual memory; see jmemnobs.c.
|
||||
*/
|
||||
|
||||
|
||||
METHODDEF(void)
|
||||
read_backing_store (j_common_ptr cinfo, backing_store_ptr info,
|
||||
void FAR * buffer_address,
|
||||
long file_offset, long byte_count)
|
||||
{
|
||||
long bytes = byte_count;
|
||||
long retVal;
|
||||
|
||||
if ( SetFPos ( info->temp_file, fsFromStart, file_offset ) != noErr )
|
||||
ERREXIT(cinfo, JERR_TFILE_SEEK);
|
||||
|
||||
retVal = FSRead ( info->temp_file, &bytes,
|
||||
(unsigned char *) buffer_address );
|
||||
if ( retVal != noErr || bytes != byte_count )
|
||||
ERREXIT(cinfo, JERR_TFILE_READ);
|
||||
}
|
||||
|
||||
|
||||
METHODDEF(void)
|
||||
write_backing_store (j_common_ptr cinfo, backing_store_ptr info,
|
||||
void FAR * buffer_address,
|
||||
long file_offset, long byte_count)
|
||||
{
|
||||
long bytes = byte_count;
|
||||
long retVal;
|
||||
|
||||
if ( SetFPos ( info->temp_file, fsFromStart, file_offset ) != noErr )
|
||||
ERREXIT(cinfo, JERR_TFILE_SEEK);
|
||||
|
||||
retVal = FSWrite ( info->temp_file, &bytes,
|
||||
(unsigned char *) buffer_address );
|
||||
if ( retVal != noErr || bytes != byte_count )
|
||||
ERREXIT(cinfo, JERR_TFILE_WRITE);
|
||||
}
|
||||
|
||||
|
||||
METHODDEF(void)
|
||||
close_backing_store (j_common_ptr cinfo, backing_store_ptr info)
|
||||
{
|
||||
FSClose ( info->temp_file );
|
||||
FSpDelete ( &(info->tempSpec) );
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Initial opening of a backing-store object.
|
||||
*
|
||||
* This version uses FindFolder to find the Temporary Items folder,
|
||||
* and puts the temporary file in there.
|
||||
*/
|
||||
|
||||
GLOBAL(void)
|
||||
jpeg_open_backing_store (j_common_ptr cinfo, backing_store_ptr info,
|
||||
long total_bytes_needed)
|
||||
{
|
||||
short tmpRef, vRefNum;
|
||||
long dirID;
|
||||
FInfo finderInfo;
|
||||
FSSpec theSpec;
|
||||
Str255 fName;
|
||||
OSErr osErr;
|
||||
long gestaltResponse = 0;
|
||||
|
||||
/* Check that FSSpec calls are available. */
|
||||
osErr = Gestalt( gestaltFSAttr, &gestaltResponse );
|
||||
if ( ( osErr != noErr )
|
||||
|| !( gestaltResponse & (1<<gestaltHasFSSpecCalls) ) )
|
||||
ERREXITS(cinfo, JERR_TFILE_CREATE, "- System 7.0 or later required");
|
||||
/* TO DO: add a proper error message to jerror.h. */
|
||||
|
||||
/* Check that FindFolder is available. */
|
||||
osErr = Gestalt( gestaltFindFolderAttr, &gestaltResponse );
|
||||
if ( ( osErr != noErr )
|
||||
|| !( gestaltResponse & (1<<gestaltFindFolderPresent) ) )
|
||||
ERREXITS(cinfo, JERR_TFILE_CREATE, "- System 7.0 or later required.");
|
||||
/* TO DO: add a proper error message to jerror.h. */
|
||||
|
||||
osErr = FindFolder ( kOnSystemDisk, kTemporaryFolderType, kCreateFolder,
|
||||
&vRefNum, &dirID );
|
||||
if ( osErr != noErr )
|
||||
ERREXITS(cinfo, JERR_TFILE_CREATE, "- temporary items folder unavailable");
|
||||
/* TO DO: Try putting the temp files somewhere else. */
|
||||
|
||||
/* Keep generating file names till we find one that's not in use */
|
||||
for (;;) {
|
||||
next_file_num++; /* advance counter */
|
||||
|
||||
sprintf(info->temp_name, TEMP_FILE_NAME, next_file_num);
|
||||
strcpy ( (Ptr)fName+1, info->temp_name );
|
||||
*fName = strlen (info->temp_name);
|
||||
osErr = FSMakeFSSpec ( vRefNum, dirID, fName, &theSpec );
|
||||
|
||||
if ( (osErr = FSpGetFInfo ( &theSpec, &finderInfo ) ) != noErr )
|
||||
break;
|
||||
}
|
||||
|
||||
osErr = FSpCreate ( &theSpec, '????', '????', smSystemScript );
|
||||
if ( osErr != noErr )
|
||||
ERREXITS(cinfo, JERR_TFILE_CREATE, info->temp_name);
|
||||
|
||||
osErr = FSpOpenDF ( &theSpec, fsRdWrPerm, &(info->temp_file) );
|
||||
if ( osErr != noErr )
|
||||
ERREXITS(cinfo, JERR_TFILE_CREATE, info->temp_name);
|
||||
|
||||
info->tempSpec = theSpec;
|
||||
|
||||
info->read_backing_store = read_backing_store;
|
||||
info->write_backing_store = write_backing_store;
|
||||
info->close_backing_store = close_backing_store;
|
||||
TRACEMSS(cinfo, 1, JTRC_TFILE_OPEN, info->temp_name);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* These routines take care of any system-dependent initialization and
|
||||
* cleanup required.
|
||||
*/
|
||||
|
||||
GLOBAL(long)
|
||||
jpeg_mem_init (j_common_ptr cinfo)
|
||||
{
|
||||
next_file_num = 0;
|
||||
|
||||
/* max_memory_to_use will be initialized to FreeMem()'s result;
|
||||
* the calling application might later reduce it, for example
|
||||
* to leave room to invoke multiple JPEG objects.
|
||||
* Note that FreeMem returns the total number of free bytes;
|
||||
* it may not be possible to allocate a single block of this size.
|
||||
*/
|
||||
return FreeMem();
|
||||
}
|
||||
|
||||
GLOBAL(void)
|
||||
jpeg_mem_term (j_common_ptr cinfo)
|
||||
{
|
||||
/* no work */
|
||||
}
|
||||
|
|
@ -1,276 +0,0 @@
|
|||
/*
|
||||
* jmemname.c
|
||||
*
|
||||
* Copyright (C) 1992-1997, 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.
|
||||
*
|
||||
* This file provides a generic implementation of the system-dependent
|
||||
* portion of the JPEG memory manager. This implementation assumes that
|
||||
* you must explicitly construct a name for each temp file.
|
||||
* Also, the problem of determining the amount of memory available
|
||||
* is shoved onto the user.
|
||||
*/
|
||||
|
||||
#define JPEG_INTERNALS
|
||||
#include "jinclude.h"
|
||||
#include "jpeglib.h"
|
||||
#include "jmemsys.h" /* import the system-dependent declarations */
|
||||
|
||||
#ifndef HAVE_STDLIB_H /* <stdlib.h> should declare malloc(),free() */
|
||||
extern void * malloc JPP((size_t size));
|
||||
extern void free JPP((void *ptr));
|
||||
#endif
|
||||
|
||||
#ifndef SEEK_SET /* pre-ANSI systems may not define this; */
|
||||
#define SEEK_SET 0 /* if not, assume 0 is correct */
|
||||
#endif
|
||||
|
||||
#ifdef DONT_USE_B_MODE /* define mode parameters for fopen() */
|
||||
#define READ_BINARY "r"
|
||||
#define RW_BINARY "w+"
|
||||
#else
|
||||
#ifdef VMS /* VMS is very nonstandard */
|
||||
#define READ_BINARY "rb", "ctx=stm"
|
||||
#define RW_BINARY "w+b", "ctx=stm"
|
||||
#else /* standard ANSI-compliant case */
|
||||
#define READ_BINARY "rb"
|
||||
#define RW_BINARY "w+b"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* Selection of a file name for a temporary file.
|
||||
* This is system-dependent!
|
||||
*
|
||||
* The code as given is suitable for most Unix systems, and it is easily
|
||||
* modified for most non-Unix systems. Some notes:
|
||||
* 1. The temp file is created in the directory named by TEMP_DIRECTORY.
|
||||
* The default value is /usr/tmp, which is the conventional place for
|
||||
* creating large temp files on Unix. On other systems you'll probably
|
||||
* want to change the file location. You can do this by editing the
|
||||
* #define, or (preferred) by defining TEMP_DIRECTORY in jconfig.h.
|
||||
*
|
||||
* 2. If you need to change the file name as well as its location,
|
||||
* you can override the TEMP_FILE_NAME macro. (Note that this is
|
||||
* actually a printf format string; it must contain %s and %d.)
|
||||
* Few people should need to do this.
|
||||
*
|
||||
* 3. mktemp() is used to ensure that multiple processes running
|
||||
* simultaneously won't select the same file names. If your system
|
||||
* doesn't have mktemp(), define NO_MKTEMP to do it the hard way.
|
||||
* (If you don't have <errno.h>, also define NO_ERRNO_H.)
|
||||
*
|
||||
* 4. You probably want to define NEED_SIGNAL_CATCHER so that cjpeg.c/djpeg.c
|
||||
* will cause the temp files to be removed if you stop the program early.
|
||||
*/
|
||||
|
||||
#ifndef TEMP_DIRECTORY /* can override from jconfig.h or Makefile */
|
||||
#define TEMP_DIRECTORY "/usr/tmp/" /* recommended setting for Unix */
|
||||
#endif
|
||||
|
||||
static int next_file_num; /* to distinguish among several temp files */
|
||||
|
||||
#ifdef NO_MKTEMP
|
||||
|
||||
#ifndef TEMP_FILE_NAME /* can override from jconfig.h or Makefile */
|
||||
#define TEMP_FILE_NAME "%sJPG%03d.TMP"
|
||||
#endif
|
||||
|
||||
#ifndef NO_ERRNO_H
|
||||
#include <errno.h> /* to define ENOENT */
|
||||
#endif
|
||||
|
||||
/* ANSI C specifies that errno is a macro, but on older systems it's more
|
||||
* likely to be a plain int variable. And not all versions of errno.h
|
||||
* bother to declare it, so we have to in order to be most portable. Thus:
|
||||
*/
|
||||
#ifndef errno
|
||||
extern int errno;
|
||||
#endif
|
||||
|
||||
|
||||
LOCAL(void)
|
||||
select_file_name (char * fname)
|
||||
{
|
||||
FILE * tfile;
|
||||
|
||||
/* Keep generating file names till we find one that's not in use */
|
||||
for (;;) {
|
||||
next_file_num++; /* advance counter */
|
||||
sprintf(fname, TEMP_FILE_NAME, TEMP_DIRECTORY, next_file_num);
|
||||
if ((tfile = fopen(fname, READ_BINARY)) == NULL) {
|
||||
/* fopen could have failed for a reason other than the file not
|
||||
* being there; for example, file there but unreadable.
|
||||
* If <errno.h> isn't available, then we cannot test the cause.
|
||||
*/
|
||||
#ifdef ENOENT
|
||||
if (errno != ENOENT)
|
||||
continue;
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
fclose(tfile); /* oops, it's there; close tfile & try again */
|
||||
}
|
||||
}
|
||||
|
||||
#else /* ! NO_MKTEMP */
|
||||
|
||||
/* Note that mktemp() requires the initial filename to end in six X's */
|
||||
#ifndef TEMP_FILE_NAME /* can override from jconfig.h or Makefile */
|
||||
#define TEMP_FILE_NAME "%sJPG%dXXXXXX"
|
||||
#endif
|
||||
|
||||
LOCAL(void)
|
||||
select_file_name (char * fname)
|
||||
{
|
||||
next_file_num++; /* advance counter */
|
||||
sprintf(fname, TEMP_FILE_NAME, TEMP_DIRECTORY, next_file_num);
|
||||
mktemp(fname); /* make sure file name is unique */
|
||||
/* mktemp replaces the trailing XXXXXX with a unique string of characters */
|
||||
}
|
||||
|
||||
#endif /* NO_MKTEMP */
|
||||
|
||||
|
||||
/*
|
||||
* Memory allocation and freeing are controlled by the regular library
|
||||
* routines malloc() and free().
|
||||
*/
|
||||
|
||||
GLOBAL(void *)
|
||||
jpeg_get_small (j_common_ptr cinfo, size_t sizeofobject)
|
||||
{
|
||||
return (void *) malloc(sizeofobject);
|
||||
}
|
||||
|
||||
GLOBAL(void)
|
||||
jpeg_free_small (j_common_ptr cinfo, void * object, size_t sizeofobject)
|
||||
{
|
||||
free(object);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* "Large" objects are treated the same as "small" ones.
|
||||
* NB: although we include FAR keywords in the routine declarations,
|
||||
* this file won't actually work in 80x86 small/medium model; at least,
|
||||
* you probably won't be able to process useful-size images in only 64KB.
|
||||
*/
|
||||
|
||||
GLOBAL(void FAR *)
|
||||
jpeg_get_large (j_common_ptr cinfo, size_t sizeofobject)
|
||||
{
|
||||
return (void FAR *) malloc(sizeofobject);
|
||||
}
|
||||
|
||||
GLOBAL(void)
|
||||
jpeg_free_large (j_common_ptr cinfo, void FAR * object, size_t sizeofobject)
|
||||
{
|
||||
free(object);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* This routine computes the total memory space available for allocation.
|
||||
* It's impossible to do this in a portable way; our current solution is
|
||||
* to make the user tell us (with a default value set at compile time).
|
||||
* If you can actually get the available space, it's a good idea to subtract
|
||||
* a slop factor of 5% or so.
|
||||
*/
|
||||
|
||||
#ifndef DEFAULT_MAX_MEM /* so can override from makefile */
|
||||
#define DEFAULT_MAX_MEM 1000000L /* default: one megabyte */
|
||||
#endif
|
||||
|
||||
GLOBAL(long)
|
||||
jpeg_mem_available (j_common_ptr cinfo, long min_bytes_needed,
|
||||
long max_bytes_needed, long already_allocated)
|
||||
{
|
||||
return cinfo->mem->max_memory_to_use - already_allocated;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Backing store (temporary file) management.
|
||||
* Backing store objects are only used when the value returned by
|
||||
* jpeg_mem_available is less than the total space needed. You can dispense
|
||||
* with these routines if you have plenty of virtual memory; see jmemnobs.c.
|
||||
*/
|
||||
|
||||
|
||||
METHODDEF(void)
|
||||
read_backing_store (j_common_ptr cinfo, backing_store_ptr info,
|
||||
void FAR * buffer_address,
|
||||
long file_offset, long byte_count)
|
||||
{
|
||||
if (fseek(info->temp_file, file_offset, SEEK_SET))
|
||||
ERREXIT(cinfo, JERR_TFILE_SEEK);
|
||||
if (JFREAD(info->temp_file, buffer_address, byte_count)
|
||||
!= (size_t) byte_count)
|
||||
ERREXIT(cinfo, JERR_TFILE_READ);
|
||||
}
|
||||
|
||||
|
||||
METHODDEF(void)
|
||||
write_backing_store (j_common_ptr cinfo, backing_store_ptr info,
|
||||
void FAR * buffer_address,
|
||||
long file_offset, long byte_count)
|
||||
{
|
||||
if (fseek(info->temp_file, file_offset, SEEK_SET))
|
||||
ERREXIT(cinfo, JERR_TFILE_SEEK);
|
||||
if (JFWRITE(info->temp_file, buffer_address, byte_count)
|
||||
!= (size_t) byte_count)
|
||||
ERREXIT(cinfo, JERR_TFILE_WRITE);
|
||||
}
|
||||
|
||||
|
||||
METHODDEF(void)
|
||||
close_backing_store (j_common_ptr cinfo, backing_store_ptr info)
|
||||
{
|
||||
fclose(info->temp_file); /* close the file */
|
||||
unlink(info->temp_name); /* delete the file */
|
||||
/* If your system doesn't have unlink(), use remove() instead.
|
||||
* remove() is the ANSI-standard name for this function, but if
|
||||
* your system was ANSI you'd be using jmemansi.c, right?
|
||||
*/
|
||||
TRACEMSS(cinfo, 1, JTRC_TFILE_CLOSE, info->temp_name);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Initial opening of a backing-store object.
|
||||
*/
|
||||
|
||||
GLOBAL(void)
|
||||
jpeg_open_backing_store (j_common_ptr cinfo, backing_store_ptr info,
|
||||
long total_bytes_needed)
|
||||
{
|
||||
select_file_name(info->temp_name);
|
||||
if ((info->temp_file = fopen(info->temp_name, RW_BINARY)) == NULL)
|
||||
ERREXITS(cinfo, JERR_TFILE_CREATE, info->temp_name);
|
||||
info->read_backing_store = read_backing_store;
|
||||
info->write_backing_store = write_backing_store;
|
||||
info->close_backing_store = close_backing_store;
|
||||
TRACEMSS(cinfo, 1, JTRC_TFILE_OPEN, info->temp_name);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* These routines take care of any system-dependent initialization and
|
||||
* cleanup required.
|
||||
*/
|
||||
|
||||
GLOBAL(long)
|
||||
jpeg_mem_init (j_common_ptr cinfo)
|
||||
{
|
||||
next_file_num = 0; /* initialize temp file name generator */
|
||||
return DEFAULT_MAX_MEM; /* default for max_memory_to_use */
|
||||
}
|
||||
|
||||
GLOBAL(void)
|
||||
jpeg_mem_term (j_common_ptr cinfo)
|
||||
{
|
||||
/* no work */
|
||||
}
|
||||
|
|
@ -1,113 +0,0 @@
|
|||
/*
|
||||
* jmemnobs.c
|
||||
*
|
||||
* Copyright (C) 1992-1996, Thomas G. Lane.
|
||||
* Modified 2019 by Guido Vollbeding.
|
||||
* This file is part of the Independent JPEG Group's software.
|
||||
* For conditions of distribution and use, see the accompanying README file.
|
||||
*
|
||||
* This file provides a really simple implementation of the system-
|
||||
* dependent portion of the JPEG memory manager. This implementation
|
||||
* assumes that no backing-store files are needed: all required space
|
||||
* can be obtained from malloc().
|
||||
* This is very portable in the sense that it'll compile on almost anything,
|
||||
* but you'd better have lots of main memory (or virtual memory) if you want
|
||||
* to process big images.
|
||||
* Note that the max_memory_to_use option is respected by this implementation.
|
||||
*/
|
||||
|
||||
#define JPEG_INTERNALS
|
||||
#include "jinclude.h"
|
||||
#include "jpeglib.h"
|
||||
#include "jmemsys.h" /* import the system-dependent declarations */
|
||||
|
||||
#ifndef HAVE_STDLIB_H /* <stdlib.h> should declare malloc(),free() */
|
||||
extern void * malloc JPP((size_t size));
|
||||
extern void free JPP((void *ptr));
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* Memory allocation and freeing are controlled by the regular library
|
||||
* routines malloc() and free().
|
||||
*/
|
||||
|
||||
GLOBAL(void *)
|
||||
jpeg_get_small (j_common_ptr cinfo, size_t sizeofobject)
|
||||
{
|
||||
return (void *) malloc(sizeofobject);
|
||||
}
|
||||
|
||||
GLOBAL(void)
|
||||
jpeg_free_small (j_common_ptr cinfo, void * object, size_t sizeofobject)
|
||||
{
|
||||
free(object);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* "Large" objects are treated the same as "small" ones.
|
||||
* NB: although we include FAR keywords in the routine declarations,
|
||||
* this file won't actually work in 80x86 small/medium model; at least,
|
||||
* you probably won't be able to process useful-size images in only 64KB.
|
||||
*/
|
||||
|
||||
GLOBAL(void FAR *)
|
||||
jpeg_get_large (j_common_ptr cinfo, size_t sizeofobject)
|
||||
{
|
||||
return (void FAR *) malloc(sizeofobject);
|
||||
}
|
||||
|
||||
GLOBAL(void)
|
||||
jpeg_free_large (j_common_ptr cinfo, void FAR * object, size_t sizeofobject)
|
||||
{
|
||||
free(object);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* This routine computes the total memory space available for allocation.
|
||||
*/
|
||||
|
||||
GLOBAL(long)
|
||||
jpeg_mem_available (j_common_ptr cinfo, long min_bytes_needed,
|
||||
long max_bytes_needed, long already_allocated)
|
||||
{
|
||||
if (cinfo->mem->max_memory_to_use)
|
||||
return cinfo->mem->max_memory_to_use - already_allocated;
|
||||
|
||||
/* Here we say, "we got all you want bud!" */
|
||||
return max_bytes_needed;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Backing store (temporary file) management.
|
||||
* Since jpeg_mem_available always promised the moon,
|
||||
* this should never be called and we can just error out.
|
||||
*/
|
||||
|
||||
GLOBAL(void)
|
||||
jpeg_open_backing_store (j_common_ptr cinfo, backing_store_ptr info,
|
||||
long total_bytes_needed)
|
||||
{
|
||||
ERREXIT(cinfo, JERR_NO_BACKING_STORE);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* These routines take care of any system-dependent initialization and
|
||||
* cleanup required. Here, there isn't any.
|
||||
*/
|
||||
|
||||
GLOBAL(long)
|
||||
jpeg_mem_init (j_common_ptr cinfo)
|
||||
{
|
||||
return 0; /* just set max_memory_to_use to 0 */
|
||||
}
|
||||
|
||||
GLOBAL(void)
|
||||
jpeg_mem_term (j_common_ptr cinfo)
|
||||
{
|
||||
/* no work */
|
||||
}
|
||||
|
|
@ -2,7 +2,7 @@
|
|||
* jmorecfg.h
|
||||
*
|
||||
* Copyright (C) 1991-1997, Thomas G. Lane.
|
||||
* Modified 1997-2013 by Guido Vollbeding.
|
||||
* Modified 1997-2022 by Guido Vollbeding.
|
||||
* This file is part of the Independent JPEG Group's software.
|
||||
* For conditions of distribution and use, see the accompanying README file.
|
||||
*
|
||||
|
|
@ -351,8 +351,8 @@ typedef enum { FALSE = 0, TRUE = 1 } boolean;
|
|||
|
||||
#define C_ARITH_CODING_SUPPORTED /* Arithmetic coding back end? */
|
||||
#define C_MULTISCAN_FILES_SUPPORTED /* Multiple-scan JPEG files? */
|
||||
#define C_PROGRESSIVE_SUPPORTED /* Progressive JPEG? (Requires MULTISCAN)*/
|
||||
#define DCT_SCALING_SUPPORTED /* Input rescaling via DCT? (Requires DCT_ISLOW)*/
|
||||
#define C_PROGRESSIVE_SUPPORTED /* Progressive JPEG? (Requires MULTISCAN) */
|
||||
#define DCT_SCALING_SUPPORTED /* Input rescaling via DCT? (Requires DCT_ISLOW) */
|
||||
#define ENTROPY_OPT_SUPPORTED /* Optimization of entropy coding parms? */
|
||||
/* Note: if you selected more than 8-bit data precision, it is dangerous to
|
||||
* turn off ENTROPY_OPT_SUPPORTED. The standard Huffman tables are only
|
||||
|
|
@ -369,8 +369,8 @@ typedef enum { FALSE = 0, TRUE = 1 } boolean;
|
|||
|
||||
#define D_ARITH_CODING_SUPPORTED /* Arithmetic coding back end? */
|
||||
#define D_MULTISCAN_FILES_SUPPORTED /* Multiple-scan JPEG files? */
|
||||
#define D_PROGRESSIVE_SUPPORTED /* Progressive JPEG? (Requires MULTISCAN)*/
|
||||
#define IDCT_SCALING_SUPPORTED /* Output rescaling via IDCT? (Requires DCT_ISLOW)*/
|
||||
#define D_PROGRESSIVE_SUPPORTED /* Progressive JPEG? (Requires MULTISCAN) */
|
||||
#define IDCT_SCALING_SUPPORTED /* Output rescaling via IDCT? (Requires DCT_ISLOW) */
|
||||
#define SAVE_MARKERS_SUPPORTED /* jpeg_save_markers() needed? */
|
||||
#define BLOCK_SMOOTHING_SUPPORTED /* Block smoothing? (Progressive only) */
|
||||
#undef UPSAMPLE_SCALING_SUPPORTED /* Output rescaling at upsample stage? */
|
||||
|
|
@ -384,20 +384,31 @@ typedef enum { FALSE = 0, TRUE = 1 } boolean;
|
|||
/*
|
||||
* Ordering of RGB data in scanlines passed to or from the application.
|
||||
* If your application wants to deal with data in the order B,G,R, just
|
||||
* change these macros. You can also deal with formats such as R,G,B,X
|
||||
* (one extra byte per pixel) by changing RGB_PIXELSIZE. Note that changing
|
||||
* the offsets will also change the order in which colormap data is organized.
|
||||
* #define JPEG_USE_RGB_CUSTOM in jconfig.h, or define your own custom
|
||||
* order in jconfig.h and #define JPEG_HAVE_RGB_CUSTOM.
|
||||
* You can also deal with formats such as R,G,B,X (one extra byte per pixel)
|
||||
* by changing RGB_PIXELSIZE.
|
||||
* Note that changing the offsets will also change
|
||||
* the order in which colormap data is organized.
|
||||
* RESTRICTIONS:
|
||||
* 1. The sample applications cjpeg,djpeg do NOT support modified RGB formats.
|
||||
* 2. The color quantizer modules will not behave desirably if RGB_PIXELSIZE
|
||||
* is not 3 (they don't understand about dummy color components!). So you
|
||||
* can't use color quantization if you change that value.
|
||||
* is not 3 (they don't understand about dummy color components!).
|
||||
* So you can't use color quantization if you change that value.
|
||||
*/
|
||||
|
||||
#ifndef JPEG_HAVE_RGB_CUSTOM
|
||||
#ifdef JPEG_USE_RGB_CUSTOM
|
||||
#define RGB_RED 2 /* Offset of Red in an RGB scanline element */
|
||||
#define RGB_GREEN 1 /* Offset of Green */
|
||||
#define RGB_BLUE 0 /* Offset of Blue */
|
||||
#else
|
||||
#define RGB_RED 0 /* Offset of Red in an RGB scanline element */
|
||||
#define RGB_GREEN 1 /* Offset of Green */
|
||||
#define RGB_BLUE 2 /* Offset of Blue */
|
||||
#endif
|
||||
#define RGB_PIXELSIZE 3 /* JSAMPLEs per RGB scanline element */
|
||||
#endif
|
||||
|
||||
|
||||
/* Definitions for speed-related optimizations. */
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
* jpeglib.h
|
||||
*
|
||||
* Copyright (C) 1991-1998, Thomas G. Lane.
|
||||
* Modified 2002-2020 by Guido Vollbeding.
|
||||
* Modified 2002-2022 by Guido Vollbeding.
|
||||
* This file is part of the Independent JPEG Group's software.
|
||||
* For conditions of distribution and use, see the accompanying README file.
|
||||
*
|
||||
|
|
@ -39,7 +39,7 @@ extern "C" {
|
|||
|
||||
#define JPEG_LIB_VERSION 90 /* Compatibility version 9.0 */
|
||||
#define JPEG_LIB_VERSION_MAJOR 9
|
||||
#define JPEG_LIB_VERSION_MINOR 5
|
||||
#define JPEG_LIB_VERSION_MINOR 6
|
||||
|
||||
|
||||
/* Various constants determining the sizes of things.
|
||||
|
|
|
|||
|
|
@ -1,654 +0,0 @@
|
|||
/*
|
||||
* jpegtran.c
|
||||
*
|
||||
* Copyright (C) 1995-2019, Thomas G. Lane, Guido Vollbeding.
|
||||
* This file is part of the Independent JPEG Group's software.
|
||||
* For conditions of distribution and use, see the accompanying README file.
|
||||
*
|
||||
* This file contains a command-line user interface for JPEG transcoding.
|
||||
* It is very similar to cjpeg.c, and partly to djpeg.c, but provides
|
||||
* lossless transcoding between different JPEG file formats. It also
|
||||
* provides some lossless and sort-of-lossless transformations of JPEG data.
|
||||
*/
|
||||
|
||||
#include "cdjpeg.h" /* Common decls for cjpeg/djpeg applications */
|
||||
#include "transupp.h" /* Support routines for jpegtran */
|
||||
#include "jversion.h" /* for version message */
|
||||
|
||||
#ifdef USE_CCOMMAND /* command-line reader for Macintosh */
|
||||
#ifdef __MWERKS__
|
||||
#include <SIOUX.h> /* Metrowerks needs this */
|
||||
#include <console.h> /* ... and this */
|
||||
#endif
|
||||
#ifdef THINK_C
|
||||
#include <console.h> /* Think declares it here */
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* Argument-parsing code.
|
||||
* The switch parser is designed to be useful with DOS-style command line
|
||||
* syntax, ie, intermixed switches and file names, where only the switches
|
||||
* to the left of a given file name affect processing of that file.
|
||||
* The main program in this file doesn't actually use this capability...
|
||||
*/
|
||||
|
||||
|
||||
static const char * progname; /* program name for error messages */
|
||||
static char * outfilename; /* for -outfile switch */
|
||||
static char * dropfilename; /* for -drop switch */
|
||||
static char * scaleoption; /* -scale switch */
|
||||
static JCOPY_OPTION copyoption; /* -copy switch */
|
||||
static jpeg_transform_info transformoption; /* image transformation options */
|
||||
|
||||
|
||||
LOCAL(void)
|
||||
usage (void)
|
||||
/* complain about bad command line */
|
||||
{
|
||||
fprintf(stderr, "usage: %s [switches] ", progname);
|
||||
#ifdef TWO_FILE_COMMANDLINE
|
||||
fprintf(stderr, "inputfile outputfile\n");
|
||||
#else
|
||||
fprintf(stderr, "[inputfile]\n");
|
||||
#endif
|
||||
|
||||
fprintf(stderr, "Switches (names may be abbreviated):\n");
|
||||
fprintf(stderr, " -copy none Copy no extra markers from source file\n");
|
||||
fprintf(stderr, " -copy comments Copy only comment markers (default)\n");
|
||||
fprintf(stderr, " -copy all Copy all extra markers\n");
|
||||
#ifdef ENTROPY_OPT_SUPPORTED
|
||||
fprintf(stderr, " -optimize Optimize Huffman table (smaller file, but slow compression)\n");
|
||||
#endif
|
||||
#ifdef C_PROGRESSIVE_SUPPORTED
|
||||
fprintf(stderr, " -progressive Create progressive JPEG file\n");
|
||||
#endif
|
||||
fprintf(stderr, "Switches for modifying the image:\n");
|
||||
#if TRANSFORMS_SUPPORTED
|
||||
fprintf(stderr, " -crop WxH+X+Y Crop to a rectangular subarea\n");
|
||||
fprintf(stderr, " -drop +X+Y filename Drop another image\n");
|
||||
fprintf(stderr, " -flip [horizontal|vertical] Mirror image (left-right or top-bottom)\n");
|
||||
fprintf(stderr, " -grayscale Reduce to grayscale (omit color data)\n");
|
||||
fprintf(stderr, " -perfect Fail if there is non-transformable edge blocks\n");
|
||||
fprintf(stderr, " -rotate [90|180|270] Rotate image (degrees clockwise)\n");
|
||||
#endif
|
||||
fprintf(stderr, " -scale M/N Scale output image by fraction M/N, eg, 1/8\n");
|
||||
#if TRANSFORMS_SUPPORTED
|
||||
fprintf(stderr, " -transpose Transpose image\n");
|
||||
fprintf(stderr, " -transverse Transverse transpose image\n");
|
||||
fprintf(stderr, " -trim Drop non-transformable edge blocks\n");
|
||||
fprintf(stderr, " with -drop: Requantize drop file to source file\n");
|
||||
fprintf(stderr, " -wipe WxH+X+Y Wipe (gray out) a rectangular subarea\n");
|
||||
#endif
|
||||
fprintf(stderr, "Switches for advanced users:\n");
|
||||
#ifdef C_ARITH_CODING_SUPPORTED
|
||||
fprintf(stderr, " -arithmetic Use arithmetic coding\n");
|
||||
#endif
|
||||
fprintf(stderr, " -restart N Set restart interval in rows, or in blocks with B\n");
|
||||
fprintf(stderr, " -maxmemory N Maximum memory to use (in kbytes)\n");
|
||||
fprintf(stderr, " -outfile name Specify name for output file\n");
|
||||
fprintf(stderr, " -verbose or -debug Emit debug output\n");
|
||||
fprintf(stderr, "Switches for wizards:\n");
|
||||
#ifdef C_MULTISCAN_FILES_SUPPORTED
|
||||
fprintf(stderr, " -scans file Create multi-scan JPEG per script file\n");
|
||||
#endif
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
|
||||
LOCAL(void)
|
||||
select_transform (JXFORM_CODE transform)
|
||||
/* Silly little routine to detect multiple transform options,
|
||||
* which we can't handle.
|
||||
*/
|
||||
{
|
||||
#if TRANSFORMS_SUPPORTED
|
||||
if (transformoption.transform == JXFORM_NONE ||
|
||||
transformoption.transform == transform) {
|
||||
transformoption.transform = transform;
|
||||
} else {
|
||||
fprintf(stderr, "%s: can only do one image transformation at a time\n",
|
||||
progname);
|
||||
usage();
|
||||
}
|
||||
#else
|
||||
fprintf(stderr, "%s: sorry, image transformation was not compiled\n",
|
||||
progname);
|
||||
exit(EXIT_FAILURE);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
LOCAL(int)
|
||||
parse_switches (j_compress_ptr cinfo, int argc, char **argv,
|
||||
int last_file_arg_seen, boolean for_real)
|
||||
/* Parse optional switches.
|
||||
* Returns argv[] index of first file-name argument (== argc if none).
|
||||
* Any file names with indexes <= last_file_arg_seen are ignored;
|
||||
* they have presumably been processed in a previous iteration.
|
||||
* (Pass 0 for last_file_arg_seen on the first or only iteration.)
|
||||
* for_real is FALSE on the first (dummy) pass; we may skip any expensive
|
||||
* processing.
|
||||
*/
|
||||
{
|
||||
int argn;
|
||||
char * arg;
|
||||
boolean simple_progressive;
|
||||
char * scansarg = NULL; /* saves -scans parm if any */
|
||||
|
||||
/* Set up default JPEG parameters. */
|
||||
simple_progressive = FALSE;
|
||||
outfilename = NULL;
|
||||
scaleoption = NULL;
|
||||
copyoption = JCOPYOPT_DEFAULT;
|
||||
transformoption.transform = JXFORM_NONE;
|
||||
transformoption.perfect = FALSE;
|
||||
transformoption.trim = FALSE;
|
||||
transformoption.force_grayscale = FALSE;
|
||||
transformoption.crop = FALSE;
|
||||
cinfo->err->trace_level = 0;
|
||||
|
||||
/* Scan command line options, adjust parameters */
|
||||
|
||||
for (argn = 1; argn < argc; argn++) {
|
||||
arg = argv[argn];
|
||||
if (*arg != '-') {
|
||||
/* Not a switch, must be a file name argument */
|
||||
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 */
|
||||
|
||||
if (keymatch(arg, "arithmetic", 1)) {
|
||||
/* Use arithmetic coding. */
|
||||
#ifdef C_ARITH_CODING_SUPPORTED
|
||||
cinfo->arith_code = TRUE;
|
||||
#else
|
||||
fprintf(stderr, "%s: sorry, arithmetic coding not supported\n",
|
||||
progname);
|
||||
exit(EXIT_FAILURE);
|
||||
#endif
|
||||
|
||||
} else if (keymatch(arg, "copy", 2)) {
|
||||
/* Select which extra markers to copy. */
|
||||
if (++argn >= argc) /* advance to next argument */
|
||||
usage();
|
||||
if (keymatch(argv[argn], "none", 1)) {
|
||||
copyoption = JCOPYOPT_NONE;
|
||||
} else if (keymatch(argv[argn], "comments", 1)) {
|
||||
copyoption = JCOPYOPT_COMMENTS;
|
||||
} else if (keymatch(argv[argn], "all", 1)) {
|
||||
copyoption = JCOPYOPT_ALL;
|
||||
} else
|
||||
usage();
|
||||
|
||||
} else if (keymatch(arg, "crop", 2)) {
|
||||
/* Perform lossless cropping. */
|
||||
#if TRANSFORMS_SUPPORTED
|
||||
if (++argn >= argc) /* advance to next argument */
|
||||
usage();
|
||||
if (transformoption.crop /* reject multiple crop/drop/wipe requests */ ||
|
||||
! jtransform_parse_crop_spec(&transformoption, argv[argn])) {
|
||||
fprintf(stderr, "%s: bogus -crop argument '%s'\n",
|
||||
progname, argv[argn]);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
#else
|
||||
select_transform(JXFORM_NONE); /* force an error */
|
||||
#endif
|
||||
|
||||
} else if (keymatch(arg, "drop", 2)) {
|
||||
#if TRANSFORMS_SUPPORTED
|
||||
if (++argn >= argc) /* advance to next argument */
|
||||
usage();
|
||||
if (transformoption.crop /* reject multiple crop/drop/wipe requests */ ||
|
||||
! jtransform_parse_crop_spec(&transformoption, argv[argn]) ||
|
||||
transformoption.crop_width_set != JCROP_UNSET ||
|
||||
transformoption.crop_height_set != JCROP_UNSET) {
|
||||
fprintf(stderr, "%s: bogus -drop argument '%s'\n",
|
||||
progname, argv[argn]);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
if (++argn >= argc) /* advance to next argument */
|
||||
usage();
|
||||
dropfilename = argv[argn];
|
||||
select_transform(JXFORM_DROP);
|
||||
#else
|
||||
select_transform(JXFORM_NONE); /* force an error */
|
||||
#endif
|
||||
|
||||
} else if (keymatch(arg, "debug", 1) || keymatch(arg, "verbose", 1)) {
|
||||
/* Enable debug printouts. */
|
||||
/* On first -d, print version identification */
|
||||
static boolean printed_version = FALSE;
|
||||
|
||||
if (! printed_version) {
|
||||
fprintf(stderr, "Independent JPEG Group's JPEGTRAN, version %s\n%s\n",
|
||||
JVERSION, JCOPYRIGHT);
|
||||
printed_version = TRUE;
|
||||
}
|
||||
cinfo->err->trace_level++;
|
||||
|
||||
} else if (keymatch(arg, "flip", 1)) {
|
||||
/* Mirror left-right or top-bottom. */
|
||||
if (++argn >= argc) /* advance to next argument */
|
||||
usage();
|
||||
if (keymatch(argv[argn], "horizontal", 1))
|
||||
select_transform(JXFORM_FLIP_H);
|
||||
else if (keymatch(argv[argn], "vertical", 1))
|
||||
select_transform(JXFORM_FLIP_V);
|
||||
else
|
||||
usage();
|
||||
|
||||
} else if (keymatch(arg, "grayscale", 1) || keymatch(arg, "greyscale",1)) {
|
||||
/* Force to grayscale. */
|
||||
#if TRANSFORMS_SUPPORTED
|
||||
transformoption.force_grayscale = TRUE;
|
||||
#else
|
||||
select_transform(JXFORM_NONE); /* force an error */
|
||||
#endif
|
||||
|
||||
} else if (keymatch(arg, "maxmemory", 3)) {
|
||||
/* Maximum memory in Kb (or Mb with 'm'). */
|
||||
long lval;
|
||||
char ch = 'x';
|
||||
|
||||
if (++argn >= argc) /* advance to next argument */
|
||||
usage();
|
||||
if (sscanf(argv[argn], "%ld%c", &lval, &ch) < 1)
|
||||
usage();
|
||||
if (ch == 'm' || ch == 'M')
|
||||
lval *= 1000L;
|
||||
cinfo->mem->max_memory_to_use = lval * 1000L;
|
||||
|
||||
} else if (keymatch(arg, "optimize", 1) || keymatch(arg, "optimise", 1)) {
|
||||
/* Enable entropy parm optimization. */
|
||||
#ifdef ENTROPY_OPT_SUPPORTED
|
||||
cinfo->optimize_coding = TRUE;
|
||||
#else
|
||||
fprintf(stderr, "%s: sorry, entropy optimization was not compiled\n",
|
||||
progname);
|
||||
exit(EXIT_FAILURE);
|
||||
#endif
|
||||
|
||||
} else if (keymatch(arg, "outfile", 4)) {
|
||||
/* 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, "perfect", 2)) {
|
||||
/* Fail if there is any partial edge MCUs that the transform can't
|
||||
* handle. */
|
||||
transformoption.perfect = TRUE;
|
||||
|
||||
} else if (keymatch(arg, "progressive", 2)) {
|
||||
/* Select simple progressive mode. */
|
||||
#ifdef C_PROGRESSIVE_SUPPORTED
|
||||
simple_progressive = TRUE;
|
||||
/* We must postpone execution until num_components is known. */
|
||||
#else
|
||||
fprintf(stderr, "%s: sorry, progressive output was not compiled\n",
|
||||
progname);
|
||||
exit(EXIT_FAILURE);
|
||||
#endif
|
||||
|
||||
} else if (keymatch(arg, "restart", 1)) {
|
||||
/* Restart interval in MCU rows (or in MCUs with 'b'). */
|
||||
long lval;
|
||||
char ch = 'x';
|
||||
|
||||
if (++argn >= argc) /* advance to next argument */
|
||||
usage();
|
||||
if (sscanf(argv[argn], "%ld%c", &lval, &ch) < 1)
|
||||
usage();
|
||||
if (lval < 0 || lval > 65535L)
|
||||
usage();
|
||||
if (ch == 'b' || ch == 'B') {
|
||||
cinfo->restart_interval = (unsigned int) lval;
|
||||
cinfo->restart_in_rows = 0; /* else prior '-restart n' overrides me */
|
||||
} else {
|
||||
cinfo->restart_in_rows = (int) lval;
|
||||
/* restart_interval will be computed during startup */
|
||||
}
|
||||
|
||||
} else if (keymatch(arg, "rotate", 2)) {
|
||||
/* Rotate 90, 180, or 270 degrees (measured clockwise). */
|
||||
if (++argn >= argc) /* advance to next argument */
|
||||
usage();
|
||||
if (keymatch(argv[argn], "90", 2))
|
||||
select_transform(JXFORM_ROT_90);
|
||||
else if (keymatch(argv[argn], "180", 3))
|
||||
select_transform(JXFORM_ROT_180);
|
||||
else if (keymatch(argv[argn], "270", 3))
|
||||
select_transform(JXFORM_ROT_270);
|
||||
else
|
||||
usage();
|
||||
|
||||
} else if (keymatch(arg, "scale", 4)) {
|
||||
/* Scale the output image by a fraction M/N. */
|
||||
if (++argn >= argc) /* advance to next argument */
|
||||
usage();
|
||||
scaleoption = argv[argn];
|
||||
/* We must postpone processing until decompression startup. */
|
||||
|
||||
} else if (keymatch(arg, "scans", 1)) {
|
||||
/* Set scan script. */
|
||||
#ifdef C_MULTISCAN_FILES_SUPPORTED
|
||||
if (++argn >= argc) /* advance to next argument */
|
||||
usage();
|
||||
scansarg = argv[argn];
|
||||
/* We must postpone reading the file in case -progressive appears. */
|
||||
#else
|
||||
fprintf(stderr, "%s: sorry, multi-scan output was not compiled\n",
|
||||
progname);
|
||||
exit(EXIT_FAILURE);
|
||||
#endif
|
||||
|
||||
} else if (keymatch(arg, "transpose", 1)) {
|
||||
/* Transpose (across UL-to-LR axis). */
|
||||
select_transform(JXFORM_TRANSPOSE);
|
||||
|
||||
} else if (keymatch(arg, "transverse", 6)) {
|
||||
/* Transverse transpose (across UR-to-LL axis). */
|
||||
select_transform(JXFORM_TRANSVERSE);
|
||||
|
||||
} else if (keymatch(arg, "trim", 3)) {
|
||||
/* Trim off any partial edge MCUs that the transform can't handle. */
|
||||
transformoption.trim = TRUE;
|
||||
|
||||
} else if (keymatch(arg, "wipe", 1)) {
|
||||
#if TRANSFORMS_SUPPORTED
|
||||
if (++argn >= argc) /* advance to next argument */
|
||||
usage();
|
||||
if (transformoption.crop /* reject multiple crop/drop/wipe requests */ ||
|
||||
! jtransform_parse_crop_spec(&transformoption, argv[argn])) {
|
||||
fprintf(stderr, "%s: bogus -wipe argument '%s'\n",
|
||||
progname, argv[argn]);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
select_transform(JXFORM_WIPE);
|
||||
#else
|
||||
select_transform(JXFORM_NONE); /* force an error */
|
||||
#endif
|
||||
|
||||
} else {
|
||||
usage(); /* bogus switch */
|
||||
}
|
||||
}
|
||||
|
||||
/* Post-switch-scanning cleanup */
|
||||
|
||||
if (for_real) {
|
||||
|
||||
#ifdef C_PROGRESSIVE_SUPPORTED
|
||||
if (simple_progressive) /* process -progressive; -scans can override */
|
||||
jpeg_simple_progression(cinfo);
|
||||
#endif
|
||||
|
||||
#ifdef C_MULTISCAN_FILES_SUPPORTED
|
||||
if (scansarg != NULL) /* process -scans if it was present */
|
||||
if (! read_scan_script(cinfo, scansarg))
|
||||
usage();
|
||||
#endif
|
||||
}
|
||||
|
||||
return argn; /* return index of next arg (file name) */
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* The main program.
|
||||
*/
|
||||
|
||||
int
|
||||
main (int argc, char **argv)
|
||||
{
|
||||
struct jpeg_decompress_struct srcinfo;
|
||||
struct jpeg_error_mgr jsrcerr;
|
||||
#if TRANSFORMS_SUPPORTED
|
||||
struct jpeg_decompress_struct dropinfo;
|
||||
struct jpeg_error_mgr jdroperr;
|
||||
FILE * drop_file;
|
||||
#endif
|
||||
struct jpeg_compress_struct dstinfo;
|
||||
struct jpeg_error_mgr jdsterr;
|
||||
#ifdef PROGRESS_REPORT
|
||||
struct cdjpeg_progress_mgr progress;
|
||||
#endif
|
||||
jvirt_barray_ptr * src_coef_arrays;
|
||||
jvirt_barray_ptr * dst_coef_arrays;
|
||||
int file_index;
|
||||
/* We assume all-in-memory processing and can therefore use only a
|
||||
* single file pointer for sequential input and output operation.
|
||||
*/
|
||||
FILE * fp;
|
||||
|
||||
/* On Mac, fetch a command line. */
|
||||
#ifdef USE_CCOMMAND
|
||||
argc = ccommand(&argv);
|
||||
#endif
|
||||
|
||||
progname = argv[0];
|
||||
if (progname == NULL || progname[0] == 0)
|
||||
progname = "jpegtran"; /* in case C library doesn't provide it */
|
||||
|
||||
/* Initialize the JPEG decompression object with default error handling. */
|
||||
srcinfo.err = jpeg_std_error(&jsrcerr);
|
||||
jpeg_create_decompress(&srcinfo);
|
||||
/* Initialize the JPEG compression object with default error handling. */
|
||||
dstinfo.err = jpeg_std_error(&jdsterr);
|
||||
jpeg_create_compress(&dstinfo);
|
||||
|
||||
/* Now safe to enable signal catcher.
|
||||
* Note: we assume only the decompression object will have virtual arrays.
|
||||
*/
|
||||
#ifdef NEED_SIGNAL_CATCHER
|
||||
enable_signal_catcher((j_common_ptr) &srcinfo);
|
||||
#endif
|
||||
|
||||
/* Scan command line to find file names.
|
||||
* It is convenient to use just one switch-parsing routine, but the switch
|
||||
* values read here are mostly ignored; we will rescan the switches after
|
||||
* opening the input file. Also note that most of the switches affect the
|
||||
* destination JPEG object, so we parse into that and then copy over what
|
||||
* needs to affect the source too.
|
||||
*/
|
||||
|
||||
file_index = parse_switches(&dstinfo, argc, argv, 0, FALSE);
|
||||
jsrcerr.trace_level = jdsterr.trace_level;
|
||||
srcinfo.mem->max_memory_to_use = dstinfo.mem->max_memory_to_use;
|
||||
|
||||
#ifdef TWO_FILE_COMMANDLINE
|
||||
/* 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();
|
||||
}
|
||||
}
|
||||
#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 ((fp = fopen(argv[file_index], READ_BINARY)) == NULL) {
|
||||
fprintf(stderr, "%s: can't open %s for reading\n", progname, argv[file_index]);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
} else {
|
||||
/* default input file is stdin */
|
||||
fp = read_stdin();
|
||||
}
|
||||
|
||||
#if TRANSFORMS_SUPPORTED
|
||||
/* Open the drop file. */
|
||||
if (dropfilename != NULL) {
|
||||
if ((drop_file = fopen(dropfilename, READ_BINARY)) == NULL) {
|
||||
fprintf(stderr, "%s: can't open %s for reading\n", progname, dropfilename);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
dropinfo.err = jpeg_std_error(&jdroperr);
|
||||
jpeg_create_decompress(&dropinfo);
|
||||
jpeg_stdio_src(&dropinfo, drop_file);
|
||||
} else {
|
||||
drop_file = NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef PROGRESS_REPORT
|
||||
start_progress_monitor((j_common_ptr) &dstinfo, &progress);
|
||||
#endif
|
||||
|
||||
/* Specify data source for decompression */
|
||||
jpeg_stdio_src(&srcinfo, fp);
|
||||
|
||||
/* Enable saving of extra markers that we want to copy */
|
||||
jcopy_markers_setup(&srcinfo, copyoption);
|
||||
|
||||
/* Read file header */
|
||||
(void) jpeg_read_header(&srcinfo, TRUE);
|
||||
|
||||
/* Adjust default decompression parameters */
|
||||
if (scaleoption != NULL)
|
||||
if (sscanf(scaleoption, "%u/%u",
|
||||
&srcinfo.scale_num, &srcinfo.scale_denom) < 1)
|
||||
usage();
|
||||
|
||||
#if TRANSFORMS_SUPPORTED
|
||||
if (dropfilename != NULL) {
|
||||
(void) jpeg_read_header(&dropinfo, TRUE);
|
||||
transformoption.crop_width = dropinfo.image_width;
|
||||
transformoption.crop_width_set = JCROP_POS;
|
||||
transformoption.crop_height = dropinfo.image_height;
|
||||
transformoption.crop_height_set = JCROP_POS;
|
||||
transformoption.drop_ptr = &dropinfo;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Any space needed by a transform option must be requested before
|
||||
* jpeg_read_coefficients so that memory allocation will be done right.
|
||||
*/
|
||||
#if TRANSFORMS_SUPPORTED
|
||||
/* Fail right away if -perfect is given and transformation is not perfect.
|
||||
*/
|
||||
if (!jtransform_request_workspace(&srcinfo, &transformoption)) {
|
||||
fprintf(stderr, "%s: transformation is not perfect\n", progname);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Read source file as DCT coefficients */
|
||||
src_coef_arrays = jpeg_read_coefficients(&srcinfo);
|
||||
|
||||
#if TRANSFORMS_SUPPORTED
|
||||
if (dropfilename != NULL) {
|
||||
transformoption.drop_coef_arrays = jpeg_read_coefficients(&dropinfo);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Initialize destination compression parameters from source values */
|
||||
jpeg_copy_critical_parameters(&srcinfo, &dstinfo);
|
||||
|
||||
/* Adjust destination parameters if required by transform options;
|
||||
* also find out which set of coefficient arrays will hold the output.
|
||||
*/
|
||||
#if TRANSFORMS_SUPPORTED
|
||||
dst_coef_arrays = jtransform_adjust_parameters(&srcinfo, &dstinfo,
|
||||
src_coef_arrays,
|
||||
&transformoption);
|
||||
#else
|
||||
dst_coef_arrays = src_coef_arrays;
|
||||
#endif
|
||||
|
||||
/* Close input file, if we opened it.
|
||||
* Note: we assume that jpeg_read_coefficients consumed all input
|
||||
* until JPEG_REACHED_EOI, and that jpeg_finish_decompress will
|
||||
* only consume more while (! cinfo->inputctl->eoi_reached).
|
||||
* We cannot call jpeg_finish_decompress here since we still need the
|
||||
* virtual arrays allocated from the source object for processing.
|
||||
*/
|
||||
if (fp != stdin)
|
||||
fclose(fp);
|
||||
|
||||
/* Open the output file. */
|
||||
if (outfilename != NULL) {
|
||||
if ((fp = fopen(outfilename, WRITE_BINARY)) == NULL) {
|
||||
fprintf(stderr, "%s: can't open %s for writing\n", progname, outfilename);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
} else {
|
||||
/* default output file is stdout */
|
||||
fp = write_stdout();
|
||||
}
|
||||
|
||||
/* Adjust default compression parameters by re-parsing the options */
|
||||
file_index = parse_switches(&dstinfo, argc, argv, 0, TRUE);
|
||||
|
||||
/* Specify data destination for compression */
|
||||
jpeg_stdio_dest(&dstinfo, fp);
|
||||
|
||||
/* Start compressor (note no image data is actually written here) */
|
||||
jpeg_write_coefficients(&dstinfo, dst_coef_arrays);
|
||||
|
||||
/* Copy to the output file any extra markers that we want to preserve */
|
||||
jcopy_markers_execute(&srcinfo, &dstinfo, copyoption);
|
||||
|
||||
/* Execute image transformation, if any */
|
||||
#if TRANSFORMS_SUPPORTED
|
||||
jtransform_execute_transformation(&srcinfo, &dstinfo,
|
||||
src_coef_arrays,
|
||||
&transformoption);
|
||||
#endif
|
||||
|
||||
/* Finish compression and release memory */
|
||||
jpeg_finish_compress(&dstinfo);
|
||||
jpeg_destroy_compress(&dstinfo);
|
||||
#if TRANSFORMS_SUPPORTED
|
||||
if (dropfilename != NULL) {
|
||||
(void) jpeg_finish_decompress(&dropinfo);
|
||||
jpeg_destroy_decompress(&dropinfo);
|
||||
}
|
||||
#endif
|
||||
(void) jpeg_finish_decompress(&srcinfo);
|
||||
jpeg_destroy_decompress(&srcinfo);
|
||||
|
||||
/* Close output file, if we opened it */
|
||||
if (fp != stdout)
|
||||
fclose(fp);
|
||||
#if TRANSFORMS_SUPPORTED
|
||||
if (drop_file != NULL)
|
||||
fclose(drop_file);
|
||||
#endif
|
||||
|
||||
#ifdef PROGRESS_REPORT
|
||||
end_progress_monitor((j_common_ptr) &dstinfo);
|
||||
#endif
|
||||
|
||||
/* All done. */
|
||||
#if TRANSFORMS_SUPPORTED
|
||||
if (dropfilename != NULL)
|
||||
exit(jsrcerr.num_warnings + jdroperr.num_warnings +
|
||||
jdsterr.num_warnings ? EXIT_WARNING : EXIT_SUCCESS);
|
||||
#endif
|
||||
exit(jsrcerr.num_warnings + jdsterr.num_warnings ?
|
||||
EXIT_WARNING : EXIT_SUCCESS);
|
||||
return 0; /* suppress no-return-value warnings */
|
||||
}
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* jversion.h
|
||||
*
|
||||
* Copyright (C) 1991-2022, Thomas G. Lane, Guido Vollbeding.
|
||||
* Copyright (C) 1991-2024, Thomas G. Lane, Guido Vollbeding.
|
||||
* 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 "9e 16-Jan-2022"
|
||||
#define JVERSION "9f 14-Jan-2024"
|
||||
|
||||
#define JCOPYRIGHT "Copyright (C) 2022, Thomas G. Lane, Guido Vollbeding"
|
||||
#define JCOPYRIGHT "Copyright (C) 2024, Thomas G. Lane, Guido Vollbeding"
|
||||
|
|
|
|||
|
|
@ -1,515 +0,0 @@
|
|||
/*
|
||||
* rdjpgcom.c
|
||||
*
|
||||
* Copyright (C) 1994-1997, Thomas G. Lane.
|
||||
* Modified 2009 by Bill Allombert, Guido Vollbeding.
|
||||
* This file is part of the Independent JPEG Group's software.
|
||||
* For conditions of distribution and use, see the accompanying README file.
|
||||
*
|
||||
* This file contains a very simple stand-alone application that displays
|
||||
* the text in COM (comment) markers in a JFIF file.
|
||||
* This may be useful as an example of the minimum logic needed to parse
|
||||
* JPEG markers.
|
||||
*/
|
||||
|
||||
#define JPEG_CJPEG_DJPEG /* to get the command-line config symbols */
|
||||
#include "jinclude.h" /* get auto-config symbols, <stdio.h> */
|
||||
|
||||
#ifdef HAVE_LOCALE_H
|
||||
#include <locale.h> /* Bill Allombert: use locale for isprint */
|
||||
#endif
|
||||
#include <ctype.h> /* to declare isupper(), tolower() */
|
||||
#ifdef USE_SETMODE
|
||||
#include <fcntl.h> /* to declare setmode()'s parameter macros */
|
||||
/* If you have setmode() but not <io.h>, just delete this line: */
|
||||
#include <io.h> /* to declare setmode() */
|
||||
#endif
|
||||
|
||||
#ifdef USE_CCOMMAND /* command-line reader for Macintosh */
|
||||
#ifdef __MWERKS__
|
||||
#include <SIOUX.h> /* Metrowerks needs this */
|
||||
#include <console.h> /* ... and this */
|
||||
#endif
|
||||
#ifdef THINK_C
|
||||
#include <console.h> /* Think declares it here */
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef DONT_USE_B_MODE /* define mode parameters for fopen() */
|
||||
#define READ_BINARY "r"
|
||||
#else
|
||||
#ifdef VMS /* VMS is very nonstandard */
|
||||
#define READ_BINARY "rb", "ctx=stm"
|
||||
#else /* standard ANSI-compliant case */
|
||||
#define READ_BINARY "rb"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef EXIT_FAILURE /* define exit() codes if not provided */
|
||||
#define EXIT_FAILURE 1
|
||||
#endif
|
||||
#ifndef EXIT_SUCCESS
|
||||
#ifdef VMS
|
||||
#define EXIT_SUCCESS 1 /* VMS is very nonstandard */
|
||||
#else
|
||||
#define EXIT_SUCCESS 0
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* These macros are used to read the input file.
|
||||
* To reuse this code in another application, you might need to change these.
|
||||
*/
|
||||
|
||||
static FILE * infile; /* input JPEG file */
|
||||
|
||||
/* Return next input byte, or EOF if no more */
|
||||
#define NEXTBYTE() getc(infile)
|
||||
|
||||
|
||||
/* Error exit handler */
|
||||
#define ERREXIT(msg) (fprintf(stderr, "%s\n", msg), exit(EXIT_FAILURE))
|
||||
|
||||
|
||||
/* Read one byte, testing for EOF */
|
||||
static int
|
||||
read_1_byte (void)
|
||||
{
|
||||
int c;
|
||||
|
||||
c = NEXTBYTE();
|
||||
if (c == EOF)
|
||||
ERREXIT("Premature EOF in JPEG file");
|
||||
return c;
|
||||
}
|
||||
|
||||
/* Read 2 bytes, convert to unsigned int */
|
||||
/* All 2-byte quantities in JPEG markers are MSB first */
|
||||
static unsigned int
|
||||
read_2_bytes (void)
|
||||
{
|
||||
int c1, c2;
|
||||
|
||||
c1 = NEXTBYTE();
|
||||
if (c1 == EOF)
|
||||
ERREXIT("Premature EOF in JPEG file");
|
||||
c2 = NEXTBYTE();
|
||||
if (c2 == EOF)
|
||||
ERREXIT("Premature EOF in JPEG file");
|
||||
return (((unsigned int) c1) << 8) + ((unsigned int) c2);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* JPEG markers consist of one or more 0xFF bytes, followed by a marker
|
||||
* code byte (which is not an FF). Here are the marker codes of interest
|
||||
* in this program. (See jdmarker.c for a more complete list.)
|
||||
*/
|
||||
|
||||
#define M_SOF0 0xC0 /* Start Of Frame N */
|
||||
#define M_SOF1 0xC1 /* N indicates which compression process */
|
||||
#define M_SOF2 0xC2 /* Only SOF0-SOF2 are now in common use */
|
||||
#define M_SOF3 0xC3
|
||||
#define M_SOF5 0xC5 /* NB: codes C4 and CC are NOT SOF markers */
|
||||
#define M_SOF6 0xC6
|
||||
#define M_SOF7 0xC7
|
||||
#define M_SOF9 0xC9
|
||||
#define M_SOF10 0xCA
|
||||
#define M_SOF11 0xCB
|
||||
#define M_SOF13 0xCD
|
||||
#define M_SOF14 0xCE
|
||||
#define M_SOF15 0xCF
|
||||
#define M_SOI 0xD8 /* Start Of Image (beginning of datastream) */
|
||||
#define M_EOI 0xD9 /* End Of Image (end of datastream) */
|
||||
#define M_SOS 0xDA /* Start Of Scan (begins compressed data) */
|
||||
#define M_APP0 0xE0 /* Application-specific marker, type N */
|
||||
#define M_APP12 0xEC /* (we don't bother to list all 16 APPn's) */
|
||||
#define M_COM 0xFE /* COMment */
|
||||
|
||||
|
||||
/*
|
||||
* Find the next JPEG marker and return its marker code.
|
||||
* We expect at least one FF byte, possibly more if the compressor used FFs
|
||||
* to pad the file.
|
||||
* There could also be non-FF garbage between markers. The treatment of such
|
||||
* garbage is unspecified; we choose to skip over it but emit a warning msg.
|
||||
* NB: this routine must not be used after seeing SOS marker, since it will
|
||||
* not deal correctly with FF/00 sequences in the compressed image data...
|
||||
*/
|
||||
|
||||
static int
|
||||
next_marker (void)
|
||||
{
|
||||
int c;
|
||||
int discarded_bytes = 0;
|
||||
|
||||
/* Find 0xFF byte; count and skip any non-FFs. */
|
||||
c = read_1_byte();
|
||||
while (c != 0xFF) {
|
||||
discarded_bytes++;
|
||||
c = read_1_byte();
|
||||
}
|
||||
/* Get marker code byte, swallowing any duplicate FF bytes. Extra FFs
|
||||
* are legal as pad bytes, so don't count them in discarded_bytes.
|
||||
*/
|
||||
do {
|
||||
c = read_1_byte();
|
||||
} while (c == 0xFF);
|
||||
|
||||
if (discarded_bytes != 0) {
|
||||
fprintf(stderr, "Warning: garbage data found in JPEG file\n");
|
||||
}
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Read the initial marker, which should be SOI.
|
||||
* For a JFIF file, the first two bytes of the file should be literally
|
||||
* 0xFF M_SOI. To be more general, we could use next_marker, but if the
|
||||
* input file weren't actually JPEG at all, next_marker might read the whole
|
||||
* file and then return a misleading error message...
|
||||
*/
|
||||
|
||||
static int
|
||||
first_marker (void)
|
||||
{
|
||||
int c1, c2;
|
||||
|
||||
c1 = NEXTBYTE();
|
||||
c2 = NEXTBYTE();
|
||||
if (c1 != 0xFF || c2 != M_SOI)
|
||||
ERREXIT("Not a JPEG file");
|
||||
return c2;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Most types of marker are followed by a variable-length parameter segment.
|
||||
* This routine skips over the parameters for any marker we don't otherwise
|
||||
* want to process.
|
||||
* Note that we MUST skip the parameter segment explicitly in order not to
|
||||
* be fooled by 0xFF bytes that might appear within the parameter segment;
|
||||
* such bytes do NOT introduce new markers.
|
||||
*/
|
||||
|
||||
static void
|
||||
skip_variable (void)
|
||||
/* Skip over an unknown or uninteresting variable-length marker */
|
||||
{
|
||||
unsigned int length;
|
||||
|
||||
/* Get the marker parameter length count */
|
||||
length = read_2_bytes();
|
||||
/* Length includes itself, so must be at least 2 */
|
||||
if (length < 2)
|
||||
ERREXIT("Erroneous JPEG marker length");
|
||||
length -= 2;
|
||||
/* Skip over the remaining bytes */
|
||||
while (length > 0) {
|
||||
(void) read_1_byte();
|
||||
length--;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Process a COM marker.
|
||||
* We want to print out the marker contents as legible text;
|
||||
* we must guard against non-text junk and varying newline representations.
|
||||
*/
|
||||
|
||||
static void
|
||||
process_COM (int raw)
|
||||
{
|
||||
unsigned int length;
|
||||
int ch;
|
||||
int lastch = 0;
|
||||
|
||||
/* Bill Allombert: set locale properly for isprint */
|
||||
#ifdef HAVE_LOCALE_H
|
||||
setlocale(LC_CTYPE, "");
|
||||
#endif
|
||||
|
||||
/* Get the marker parameter length count */
|
||||
length = read_2_bytes();
|
||||
/* Length includes itself, so must be at least 2 */
|
||||
if (length < 2)
|
||||
ERREXIT("Erroneous JPEG marker length");
|
||||
length -= 2;
|
||||
|
||||
while (length > 0) {
|
||||
ch = read_1_byte();
|
||||
if (raw) {
|
||||
putc(ch, stdout);
|
||||
/* Emit the character in a readable form.
|
||||
* Nonprintables are converted to \nnn form,
|
||||
* while \ is converted to \\.
|
||||
* Newlines in CR, CR/LF, or LF form will be printed as one newline.
|
||||
*/
|
||||
} else if (ch == '\r') {
|
||||
printf("\n");
|
||||
} else if (ch == '\n') {
|
||||
if (lastch != '\r')
|
||||
printf("\n");
|
||||
} else if (ch == '\\') {
|
||||
printf("\\\\");
|
||||
} else if (isprint(ch)) {
|
||||
putc(ch, stdout);
|
||||
} else {
|
||||
printf("\\%03o", ch);
|
||||
}
|
||||
lastch = ch;
|
||||
length--;
|
||||
}
|
||||
printf("\n");
|
||||
|
||||
/* Bill Allombert: revert to C locale */
|
||||
#ifdef HAVE_LOCALE_H
|
||||
setlocale(LC_CTYPE, "C");
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Process a SOFn marker.
|
||||
* This code is only needed if you want to know the image dimensions...
|
||||
*/
|
||||
|
||||
static void
|
||||
process_SOFn (int marker)
|
||||
{
|
||||
unsigned int length;
|
||||
unsigned int image_height, image_width;
|
||||
int data_precision, num_components;
|
||||
const char * process;
|
||||
int ci;
|
||||
|
||||
length = read_2_bytes(); /* usual parameter length count */
|
||||
|
||||
data_precision = read_1_byte();
|
||||
image_height = read_2_bytes();
|
||||
image_width = read_2_bytes();
|
||||
num_components = read_1_byte();
|
||||
|
||||
switch (marker) {
|
||||
case M_SOF0: process = "Baseline"; break;
|
||||
case M_SOF1: process = "Extended sequential"; break;
|
||||
case M_SOF2: process = "Progressive"; break;
|
||||
case M_SOF3: process = "Lossless"; break;
|
||||
case M_SOF5: process = "Differential sequential"; break;
|
||||
case M_SOF6: process = "Differential progressive"; break;
|
||||
case M_SOF7: process = "Differential lossless"; break;
|
||||
case M_SOF9: process = "Extended sequential, arithmetic coding"; break;
|
||||
case M_SOF10: process = "Progressive, arithmetic coding"; break;
|
||||
case M_SOF11: process = "Lossless, arithmetic coding"; break;
|
||||
case M_SOF13: process = "Differential sequential, arithmetic coding"; break;
|
||||
case M_SOF14: process = "Differential progressive, arithmetic coding"; break;
|
||||
case M_SOF15: process = "Differential lossless, arithmetic coding"; break;
|
||||
default: process = "Unknown"; break;
|
||||
}
|
||||
|
||||
printf("JPEG image is %uw * %uh, %d color components, %d bits per sample\n",
|
||||
image_width, image_height, num_components, data_precision);
|
||||
printf("JPEG process: %s\n", process);
|
||||
|
||||
if (length != (unsigned int) (8 + num_components * 3))
|
||||
ERREXIT("Bogus SOF marker length");
|
||||
|
||||
for (ci = 0; ci < num_components; ci++) {
|
||||
(void) read_1_byte(); /* Component ID code */
|
||||
(void) read_1_byte(); /* H, V sampling factors */
|
||||
(void) read_1_byte(); /* Quantization table number */
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Parse the marker stream until SOS or EOI is seen;
|
||||
* display any COM markers.
|
||||
* While the companion program wrjpgcom will always insert COM markers before
|
||||
* SOFn, other implementations might not, so we scan to SOS before stopping.
|
||||
* If we were only interested in the image dimensions, we would stop at SOFn.
|
||||
* (Conversely, if we only cared about COM markers, there would be no need
|
||||
* for special code to handle SOFn; we could treat it like other markers.)
|
||||
*/
|
||||
|
||||
static int
|
||||
scan_JPEG_header (int verbose, int raw)
|
||||
{
|
||||
int marker;
|
||||
|
||||
/* Expect SOI at start of file */
|
||||
if (first_marker() != M_SOI)
|
||||
ERREXIT("Expected SOI marker first");
|
||||
|
||||
/* Scan miscellaneous markers until we reach SOS. */
|
||||
for (;;) {
|
||||
marker = next_marker();
|
||||
switch (marker) {
|
||||
/* Note that marker codes 0xC4, 0xC8, 0xCC are not, and must not be,
|
||||
* treated as SOFn. C4 in particular is actually DHT.
|
||||
*/
|
||||
case M_SOF0: /* Baseline */
|
||||
case M_SOF1: /* Extended sequential, Huffman */
|
||||
case M_SOF2: /* Progressive, Huffman */
|
||||
case M_SOF3: /* Lossless, Huffman */
|
||||
case M_SOF5: /* Differential sequential, Huffman */
|
||||
case M_SOF6: /* Differential progressive, Huffman */
|
||||
case M_SOF7: /* Differential lossless, Huffman */
|
||||
case M_SOF9: /* Extended sequential, arithmetic */
|
||||
case M_SOF10: /* Progressive, arithmetic */
|
||||
case M_SOF11: /* Lossless, arithmetic */
|
||||
case M_SOF13: /* Differential sequential, arithmetic */
|
||||
case M_SOF14: /* Differential progressive, arithmetic */
|
||||
case M_SOF15: /* Differential lossless, arithmetic */
|
||||
if (verbose)
|
||||
process_SOFn(marker);
|
||||
else
|
||||
skip_variable();
|
||||
break;
|
||||
|
||||
case M_SOS: /* stop before hitting compressed data */
|
||||
return marker;
|
||||
|
||||
case M_EOI: /* in case it's a tables-only JPEG stream */
|
||||
return marker;
|
||||
|
||||
case M_COM:
|
||||
process_COM(raw);
|
||||
break;
|
||||
|
||||
case M_APP12:
|
||||
/* Some digital camera makers put useful textual information into
|
||||
* APP12 markers, so we print those out too when in -verbose mode.
|
||||
*/
|
||||
if (verbose) {
|
||||
printf("APP12 contains:\n");
|
||||
process_COM(raw);
|
||||
} else
|
||||
skip_variable();
|
||||
break;
|
||||
|
||||
default: /* Anything else just gets skipped */
|
||||
skip_variable(); /* we assume it has a parameter count... */
|
||||
break;
|
||||
}
|
||||
} /* end loop */
|
||||
}
|
||||
|
||||
|
||||
/* Command line parsing code */
|
||||
|
||||
static const char * progname; /* program name for error messages */
|
||||
|
||||
|
||||
static void
|
||||
usage (void)
|
||||
/* complain about bad command line */
|
||||
{
|
||||
fprintf(stderr, "rdjpgcom displays any textual comments in a JPEG file.\n");
|
||||
|
||||
fprintf(stderr, "Usage: %s [switches] [inputfile]\n", progname);
|
||||
|
||||
fprintf(stderr, "Switches (names may be abbreviated):\n");
|
||||
fprintf(stderr, " -raw Display non-printable characters in comments (unsafe)\n");
|
||||
fprintf(stderr, " -verbose Also display dimensions of JPEG image\n");
|
||||
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
keymatch (char * arg, const char * keyword, int minchars)
|
||||
/* Case-insensitive matching of (possibly abbreviated) keyword switches. */
|
||||
/* keyword is the constant keyword (must be lower case already), */
|
||||
/* minchars is length of minimum legal abbreviation. */
|
||||
{
|
||||
register int ca, ck;
|
||||
register int nmatched = 0;
|
||||
|
||||
while ((ca = *arg++) != '\0') {
|
||||
if ((ck = *keyword++) == '\0')
|
||||
return 0; /* arg longer than keyword, no good */
|
||||
if (isupper(ca)) /* force arg to lcase (assume ck is already) */
|
||||
ca = tolower(ca);
|
||||
if (ca != ck)
|
||||
return 0; /* no good */
|
||||
nmatched++; /* count matched characters */
|
||||
}
|
||||
/* reached end of argument; fail if it's too short for unique abbrev */
|
||||
if (nmatched < minchars)
|
||||
return 0;
|
||||
return 1; /* A-OK */
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* The main program.
|
||||
*/
|
||||
|
||||
int
|
||||
main (int argc, char **argv)
|
||||
{
|
||||
int argn;
|
||||
char * arg;
|
||||
int verbose = 0, raw = 0;
|
||||
|
||||
/* On Mac, fetch a command line. */
|
||||
#ifdef USE_CCOMMAND
|
||||
argc = ccommand(&argv);
|
||||
#endif
|
||||
|
||||
progname = argv[0];
|
||||
if (progname == NULL || progname[0] == 0)
|
||||
progname = "rdjpgcom"; /* in case C library doesn't provide it */
|
||||
|
||||
/* Parse switches, if any */
|
||||
for (argn = 1; argn < argc; argn++) {
|
||||
arg = argv[argn];
|
||||
if (arg[0] != '-')
|
||||
break; /* not switch, must be file name */
|
||||
arg++; /* advance over '-' */
|
||||
if (keymatch(arg, "verbose", 1)) {
|
||||
verbose++;
|
||||
} else if (keymatch(arg, "raw", 1)) {
|
||||
raw = 1;
|
||||
} else
|
||||
usage();
|
||||
}
|
||||
|
||||
/* Open the input file. */
|
||||
/* Unix style: expect zero or one file name */
|
||||
if (argn < argc-1) {
|
||||
fprintf(stderr, "%s: only one input file\n", progname);
|
||||
usage();
|
||||
}
|
||||
if (argn < argc) {
|
||||
if ((infile = fopen(argv[argn], READ_BINARY)) == NULL) {
|
||||
fprintf(stderr, "%s: can't open %s\n", progname, argv[argn]);
|
||||
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 ((infile = fdopen(fileno(stdin), READ_BINARY)) == NULL) {
|
||||
fprintf(stderr, "%s: can't open stdin\n", progname);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
#else
|
||||
infile = stdin;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Scan the JPEG headers. */
|
||||
(void) scan_JPEG_header(verbose, raw);
|
||||
|
||||
/* All done. */
|
||||
exit(EXIT_SUCCESS);
|
||||
return 0; /* suppress no-return-value warnings */
|
||||
}
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* transupp.c
|
||||
*
|
||||
* Copyright (C) 1997-2019, Thomas G. Lane, Guido Vollbeding.
|
||||
* Copyright (C) 1997-2023, Thomas G. Lane, Guido Vollbeding.
|
||||
* This file is part of the Independent JPEG Group's software.
|
||||
* For conditions of distribution and use, see the accompanying README file.
|
||||
*
|
||||
|
|
@ -195,12 +195,11 @@ requant_comp (j_decompress_ptr cinfo, jpeg_component_info *compptr,
|
|||
jvirt_barray_ptr coef_array, JQUANT_TBL *qtblptr1)
|
||||
{
|
||||
JDIMENSION blk_x, blk_y;
|
||||
int offset_y, k;
|
||||
int offset_y, k, temp, qval;
|
||||
JQUANT_TBL *qtblptr;
|
||||
JBLOCKARRAY buffer;
|
||||
JBLOCKROW block;
|
||||
JCOEFPTR ptr;
|
||||
JCOEF temp, qval;
|
||||
|
||||
qtblptr = compptr->quant_table;
|
||||
for (blk_y = 0; blk_y < compptr->height_in_blocks;
|
||||
|
|
@ -213,27 +212,27 @@ requant_comp (j_decompress_ptr cinfo, jpeg_component_info *compptr,
|
|||
for (blk_x = 0; blk_x < compptr->width_in_blocks; blk_x++) {
|
||||
ptr = block[blk_x];
|
||||
for (k = 0; k < DCTSIZE2; k++) {
|
||||
temp = qtblptr->quantval[k];
|
||||
qval = qtblptr1->quantval[k];
|
||||
if (temp != qval) {
|
||||
temp *= ptr[k];
|
||||
/* The following quantization code is a copy from jcdctmgr.c */
|
||||
if (qval == 0) continue;
|
||||
temp = qtblptr->quantval[k];
|
||||
if (temp == qval) continue;
|
||||
temp *= ptr[k];
|
||||
/* The following quantization code is a copy from jcdctmgr.c */
|
||||
#ifdef FAST_DIVIDE
|
||||
#define DIVIDE_BY(a,b) a /= b
|
||||
#else
|
||||
#define DIVIDE_BY(a,b) if (a >= b) a /= b; else a = 0
|
||||
#endif
|
||||
if (temp < 0) {
|
||||
temp = -temp;
|
||||
temp += qval>>1; /* for rounding */
|
||||
DIVIDE_BY(temp, qval);
|
||||
temp = -temp;
|
||||
} else {
|
||||
temp += qval>>1; /* for rounding */
|
||||
DIVIDE_BY(temp, qval);
|
||||
}
|
||||
ptr[k] = temp;
|
||||
if (temp < 0) {
|
||||
temp = -temp;
|
||||
temp += qval>>1; /* for rounding */
|
||||
DIVIDE_BY(temp, qval);
|
||||
temp = -temp;
|
||||
} else {
|
||||
temp += qval>>1; /* for rounding */
|
||||
DIVIDE_BY(temp, qval);
|
||||
}
|
||||
ptr[k] = (JCOEF) temp;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -248,11 +247,11 @@ largest_common_denominator(JCOEF a, JCOEF b)
|
|||
{
|
||||
JCOEF c;
|
||||
|
||||
do {
|
||||
while (b) {
|
||||
c = a % b;
|
||||
a = b;
|
||||
b = c;
|
||||
} while (c);
|
||||
}
|
||||
|
||||
return a;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,599 +0,0 @@
|
|||
/*
|
||||
* wrjpgcom.c
|
||||
*
|
||||
* Copyright (C) 1994-1997, Thomas G. Lane.
|
||||
* Modified 2015-2017 by Guido Vollbeding.
|
||||
* This file is part of the Independent JPEG Group's software.
|
||||
* For conditions of distribution and use, see the accompanying README file.
|
||||
*
|
||||
* This file contains a very simple stand-alone application that inserts
|
||||
* user-supplied text as a COM (comment) marker in a JFIF file.
|
||||
* This may be useful as an example of the minimum logic needed to parse
|
||||
* JPEG markers.
|
||||
*/
|
||||
|
||||
#define JPEG_CJPEG_DJPEG /* to get the command-line config symbols */
|
||||
#include "jinclude.h" /* get auto-config symbols, <stdio.h> */
|
||||
|
||||
#ifndef HAVE_STDLIB_H /* <stdlib.h> should declare malloc() */
|
||||
extern void * malloc ();
|
||||
#endif
|
||||
#include <ctype.h> /* to declare isupper(), tolower() */
|
||||
#ifdef USE_SETMODE
|
||||
#include <fcntl.h> /* to declare setmode()'s parameter macros */
|
||||
/* If you have setmode() but not <io.h>, just delete this line: */
|
||||
#include <io.h> /* to declare setmode() */
|
||||
#endif
|
||||
|
||||
#ifdef USE_CCOMMAND /* command-line reader for Macintosh */
|
||||
#ifdef __MWERKS__
|
||||
#include <SIOUX.h> /* Metrowerks needs this */
|
||||
#include <console.h> /* ... and this */
|
||||
#endif
|
||||
#ifdef THINK_C
|
||||
#include <console.h> /* Think declares it here */
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef DONT_USE_B_MODE /* define mode parameters for fopen() */
|
||||
#define READ_BINARY "r"
|
||||
#define WRITE_BINARY "w"
|
||||
#else
|
||||
#ifdef VMS /* VMS is very nonstandard */
|
||||
#define READ_BINARY "rb", "ctx=stm"
|
||||
#define WRITE_BINARY "wb", "ctx=stm"
|
||||
#else /* standard ANSI-compliant case */
|
||||
#define READ_BINARY "rb"
|
||||
#define WRITE_BINARY "wb"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef EXIT_FAILURE /* define exit() codes if not provided */
|
||||
#define EXIT_FAILURE 1
|
||||
#endif
|
||||
#ifndef EXIT_SUCCESS
|
||||
#ifdef VMS
|
||||
#define EXIT_SUCCESS 1 /* VMS is very nonstandard */
|
||||
#else
|
||||
#define EXIT_SUCCESS 0
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* Reduce this value if your malloc() can't allocate blocks up to 64K.
|
||||
* On DOS, compiling in large model is usually a better solution.
|
||||
*/
|
||||
|
||||
#ifndef MAX_COM_LENGTH
|
||||
#define MAX_COM_LENGTH 65000L /* must be <= 65533 in any case */
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* These macros are used to read the input file and write the output file.
|
||||
* To reuse this code in another application, you might need to change these.
|
||||
*/
|
||||
|
||||
static FILE * infile; /* input JPEG file */
|
||||
|
||||
/* Return next input byte, or EOF if no more */
|
||||
#define NEXTBYTE() getc(infile)
|
||||
|
||||
static FILE * outfile; /* output JPEG file */
|
||||
|
||||
/* Emit an output byte */
|
||||
#define PUTBYTE(x) putc((x), outfile)
|
||||
|
||||
|
||||
/* Error exit handler */
|
||||
#define ERREXIT(msg) (fprintf(stderr, "%s\n", msg), exit(EXIT_FAILURE))
|
||||
|
||||
|
||||
/* Read one byte, testing for EOF */
|
||||
static int
|
||||
read_1_byte (void)
|
||||
{
|
||||
int c;
|
||||
|
||||
c = NEXTBYTE();
|
||||
if (c == EOF)
|
||||
ERREXIT("Premature EOF in JPEG file");
|
||||
return c;
|
||||
}
|
||||
|
||||
/* Read 2 bytes, convert to unsigned int */
|
||||
/* All 2-byte quantities in JPEG markers are MSB first */
|
||||
static unsigned int
|
||||
read_2_bytes (void)
|
||||
{
|
||||
int c1, c2;
|
||||
|
||||
c1 = NEXTBYTE();
|
||||
if (c1 == EOF)
|
||||
ERREXIT("Premature EOF in JPEG file");
|
||||
c2 = NEXTBYTE();
|
||||
if (c2 == EOF)
|
||||
ERREXIT("Premature EOF in JPEG file");
|
||||
return (((unsigned int) c1) << 8) + ((unsigned int) c2);
|
||||
}
|
||||
|
||||
|
||||
/* Routines to write data to output file */
|
||||
|
||||
static void
|
||||
write_1_byte (int c)
|
||||
{
|
||||
PUTBYTE(c);
|
||||
}
|
||||
|
||||
static void
|
||||
write_2_bytes (unsigned int val)
|
||||
{
|
||||
PUTBYTE((val >> 8) & 0xFF);
|
||||
PUTBYTE(val & 0xFF);
|
||||
}
|
||||
|
||||
static void
|
||||
write_marker (int marker)
|
||||
{
|
||||
PUTBYTE(0xFF);
|
||||
PUTBYTE(marker);
|
||||
}
|
||||
|
||||
static void
|
||||
copy_rest_of_file (void)
|
||||
{
|
||||
int c;
|
||||
|
||||
while ((c = NEXTBYTE()) != EOF)
|
||||
PUTBYTE(c);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* JPEG markers consist of one or more 0xFF bytes, followed by a marker
|
||||
* code byte (which is not an FF). Here are the marker codes of interest
|
||||
* in this program. (See jdmarker.c for a more complete list.)
|
||||
*/
|
||||
|
||||
#define M_SOF0 0xC0 /* Start Of Frame N */
|
||||
#define M_SOF1 0xC1 /* N indicates which compression process */
|
||||
#define M_SOF2 0xC2 /* Only SOF0-SOF2 are now in common use */
|
||||
#define M_SOF3 0xC3
|
||||
#define M_SOF5 0xC5 /* NB: codes C4 and CC are NOT SOF markers */
|
||||
#define M_SOF6 0xC6
|
||||
#define M_SOF7 0xC7
|
||||
#define M_SOF9 0xC9
|
||||
#define M_SOF10 0xCA
|
||||
#define M_SOF11 0xCB
|
||||
#define M_SOF13 0xCD
|
||||
#define M_SOF14 0xCE
|
||||
#define M_SOF15 0xCF
|
||||
#define M_SOI 0xD8 /* Start Of Image (beginning of datastream) */
|
||||
#define M_EOI 0xD9 /* End Of Image (end of datastream) */
|
||||
#define M_SOS 0xDA /* Start Of Scan (begins compressed data) */
|
||||
#define M_COM 0xFE /* COMment */
|
||||
|
||||
|
||||
/*
|
||||
* Find the next JPEG marker and return its marker code.
|
||||
* We expect at least one FF byte, possibly more if the compressor used FFs
|
||||
* to pad the file. (Padding FFs will NOT be replicated in the output file.)
|
||||
* There could also be non-FF garbage between markers. The treatment of such
|
||||
* garbage is unspecified; we choose to skip over it but emit a warning msg.
|
||||
* NB: this routine must not be used after seeing SOS marker, since it will
|
||||
* not deal correctly with FF/00 sequences in the compressed image data...
|
||||
*/
|
||||
|
||||
static int
|
||||
next_marker (void)
|
||||
{
|
||||
int c;
|
||||
int discarded_bytes = 0;
|
||||
|
||||
/* Find 0xFF byte; count and skip any non-FFs. */
|
||||
c = read_1_byte();
|
||||
while (c != 0xFF) {
|
||||
discarded_bytes++;
|
||||
c = read_1_byte();
|
||||
}
|
||||
/* Get marker code byte, swallowing any duplicate FF bytes. Extra FFs
|
||||
* are legal as pad bytes, so don't count them in discarded_bytes.
|
||||
*/
|
||||
do {
|
||||
c = read_1_byte();
|
||||
} while (c == 0xFF);
|
||||
|
||||
if (discarded_bytes != 0) {
|
||||
fprintf(stderr, "Warning: garbage data found in JPEG file\n");
|
||||
}
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Read the initial marker, which should be SOI.
|
||||
* For a JFIF file, the first two bytes of the file should be literally
|
||||
* 0xFF M_SOI. To be more general, we could use next_marker, but if the
|
||||
* input file weren't actually JPEG at all, next_marker might read the whole
|
||||
* file and then return a misleading error message...
|
||||
*/
|
||||
|
||||
static int
|
||||
first_marker (void)
|
||||
{
|
||||
int c1, c2;
|
||||
|
||||
c1 = NEXTBYTE();
|
||||
c2 = NEXTBYTE();
|
||||
if (c1 != 0xFF || c2 != M_SOI)
|
||||
ERREXIT("Not a JPEG file");
|
||||
return c2;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Most types of marker are followed by a variable-length parameter segment.
|
||||
* This routine skips over the parameters for any marker we don't otherwise
|
||||
* want to process.
|
||||
* Note that we MUST skip the parameter segment explicitly in order not to
|
||||
* be fooled by 0xFF bytes that might appear within the parameter segment;
|
||||
* such bytes do NOT introduce new markers.
|
||||
*/
|
||||
|
||||
static void
|
||||
copy_variable (void)
|
||||
/* Copy an unknown or uninteresting variable-length marker */
|
||||
{
|
||||
unsigned int length;
|
||||
|
||||
/* Get the marker parameter length count */
|
||||
length = read_2_bytes();
|
||||
write_2_bytes(length);
|
||||
/* Length includes itself, so must be at least 2 */
|
||||
if (length < 2)
|
||||
ERREXIT("Erroneous JPEG marker length");
|
||||
length -= 2;
|
||||
/* Copy the remaining bytes */
|
||||
while (length > 0) {
|
||||
write_1_byte(read_1_byte());
|
||||
length--;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
skip_variable (void)
|
||||
/* Skip over an unknown or uninteresting variable-length marker */
|
||||
{
|
||||
unsigned int length;
|
||||
|
||||
/* Get the marker parameter length count */
|
||||
length = read_2_bytes();
|
||||
/* Length includes itself, so must be at least 2 */
|
||||
if (length < 2)
|
||||
ERREXIT("Erroneous JPEG marker length");
|
||||
length -= 2;
|
||||
/* Skip over the remaining bytes */
|
||||
while (length > 0) {
|
||||
(void) read_1_byte();
|
||||
length--;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Parse the marker stream until SOFn or EOI is seen;
|
||||
* copy data to output, but discard COM markers unless keep_COM is true.
|
||||
*/
|
||||
|
||||
static int
|
||||
scan_JPEG_header (int keep_COM)
|
||||
{
|
||||
int marker;
|
||||
|
||||
/* Expect SOI at start of file */
|
||||
if (first_marker() != M_SOI)
|
||||
ERREXIT("Expected SOI marker first");
|
||||
write_marker(M_SOI);
|
||||
|
||||
/* Scan miscellaneous markers until we reach SOFn. */
|
||||
for (;;) {
|
||||
marker = next_marker();
|
||||
switch (marker) {
|
||||
/* Note that marker codes 0xC4, 0xC8, 0xCC are not, and must not be,
|
||||
* treated as SOFn. C4 in particular is actually DHT.
|
||||
*/
|
||||
case M_SOF0: /* Baseline */
|
||||
case M_SOF1: /* Extended sequential, Huffman */
|
||||
case M_SOF2: /* Progressive, Huffman */
|
||||
case M_SOF3: /* Lossless, Huffman */
|
||||
case M_SOF5: /* Differential sequential, Huffman */
|
||||
case M_SOF6: /* Differential progressive, Huffman */
|
||||
case M_SOF7: /* Differential lossless, Huffman */
|
||||
case M_SOF9: /* Extended sequential, arithmetic */
|
||||
case M_SOF10: /* Progressive, arithmetic */
|
||||
case M_SOF11: /* Lossless, arithmetic */
|
||||
case M_SOF13: /* Differential sequential, arithmetic */
|
||||
case M_SOF14: /* Differential progressive, arithmetic */
|
||||
case M_SOF15: /* Differential lossless, arithmetic */
|
||||
return marker;
|
||||
|
||||
case M_SOS: /* should not see compressed data before SOF */
|
||||
ERREXIT("SOS without prior SOFn");
|
||||
break;
|
||||
|
||||
case M_EOI: /* in case it's a tables-only JPEG stream */
|
||||
return marker;
|
||||
|
||||
case M_COM: /* Existing COM: conditionally discard */
|
||||
if (keep_COM) {
|
||||
write_marker(marker);
|
||||
copy_variable();
|
||||
} else {
|
||||
skip_variable();
|
||||
}
|
||||
break;
|
||||
|
||||
default: /* Anything else just gets copied */
|
||||
write_marker(marker);
|
||||
copy_variable(); /* we assume it has a parameter count... */
|
||||
break;
|
||||
}
|
||||
} /* end loop */
|
||||
}
|
||||
|
||||
|
||||
/* Command line parsing code */
|
||||
|
||||
static const char * progname; /* program name for error messages */
|
||||
|
||||
|
||||
static void
|
||||
usage (void)
|
||||
/* complain about bad command line */
|
||||
{
|
||||
fprintf(stderr, "wrjpgcom inserts a textual comment in a JPEG file.\n");
|
||||
fprintf(stderr, "You can add to or replace any existing comment(s).\n");
|
||||
|
||||
fprintf(stderr, "Usage: %s [switches] ", progname);
|
||||
#ifdef TWO_FILE_COMMANDLINE
|
||||
fprintf(stderr, "inputfile outputfile\n");
|
||||
#else
|
||||
fprintf(stderr, "[inputfile]\n");
|
||||
#endif
|
||||
|
||||
fprintf(stderr, "Switches (names may be abbreviated):\n");
|
||||
fprintf(stderr, " -replace Delete any existing comments\n");
|
||||
fprintf(stderr, " -comment \"text\" Insert comment with given text\n");
|
||||
fprintf(stderr, " -cfile name Read comment from named file\n");
|
||||
fprintf(stderr, "Notice that you must put quotes around the comment text\n");
|
||||
fprintf(stderr, "when you use -comment.\n");
|
||||
fprintf(stderr, "If you do not give either -comment or -cfile on the command line,\n");
|
||||
fprintf(stderr, "then the comment text is read from standard input.\n");
|
||||
fprintf(stderr, "It can be multiple lines, up to %u characters total.\n",
|
||||
(unsigned int) MAX_COM_LENGTH);
|
||||
#ifndef TWO_FILE_COMMANDLINE
|
||||
fprintf(stderr, "You must specify an input JPEG file name when supplying\n");
|
||||
fprintf(stderr, "comment text from standard input.\n");
|
||||
#endif
|
||||
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
keymatch (char * arg, const char * keyword, int minchars)
|
||||
/* Case-insensitive matching of (possibly abbreviated) keyword switches. */
|
||||
/* keyword is the constant keyword (must be lower case already), */
|
||||
/* minchars is length of minimum legal abbreviation. */
|
||||
{
|
||||
register int ca, ck;
|
||||
register int nmatched = 0;
|
||||
|
||||
while ((ca = *arg++) != '\0') {
|
||||
if ((ck = *keyword++) == '\0')
|
||||
return 0; /* arg longer than keyword, no good */
|
||||
if (isupper(ca)) /* force arg to lcase (assume ck is already) */
|
||||
ca = tolower(ca);
|
||||
if (ca != ck)
|
||||
return 0; /* no good */
|
||||
nmatched++; /* count matched characters */
|
||||
}
|
||||
/* reached end of argument; fail if it's too short for unique abbrev */
|
||||
if (nmatched < minchars)
|
||||
return 0;
|
||||
return 1; /* A-OK */
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* The main program.
|
||||
*/
|
||||
|
||||
int
|
||||
main (int argc, char **argv)
|
||||
{
|
||||
int argn;
|
||||
char * arg;
|
||||
int keep_COM = 1;
|
||||
char * comment_arg = NULL;
|
||||
FILE * comment_file = NULL;
|
||||
unsigned int comment_length = 0;
|
||||
int marker;
|
||||
|
||||
/* On Mac, fetch a command line. */
|
||||
#ifdef USE_CCOMMAND
|
||||
argc = ccommand(&argv);
|
||||
#endif
|
||||
|
||||
progname = argv[0];
|
||||
if (progname == NULL || progname[0] == 0)
|
||||
progname = "wrjpgcom"; /* in case C library doesn't provide it */
|
||||
|
||||
/* Parse switches, if any */
|
||||
for (argn = 1; argn < argc; argn++) {
|
||||
arg = argv[argn];
|
||||
if (arg[0] != '-')
|
||||
break; /* not switch, must be file name */
|
||||
arg++; /* advance over '-' */
|
||||
if (keymatch(arg, "replace", 1)) {
|
||||
keep_COM = 0;
|
||||
} else if (keymatch(arg, "cfile", 2)) {
|
||||
if (++argn >= argc) usage();
|
||||
if ((comment_file = fopen(argv[argn], "r")) == NULL) {
|
||||
fprintf(stderr, "%s: can't open %s\n", progname, argv[argn]);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
} else if (keymatch(arg, "comment", 1)) {
|
||||
if (++argn >= argc) usage();
|
||||
comment_arg = argv[argn];
|
||||
/* If the comment text starts with '"', then we are probably running
|
||||
* under MS-DOG and must parse out the quoted string ourselves. Sigh.
|
||||
*/
|
||||
if (comment_arg[0] == '"') {
|
||||
comment_arg = (char *) malloc((size_t) MAX_COM_LENGTH);
|
||||
if (comment_arg == NULL)
|
||||
ERREXIT("Insufficient memory");
|
||||
if (strlen(argv[argn]+1) >= (size_t) MAX_COM_LENGTH) {
|
||||
fprintf(stderr, "Comment text may not exceed %u bytes\n",
|
||||
(unsigned int) MAX_COM_LENGTH);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
strcpy(comment_arg, argv[argn]+1);
|
||||
for (;;) {
|
||||
comment_length = (unsigned int) strlen(comment_arg);
|
||||
if (comment_length > 0 && comment_arg[comment_length-1] == '"') {
|
||||
comment_arg[comment_length-1] = '\0'; /* zap terminating quote */
|
||||
break;
|
||||
}
|
||||
if (++argn >= argc)
|
||||
ERREXIT("Missing ending quote mark");
|
||||
if (strlen(comment_arg) + 1 + strlen(argv[argn]) >=
|
||||
(size_t) MAX_COM_LENGTH) {
|
||||
fprintf(stderr, "Comment text may not exceed %u bytes\n",
|
||||
(unsigned int) MAX_COM_LENGTH);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
strcat(comment_arg, " ");
|
||||
strcat(comment_arg, argv[argn]);
|
||||
}
|
||||
} else if (strlen(comment_arg) >= (size_t) MAX_COM_LENGTH) {
|
||||
fprintf(stderr, "Comment text may not exceed %u bytes\n",
|
||||
(unsigned int) MAX_COM_LENGTH);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
comment_length = (unsigned int) strlen(comment_arg);
|
||||
} else
|
||||
usage();
|
||||
}
|
||||
|
||||
/* Cannot use both -comment and -cfile. */
|
||||
if (comment_arg != NULL && comment_file != NULL)
|
||||
usage();
|
||||
/* If there is neither -comment nor -cfile, we will read the comment text
|
||||
* from stdin; in this case there MUST be an input JPEG file name.
|
||||
*/
|
||||
if (comment_arg == NULL && comment_file == NULL && argn >= argc)
|
||||
usage();
|
||||
|
||||
/* Open the input file. */
|
||||
if (argn < argc) {
|
||||
if ((infile = fopen(argv[argn], READ_BINARY)) == NULL) {
|
||||
fprintf(stderr, "%s: can't open %s\n", progname, argv[argn]);
|
||||
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 ((infile = fdopen(fileno(stdin), READ_BINARY)) == NULL) {
|
||||
fprintf(stderr, "%s: can't open stdin\n", progname);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
#else
|
||||
infile = stdin;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Open the output file. */
|
||||
#ifdef TWO_FILE_COMMANDLINE
|
||||
/* Must have explicit output file name */
|
||||
if (argn != argc-2) {
|
||||
fprintf(stderr, "%s: must name one input and one output file\n",
|
||||
progname);
|
||||
usage();
|
||||
}
|
||||
if ((outfile = fopen(argv[argn+1], WRITE_BINARY)) == NULL) {
|
||||
fprintf(stderr, "%s: can't open %s\n", progname, argv[argn+1]);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
#else
|
||||
/* Unix style: expect zero or one file name */
|
||||
if (argn < argc-1) {
|
||||
fprintf(stderr, "%s: only one input file\n", progname);
|
||||
usage();
|
||||
}
|
||||
/* 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 ((outfile = fdopen(fileno(stdout), WRITE_BINARY)) == NULL) {
|
||||
fprintf(stderr, "%s: can't open stdout\n", progname);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
#else
|
||||
outfile = stdout;
|
||||
#endif
|
||||
#endif /* TWO_FILE_COMMANDLINE */
|
||||
|
||||
/* Collect comment text from comment_file or stdin, if necessary */
|
||||
if (comment_arg == NULL) {
|
||||
FILE * src_file;
|
||||
int c;
|
||||
|
||||
comment_arg = (char *) malloc((size_t) MAX_COM_LENGTH);
|
||||
if (comment_arg == NULL)
|
||||
ERREXIT("Insufficient memory");
|
||||
comment_length = 0;
|
||||
src_file = (comment_file != NULL ? comment_file : stdin);
|
||||
while ((c = getc(src_file)) != EOF) {
|
||||
if (comment_length >= (unsigned int) MAX_COM_LENGTH) {
|
||||
fprintf(stderr, "Comment text may not exceed %u bytes\n",
|
||||
(unsigned int) MAX_COM_LENGTH);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
comment_arg[comment_length++] = (char) c;
|
||||
}
|
||||
if (comment_file != NULL)
|
||||
fclose(comment_file);
|
||||
}
|
||||
|
||||
/* Copy JPEG headers until SOFn marker;
|
||||
* we will insert the new comment marker just before SOFn.
|
||||
* This (a) causes the new comment to appear after, rather than before,
|
||||
* existing comments; and (b) ensures that comments come after any JFIF
|
||||
* or JFXX markers, as required by the JFIF specification.
|
||||
*/
|
||||
marker = scan_JPEG_header(keep_COM);
|
||||
/* Insert the new COM marker, but only if nonempty text has been supplied */
|
||||
if (comment_length > 0) {
|
||||
write_marker(M_COM);
|
||||
write_2_bytes(comment_length + 2);
|
||||
while (comment_length > 0) {
|
||||
write_1_byte(*comment_arg++);
|
||||
comment_length--;
|
||||
}
|
||||
}
|
||||
/* Duplicate the remainder of the source file.
|
||||
* Note that any COM markers occuring after SOF will not be touched.
|
||||
*/
|
||||
write_marker(marker);
|
||||
copy_rest_of_file();
|
||||
|
||||
/* All done. */
|
||||
exit(EXIT_SUCCESS);
|
||||
return 0; /* suppress no-return-value warnings */
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue