3 % Copyright
1996-2006 Han The Thanh
<thanh@@pdftex.org
>
4 % Copyright
2006-2013 Taco Hoekwater
<taco@@luatex.org
>
5 % Copyright
2003-2013 Hartmut Henkel
<hartmut@@luatex.org
>
7 % This file is part of LuaTeX.
9 % LuaTeX is free software
; you can redistribute it and
/or modify it under
10 % the terms of the GNU General Public License as published by the Free
11 % Software Foundation
; either version
2 of the License
, or
(at your
12 % option
) any later version.
14 % LuaTeX is distributed in the hope that it will be useful
, but WITHOUT
15 % ANY WARRANTY
; without even the implied warranty of MERCHANTABILITY or
16 % FITNESS
FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
17 % License for more details.
19 % You should have received a copy of the GNU General Public License along
20 % with LuaTeX
; if not
, see
<http
://www.gnu.org
/licenses
/>.
23 This is experimental JBIG2 image support to pdfTeX. JBIG2 image decoding
24 is part of Adobe PDF-1.4
, and requires Acroread
5.0 or later.
29 * 14492 FCD
: Information technology
-- coded representation of picture
30 and audio information
-- lossy
/lossless coding of bi-level images
/
31 JBIG committee
, 1999 July
16. This JBIG2 Working Draft is available from
32 http
://www.jpeg.org
/public
/fcd14492.pdf. The references in the C-code
33 correspond to the sections of this document.
35 * PDF Reference
, 5th edition
, version
1.6, 1985--2005 Adobe Systems
36 Incorporated. Available online
:
38 http
://partners.adobe.com
/public
/developer
/en
/pdf
/PDFReference16.pdf
43 31 May
2006: no need to wait for |endoffileflag| in sequential access
46 10 May
2006: |ygetc
()| for some catching of broken JBIG2 files
; modify to
47 accept Example
3.4 from PDFRef
5th ed. with short end-of-file segment.
49 09 May
2006: |pages_maketree
()| and |segments_maketree
()| by AVL tree
,
52 06 May
2006: File list replaced by AVL tree
; |new_fileinfo
()|
,
55 04 May
2006: Updated for pdftex-1.40
-beta-20060213.
57 08 Jan.
2003: Added |flushjbig2page0objects
()| function. Now at the end
58 of the pdfTeX run all pending page0 objects are written out.
60 08 Jan.
2003: Release on private webpage.
62 04 Jan.
2003: Completely rewritten. Now with some data structures.
63 Rudimentary local file and image bookkeeping. Multiple image inclusion
64 from one JBIG2 file. Only required page0 segments are marked for
67 13 Nov.
2002: pdfcrypting removed.
69 08 Dec.
2002: bug in page
0 stream writing repaired.
70 Strategy for multiple page inclusion from same JBIG2 file
: When writing
71 1st image
, create fresh PDF object for page
0, and include any page
72 0 segments from complete file
(even if these segments are not needed
73 for image
). When writing next image
, check by filename comparison if
74 PDF object for page
0 of this JBIG2 file has already been written. This
75 can only remember the file name for the direct predecessor JBIG2 image
76 (but images of other types might come inbetween
). If such page
0 PDF
77 object exists
, reference it. Else create fresh one.
79 09 Dec.
2002: JBIG2 seg. page numbers
> 0 are now set to
1, see PDF Ref.
88 #include
"image/image.h"
91 /* 7.3 Segment types
*/
92 #define M_SymbolDictionary
0
93 #define M_IntermediateTextRegion
4
94 #define M_ImmediateTextRegion
6
95 #define M_ImmediateLosslessTextRegion
7
96 #define M_PatternDictionary
16
97 #define M_IntermediateHalftoneRegion
20
98 #define M_ImmediateHalftoneRegion
22
99 #define M_ImmediateLosslessHalftoneRegion
23
100 #define M_IntermediateGenericRegion
36
101 #define M_ImmediateGenericRegion
38
102 #define M_ImmediateLosslessGenericRegion
39
103 #define M_IntermediateGenericRefinementRegion
40
104 #define M_ImmediateGenericRefinementRegion
42
105 #define M_ImmediateLosslessGenericRefinementRegion
43
106 #define M_PageInformation
48
107 #define M_EndOfPage
49
108 #define M_EndOfStripe
50
109 #define M_EndOfFile
51
110 #define M_Profiles
52
112 #define M_Extension
62
115 typedef enum
{ INITIAL, HAVEINFO
, WRITEPDF
} PHASE
;
117 typedef struct _LITEM
{
123 typedef struct
_LIST {
126 struct avl_table
*tree
;
129 typedef struct _SEGINFO
{
130 unsigned long segnum
;
133 unsigned int seghdrflags
; /* set by readseghdr
() */
134 boolean pageassocsizeflag
; /* set by readseghdr
() */
135 unsigned int reftosegcount
; /* set by readseghdr
() */
136 unsigned int countofrefered
; /* set by readseghdr
() */
137 unsigned int fieldlen
; /* set by readseghdr
() */
138 unsigned int segnumwidth
; /* set by readseghdr
() */
139 long segpage
; /* set by readseghdr
() */
140 unsigned long segdatalen
; /* set by readseghdr
() */
141 unsigned long hdrstart
; /* set by readseghdr
() */
142 unsigned long hdrend
; /* set by readseghdr
() */
143 unsigned long datastart
;
144 unsigned long dataend
;
145 boolean endofstripeflag
; /* set by checkseghdrflags
() */
146 boolean endofpageflag
; /* set by checkseghdrflags
() */
147 boolean pageinfoflag
; /* set by checkseghdrflags
() */
148 boolean endoffileflag
; /* set by checkseghdrflags
() */
151 typedef struct _PAGEINFO
{
152 LIST segments
; /* segments associated with page
*/
153 unsigned long pagenum
;
158 unsigned int pagesegmentflags
;
159 unsigned int stripinginfo
;
160 unsigned int stripedheight
;
163 typedef struct _FILEINFO
{
167 LIST pages
; /* not including page0
*/
169 unsigned int filehdrflags
; /* set by readfilehdr
() */
170 boolean sequentialaccess
; /* set by readfilehdr
() */
171 unsigned long numofpages
; /* set by readfilehdr
() */
172 unsigned long streamstart
; /* set by |get_jbig2_info
()|
*/
173 unsigned long pdfpage0objnum
;
178 static struct avl_table
*file_tree
= NULL;
180 static int comp_file_entry
(const void
*pa
, const void
*pb
, void
*p
)
183 return strcmp
(((const FILEINFO
*) pa
)->filepath
,((const FILEINFO
*) pb
)->filepath
);
186 static int comp_page_entry
(const void
*pa
, const void
*pb
, void
*p
)
189 return
(int
) (((const PAGEINFO
*) pa
)->pagenum
- ((const PAGEINFO
*) pb
)->pagenum
);
192 static int comp_segment_entry
(const void
*pa
, const void
*pb
, void
*p
)
195 return
(int
) (((const SEGINFO
*) pa
)->segnum
- ((const SEGINFO
*) pb
)->segnum
);
199 static int ygetc
(FILE * stream
)
201 int c
= getc
(stream
);
204 normal_error
("readjbig2","premature end file");
206 normal_error
("readjbig2","can't happen");
212 static void initlinkedlist
(LIST
* lp
)
219 static LIST
*litem_append
(LIST
* lp
)
222 ip
= xtalloc
(1, LITEM
);
223 if
(lp-
>first
== NULL) {
237 static FILEINFO
*new_fileinfo
(void
)
240 fip
= xtalloc
(1, FILEINFO
);
242 fip-
>filepath
= NULL;
244 initlinkedlist
(&(fip->pages));
245 initlinkedlist
(&(fip->page0));
246 fip-
>filehdrflags
= 0;
247 fip-
>sequentialaccess
= false
;
249 fip-
>streamstart
= 0;
250 fip-
>pdfpage0objnum
= 0;
251 fip-
>phase
= INITIAL;
256 static PAGEINFO
*new_pageinfo
(void
)
259 pip
= xtalloc
(1, PAGEINFO
);
260 initlinkedlist
(&(pip->segments));
266 pip-
>pagesegmentflags
= 0;
267 pip-
>stripinginfo
= 0;
268 pip-
>stripedheight
= 0;
273 static void init_seginfo
(SEGINFO
* sip
)
276 sip-
>isrefered
= false
;
278 sip-
>seghdrflags
= 0;
279 sip-
>pageassocsizeflag
= false
;
280 sip-
>reftosegcount
= 0;
281 sip-
>countofrefered
= 0;
283 sip-
>segnumwidth
= 0;
290 sip-
>endofstripeflag
= false
;
291 sip-
>endofpageflag
= false
;
292 sip-
>pageinfoflag
= false
;
293 sip-
>endoffileflag
= false
;
297 static void pages_maketree
(LIST
* plp
)
301 assert
(plp-
>tree
== NULL);
302 plp-
>tree
= avl_create
(comp_page_entry
, NULL, &avl_xallocator);
303 assert
(plp-
>tree
!= NULL);
304 for
(ip
= plp-
>first
; ip
!= NULL; ip
= ip-
>next
) {
305 aa
= avl_probe
(plp-
>tree
, (PAGEINFO
*) ip-
>d
);
311 static void segments_maketree
(LIST
* slp
)
315 assert
(slp-
>tree
== NULL);
316 slp-
>tree
= avl_create
(comp_segment_entry
, NULL, &avl_xallocator);
317 assert
(slp-
>tree
!= NULL);
318 for
(ip
= slp-
>first
; ip
!= NULL; ip
= ip-
>next
) {
319 aa
= avl_probe
(slp-
>tree
, (SEGINFO
*) ip-
>d
);
325 static PAGEINFO
*find_pageinfo
(LIST
* plp
, unsigned long pagenum
)
328 tmp.pagenum
= pagenum
;
329 assert
(plp-
>tree
!= NULL);
330 return
(PAGEINFO
*) avl_find
(plp-
>tree
, &tmp);
334 static SEGINFO
*find_seginfo
(LIST
* slp
, unsigned long segnum
)
338 assert
(slp-
>tree
!= NULL);
339 return
(SEGINFO
*) avl_find
(slp-
>tree
, &tmp);
343 unsigned int read2bytes
(FILE * f
)
345 unsigned int c
= (unsigned int
) ygetc
(f
);
346 return
(c
<< 8) + (unsigned int
) ygetc
(f
);
350 unsigned int read4bytes
(FILE * f
)
352 unsigned int l
= read2bytes
(f
);
353 return
(l
<< 16) + read2bytes
(f
);
357 static unsigned long getstreamlen
(LITEM
* slip
, boolean refer
)
360 unsigned long len
= 0;
361 for
(; slip
!= NULL; slip
= slip-
>next
) {
363 if
(refer || sip-
>isrefered
)
364 len
+= sip-
>hdrend
- sip-
>hdrstart
+ sip-
>dataend
- sip-
>datastart
;
370 static void readfilehdr
(FILEINFO
* fip
)
373 /* Annex D
.4 File header syntax
*/
374 /* Annex D
.4.1 ID string
*/
375 unsigned char jbig2_id
[] = { 0x97, 'J'
, 'B'
, '
2'
, 0x0d, 0x0a, 0x1a, 0x0a };
376 xfseek
(fip-
>file
, 0, SEEK_SET
, fip-
>filepath
);
377 for
(i
= 0; i
< 8; i
++)
378 if
(ygetc
(fip-
>file
) != jbig2_id
[i
])
379 normal_error
("readjbig2","ID string missing");
380 /* Annex D
.4.2 File header flags
*/
381 fip-
>filehdrflags
= (unsigned int
) ygetc
(fip-
>file
);
382 fip-
>sequentialaccess
= (fip-
>filehdrflags
& 0x01) ? true : false;
383 if
(fip-
>sequentialaccess
) { /* Annex D
.1 vs. Annex D
.2 */
384 xfseek
(fip-
>file
, 0, SEEK_END
, fip-
>filepath
);
385 fip-
>filesize
= (long
) xftello
(fip-
>file
, fip-
>filepath
);
386 xfseek
(fip-
>file
, 9, SEEK_SET
, fip-
>filepath
);
388 /* Annex D
.4.3 Number of pages
*/
389 if
(!(fip-
>filehdrflags
>> 1) & 0x01) /* known number of pages */
390 fip-
>numofpages
= read4bytes
(fip-
>file
);
391 /* --- at end of file header
--- */
395 static void checkseghdrflags
(SEGINFO
* sip
)
397 sip-
>endofstripeflag
= false
;
398 sip-
>endofpageflag
= false
;
399 sip-
>pageinfoflag
= false
;
400 sip-
>endoffileflag
= false
;
401 /* 7.3 Segment types
*/
402 switch
(sip-
>seghdrflags
& 0x3f) {
403 case M_SymbolDictionary
:
404 case M_IntermediateTextRegion
:
405 case M_ImmediateTextRegion
:
406 case M_ImmediateLosslessTextRegion
:
407 case M_PatternDictionary
:
408 case M_IntermediateHalftoneRegion
:
409 case M_ImmediateHalftoneRegion
:
410 case M_ImmediateLosslessHalftoneRegion
:
411 case M_IntermediateGenericRegion
:
412 case M_ImmediateGenericRegion
:
413 case M_ImmediateLosslessGenericRegion
:
414 case M_IntermediateGenericRefinementRegion
:
415 case M_ImmediateGenericRefinementRegion
:
416 case M_ImmediateLosslessGenericRefinementRegion
:
418 case M_PageInformation
:
419 sip-
>pageinfoflag
= true
;
422 sip-
>endofpageflag
= true
;
425 sip-
>endofstripeflag
= true
;
428 sip-
>endoffileflag
= true
;
435 normal_error
("readjbig2","unknown segment type file");
440 @ for first reading of file
; return value tells if header been read
443 static boolean readseghdr
(FILEINFO
* fip
, SEGINFO
* sip
)
446 sip-
>hdrstart
= xftell
(fip-
>file
, fip-
>filepath
);
447 if
(fip-
>sequentialaccess
&& sip->hdrstart == (unsigned) fip->filesize)
448 return false
; /* no endoffileflag is ok for sequentialaccess
*/
449 /* 7.2.2 Segment number
*/
450 sip-
>segnum
= read4bytes
(fip-
>file
);
451 /* 7.2.3 Segment header flags
*/
452 sip-
>seghdrflags
= (unsigned int
) ygetc
(fip-
>file
);
453 checkseghdrflags
(sip
);
454 if
(fip-
>sequentialaccess
&& sip->endoffileflag) /* accept shorter segment, */
455 return true
; /* makes it compliant with Example
3.4 of PDFRef.
5th ed.
*/
456 sip-
>pageassocsizeflag
= ((sip-
>seghdrflags
>> 6) & 0x01) ? true : false;
457 /* 7.2.4 Referred-to segment count and retention flags
*/
458 sip-
>reftosegcount
= (unsigned int
) ygetc
(fip-
>file
);
459 sip-
>countofrefered
= sip-
>reftosegcount
>> 5;
460 if
(sip-
>countofrefered
< 5)
463 sip-
>fieldlen
= 5 + sip-
>countofrefered
/ 8;
464 xfseek
(fip-
>file
, sip-
>fieldlen
- 1, SEEK_CUR
, fip-
>filepath
);
466 /* 7.2.5 Referred-to segment numbers
*/
467 if
(sip-
>segnum
<= 256)
468 sip-
>segnumwidth
= 1;
469 else if
(sip-
>segnum
<= 65536)
470 sip-
>segnumwidth
= 2;
472 sip-
>segnumwidth
= 4;
473 for
(i
= 0; i
< sip-
>countofrefered
; i
++) {
474 switch
(sip-
>segnumwidth
) {
476 (void
) ygetc
(fip-
>file
);
479 (void
) read2bytes
(fip-
>file
);
482 (void
) read4bytes
(fip-
>file
);
486 /* 7.2.6 Segment page association
*/
487 if
(sip-
>pageassocsizeflag
)
488 sip-
>segpage
= read4bytes
(fip-
>file
);
490 sip-
>segpage
= ygetc
(fip-
>file
);
491 /* 7.2.7 Segment data length
*/
492 sip-
>segdatalen
= read4bytes
(fip-
>file
);
493 sip-
>hdrend
= (unsigned long
) xftello
(fip-
>file
, fip-
>filepath
);
494 /* ---- at end of segment header
---- */
499 static void checkseghdr
(FILEINFO
* fip
, SEGINFO
* sip
);
501 static void markpage0seg
(FILEINFO
* fip
, unsigned long referedseg
)
505 pip
= fip-
>page0.first-
>d
;
506 sip
= find_seginfo
(&(pip->segments), referedseg);
508 if
(!sip-
>refers
&& sip->countofrefered > 0)
509 checkseghdr
(fip
, sip
);
510 sip-
>isrefered
= true
;
514 @ for writing
, marks refered page0 segments
, sets segpage
> 0 to
1
517 static void writeseghdr
(PDF pdf
, FILEINFO
* fip
, SEGINFO
* sip
)
520 unsigned long referedseg
= 0;
521 /* 7.2.2 Segment number
*/
522 /* 7.2.3 Segment header flags
*/
523 /* 7.2.4 Referred-to segment count and retention flags
*/
524 for
(i
= 0; i
< 5 + sip-
>fieldlen
; i
++)
525 pdf_out
(pdf
, ygetc
(fip-
>file
));
526 /* 7.2.5 Referred-to segment numbers
*/
527 for
(i
= 0; i
< sip-
>countofrefered
; i
++) {
528 switch
(sip-
>segnumwidth
) {
530 referedseg
= (unsigned long
) ygetc
(fip-
>file
);
531 pdf_out
(pdf
, referedseg
);
534 referedseg
= read2bytes
(fip-
>file
);
535 pdf_out
(pdf
, (referedseg
>> 8) & 0xff);
536 pdf_out
(pdf
, referedseg
& 0xff);
539 referedseg
= read4bytes
(fip-
>file
);
540 pdf_out
(pdf
, (referedseg
>> 24) & 0xff);
541 pdf_out
(pdf
, (referedseg
>> 16) & 0xff);
542 pdf_out
(pdf
, (referedseg
>> 8) & 0xff);
543 pdf_out
(pdf
, referedseg
& 0xff);
546 if
(fip-
>page0.last
!= NULL && !sip->refers)
547 markpage0seg
(fip
, referedseg
);
549 if
(sip-
>countofrefered
> 0)
551 /* 7.2.6 Segment page association
*/
552 if
(sip-
>pageassocsizeflag
)
553 for
(i
= 0; i
< 3; i
++) {
554 (void
) ygetc
(fip-
>file
);
557 (void
) ygetc
(fip-
>file
);
558 pdf_out
(pdf
, (unsigned char
) ((sip-
>segpage
> 0) ?
1 : 0));
559 /* 7.2.7 Segment data length
*/
560 for
(i
= 0; i
< 4; i
++)
561 pdf_out
(pdf
, ygetc
(fip-
>file
));
562 /* ---- at end of segment header
---- */
565 @ for recursive marking of refered page0 segments
567 static void checkseghdr
(FILEINFO
* fip
, SEGINFO
* sip
)
570 unsigned long referedseg
= 0;
571 /* 7.2.2 Segment number
*/
572 /* 7.2.3 Segment header flags
*/
573 /* 7.2.4 Referred-to segment count and retention flags
*/
574 xfseek
(fip-
>file
, 5 + sip-
>fieldlen
, SEEK_CUR
, fip-
>filepath
);
575 /* 7.2.5 Referred-to segment numbers
*/
576 for
(i
= 0; i
< sip-
>countofrefered
; i
++) {
577 switch
(sip-
>segnumwidth
) {
579 referedseg
= (unsigned long
) ygetc
(fip-
>file
);
582 referedseg
= read2bytes
(fip-
>file
);
585 referedseg
= read4bytes
(fip-
>file
);
589 markpage0seg
(fip
, referedseg
);
591 if
(sip-
>countofrefered
> 0)
593 /* 7.2.6 Segment page association
*/
594 /* 7.2.7 Segment data length
*/
595 if
(sip-
>pageassocsizeflag
)
596 xfseek
(fip-
>file
, 8, SEEK_CUR
, fip-
>filepath
);
598 xfseek
(fip-
>file
, 5, SEEK_CUR
, fip-
>filepath
);
599 /* ---- at end of segment header
---- */
603 static unsigned long findstreamstart
(FILEINFO
* fip
)
606 assert
(!fip-
>sequentialaccess
); /* D
.2 Random-access organisation
*/
607 do
/* find random-access stream start
*/
608 (void
) readseghdr
(fip
, &tmp);
609 while
(!tmp.endoffileflag
);
610 fip-
>streamstart
= tmp.hdrend
;
612 return fip-
>streamstart
;
616 static void rd_jbig2_info
(FILEINFO
* fip
)
618 unsigned long seekdist
= 0; /* for sequential-access only
*/
619 unsigned long streampos
= 0; /* for random-access only
*/
620 unsigned long currentpage
= 0;
621 boolean sipavail
= false
;
625 fip-
>file
= xfopen
(fip-
>filepath
, FOPEN_RBIN_MODE
);
627 if
(!fip-
>sequentialaccess
) /* D
.2 Random-access organisation
*/
628 streampos
= findstreamstart
(fip
);
629 while
(true
) { /* loop over segments
*/
631 sip
= xtalloc
(1, SEGINFO
);
635 if
(!readseghdr
(fip
, sip
) || sip-
>endoffileflag
)
637 if
(sip-
>segpage
> 0) {
638 if
(sip-
>segpage
> (int
) currentpage
) {
639 plp
= litem_append
(&(fip->pages));
640 plp-
>last-
>d
= new_pageinfo
();
641 currentpage
= (unsigned long
) sip-
>segpage
;
643 pip
= fip-
>pages.last-
>d
;
645 if
(fip-
>page0.last
== NULL) {
646 plp
= litem_append
(&(fip->page0));
647 plp-
>last-
>d
= new_pageinfo
();
649 pip
= fip-
>page0.last-
>d
;
651 if
(!sip-
>endofpageflag
) {
652 slp
= litem_append
(&(pip->segments));
656 if
(!fip-
>sequentialaccess
)
657 sip-
>datastart
= streampos
;
659 sip-
>datastart
= sip-
>hdrend
;
660 sip-
>dataend
= sip-
>datastart
+ sip-
>segdatalen
;
661 if
(!fip-
>sequentialaccess
662 && (sip->pageinfoflag || sip->endofstripeflag))
663 xfseeko
(fip-
>file
, (off_t
) sip-
>datastart
, SEEK_SET
, fip-
>filepath
);
664 seekdist
= sip-
>segdatalen
;
665 /* 7.4.8 Page information segment syntax
*/
666 if
(sip-
>pageinfoflag
) {
667 pip-
>pagenum
= (unsigned long
) sip-
>segpage
;
668 pip-
>width
= read4bytes
(fip-
>file
);
669 pip-
>height
= read4bytes
(fip-
>file
);
670 pip-
>xres
= read4bytes
(fip-
>file
);
671 pip-
>yres
= read4bytes
(fip-
>file
);
672 pip-
>pagesegmentflags
= (unsigned
) ygetc
(fip-
>file
);
673 /* 7.4.8.6 Page striping information
*/
674 pip-
>stripinginfo
= read2bytes
(fip-
>file
);
677 if
(sip-
>endofstripeflag
) {
678 pip-
>stripedheight
= read4bytes
(fip-
>file
);
681 if
(!fip-
>sequentialaccess
682 && (sip->pageinfoflag || sip->endofstripeflag))
683 xfseeko
(fip-
>file
, (off_t
) sip-
>hdrend
, SEEK_SET
, fip-
>filepath
);
684 if
(!fip-
>sequentialaccess
)
685 streampos
+= sip-
>segdatalen
;
686 if
(fip-
>sequentialaccess
)
687 xfseeko
(fip-
>file
, (off_t
) seekdist
, SEEK_CUR
, fip-
>filepath
);
688 if
(sip-
>endofpageflag
&& currentpage && (pip->stripinginfo >> 15))
689 pip-
>height
= pip-
>stripedheight
;
691 fip-
>phase
= HAVEINFO
;
694 xfclose
(fip-
>file
, fip-
>filepath
);
698 static void wr_jbig2
(PDF pdf
, image_dict
* idict
, FILEINFO
* fip
,
706 assert
(idict
!= NULL);
707 pip
= find_pageinfo
(&(fip->pages), page);
709 pdf_begin_obj
(pdf
, img_objnum
(idict
), OBJSTM_NEVER
);
711 pdf_dict_add_name
(pdf
, "Type", "XObject");
712 pdf_dict_add_name
(pdf
, "Subtype", "Image");
713 pdf_dict_add_img_filename
(pdf
, idict
);
714 pdf_dict_add_int
(pdf
, "Width", pip-
>width
);
715 pdf_dict_add_int
(pdf
, "Height", pip-
>height
);
716 pdf_dict_add_name
(pdf
, "ColorSpace", "DeviceGray");
717 pdf_dict_add_int
(pdf
, "BitsPerComponent", 1);
718 pdf_dict_add_int
(pdf
, "Length", getstreamlen
(pip-
>segments.first
, true
));
719 pdf_add_name
(pdf
, "Filter");
720 pdf_begin_array
(pdf
);
721 pdf_add_name
(pdf
, "JBIG2Decode");
723 if
(fip-
>page0.last
!= NULL) {
724 if
(fip-
>pdfpage0objnum
== 0) {
725 fip-
>pdfpage0objnum
= (unsigned long
) pdf_create_obj
(pdf
, obj_type_others
, 0);
727 pdf_add_name
(pdf
, "DecodeParms");
728 pdf_begin_array
(pdf
);
730 pdf_dict_add_ref
(pdf
, "JBIG2Globals", fip-
>pdfpage0objnum
);
736 assert
(idict
== NULL);
737 pip
= find_pageinfo
(&(fip->page0), page);
739 pdf_begin_obj
(pdf
, (int
) fip-
>pdfpage0objnum
, OBJSTM_NEVER
);
741 pdf_dict_add_int
(pdf
, "Length", getstreamlen
(pip-
>segments.first
, false
));
744 pdf_begin_stream
(pdf
);
745 fip-
>file
= xfopen
(fip-
>filepath
, FOPEN_RBIN_MODE
);
746 for
(slip
= pip-
>segments.first
; slip
!= NULL; slip
= slip-
>next
) { /* loop over page segments
*/
748 if
(sip-
>isrefered || page
> 0) {
749 xfseeko
(fip-
>file
, (off_t
) sip-
>hdrstart
, SEEK_SET
, fip-
>filepath
);
750 /* mark refered-to page
0 segments
, change segpages
> 1 to
1 */
751 writeseghdr
(pdf
, fip
, sip
);
752 xfseeko
(fip-
>file
, (off_t
) sip-
>datastart
, SEEK_SET
, fip-
>filepath
);
753 for
(i
= sip-
>datastart
; i
< sip-
>dataend
; i
++)
754 pdf_out
(pdf
, ygetc
(fip-
>file
));
759 xfclose
(fip-
>file
, fip-
>filepath
);
763 boolean supported_jbig2
(image_dict
* idict
)
765 if
(img_pdfminorversion
(idict
) < 4) {
766 normal_error
("readjbig2","you need to generate at least PDF 1.4");
774 void flush_jbig2_info
(image_dict
* idict
)
780 void read_jbig2_info
(image_dict
* idict
)
784 img_type
(idict
) = IMG_TYPE_JBIG2
; /* already set probably
, see other read_...
*/
785 if
(! supported_jbig2
(idict
)) {
786 /* already an error done
*/
788 if
(img_pagenum
(idict
) < 1) {
789 normal_error
("readjbig2","page must be > 0");
791 if
(file_tree
== NULL) {
792 file_tree
= avl_create
(comp_file_entry
, NULL, &avl_xallocator);
794 tmp.filepath
= img_filepath
(idict
);
795 fip
= (FILEINFO
*) avl_find
(file_tree
, &tmp);
797 fip
= new_fileinfo
();
798 fip-
>filepath
= xstrdup
(img_filepath
(idict
));
799 avl_probe
(file_tree
, fip
);
801 if
(fip-
>phase
== INITIAL) {
803 pages_maketree
(&(fip->pages));
804 if
(fip-
>page0.last
!= NULL) {
805 pages_maketree
(&(fip->page0));
806 pip
= fip-
>page0.first-
>d
;
807 segments_maketree
(&(pip->segments));
810 pip
= find_pageinfo
(&(fip->pages), (unsigned long) img_pagenum(idict));
812 formatted_error
("readjbig2","page %d not found in image file",(int
) img_pagenum
(idict
));
814 img_totalpages
(idict
) = (int
) fip-
>numofpages
;
815 img_xsize
(idict
) = (int
) pip-
>width
;
816 img_ysize
(idict
) = (int
) pip-
>height
;
817 img_xres
(idict
) = (int
) (pip-
>xres
* 0.0254 + 0.5);
818 img_yres
(idict
) = (int
) (pip-
>yres
* 0.0254 + 0.5);
819 img_colordepth
(idict
) = 1;
823 void write_jbig2
(PDF pdf
, image_dict
* idict
)
827 assert
(idict
!= NULL);
828 assert
(file_tree
!= NULL);
829 tmp.filepath
= img_filepath
(idict
);
830 fip
= (FILEINFO
*) avl_find
(file_tree
, &tmp);
832 assert
(fip-
>phase
== HAVEINFO
); /* don't write before |rd_jbig2_info
()| call
*/
833 pip
= find_pageinfo
(&(fip->pages), (unsigned long) img_pagenum(idict));
835 wr_jbig2
(pdf
, idict
, fip
, pip-
>pagenum
);
836 img_file
(idict
) = NULL;
840 void flush_jbig2_page0_objects
(PDF pdf
)
843 struct avl_traverser t
;
844 if
(file_tree
!= NULL) {
845 avl_t_init
(&t, file_tree);
846 for
(fip
= avl_t_first
(&t, file_tree); fip != NULL;
847 fip
= avl_t_next
(&t)) {
848 if
(fip-
>page0.last
!= NULL)
849 wr_jbig2
(pdf
, NULL, fip
, 0); /* NULL: page0
*/