[sane-devel] [PATCH 2/2] add JPEG support to scanimage

Matteo Croce matteo at openwrt.org
Thu Sep 10 15:46:24 UTC 2015


---
 frontend/Makefile.am |  2 +-
 frontend/scanimage.c | 96 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 97 insertions(+), 1 deletion(-)

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 2449485..b3717e2 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,37 @@ 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;
+  cinfo->in_color_space = JCS_RGB;
+  switch (format)
+    {
+    case SANE_FRAME_RED:
+    case SANE_FRAME_GREEN:
+    case SANE_FRAME_BLUE:
+    case SANE_FRAME_RGB:
+      cinfo->input_components = 3;
+      break;
+
+    default:
+      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 +1284,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
     {
@@ -1343,6 +1385,15 @@ scan_it (FILE *ofp)
 		    exit(1);
 #endif
 		    break;
+		  case OUTPUT_JPEG:
+#ifdef HAVE_LIBJPEG
+		    write_jpeg_header (parm.format, parm.pixels_per_line,
+				      parm.lines, ofp, &cinfo, &jerr);
+#else
+		    fprintf(stderr, "JPEG support not compiled in\n");
+		    exit(1);
+#endif
+		    break;
 		  }
 	      break;
 
@@ -1353,6 +1404,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)
 	    {
@@ -1483,6 +1538,23 @@ scan_it (FILE *ofp)
 		  pngrow += left;
 #endif
 		}
+	      if (output_format == OUTPUT_JPEG)
+	        {
+#ifdef HAVE_LIBJPEG
+		  int i = 0;
+		  int left = len;
+		  while(jpegrow + left >= parm.bytes_per_line)
+		    {
+		      memcpy(jpegbuf + jpegrow, buffer + i, parm.bytes_per_line - jpegrow);
+		      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;
+#endif
+		}
 	      else if ((output_format == OUTPUT_TIFF) || (parm.depth != 16))
 		fwrite (buffer, 1, len, ofp);
 	      else
@@ -1556,6 +1628,15 @@ scan_it (FILE *ofp)
 	exit(1);
 #endif
       break;
+      case OUTPUT_JPEG:
+#ifdef HAVE_LIBJPEG
+	write_jpeg_header (parm.format, parm.pixels_per_line,
+	parm.lines, ofp, &cinfo, &jerr);
+#else
+	fprintf(stderr, "JPEG support not compiled in\n");
+	exit(1);
+#endif
+      break;
       }
 
 #if !defined(WORDS_BIGENDIAN)
@@ -1580,6 +1661,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 +1676,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);
 
@@ -1911,6 +2002,8 @@ main (int argc, char **argv)
 	    output_format = OUTPUT_TIFF;
 	  else if (strcmp (optarg, "png") == 0)
 	    output_format = OUTPUT_PNG;
+	  else if (strcmp (optarg, "jpeg") == 0)
+	    output_format = OUTPUT_JPEG;
 	  else
 	    output_format = OUTPUT_PNM;
 	  break;
@@ -2347,6 +2440,9 @@ List of available devices:", prog_name);
 	  case OUTPUT_PNG:
 	    format = "out%d.png";
 	    break;
+	  case OUTPUT_JPEG:
+	    format = "out%d.jpg";
+	    break;
 	  }
 	}
 
-- 
2.1.4




More information about the sane-devel mailing list