1 /* scanimage -- command line scanning utility
2 * Uses the SANE library.
3 *
4 * Copyright (C) 2021 Thierry HUCHARD <thierry@ordissimo.com>
5 *
6 * For questions and comments contact the sane-devel mailinglist (see
7 * http://www.sane-project.org/mailing-lists.html).
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; either version 2 of the
12 * License, or (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful, but
15 * WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program. If not, see <https://www.gnu.org/licenses/>.
21 */
22
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <unistd.h>
27 #include <stdarg.h>
28 #include <errno.h>
29
30 #include <sys/types.h>
31 #include <sys/stat.h>
32 #include <time.h>
33 #include "jpegtopdf.h"
34
35 #ifndef PATH_MAX
36 # define PATH_MAX 4096
37 #endif
38
39 #define SANE_NO_ERR (0)
40 #define SANE_NO_ERR_CANCLED (1)
41
42 #define SANE_ERR (-128)
43 #define SANE_FILE_ERR (-1)
44
45
46 /* Creater/Producer */
47 #define SANE_PDF_CREATER "sane"
48 #define SANE_PDF_PRODUCER "sane"
49
50 /* PDF File Header */
51 #define SANE_PDF_HEADER "%%PDF-1.3\n"
52
53 /* trailer format */
54 #define SANE_PDF_TRAILER_OBJ "trailer\n<<\n/Size %d\n/Root 1 0 R\n/Info 3 0 R\n>>\nstartxref\n%lld\n%%%%EOF\n"
55
56 /* xref format */
57 #define SANE_PDF_XREF_OBJ1 "xref\n0 %d\n0000000000 65535 f \n"
58 #define SANE_PDF_XREF_OBJ2 "%010lld 00000 n \n"
59
60 /* Catalog format */
61 #define SANE_PDF_CATALOG_OBJ "1 0 obj\n<<\n/Type /Catalog\n/Pages 2 0 R\n>>\nendobj\n"
62
63 /* Pages format */
64 #define SANE_PDF_PAGES_OBJ1 "2 0 obj\n<<\n/Type /Pages\n/Kids [ "
65 #define SANE_PDF_PAGES_OBJ2 "%d 0 R "
66 #define SANE_PDF_PAGES_OBJ3 "]\n/Count %d\n>>\nendobj\n"
67
68 /* Info format */
69 #define SANE_PDF_INFO_OBJ "3 0 obj\n<<\n/Creator (" SANE_PDF_CREATER ")\n/Producer (" SANE_PDF_PRODUCER ")\n/CreationDate %s\n>>\nendobj\n"
70 #define SANE_PDF_INFO_DATES "(D:%4d%02d%02d%02d%02d%02d%c%02d'%02d')"
71
72 /* Page format */
73 #define SANE_PDF_PAGE_OBJ1 "%d 0 obj\n<<\n/Type /Page\n/Parent 2 0 R\n"
74 #define SANE_PDF_PAGE_OBJ2 "/Resources\n<<\n/XObject << /Im%d %d 0 R >>\n/ProcSet [ /PDF /%s ]\n>>\n"
75 #define SANE_PDF_PAGE_OBJ3 "/MediaBox [ 0 0 %d %d ]\n/Contents %d 0 R\n>>\nendobj\n"
76 #define SANE_PDF_PAGE_OBJ3_180 "/Rotate 180\n/MediaBox [ 0 0 %d %d ]\n/Contents %d 0 R\n>>\nendobj\n"
77 #define SANE_PDF_PAGE_OBJ SANE_PDF_PAGE_OBJ1 SANE_PDF_PAGE_OBJ2 SANE_PDF_PAGE_OBJ3
78 #define SANE_PDF_PAGE_OBJ_180 SANE_PDF_PAGE_OBJ1 SANE_PDF_PAGE_OBJ2 SANE_PDF_PAGE_OBJ3_180
79
80 /* Contents format */
81 #define SANE_PDF_CONTENTS_OBJ1 "%d 0 obj\n<< /Length %d 0 R >>\nstream\n"
82 #define SANE_PDF_CONTENTS_OBJ2 "q\n%d 0 0 %d 0 0 cm\n/Im%d Do\nQ\n"
83
84 /* XObject(Image) format */
85 #define SANE_PDF_IMAGE_OBJ1 "%d 0 obj\n<<\n/Length %d 0 R\n/Type /XObject\n/Subtype /Image\n"
86 #define SANE_PDF_IMAGE_OBJ2 "/Width %d /Height %d\n/ColorSpace /%s\n/BitsPerComponent %d\n"
87 #define SANE_PDF_IMAGE_OBJ3 "/Filter /DCTDecode\n>>\nstream\n"
88 #define SANE_PDF_IMAGE_OBJ SANE_PDF_IMAGE_OBJ1 SANE_PDF_IMAGE_OBJ2 SANE_PDF_IMAGE_OBJ3
89
90 /* Length format */
91 #define SANE_PDF_LENGTH_OBJ "%d 0 obj\n%d\nendobj\n"
92
93 /* end of stream/object */
94 #define SANE_PDF_END_ST_OBJ "\nendstream\nendobj\n"
95
96
97 /* object id of first page */
98 #define SANE_PDF_FIRST_PAGE_ID (4)
99
100 /* xref max value */
101 #define SANE_PDF_XREF_MAX (9999999999LL)
102
103 /* pdfwork->offset_table */
104 enum {
105 SANE_PDF_ENDDOC_XREF = 0,
106 SANE_PDF_ENDDOC_CATALOG,
107 SANE_PDF_ENDDOC_PAGES,
108 SANE_PDF_ENDDOC_INFO,
109 SANE_PDF_ENDDOC_NUM,
110 };
111
112 /* pdfpage->offset_table */
113 enum {
114 SANE_PDF_PAGE_OBJ_PAGE = 0,
115 SANE_PDF_PAGE_OBJ_IMAGE,
116 SANE_PDF_PAGE_OBJ_IMAGE_LEN,
117 SANE_PDF_PAGE_OBJ_CONTENTS,
118 SANE_PDF_PAGE_OBJ_CONTENTS_LEN,
119 SANE_PDF_PAGE_OBJ_NUM,
120 };
121
122 /* Page object info */
123 typedef struct sane_pdf_page {
124 SANE_Int page; /* page No. */
125 SANE_Int obj_id; /* Page object id */
126 SANE_Int image_type; /* ColorSpace, BitsPerComponent */
127 SANE_Int res; /* image resolution */
128 SANE_Int w; /* width (image res) */
129 SANE_Int h; /* height (image res) */
130 SANE_Int w_72; /* width (72dpi) */
131 SANE_Int h_72; /* height (72dpi) */
132 SANE_Int64 offset_table[SANE_PDF_PAGE_OBJ_NUM]; /* xref table */
133 SANE_Int stream_len; /* stream object length */
134 SANE_Int status; /* page object status */
135 struct sane_pdf_page *prev; /* previous page data */
136 struct sane_pdf_page *next; /* next page data */
137 } SANE_pdf_page;
138
139
140 /* PDF Work */
141 typedef struct {
142 SANE_Int obj_num; /* xref - num, trailer - Size */
143 SANE_Int page_num; /* Pages - Count */
144 SANE_Int64 offset_table[SANE_PDF_ENDDOC_NUM]; /* xref table */
145 SANE_pdf_page *first; /* first page data */
146 SANE_pdf_page *last; /* last page data */
147 FILE* fd; /* destination file */
148 } SANE_pdf_work;
149
re_write_if_fail(FILE * fd,void * lpSrc,SANE_Int writeSize)150 static SANE_Int re_write_if_fail(
151 FILE * fd,
152 void * lpSrc,
153 SANE_Int writeSize )
154 {
155 SANE_Int ret = SANE_ERR, ldata_1st, ldata_2nd;
156
157 if( ( fd == NULL ) || ( lpSrc == NULL ) || ( writeSize <= 0 ) ) {
158 fprintf ( stderr, "[re_write_if_fail]Parameter is error.\n" );
159 goto EXIT;
160 }
161 else if( ( ldata_1st = fwrite( (SANE_Byte *)lpSrc, 1, writeSize, fd ) ) != writeSize ){
162 fprintf ( stderr, "[re_write_if_fail]Can't write file(1st request:%d -> write:%d).\n", writeSize, ldata_1st );
163 if( ( ldata_2nd = fwrite( (SANE_Byte*)lpSrc+ldata_1st, 1, writeSize-ldata_1st, fd) ) != writeSize-ldata_1st ){ /* For detect write() error */
164 fprintf ( stderr, "[re_write_if_fail]Can't write file(2nd request:%d -> write:%d).\n", writeSize-ldata_1st, ldata_2nd );
165 goto EXIT;
166 }
167 }
168 ret = SANE_NO_ERR;
169 EXIT:
170 return ret;
171 }
172
_get_current_offset(FILE * fd)173 static SANE_Int64 _get_current_offset( FILE *fd )
174 {
175 SANE_Int64 offset64 = (SANE_Int64)fseek( fd, 0, SEEK_CUR );
176
177 if ( offset64 > SANE_PDF_XREF_MAX ) offset64 = -1;
178
179 return offset64;
180 }
181
_get_current_time(struct tm * pt,SANE_Byte * sign_c,int * ptz_h,int * ptz_m)182 static SANE_Int _get_current_time( struct tm *pt, SANE_Byte *sign_c, int *ptz_h, int *ptz_m )
183 {
184 SANE_Int ret = SANE_ERR;
185 time_t t;
186 long tz;
187
188 if ( pt == NULL || sign_c == NULL || ptz_h == NULL || ptz_m == NULL ) {
189 goto EXIT;
190 }
191
192 memset ((void *)pt, 0, sizeof(struct tm) );
193 /* get time */
194 if( ( t = time( NULL ) ) < 0 ) {
195 fprintf ( stderr, " Can't get time.\n" );
196 goto EXIT;
197 }
198 /* get localtime */
199 if ( localtime_r( &t, pt ) == NULL ) {
200 fprintf ( stderr, " Can't get localtime.\n" );
201 goto EXIT;
202 }
203 /* get time difference ( OHH'mm' ) */
204 #ifdef __FreeBSD__
205 tz = -pt->tm_gmtoff;
206 #else
207 tz = timezone;
208 #endif
209 if ( tz > 0 ) {
210 *sign_c = '-';
211 }
212 else {
213 tz = -tz;
214 *sign_c = '+';
215 }
216 *ptz_h = tz / 60 / 60;
217 *ptz_m = ( tz / 60 ) % 60;
218
219 ret = SANE_NO_ERR;
220 EXIT:
221 return ret;
222 }
223
sane_pdf_open(void ** ppw,FILE * fd)224 SANE_Int sane_pdf_open( void **ppw, FILE *fd )
225 {
226 SANE_Int ret = SANE_ERR;
227 SANE_pdf_work *p = NULL;
228
229 if ( fd == NULL ) {
230 fprintf ( stderr, " Initialize parameter is error!\n" );
231 goto EXIT;
232 }
233 else if ( ( p = (SANE_pdf_work *)calloc(1, sizeof(SANE_pdf_page) ) ) == NULL ) {
234 fprintf ( stderr, " Can't get work memory!\n" );
235 goto EXIT;
236 }
237
238 p->fd = fd;
239 p->obj_num = SANE_PDF_FIRST_PAGE_ID - 1; /* Catalog, Pages, Info */
240 p->page_num = 0;
241 p->first = NULL;
242 p->last = NULL;
243
244 *ppw = (void *)p;
245
246 ret = SANE_NO_ERR;
247 EXIT:
248 return ret;
249 }
250
sane_pdf_close(void * pw)251 void sane_pdf_close( void *pw )
252 {
253 SANE_pdf_page *cur, *next;
254 SANE_pdf_work *pwork = (SANE_pdf_work *)pw;
255
256 if ( pwork == NULL ) {
257 fprintf ( stderr, " Initialize parameter is error!\n");
258 goto EXIT;
259 }
260
261 cur = pwork->first;
262 while ( cur != NULL ) {
263 next = cur->next;
264 free( (void *)cur );
265 cur = next;
266 }
267
268 free ( (void *)pwork );
269
270 EXIT:
271 return ;
272 }
273
sane_pdf_start_doc(void * pw)274 SANE_Int sane_pdf_start_doc( void *pw )
275 {
276 SANE_Int ret = SANE_ERR, ldata;
277 SANE_Byte str[32];
278 SANE_Int len;
279 SANE_pdf_work *pwork = (SANE_pdf_work *)pw;
280
281 if ( pwork == NULL ) {
282 fprintf ( stderr, " Initialize parameter is error!\n");
283 goto EXIT;
284 }
285
286 len = snprintf( (char*)str, sizeof(str), SANE_PDF_HEADER );
287 if ( (size_t)len >= sizeof(str) || len < 0 ) {
288 fprintf ( stderr, " string is too long!\n" );
289 goto EXIT;
290 }
291 if ( ( ldata = re_write_if_fail( pwork->fd, str, len ) ) < 0 ) {
292 fprintf ( stderr, " Error is occured in re_write_if_fail.\n" );
293 goto EXIT;
294 }
295
296 ret = SANE_NO_ERR;
297 EXIT:
298 return ret;
299 }
300
sane_pdf_end_doc(void * pw)301 SANE_Int sane_pdf_end_doc( void *pw )
302 {
303 SANE_Int ret = SANE_ERR, ldata, i, size, w_count;
304 SANE_pdf_page *p = NULL;
305 SANE_Byte str[1024], str_t[64];
306 SANE_Int len;
307 SANE_pdf_work *pwork = (SANE_pdf_work *)pw;
308
309 struct tm tm;
310 SANE_Byte sign_c;
311 int tz_h = 0, tz_m = 0;
312
313 if ( pwork == NULL ) {
314 fprintf ( stderr, " Initialize parameter is error!\n");
315 goto EXIT;
316 }
317
318 size = pwork->obj_num + 1;
319 w_count = 1;
320
321 /* <1> Pages */
322 if ( ( pwork->offset_table[ SANE_PDF_ENDDOC_PAGES ] = _get_current_offset( pwork->fd ) ) < 0 ) {
323 fprintf ( stderr, " offset > %lld\n", SANE_PDF_XREF_MAX );
324 goto EXIT;
325 }
326 /* write Pages(1) */
327 len = snprintf( (char*)str, sizeof(str), SANE_PDF_PAGES_OBJ1 );
328 if ( (size_t)len >= sizeof(str) || len < 0 ) {
329 fprintf ( stderr, " string is too long!\n" );
330 goto EXIT;
331 }
332 if ( ( ldata = re_write_if_fail( pwork->fd, str, len ) ) < 0 ) {
333 fprintf ( stderr, " Error is occured in re_write_if_fail.\n" );
334 goto EXIT;
335 }
336
337 /* write Pages(2) ... Kids array */
338 p = pwork->first;
339 i = 0;
340 while ( p != NULL ) {
341 i++;
342 if ( p->status != SANE_NO_ERR ) {
343 fprintf ( stderr, " page(%d) is NG!\n", i );
344 goto EXIT;
345 }
346
347 len = snprintf( (char*)str, sizeof(str), SANE_PDF_PAGES_OBJ2, (int)p->obj_id ); /* Page object id */
348 if ( (size_t)len >= sizeof(str) || len < 0 ) {
349 fprintf ( stderr, " string is too long!\n" );
350 goto EXIT;
351 }
352 if ( ( ldata = re_write_if_fail( pwork->fd, str, len ) ) < 0 ) {
353 fprintf ( stderr, " Error is occured in re_write_if_fail.\n" );
354 goto EXIT;
355 }
356
357 p = p->next;
358 }
359
360 /* write Pages(3) */
361 len = snprintf( (char*)str, sizeof(str), SANE_PDF_PAGES_OBJ3, (int)pwork->page_num ); /* Count */
362 if ( (size_t)len >= sizeof(str) || len < 0 ) {
363 fprintf ( stderr, " string is too long!\n" );
364 goto EXIT;
365 }
366 if ( ( ldata = re_write_if_fail( pwork->fd, str, len ) ) < 0 ) {
367 fprintf ( stderr, " Error is occured in re_write_if_fail.\n" );
368 goto EXIT;
369 }
370
371 /* <2> Catalog */
372 if ( ( pwork->offset_table[ SANE_PDF_ENDDOC_CATALOG ] = _get_current_offset( pwork->fd ) ) < 0 ) {
373 fprintf ( stderr, " offset > %lld\n", SANE_PDF_XREF_MAX );
374 goto EXIT;
375 }
376 /* write Catalog */
377 len = snprintf( (char*)str, sizeof(str), SANE_PDF_CATALOG_OBJ );
378 if ( (size_t)len >= sizeof(str) || len < 0 ) {
379 fprintf ( stderr, " string is too long!\n" );
380 goto EXIT;
381 }
382 if ( ( ldata = re_write_if_fail( pwork->fd, str, len ) ) < 0 ) {
383 fprintf ( stderr, " Error is occured in re_write_if_fail.\n" );
384 goto EXIT;
385 }
386
387 /* <3> Info */
388 if ( ( pwork->offset_table[ SANE_PDF_ENDDOC_INFO ] = _get_current_offset( pwork->fd ) ) < 0 ) {
389 fprintf ( stderr, " offset > %lld\n", SANE_PDF_XREF_MAX );
390 goto EXIT;
391 }
392 if ( _get_current_time( &tm, &sign_c, &tz_h, &tz_m ) == SANE_ERR ) {
393 fprintf ( stderr, " Error is occured in _get_current_time.\n" );
394 goto EXIT;
395 }
396 /* Dates format */
397 len = snprintf((char*)str_t, sizeof(str_t), SANE_PDF_INFO_DATES,
398 tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
399 tm.tm_hour, tm.tm_min, tm.tm_sec, sign_c, tz_h, tz_m );
400 if ( (size_t)len >= sizeof(str_t) || len < 0 ) {
401 fprintf ( stderr, " string is too long!\n" );
402 goto EXIT;
403 }
404 /* write Info */
405 len = snprintf( (char*)str, sizeof(str), SANE_PDF_INFO_OBJ, str_t ); /* CreationDate */
406 if ( (size_t)len >= sizeof(str) || len < 0 ) {
407 fprintf ( stderr, " string is too long!\n" );
408 goto EXIT;
409 }
410 if ( ( ldata = re_write_if_fail( pwork->fd, str, len ) ) < 0 ) {
411 fprintf ( stderr, " Error is occured in re_write_if_fail.\n" );
412 goto EXIT;
413 }
414
415 /* <4> xref */
416 if ( ( pwork->offset_table[ SANE_PDF_ENDDOC_XREF ] = _get_current_offset( pwork->fd ) ) < 0 ) {
417 fprintf ( stderr, " offset > %lld\n", SANE_PDF_XREF_MAX );
418 goto EXIT;
419 }
420 /* write xref(1) */
421 len = snprintf( (char*)str, sizeof(str), SANE_PDF_XREF_OBJ1, (int)size ); /* object num */
422 if ( (size_t)len >= sizeof(str) || len < 0 ) {
423 fprintf ( stderr, " string is too long!\n" );
424 goto EXIT;
425 }
426 if ( ( ldata = re_write_if_fail( pwork->fd, str, len ) ) < 0 ) {
427 fprintf ( stderr, " Error is occured in re_write_if_fail.\n" );
428 goto EXIT;
429 }
430
431 /* write xref(2) */
432 len = snprintf( (char*)str, sizeof(str), SANE_PDF_XREF_OBJ2 SANE_PDF_XREF_OBJ2 SANE_PDF_XREF_OBJ2,
433 pwork->offset_table[ SANE_PDF_ENDDOC_CATALOG ], /* object id = 1 : Catalog */
434 pwork->offset_table[ SANE_PDF_ENDDOC_PAGES ], /* object id = 2 : Pages */
435 pwork->offset_table[ SANE_PDF_ENDDOC_INFO ] ); /* object id = 3 : Info */
436 if ( (size_t)len >= sizeof(str) || len < 0 ) {
437 fprintf ( stderr, " string is too long!\n" );
438 goto EXIT;
439 }
440 if ( ( ldata = re_write_if_fail( pwork->fd, str, len ) ) < 0 ) {
441 fprintf ( stderr, " Error is occured in re_write_if_fail.\n" );
442 goto EXIT;
443 }
444 w_count += SANE_PDF_FIRST_PAGE_ID - 1;
445
446 /* write xref(3) */
447 p = pwork->first;
448 while ( p != NULL ) {
449 /* write offset : SANE_PDF_PAGE_OBJ_PAGE -> SANE_PDF_PAGE_OBJ_CONTENTS_LEN */
450 for ( i = 0; i < SANE_PDF_PAGE_OBJ_NUM; i++ ) {
451 len = snprintf( (char*)str, sizeof(str), SANE_PDF_XREF_OBJ2, p->offset_table[ i ] ); /* object id = 3 ~ */
452 if ( (size_t)len >= sizeof(str) || len < 0 ) {
453 fprintf ( stderr, " string is too long!\n" );
454 goto EXIT;
455 }
456 if ( ( ldata = re_write_if_fail( pwork->fd, str, len ) ) < 0 ) {
457 fprintf ( stderr, " Error is occured in re_write_if_fail.\n" );
458 goto EXIT;
459 }
460 w_count ++;
461 }
462 p = p->next;
463 }
464 /* check object number */
465 if ( w_count != size ) {
466 fprintf ( stderr, " object number is wrong.\n" );
467 goto EXIT;
468 }
469
470 /* <4> trailer */
471 len = snprintf( (char*)str, sizeof(str), SANE_PDF_TRAILER_OBJ,
472 (int)size, /* object num */
473 pwork->offset_table[ SANE_PDF_ENDDOC_XREF ] ); /* xref offset */
474 if ( (size_t)len >= sizeof(str) || len < 0 ) {
475 fprintf ( stderr, " string is too long!\n" );
476 goto EXIT;
477 }
478 if ( ( ldata = re_write_if_fail( pwork->fd, str, len ) ) < 0 ) {
479 fprintf ( stderr, " Error is occured in re_write_if_fail.\n" );
480 goto EXIT;
481 }
482
483
484 ret = SANE_NO_ERR;
485 EXIT:
486 return ret;
487 }
488
sane_pdf_start_page(void * pw,SANE_Int w,SANE_Int h,SANE_Int res,SANE_Int type,SANE_Int rotate)489 SANE_Int sane_pdf_start_page(
490 void *pw,
491 SANE_Int w,
492 SANE_Int h,
493 SANE_Int res,
494 SANE_Int type,
495 SANE_Int rotate )
496 {
497 SANE_Int ret = SANE_ERR, ldata;
498 SANE_pdf_page *p = NULL;
499 SANE_Byte str[1024];
500 SANE_Int len, len_c;
501 SANE_Byte *ProcSetImage[SANE_PDF_IMAGE_NUM] = { (SANE_Byte *)"ImageC", (SANE_Byte *)"ImageG", (SANE_Byte *)"ImageG" };
502 SANE_Byte *ColorSpace[SANE_PDF_IMAGE_NUM] = { (SANE_Byte *)"DeviceRGB", (SANE_Byte *)"DeviceGray", (SANE_Byte *)"DeviceGray" };
503 SANE_Int BitsPerComponent[SANE_PDF_IMAGE_NUM] = { 8, 8, 1 };
504 SANE_pdf_work *pwork = (SANE_pdf_work *)pw;
505
506 if ( pwork == NULL || w <= 0 || h <= 0 || res <= 0 ||
507 !( type == SANE_PDF_IMAGE_COLOR || type == SANE_PDF_IMAGE_GRAY || type == SANE_PDF_IMAGE_MONO ) ||
508 !( rotate == SANE_PDF_ROTATE_OFF || rotate == SANE_PDF_ROTATE_ON ) ) {
509 fprintf ( stderr, " Initialize parameter is error!\n");
510 goto EXIT;
511 }
512 else if ( ( p = (SANE_pdf_page *)calloc( 1, sizeof(SANE_pdf_page) ) ) == NULL ) {
513 fprintf ( stderr, " Can't get work memory!\n" );
514 goto EXIT;
515 }
516
517 pwork->obj_num += SANE_PDF_PAGE_OBJ_NUM;
518 pwork->page_num ++;
519
520 p->prev = p->next = NULL;
521 if ( pwork->first == NULL ) {
522 /* append first page */
523 pwork->first = p;
524 }
525 if ( pwork->last == NULL ) {
526 /* append first page */
527 pwork->last = p;
528 }
529 else {
530 /* append page */
531 pwork->last->next = p;
532 p->prev = pwork->last;
533 pwork->last = p;
534 }
535
536 p->page = pwork->page_num;
537 /* page obj id : page1=4, page2=4+5=9, page3=4+5*2=14, ... */
538 p->obj_id = SANE_PDF_FIRST_PAGE_ID + ( p->page - 1 ) * SANE_PDF_PAGE_OBJ_NUM;
539 p->image_type = type;
540 p->res = res;
541 p->w = w; p->h = h;
542 p->w_72 = w * 72 / res; p->h_72 = h * 72 / res;
543 p->stream_len = 0;
544 p->status = SANE_ERR;
545
546 /* <1> Page */
547 if ( ( p->offset_table[ SANE_PDF_PAGE_OBJ_PAGE ] = _get_current_offset( pwork->fd ) ) < 0 ) {
548 fprintf ( stderr, " offset > %lld\n", SANE_PDF_XREF_MAX );
549 goto EXIT;
550 }
551 /* write Page */
552 if ( rotate == SANE_PDF_ROTATE_OFF ) {
553 len = snprintf( (char*)str, sizeof(str), SANE_PDF_PAGE_OBJ,
554 (int)(p->obj_id + SANE_PDF_PAGE_OBJ_PAGE), /* object id ( Page ) */
555 (int)p->page, /* ImX (X = page number) ... XObject/Image Name */
556 (int)(p->obj_id + SANE_PDF_PAGE_OBJ_IMAGE), /* object id ( XObject/Image ) */
557 ProcSetImage[ type ], /* ProcSet */
558 (int)p->w_72, (int)p->h_72, /* MediaBox */
559 (int)(p->obj_id + SANE_PDF_PAGE_OBJ_CONTENTS) ); /* object id ( Contents ) */
560 }
561 else {
562 len = snprintf( (char*)str, sizeof(str), SANE_PDF_PAGE_OBJ_180,
563 (int)(p->obj_id + SANE_PDF_PAGE_OBJ_PAGE), /* object id ( Page ) */
564 (int)p->page, /* ImX (X = page number) ... XObject/Image Name */
565 (int)(p->obj_id + SANE_PDF_PAGE_OBJ_IMAGE), /* object id ( XObject/Image ) */
566 ProcSetImage[ type ], /* ProcSet */
567 (int)p->w_72, (int)p->h_72, /* MediaBox */
568 (int)(p->obj_id + SANE_PDF_PAGE_OBJ_CONTENTS) ); /* object id ( Contents ) */
569 }
570 if ( (size_t)len >= sizeof(str) || len < 0 ) {
571 fprintf ( stderr, " string is too long!\n" );
572 goto EXIT;
573 }
574 if ( ( ldata = re_write_if_fail( pwork->fd, str, len ) ) < 0 ) {
575 fprintf ( stderr, " Error is occured in re_write_if_fail.\n" );
576 goto EXIT;
577 }
578
579 /* <2> Contents */
580 if ( ( p->offset_table[ SANE_PDF_PAGE_OBJ_CONTENTS ] = _get_current_offset( pwork->fd ) ) < 0 ) {
581 fprintf ( stderr, " offset > %lld\n", SANE_PDF_XREF_MAX );
582 goto EXIT;
583 }
584 /* write Contents(1) */
585 len = snprintf( (char*)str, sizeof(str), SANE_PDF_CONTENTS_OBJ1,
586 (int)(p->obj_id + SANE_PDF_PAGE_OBJ_CONTENTS), /* object id ( Contents ) */
587 (int)(p->obj_id + SANE_PDF_PAGE_OBJ_CONTENTS_LEN) ); /* object id ( Length of Contents ) */
588 if ( (size_t)len >= sizeof(str) || len < 0 ) {
589 fprintf ( stderr, " string is too long!\n" );
590 goto EXIT;
591 }
592 if ( ( ldata = re_write_if_fail( pwork->fd, str, len ) ) < 0 ) {
593 fprintf ( stderr, " Error is occured in re_write_if_fail.\n" );
594 goto EXIT;
595 }
596 /* write Contents(2) */
597 len_c = len = snprintf( (char*)str, sizeof(str), SANE_PDF_CONTENTS_OBJ2,
598 (int)p->w_72, (int)p->h_72, /* CTM ( scaling ) */
599 (int)p->page ); /* ImX (X = page number) ... XObject/Image Name */
600 if ( (size_t)len >= sizeof(str) || len < 0 ) {
601 fprintf ( stderr, " string is too long!\n" );
602 goto EXIT;
603 }
604 if ( ( ldata = re_write_if_fail( pwork->fd, str, len ) ) < 0 ) {
605 fprintf ( stderr, " Error is occured in re_write_if_fail.\n" );
606 goto EXIT;
607 }
608
609 /* write Contents(3) */
610 len = snprintf( (char*)str, sizeof(str), SANE_PDF_END_ST_OBJ );
611 if ( (size_t)len >= sizeof(str) || len < 0 ) {
612 fprintf ( stderr, " string is too long!\n" );
613 goto EXIT;
614 }
615 if ( ( ldata = re_write_if_fail( pwork->fd, str, len ) ) < 0 ) {
616 fprintf ( stderr, " Error is occured in re_write_if_fail.\n" );
617 goto EXIT;
618 }
619
620 /* <3> Length of Contents - stream */
621 if ( ( p->offset_table[ SANE_PDF_PAGE_OBJ_CONTENTS_LEN ] = _get_current_offset( pwork->fd ) ) < 0 ) {
622 fprintf ( stderr, " offset > %lld\n", SANE_PDF_XREF_MAX );
623 goto EXIT;
624 }
625 /* write Length */
626 len = snprintf( (char *)str, sizeof(str), SANE_PDF_LENGTH_OBJ,
627 (int)(p->obj_id + SANE_PDF_PAGE_OBJ_CONTENTS_LEN), /* object id ( Length of Contents ) */
628 len_c ); /* length value */
629 if ( (size_t)len >= sizeof(str) || len < 0 ) {
630 fprintf ( stderr, " string is too long!\n" );
631 goto EXIT;
632 }
633 if ( ( ldata = re_write_if_fail( pwork->fd, str, len ) ) < 0 ) {
634 fprintf ( stderr, " Error is occured in re_write_if_fail.\n" );
635 goto EXIT;
636 }
637
638 /* <4> XObject(Image) */
639 if ( ( p->offset_table[ SANE_PDF_PAGE_OBJ_IMAGE ] = _get_current_offset( pwork->fd ) ) < 0 ) {
640 fprintf ( stderr, " offset > %lld\n", SANE_PDF_XREF_MAX );
641 goto EXIT;
642 }
643 /* write XObject */
644 len = snprintf( (char*)str, sizeof(str), SANE_PDF_IMAGE_OBJ,
645 (int)(p->obj_id + SANE_PDF_PAGE_OBJ_IMAGE), /* object id ( XObject(Image) ) */
646 (int)(p->obj_id + SANE_PDF_PAGE_OBJ_IMAGE_LEN), /* object id ( Length of XObject ) */
647 (int)p->w, (int)p->h, /* Width/Height */
648 ColorSpace[ type ], /* ColorSpace */
649 (int)BitsPerComponent[ type ] ); /* BitsPerComponent */
650 if ( (size_t)len >= sizeof(str) || len < 0 ) {
651 fprintf ( stderr, " string is too long!\n" );
652 goto EXIT;
653 }
654 if ( ( ldata = re_write_if_fail( pwork->fd, str, len ) ) < 0 ) {
655 fprintf ( stderr, " Error is occured in re_write_if_fail.\n" );
656 goto EXIT;
657 }
658
659 ret = SANE_NO_ERR;
660 EXIT:
661 return ret;
662
663 }
664
sane_pdf_end_page(void * pw)665 SANE_Int sane_pdf_end_page( void *pw )
666 {
667 SANE_Int ret = SANE_ERR, ldata;
668 SANE_pdf_page *p = NULL;
669 SANE_Byte str[1024];
670 SANE_Int len;
671 SANE_pdf_work *pwork = (SANE_pdf_work *)pw;
672
673 if ( pwork == NULL ) {
674 fprintf ( stderr, " Initialize parameter is error!\n" );
675 goto EXIT;
676 }
677
678 p = pwork->last;
679
680 /* <1> endstream, endobj (XObject) */
681 len = snprintf( (char*)str, sizeof(str), SANE_PDF_END_ST_OBJ );
682 if ( (size_t)len >= sizeof(str) || len < 0 ) {
683 fprintf ( stderr, " string is too long!\n" );
684 goto EXIT;
685 }
686 if ( ( ldata = re_write_if_fail( pwork->fd, str, len ) ) < 0 ) {
687 fprintf ( stderr, " Error is occured in re_write_if_fail.\n" );
688 goto EXIT;
689 }
690
691 /* <2> Length of XObject - stream */
692 if ( ( p->offset_table[ SANE_PDF_PAGE_OBJ_IMAGE_LEN ] = _get_current_offset( pwork->fd ) ) < 0 ) {
693 fprintf ( stderr, " offset > %lld\n", SANE_PDF_XREF_MAX );
694 goto EXIT;
695 }
696 /* write Length */
697 len = snprintf( (char*)str, sizeof(str), SANE_PDF_LENGTH_OBJ,
698 (int)(p->obj_id + SANE_PDF_PAGE_OBJ_IMAGE_LEN), /* object id ( Length of XObject stream ) */
699 (int)p->stream_len ); /* length value */
700 if ( (size_t)len >= sizeof(str) || len < 0 ) {
701 fprintf ( stderr, " string is too long!\n" );
702 goto EXIT;
703 }
704 if ( ( ldata = re_write_if_fail( pwork->fd, str, len ) ) < 0 ) {
705 fprintf ( stderr, " Error is occured in re_write_if_fail.\n" );
706 goto EXIT;
707 }
708
709 ret = SANE_NO_ERR;
710 p->status = SANE_NO_ERR;
711 EXIT:
712 return ret;
713 }
714