1 /* sane - Scanner Access Now Easy.
2 
3    Copyright (C) 2020 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 #include <stdio.h>
28 #include <stdlib.h>
29 #include <string.h>
30 
31 unsigned char *
escl_crop_surface(capabilities_t *scanner, unsigned char *surface, int w, int h, int bps, int *width, int *height)32 escl_crop_surface(capabilities_t *scanner,
33                unsigned char *surface,
34 	       int w,
35 	       int h,
36 	       int bps,
37 	       int *width,
38 	       int *height)
39 {
40     double ratio = 1.0;
41     int x_off = 0, x = 0;
42     int real_w = 0;
43     int y_off = 0, y = 0;
44     int real_h = 0;
45     unsigned char *surface_crop = NULL;
46 
47     DBG( 1, "Escl Image Crop\n");
48     ratio = (double)w / (double)scanner->caps[scanner->source].width;
49     scanner->caps[scanner->source].width = w;
50     if (scanner->caps[scanner->source].pos_x < 0)
51        scanner->caps[scanner->source].pos_x = 0;
52     if (scanner->caps[scanner->source].pos_x &&
53         (scanner->caps[scanner->source].width >
54         scanner->caps[scanner->source].pos_x))
55        x_off = (int)((double)scanner->caps[scanner->source].pos_x * ratio);
56     real_w = scanner->caps[scanner->source].width - x_off;
57 
58     scanner->caps[scanner->source].height = h;
59     if (scanner->caps[scanner->source].pos_y &&
60         (scanner->caps[scanner->source].height >
61         scanner->caps[scanner->source].pos_y))
62        y_off = (int)((double)scanner->caps[scanner->source].pos_y * ratio);
63     real_h = scanner->caps[scanner->source].height - y_off;
64 
65     DBG( 1, "Escl Image Crop [%dx%d|%dx%d]\n", scanner->caps[scanner->source].pos_x, scanner->caps[scanner->source].pos_y,
66 		    scanner->caps[scanner->source].width, scanner->caps[scanner->source].height);
67 
68     *width = real_w;
69     *height = real_h;
70     DBG( 1, "Escl Image Crop [%dx%d]\n", *width, *height);
71     if (x_off > 0 || real_w < scanner->caps[scanner->source].width ||
72         y_off > 0 || real_h < scanner->caps[scanner->source].height) {
73           surface_crop = (unsigned char *)malloc (sizeof (unsigned char) * real_w
74                      * real_h * bps);
75 	  if(!surface_crop) {
76              DBG( 1, "Escl Crop : Surface_crop Memory allocation problem\n");
77 	     free(surface);
78 	     surface = NULL;
79 	     goto finish;
80 	  }
81           for (y = 0; y < real_h; y++)
82           {
83              for (x = 0; x < real_w; x++)
84              {
85                 surface_crop[(y * real_w * bps) + (x * bps)] =
86                    surface[((y + y_off) * w  * bps) + ((x + x_off) * bps)];
87                 surface_crop[(y * real_w * bps) + (x * bps) + 1] =
88 	           surface[((y + y_off) * w  * bps) + ((x + x_off) * bps) + 1];
89 	        surface_crop[(y * real_w * bps) + (x * bps) + 2] =
90 	           surface[((y + y_off) * w  * bps) + ((x + x_off) * bps) + 2];
91              }
92           }
93           free(surface);
94 	  surface = surface_crop;
95     }
96     // we don't need row pointers anymore
97     scanner->img_data = surface;
98     scanner->img_size = (int)(real_w * real_h * bps);
99     scanner->img_read = 0;
100 finish:
101     return surface;
102 }
103