Hi Matteo,

I also reviewed and tested this in more detail.  The PNG remarks hold
here as well and the 1-bit output is inverted.

In addition, during testing I used --format=jpg which a bit to my
surprise led to a PNM image.  I know that was my fault but I thought
that recognizing this common three letter variant could be supported
rather easily.

Finally, the documentation for the --batch option uses 'out%d.png'
twice.  The code uses 'out%d.jpg', without the 'e' ;-)

Could you fix this too?

Matteo Croce writes:

> ---
> exit with error immediately if JPEG support is not compiled in
> upscale for 1 bit depth scans to 8 bit gray
>
>  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 jpeg.
>  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 8445b53..9ce4368 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)
>           {
> @@ -1480,6 +1533,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)) ? 0xff : 0;
> +                       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
> @@ -1550,6 +1632,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)
> @@ -1574,6 +1662,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 );
> @@ -1585,6 +1677,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 +2009,15 @@ main (int argc, char **argv)
>             exit(1);
>  #endif
>           }
> +       else if (strcmp (optarg, "jpeg") == 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;
> @@ -2049,7 +2156,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|jpeg  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\
> @@ -2057,8 +2164,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.png' 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\
> @@ -2349,6 +2456,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

-- 
Olaf Meeuwissen, LPIC-2            FSF Associate Member since 2004-01-27
Support Free Software               Support the Free Software Foundation
https://my.fsf.org/donate                        https://my.fsf.org/join


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