1 /*
2 * Copyright (c) 1999-2000 Image Power, Inc. and the University of
3 * British Columbia.
4 * Copyright (c) 2001-2003 Michael David Adams.
5 * All rights reserved.
6 */
7
8 /*
9 * Modified by Andrey Kiselev <dron@remotesensing.org> to handle UUID
10 * box properly.
11 */
12
13 /* __START_OF_JASPER_LICENSE__
14 *
15 * JasPer License Version 2.0
16 *
17 * Copyright (c) 2001-2006 Michael David Adams
18 * Copyright (c) 1999-2000 Image Power, Inc.
19 * Copyright (c) 1999-2000 The University of British Columbia
20 *
21 * All rights reserved.
22 *
23 * Permission is hereby granted, free of charge, to any person (the
24 * "User") obtaining a copy of this software and associated documentation
25 * files (the "Software"), to deal in the Software without restriction,
26 * including without limitation the rights to use, copy, modify, merge,
27 * publish, distribute, and/or sell copies of the Software, and to permit
28 * persons to whom the Software is furnished to do so, subject to the
29 * following conditions:
30 *
31 * 1. The above copyright notices and this permission notice (which
32 * includes the disclaimer below) shall be included in all copies or
33 * substantial portions of the Software.
34 *
35 * 2. The name of a copyright holder shall not be used to endorse or
36 * promote products derived from the Software without specific prior
37 * written permission.
38 *
39 * THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL PART OF THIS
40 * LICENSE. NO USE OF THE SOFTWARE IS AUTHORIZED HEREUNDER EXCEPT UNDER
41 * THIS DISCLAIMER. THE SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS
42 * "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
43 * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
44 * PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. IN NO
45 * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL
46 * INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING
47 * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
48 * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
49 * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. NO ASSURANCES ARE
50 * PROVIDED BY THE COPYRIGHT HOLDERS THAT THE SOFTWARE DOES NOT INFRINGE
51 * THE PATENT OR OTHER INTELLECTUAL PROPERTY RIGHTS OF ANY OTHER ENTITY.
52 * EACH COPYRIGHT HOLDER DISCLAIMS ANY LIABILITY TO THE USER FOR CLAIMS
53 * BROUGHT BY ANY OTHER ENTITY BASED ON INFRINGEMENT OF INTELLECTUAL
54 * PROPERTY RIGHTS OR OTHERWISE. AS A CONDITION TO EXERCISING THE RIGHTS
55 * GRANTED HEREUNDER, EACH USER HEREBY ASSUMES SOLE RESPONSIBILITY TO SECURE
56 * ANY OTHER INTELLECTUAL PROPERTY RIGHTS NEEDED, IF ANY. THE SOFTWARE
57 * IS NOT FAULT-TOLERANT AND IS NOT INTENDED FOR USE IN MISSION-CRITICAL
58 * SYSTEMS, SUCH AS THOSE USED IN THE OPERATION OF NUCLEAR FACILITIES,
59 * AIRCRAFT NAVIGATION OR COMMUNICATION SYSTEMS, AIR TRAFFIC CONTROL
60 * SYSTEMS, DIRECT LIFE SUPPORT MACHINES, OR WEAPONS SYSTEMS, IN WHICH
61 * THE FAILURE OF THE SOFTWARE OR SYSTEM COULD LEAD DIRECTLY TO DEATH,
62 * PERSONAL INJURY, OR SEVERE PHYSICAL OR ENVIRONMENTAL DAMAGE ("HIGH
63 * RISK ACTIVITIES"). THE COPYRIGHT HOLDERS SPECIFICALLY DISCLAIM ANY
64 * EXPRESS OR IMPLIED WARRANTY OF FITNESS FOR HIGH RISK ACTIVITIES.
65 *
66 * __END_OF_JASPER_LICENSE__
67 */
68
69 /*
70 * JP2 Library
71 *
72 * $Id: jp2_enc.c,v 1.2 2008-05-26 09:40:52 vp153 Exp $
73 */
74
75 /******************************************************************************\
76 * Includes.
77 \******************************************************************************/
78
79 #include <assert.h>
80 #include "jasper/jas_malloc.h"
81 #include "jasper/jas_image.h"
82 #include "jasper/jas_stream.h"
83 #include "jasper/jas_cm.h"
84 #include "jasper/jas_icc.h"
85 #include "jp2_cod.h"
86
87 static uint_fast32_t jp2_gettypeasoc(int colorspace, int ctype);
88 static int clrspctojp2(jas_clrspc_t clrspc);
89
90 /******************************************************************************\
91 * Functions.
92 \******************************************************************************/
93
jp2_write_header(jas_image_t * image,jas_stream_t * out)94 int jp2_write_header(jas_image_t *image, jas_stream_t *out)
95 {
96 jp2_box_t *box;
97 jp2_ftyp_t *ftyp;
98 jp2_ihdr_t *ihdr;
99 jas_stream_t *tmpstream;
100 int allcmptssame;
101 jp2_bpcc_t *bpcc;
102 long len;
103 uint_fast16_t cmptno;
104 jp2_colr_t *colr;
105 jp2_cdefchan_t *cdefchanent;
106 jp2_cdef_t *cdef;
107 int i;
108 uint_fast32_t typeasoc;
109 jas_iccprof_t *iccprof;
110 jas_stream_t *iccstream;
111 int pos;
112 int needcdef;
113 int prec;
114 int sgnd;
115
116 box = 0;
117 tmpstream = 0;
118
119 allcmptssame = 1;
120 sgnd = jas_image_cmptsgnd(image, 0);
121 prec = jas_image_cmptprec(image, 0);
122 for (i = 1; i < jas_image_numcmpts(image); ++i) {
123 if (jas_image_cmptsgnd(image, i) != sgnd ||
124 jas_image_cmptprec(image, i) != prec) {
125 allcmptssame = 0;
126 break;
127 }
128 }
129
130 /* Output the signature box. */
131
132 if (!(box = jp2_box_create(JP2_BOX_JP))) {
133 goto error;
134 }
135 box->data.jp.magic = JP2_JP_MAGIC;
136 if (jp2_box_put(box, out)) {
137 goto error;
138 }
139 jp2_box_destroy(box);
140 box = 0;
141
142 /* Output the file type box. */
143
144 if (!(box = jp2_box_create(JP2_BOX_FTYP))) {
145 goto error;
146 }
147 ftyp = &box->data.ftyp;
148 ftyp->majver = JP2_FTYP_MAJVER;
149 ftyp->minver = JP2_FTYP_MINVER;
150 ftyp->numcompatcodes = 1;
151 ftyp->compatcodes[0] = JP2_FTYP_COMPATCODE;
152 if (jp2_box_put(box, out)) {
153 goto error;
154 }
155 jp2_box_destroy(box);
156 box = 0;
157
158 /*
159 * Generate the data portion of the JP2 header box.
160 * We cannot simply output the header for this box
161 * since we do not yet know the correct value for the length
162 * field.
163 */
164
165 if (!(tmpstream = jas_stream_memopen(0, 0))) {
166 goto error;
167 }
168
169 /* Generate image header box. */
170
171 if (!(box = jp2_box_create(JP2_BOX_IHDR))) {
172 goto error;
173 }
174 ihdr = &box->data.ihdr;
175 ihdr->width = jas_image_width(image);
176 ihdr->height = jas_image_height(image);
177 ihdr->numcmpts = jas_image_numcmpts(image);
178 ihdr->bpc = allcmptssame ? JP2_SPTOBPC(jas_image_cmptsgnd(image, 0),
179 jas_image_cmptprec(image, 0)) : JP2_IHDR_BPCNULL;
180 ihdr->comptype = JP2_IHDR_COMPTYPE;
181 ihdr->csunk = 0;
182 ihdr->ipr = 0;
183 if (jp2_box_put(box, tmpstream)) {
184 goto error;
185 }
186 jp2_box_destroy(box);
187 box = 0;
188
189 /* Generate bits per component box. */
190
191 if (!allcmptssame) {
192 if (!(box = jp2_box_create(JP2_BOX_BPCC))) {
193 goto error;
194 }
195 bpcc = &box->data.bpcc;
196 bpcc->numcmpts = jas_image_numcmpts(image);
197 if (!(bpcc->bpcs = jas_alloc2(bpcc->numcmpts,
198 sizeof(uint_fast8_t)))) {
199 goto error;
200 }
201 for (cmptno = 0; cmptno < bpcc->numcmpts; ++cmptno) {
202 bpcc->bpcs[cmptno] = JP2_SPTOBPC(jas_image_cmptsgnd(image,
203 cmptno), jas_image_cmptprec(image, cmptno));
204 }
205 if (jp2_box_put(box, tmpstream)) {
206 goto error;
207 }
208 jp2_box_destroy(box);
209 box = 0;
210 }
211
212 /* Generate color specification box. */
213
214 if (!(box = jp2_box_create(JP2_BOX_COLR))) {
215 goto error;
216 }
217 colr = &box->data.colr;
218 switch (jas_image_clrspc(image)) {
219 case JAS_CLRSPC_SRGB:
220 case JAS_CLRSPC_SYCBCR:
221 case JAS_CLRSPC_SGRAY:
222 colr->method = JP2_COLR_ENUM;
223 colr->csid = clrspctojp2(jas_image_clrspc(image));
224 colr->pri = JP2_COLR_PRI;
225 colr->approx = 0;
226 break;
227 default:
228 colr->method = JP2_COLR_ICC;
229 colr->pri = JP2_COLR_PRI;
230 colr->approx = 0;
231 iccprof = jas_iccprof_createfromcmprof(jas_image_cmprof(image));
232 assert(iccprof);
233 iccstream = jas_stream_memopen(0, 0);
234 assert(iccstream);
235 if (jas_iccprof_save(iccprof, iccstream))
236 abort();
237 if ((pos = jas_stream_tell(iccstream)) < 0)
238 abort();
239 colr->iccplen = pos;
240 colr->iccp = jas_malloc(pos);
241 assert(colr->iccp);
242 jas_stream_rewind(iccstream);
243 if (jas_stream_read(iccstream, colr->iccp, colr->iccplen) != colr->iccplen)
244 abort();
245 jas_stream_close(iccstream);
246 jas_iccprof_destroy(iccprof);
247 break;
248 }
249 if (jp2_box_put(box, tmpstream)) {
250 goto error;
251 }
252 jp2_box_destroy(box);
253 box = 0;
254
255 needcdef = 1;
256 switch (jas_clrspc_fam(jas_image_clrspc(image))) {
257 case JAS_CLRSPC_FAM_RGB:
258 if (jas_image_cmpttype(image, 0) ==
259 JAS_IMAGE_CT_COLOR(JAS_CLRSPC_CHANIND_RGB_R) &&
260 jas_image_cmpttype(image, 1) ==
261 JAS_IMAGE_CT_COLOR(JAS_CLRSPC_CHANIND_RGB_G) &&
262 jas_image_cmpttype(image, 2) ==
263 JAS_IMAGE_CT_COLOR(JAS_CLRSPC_CHANIND_RGB_B))
264 needcdef = 0;
265 break;
266 case JAS_CLRSPC_FAM_YCBCR:
267 if (jas_image_cmpttype(image, 0) ==
268 JAS_IMAGE_CT_COLOR(JAS_CLRSPC_CHANIND_YCBCR_Y) &&
269 jas_image_cmpttype(image, 1) ==
270 JAS_IMAGE_CT_COLOR(JAS_CLRSPC_CHANIND_YCBCR_CB) &&
271 jas_image_cmpttype(image, 2) ==
272 JAS_IMAGE_CT_COLOR(JAS_CLRSPC_CHANIND_YCBCR_CR))
273 needcdef = 0;
274 break;
275 case JAS_CLRSPC_FAM_GRAY:
276 if (jas_image_cmpttype(image, 0) ==
277 JAS_IMAGE_CT_COLOR(JAS_IMAGE_CT_GRAY_Y))
278 needcdef = 0;
279 break;
280 default:
281 abort();
282 break;
283 }
284
285 if (needcdef) {
286 if (!(box = jp2_box_create(JP2_BOX_CDEF))) {
287 goto error;
288 }
289 cdef = &box->data.cdef;
290 cdef->numchans = jas_image_numcmpts(image);
291 cdef->ents = jas_alloc2(cdef->numchans, sizeof(jp2_cdefchan_t));
292 for (i = 0; i < jas_image_numcmpts(image); ++i) {
293 cdefchanent = &cdef->ents[i];
294 cdefchanent->channo = i;
295 typeasoc = jp2_gettypeasoc(jas_image_clrspc(image), jas_image_cmpttype(image, i));
296 cdefchanent->type = typeasoc >> 16;
297 cdefchanent->assoc = typeasoc & 0x7fff;
298 }
299 if (jp2_box_put(box, tmpstream)) {
300 goto error;
301 }
302 jp2_box_destroy(box);
303 box = 0;
304 }
305
306 /* Determine the total length of the JP2 header box. */
307
308 len = jas_stream_tell(tmpstream);
309 jas_stream_rewind(tmpstream);
310
311 /*
312 * Output the JP2 header box and all of the boxes which it contains.
313 */
314
315 if (!(box = jp2_box_create(JP2_BOX_JP2H))) {
316 goto error;
317 }
318 box->len = len + JP2_BOX_HDRLEN(false);
319 if (jp2_box_put(box, out)) {
320 goto error;
321 }
322 jp2_box_destroy(box);
323 box = 0;
324
325 if (jas_stream_copy(out, tmpstream, len)) {
326 goto error;
327 }
328
329 jas_stream_close(tmpstream);
330 tmpstream = 0;
331
332 return 0;
333 abort();
334
335 error:
336
337 if (box) {
338 jp2_box_destroy(box);
339 }
340 if (tmpstream) {
341 jas_stream_close(tmpstream);
342 }
343 return -1;
344 }
345
jp2_write_codestream(jas_image_t * image,jas_stream_t * out,char * optstr)346 int jp2_write_codestream(jas_image_t *image, jas_stream_t *out, char *optstr)
347 {
348 jp2_box_t *box;
349 char buf[4096];
350 uint_fast32_t overhead;
351
352 /*
353 * Output the contiguous code stream box.
354 */
355
356 if (!(box = jp2_box_create(JP2_BOX_JP2C))) {
357 goto error;
358 }
359 box->len = 0;
360 if (jp2_box_put(box, out)) {
361 goto error;
362 }
363 jp2_box_destroy(box);
364 box = 0;
365
366 /* Output the JPEG-2000 code stream. */
367
368 overhead = jas_stream_getrwcount(out);
369 sprintf(buf, "%s\n_jp2overhead=%lu\n", (optstr ? optstr : ""),
370 (unsigned long) overhead);
371
372 if (jpc_encode(image, out, buf)) {
373 goto error;
374 }
375
376 return 0;
377 abort();
378
379 error:
380
381 if (box) {
382 jp2_box_destroy(box);
383 }
384 return -1;
385 }
386
jp2_encode(jas_image_t * image,jas_stream_t * out,char * optstr)387 int jp2_encode(jas_image_t *image, jas_stream_t *out, char *optstr)
388 {
389 if (jp2_write_header(image, out) < 0)
390 return -1;
391 if (jp2_write_codestream(image, out, optstr) < 0)
392 return -1;
393
394 return 0;
395 }
396
jp2_encode_uuid(jas_image_t * image,jas_stream_t * out,char * optstr,jp2_box_t * uuid)397 int jp2_encode_uuid(jas_image_t *image, jas_stream_t *out,
398 char *optstr, jp2_box_t *uuid)
399 {
400 if (jp2_write_header(image, out) < 0)
401 return -1;
402 if (uuid) {
403 if (jp2_box_put(uuid, out))
404 return -1;
405 }
406 if (jp2_write_codestream(image, out, optstr) < 0)
407 return -1;
408
409 return 0;
410 }
411
jp2_gettypeasoc(int colorspace,int ctype)412 static uint_fast32_t jp2_gettypeasoc(int colorspace, int ctype)
413 {
414 int type;
415 int asoc;
416
417 if (ctype & JAS_IMAGE_CT_OPACITY) {
418 type = JP2_CDEF_TYPE_OPACITY;
419 asoc = JP2_CDEF_ASOC_ALL;
420 goto done;
421 }
422
423 type = JP2_CDEF_TYPE_UNSPEC;
424 asoc = JP2_CDEF_ASOC_NONE;
425 switch (jas_clrspc_fam(colorspace)) {
426 case JAS_CLRSPC_FAM_RGB:
427 switch (JAS_IMAGE_CT_COLOR(ctype)) {
428 case JAS_IMAGE_CT_RGB_R:
429 type = JP2_CDEF_TYPE_COLOR;
430 asoc = JP2_CDEF_RGB_R;
431 break;
432 case JAS_IMAGE_CT_RGB_G:
433 type = JP2_CDEF_TYPE_COLOR;
434 asoc = JP2_CDEF_RGB_G;
435 break;
436 case JAS_IMAGE_CT_RGB_B:
437 type = JP2_CDEF_TYPE_COLOR;
438 asoc = JP2_CDEF_RGB_B;
439 break;
440 }
441 break;
442 case JAS_CLRSPC_FAM_YCBCR:
443 switch (JAS_IMAGE_CT_COLOR(ctype)) {
444 case JAS_IMAGE_CT_YCBCR_Y:
445 type = JP2_CDEF_TYPE_COLOR;
446 asoc = JP2_CDEF_YCBCR_Y;
447 break;
448 case JAS_IMAGE_CT_YCBCR_CB:
449 type = JP2_CDEF_TYPE_COLOR;
450 asoc = JP2_CDEF_YCBCR_CB;
451 break;
452 case JAS_IMAGE_CT_YCBCR_CR:
453 type = JP2_CDEF_TYPE_COLOR;
454 asoc = JP2_CDEF_YCBCR_CR;
455 break;
456 }
457 break;
458 case JAS_CLRSPC_FAM_GRAY:
459 type = JP2_CDEF_TYPE_COLOR;
460 asoc = JP2_CDEF_GRAY_Y;
461 break;
462 }
463
464 done:
465 return (type << 16) | asoc;
466 }
467
clrspctojp2(jas_clrspc_t clrspc)468 static int clrspctojp2(jas_clrspc_t clrspc)
469 {
470 switch (clrspc) {
471 case JAS_CLRSPC_SRGB:
472 return JP2_COLR_SRGB;
473 case JAS_CLRSPC_SYCBCR:
474 return JP2_COLR_SYCC;
475 case JAS_CLRSPC_SGRAY:
476 return JP2_COLR_SGRAY;
477 default:
478 abort();
479 break;
480 }
481 }
482