---
 acinclude.m4         |  13 +++++
 configure.in         |   1 +
 frontend/Makefile.am |   2 +-
 frontend/scanimage.c | 137 +++++++++++++++++++++++++++++++++++++++++++++++----
 4 files changed, 143 insertions(+), 10 deletions(-)

diff --git a/acinclude.m4 b/acinclude.m4
index a8f1b7c..41a2ea4 100644
--- a/acinclude.m4
+++ b/acinclude.m4
@@ -312,6 +312,19 @@ AC_DEFUN([SANE_CHECK_TIFF],
   AC_SUBST(TIFF_LIBS)
 ])
 
+AC_DEFUN([SANE_CHECK_PNG],
+[
+  AC_CHECK_LIB(png,png_init_io,
+  [
+    AC_CHECK_HEADER(png.h,
+    [sane_cv_use_libpng="yes"; PNG_LIBS="-lpng"],)
+  ],)
+  if test "$sane_cv_use_libpng" = "yes" ; then
+    AC_DEFINE(HAVE_LIBPNG,1,[Define to 1 if you have the libpng library.])
+  fi
+  AC_SUBST(PNG_LIBS)
+])
+
 #
 # Checks for pthread support
 AC_DEFUN([SANE_CHECK_LOCKING],
diff --git a/configure.in b/configure.in
index 387c64a..56eb339 100644
--- a/configure.in
+++ b/configure.in
@@ -122,6 +122,7 @@ AC_SUBST(SYSLOG_LIBS)
 
 SANE_CHECK_JPEG
 SANE_CHECK_TIFF
+SANE_CHECK_PNG
 SANE_CHECK_IEEE1284
 SANE_CHECK_PTHREAD
 SANE_CHECK_LOCKING
diff --git a/frontend/Makefile.am b/frontend/Makefile.am
index a501931..5adf22a 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
+             ../lib/libfelib.la @PNG_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 9a84716..2449485 100644
--- a/frontend/scanimage.c
+++ b/frontend/scanimage.c
@@ -42,6 +42,10 @@
 #include <sys/types.h>
 #include <sys/stat.h>
 
+#ifdef HAVE_LIBPNG
+#include <png.h>
+#endif
+
 #include "../include/_stdint.h"
 
 #include "../include/sane/sane.h"
@@ -104,6 +108,7 @@ static struct option basic_options[] = {
 
 #define OUTPUT_PNM      0
 #define OUTPUT_TIFF     1
+#define OUTPUT_PNG      2
 
 #define BASE_OPTSTRING "d:hi:Lf:B::nvVTAbp"
 #define STRIP_HEIGHT   256     /* # lines we increment image height */
@@ -1153,6 +1158,47 @@ write_pnm_header (SANE_Frame format, int width, int 
height, int depth, FILE *ofp
 #endif
 }
 
+#ifdef HAVE_LIBPNG
+static void
+write_png_header (SANE_Frame format, int width, int height, int depth, FILE 
*ofp, png_structp* png_ptr, png_infop* info_ptr)
+{
+  int color_type;
+
+  *png_ptr = png_create_write_struct
+       (PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
+  if (!*png_ptr) {
+    fprintf(stderr, "png_create_write_struct failed\n");
+    exit(1);
+  }
+  *info_ptr = png_create_info_struct(*png_ptr);
+  if (!*info_ptr) {
+    fprintf(stderr, "png_create_info_struct failed\n");
+    exit(1);
+  }
+  png_init_io(*png_ptr, ofp);
+
+  switch (format)
+    {
+    case SANE_FRAME_RED:
+    case SANE_FRAME_GREEN:
+    case SANE_FRAME_BLUE:
+    case SANE_FRAME_RGB:
+      color_type = PNG_COLOR_TYPE_RGB;
+      break;
+
+    default:
+      color_type = PNG_COLOR_TYPE_GRAY;
+      break;
+    }
+
+  png_set_IHDR(*png_ptr, *info_ptr, width, height,
+    depth, color_type, PNG_INTERLACE_NONE,
+    PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);
+
+  png_write_info(*png_ptr, *info_ptr);
+}
+#endif
+
 static void *
 advance (Image * image)
 {
@@ -1196,6 +1242,12 @@ scan_it (FILE *ofp)
   };
   SANE_Word total_bytes = 0, expected_bytes;
   SANE_Int hang_over = -1;
+#ifdef HAVE_LIBPNG
+  int pngrow = 0;
+  png_bytep pngbuf = NULL;
+  png_structp png_ptr;
+  png_infop info_ptr;
+#endif
 
   do
     {
@@ -1219,6 +1271,7 @@ scan_it (FILE *ofp)
        }
 
       status = sane_get_parameters (device, &parm);
+
       if (status != SANE_STATUS_GOOD)
        {
          fprintf (stderr, "%s: sane_get_parameters: %s\n",
@@ -1269,21 +1322,37 @@ scan_it (FILE *ofp)
                  offset = 0;
                }
              else
-               {
-                 if (output_format == OUTPUT_TIFF)
+                 switch(output_format)
+                 {
+                 case OUTPUT_TIFF:
                    sanei_write_tiff_header (parm.format,
                                             parm.pixels_per_line, parm.lines,
                                             parm.depth, resolution_value,
                                             icc_profile, ofp);
-                 else
+                   break;
+                 case OUTPUT_PNM:
                    write_pnm_header (parm.format, parm.pixels_per_line,
                                      parm.lines, parm.depth, ofp);
-               }
+                   break;
+                 case OUTPUT_PNG:
+#ifdef HAVE_LIBPNG
+                   write_png_header (parm.format, parm.pixels_per_line,
+                                     parm.lines, parm.depth, ofp, &png_ptr, 
&info_ptr);
+#else
+                   fprintf(stderr, "PNG support not compiled in\n");
+                   exit(1);
+#endif
+                   break;
+                 }
              break;
 
             default:
              break;
            }
+#ifdef HAVE_LIBPNG
+         if(output_format == OUTPUT_PNG)
+           pngbuf = malloc(parm.bytes_per_line);
+#endif
 
          if (must_buffer)
            {
@@ -1397,7 +1466,24 @@ scan_it (FILE *ofp)
            }
          else                  /* ! must_buffer */
            {
-             if ((output_format == OUTPUT_TIFF) || (parm.depth != 16))
+             if (output_format == OUTPUT_PNG)
+               {
+#ifdef HAVE_LIBPNG
+                 int i = 0;
+                 int left = len;
+                 while(pngrow + left >= parm.bytes_per_line)
+                   {
+                     memcpy(pngbuf + pngrow, buffer + i, parm.bytes_per_line - 
pngrow);
+                     png_write_row(png_ptr, pngbuf);
+                     i += parm.bytes_per_line - pngrow;
+                     left -= parm.bytes_per_line - pngrow;
+                     pngrow = 0;
+                   }
+                 memcpy(pngbuf + pngrow, buffer + i, left);
+                 pngrow += left;
+#endif
+               }
+             else if ((output_format == OUTPUT_TIFF) || (parm.depth != 16))
                fwrite (buffer, 1, len, ofp);
              else
                {
@@ -1451,13 +1537,26 @@ scan_it (FILE *ofp)
     {
       image.height = image.y;
 
-      if (output_format == OUTPUT_TIFF)
+      switch(output_format) {
+      case OUTPUT_TIFF:
        sanei_write_tiff_header (parm.format, parm.pixels_per_line,
                                 image.height, parm.depth, resolution_value,
                                 icc_profile, ofp);
-      else
+      break;
+      case OUTPUT_PNM:
        write_pnm_header (parm.format, parm.pixels_per_line,
                           image.height, parm.depth, ofp);
+      break;
+      case OUTPUT_PNG:
+#ifdef HAVE_LIBPNG
+       write_png_header (parm.format, parm.pixels_per_line,
+                          image.height, parm.depth, ofp, &png_ptr, &info_ptr);
+#else
+       fprintf(stderr, "PNG support not compiled in\n");
+       exit(1);
+#endif
+      break;
+      }
 
 #if !defined(WORDS_BIGENDIAN)
       /* multibyte pnm file may need byte swap to LE */
@@ -1477,11 +1576,21 @@ scan_it (FILE *ofp)
 
        fwrite (image.data, 1, image.height * image.width, ofp);
     }
+#ifdef HAVE_LIBPNG
+    if(output_format == OUTPUT_PNG)
+       png_write_end(png_ptr, info_ptr);
+#endif
 
   /* flush the output buffer */
   fflush( ofp );
 
 cleanup:
+#ifdef HAVE_LIBPNG
+  if(output_format == OUTPUT_PNG) {
+    png_destroy_write_struct(&png_ptr, &info_ptr);
+    free(pngbuf);
+  }
+#endif
   if (image.data)
     free (image.data);
 
@@ -1552,6 +1661,7 @@ test_it (void)
     }
 
   status = sane_get_parameters (device, &parm);
+
   if (status != SANE_STATUS_GOOD)
     {
       fprintf (stderr, "%s: sane_get_parameters: %s\n",
@@ -1799,6 +1909,8 @@ main (int argc, char **argv)
        case OPTION_FORMAT:
          if (strcmp (optarg, "tiff") == 0)
            output_format = OUTPUT_TIFF;
+         else if (strcmp (optarg, "png") == 0)
+           output_format = OUTPUT_PNG;
          else
            output_format = OUTPUT_PNM;
          break;
@@ -2225,10 +2337,17 @@ List of available devices:", prog_name);
 
       if (batch && NULL == format)
        {
-         if (output_format == OUTPUT_TIFF)
+         switch(output_format) {
+         case OUTPUT_TIFF:
            format = "out%d.tif";
-         else
+           break;
+         case OUTPUT_PNM:
            format = "out%d.pnm";
+           break;
+         case OUTPUT_PNG:
+           format = "out%d.png";
+           break;
+         }
        }
 
       if (!batch)
-- 
2.1.4


-- 
sane-devel mailing list: sane-devel@lists.alioth.debian.org
http://lists.alioth.debian.org/cgi-bin/mailman/listinfo/sane-devel
Unsubscribe: Send mail with subject "unsubscribe your_password"
             to sane-devel-requ...@lists.alioth.debian.org

Reply via email to