--- 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