• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * epsonds-jpeg.c - Epson ESC/I-2 driver, JPEG support.
3  *
4  * Copyright (C) 2015 Tower Technologies
5  * Author: Alessandro Zummo <a.zummo@towertech.it>
6  *
7  * This file is part of the SANE package.
8  *
9  * This program is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU General Public License as
11  * published by the Free Software Foundation, version 2.
12  */
13 
14 #define DEBUG_DECLARE_ONLY
15 
16 #include "sane/config.h"
17 
18 #include <math.h>
19 
20 #include "epsonds.h"
21 #include "epsonds-jpeg.h"
22 #include "epsonds-ops.h"
23 #include <setjmp.h>
24 
25 struct my_error_mgr {
26   struct jpeg_error_mgr pub;
27   jmp_buf setjmp_buffer;
28 };
29 
30 typedef struct my_error_mgr * my_error_ptr;
31 
32 
my_error_exit(j_common_ptr cinfo)33 METHODDEF(void) my_error_exit (j_common_ptr cinfo)
34 {
35 
36 	char buffer[JMSG_LENGTH_MAX];
37 	(*cinfo->err->format_message) (cinfo, buffer);
38 
39 	DBG(10,"Jpeg decode error [%s]", buffer);
40 }
41 
jpeg_custom_error(struct my_error_mgr * err)42 LOCAL(struct jpeg_error_mgr *) jpeg_custom_error (struct my_error_mgr * err)
43 {
44 
45 	struct jpeg_error_mgr* pRet  = jpeg_std_error(&(err->pub));
46 	err->pub.error_exit = my_error_exit;
47 
48 	return pRet;
49 }
50 
51 typedef struct
52 {
53 	struct jpeg_source_mgr pub;
54 	JOCTET *buffer;
55 	int length;
56 }
57 epsonds_src_mgr;
58 
59 METHODDEF(void)
jpeg_init_source(j_decompress_ptr __sane_unused__ cinfo)60 jpeg_init_source(j_decompress_ptr __sane_unused__ cinfo)
61 {
62 }
63 
64 METHODDEF(void)
jpeg_term_source(j_decompress_ptr __sane_unused__ cinfo)65 jpeg_term_source(j_decompress_ptr __sane_unused__ cinfo)
66 {
67 }
68 
69 METHODDEF(boolean)
jpeg_fill_input_buffer(j_decompress_ptr cinfo)70 jpeg_fill_input_buffer(j_decompress_ptr cinfo)
71 {
72 	epsonds_src_mgr *src = (epsonds_src_mgr *)cinfo->src;
73 	/* read from scanner if no data? */
74 
75 	src->pub.next_input_byte = src->buffer;
76 	src->pub.bytes_in_buffer = src->length;
77 	DBG(18, "reading from ring buffer, %d left\n",  src->length);
78 
79 	return TRUE;
80 }
81 
82 METHODDEF (void)
jpeg_skip_input_data(j_decompress_ptr cinfo,long num_bytes)83 jpeg_skip_input_data(j_decompress_ptr cinfo, long num_bytes)
84 {
85 	epsonds_src_mgr *src = (epsonds_src_mgr *)cinfo->src;
86 
87 	if (num_bytes > 0) {
88 
89 		while (num_bytes > (long)src->pub.bytes_in_buffer) {
90 			num_bytes -= (long)src->pub.bytes_in_buffer;
91 			jpeg_fill_input_buffer(cinfo);
92 		}
93 
94 		src->pub.next_input_byte += (size_t) num_bytes;
95 		src->pub.bytes_in_buffer -= (size_t) num_bytes;
96 	}
97 }
98 
99 
eds_decode_jpeg(epsonds_scanner * s,SANE_Byte * data,SANE_Int size,ring_buffer * ringBuffer,SANE_Int isBackSide,SANE_Int needToConvertBW)100 void eds_decode_jpeg(epsonds_scanner*s, SANE_Byte *data, SANE_Int size, ring_buffer* ringBuffer, SANE_Int isBackSide, SANE_Int needToConvertBW)
101 {
102     struct jpeg_decompress_struct jpeg_cinfo;
103    	struct my_error_mgr jpeg_err;
104 
105     {
106         epsonds_src_mgr *src;
107 
108         jpeg_cinfo.err = jpeg_custom_error(&jpeg_err);
109 
110         jpeg_create_decompress(&jpeg_cinfo);
111 
112         jpeg_cinfo.src = (struct jpeg_source_mgr *)(*jpeg_cinfo.mem->alloc_small)((j_common_ptr)&jpeg_cinfo,
113                             JPOOL_PERMANENT, sizeof(epsonds_src_mgr));
114 
115         memset(jpeg_cinfo.src, 0x00, sizeof(epsonds_src_mgr));
116 ;
117     	src = (epsonds_src_mgr *)jpeg_cinfo.src;
118         src->pub.init_source = jpeg_init_source;
119         src->pub.fill_input_buffer = jpeg_fill_input_buffer;
120         src->pub.skip_input_data = jpeg_skip_input_data;
121         src->pub.resync_to_restart = jpeg_resync_to_restart;
122         src->pub.term_source = jpeg_term_source;
123         src->pub.bytes_in_buffer = 0;
124         src->pub.next_input_byte = NULL;
125 		src->buffer = (JOCTET*)data;
126 		src->length = size;
127     }
128     {
129 	    if (jpeg_read_header(&jpeg_cinfo, TRUE)) {
130 
131 		if (jpeg_start_decompress(&jpeg_cinfo)) {
132 
133 			DBG(10,"%s: w: %d, h: %d, components: %d\n",
134 				__func__,
135 				jpeg_cinfo.output_width, jpeg_cinfo.output_height,
136 				jpeg_cinfo.output_components);
137 		}
138         }
139     }
140     {
141 		int sum = 0;
142         int bufSize = jpeg_cinfo.output_width * jpeg_cinfo.output_components;
143 
144 		int monoBufSize = (jpeg_cinfo.output_width + 7)/8;
145 
146         JSAMPARRAY scanlines = (jpeg_cinfo.mem->alloc_sarray)((j_common_ptr)&jpeg_cinfo, JPOOL_IMAGE, bufSize, 1);
147         while (jpeg_cinfo.output_scanline < jpeg_cinfo.output_height) {
148             int l = jpeg_read_scanlines(&jpeg_cinfo, scanlines, 1);
149             if (l == 0) {
150                 break;
151             }
152 			sum += l;
153 
154 			if (needToConvertBW)
155 			{
156 				SANE_Byte* bytes = scanlines[0];
157 
158 				SANE_Int imgPos = 0;
159 
160 				for (int i = 0; i < monoBufSize; i++)
161 				{
162 					SANE_Byte outByte = 0;
163 
164                     for(SANE_Int bitIndex = 0; bitIndex < 8 && imgPos < bufSize; bitIndex++) {
165 						//DBG(10,"bytes[imgPos] = %d\n", bytes[imgPos]);
166 
167                          if(bytes[imgPos] >= 110) {
168                                SANE_Byte bit = 7 - (bitIndex % 8);
169                                outByte     |= (1<< bit);
170                          }
171 						 imgPos += 1;
172                   	 }
173 						//DBG(10,"outByte = %d\n", outByte);
174 					eds_ring_write(ringBuffer, &outByte, 1);
175 				}
176 			}
177 			else
178 			{
179 				eds_ring_write(ringBuffer, scanlines[0], bufSize);
180 			}
181 
182 			// decode until valida data
183 			if (isBackSide)
184 			{
185 				if (sum >= s->height_back)
186 				{
187 					break;
188 				}
189 			}else
190 			{
191 				if (sum >= s->height_front)
192 				{
193 					break;
194 				}
195 			}
196         }
197 		DBG(10,"decodded lines = %d\n", sum);
198 
199 		// abandon unncessary data
200 		if ((JDIMENSION)sum < jpeg_cinfo.output_height)
201 		{
202 			// unncessary data
203 			while(1)
204 			{
205 				int l = jpeg_read_scanlines(&jpeg_cinfo, scanlines, 1);
206 				if (l == 0)
207 				{
208 					break;
209 				}
210 			}
211 		}
212 
213 		// if not auto crop mode padding to lines
214 		if (s->val[OPT_ADF_CRP].w == 0)
215 		{
216 			unsigned char* padding = malloc(s->params.bytes_per_line);
217 			memset(padding, 255, s->params.bytes_per_line);
218 			DBG(10,"padding data lines = %d to %d pa \n", sum,  s->params.lines);
219 
220 			while(sum < s->params.lines)
221 			{
222 				eds_ring_write(ringBuffer, padding, bufSize);
223 				sum++;
224 			}
225 
226 			free(padding);
227 			padding = NULL;
228 		}
229     }
230     {
231         jpeg_finish_decompress(&jpeg_cinfo);
232         jpeg_destroy_decompress(&jpeg_cinfo);
233     }
234     return;
235 }
236