xref: /third_party/backends/frontend/jpegtopdf.c (revision 141cc406)
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