#ifdef _MSC_VER
#define _CRT_SECURE_NO_DEPRECATE
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifdef _WIN32
#define strcasecmp stricmp
#define strncasecmp strnicmp
#endif
#include "jpeglib.h"
#include "jerror.h"
#include <setjmp.h>
#define WIDTH 640
#define HEIGHT 480
METHODDEF(void)
write_JPEG_file(char *filename, int quality, int data_precision)
{
struct jpeg_compress_struct cinfo;
struct jpeg_error_mgr jerr;
FILE *outfile;
JSAMPARRAY image_buffer = NULL;
JSAMPROW row_pointer[1];
J12SAMPARRAY image_buffer12 = NULL;
J12SAMPROW row_pointer12[1];
int row_stride;
int row, col;
cinfo.err = jpeg_std_error(&jerr);
jpeg_create_compress(&cinfo);
if ((outfile = fopen(filename, "wb")) == NULL)
ERREXIT(&cinfo, JERR_FILE_WRITE);
jpeg_stdio_dest(&cinfo, outfile);
cinfo.image_width = WIDTH;
cinfo.image_height = HEIGHT;
cinfo.input_components = 3;
cinfo.in_color_space = JCS_RGB;
cinfo.data_precision = data_precision;
jpeg_set_defaults(&cinfo);
jpeg_set_quality(&cinfo, quality, TRUE );
cinfo.comp_info[0].h_samp_factor = cinfo.comp_info[0].v_samp_factor = 1;
jpeg_start_compress(&cinfo, TRUE);
row_stride = WIDTH * 3;
if (cinfo.data_precision == 12) {
image_buffer12 = (J12SAMPARRAY)(*cinfo.mem->alloc_sarray)
((j_common_ptr)&cinfo, JPOOL_IMAGE, row_stride, HEIGHT);
for (row = 0; row < HEIGHT; row++) {
for (col = 0; col < WIDTH; col++) {
image_buffer12[row][col * 3] =
(col * (MAXJ12SAMPLE + 1) / WIDTH) % (MAXJ12SAMPLE + 1);
image_buffer12[row][col * 3 + 1] =
(row * (MAXJ12SAMPLE + 1) / HEIGHT) % (MAXJ12SAMPLE + 1);
image_buffer12[row][col * 3 + 2] =
(row * (MAXJ12SAMPLE + 1) / HEIGHT +
col * (MAXJ12SAMPLE + 1) / WIDTH) % (MAXJ12SAMPLE + 1);
}
}
} else {
image_buffer = (*cinfo.mem->alloc_sarray)
((j_common_ptr)&cinfo, JPOOL_IMAGE, row_stride, HEIGHT);
for (row = 0; row < HEIGHT; row++) {
for (col = 0; col < WIDTH; col++) {
image_buffer[row][col * 3] =
(col * (MAXJSAMPLE + 1) / WIDTH) % (MAXJSAMPLE + 1);
image_buffer[row][col * 3 + 1] =
(row * (MAXJSAMPLE + 1) / HEIGHT) % (MAXJSAMPLE + 1);
image_buffer[row][col * 3 + 2] =
(row * (MAXJSAMPLE + 1) / HEIGHT + col * (MAXJSAMPLE + 1) / WIDTH) %
(MAXJSAMPLE + 1);
}
}
}
if (cinfo.data_precision == 12) {
while (cinfo.next_scanline < cinfo.image_height) {
row_pointer12[0] = image_buffer12[cinfo.next_scanline];
(void)jpeg12_write_scanlines(&cinfo, row_pointer12, 1);
}
} else {
while (cinfo.next_scanline < cinfo.image_height) {
row_pointer[0] = image_buffer[cinfo.next_scanline];
(void)jpeg_write_scanlines(&cinfo, row_pointer, 1);
}
}
jpeg_finish_compress(&cinfo);
fclose(outfile);
jpeg_destroy_compress(&cinfo);
}
struct my_error_mgr {
struct jpeg_error_mgr pub;
jmp_buf setjmp_buffer;
};
typedef struct my_error_mgr *my_error_ptr;
METHODDEF(void)
my_error_exit(j_common_ptr cinfo)
{
my_error_ptr myerr = (my_error_ptr)cinfo->err;
(*cinfo->err->output_message) (cinfo);
longjmp(myerr->setjmp_buffer, 1);
}
METHODDEF(int) do_read_JPEG_file(struct jpeg_decompress_struct *cinfo,
char *infilename, char *outfilename);
METHODDEF(int)
read_JPEG_file(char *infilename, char *outfilename)
{
struct jpeg_decompress_struct cinfo;
return do_read_JPEG_file(&cinfo, infilename, outfilename);
}
METHODDEF(int)
do_read_JPEG_file(struct jpeg_decompress_struct *cinfo, char *infilename,
char *outfilename)
{
struct my_error_mgr jerr;
FILE *infile;
FILE *outfile;
JSAMPARRAY buffer = NULL;
J12SAMPARRAY buffer12 = NULL;
int col;
int row_stride;
int little_endian = 1;
if ((infile = fopen(infilename, "rb")) == NULL) {
fprintf(stderr, "can't open %s\n", infilename);
return 0;
}
if ((outfile = fopen(outfilename, "wb")) == NULL) {
fprintf(stderr, "can't open %s\n", outfilename);
fclose(infile);
return 0;
}
cinfo->err = jpeg_std_error(&jerr.pub);
jerr.pub.error_exit = my_error_exit;
if (setjmp(jerr.setjmp_buffer)) {
jpeg_destroy_decompress(cinfo);
fclose(infile);
fclose(outfile);
return 0;
}
jpeg_create_decompress(cinfo);
jpeg_stdio_src(cinfo, infile);
(void)jpeg_read_header(cinfo, TRUE);
fprintf(outfile, "P6\n%u %u\n%d\n", cinfo->image_width, cinfo->image_height,
cinfo->data_precision == 12 ? MAXJ12SAMPLE : MAXJSAMPLE);
(void)jpeg_start_decompress(cinfo);
row_stride = cinfo->output_width * cinfo->output_components;
if (cinfo->data_precision == 12)
buffer12 = (J12SAMPARRAY)(*cinfo->mem->alloc_sarray)
((j_common_ptr)cinfo, JPOOL_IMAGE, row_stride, 1);
else
buffer = (*cinfo->mem->alloc_sarray)
((j_common_ptr)cinfo, JPOOL_IMAGE, row_stride, 1);
if (cinfo->data_precision == 12) {
while (cinfo->output_scanline < cinfo->output_height) {
(void)jpeg12_read_scanlines(cinfo, buffer12, 1);
if (*(char *)&little_endian == 1) {
for (col = 0; col < row_stride; col++)
buffer12[0][col] = ((buffer12[0][col] & 0xFF) << 8) |
((buffer12[0][col] >> 8) & 0xFF);
}
fwrite(buffer12[0], 1, row_stride * sizeof(J12SAMPLE), outfile);
}
} else {
while (cinfo->output_scanline < cinfo->output_height) {
(void)jpeg_read_scanlines(cinfo, buffer, 1);
fwrite(buffer[0], 1, row_stride, outfile);
}
}
(void)jpeg_finish_decompress(cinfo);
jpeg_destroy_decompress(cinfo);
fclose(infile);
fclose(outfile);
return 1;
}
LOCAL(void)
usage(const char *progname)
{
fprintf(stderr, "usage: %s compress [switches] outputfile[.jpg]\n",
progname);
fprintf(stderr, " %s decompress inputfile[.jpg] outputfile[.ppm]\n",
progname);
fprintf(stderr, "Switches (names may be abbreviated):\n");
fprintf(stderr, " -precision N Create JPEG file with N-bit data precision\n");
fprintf(stderr, " (N is 8 or 12; default is 8)\n");
fprintf(stderr, " -quality N Compression quality (0..100; 5-95 is most useful range,\n");
fprintf(stderr, " default is 75)\n");
exit(EXIT_FAILURE);
}
typedef enum {
COMPRESS,
DECOMPRESS
} EXAMPLE_MODE;
int
main(int argc, char **argv)
{
int argn, quality = 75;
int data_precision = 8;
EXAMPLE_MODE mode = -1;
char *arg, *filename = NULL;
if (argc < 3)
usage(argv[0]);
if (!strcasecmp(argv[1], "compress"))
mode = COMPRESS;
else if (!strcasecmp(argv[1], "decompress"))
mode = DECOMPRESS;
else
usage(argv[0]);
for (argn = 2; argn < argc; argn++) {
arg = argv[argn];
if (*arg != '-') {
filename = arg;
break;
}
arg++;
if (!strncasecmp(arg, "p", 1)) {
if (++argn >= argc)
usage(argv[0]);
if (sscanf(argv[argn], "%d", &data_precision) < 1 ||
(data_precision != 8 && data_precision != 12))
usage(argv[0]);
} else if (!strncasecmp(arg, "q", 1)) {
if (++argn >= argc)
usage(argv[0]);
if (sscanf(argv[argn], "%d", &quality) < 1 || quality < 0 ||
quality > 100)
usage(argv[0]);
if (quality < 1)
quality = 1;
}
}
if (!filename)
usage(argv[0]);
if (mode == COMPRESS)
write_JPEG_file(filename, quality, data_precision);
else if (mode == DECOMPRESS) {
if (argc - argn < 2)
usage(argv[0]);
read_JPEG_file(argv[argn], argv[argn + 1]);
}
return 0;
}