[sane-devel] [PATCH v4 2/2] add JPEG support to scanimage
Matteo Croce
matteo at openwrt.org
Fri Sep 18 09:51:03 UTC 2015
---
fix 1 bit scans colors
doc/scanimage.man | 4 +-
frontend/Makefile.am | 2 +-
frontend/scanimage.c | 118 +++++++++++++++++++++++++++++++++++++++++++++++++--
3 files changed, 118 insertions(+), 6 deletions(-)
diff --git a/doc/scanimage.man b/doc/scanimage.man
index 387e962..480d51e 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 5adf22a..23061b3 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 77217b3..aa472d0 100644
--- a/frontend/scanimage.c
+++ b/frontend/scanimage.c
@@ -46,6 +46,10 @@
#include <png.h>
#endif
+#ifdef HAVE_LIBJPEG
+#include <jpeglib.h>
+#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
{
@@ -1339,6 +1382,12 @@ scan_it (FILE *ofp)
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)
{
@@ -1486,6 +1539,35 @@ scan_it (FILE *ofp)
}
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);
else
@@ -1556,6 +1638,12 @@ scan_it (FILE *ofp)
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
}
#if !defined(WORDS_BIGENDIAN)
@@ -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 );
@@ -1591,6 +1683,12 @@ cleanup:
free(pngbuf);
}
#endif
+#ifdef HAVE_LIBJPEG
+ if(output_format == OUTPUT_JPEG) {
+ jpeg_destroy_compress(&cinfo);
+ free(jpegbuf);
+ }
+#endif
if (image.data)
free (image.data);
@@ -1917,6 +2015,15 @@ main (int argc, char **argv)
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
output_format = OUTPUT_PNM;
break;
@@ -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\
@@ -2355,6 +2462,11 @@ List of available devices:", prog_name);
format = "out%d.png";
break;
#endif
+#ifdef HAVE_LIBJPEG
+ case OUTPUT_JPEG:
+ format = "out%d.jpg";
+ break;
+#endif
}
}
--
2.1.4
More information about the sane-devel
mailing list