summaryrefslogtreecommitdiff
path: root/backend/escl/escl_png.c
diff options
context:
space:
mode:
Diffstat (limited to 'backend/escl/escl_png.c')
-rw-r--r--backend/escl/escl_png.c193
1 files changed, 193 insertions, 0 deletions
diff --git a/backend/escl/escl_png.c b/backend/escl/escl_png.c
new file mode 100644
index 0000000..18f6f35
--- /dev/null
+++ b/backend/escl/escl_png.c
@@ -0,0 +1,193 @@
+/* sane - Scanner Access Now Easy.
+
+ Copyright (C) 2019 Touboul Nathane
+ Copyright (C) 2019 Thierry HUCHARD <thierry@ordissimo.com>
+
+ This file is part of the SANE package.
+
+ SANE is free software; you can redistribute it and/or modify it under
+ the terms of the GNU General Public License as published by the Free
+ Software Foundation; either version 3 of the License, or (at your
+ option) any later version.
+
+ SANE is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with sane; see the file COPYING. If not, write to the Free
+ Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ This file implements a SANE backend for eSCL scanners. */
+
+#define DEBUG_DECLARE_ONLY
+#include "../include/sane/config.h"
+
+#include "escl.h"
+
+#include "../include/sane/sanei.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#if(defined HAVE_LIBPNG)
+#include <png.h>
+#endif
+
+#include <setjmp.h>
+
+
+#if(defined HAVE_LIBPNG)
+
+/**
+ * \fn SANE_Status escl_sane_decompressor(escl_sane_t *handler)
+ * \brief Function that aims to decompress the png image to SANE be able to read the image.
+ * This function is called in the "sane_read" function.
+ *
+ * \return SANE_STATUS_GOOD (if everything is OK, otherwise, SANE_STATUS_NO_MEM/SANE_STATUS_INVAL)
+ */
+SANE_Status
+get_PNG_data(capabilities_t *scanner, int *w, int *h, int *components)
+{
+ unsigned int width = 0; /* largeur */
+ unsigned int height = 0; /* hauteur */
+ int bps = 3; /* composantes d'un texel */
+ unsigned char *texels = NULL; /* données de l'image */
+ unsigned int i = 0;
+ png_byte magic[8];
+
+ // read magic number
+ fread (magic, 1, sizeof (magic), scanner->tmp);
+ // check for valid magic number
+ if (!png_check_sig (magic, sizeof (magic)))
+ {
+ DBG( 1, "Escl Png : PNG error is not a valid PNG image!\n");
+ if (scanner->tmp) {
+ fclose(scanner->tmp);
+ scanner->tmp = NULL;
+ }
+ return (SANE_STATUS_INVAL);
+ }
+ // create a png read struct
+ png_structp png_ptr = png_create_read_struct
+ (PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
+ if (!png_ptr)
+ {
+ DBG( 1, "Escl Png : PNG error create a png read struct\n");
+ if (scanner->tmp)
+ if (scanner->tmp) {
+ fclose(scanner->tmp);
+ scanner->tmp = NULL;
+ }
+ return (SANE_STATUS_INVAL);
+ }
+ // create a png info struct
+ png_infop info_ptr = png_create_info_struct (png_ptr);
+ if (!info_ptr)
+ {
+ DBG( 1, "Escl Png : PNG error create a png info struct\n");
+ png_destroy_read_struct (&png_ptr, NULL, NULL);
+ if (scanner->tmp) {
+ fclose(scanner->tmp);
+ scanner->tmp = NULL;
+ }
+ return (SANE_STATUS_INVAL);
+ }
+ // initialize the setjmp for returning properly after a libpng
+ // error occured
+ if (setjmp (png_jmpbuf (png_ptr)))
+ {
+ png_destroy_read_struct (&png_ptr, &info_ptr, NULL);
+ if (texels)
+ free (texels);
+ fprintf(stderr,"PNG read error.\n");
+ if (scanner->tmp) {
+ fclose(scanner->tmp);
+ scanner->tmp = NULL;
+ }
+ DBG( 1, "Escl Png : PNG read error.\n");
+ return (SANE_STATUS_INVAL);
+ }
+ // setup libpng for using standard C fread() function
+ // with our FILE pointer
+ png_init_io (png_ptr, scanner->tmp);
+ // tell libpng that we have already read the magic number
+ png_set_sig_bytes (png_ptr, sizeof (magic));
+
+ // read png info
+ png_read_info (png_ptr, info_ptr);
+
+ int bit_depth, color_type;
+ // get some usefull information from header
+ bit_depth = png_get_bit_depth (png_ptr, info_ptr);
+ color_type = png_get_color_type (png_ptr, info_ptr);
+ // convert index color images to RGB images
+ if (color_type == PNG_COLOR_TYPE_PALETTE)
+ png_set_palette_to_rgb (png_ptr);
+ else if (color_type != PNG_COLOR_TYPE_RGB && color_type != PNG_COLOR_TYPE_RGB_ALPHA)
+ {
+ fprintf(stderr,"PNG format not supported.\n");
+ if (scanner->tmp) {
+ fclose(scanner->tmp);
+ scanner->tmp = NULL;
+ }
+ return (SANE_STATUS_INVAL);
+ }
+ if (color_type == PNG_COLOR_TYPE_RGB_ALPHA)
+ bps = 4;
+ else
+ bps = 3;
+ if (png_get_valid (png_ptr, info_ptr, PNG_INFO_tRNS))
+ png_set_tRNS_to_alpha (png_ptr);
+ if (bit_depth == 16)
+ png_set_strip_16 (png_ptr);
+ else if (bit_depth < 8)
+ png_set_packing (png_ptr);
+ // update info structure to apply transformations
+ png_read_update_info (png_ptr, info_ptr);
+ // retrieve updated information
+ png_get_IHDR (png_ptr, info_ptr,
+ (png_uint_32*)(&width),
+ (png_uint_32*)(&height),
+ &bit_depth, &color_type,
+ NULL, NULL, NULL);
+
+ *w = (int)width;
+ *h = (int)height;
+ *components = bps;
+ // we can now allocate memory for storing pixel data
+ texels = (unsigned char *)malloc (sizeof (unsigned char) * width
+ * height * bps);
+ png_bytep *row_pointers;
+ // setup a pointer array. Each one points at the begening of a row.
+ row_pointers = (png_bytep *)malloc (sizeof (png_bytep) * height);
+ for (i = 0; i < height; ++i)
+ {
+ row_pointers[i] = (png_bytep)(texels +
+ ((height - (i + 1)) * width * bps));
+ }
+ // read pixel data using row pointers
+ png_read_image (png_ptr, row_pointers);
+ // we don't need row pointers anymore
+ scanner->img_data = texels;
+ scanner->img_size = (int)(width * height * bps);
+ scanner->img_read = 0;
+ free (row_pointers);
+ fclose(scanner->tmp);
+ scanner->tmp = NULL;
+ return (SANE_STATUS_GOOD);
+}
+#else
+
+SANE_Status
+get_PNG_data(capabilities_t __sane_unused__ *scanner,
+ int __sane_unused__ *w,
+ int __sane_unused__ *h,
+ int __sane_unused__ *bps)
+{
+ return (SANE_STATUS_INVAL);
+}
+
+#endif