fix getsup (HH)
[luatex.git] / source / texk / web2c / luatexdir / image / writejp2.w
blobcb317e11928a4b6f9a147860ab4d8157bef78c51
1 % writejp2.w
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/>.
21 @ @c
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|.
28 #include "ptexlib.h"
29 #include <math.h>
30 #include <assert.h>
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 */
49 typedef struct {
50 uint64_t lbox;
51 unsigned int tbox;
52 } hdr_struct;
54 static uint64_t read8bytes(FILE * f)
56 uint64_t l = read4bytes(f);
57 l = (l << 32) + read4bytes(f);
58 return l;
61 static hdr_struct read_boxhdr(image_dict * idict)
63 hdr_struct hdr;
64 hdr.lbox = read4bytes(img_file(idict));
65 hdr.tbox = read4bytes(img_file(idict));
66 if (hdr.lbox == 1)
67 hdr.lbox = read8bytes(img_file(idict));
68 if (hdr.lbox == 0 && hdr.tbox != BOX_JP2C) {
69 normal_error("readjp2","LBox == 0");
71 return hdr;
74 /* 1.5.3.1 Image Header box */
75 static void scan_ihdr(image_dict * idict)
77 unsigned int height, width;
78 unsigned char bpc;
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;
98 double hr_, vr_;
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)
115 hdr_struct hdr;
116 uint64_t spos, epos;
117 epos = xftell(img_file(idict), img_filepath(idict));
118 while (1) {
119 spos = epos;
120 hdr = read_boxhdr(idict);
121 epos = spos + hdr.lbox;
122 switch (hdr.tbox) {
123 case (BOX_RESC):
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");
130 break;
131 case (BOX_RESD):
132 scan_resc_resd(idict);
133 if (xftell(img_file(idict), img_filepath(idict)) != (long)epos)
134 normal_error("readjp2","resd box size inconsistent");
135 break;
136 default:;
138 if (epos > epos_s)
139 normal_error("readjp2","res box size inconsistent");
140 if (epos == epos_s)
141 break;
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;
151 hdr_struct hdr;
152 uint64_t spos, epos;
153 epos = xftell(img_file(idict), img_filepath(idict));
154 while (1) {
155 spos = epos;
156 hdr = read_boxhdr(idict);
157 epos = spos + hdr.lbox;
158 switch (hdr.tbox) {
159 case (BOX_IHDR):
160 scan_ihdr(idict);
161 if (xftell(img_file(idict), img_filepath(idict)) != (long)epos)
162 normal_error("readjp2","ihdr box size inconsistent");
163 ihdr_found = true;
164 break;
165 case (BOX_RES):
166 scan_res(idict, epos);
167 break;
168 default:;
170 if (epos > epos_s)
171 normal_error("readjp2","jp2h box size inconsistent");
172 if (epos == epos_s)
173 break;
174 xfseek(img_file(idict), (long) epos, SEEK_SET, img_filepath(idict));
176 return ihdr_found;
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;
199 hdr_struct hdr;
200 uint64_t spos, epos;
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");
218 spos = epos = 0;
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 */
224 spos = epos;
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) {
232 spos = epos;
233 hdr = read_boxhdr(idict);
234 epos = spos + hdr.lbox;
235 switch (hdr.tbox) {
236 case BOX_JP2H:
237 ihdr_found = scan_jp2h(idict, epos);
238 break;
239 case BOX_JP2C:
240 if (!ihdr_found)
241 normal_error("readjp2","no ihdr box found");
242 break;
243 default:;
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)
272 long unsigned l;
273 if (img_file(idict) == NULL) {
274 reopen_jp2(idict);
276 pdf_begin_obj(pdf, img_objnum(idict), OBJSTM_NEVER);
277 pdf_begin_dict(pdf);
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");
287 pdf_end_dict(pdf);
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");
293 pdf_end_stream(pdf);
294 pdf_end_obj(pdf);
295 /* always */
296 close_and_cleanup_jp2(idict);