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 "endstream\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 */ 104enum { 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 */ 113enum { 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 */ 123typedef 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 */ 141typedef 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 150static 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; 169EXIT: 170 return ret; 171} 172 173static 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 182static 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; 220EXIT: 221 return ret; 222} 223 224SANE_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; 247EXIT: 248 return ret; 249} 250 251void 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 270EXIT: 271 return ; 272} 273 274SANE_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; 297EXIT: 298 return ret; 299} 300 301SANE_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; 485EXIT: 486 return ret; 487} 488 489SANE_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; 660EXIT: 661 return ret; 662 663} 664 665SANE_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; 711EXIT: 712 return ret; 713} 714