• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* sane - Scanner Access Now Easy.
2 
3    Copyright (C) 2019 Thierry HUCHARD <thierry@ordissimo.com>
4 
5    This file is part of the SANE package.
6 
7    SANE is free software; you can redistribute it and/or modify it under
8    the terms of the GNU General Public License as published by the Free
9    Software Foundation; either version 3 of the License, or (at your
10    option) any later version.
11 
12    SANE is distributed in the hope that it will be useful, but WITHOUT
13    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
15    for more details.
16 
17    You should have received a copy of the GNU General Public License
18    along with sane; see the file COPYING.
19    If not, see <https://www.gnu.org/licenses/>.
20 
21    This file implements a SANE backend for eSCL scanners.  */
22 
23 #define DEBUG_DECLARE_ONLY
24 #include "../include/sane/config.h"
25 
26 #include "escl.h"
27 
28 #include "../include/sane/sanei.h"
29 
30 #include <stdlib.h>
31 #include <stdio.h>
32 #include <string.h>
33 #include <stddef.h>
34 #include <math.h>
35 
36 #include <errno.h>
37 
38 #if HAVE_POPPLER_GLIB
39 #include <poppler/glib/poppler.h>
40 #endif
41 
42 #include <setjmp.h>
43 
44 
45 #if HAVE_POPPLER_GLIB
46 
47 #define ESCL_PDF_USE_MAPPED_FILE POPPLER_CHECK_VERSION(0,82,0)
48 
49 #if ! ESCL_PDF_USE_MAPPED_FILE
50 static unsigned char*
set_file_in_buffer(FILE * fp,int * size)51 set_file_in_buffer(FILE *fp, int *size)
52 {
53 	char buffer[1024] = { 0 };
54     unsigned char *data = (unsigned char *)calloc(1, sizeof(char));
55     int nx = 0;
56 
57     while(!feof(fp))
58     {
59       int n = fread(buffer,sizeof(char),1024,fp);
60       unsigned char *t = realloc(data, nx + n + 1);
61       if (t == NULL) {
62         DBG(10, "not enough memory (realloc returned NULL)");
63         free(data);
64         return NULL;
65       }
66       data = t;
67       memcpy(&(data[nx]), buffer, n);
68       nx = nx + n;
69       data[nx] = 0;
70     }
71     *size = nx;
72     return data;
73 }
74 #endif
75 
76 static unsigned char *
cairo_surface_to_pixels(cairo_surface_t * surface,int bps)77 cairo_surface_to_pixels (cairo_surface_t *surface, int bps)
78 {
79   int cairo_width, cairo_height, cairo_rowstride;
80   unsigned char *data, *dst, *cairo_data;
81   unsigned int *src;
82   int x, y;
83 
84   cairo_width = cairo_image_surface_get_width (surface);
85   cairo_height = cairo_image_surface_get_height (surface);
86   cairo_rowstride = cairo_image_surface_get_stride (surface);
87   cairo_data = cairo_image_surface_get_data (surface);
88   data = (unsigned char*)calloc(1, sizeof(unsigned char) * (cairo_height * cairo_width * bps));
89 
90   for (y = 0; y < cairo_height; y++)
91     {
92       src = (unsigned int *) (cairo_data + y * cairo_rowstride);
93       dst = data + y * (cairo_width * bps);
94       for (x = 0; x < cairo_width; x++)
95         {
96           dst[0] = (*src >> 16) & 0xff;
97           dst[1] = (*src >> 8) & 0xff;
98           dst[2] = (*src >> 0) & 0xff;
99           dst += bps;
100           src++;
101         }
102     }
103     return data;
104 }
105 
106 SANE_Status
get_PDF_data(capabilities_t * scanner,int * width,int * height,int * bps)107 get_PDF_data(capabilities_t *scanner, int *width, int *height, int *bps)
108 {
109         cairo_surface_t *cairo_surface = NULL;
110         cairo_t *cr;
111     PopplerPage *page;
112     PopplerDocument   *doc;
113     double dw, dh;
114     int w, h;
115     unsigned char* surface = NULL;
116     SANE_Status status = SANE_STATUS_GOOD;
117 
118 #if ESCL_PDF_USE_MAPPED_FILE
119     GMappedFile *file;
120     GBytes *bytes;
121 
122     file = g_mapped_file_new_from_fd (fileno (scanner->tmp), 0, NULL);
123     if (!file) {
124                 DBG(1, "Error : g_mapped_file_new_from_fd");
125                 status =  SANE_STATUS_INVAL;
126                 goto close_file;
127         }
128 
129     bytes = g_mapped_file_get_bytes (file);
130     if (!bytes) {
131                 DBG(1, "Error : g_mapped_file_get_bytes");
132                 status =  SANE_STATUS_INVAL;
133                 goto free_file;
134         }
135 
136     doc = poppler_document_new_from_bytes (bytes, NULL, NULL);
137     if (!doc) {
138                 DBG(1, "Error : poppler_document_new_from_bytes");
139                 status =  SANE_STATUS_INVAL;
140                 goto free_bytes;
141         }
142 #else
143     int size = 0;
144     char *data = NULL;
145 
146     data = (char*)set_file_in_buffer(scanner->tmp, &size);
147     if (!data) {
148                 DBG(1, "Error : set_file_in_buffer");
149                 status =  SANE_STATUS_INVAL;
150                 goto close_file;
151         }
152 
153     doc = poppler_document_new_from_data (data, size, NULL, NULL);
154     if (!doc) {
155                 DBG(1, "Error : poppler_document_new_from_data");
156                 status =  SANE_STATUS_INVAL;
157                 goto free_data;
158         }
159 #endif
160 
161     page = poppler_document_get_page (doc, 0);
162     if (!page) {
163                 DBG(1, "Error : poppler_document_get_page");
164                 status =  SANE_STATUS_INVAL;
165                 goto free_doc;
166         }
167 
168     poppler_page_get_size (page, &dw, &dh);
169     dw = (double)scanner->caps[scanner->source].default_resolution * dw / 72.0;
170     dh = (double)scanner->caps[scanner->source].default_resolution * dh / 72.0;
171     w = (int)ceil(dw);
172     h = (int)ceil(dh);
173     cairo_surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, w, h);
174     if (!cairo_surface) {
175                 DBG(1, "Error : cairo_image_surface_create");
176                 status =  SANE_STATUS_INVAL;
177                 goto free_page;
178         }
179 
180     cr = cairo_create (cairo_surface);
181     if (!cairo_surface) {
182                 DBG(1, "Error : cairo_create");
183                 status =  SANE_STATUS_INVAL;
184                 goto free_surface;
185         }
186     cairo_scale (cr, (double)scanner->caps[scanner->source].default_resolution / 72.0,
187                      (double)scanner->caps[scanner->source].default_resolution / 72.0);
188     cairo_save (cr);
189     poppler_page_render (page, cr);
190     cairo_restore (cr);
191 
192     cairo_set_operator (cr, CAIRO_OPERATOR_DEST_OVER);
193     cairo_set_source_rgb (cr, 1, 1, 1);
194     cairo_paint (cr);
195 
196     int st = cairo_status(cr);
197     if (st)
198     {
199         DBG(1, "%s", cairo_status_to_string (st));
200                 status =  SANE_STATUS_INVAL;
201         goto destroy_cr;
202     }
203 
204     *bps = 3;
205 
206     DBG(1, "Escl Pdf : Image Size [%dx%d]\n", w, h);
207 
208     surface = cairo_surface_to_pixels (cairo_surface, *bps);
209     if (!surface)  {
210         status = SANE_STATUS_NO_MEM;
211         DBG(1, "Escl Pdf : Surface Memory allocation problem");
212         goto destroy_cr;
213     }
214 
215     // If necessary, trim the image.
216     surface = escl_crop_surface(scanner, surface, w, h, *bps, width, height);
217     if (!surface)  {
218         DBG(1, "Escl Pdf Crop: Surface Memory allocation problem");
219         status = SANE_STATUS_NO_MEM;
220     }
221 
222 destroy_cr:
223     cairo_destroy (cr);
224 free_surface:
225     cairo_surface_destroy (cairo_surface);
226 free_page:
227     g_object_unref (page);
228 free_doc:
229     g_object_unref (doc);
230 #if ESCL_PDF_USE_MAPPED_FILE
231 free_bytes:
232     g_bytes_unref (bytes);
233 free_file:
234     g_mapped_file_unref (file);
235 #else
236 free_data:
237     free(data);
238 #endif
239 close_file:
240     if (scanner->tmp)
241         fclose(scanner->tmp);
242     scanner->tmp = NULL;
243     return status;
244 }
245 #else
246 
247 SANE_Status
get_PDF_data(capabilities_t __sane_unused__ * scanner,int __sane_unused__ * width,int __sane_unused__ * height,int __sane_unused__ * bps)248 get_PDF_data(capabilities_t __sane_unused__ *scanner,
249               int __sane_unused__ *width,
250               int __sane_unused__ *height,
251               int __sane_unused__ *bps)
252 {
253 	return (SANE_STATUS_INVAL);
254 }
255 
256 #endif
257