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