3 % Copyright
2011-2013 Taco Hoekwater
<taco@@luatex.org
>
4 % Copyright
2011-2013 Hartmut Henkel
<hartmut@@luatex.org
>
6 % This file is part of LuaTeX.
8 % LuaTeX is free software
; you can redistribute it and
/or modify it under
9 % the terms of the GNU General Public License as published by the Free
10 % Software Foundation
; either version
2 of the License
, or
(at your
11 % option
) any later version.
13 % LuaTeX is distributed in the hope that it will be useful
, but WITHOUT
14 % ANY WARRANTY
; without even the implied warranty of MERCHANTABILITY or
15 % FITNESS
FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
16 % License for more details.
18 % You should have received a copy of the GNU General Public License along
19 % with LuaTeX
; if not
, see
<http
://www.gnu.org
/licenses
/>.
23 @ Basic JPEG
~2000 image support. Section and Table references below
:
24 Information technology
--- JPEG
~2000 image coding system
: Core coding system.
25 ISO
/IEC
15444-1, Second edition
, 2004-09-15, file |
15444-1annexi.pdf|.
31 #include
"image/image.h"
32 #include
"image/writejp2.h"
33 #include
"image/writejbig2.h" /* read2bytes
(), read4bytes
() */
35 /* Table
1.2 -- Defined boxes
*/
36 #define BOX_JP
0x6A502020
37 #define BOX_FTYP
0x66747970
38 #define BOX_JP2H
0x6a703268
39 #define BOX_IHDR
0x69686472
40 #define BOX_BPCC
0x62706363
41 #define BOX_COLR
0x636D6170
42 #define BOX_CDEF
0x63646566
43 #define BOX_RES
0x72657320
44 #define BOX_RESC
0x72657363
45 #define BOX_RESD
0x72657364
46 #define BOX_JP2C
0x6A703263
48 /* 1.4 Box definition
*/
54 static uint64_t read8bytes
(FILE * f
)
56 uint64_t l
= read4bytes
(f
);
57 l
= (l
<< 32) + read4bytes
(f
);
61 static hdr_struct read_boxhdr
(image_dict
* idict
)
64 hdr.lbox
= read4bytes
(img_file
(idict
));
65 hdr.tbox
= read4bytes
(img_file
(idict
));
67 hdr.lbox
= read8bytes
(img_file
(idict
));
68 if
(hdr.lbox
== 0 && hdr.tbox != BOX_JP2C) {
69 normal_error
("readjp2","LBox == 0");
74 /* 1.5.3.1 Image Header box
*/
75 static void scan_ihdr
(image_dict
* idict
)
77 unsigned int height
, width
;
79 height
= read4bytes
(img_file
(idict
));
80 width
= read4bytes
(img_file
(idict
));
81 img_ysize
(idict
) = (int
) height
;
82 img_xsize
(idict
) = (int
) width
;
83 (void
) read2bytes
(img_file
(idict
)); /* nc
*/
84 bpc
= (unsigned char
) xgetc
(img_file
(idict
));
85 img_colordepth
(idict
) = bpc
+ 1;
86 (void
) xgetc
(img_file
(idict
)); /* c
*/
87 (void
) xgetc
(img_file
(idict
)); /* unkc
*/
88 (void
) xgetc
(img_file
(idict
)); /* ipr
*/
91 /* 1.5.3.7.1 Capture Resolution box
*/
92 /* 1.5.3.7.2 Default Display Resolution box
*/
94 static void scan_resc_resd
(image_dict
* idict
)
96 unsigned int vr_n
, vr_d
, hr_n
, hr_d
;
97 unsigned char vr_e
, hr_e
;
99 vr_n
= read2bytes
(img_file
(idict
));
100 vr_d
= read2bytes
(img_file
(idict
));
101 hr_n
= read2bytes
(img_file
(idict
));
102 hr_d
= read2bytes
(img_file
(idict
));
103 vr_e
= (unsigned char
) xgetc
(img_file
(idict
));
104 hr_e
= (unsigned char
) xgetc
(img_file
(idict
));
105 hr_
= ((double
) hr_n
/ hr_d
) * exp
(hr_e
* log
(10.0)) * 0.0254;
106 vr_
= ((double
) vr_n
/ vr_d
) * exp
(vr_e
* log
(10.0)) * 0.0254;
107 img_xres
(idict
) = (int
) (hr_
+ 0.5);
108 img_yres
(idict
) = (int
) (vr_
+ 0.5);
111 /* 1.5.3.7 Resolution box
(superbox
) */
113 static void scan_res
(image_dict
* idict
, uint64_t epos_s
)
117 epos
= xftell
(img_file
(idict
), img_filepath
(idict
));
120 hdr
= read_boxhdr
(idict
);
121 epos
= spos
+ hdr.lbox
;
124 /* arbitrarily
: let BOX_RESD have precedence
*/
125 if
(img_xres
(idict
) == 0 && img_yres(idict) == 0) {
126 scan_resc_resd
(idict
);
127 if
(xftell
(img_file
(idict
), img_filepath
(idict
)) != (long
)epos
)
128 normal_error
("readjp2","resc box size inconsistent");
132 scan_resc_resd
(idict
);
133 if
(xftell
(img_file
(idict
), img_filepath
(idict
)) != (long
)epos
)
134 normal_error
("readjp2","resd box size inconsistent");
139 normal_error
("readjp2","res box size inconsistent");
142 xfseek
(img_file
(idict
), (long
) epos
, SEEK_SET
, img_filepath
(idict
));
146 /* 1.5.3 JP2 Header box
(superbox
) */
148 static boolean scan_jp2h
(image_dict
* idict
, uint64_t epos_s
)
150 boolean ihdr_found
= false
;
153 epos
= xftell
(img_file
(idict
), img_filepath
(idict
));
156 hdr
= read_boxhdr
(idict
);
157 epos
= spos
+ hdr.lbox
;
161 if
(xftell
(img_file
(idict
), img_filepath
(idict
)) != (long
)epos
)
162 normal_error
("readjp2","ihdr box size inconsistent");
166 scan_res
(idict
, epos
);
171 normal_error
("readjp2","jp2h box size inconsistent");
174 xfseek
(img_file
(idict
), (long
) epos
, SEEK_SET
, img_filepath
(idict
));
179 static void close_and_cleanup_jp2
(image_dict
* idict
)
181 /* if one of then is not
NULL we already cleaned up
*/
182 if
(img_file
(idict
) != NULL) {
183 xfclose
(img_file
(idict
), img_filepath
(idict
));
184 img_file
(idict
) = NULL;
186 if
(img_jp2_ptr
(idict
) != NULL) {
187 xfree
(img_jp2_ptr
(idict
));
191 void flush_jp2_info
(image_dict
* idict
)
193 close_and_cleanup_jp2
(idict
);
196 void read_jp2_info
(image_dict
* idict
)
198 boolean ihdr_found
= false
;
201 if
(img_type
(idict
) != IMG_TYPE_JP2
) {
202 normal_error
("readjp2","conflicting image dictionary");
204 if
(img_file
(idict
) != NULL) {
205 normal_error
("readjp2","image data already read");
207 img_totalpages
(idict
) = 1;
208 img_pagenum
(idict
) = 1;
209 img_xres
(idict
) = img_yres
(idict
) = 0;
210 img_file
(idict
) = xfopen
(img_filepath
(idict
), FOPEN_RBIN_MODE
);
211 img_jp2_ptr
(idict
) = xtalloc
(1, jp2_img_struct
);
212 xfseek
(img_file
(idict
), 0, SEEK_END
, img_filepath
(idict
));
213 img_jp2_ptr
(idict
)->length
= (int
) xftell
(img_file
(idict
), img_filepath
(idict
));
214 xfseek
(img_file
(idict
), 0, SEEK_SET
, img_filepath
(idict
));
215 if
(sizeof
(uint64_t
) < 8) {
216 normal_error
("readjp2","size problem");
219 /* 1.5.1 JPEG
2000 Signature box
*/
220 hdr
= read_boxhdr
(idict
);
221 epos
= spos
+ hdr.lbox
;
222 xfseek
(img_file
(idict
), (long
) epos
, SEEK_SET
, img_filepath
(idict
));
223 /* 1.5.2 File Type box
*/
225 hdr
= read_boxhdr
(idict
);
226 if
(hdr.tbox
!= BOX_FTYP
) {
227 normal_error
("readjp2","missing ftyp box");
229 epos
= spos
+ hdr.lbox
;
230 xfseek
(img_file
(idict
), (long
) epos
, SEEK_SET
, img_filepath
(idict
));
231 while
(!ihdr_found
) {
233 hdr
= read_boxhdr
(idict
);
234 epos
= spos
+ hdr.lbox
;
237 ihdr_found
= scan_jp2h
(idict
, epos
);
241 normal_error
("readjp2","no ihdr box found");
245 xfseek
(img_file
(idict
), (long
) epos
, SEEK_SET
, img_filepath
(idict
));
247 if
(! img_keepopen
(idict
)) {
248 close_and_cleanup_jp2
(idict
);
252 static void reopen_jp2
(image_dict
* idict
)
254 int width
, height
, xres
, yres
;
255 width
= img_xsize
(idict
);
256 height
= img_ysize
(idict
);
257 xres
= img_xres
(idict
);
258 yres
= img_yres
(idict
);
260 we need to make sure that the file kept open
262 img_keepopen
(idict
) = 1;
263 read_jp2_info
(idict
);
264 if
(width
!= img_xsize
(idict
) || height
!= img_ysize
(idict
)
265 || xres
!= img_xres
(idict
) || yres
!= img_yres
(idict
)) {
266 normal_error
("writejp2","image dimensions have changed");
270 void write_jp2
(PDF pdf
, image_dict
* idict
)
273 if
(img_file
(idict
) == NULL) {
276 pdf_begin_obj
(pdf
, img_objnum
(idict
), OBJSTM_NEVER
);
278 pdf_dict_add_name
(pdf
, "Type", "XObject");
279 pdf_dict_add_name
(pdf
, "Subtype", "Image");
280 pdf_dict_add_img_filename
(pdf
, idict
);
281 if
(img_attr
(idict
) != NULL && strlen(img_attr(idict)) > 0)
282 pdf_printf
(pdf
, "\n%s\n", img_attr
(idict
));
283 pdf_dict_add_int
(pdf
, "Width", (int
) img_xsize
(idict
));
284 pdf_dict_add_int
(pdf
, "Height", (int
) img_ysize
(idict
));
285 pdf_dict_add_int
(pdf
, "Length", (int
) img_jp2_ptr
(idict
)->length
);
286 pdf_dict_add_name
(pdf
, "Filter", "JPXDecode");
288 pdf_begin_stream
(pdf
);
289 l
= (long unsigned int
) img_jp2_ptr
(idict
)->length
;
290 xfseek
(img_file
(idict
), 0, SEEK_SET
, img_filepath
(idict
));
291 if
(read_file_to_buf
(pdf
, img_file
(idict
), l
) != l
)
292 normal_error
("writejp2","fread failed");
296 close_and_cleanup_jp2
(idict
);