diff --git a/doc/scanimage.man b/doc/scanimage.man index 387e9625c..b89fed85c 100644 --- a/doc/scanimage.man +++ b/doc/scanimage.man @@ -103,9 +103,9 @@ The option selects how image data is written to standard output. .I format can be -.B pnm tiff +.B pnm tiff png or -.BR png. +.BR jpg. If .B \-\-format is not used, PNM is written. diff --git a/frontend/Makefile.am b/frontend/Makefile.am index 5adf22a59..23061b358 100644 --- a/frontend/Makefile.am +++ b/frontend/Makefile.am @@ -18,7 +18,7 @@ AM_CPPFLAGS = -I. -I$(srcdir) -I$(top_builddir)/include -I$(top_srcdir)/include scanimage_SOURCES = scanimage.c stiff.c stiff.h scanimage_LDADD = ../backend/libsane.la ../sanei/libsanei.la ../lib/liblib.la \ - ../lib/libfelib.la @PNG_LIBS@ + ../lib/libfelib.la @PNG_LIBS@ @JPEG_LIBS@ saned_SOURCES = saned.c saned_LDADD = ../backend/libsane.la ../sanei/libsanei.la ../lib/liblib.la \ diff --git a/frontend/scanimage.c b/frontend/scanimage.c index 77217b3b6..aa472d0e8 100644 --- a/frontend/scanimage.c +++ b/frontend/scanimage.c @@ -46,6 +46,10 @@ #include #endif +#ifdef HAVE_LIBJPEG +#include +#endif + #include "../include/_stdint.h" #include "../include/sane/sane.h" @@ -109,6 +113,7 @@ static struct option basic_options[] = { #define OUTPUT_PNM 0 #define OUTPUT_TIFF 1 #define OUTPUT_PNG 2 +#define OUTPUT_JPEG 3 #define BASE_OPTSTRING "d:hi:Lf:B::nvVTAbp" #define STRIP_HEIGHT 256 /* # lines we increment image height */ @@ -1199,6 +1204,38 @@ write_png_header (SANE_Frame format, int width, int height, int depth, FILE *ofp } #endif +#ifdef HAVE_LIBJPEG +static void +write_jpeg_header (SANE_Frame format, int width, int height, FILE *ofp, struct jpeg_compress_struct *cinfo, struct jpeg_error_mgr *jerr) +{ + cinfo->err = jpeg_std_error(jerr); + jpeg_create_compress(cinfo); + jpeg_stdio_dest(cinfo, ofp); + + cinfo->image_width = width; + cinfo->image_height = height; + switch (format) + { + case SANE_FRAME_RED: + case SANE_FRAME_GREEN: + case SANE_FRAME_BLUE: + case SANE_FRAME_RGB: + cinfo->in_color_space = JCS_RGB; + cinfo->input_components = 3; + break; + + default: + cinfo->in_color_space = JCS_GRAYSCALE; + cinfo->input_components = 1; + break; + } + + jpeg_set_defaults(cinfo); + jpeg_set_quality(cinfo, 75, TRUE); + jpeg_start_compress(cinfo, TRUE); +} +#endif + static void * advance (Image * image) { @@ -1248,6 +1285,12 @@ scan_it (FILE *ofp) png_structp png_ptr; png_infop info_ptr; #endif +#ifdef HAVE_LIBJPEG + int jpegrow = 0; + JSAMPLE *jpegbuf = NULL; + struct jpeg_compress_struct cinfo; + struct jpeg_error_mgr jerr; +#endif do { @@ -1338,6 +1381,12 @@ scan_it (FILE *ofp) write_png_header (parm.format, parm.pixels_per_line, parm.lines, parm.depth, ofp, &png_ptr, &info_ptr); break; +#endif +#ifdef HAVE_LIBJPEG + case OUTPUT_JPEG: + write_jpeg_header (parm.format, parm.pixels_per_line, + parm.lines, ofp, &cinfo, &jerr); + break; #endif } break; @@ -1349,6 +1398,10 @@ scan_it (FILE *ofp) if(output_format == OUTPUT_PNG) pngbuf = malloc(parm.bytes_per_line); #endif +#ifdef HAVE_LIBJPEG + if(output_format == OUTPUT_JPEG) + jpegbuf = malloc(parm.bytes_per_line); +#endif if (must_buffer) { @@ -1485,6 +1538,35 @@ scan_it (FILE *ofp) pngrow += left; } else +#endif +#ifdef HAVE_LIBJPEG + if (output_format == OUTPUT_JPEG) + { + int i = 0; + int left = len; + while(jpegrow + left >= parm.bytes_per_line) + { + memcpy(jpegbuf + jpegrow, buffer + i, parm.bytes_per_line - jpegrow); + if(parm.depth == 1) + { + int col1, col8; + JSAMPLE *buf8 = malloc(parm.bytes_per_line * 8); + for(col1 = 0; col1 < parm.bytes_per_line; col1++) + for(col8 = 0; col8 < 8; col8++) + buf8[col1 * 8 + col8] = jpegbuf[col1] & (1 << (8 - col8 - 1)) ? 0 : 0xff; + jpeg_write_scanlines(&cinfo, &buf8, 1); + free(buf8); + } else { + jpeg_write_scanlines(&cinfo, &jpegbuf, 1); + } + i += parm.bytes_per_line - jpegrow; + left -= parm.bytes_per_line - jpegrow; + jpegrow = 0; + } + memcpy(jpegbuf + jpegrow, buffer + i, left); + jpegrow += left; + } + else #endif if ((output_format == OUTPUT_TIFF) || (parm.depth != 16)) fwrite (buffer, 1, len, ofp); @@ -1555,6 +1637,12 @@ scan_it (FILE *ofp) write_png_header (parm.format, parm.pixels_per_line, image.height, parm.depth, ofp, &png_ptr, &info_ptr); break; +#endif +#ifdef HAVE_LIBJPEG + case OUTPUT_JPEG: + write_jpeg_header (parm.format, parm.pixels_per_line, + parm.lines, ofp, &cinfo, &jerr); + break; #endif } @@ -1580,6 +1668,10 @@ scan_it (FILE *ofp) if(output_format == OUTPUT_PNG) png_write_end(png_ptr, info_ptr); #endif +#ifdef HAVE_LIBJPEG + if(output_format == OUTPUT_JPEG) + jpeg_finish_compress(&cinfo); +#endif /* flush the output buffer */ fflush( ofp ); @@ -1590,6 +1682,12 @@ cleanup: png_destroy_write_struct(&png_ptr, &info_ptr); free(pngbuf); } +#endif +#ifdef HAVE_LIBJPEG + if(output_format == OUTPUT_JPEG) { + jpeg_destroy_compress(&cinfo); + free(jpegbuf); + } #endif if (image.data) free (image.data); @@ -1915,6 +2013,15 @@ main (int argc, char **argv) #else fprintf(stderr, "PNG support not compiled in\n"); exit(1); +#endif + } + else if (strcmp (optarg, "jpg") == 0) + { +#ifdef HAVE_LIBJPEG + output_format = OUTPUT_JPEG; +#else + fprintf(stderr, "JPEG support not compiled in\n"); + exit(1); #endif } else @@ -2055,7 +2162,7 @@ standard output.\n\ Parameters are separated by a blank from single-character options (e.g.\n\ -d epson) and by a \"=\" from multi-character options (e.g. --device-name=epson).\n\ -d, --device-name=DEVICE use a given scanner device (e.g. hp:/dev/scanner)\n\ - --format=pnm|tiff|png file format of output file\n\ + --format=pnm|tiff|png|jpg file format of output file\n\ -i, --icc-profile=PROFILE include this ICC profile into TIFF file\n", prog_name); printf ("\ -L, --list-devices show available scanner devices\n\ @@ -2063,8 +2170,8 @@ Parameters are separated by a blank from single-character options (e.g.\n\ can be specified: %%d (device name), %%v (vendor),\n\ %%m (model), %%t (type), %%i (index number), and\n\ %%n (newline)\n\ --b, --batch[=FORMAT] working in batch mode, FORMAT is `out%%d.pnm' `out%%d.tif' or\n\ - `out%%d.png' by default depending on --format\n"); +-b, --batch[=FORMAT] working in batch mode, FORMAT is `out%%d.pnm' `out%%d.tif'\n\ + `out%%d.png' or `out%%d.jpg' by default depending on --format\n"); printf ("\ --batch-start=# page number to start naming files with\n\ --batch-count=# how many pages to scan in batch mode\n\ @@ -2354,6 +2461,11 @@ List of available devices:", prog_name); case OUTPUT_PNG: format = "out%d.png"; break; +#endif +#ifdef HAVE_LIBJPEG + case OUTPUT_JPEG: + format = "out%d.jpg"; + break; #endif } }