corrade-vassal – Blame information for rev 1
?pathlinks?
Rev | Author | Line No. | Line |
---|---|---|---|
1 | vero | 1 | /* |
2 | * Copyright (c) 2002-2007, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium |
||
3 | * Copyright (c) 2002-2007, Professor Benoit Macq |
||
4 | * Copyright (c) 2001-2003, David Janssens |
||
5 | * Copyright (c) 2002-2003, Yannick Verschueren |
||
6 | * Copyright (c) 2003-2007, Francois-Olivier Devaux and Antonin Descampe |
||
7 | * Copyright (c) 2005, Herve Drolon, FreeImage Team |
||
8 | * Copyright (c) 2010-2011, Kaori Hagihara |
||
9 | * All rights reserved. |
||
10 | * |
||
11 | * Redistribution and use in source and binary forms, with or without |
||
12 | * modification, are permitted provided that the following conditions |
||
13 | * are met: |
||
14 | * 1. Redistributions of source code must retain the above copyright |
||
15 | * notice, this list of conditions and the following disclaimer. |
||
16 | * 2. Redistributions in binary form must reproduce the above copyright |
||
17 | * notice, this list of conditions and the following disclaimer in the |
||
18 | * documentation and/or other materials provided with the distribution. |
||
19 | * |
||
20 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS' |
||
21 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
||
22 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
||
23 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE |
||
24 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
||
25 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
||
26 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
||
27 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
||
28 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
||
29 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
||
30 | * POSSIBILITY OF SUCH DAMAGE. |
||
31 | */ |
||
32 | #include "opj_includes.h" |
||
33 | |||
34 | /** @defgroup JP2 JP2 - JPEG-2000 file format reader/writer */ |
||
35 | /*@{*/ |
||
36 | |||
37 | /** @name Local static functions */ |
||
38 | /*@{*/ |
||
39 | |||
40 | /** |
||
41 | Read box headers |
||
42 | @param cinfo Codec context info |
||
43 | @param cio Input stream |
||
44 | @param box |
||
45 | @return Returns true if successful, returns false otherwise |
||
46 | */ |
||
47 | static opj_bool jp2_read_boxhdr(opj_common_ptr cinfo, opj_cio_t *cio, opj_jp2_box_t *box); |
||
48 | /*static void jp2_write_url(opj_cio_t *cio, char *Idx_file);*/ |
||
49 | /** |
||
50 | Read the IHDR box - Image Header box |
||
51 | @param jp2 JP2 handle |
||
52 | @param cio Input buffer stream |
||
53 | @return Returns true if successful, returns false otherwise |
||
54 | */ |
||
55 | static opj_bool jp2_read_ihdr(opj_jp2_t *jp2, opj_cio_t *cio); |
||
56 | static void jp2_write_ihdr(opj_jp2_t *jp2, opj_cio_t *cio); |
||
57 | static void jp2_write_bpcc(opj_jp2_t *jp2, opj_cio_t *cio); |
||
58 | static opj_bool jp2_read_bpcc(opj_jp2_t *jp2, opj_cio_t *cio); |
||
59 | static void jp2_write_colr(opj_jp2_t *jp2, opj_cio_t *cio); |
||
60 | /** |
||
61 | Write the FTYP box - File type box |
||
62 | @param jp2 JP2 handle |
||
63 | @param cio Output buffer stream |
||
64 | */ |
||
65 | static void jp2_write_ftyp(opj_jp2_t *jp2, opj_cio_t *cio); |
||
66 | /** |
||
67 | Read the FTYP box - File type box |
||
68 | @param jp2 JP2 handle |
||
69 | @param cio Input buffer stream |
||
70 | @return Returns true if successful, returns false otherwise |
||
71 | */ |
||
72 | static opj_bool jp2_read_ftyp(opj_jp2_t *jp2, opj_cio_t *cio); |
||
73 | static int jp2_write_jp2c(opj_jp2_t *jp2, opj_cio_t *cio, opj_image_t *image, opj_codestream_info_t *cstr_info); |
||
74 | static opj_bool jp2_read_jp2c(opj_jp2_t *jp2, opj_cio_t *cio, unsigned int *j2k_codestream_length, unsigned int *j2k_codestream_offset); |
||
75 | static void jp2_write_jp(opj_cio_t *cio); |
||
76 | /** |
||
77 | Read the JP box - JPEG 2000 signature |
||
78 | @param jp2 JP2 handle |
||
79 | @param cio Input buffer stream |
||
80 | @return Returns true if successful, returns false otherwise |
||
81 | */ |
||
82 | static opj_bool jp2_read_jp(opj_jp2_t *jp2, opj_cio_t *cio); |
||
83 | /** |
||
84 | Decode the structure of a JP2 file |
||
85 | @param jp2 JP2 handle |
||
86 | @param cio Input buffer stream |
||
87 | @param color Collector for profile, cdef and pclr data |
||
88 | @return Returns true if successful, returns false otherwise |
||
89 | */ |
||
90 | static opj_bool jp2_read_struct(opj_jp2_t *jp2, opj_cio_t *cio, |
||
91 | opj_jp2_color_t *color); |
||
92 | /** |
||
93 | Apply collected palette data |
||
94 | @param color Collector for profile, cdef and pclr data |
||
95 | @param image |
||
96 | */ |
||
97 | static void jp2_apply_pclr(opj_jp2_color_t *color, opj_image_t *image, opj_common_ptr cinfo); |
||
98 | /** |
||
99 | Collect palette data |
||
100 | @param jp2 JP2 handle |
||
101 | @param cio Input buffer stream |
||
102 | @param box |
||
103 | @param color Collector for profile, cdef and pclr data |
||
104 | @return Returns true if successful, returns false otherwise |
||
105 | */ |
||
106 | static opj_bool jp2_read_pclr(opj_jp2_t *jp2, opj_cio_t *cio, |
||
107 | opj_jp2_box_t *box, opj_jp2_color_t *color); |
||
108 | /** |
||
109 | Collect component mapping data |
||
110 | @param jp2 JP2 handle |
||
111 | @param cio Input buffer stream |
||
112 | @param box |
||
113 | @param color Collector for profile, cdef and pclr data |
||
114 | @return Returns true if successful, returns false otherwise |
||
115 | */ |
||
116 | static opj_bool jp2_read_cmap(opj_jp2_t *jp2, opj_cio_t *cio, |
||
117 | opj_jp2_box_t *box, opj_jp2_color_t *color); |
||
118 | /** |
||
119 | Collect colour specification data |
||
120 | @param jp2 JP2 handle |
||
121 | @param cio Input buffer stream |
||
122 | @param box |
||
123 | @param color Collector for profile, cdef and pclr data |
||
124 | @return Returns true if successful, returns false otherwise |
||
125 | */ |
||
126 | static opj_bool jp2_read_colr(opj_jp2_t *jp2, opj_cio_t *cio, |
||
127 | opj_jp2_box_t *box, opj_jp2_color_t *color); |
||
128 | /** |
||
129 | Write file Index (superbox) |
||
130 | @param[in] offset_jp2c offset of jp2c box |
||
131 | @param[in] length_jp2c length of jp2c box |
||
132 | @param[in] offset_idx offset of cidx box |
||
133 | @param[in] length_idx length of cidx box |
||
134 | @param[in] cio file output handle |
||
135 | @return length of fidx box |
||
136 | */ |
||
137 | static int write_fidx( int offset_jp2c, int length_jp2c, int offset_idx, int length_idx, opj_cio_t *cio); |
||
138 | /** |
||
139 | Write index Finder box |
||
140 | @param[in] offset offset of fidx box |
||
141 | @param[in] length length of fidx box |
||
142 | @param[in] cio file output handle |
||
143 | */ |
||
144 | static void write_iptr( int offset, int length, opj_cio_t *cio); |
||
145 | /** |
||
146 | Write proxy box |
||
147 | @param[in] offset_jp2c offset of jp2c box |
||
148 | @param[in] length_jp2c length of jp2c box |
||
149 | @param[in] offset_idx offset of cidx box |
||
150 | @param[in] length_idx length of cidx box |
||
151 | @param[in] cio file output handle |
||
152 | */ |
||
153 | static void write_prxy( int offset_jp2c, int length_jp2c, int offset_idx, int length_idx, opj_cio_t *cio); |
||
154 | /*@}*/ |
||
155 | |||
156 | /*@}*/ |
||
157 | |||
158 | /* ----------------------------------------------------------------------- */ |
||
159 | |||
160 | static opj_bool jp2_read_boxhdr(opj_common_ptr cinfo, opj_cio_t *cio, opj_jp2_box_t *box) { |
||
161 | box->init_pos = cio_tell(cio); |
||
162 | box->length = cio_read(cio, 4); |
||
163 | box->type = cio_read(cio, 4); |
||
164 | if (box->length == 1) { |
||
165 | if (cio_read(cio, 4) != 0) { |
||
166 | opj_event_msg(cinfo, EVT_ERROR, "Cannot handle box sizes higher than 2^32\n"); |
||
167 | return OPJ_FALSE; |
||
168 | } |
||
169 | box->length = cio_read(cio, 4); |
||
170 | if (box->length == 0) |
||
171 | box->length = cio_numbytesleft(cio) + 12; |
||
172 | } |
||
173 | else if (box->length == 0) { |
||
174 | box->length = cio_numbytesleft(cio) + 8; |
||
175 | } |
||
176 | |||
177 | return OPJ_TRUE; |
||
178 | } |
||
179 | |||
180 | #if 0 |
||
181 | static void jp2_write_url(opj_cio_t *cio, char *Idx_file) { |
||
182 | unsigned int i; |
||
183 | opj_jp2_box_t box; |
||
184 | |||
185 | box.init_pos = cio_tell(cio); |
||
186 | cio_skip(cio, 4); |
||
187 | cio_write(cio, JP2_URL, 4); /* DBTL */ |
||
188 | cio_write(cio, 0, 1); /* VERS */ |
||
189 | cio_write(cio, 0, 3); /* FLAG */ |
||
190 | |||
191 | if(Idx_file) { |
||
192 | for (i = 0; i < strlen(Idx_file); i++) { |
||
193 | cio_write(cio, Idx_file[i], 1); |
||
194 | } |
||
195 | } |
||
196 | |||
197 | box.length = cio_tell(cio) - box.init_pos; |
||
198 | cio_seek(cio, box.init_pos); |
||
199 | cio_write(cio, box.length, 4); /* L */ |
||
200 | cio_seek(cio, box.init_pos + box.length); |
||
201 | } |
||
202 | #endif |
||
203 | |||
204 | static opj_bool jp2_read_ihdr(opj_jp2_t *jp2, opj_cio_t *cio) { |
||
205 | opj_jp2_box_t box; |
||
206 | |||
207 | opj_common_ptr cinfo = jp2->cinfo; |
||
208 | |||
209 | jp2_read_boxhdr(cinfo, cio, &box); |
||
210 | if (JP2_IHDR != box.type) { |
||
211 | opj_event_msg(cinfo, EVT_ERROR, "Expected IHDR Marker\n"); |
||
212 | return OPJ_FALSE; |
||
213 | } |
||
214 | |||
215 | jp2->h = cio_read(cio, 4); /* HEIGHT */ |
||
216 | jp2->w = cio_read(cio, 4); /* WIDTH */ |
||
217 | jp2->numcomps = cio_read(cio, 2); /* NC */ |
||
218 | jp2->comps = (opj_jp2_comps_t*) opj_malloc(jp2->numcomps * sizeof(opj_jp2_comps_t)); |
||
219 | |||
220 | jp2->bpc = cio_read(cio, 1); /* BPC */ |
||
221 | |||
222 | jp2->C = cio_read(cio, 1); /* C */ |
||
223 | jp2->UnkC = cio_read(cio, 1); /* UnkC */ |
||
224 | jp2->IPR = cio_read(cio, 1); /* IPR */ |
||
225 | |||
226 | if (cio_tell(cio) - box.init_pos != box.length) { |
||
227 | opj_event_msg(cinfo, EVT_ERROR, "Error with IHDR Box\n"); |
||
228 | return OPJ_FALSE; |
||
229 | } |
||
230 | |||
231 | return OPJ_TRUE; |
||
232 | } |
||
233 | |||
234 | static void jp2_write_ihdr(opj_jp2_t *jp2, opj_cio_t *cio) { |
||
235 | opj_jp2_box_t box; |
||
236 | |||
237 | box.init_pos = cio_tell(cio); |
||
238 | cio_skip(cio, 4); |
||
239 | cio_write(cio, JP2_IHDR, 4); /* IHDR */ |
||
240 | |||
241 | cio_write(cio, jp2->h, 4); /* HEIGHT */ |
||
242 | cio_write(cio, jp2->w, 4); /* WIDTH */ |
||
243 | cio_write(cio, jp2->numcomps, 2); /* NC */ |
||
244 | |||
245 | cio_write(cio, jp2->bpc, 1); /* BPC */ |
||
246 | |||
247 | cio_write(cio, jp2->C, 1); /* C : Always 7 */ |
||
248 | cio_write(cio, jp2->UnkC, 1); /* UnkC, colorspace unknown */ |
||
249 | cio_write(cio, jp2->IPR, 1); /* IPR, no intellectual property */ |
||
250 | |||
251 | box.length = cio_tell(cio) - box.init_pos; |
||
252 | cio_seek(cio, box.init_pos); |
||
253 | cio_write(cio, box.length, 4); /* L */ |
||
254 | cio_seek(cio, box.init_pos + box.length); |
||
255 | } |
||
256 | |||
257 | static void jp2_write_bpcc(opj_jp2_t *jp2, opj_cio_t *cio) { |
||
258 | unsigned int i; |
||
259 | opj_jp2_box_t box; |
||
260 | |||
261 | box.init_pos = cio_tell(cio); |
||
262 | cio_skip(cio, 4); |
||
263 | cio_write(cio, JP2_BPCC, 4); /* BPCC */ |
||
264 | |||
265 | for (i = 0; i < jp2->numcomps; i++) { |
||
266 | cio_write(cio, jp2->comps[i].bpcc, 1); |
||
267 | } |
||
268 | |||
269 | box.length = cio_tell(cio) - box.init_pos; |
||
270 | cio_seek(cio, box.init_pos); |
||
271 | cio_write(cio, box.length, 4); /* L */ |
||
272 | cio_seek(cio, box.init_pos + box.length); |
||
273 | } |
||
274 | |||
275 | |||
276 | static opj_bool jp2_read_bpcc(opj_jp2_t *jp2, opj_cio_t *cio) { |
||
277 | unsigned int i; |
||
278 | opj_jp2_box_t box; |
||
279 | |||
280 | opj_common_ptr cinfo = jp2->cinfo; |
||
281 | |||
282 | jp2_read_boxhdr(cinfo, cio, &box); |
||
283 | if (JP2_BPCC != box.type) { |
||
284 | opj_event_msg(cinfo, EVT_ERROR, "Expected BPCC Marker\n"); |
||
285 | return OPJ_FALSE; |
||
286 | } |
||
287 | |||
288 | for (i = 0; i < jp2->numcomps; i++) { |
||
289 | jp2->comps[i].bpcc = cio_read(cio, 1); |
||
290 | } |
||
291 | |||
292 | if (cio_tell(cio) - box.init_pos != box.length) { |
||
293 | opj_event_msg(cinfo, EVT_ERROR, "Error with BPCC Box\n"); |
||
294 | return OPJ_FALSE; |
||
295 | } |
||
296 | |||
297 | return OPJ_TRUE; |
||
298 | } |
||
299 | |||
300 | static void jp2_write_colr(opj_jp2_t *jp2, opj_cio_t *cio) { |
||
301 | opj_jp2_box_t box; |
||
302 | |||
303 | box.init_pos = cio_tell(cio); |
||
304 | cio_skip(cio, 4); |
||
305 | cio_write(cio, JP2_COLR, 4); /* COLR */ |
||
306 | |||
307 | cio_write(cio, jp2->meth, 1); /* METH */ |
||
308 | cio_write(cio, jp2->precedence, 1); /* PRECEDENCE */ |
||
309 | cio_write(cio, jp2->approx, 1); /* APPROX */ |
||
310 | |||
311 | if(jp2->meth == 2) |
||
312 | jp2->enumcs = 0; |
||
313 | |||
314 | cio_write(cio, jp2->enumcs, 4); /* EnumCS */ |
||
315 | |||
316 | box.length = cio_tell(cio) - box.init_pos; |
||
317 | cio_seek(cio, box.init_pos); |
||
318 | cio_write(cio, box.length, 4); /* L */ |
||
319 | cio_seek(cio, box.init_pos + box.length); |
||
320 | } |
||
321 | |||
322 | static void jp2_free_pclr(opj_jp2_color_t *color) |
||
323 | { |
||
324 | opj_free(color->jp2_pclr->channel_sign); |
||
325 | opj_free(color->jp2_pclr->channel_size); |
||
326 | opj_free(color->jp2_pclr->entries); |
||
327 | |||
328 | if(color->jp2_pclr->cmap) opj_free(color->jp2_pclr->cmap); |
||
329 | |||
330 | opj_free(color->jp2_pclr); color->jp2_pclr = NULL; |
||
331 | } |
||
332 | |||
333 | static void free_color_data(opj_jp2_color_t *color) |
||
334 | { |
||
335 | if(color->jp2_pclr) |
||
336 | { |
||
337 | jp2_free_pclr(color); |
||
338 | } |
||
339 | if(color->jp2_cdef) |
||
340 | { |
||
341 | if(color->jp2_cdef->info) opj_free(color->jp2_cdef->info); |
||
342 | opj_free(color->jp2_cdef); |
||
343 | } |
||
344 | if(color->icc_profile_buf) opj_free(color->icc_profile_buf); |
||
345 | } |
||
346 | |||
347 | static void jp2_apply_pclr(opj_jp2_color_t *color, opj_image_t *image, opj_common_ptr cinfo) |
||
348 | { |
||
349 | opj_image_comp_t *old_comps, *new_comps; |
||
350 | unsigned char *channel_size, *channel_sign; |
||
351 | unsigned int *entries; |
||
352 | opj_jp2_cmap_comp_t *cmap; |
||
353 | int *src, *dst; |
||
354 | unsigned int j, max; |
||
355 | unsigned short i, nr_channels, cmp, pcol; |
||
356 | int k, top_k; |
||
357 | |||
358 | channel_size = color->jp2_pclr->channel_size; |
||
359 | channel_sign = color->jp2_pclr->channel_sign; |
||
360 | entries = color->jp2_pclr->entries; |
||
361 | cmap = color->jp2_pclr->cmap; |
||
362 | nr_channels = color->jp2_pclr->nr_channels; |
||
363 | |||
364 | old_comps = image->comps; |
||
365 | new_comps = (opj_image_comp_t*) |
||
366 | opj_malloc(nr_channels * sizeof(opj_image_comp_t)); |
||
367 | |||
368 | for(i = 0; i < nr_channels; ++i) |
||
369 | { |
||
370 | pcol = cmap[i].pcol; cmp = cmap[i].cmp; |
||
371 | |||
372 | if( pcol < nr_channels ) |
||
373 | new_comps[pcol] = old_comps[cmp]; |
||
374 | else |
||
375 | { |
||
376 | opj_event_msg(cinfo, EVT_ERROR, "Error with pcol value %d (max: %d). skipping\n", pcol, nr_channels); |
||
377 | continue; |
||
378 | } |
||
379 | |||
380 | if(cmap[i].mtyp == 0) /* Direct use */ |
||
381 | { |
||
382 | old_comps[cmp].data = NULL; continue; |
||
383 | } |
||
384 | /* Palette mapping: */ |
||
385 | new_comps[pcol].data = (int*) |
||
386 | opj_malloc(old_comps[cmp].w * old_comps[cmp].h * sizeof(int)); |
||
387 | new_comps[pcol].prec = channel_size[i]; |
||
388 | new_comps[pcol].sgnd = channel_sign[i]; |
||
389 | } |
||
390 | top_k = color->jp2_pclr->nr_entries - 1; |
||
391 | |||
392 | for(i = 0; i < nr_channels; ++i) |
||
393 | { |
||
394 | /* Direct use: */ |
||
395 | if(cmap[i].mtyp == 0) continue; |
||
396 | |||
397 | /* Palette mapping: */ |
||
398 | cmp = cmap[i].cmp; pcol = cmap[i].pcol; |
||
399 | src = old_comps[cmp].data; |
||
400 | dst = new_comps[pcol].data; |
||
401 | max = new_comps[pcol].w * new_comps[pcol].h; |
||
402 | |||
403 | for(j = 0; j < max; ++j) |
||
404 | { |
||
405 | /* The index */ |
||
406 | if((k = src[j]) < 0) k = 0; else if(k > top_k) k = top_k; |
||
407 | /* The colour */ |
||
408 | dst[j] = entries[k * nr_channels + pcol]; |
||
409 | } |
||
410 | } |
||
411 | max = image->numcomps; |
||
412 | for(i = 0; i < max; ++i) |
||
413 | { |
||
414 | if(old_comps[i].data) opj_free(old_comps[i].data); |
||
415 | } |
||
416 | opj_free(old_comps); |
||
417 | image->comps = new_comps; |
||
418 | image->numcomps = nr_channels; |
||
419 | |||
420 | jp2_free_pclr(color); |
||
421 | |||
422 | }/* apply_pclr() */ |
||
423 | |||
424 | static opj_bool jp2_read_pclr(opj_jp2_t *jp2, opj_cio_t *cio, |
||
425 | opj_jp2_box_t *box, opj_jp2_color_t *color) |
||
426 | { |
||
427 | opj_jp2_pclr_t *jp2_pclr; |
||
428 | unsigned char *channel_size, *channel_sign; |
||
429 | unsigned int *entries; |
||
430 | unsigned short nr_entries, nr_channels; |
||
431 | unsigned short i, j; |
||
432 | unsigned char uc; |
||
433 | |||
434 | OPJ_ARG_NOT_USED(box); |
||
435 | OPJ_ARG_NOT_USED(jp2); |
||
436 | |||
437 | /* Part 1, I.5.3.4: 'There shall be at most one Palette box inside |
||
438 | * a JP2 Header box' : |
||
439 | */ |
||
440 | if(color->jp2_pclr) return OPJ_FALSE; |
||
441 | |||
442 | nr_entries = (unsigned short)cio_read(cio, 2); /* NE */ |
||
443 | nr_channels = (unsigned short)cio_read(cio, 1);/* NPC */ |
||
444 | |||
445 | entries = (unsigned int*) |
||
446 | opj_malloc(nr_channels * nr_entries * sizeof(unsigned int)); |
||
447 | channel_size = (unsigned char*)opj_malloc(nr_channels); |
||
448 | channel_sign = (unsigned char*)opj_malloc(nr_channels); |
||
449 | |||
450 | jp2_pclr = (opj_jp2_pclr_t*)opj_malloc(sizeof(opj_jp2_pclr_t)); |
||
451 | jp2_pclr->channel_sign = channel_sign; |
||
452 | jp2_pclr->channel_size = channel_size; |
||
453 | jp2_pclr->entries = entries; |
||
454 | jp2_pclr->nr_entries = nr_entries; |
||
455 | jp2_pclr->nr_channels = nr_channels; |
||
456 | jp2_pclr->cmap = NULL; |
||
457 | |||
458 | color->jp2_pclr = jp2_pclr; |
||
459 | |||
460 | for(i = 0; i < nr_channels; ++i) |
||
461 | { |
||
462 | uc = cio_read(cio, 1); /* Bi */ |
||
463 | channel_size[i] = (uc & 0x7f) + 1; |
||
464 | channel_sign[i] = (uc & 0x80)?1:0; |
||
465 | } |
||
466 | |||
467 | for(j = 0; j < nr_entries; ++j) |
||
468 | { |
||
469 | for(i = 0; i < nr_channels; ++i) |
||
470 | { |
||
471 | /* Cji */ |
||
472 | *entries++ = cio_read(cio, channel_size[i]>>3); |
||
473 | } |
||
474 | } |
||
475 | |||
476 | return OPJ_TRUE; |
||
477 | }/* jp2_read_pclr() */ |
||
478 | |||
479 | static opj_bool jp2_read_cmap(opj_jp2_t *jp2, opj_cio_t *cio, |
||
480 | opj_jp2_box_t *box, opj_jp2_color_t *color) |
||
481 | { |
||
482 | opj_jp2_cmap_comp_t *cmap; |
||
483 | unsigned short i, nr_channels; |
||
484 | |||
485 | OPJ_ARG_NOT_USED(box); |
||
486 | OPJ_ARG_NOT_USED(jp2); |
||
487 | |||
488 | /* Need nr_channels: */ |
||
489 | if(color->jp2_pclr == NULL) return OPJ_FALSE; |
||
490 | |||
491 | /* Part 1, I.5.3.5: 'There shall be at most one Component Mapping box |
||
492 | * inside a JP2 Header box' : |
||
493 | */ |
||
494 | if(color->jp2_pclr->cmap) return OPJ_FALSE; |
||
495 | |||
496 | nr_channels = color->jp2_pclr->nr_channels; |
||
497 | cmap = (opj_jp2_cmap_comp_t*) |
||
498 | opj_malloc(nr_channels * sizeof(opj_jp2_cmap_comp_t)); |
||
499 | |||
500 | for(i = 0; i < nr_channels; ++i) |
||
501 | { |
||
502 | cmap[i].cmp = (unsigned short)cio_read(cio, 2); |
||
503 | cmap[i].mtyp = cio_read(cio, 1); |
||
504 | cmap[i].pcol = cio_read(cio, 1); |
||
505 | |||
506 | } |
||
507 | color->jp2_pclr->cmap = cmap; |
||
508 | |||
509 | return OPJ_TRUE; |
||
510 | }/* jp2_read_cmap() */ |
||
511 | |||
512 | static void jp2_apply_cdef(opj_image_t *image, opj_jp2_color_t *color) |
||
513 | { |
||
514 | opj_jp2_cdef_info_t *info; |
||
515 | int color_space; |
||
516 | unsigned short i, n, cn, typ, asoc, acn; |
||
517 | |||
518 | color_space = image->color_space; |
||
519 | info = color->jp2_cdef->info; |
||
520 | n = color->jp2_cdef->n; |
||
521 | |||
522 | for(i = 0; i < n; ++i) |
||
523 | { |
||
524 | /* WATCH: acn = asoc - 1 ! */ |
||
525 | if((asoc = info[i].asoc) == 0) continue; |
||
526 | |||
527 | cn = info[i].cn; typ = info[i].typ; acn = asoc - 1; |
||
528 | |||
529 | if(cn != acn) |
||
530 | { |
||
531 | opj_image_comp_t saved; |
||
532 | |||
533 | memcpy(&saved, &image->comps[cn], sizeof(opj_image_comp_t)); |
||
534 | memcpy(&image->comps[cn], &image->comps[acn], sizeof(opj_image_comp_t)); |
||
535 | memcpy(&image->comps[acn], &saved, sizeof(opj_image_comp_t)); |
||
536 | |||
537 | info[i].asoc = cn + 1; |
||
538 | info[acn].asoc = info[acn].cn + 1; |
||
539 | } |
||
540 | } |
||
541 | if(color->jp2_cdef->info) opj_free(color->jp2_cdef->info); |
||
542 | |||
543 | opj_free(color->jp2_cdef); color->jp2_cdef = NULL; |
||
544 | |||
545 | }/* jp2_apply_cdef() */ |
||
546 | |||
547 | static opj_bool jp2_read_cdef(opj_jp2_t *jp2, opj_cio_t *cio, |
||
548 | opj_jp2_box_t *box, opj_jp2_color_t *color) |
||
549 | { |
||
550 | opj_jp2_cdef_info_t *info; |
||
551 | unsigned short i, n; |
||
552 | |||
553 | OPJ_ARG_NOT_USED(box); |
||
554 | OPJ_ARG_NOT_USED(jp2); |
||
555 | |||
556 | /* Part 1, I.5.3.6: 'The shall be at most one Channel Definition box |
||
557 | * inside a JP2 Header box.' |
||
558 | */ |
||
559 | if(color->jp2_cdef) return OPJ_FALSE; |
||
560 | |||
561 | if((n = (unsigned short)cio_read(cio, 2)) == 0) return OPJ_FALSE; /* szukw000: FIXME */ |
||
562 | |||
563 | info = (opj_jp2_cdef_info_t*) |
||
564 | opj_malloc(n * sizeof(opj_jp2_cdef_info_t)); |
||
565 | |||
566 | color->jp2_cdef = (opj_jp2_cdef_t*)opj_malloc(sizeof(opj_jp2_cdef_t)); |
||
567 | color->jp2_cdef->info = info; |
||
568 | color->jp2_cdef->n = n; |
||
569 | |||
570 | for(i = 0; i < n; ++i) |
||
571 | { |
||
572 | info[i].cn = (unsigned short)cio_read(cio, 2); |
||
573 | info[i].typ = (unsigned short)cio_read(cio, 2); |
||
574 | info[i].asoc = (unsigned short)cio_read(cio, 2); |
||
575 | |||
576 | } |
||
577 | return OPJ_TRUE; |
||
578 | }/* jp2_read_cdef() */ |
||
579 | |||
580 | static opj_bool jp2_read_colr(opj_jp2_t *jp2, opj_cio_t *cio, |
||
581 | opj_jp2_box_t *box, opj_jp2_color_t *color) |
||
582 | { |
||
583 | int skip_len; |
||
584 | opj_common_ptr cinfo; |
||
585 | |||
586 | /* Part 1, I.5.3.3 : 'A conforming JP2 reader shall ignore all Colour |
||
587 | * Specification boxes after the first.' |
||
588 | */ |
||
589 | if(color->jp2_has_colr) return OPJ_FALSE; |
||
590 | |||
591 | cinfo = jp2->cinfo; |
||
592 | |||
593 | jp2->meth = cio_read(cio, 1); /* METH */ |
||
594 | jp2->precedence = cio_read(cio, 1); /* PRECEDENCE */ |
||
595 | jp2->approx = cio_read(cio, 1); /* APPROX */ |
||
596 | |||
597 | if (jp2->meth == 1) |
||
598 | { |
||
599 | jp2->enumcs = cio_read(cio, 4); /* EnumCS */ |
||
600 | } |
||
601 | else |
||
602 | if (jp2->meth == 2) |
||
603 | { |
||
604 | /* skip PROFILE */ |
||
605 | skip_len = box->init_pos + box->length - cio_tell(cio); |
||
606 | if (skip_len < 0) |
||
607 | { |
||
608 | opj_event_msg(cinfo, EVT_ERROR, "Error with COLR box size\n"); |
||
609 | return OPJ_FALSE; |
||
610 | } |
||
611 | if(skip_len > 0) |
||
612 | { |
||
613 | unsigned char *start; |
||
614 | |||
615 | start = cio_getbp(cio); |
||
616 | color->icc_profile_buf = (unsigned char*)opj_malloc(skip_len); |
||
617 | color->icc_profile_len = skip_len; |
||
618 | |||
619 | cio_skip(cio, box->init_pos + box->length - cio_tell(cio)); |
||
620 | |||
621 | memcpy(color->icc_profile_buf, start, skip_len); |
||
622 | } |
||
623 | } |
||
624 | |||
625 | if (cio_tell(cio) - box->init_pos != box->length) |
||
626 | { |
||
627 | opj_event_msg(cinfo, EVT_ERROR, "Error with COLR Box\n"); |
||
628 | return OPJ_FALSE; |
||
629 | } |
||
630 | color->jp2_has_colr = 1; |
||
631 | |||
632 | return OPJ_TRUE; |
||
633 | }/* jp2_read_colr() */ |
||
634 | |||
635 | opj_bool jp2_read_jp2h(opj_jp2_t *jp2, opj_cio_t *cio, opj_jp2_color_t *color) |
||
636 | { |
||
637 | opj_jp2_box_t box; |
||
638 | int jp2h_end; |
||
639 | |||
640 | opj_common_ptr cinfo = jp2->cinfo; |
||
641 | |||
642 | jp2_read_boxhdr(cinfo, cio, &box); |
||
643 | do |
||
644 | { |
||
645 | if (JP2_JP2H != box.type) |
||
646 | { |
||
647 | if (box.type == JP2_JP2C) |
||
648 | { |
||
649 | opj_event_msg(cinfo, EVT_ERROR, "Expected JP2H Marker\n"); |
||
650 | return OPJ_FALSE; |
||
651 | } |
||
652 | cio_skip(cio, box.length - 8); |
||
653 | |||
654 | if(cio->bp >= cio->end) return OPJ_FALSE; |
||
655 | |||
656 | jp2_read_boxhdr(cinfo, cio, &box); |
||
657 | } |
||
658 | } while(JP2_JP2H != box.type); |
||
659 | |||
660 | if (!jp2_read_ihdr(jp2, cio)) |
||
661 | return OPJ_FALSE; |
||
662 | jp2h_end = box.init_pos + box.length; |
||
663 | |||
664 | if (jp2->bpc == 255) |
||
665 | { |
||
666 | if (!jp2_read_bpcc(jp2, cio)) |
||
667 | return OPJ_FALSE; |
||
668 | } |
||
669 | jp2_read_boxhdr(cinfo, cio, &box); |
||
670 | |||
671 | while(cio_tell(cio) < jp2h_end) |
||
672 | { |
||
673 | if(box.type == JP2_COLR) |
||
674 | { |
||
675 | if( !jp2_read_colr(jp2, cio, &box, color)) |
||
676 | { |
||
677 | cio_seek(cio, box.init_pos + 8); |
||
678 | cio_skip(cio, box.length - 8); |
||
679 | } |
||
680 | jp2_read_boxhdr(cinfo, cio, &box); |
||
681 | continue; |
||
682 | } |
||
683 | if(box.type == JP2_CDEF && !jp2->ignore_pclr_cmap_cdef) |
||
684 | { |
||
685 | if( !jp2_read_cdef(jp2, cio, &box, color)) |
||
686 | { |
||
687 | cio_seek(cio, box.init_pos + 8); |
||
688 | cio_skip(cio, box.length - 8); |
||
689 | } |
||
690 | jp2_read_boxhdr(cinfo, cio, &box); |
||
691 | continue; |
||
692 | } |
||
693 | if(box.type == JP2_PCLR && !jp2->ignore_pclr_cmap_cdef) |
||
694 | { |
||
695 | if( !jp2_read_pclr(jp2, cio, &box, color)) |
||
696 | { |
||
697 | cio_seek(cio, box.init_pos + 8); |
||
698 | cio_skip(cio, box.length - 8); |
||
699 | } |
||
700 | jp2_read_boxhdr(cinfo, cio, &box); |
||
701 | continue; |
||
702 | } |
||
703 | if(box.type == JP2_CMAP && !jp2->ignore_pclr_cmap_cdef) |
||
704 | { |
||
705 | if( !jp2_read_cmap(jp2, cio, &box, color)) |
||
706 | { |
||
707 | cio_seek(cio, box.init_pos + 8); |
||
708 | cio_skip(cio, box.length - 8); |
||
709 | } |
||
710 | jp2_read_boxhdr(cinfo, cio, &box); |
||
711 | continue; |
||
712 | } |
||
713 | cio_seek(cio, box.init_pos + 8); |
||
714 | cio_skip(cio, box.length - 8); |
||
715 | jp2_read_boxhdr(cinfo, cio, &box); |
||
716 | |||
717 | }/* while(cio_tell(cio) < box_end) */ |
||
718 | |||
719 | cio_seek(cio, jp2h_end); |
||
720 | |||
721 | /* Part 1, I.5.3.3 : 'must contain at least one' */ |
||
722 | return (color->jp2_has_colr == 1); |
||
723 | |||
724 | }/* jp2_read_jp2h() */ |
||
725 | |||
726 | opj_image_t* opj_jp2_decode(opj_jp2_t *jp2, opj_cio_t *cio, |
||
727 | opj_codestream_info_t *cstr_info) |
||
728 | { |
||
729 | opj_common_ptr cinfo; |
||
730 | opj_image_t *image = NULL; |
||
731 | opj_jp2_color_t color; |
||
732 | |||
733 | if(!jp2 || !cio) |
||
734 | { |
||
735 | return NULL; |
||
736 | } |
||
737 | memset(&color, 0, sizeof(opj_jp2_color_t)); |
||
738 | cinfo = jp2->cinfo; |
||
739 | |||
740 | /* JP2 decoding */ |
||
741 | if(!jp2_read_struct(jp2, cio, &color)) |
||
742 | { |
||
743 | free_color_data(&color); |
||
744 | opj_event_msg(cinfo, EVT_ERROR, "Failed to decode jp2 structure\n"); |
||
745 | return NULL; |
||
746 | } |
||
747 | |||
748 | /* J2K decoding */ |
||
749 | image = j2k_decode(jp2->j2k, cio, cstr_info); |
||
750 | |||
751 | if(!image) |
||
752 | { |
||
753 | free_color_data(&color); |
||
754 | opj_event_msg(cinfo, EVT_ERROR, "Failed to decode J2K image\n"); |
||
755 | return NULL; |
||
756 | } |
||
757 | |||
758 | if (!jp2->ignore_pclr_cmap_cdef){ |
||
759 | |||
760 | /* Set Image Color Space */ |
||
761 | if (jp2->enumcs == 16) |
||
762 | image->color_space = CLRSPC_SRGB; |
||
763 | else if (jp2->enumcs == 17) |
||
764 | image->color_space = CLRSPC_GRAY; |
||
765 | else if (jp2->enumcs == 18) |
||
766 | image->color_space = CLRSPC_SYCC; |
||
767 | else |
||
768 | image->color_space = CLRSPC_UNKNOWN; |
||
769 | |||
770 | if(color.jp2_cdef) |
||
771 | { |
||
772 | jp2_apply_cdef(image, &color); |
||
773 | } |
||
774 | if(color.jp2_pclr) |
||
775 | { |
||
776 | /* Part 1, I.5.3.4: Either both or none : */ |
||
777 | if( !color.jp2_pclr->cmap) |
||
778 | jp2_free_pclr(&color); |
||
779 | else |
||
780 | jp2_apply_pclr(&color, image, cinfo); |
||
781 | } |
||
782 | if(color.icc_profile_buf) |
||
783 | { |
||
784 | image->icc_profile_buf = color.icc_profile_buf; |
||
785 | color.icc_profile_buf = NULL; |
||
786 | image->icc_profile_len = color.icc_profile_len; |
||
787 | } |
||
788 | } |
||
789 | |||
790 | return image; |
||
791 | |||
792 | }/* opj_jp2_decode() */ |
||
793 | |||
794 | |||
795 | void jp2_write_jp2h(opj_jp2_t *jp2, opj_cio_t *cio) { |
||
796 | opj_jp2_box_t box; |
||
797 | |||
798 | box.init_pos = cio_tell(cio); |
||
799 | cio_skip(cio, 4); |
||
800 | cio_write(cio, JP2_JP2H, 4); /* JP2H */ |
||
801 | |||
802 | jp2_write_ihdr(jp2, cio); |
||
803 | |||
804 | if (jp2->bpc == 255) { |
||
805 | jp2_write_bpcc(jp2, cio); |
||
806 | } |
||
807 | jp2_write_colr(jp2, cio); |
||
808 | |||
809 | box.length = cio_tell(cio) - box.init_pos; |
||
810 | cio_seek(cio, box.init_pos); |
||
811 | cio_write(cio, box.length, 4); /* L */ |
||
812 | cio_seek(cio, box.init_pos + box.length); |
||
813 | } |
||
814 | |||
815 | static void jp2_write_ftyp(opj_jp2_t *jp2, opj_cio_t *cio) { |
||
816 | unsigned int i; |
||
817 | opj_jp2_box_t box; |
||
818 | |||
819 | box.init_pos = cio_tell(cio); |
||
820 | cio_skip(cio, 4); |
||
821 | cio_write(cio, JP2_FTYP, 4); /* FTYP */ |
||
822 | |||
823 | cio_write(cio, jp2->brand, 4); /* BR */ |
||
824 | cio_write(cio, jp2->minversion, 4); /* MinV */ |
||
825 | |||
826 | for (i = 0; i < jp2->numcl; i++) { |
||
827 | cio_write(cio, jp2->cl[i], 4); /* CL */ |
||
828 | } |
||
829 | |||
830 | box.length = cio_tell(cio) - box.init_pos; |
||
831 | cio_seek(cio, box.init_pos); |
||
832 | cio_write(cio, box.length, 4); /* L */ |
||
833 | cio_seek(cio, box.init_pos + box.length); |
||
834 | } |
||
835 | |||
836 | static opj_bool jp2_read_ftyp(opj_jp2_t *jp2, opj_cio_t *cio) { |
||
837 | int i; |
||
838 | opj_jp2_box_t box; |
||
839 | |||
840 | opj_common_ptr cinfo = jp2->cinfo; |
||
841 | |||
842 | jp2_read_boxhdr(cinfo, cio, &box); |
||
843 | |||
844 | if (JP2_FTYP != box.type) { |
||
845 | opj_event_msg(cinfo, EVT_ERROR, "Expected FTYP Marker\n"); |
||
846 | return OPJ_FALSE; |
||
847 | } |
||
848 | |||
849 | jp2->brand = cio_read(cio, 4); /* BR */ |
||
850 | jp2->minversion = cio_read(cio, 4); /* MinV */ |
||
851 | jp2->numcl = (box.length - 16) / 4; |
||
852 | jp2->cl = (unsigned int *) opj_malloc(jp2->numcl * sizeof(unsigned int)); |
||
853 | |||
854 | for (i = 0; i < (int)jp2->numcl; i++) { |
||
855 | jp2->cl[i] = cio_read(cio, 4); /* CLi */ |
||
856 | } |
||
857 | |||
858 | if (cio_tell(cio) - box.init_pos != box.length) { |
||
859 | opj_event_msg(cinfo, EVT_ERROR, "Error with FTYP Box\n"); |
||
860 | return OPJ_FALSE; |
||
861 | } |
||
862 | |||
863 | return OPJ_TRUE; |
||
864 | } |
||
865 | |||
866 | static int jp2_write_jp2c(opj_jp2_t *jp2, opj_cio_t *cio, opj_image_t *image, opj_codestream_info_t *cstr_info) { |
||
867 | unsigned int j2k_codestream_offset, j2k_codestream_length; |
||
868 | opj_jp2_box_t box; |
||
869 | |||
870 | opj_j2k_t *j2k = jp2->j2k; |
||
871 | |||
872 | box.init_pos = cio_tell(cio); |
||
873 | cio_skip(cio, 4); |
||
874 | cio_write(cio, JP2_JP2C, 4); /* JP2C */ |
||
875 | |||
876 | /* J2K encoding */ |
||
877 | j2k_codestream_offset = cio_tell(cio); |
||
878 | if(!j2k_encode(j2k, cio, image, cstr_info)) { |
||
879 | opj_event_msg(j2k->cinfo, EVT_ERROR, "Failed to encode image\n"); |
||
880 | return 0; |
||
881 | } |
||
882 | j2k_codestream_length = cio_tell(cio) - j2k_codestream_offset; |
||
883 | |||
884 | jp2->j2k_codestream_offset = j2k_codestream_offset; |
||
885 | jp2->j2k_codestream_length = j2k_codestream_length; |
||
886 | |||
887 | box.length = 8 + jp2->j2k_codestream_length; |
||
888 | cio_seek(cio, box.init_pos); |
||
889 | cio_write(cio, box.length, 4); /* L */ |
||
890 | cio_seek(cio, box.init_pos + box.length); |
||
891 | |||
892 | return box.length; |
||
893 | } |
||
894 | |||
895 | static opj_bool jp2_read_jp2c(opj_jp2_t *jp2, opj_cio_t *cio, unsigned int *j2k_codestream_length, unsigned int *j2k_codestream_offset) { |
||
896 | opj_jp2_box_t box; |
||
897 | |||
898 | opj_common_ptr cinfo = jp2->cinfo; |
||
899 | |||
900 | jp2_read_boxhdr(cinfo, cio, &box); |
||
901 | do { |
||
902 | if(JP2_JP2C != box.type) { |
||
903 | cio_skip(cio, box.length - 8); |
||
904 | jp2_read_boxhdr(cinfo, cio, &box); |
||
905 | } |
||
906 | } while(JP2_JP2C != box.type); |
||
907 | |||
908 | *j2k_codestream_offset = cio_tell(cio); |
||
909 | *j2k_codestream_length = box.length - 8; |
||
910 | |||
911 | return OPJ_TRUE; |
||
912 | } |
||
913 | |||
914 | static void jp2_write_jp(opj_cio_t *cio) { |
||
915 | opj_jp2_box_t box; |
||
916 | |||
917 | box.init_pos = cio_tell(cio); |
||
918 | cio_skip(cio, 4); |
||
919 | cio_write(cio, JP2_JP, 4); /* JP2 signature */ |
||
920 | cio_write(cio, 0x0d0a870a, 4); |
||
921 | |||
922 | box.length = cio_tell(cio) - box.init_pos; |
||
923 | cio_seek(cio, box.init_pos); |
||
924 | cio_write(cio, box.length, 4); /* L */ |
||
925 | cio_seek(cio, box.init_pos + box.length); |
||
926 | } |
||
927 | |||
928 | static opj_bool jp2_read_jp(opj_jp2_t *jp2, opj_cio_t *cio) { |
||
929 | opj_jp2_box_t box; |
||
930 | |||
931 | opj_common_ptr cinfo = jp2->cinfo; |
||
932 | |||
933 | jp2_read_boxhdr(cinfo, cio, &box); |
||
934 | if (JP2_JP != box.type) { |
||
935 | opj_event_msg(cinfo, EVT_ERROR, "Expected JP Marker\n"); |
||
936 | return OPJ_FALSE; |
||
937 | } |
||
938 | if (0x0d0a870a != cio_read(cio, 4)) { |
||
939 | opj_event_msg(cinfo, EVT_ERROR, "Error with JP Marker\n"); |
||
940 | return OPJ_FALSE; |
||
941 | } |
||
942 | if (cio_tell(cio) - box.init_pos != box.length) { |
||
943 | opj_event_msg(cinfo, EVT_ERROR, "Error with JP Box size\n"); |
||
944 | return OPJ_FALSE; |
||
945 | } |
||
946 | |||
947 | return OPJ_TRUE; |
||
948 | } |
||
949 | |||
950 | |||
951 | static opj_bool jp2_read_struct(opj_jp2_t *jp2, opj_cio_t *cio, |
||
952 | opj_jp2_color_t *color) { |
||
953 | if (!jp2_read_jp(jp2, cio)) |
||
954 | return OPJ_FALSE; |
||
955 | if (!jp2_read_ftyp(jp2, cio)) |
||
956 | return OPJ_FALSE; |
||
957 | if (!jp2_read_jp2h(jp2, cio, color)) |
||
958 | return OPJ_FALSE; |
||
959 | if (!jp2_read_jp2c(jp2, cio, &jp2->j2k_codestream_length, &jp2->j2k_codestream_offset)) |
||
960 | return OPJ_FALSE; |
||
961 | |||
962 | return OPJ_TRUE; |
||
963 | } |
||
964 | |||
965 | |||
966 | static int write_fidx( int offset_jp2c, int length_jp2c, int offset_idx, int length_idx, opj_cio_t *cio) |
||
967 | { |
||
968 | int len, lenp; |
||
969 | |||
970 | lenp = cio_tell( cio); |
||
971 | cio_skip( cio, 4); /* L [at the end] */ |
||
972 | cio_write( cio, JPIP_FIDX, 4); /* IPTR */ |
||
973 | |||
974 | write_prxy( offset_jp2c, length_jp2c, offset_idx, length_idx, cio); |
||
975 | |||
976 | len = cio_tell( cio)-lenp; |
||
977 | cio_seek( cio, lenp); |
||
978 | cio_write( cio, len, 4); /* L */ |
||
979 | cio_seek( cio, lenp+len); |
||
980 | |||
981 | return len; |
||
982 | } |
||
983 | |||
984 | static void write_prxy( int offset_jp2c, int length_jp2c, int offset_idx, int length_idx, opj_cio_t *cio) |
||
985 | { |
||
986 | int len, lenp; |
||
987 | |||
988 | lenp = cio_tell( cio); |
||
989 | cio_skip( cio, 4); /* L [at the end] */ |
||
990 | cio_write( cio, JPIP_PRXY, 4); /* IPTR */ |
||
991 | |||
992 | cio_write( cio, offset_jp2c, 8); /* OOFF */ |
||
993 | cio_write( cio, length_jp2c, 4); /* OBH part 1 */ |
||
994 | cio_write( cio, JP2_JP2C, 4); /* OBH part 2 */ |
||
995 | |||
996 | cio_write( cio, 1,1); /* NI */ |
||
997 | |||
998 | cio_write( cio, offset_idx, 8); /* IOFF */ |
||
999 | cio_write( cio, length_idx, 4); /* IBH part 1 */ |
||
1000 | cio_write( cio, JPIP_CIDX, 4); /* IBH part 2 */ |
||
1001 | |||
1002 | len = cio_tell( cio)-lenp; |
||
1003 | cio_seek( cio, lenp); |
||
1004 | cio_write( cio, len, 4); /* L */ |
||
1005 | cio_seek( cio, lenp+len); |
||
1006 | } |
||
1007 | |||
1008 | static void write_iptr( int offset, int length, opj_cio_t *cio) |
||
1009 | { |
||
1010 | int len, lenp; |
||
1011 | |||
1012 | lenp = cio_tell( cio); |
||
1013 | cio_skip( cio, 4); /* L [at the end] */ |
||
1014 | cio_write( cio, JPIP_IPTR, 4); /* IPTR */ |
||
1015 | |||
1016 | cio_write( cio, offset, 8); |
||
1017 | cio_write( cio, length, 8); |
||
1018 | |||
1019 | len = cio_tell( cio)-lenp; |
||
1020 | cio_seek( cio, lenp); |
||
1021 | cio_write( cio, len, 4); /* L */ |
||
1022 | cio_seek( cio, lenp+len); |
||
1023 | } |
||
1024 | |||
1025 | |||
1026 | /* ----------------------------------------------------------------------- */ |
||
1027 | /* JP2 decoder interface */ |
||
1028 | /* ----------------------------------------------------------------------- */ |
||
1029 | |||
1030 | opj_jp2_t* jp2_create_decompress(opj_common_ptr cinfo) { |
||
1031 | opj_jp2_t *jp2 = (opj_jp2_t*) opj_calloc(1, sizeof(opj_jp2_t)); |
||
1032 | if(jp2) { |
||
1033 | jp2->cinfo = cinfo; |
||
1034 | /* create the J2K codec */ |
||
1035 | jp2->j2k = j2k_create_decompress(cinfo); |
||
1036 | if(jp2->j2k == NULL) { |
||
1037 | jp2_destroy_decompress(jp2); |
||
1038 | return NULL; |
||
1039 | } |
||
1040 | } |
||
1041 | return jp2; |
||
1042 | } |
||
1043 | |||
1044 | void jp2_destroy_decompress(opj_jp2_t *jp2) { |
||
1045 | if(jp2) { |
||
1046 | /* destroy the J2K codec */ |
||
1047 | j2k_destroy_decompress(jp2->j2k); |
||
1048 | |||
1049 | if(jp2->comps) { |
||
1050 | opj_free(jp2->comps); |
||
1051 | } |
||
1052 | if(jp2->cl) { |
||
1053 | opj_free(jp2->cl); |
||
1054 | } |
||
1055 | opj_free(jp2); |
||
1056 | } |
||
1057 | } |
||
1058 | |||
1059 | void jp2_setup_decoder(opj_jp2_t *jp2, opj_dparameters_t *parameters) { |
||
1060 | /* setup the J2K codec */ |
||
1061 | j2k_setup_decoder(jp2->j2k, parameters); |
||
1062 | /* further JP2 initializations go here */ |
||
1063 | jp2->ignore_pclr_cmap_cdef = parameters->flags & OPJ_DPARAMETERS_IGNORE_PCLR_CMAP_CDEF_FLAG; |
||
1064 | } |
||
1065 | |||
1066 | /* ----------------------------------------------------------------------- */ |
||
1067 | /* JP2 encoder interface */ |
||
1068 | /* ----------------------------------------------------------------------- */ |
||
1069 | |||
1070 | opj_jp2_t* jp2_create_compress(opj_common_ptr cinfo) { |
||
1071 | opj_jp2_t *jp2 = (opj_jp2_t*)opj_malloc(sizeof(opj_jp2_t)); |
||
1072 | if(jp2) { |
||
1073 | jp2->cinfo = cinfo; |
||
1074 | /* create the J2K codec */ |
||
1075 | jp2->j2k = j2k_create_compress(cinfo); |
||
1076 | if(jp2->j2k == NULL) { |
||
1077 | jp2_destroy_compress(jp2); |
||
1078 | return NULL; |
||
1079 | } |
||
1080 | } |
||
1081 | return jp2; |
||
1082 | } |
||
1083 | |||
1084 | void jp2_destroy_compress(opj_jp2_t *jp2) { |
||
1085 | if(jp2) { |
||
1086 | /* destroy the J2K codec */ |
||
1087 | j2k_destroy_compress(jp2->j2k); |
||
1088 | |||
1089 | if(jp2->comps) { |
||
1090 | opj_free(jp2->comps); |
||
1091 | } |
||
1092 | if(jp2->cl) { |
||
1093 | opj_free(jp2->cl); |
||
1094 | } |
||
1095 | opj_free(jp2); |
||
1096 | } |
||
1097 | } |
||
1098 | |||
1099 | void jp2_setup_encoder(opj_jp2_t *jp2, opj_cparameters_t *parameters, opj_image_t *image) { |
||
1100 | int i; |
||
1101 | int depth_0, sign; |
||
1102 | |||
1103 | if(!jp2 || !parameters || !image) |
||
1104 | return; |
||
1105 | |||
1106 | /* setup the J2K codec */ |
||
1107 | /* ------------------- */ |
||
1108 | |||
1109 | /* Check if number of components respects standard */ |
||
1110 | if (image->numcomps < 1 || image->numcomps > 16384) { |
||
1111 | opj_event_msg(jp2->cinfo, EVT_ERROR, "Invalid number of components specified while setting up JP2 encoder\n"); |
||
1112 | return; |
||
1113 | } |
||
1114 | |||
1115 | j2k_setup_encoder(jp2->j2k, parameters, image); |
||
1116 | |||
1117 | /* setup the JP2 codec */ |
||
1118 | /* ------------------- */ |
||
1119 | |||
1120 | /* Profile box */ |
||
1121 | |||
1122 | jp2->brand = JP2_JP2; /* BR */ |
||
1123 | jp2->minversion = 0; /* MinV */ |
||
1124 | jp2->numcl = 1; |
||
1125 | jp2->cl = (unsigned int*) opj_malloc(jp2->numcl * sizeof(unsigned int)); |
||
1126 | jp2->cl[0] = JP2_JP2; /* CL0 : JP2 */ |
||
1127 | |||
1128 | /* Image Header box */ |
||
1129 | |||
1130 | jp2->numcomps = image->numcomps; /* NC */ |
||
1131 | jp2->comps = (opj_jp2_comps_t*) opj_malloc(jp2->numcomps * sizeof(opj_jp2_comps_t)); |
||
1132 | jp2->h = image->y1 - image->y0; /* HEIGHT */ |
||
1133 | jp2->w = image->x1 - image->x0; /* WIDTH */ |
||
1134 | /* BPC */ |
||
1135 | depth_0 = image->comps[0].prec - 1; |
||
1136 | sign = image->comps[0].sgnd; |
||
1137 | jp2->bpc = depth_0 + (sign << 7); |
||
1138 | for (i = 1; i < image->numcomps; i++) { |
||
1139 | int depth = image->comps[i].prec - 1; |
||
1140 | sign = image->comps[i].sgnd; |
||
1141 | if (depth_0 != depth) |
||
1142 | jp2->bpc = 255; |
||
1143 | } |
||
1144 | jp2->C = 7; /* C : Always 7 */ |
||
1145 | jp2->UnkC = 0; /* UnkC, colorspace specified in colr box */ |
||
1146 | jp2->IPR = 0; /* IPR, no intellectual property */ |
||
1147 | |||
1148 | /* BitsPerComponent box */ |
||
1149 | |||
1150 | for (i = 0; i < image->numcomps; i++) { |
||
1151 | jp2->comps[i].bpcc = image->comps[i].prec - 1 + (image->comps[i].sgnd << 7); |
||
1152 | } |
||
1153 | jp2->meth = 1; |
||
1154 | if (image->color_space == 1) |
||
1155 | jp2->enumcs = 16; /* sRGB as defined by IEC 61966-2.1 */ |
||
1156 | else if (image->color_space == 2) |
||
1157 | jp2->enumcs = 17; /* greyscale */ |
||
1158 | else if (image->color_space == 3) |
||
1159 | jp2->enumcs = 18; /* YUV */ |
||
1160 | jp2->precedence = 0; /* PRECEDENCE */ |
||
1161 | jp2->approx = 0; /* APPROX */ |
||
1162 | |||
1163 | jp2->jpip_on = parameters->jpip_on; |
||
1164 | } |
||
1165 | |||
1166 | opj_bool opj_jp2_encode(opj_jp2_t *jp2, opj_cio_t *cio, opj_image_t *image, opj_codestream_info_t *cstr_info) { |
||
1167 | |||
1168 | int pos_iptr, pos_cidx, pos_jp2c, len_jp2c, len_cidx, end_pos, pos_fidx, len_fidx; |
||
1169 | pos_jp2c = pos_iptr = -1; /* remove a warning */ |
||
1170 | |||
1171 | /* JP2 encoding */ |
||
1172 | |||
1173 | /* JPEG 2000 Signature box */ |
||
1174 | jp2_write_jp(cio); |
||
1175 | /* File Type box */ |
||
1176 | jp2_write_ftyp(jp2, cio); |
||
1177 | /* JP2 Header box */ |
||
1178 | jp2_write_jp2h(jp2, cio); |
||
1179 | |||
1180 | if( jp2->jpip_on){ |
||
1181 | pos_iptr = cio_tell( cio); |
||
1182 | cio_skip( cio, 24); /* IPTR further ! */ |
||
1183 | |||
1184 | pos_jp2c = cio_tell( cio); |
||
1185 | } |
||
1186 | |||
1187 | /* J2K encoding */ |
||
1188 | if(!(len_jp2c = jp2_write_jp2c( jp2, cio, image, cstr_info))){ |
||
1189 | opj_event_msg(jp2->cinfo, EVT_ERROR, "Failed to encode image\n"); |
||
1190 | return OPJ_FALSE; |
||
1191 | } |
||
1192 | |||
1193 | if( jp2->jpip_on){ |
||
1194 | pos_cidx = cio_tell( cio); |
||
1195 | |||
1196 | len_cidx = write_cidx( pos_jp2c+8, cio, image, *cstr_info, len_jp2c-8); |
||
1197 | |||
1198 | pos_fidx = cio_tell( cio); |
||
1199 | len_fidx = write_fidx( pos_jp2c, len_jp2c, pos_cidx, len_cidx, cio); |
||
1200 | |||
1201 | end_pos = cio_tell( cio); |
||
1202 | |||
1203 | cio_seek( cio, pos_iptr); |
||
1204 | write_iptr( pos_fidx, len_fidx, cio); |
||
1205 | |||
1206 | cio_seek( cio, end_pos); |
||
1207 | } |
||
1208 | |||
1209 | return OPJ_TRUE; |
||
1210 | } |