diff options
| author | scuri <scuri> | 2008-10-17 06:10:15 +0000 | 
|---|---|---|
| committer | scuri <scuri> | 2008-10-17 06:10:15 +0000 | 
| commit | 5a422aba704c375a307a902bafe658342e209906 (patch) | |
| tree | 5005011e086bb863d8fb587ad3319bbec59b2447 /src/libjasper/jp2 | |
First commit - moving from LuaForge to SourceForge
Diffstat (limited to 'src/libjasper/jp2')
| -rw-r--r-- | src/libjasper/jp2/jp2_cod.c | 980 | ||||
| -rw-r--r-- | src/libjasper/jp2/jp2_cod.h | 328 | ||||
| -rw-r--r-- | src/libjasper/jp2/jp2_dec.c | 702 | ||||
| -rw-r--r-- | src/libjasper/jp2/jp2_dec.h | 85 | ||||
| -rw-r--r-- | src/libjasper/jp2/jp2_enc.c | 469 | 
5 files changed, 2564 insertions, 0 deletions
| diff --git a/src/libjasper/jp2/jp2_cod.c b/src/libjasper/jp2/jp2_cod.c new file mode 100644 index 0000000..81b01ce --- /dev/null +++ b/src/libjasper/jp2/jp2_cod.c @@ -0,0 +1,980 @@ +/* + * Copyright (c) 1999-2000 Image Power, Inc. and the University of + *   British Columbia. + * Copyright (c) 2001-2002 Michael David Adams. + * All rights reserved. + + GeoJasper revision: Dima (11/07/2003 17:29 - UUID from j_image_t) + Modifications by Andrey Kiselev <dron@remotesensing.org> to handle UUID box properly. + */ + +/* __START_OF_JASPER_LICENSE__ + *  + * JasPer License Version 2.0 + *  + * Copyright (c) 2001-2006 Michael David Adams + * Copyright (c) 1999-2000 Image Power, Inc. + * Copyright (c) 1999-2000 The University of British Columbia + *  + * All rights reserved. + *  + * Permission is hereby granted, free of charge, to any person (the + * "User") obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without restriction, + * including without limitation the rights to use, copy, modify, merge, + * publish, distribute, and/or sell copies of the Software, and to permit + * persons to whom the Software is furnished to do so, subject to the + * following conditions: + *  + * 1.  The above copyright notices and this permission notice (which + * includes the disclaimer below) shall be included in all copies or + * substantial portions of the Software. + *  + * 2.  The name of a copyright holder shall not be used to endorse or + * promote products derived from the Software without specific prior + * written permission. + *  + * THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL PART OF THIS + * LICENSE.  NO USE OF THE SOFTWARE IS AUTHORIZED HEREUNDER EXCEPT UNDER + * THIS DISCLAIMER.  THE SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS + * "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING + * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.  IN NO + * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL + * INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING + * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, + * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION + * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.  NO ASSURANCES ARE + * PROVIDED BY THE COPYRIGHT HOLDERS THAT THE SOFTWARE DOES NOT INFRINGE + * THE PATENT OR OTHER INTELLECTUAL PROPERTY RIGHTS OF ANY OTHER ENTITY. + * EACH COPYRIGHT HOLDER DISCLAIMS ANY LIABILITY TO THE USER FOR CLAIMS + * BROUGHT BY ANY OTHER ENTITY BASED ON INFRINGEMENT OF INTELLECTUAL + * PROPERTY RIGHTS OR OTHERWISE.  AS A CONDITION TO EXERCISING THE RIGHTS + * GRANTED HEREUNDER, EACH USER HEREBY ASSUMES SOLE RESPONSIBILITY TO SECURE + * ANY OTHER INTELLECTUAL PROPERTY RIGHTS NEEDED, IF ANY.  THE SOFTWARE + * IS NOT FAULT-TOLERANT AND IS NOT INTENDED FOR USE IN MISSION-CRITICAL + * SYSTEMS, SUCH AS THOSE USED IN THE OPERATION OF NUCLEAR FACILITIES, + * AIRCRAFT NAVIGATION OR COMMUNICATION SYSTEMS, AIR TRAFFIC CONTROL + * SYSTEMS, DIRECT LIFE SUPPORT MACHINES, OR WEAPONS SYSTEMS, IN WHICH + * THE FAILURE OF THE SOFTWARE OR SYSTEM COULD LEAD DIRECTLY TO DEATH, + * PERSONAL INJURY, OR SEVERE PHYSICAL OR ENVIRONMENTAL DAMAGE ("HIGH + * RISK ACTIVITIES").  THE COPYRIGHT HOLDERS SPECIFICALLY DISCLAIM ANY + * EXPRESS OR IMPLIED WARRANTY OF FITNESS FOR HIGH RISK ACTIVITIES. + *  + * __END_OF_JASPER_LICENSE__ + */ + +/* + * JP2 Library + * + * $Id: jp2_cod.c,v 1.1 2008/10/17 06:14:59 scuri Exp $ + */ + +/******************************************************************************\ +* Includes. +\******************************************************************************/ + +#include <assert.h> +#include <stdlib.h> + +#include "jasper/jas_stream.h" +#include "jasper/jas_malloc.h" +#include "jasper/jas_debug.h" + +#include "jp2_cod.h" + +/******************************************************************************\ +* Function prototypes. +\******************************************************************************/ + +#define	ONES(n)	((1 << (n)) - 1) + +jp2_boxinfo_t *jp2_boxinfolookup(int type); + +static int jp2_getuint8(jas_stream_t *in, uint_fast8_t *val); +static int jp2_getuint16(jas_stream_t *in, uint_fast16_t *val); +static int jp2_getuint32(jas_stream_t *in, uint_fast32_t *val); +static int jp2_getuint64(jas_stream_t *in, uint_fast64_t *val); +static int jp2_putuint8(jas_stream_t *out, uint_fast8_t val); +static int jp2_putuint16(jas_stream_t *out, uint_fast16_t val); +static int jp2_putuint32(jas_stream_t *out, uint_fast32_t val); +static int jp2_putuint64(jas_stream_t *out, uint_fast64_t val); + +static int jp2_getint(jas_stream_t *in, int s, int n, int_fast32_t *val); + +jp2_box_t *jp2_box_get(jas_stream_t *in); +void jp2_box_dump(jp2_box_t *box, FILE *out); + +static int jp2_jp_getdata(jp2_box_t *box, jas_stream_t *in); +static int jp2_jp_putdata(jp2_box_t *box, jas_stream_t *out); +static int jp2_ftyp_getdata(jp2_box_t *box, jas_stream_t *in); +static int jp2_ftyp_putdata(jp2_box_t *box, jas_stream_t *out); +static int jp2_ihdr_getdata(jp2_box_t *box, jas_stream_t *in); +static int jp2_ihdr_putdata(jp2_box_t *box, jas_stream_t *out); +static void jp2_bpcc_destroy(jp2_box_t *box); +static int jp2_bpcc_getdata(jp2_box_t *box, jas_stream_t *in); +static int jp2_bpcc_putdata(jp2_box_t *box, jas_stream_t *out); +static int jp2_colr_getdata(jp2_box_t *box, jas_stream_t *in); +static int jp2_colr_putdata(jp2_box_t *box, jas_stream_t *out); +static void jp2_colr_dumpdata(jp2_box_t *box, FILE *out); +static void jp2_colr_destroy(jp2_box_t *box); +static void jp2_cdef_destroy(jp2_box_t *box); +static int jp2_cdef_getdata(jp2_box_t *box, jas_stream_t *in); +static int jp2_cdef_putdata(jp2_box_t *box, jas_stream_t *out); +static void jp2_cdef_dumpdata(jp2_box_t *box, FILE *out); +static void jp2_cmap_destroy(jp2_box_t *box); +static int jp2_cmap_getdata(jp2_box_t *box, jas_stream_t *in); +static int jp2_cmap_putdata(jp2_box_t *box, jas_stream_t *out); +static void jp2_cmap_dumpdata(jp2_box_t *box, FILE *out); +static void jp2_pclr_destroy(jp2_box_t *box); +static int jp2_pclr_getdata(jp2_box_t *box, jas_stream_t *in); +static int jp2_pclr_putdata(jp2_box_t *box, jas_stream_t *out); +static void jp2_pclr_dumpdata(jp2_box_t *box, FILE *out); +// GeoJasper: dima - uuid +static void jp2_uuid_destroy(jp2_box_t *box); +static int jp2_uuid_getdata(jp2_box_t *box, jas_stream_t *in); +static int jp2_uuid_putdata(jp2_box_t *box, jas_stream_t *out); + + +/******************************************************************************\ +* Local data. +\******************************************************************************/ + +jp2_boxinfo_t jp2_boxinfos[] = { +	{JP2_BOX_JP, "JP", 0, +	  {0, 0, jp2_jp_getdata, jp2_jp_putdata, 0}}, +	{JP2_BOX_FTYP, "FTYP", 0, +	  {0, 0, jp2_ftyp_getdata, jp2_ftyp_putdata, 0}}, +	{JP2_BOX_JP2H, "JP2H", JP2_BOX_SUPER, +	  {0, 0, 0, 0, 0}}, +	{JP2_BOX_IHDR, "IHDR", 0, +	  {0, 0, jp2_ihdr_getdata, jp2_ihdr_putdata, 0}}, +	{JP2_BOX_BPCC, "BPCC", 0, +	  {0, jp2_bpcc_destroy, jp2_bpcc_getdata, jp2_bpcc_putdata, 0}}, +	{JP2_BOX_COLR, "COLR", 0, +	  {0, jp2_colr_destroy, jp2_colr_getdata, jp2_colr_putdata, jp2_colr_dumpdata}}, +	{JP2_BOX_PCLR, "PCLR", 0, +	  {0, jp2_pclr_destroy, jp2_pclr_getdata, jp2_pclr_putdata, jp2_pclr_dumpdata}}, +	{JP2_BOX_CMAP, "CMAP", 0, +	  {0, jp2_cmap_destroy, jp2_cmap_getdata, jp2_cmap_putdata, jp2_cmap_dumpdata}}, +	{JP2_BOX_CDEF, "CDEF", 0, +	  {0, jp2_cdef_destroy, jp2_cdef_getdata, jp2_cdef_putdata, jp2_cdef_dumpdata}}, +	{JP2_BOX_RES, "RES", JP2_BOX_SUPER, +	  {0, 0, 0, 0, 0}}, +	{JP2_BOX_RESC, "RESC", 0, +	  {0, 0, 0, 0, 0}}, +	{JP2_BOX_RESD, "RESD", 0, +	  {0, 0, 0, 0, 0}}, +	{JP2_BOX_JP2C, "JP2C", JP2_BOX_NODATA, +	  {0, 0, 0, 0, 0}}, +	{JP2_BOX_JP2I, "JP2I", 0, +	  {0, 0, 0, 0, 0}}, +	{JP2_BOX_XML, "XML", 0, +	  {0, 0, 0, 0, 0}}, +	{JP2_BOX_UUID, "UUID", 0, +	  //{0, 0, 0, 0, 0}}, +	  {0, jp2_uuid_destroy, jp2_uuid_getdata, jp2_uuid_putdata, 0}}, // GeoJasper: dima - uuid +	{JP2_BOX_UINF, "UINF", JP2_BOX_SUPER, +	  {0, 0, 0, 0, 0}}, +	{JP2_BOX_ULST, "ULST", 0, +	  {0, 0, 0, 0, 0}}, +	{JP2_BOX_URL, "URL", 0, +	  {0, 0, 0, 0, 0}}, +	{0, 0, 0, {0, 0, 0, 0, 0}}, +}; + +jp2_boxinfo_t jp2_boxinfo_unk = { +	0, "Unknown", 0, {0, 0, 0, 0, 0} +}; + +/******************************************************************************\ +* Box constructor. +\******************************************************************************/ + +jp2_box_t *jp2_box_create(int type) +{ +	jp2_box_t *box; +	jp2_boxinfo_t *boxinfo; + +	if (!(box = jas_malloc(sizeof(jp2_box_t)))) { +		return 0; +	} +	memset(box, 0, sizeof(jp2_box_t)); +	box->type = type; +	box->len = 0; +	if (!(boxinfo = jp2_boxinfolookup(type))) { +		return 0; +	} +	box->info = boxinfo; +	box->ops = &boxinfo->ops; +	return box; +} + +/******************************************************************************\ +* Box destructor. +\******************************************************************************/ + +void jp2_box_destroy(jp2_box_t *box) +{ +	if (box->ops->destroy) { +		(*box->ops->destroy)(box); +	} +	jas_free(box); +} + +static void jp2_bpcc_destroy(jp2_box_t *box) +{ +	jp2_bpcc_t *bpcc = &box->data.bpcc; +	if (bpcc->bpcs) { +		jas_free(bpcc->bpcs); +		bpcc->bpcs = 0; +	} +} + +static void jp2_cdef_destroy(jp2_box_t *box) +{ +	jp2_cdef_t *cdef = &box->data.cdef; +	if (cdef->ents) { +		jas_free(cdef->ents); +		cdef->ents = 0; +	} +} + +/******************************************************************************\ +* Box input. +\******************************************************************************/ + +jp2_box_t *jp2_box_get(jas_stream_t *in) +{ +	jp2_box_t *box; +	jp2_boxinfo_t *boxinfo; +	jas_stream_t *tmpstream; +	uint_fast32_t len; +	uint_fast64_t extlen; +	bool dataflag; + +	box = 0; +	tmpstream = 0; + +	if (!(box = jas_malloc(sizeof(jp2_box_t)))) { +		goto error; +	} +	box->ops = &jp2_boxinfo_unk.ops; +	if (jp2_getuint32(in, &len) || jp2_getuint32(in, &box->type)) { +		goto error; +	} +	boxinfo = jp2_boxinfolookup(box->type); +	box->info = boxinfo; +	box->ops = &boxinfo->ops; +	box->len = len; +	if (box->len == 1) { +		if (jp2_getuint64(in, &extlen)) { +			goto error; +		} +		if (extlen > 0xffffffffUL) { +			jas_eprintf("warning: cannot handle large 64-bit box length\n"); +			extlen = 0xffffffffUL; +		} +		box->len = extlen; +		box->datalen = extlen - JP2_BOX_HDRLEN(true); +	} else { +		box->datalen = box->len - JP2_BOX_HDRLEN(false); +	} +	if (box->len != 0 && box->len < 8) { +		goto error; +	} + +	dataflag = !(box->info->flags & (JP2_BOX_SUPER | JP2_BOX_NODATA)); + +	if (dataflag) { +		if (!(tmpstream = jas_stream_memopen(0, 0))) { +			goto error; +		} +		if (jas_stream_copy(tmpstream, in, box->datalen)) { +			jas_eprintf("cannot copy box data\n"); +			goto error; +		} +		jas_stream_rewind(tmpstream); + +		if (box->ops->getdata) { +			if ((*box->ops->getdata)(box, tmpstream)) { +				jas_eprintf("cannot parse box data\n"); +				goto error; +			} +		} +		jas_stream_close(tmpstream); +	} + +	if (jas_getdbglevel() >= 1) { +		jp2_box_dump(box, stderr); +	} + +	return box; +	abort(); + +error: +	if (box) { +		jp2_box_destroy(box); +	} +	if (tmpstream) { +		jas_stream_close(tmpstream); +	} +	return 0; +} + +void jp2_box_dump(jp2_box_t *box, FILE *out) +{ +	jp2_boxinfo_t *boxinfo; +	boxinfo = jp2_boxinfolookup(box->type); +	assert(boxinfo); + +	fprintf(out, "JP2 box: "); +	fprintf(out, "type=%c%s%c (0x%08x); length=%d\n", '"', boxinfo->name, +	  '"', box->type, box->len); +	if (box->ops->dumpdata) { +		(*box->ops->dumpdata)(box, out); +	} +} + +static int jp2_jp_getdata(jp2_box_t *box, jas_stream_t *in) +{ +	jp2_jp_t *jp = &box->data.jp; +	if (jp2_getuint32(in, &jp->magic)) { +		return -1; +	} +	return 0; +} + +static int jp2_ftyp_getdata(jp2_box_t *box, jas_stream_t *in) +{ +	jp2_ftyp_t *ftyp = &box->data.ftyp; +	unsigned int i; +	if (jp2_getuint32(in, &ftyp->majver) || jp2_getuint32(in, &ftyp->minver)) { +		return -1; +	} +	ftyp->numcompatcodes = (box->datalen - 8) / 4; +	if (ftyp->numcompatcodes > JP2_FTYP_MAXCOMPATCODES) { +		return -1; +	} +	for (i = 0; i < ftyp->numcompatcodes; ++i) { +		if (jp2_getuint32(in, &ftyp->compatcodes[i])) { +			return -1; +		} +	} +	return 0; +} + +static int jp2_ihdr_getdata(jp2_box_t *box, jas_stream_t *in) +{ +	jp2_ihdr_t *ihdr = &box->data.ihdr; +	if (jp2_getuint32(in, &ihdr->height) || jp2_getuint32(in, &ihdr->width) || +	  jp2_getuint16(in, &ihdr->numcmpts) || jp2_getuint8(in, &ihdr->bpc) || +	  jp2_getuint8(in, &ihdr->comptype) || jp2_getuint8(in, &ihdr->csunk) || +	  jp2_getuint8(in, &ihdr->ipr)) { +		return -1; +	} +	return 0; +} + +static int jp2_bpcc_getdata(jp2_box_t *box, jas_stream_t *in) +{ +	jp2_bpcc_t *bpcc = &box->data.bpcc; +	unsigned int i; +	bpcc->numcmpts = box->datalen; +	if (!(bpcc->bpcs = jas_malloc(bpcc->numcmpts * sizeof(uint_fast8_t)))) { +		return -1; +	} +	for (i = 0; i < bpcc->numcmpts; ++i) { +		if (jp2_getuint8(in, &bpcc->bpcs[i])) { +			return -1; +		} +	} +	return 0; +} + +static void jp2_colr_dumpdata(jp2_box_t *box, FILE *out) +{ +	jp2_colr_t *colr = &box->data.colr; +	fprintf(out, "method=%d; pri=%d; approx=%d\n", (int)colr->method, (int)colr->pri, (int)colr->approx); +	switch (colr->method) { +	case JP2_COLR_ENUM: +		fprintf(out, "csid=%d\n", (int)colr->csid); +		break; +	case JP2_COLR_ICC: +		jas_memdump(out, colr->iccp, colr->iccplen); +		break; +	} +} + +static int jp2_colr_getdata(jp2_box_t *box, jas_stream_t *in) +{ +	jp2_colr_t *colr = &box->data.colr; +	colr->csid = 0; +	colr->iccp = 0; +	colr->iccplen = 0; + +	if (jp2_getuint8(in, &colr->method) || jp2_getuint8(in, &colr->pri) || +	  jp2_getuint8(in, &colr->approx)) { +		return -1; +	} +	switch (colr->method) { +	case JP2_COLR_ENUM: +		if (jp2_getuint32(in, &colr->csid)) { +			return -1; +		} +		break; +	case JP2_COLR_ICC: +		colr->iccplen = box->datalen - 3; +		if (!(colr->iccp = jas_malloc(colr->iccplen * sizeof(uint_fast8_t)))) { +			return -1; +		} +		if (jas_stream_read(in, colr->iccp, colr->iccplen) != colr->iccplen) { +			return -1; +		} +		break; +	} +	return 0; +} + +static void jp2_cdef_dumpdata(jp2_box_t *box, FILE *out) +{ +	jp2_cdef_t *cdef = &box->data.cdef; +	unsigned int i; +	for (i = 0; i < cdef->numchans; ++i) { +		fprintf(out, "channo=%d; type=%d; assoc=%d\n", +		  cdef->ents[i].channo, cdef->ents[i].type, cdef->ents[i].assoc); +	} +} + +static void jp2_colr_destroy(jp2_box_t *box) +{ +	jp2_colr_t *colr = &box->data.colr; +	if (colr->iccp) { +		jas_free(colr->iccp); +	} +} + +static int jp2_cdef_getdata(jp2_box_t *box, jas_stream_t *in) +{ +	jp2_cdef_t *cdef = &box->data.cdef; +	jp2_cdefchan_t *chan; +	unsigned int channo; +	if (jp2_getuint16(in, &cdef->numchans)) { +		return -1; +	} +	if (!(cdef->ents = jas_malloc(cdef->numchans * sizeof(jp2_cdefchan_t)))) { +		return -1; +	} +	for (channo = 0; channo < cdef->numchans; ++channo) { +		chan = &cdef->ents[channo]; +		if (jp2_getuint16(in, &chan->channo) || jp2_getuint16(in, &chan->type) || +		  jp2_getuint16(in, &chan->assoc)) { +			return -1; +		} +	} +	return 0; +} + +/******************************************************************************\ +* Box output. +\******************************************************************************/ + +int jp2_box_put(jp2_box_t *box, jas_stream_t *out) +{ +	jas_stream_t *tmpstream; +	bool extlen; +	bool dataflag; + +	tmpstream = 0; + +	dataflag = !(box->info->flags & (JP2_BOX_SUPER | JP2_BOX_NODATA)); + +	if (dataflag) { +		tmpstream = jas_stream_memopen(0, 0); +		if (box->ops->putdata) { +			if ((*box->ops->putdata)(box, tmpstream)) { +				goto error; +			} +		} +		box->len = jas_stream_tell(tmpstream) + JP2_BOX_HDRLEN(false); +		jas_stream_rewind(tmpstream); +	} +	extlen = (box->len >= (((uint_fast64_t)1) << 32)) != 0; +	if (jp2_putuint32(out, extlen ? 1 : box->len)) { +		goto error; +	} +	if (jp2_putuint32(out, box->type)) { +		goto error; +	} +	if (extlen) { +		if (jp2_putuint64(out, box->len)) { +			goto error; +		} +	} + +	if (dataflag) { +		if (jas_stream_copy(out, tmpstream, box->len - JP2_BOX_HDRLEN(false))) { +			goto error; +		} +		jas_stream_close(tmpstream); +	} + +	return 0; +	abort(); + +error: + +	if (tmpstream) { +		jas_stream_close(tmpstream); +	} +	return -1; +} + +static int jp2_jp_putdata(jp2_box_t *box, jas_stream_t *out) +{ +	jp2_jp_t *jp = &box->data.jp; +	if (jp2_putuint32(out, jp->magic)) { +		return -1; +	} +	return 0; +} + +static int jp2_ftyp_putdata(jp2_box_t *box, jas_stream_t *out) +{ +	jp2_ftyp_t *ftyp = &box->data.ftyp; +	unsigned int i; +	if (jp2_putuint32(out, ftyp->majver) || jp2_putuint32(out, ftyp->minver)) { +		return -1; +	} +	for (i = 0; i < ftyp->numcompatcodes; ++i) { +		if (jp2_putuint32(out, ftyp->compatcodes[i])) { +			return -1; +		} +	} +	return 0; +} + +static int jp2_ihdr_putdata(jp2_box_t *box, jas_stream_t *out) +{ +	jp2_ihdr_t *ihdr = &box->data.ihdr; +	if (jp2_putuint32(out, ihdr->height) || jp2_putuint32(out, ihdr->width) || +	  jp2_putuint16(out, ihdr->numcmpts) || jp2_putuint8(out, ihdr->bpc) || +	  jp2_putuint8(out, ihdr->comptype) || jp2_putuint8(out, ihdr->csunk) || +	  jp2_putuint8(out, ihdr->ipr)) { +		return -1; +	} +	return 0; +} + +static int jp2_bpcc_putdata(jp2_box_t *box, jas_stream_t *out) +{ +	jp2_bpcc_t *bpcc = &box->data.bpcc; +	unsigned int i; +	for (i = 0; i < bpcc->numcmpts; ++i) { +		if (jp2_putuint8(out, bpcc->bpcs[i])) { +			return -1; +		} +	} +	return 0; +} + +static int jp2_colr_putdata(jp2_box_t *box, jas_stream_t *out) +{ +	jp2_colr_t *colr = &box->data.colr; +	if (jp2_putuint8(out, colr->method) || jp2_putuint8(out, colr->pri) || +	  jp2_putuint8(out, colr->approx)) { +		return -1; +	} +	switch (colr->method) { +	case JP2_COLR_ENUM: +		if (jp2_putuint32(out, colr->csid)) { +			return -1; +		} +		break; +	case JP2_COLR_ICC: +		if (jas_stream_write(out, colr->iccp, +		  JAS_CAST(int, colr->iccplen)) != JAS_CAST(int, colr->iccplen)) +			return -1; +		break; +	} +	return 0; +} + +static int jp2_cdef_putdata(jp2_box_t *box, jas_stream_t *out) +{ +	jp2_cdef_t *cdef = &box->data.cdef; +	unsigned int i; +	jp2_cdefchan_t *ent; + +	if (jp2_putuint16(out, cdef->numchans)) { +		return -1; +	} + +	for (i = 0; i < cdef->numchans; ++i) { +		ent = &cdef->ents[i]; +		if (jp2_putuint16(out, ent->channo) || +		  jp2_putuint16(out, ent->type) || +		  jp2_putuint16(out, ent->assoc)) { +			return -1; +		} +	} +	return 0; +} + +/******************************************************************************\ +* Input operations for primitive types. +\******************************************************************************/ + +static int jp2_getuint8(jas_stream_t *in, uint_fast8_t *val) +{ +	int c; +	if ((c = jas_stream_getc(in)) == EOF) { +		return -1; +	} +	if (val) { +		*val = c; +	} +	return 0; +} + +static int jp2_getuint16(jas_stream_t *in, uint_fast16_t *val) +{ +	uint_fast16_t v; +	int c; +	if ((c = jas_stream_getc(in)) == EOF) { +		return -1; +	} +	v = c; +	if ((c = jas_stream_getc(in)) == EOF) { +		return -1; +	} +	v = (v << 8) | c; +	if (val) { +		*val = v; +	} +	return 0; +} + +static int jp2_getuint32(jas_stream_t *in, uint_fast32_t *val) +{ +	uint_fast32_t v; +	int c; +	if ((c = jas_stream_getc(in)) == EOF) { +		return -1; +	} +	v = c; +	if ((c = jas_stream_getc(in)) == EOF) { +		return -1; +	} +	v = (v << 8) | c; +	if ((c = jas_stream_getc(in)) == EOF) { +		return -1; +	} +	v = (v << 8) | c; +	if ((c = jas_stream_getc(in)) == EOF) { +		return -1; +	} +	v = (v << 8) | c; +	if (val) { +		*val = v; +	} +	return 0; +} + +static int jp2_getuint64(jas_stream_t *in, uint_fast64_t *val) +{ +	uint_fast64_t tmpval; +	int i; +	int c; + +	tmpval = 0; +	for (i = 0; i < 8; ++i) { +		tmpval <<= 8; +		if ((c = jas_stream_getc(in)) == EOF) { +			return -1; +		} +		tmpval |= (c & 0xff); +	} +	*val = tmpval; + +	return 0; +} + +/******************************************************************************\ +* Output operations for primitive types. +\******************************************************************************/ + +static int jp2_putuint8(jas_stream_t *out, uint_fast8_t val) +{ +	if (jas_stream_putc(out, val & 0xff) == EOF) { +		return -1; +	} +	return 0; +} + +static int jp2_putuint16(jas_stream_t *out, uint_fast16_t val) +{ +	if (jas_stream_putc(out, (val >> 8) & 0xff) == EOF || +	  jas_stream_putc(out, val & 0xff) == EOF) { +		return -1; +	} +	return 0; +} + +static int jp2_putuint32(jas_stream_t *out, uint_fast32_t val) +{ +	if (jas_stream_putc(out, (val >> 24) & 0xff) == EOF || +	  jas_stream_putc(out, (val >> 16) & 0xff) == EOF || +	  jas_stream_putc(out, (val >> 8) & 0xff) == EOF || +	  jas_stream_putc(out, val & 0xff) == EOF) { +		return -1; +	} +	return 0; +} + +static int jp2_putuint64(jas_stream_t *out, uint_fast64_t val) +{ +	if (jp2_putuint32(out, (val >> 32) & 0xffffffffUL) || +	  jp2_putuint32(out, val & 0xffffffffUL)) { +		return -1; +	} +	return 0; +} + +/******************************************************************************\ +* Miscellaneous code. +\******************************************************************************/ + +jp2_boxinfo_t *jp2_boxinfolookup(int type) +{ +	jp2_boxinfo_t *boxinfo; +	for (boxinfo = jp2_boxinfos; boxinfo->name; ++boxinfo) { +		if (boxinfo->type == type) { +			return boxinfo; +		} +	} +	return &jp2_boxinfo_unk; +} + + + + + +static void jp2_cmap_destroy(jp2_box_t *box) +{ +	jp2_cmap_t *cmap = &box->data.cmap; +	if (cmap->ents) { +		jas_free(cmap->ents); +	} +} + +static int jp2_cmap_getdata(jp2_box_t *box, jas_stream_t *in) +{ +	jp2_cmap_t *cmap = &box->data.cmap; +	jp2_cmapent_t *ent; +	unsigned int i; + +	cmap->numchans = (box->datalen) / 4; +	if (!(cmap->ents = jas_malloc(cmap->numchans * sizeof(jp2_cmapent_t)))) { +		return -1; +	} +	for (i = 0; i < cmap->numchans; ++i) { +		ent = &cmap->ents[i]; +		if (jp2_getuint16(in, &ent->cmptno) || +		  jp2_getuint8(in, &ent->map) || +		  jp2_getuint8(in, &ent->pcol)) { +			return -1; +		} +	} +	 +	return 0; +} + +static int jp2_cmap_putdata(jp2_box_t *box, jas_stream_t *out) +{ +	/* Eliminate compiler warning about unused variables. */ +	box = 0; +	out = 0; + +	return -1; +} + +static void jp2_cmap_dumpdata(jp2_box_t *box, FILE *out) +{ +	jp2_cmap_t *cmap = &box->data.cmap; +	unsigned int i; +	jp2_cmapent_t *ent; +	fprintf(out, "numchans = %d\n", (int) cmap->numchans); +	for (i = 0; i < cmap->numchans; ++i) { +		ent = &cmap->ents[i]; +		fprintf(out, "cmptno=%d; map=%d; pcol=%d\n", +		  (int) ent->cmptno, (int) ent->map, (int) ent->pcol); +	} +} + +static void jp2_pclr_destroy(jp2_box_t *box) +{ +	jp2_pclr_t *pclr = &box->data.pclr; +	if (pclr->lutdata) { +		jas_free(pclr->lutdata); +	} +	if (pclr->bpc) +		jas_free(pclr->bpc); +} + +static int jp2_pclr_getdata(jp2_box_t *box, jas_stream_t *in) +{ +	jp2_pclr_t *pclr = &box->data.pclr; +	int lutsize; +	unsigned int i; +	unsigned int j; +	int_fast32_t x; + +	pclr->lutdata = 0; + +	if (jp2_getuint16(in, &pclr->numlutents) || +	  jp2_getuint8(in, &pclr->numchans)) { +		return -1; +	} +	lutsize = pclr->numlutents * pclr->numchans; +	if (!(pclr->lutdata = jas_malloc(lutsize * sizeof(int_fast32_t)))) { +		return -1; +	} +	if (!(pclr->bpc = jas_malloc(pclr->numchans * sizeof(uint_fast8_t)))) { +		return -1; +	} +	for (i = 0; i < pclr->numchans; ++i) { +		if (jp2_getuint8(in, &pclr->bpc[i])) { +			return -1; +		} +	} +	for (i = 0; i < pclr->numlutents; ++i) { +		for (j = 0; j < pclr->numchans; ++j) { +			if (jp2_getint(in, (pclr->bpc[j] & 0x80) != 0, +			  (pclr->bpc[j] & 0x7f) + 1, &x)) { +				return -1; +			} +			pclr->lutdata[i * pclr->numchans + j] = x; +		} +	} +	return 0; +} + +static int jp2_pclr_putdata(jp2_box_t *box, jas_stream_t *out) +{ +#if 0 +	jp2_pclr_t *pclr = &box->data.pclr; +#endif +/* Eliminate warning about unused variable. */ +box = 0; +out = 0; +	return -1; +} + +static void jp2_pclr_dumpdata(jp2_box_t *box, FILE *out) +{ +	jp2_pclr_t *pclr = &box->data.pclr; +	unsigned int i; +	int j; +	fprintf(out, "numents=%d; numchans=%d\n", (int) pclr->numlutents, +	  (int) pclr->numchans); +	for (i = 0; i < pclr->numlutents; ++i) { +		for (j = 0; j < pclr->numchans; ++j) { +			fprintf(out, "LUT[%d][%d]=%d\n", i, j, pclr->lutdata[i * pclr->numchans + j]); +		} +	} +} + +static void jp2_uuid_destroy(jp2_box_t *box) +{ +  jp2_uuid_t *uuid = &box->data.uuid; +  if (uuid->data) +  { +      jas_free(uuid->data); +      uuid->data = NULL; +  } +} + +static int jp2_uuid_getdata(jp2_box_t *box, jas_stream_t *in) +{ +  jp2_uuid_t *uuid = &box->data.uuid; +  int i; +   +  for (i = 0; i < 16; i++) +  { +    if (jp2_getuint8(in, &uuid->uuid[i])) +      return -1; +  } +   +  uuid->data_len = box->datalen - 16; +  uuid->data = jas_malloc(uuid->data_len * sizeof(uint_fast8_t)); +  for (i = 0; i < uuid->data_len; i++) +  { +    if (jp2_getuint8(in, &uuid->data[i])) +      return -1; +  } +  return 0; +} + +static int jp2_uuid_putdata(jp2_box_t *box, jas_stream_t *out) +{ +  jp2_uuid_t *uuid = &box->data.uuid; +  int i; +   +  for (i = 0; i < 16; i++) +  { +      if (jp2_putuint8(out, uuid->uuid[i])) +    return -1; +  } +   +  for (i = 0; i < uuid->data_len; i++) +  { +      if (jp2_putuint8(out, uuid->data[i])) +    return -1; +  } +  return 0; +} + +static int jp2_getint(jas_stream_t *in, int s, int n, int_fast32_t *val) +{ +	int c; +	int i; +	uint_fast32_t v; +	int m; + +	m = (n + 7) / 8; + +	v = 0; +	for (i = 0; i < m; ++i) { +		if ((c = jas_stream_getc(in)) == EOF) { +			return -1; +		} +		v = (v << 8) | c; +	} +	v &= ONES(n); +	if (s) { +		int sb; +		sb = v & (1 << (8 * m - 1)); +		*val = ((~v) + 1) & ONES(8 * m); +		if (sb) { +			*val = -*val; +		} +	} else { +		*val = v; +	} + +	return 0; +} + +jp2_cdefchan_t *jp2_cdef_lookup(jp2_cdef_t *cdef, int channo) +{ +	unsigned int i; +	jp2_cdefchan_t *cdefent; +	for (i = 0; i < cdef->numchans; ++i) { +		cdefent = &cdef->ents[i]; +		if (cdefent->channo == JAS_CAST(unsigned int, channo)) { +			return cdefent; +		} +	} +	return 0; +} diff --git a/src/libjasper/jp2/jp2_cod.h b/src/libjasper/jp2/jp2_cod.h new file mode 100644 index 0000000..5bad06f --- /dev/null +++ b/src/libjasper/jp2/jp2_cod.h @@ -0,0 +1,328 @@ +/* + * Copyright (c) 1999-2000 Image Power, Inc. and the University of + *   British Columbia. + * Copyright (c) 2001-2002 Michael David Adams. + * All rights reserved. + + GeoJasper revision: Dima (11/07/2003 17:29 - UUID from j_image_t) + Modifications by Andrey Kiselev <dron@remotesensing.org> to handle UUID box properly. + */ + +/* __START_OF_JASPER_LICENSE__ + *  + * JasPer License Version 2.0 + *  + * Copyright (c) 2001-2006 Michael David Adams + * Copyright (c) 1999-2000 Image Power, Inc. + * Copyright (c) 1999-2000 The University of British Columbia + *  + * All rights reserved. + *  + * Permission is hereby granted, free of charge, to any person (the + * "User") obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without restriction, + * including without limitation the rights to use, copy, modify, merge, + * publish, distribute, and/or sell copies of the Software, and to permit + * persons to whom the Software is furnished to do so, subject to the + * following conditions: + *  + * 1.  The above copyright notices and this permission notice (which + * includes the disclaimer below) shall be included in all copies or + * substantial portions of the Software. + *  + * 2.  The name of a copyright holder shall not be used to endorse or + * promote products derived from the Software without specific prior + * written permission. + *  + * THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL PART OF THIS + * LICENSE.  NO USE OF THE SOFTWARE IS AUTHORIZED HEREUNDER EXCEPT UNDER + * THIS DISCLAIMER.  THE SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS + * "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING + * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.  IN NO + * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL + * INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING + * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, + * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION + * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.  NO ASSURANCES ARE + * PROVIDED BY THE COPYRIGHT HOLDERS THAT THE SOFTWARE DOES NOT INFRINGE + * THE PATENT OR OTHER INTELLECTUAL PROPERTY RIGHTS OF ANY OTHER ENTITY. + * EACH COPYRIGHT HOLDER DISCLAIMS ANY LIABILITY TO THE USER FOR CLAIMS + * BROUGHT BY ANY OTHER ENTITY BASED ON INFRINGEMENT OF INTELLECTUAL + * PROPERTY RIGHTS OR OTHERWISE.  AS A CONDITION TO EXERCISING THE RIGHTS + * GRANTED HEREUNDER, EACH USER HEREBY ASSUMES SOLE RESPONSIBILITY TO SECURE + * ANY OTHER INTELLECTUAL PROPERTY RIGHTS NEEDED, IF ANY.  THE SOFTWARE + * IS NOT FAULT-TOLERANT AND IS NOT INTENDED FOR USE IN MISSION-CRITICAL + * SYSTEMS, SUCH AS THOSE USED IN THE OPERATION OF NUCLEAR FACILITIES, + * AIRCRAFT NAVIGATION OR COMMUNICATION SYSTEMS, AIR TRAFFIC CONTROL + * SYSTEMS, DIRECT LIFE SUPPORT MACHINES, OR WEAPONS SYSTEMS, IN WHICH + * THE FAILURE OF THE SOFTWARE OR SYSTEM COULD LEAD DIRECTLY TO DEATH, + * PERSONAL INJURY, OR SEVERE PHYSICAL OR ENVIRONMENTAL DAMAGE ("HIGH + * RISK ACTIVITIES").  THE COPYRIGHT HOLDERS SPECIFICALLY DISCLAIM ANY + * EXPRESS OR IMPLIED WARRANTY OF FITNESS FOR HIGH RISK ACTIVITIES. + *  + * __END_OF_JASPER_LICENSE__ + */ + +/* + * JP2 Library + * + * $Id: jp2_cod.h,v 1.1 2008/10/17 06:14:59 scuri Exp $ + */ + +#ifndef JP2_COD_H +#define JP2_COD_H + +/******************************************************************************\ +* Includes. +\******************************************************************************/ + +#include "jasper/jas_types.h" + +/******************************************************************************\ +* Macros. +\******************************************************************************/ + +#define	JP2_SPTOBPC(s, p) \ +	((((p) - 1) & 0x7f) | (((s) & 1) << 7)) + +/******************************************************************************\ +* Box class. +\******************************************************************************/ + +#define	JP2_BOX_HDRLEN(ext) ((ext) ? 16 : 8) + +/* Box types. */ +#define	JP2_BOX_JP		0x6a502020	/* Signature */ +#define JP2_BOX_FTYP	0x66747970	/* File Type */ +#define	JP2_BOX_JP2H	0x6a703268	/* JP2 Header */ +#define	JP2_BOX_IHDR	0x69686472	/* Image Header */ +#define	JP2_BOX_BPCC	0x62706363	/* Bits Per Component */ +#define	JP2_BOX_COLR	0x636f6c72	/* Color Specification */ +#define	JP2_BOX_PCLR	0x70636c72	/* Palette */ +#define	JP2_BOX_CMAP	0x636d6170	/* Component Mapping */ +#define	JP2_BOX_CDEF	0x63646566	/* Channel Definition */ +#define	JP2_BOX_RES		0x72657320	/* Resolution */ +#define	JP2_BOX_RESC	0x72657363	/* Capture Resolution */ +#define	JP2_BOX_RESD	0x72657364	/* Default Display Resolution */ +#define	JP2_BOX_JP2C	0x6a703263	/* Contiguous Code Stream */ +#define	JP2_BOX_JP2I	0x6a703269	/* Intellectual Property */ +#define	JP2_BOX_XML		0x786d6c20	/* XML */ +#define	JP2_BOX_UUID	0x75756964	/* UUID */ +#define	JP2_BOX_UINF	0x75696e66	/* UUID Info */ +#define	JP2_BOX_ULST	0x75637374	/* UUID List */ +#define	JP2_BOX_URL		0x75726c20	/* URL */ + +#define	JP2_BOX_SUPER	0x01 +#define	JP2_BOX_NODATA	0x02 + +/* JP box data. */ + +#define	JP2_JP_MAGIC	0x0d0a870a +#define	JP2_JP_LEN		12 + +// Magic sequence for GeoJP2 UUID box +static unsigned char msi_uuid[16] = +        { 0xb1,0x4b,0xf8,0xbd, +          0x08,0x3d,0x4b,0x43,  +          0xa5,0xae,0x8c,0xd7, +          0xd5,0xa6,0xce,0x03}; + +// Magic sequence for XMP UUID box +static unsigned char xmp_uuid[16] = +        { 0xBE, 0x7A, 0xCF, 0xCB,  +          0x97, 0xA9, 0x42, 0xE8,  +          0x9C, 0x71, 0x99, 0x94, +          0x91, 0xE3, 0xAF, 0xAC }; + +typedef struct { +	uint_fast32_t magic; +} jp2_jp_t; + +/* FTYP box data. */ + +#define	JP2_FTYP_MAXCOMPATCODES	32 +#define	JP2_FTYP_MAJVER		0x6a703220 +#define	JP2_FTYP_MINVER		0 +#define	JP2_FTYP_COMPATCODE		JP2_FTYP_MAJVER + +typedef struct { +	uint_fast32_t majver; +	uint_fast32_t minver; +	uint_fast32_t numcompatcodes; +	uint_fast32_t compatcodes[JP2_FTYP_MAXCOMPATCODES]; +} jp2_ftyp_t; + +/* IHDR box data. */ + +#define	JP2_IHDR_COMPTYPE	7 +#define	JP2_IHDR_BPCNULL	255 + +typedef struct { +	uint_fast32_t width; +	uint_fast32_t height; +	uint_fast16_t numcmpts; +	uint_fast8_t bpc; +	uint_fast8_t comptype; +	uint_fast8_t csunk; +	uint_fast8_t ipr; +} jp2_ihdr_t; + +/* BPCC box data. */ + +typedef struct { +	uint_fast16_t numcmpts; +	uint_fast8_t *bpcs; +} jp2_bpcc_t; + +/* COLR box data. */ + +#define	JP2_COLR_ENUM	1 +#define	JP2_COLR_ICC	2 +#define	JP2_COLR_PRI	0 + +#define	JP2_COLR_SRGB	16 +#define	JP2_COLR_SGRAY	17 +#define	JP2_COLR_SYCC	18 + +typedef struct { +	uint_fast8_t method; +	uint_fast8_t pri; +	uint_fast8_t approx; +	uint_fast32_t csid; +	uint_fast8_t *iccp; +	int iccplen; +	/* XXX - Someday we ought to add ICC profile data here. */ +} jp2_colr_t; + +/* PCLR box data. */ + +typedef struct { +	uint_fast16_t numlutents; +	uint_fast8_t numchans; +	int_fast32_t *lutdata; +	uint_fast8_t *bpc; +} jp2_pclr_t; + +/* CDEF box per-channel data. */ + +#define JP2_CDEF_RGB_R	1 +#define JP2_CDEF_RGB_G	2 +#define JP2_CDEF_RGB_B	3 + +#define JP2_CDEF_YCBCR_Y	1 +#define JP2_CDEF_YCBCR_CB	2 +#define JP2_CDEF_YCBCR_CR	3 + +#define	JP2_CDEF_GRAY_Y	1 + +#define	JP2_CDEF_TYPE_COLOR	0 +#define	JP2_CDEF_TYPE_OPACITY	1 +#define	JP2_CDEF_TYPE_UNSPEC	65535 +#define	JP2_CDEF_ASOC_ALL	0 +#define	JP2_CDEF_ASOC_NONE	65535 + +typedef struct { +	uint_fast16_t channo; +	uint_fast16_t type; +	uint_fast16_t assoc; +} jp2_cdefchan_t; + +/* CDEF box data. */ + +typedef struct { +	uint_fast16_t numchans; +	jp2_cdefchan_t *ents; +} jp2_cdef_t; + +typedef struct { +	uint_fast16_t cmptno; +	uint_fast8_t map; +	uint_fast8_t pcol; +} jp2_cmapent_t; + +typedef struct { +	uint_fast16_t numchans; +	jp2_cmapent_t *ents; +} jp2_cmap_t; + +typedef struct { +	uint_fast32_t data_len; +	uint_fast8_t uuid[16]; +	uint_fast8_t *data; +} jp2_uuid_t; + +#define	JP2_CMAP_DIRECT		0 +#define	JP2_CMAP_PALETTE	1 + +/* Generic box. */ + +struct jp2_boxops_s; +typedef struct { + +	struct jp2_boxops_s *ops; +	struct jp2_boxinfo_s *info; + +	uint_fast32_t type; + +	/* The length of the box including the (variable-length) header. */ +	uint_fast32_t len; + +	/* The length of the box data. */ +	uint_fast32_t datalen; + +	union { +		jp2_jp_t jp; +		jp2_ftyp_t ftyp; +		jp2_ihdr_t ihdr; +		jp2_bpcc_t bpcc; +		jp2_colr_t colr; +		jp2_pclr_t pclr; +		jp2_cdef_t cdef; +		jp2_cmap_t cmap; +		jp2_uuid_t uuid; +	} data; + +} jp2_box_t; + +typedef struct jp2_boxops_s { +	void (*init)(jp2_box_t *box); +	void (*destroy)(jp2_box_t *box); +	int (*getdata)(jp2_box_t *box, jas_stream_t *in); +	int (*putdata)(jp2_box_t *box, jas_stream_t *out); +	void (*dumpdata)(jp2_box_t *box, FILE *out); +} jp2_boxops_t; + +/******************************************************************************\ +* +\******************************************************************************/ + +typedef struct jp2_boxinfo_s { +	int type; +	char *name; +	int flags; +	jp2_boxops_t ops; +} jp2_boxinfo_t; + +/******************************************************************************\ +* Box class. +\******************************************************************************/ + +jp2_box_t *jp2_box_create(int type); +void jp2_box_destroy(jp2_box_t *box); +jp2_box_t *jp2_box_get(jas_stream_t *in); +int jp2_box_put(jp2_box_t *box, jas_stream_t *out); + +#define JP2_DTYPETOBPC(dtype) \ +  ((JAS_IMAGE_CDT_GETSGND(dtype) << 7) | (JAS_IMAGE_CDT_GETPREC(dtype) - 1)) +#define	JP2_BPCTODTYPE(bpc) \ +  (JAS_IMAGE_CDT_SETSGND(bpc >> 7) | JAS_IMAGE_CDT_SETPREC((bpc & 0x7f) + 1)) + +#define ICC_CS_RGB	0x52474220 +#define ICC_CS_YCBCR	0x59436272 +#define ICC_CS_GRAY	0x47524159 + +jp2_cdefchan_t *jp2_cdef_lookup(jp2_cdef_t *cdef, int channo); + + +#endif diff --git a/src/libjasper/jp2/jp2_dec.c b/src/libjasper/jp2/jp2_dec.c new file mode 100644 index 0000000..45a8993 --- /dev/null +++ b/src/libjasper/jp2/jp2_dec.c @@ -0,0 +1,702 @@ +/* + * Copyright (c) 1999-2000 Image Power, Inc. and the University of + *   British Columbia. + * Copyright (c) 2001-2003 Michael David Adams. + * All rights reserved. + + GeoJasper revision: Dima (11/07/2003 17:29 - UUID and additional args) + */ + +/* __START_OF_JASPER_LICENSE__ + *  + * JasPer License Version 2.0 + *  + * Copyright (c) 2001-2006 Michael David Adams + * Copyright (c) 1999-2000 Image Power, Inc. + * Copyright (c) 1999-2000 The University of British Columbia + *  + * All rights reserved. + *  + * Permission is hereby granted, free of charge, to any person (the + * "User") obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without restriction, + * including without limitation the rights to use, copy, modify, merge, + * publish, distribute, and/or sell copies of the Software, and to permit + * persons to whom the Software is furnished to do so, subject to the + * following conditions: + *  + * 1.  The above copyright notices and this permission notice (which + * includes the disclaimer below) shall be included in all copies or + * substantial portions of the Software. + *  + * 2.  The name of a copyright holder shall not be used to endorse or + * promote products derived from the Software without specific prior + * written permission. + *  + * THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL PART OF THIS + * LICENSE.  NO USE OF THE SOFTWARE IS AUTHORIZED HEREUNDER EXCEPT UNDER + * THIS DISCLAIMER.  THE SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS + * "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING + * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.  IN NO + * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL + * INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING + * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, + * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION + * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.  NO ASSURANCES ARE + * PROVIDED BY THE COPYRIGHT HOLDERS THAT THE SOFTWARE DOES NOT INFRINGE + * THE PATENT OR OTHER INTELLECTUAL PROPERTY RIGHTS OF ANY OTHER ENTITY. + * EACH COPYRIGHT HOLDER DISCLAIMS ANY LIABILITY TO THE USER FOR CLAIMS + * BROUGHT BY ANY OTHER ENTITY BASED ON INFRINGEMENT OF INTELLECTUAL + * PROPERTY RIGHTS OR OTHERWISE.  AS A CONDITION TO EXERCISING THE RIGHTS + * GRANTED HEREUNDER, EACH USER HEREBY ASSUMES SOLE RESPONSIBILITY TO SECURE + * ANY OTHER INTELLECTUAL PROPERTY RIGHTS NEEDED, IF ANY.  THE SOFTWARE + * IS NOT FAULT-TOLERANT AND IS NOT INTENDED FOR USE IN MISSION-CRITICAL + * SYSTEMS, SUCH AS THOSE USED IN THE OPERATION OF NUCLEAR FACILITIES, + * AIRCRAFT NAVIGATION OR COMMUNICATION SYSTEMS, AIR TRAFFIC CONTROL + * SYSTEMS, DIRECT LIFE SUPPORT MACHINES, OR WEAPONS SYSTEMS, IN WHICH + * THE FAILURE OF THE SOFTWARE OR SYSTEM COULD LEAD DIRECTLY TO DEATH, + * PERSONAL INJURY, OR SEVERE PHYSICAL OR ENVIRONMENTAL DAMAGE ("HIGH + * RISK ACTIVITIES").  THE COPYRIGHT HOLDERS SPECIFICALLY DISCLAIM ANY + * EXPRESS OR IMPLIED WARRANTY OF FITNESS FOR HIGH RISK ACTIVITIES. + *  + * __END_OF_JASPER_LICENSE__ + */ + +/* + * JP2 Library + * + * $Id: jp2_dec.c,v 1.1 2008/10/17 06:14:59 scuri Exp $ + */ + +/******************************************************************************\ +* Includes. +\******************************************************************************/ + +#include "jasper/jas_image.h" +#include "jasper/jas_stream.h" +#include "jasper/jas_math.h" +#include "jasper/jas_debug.h" +#include "jasper/jas_malloc.h" +#include "jasper/jas_version.h" + +// GeoJasper: dima +#if !defined( JAS_GEO_OMIT_PRINTING_CODE ) +#include "../tiff/geotiff_buffer.h" +#endif +// end: dima + +#include "jp2_cod.h" +#include "jp2_dec.h" + +#define	JP2_VALIDATELEN	(JAS_MIN(JP2_JP_LEN + 16, JAS_STREAM_MAXPUTBACK)) + +static jp2_dec_t *jp2_dec_create(void); +static void jp2_dec_destroy(jp2_dec_t *dec); +static int jp2_getcs(jp2_colr_t *colr); +static int fromiccpcs(int cs); +static int jp2_getct(int colorspace, int type, int assoc); + +/******************************************************************************\ +* Functions. +\******************************************************************************/ + +jas_image_t *jp2_decode(jas_stream_t *in, char *optstr) +{ +	jp2_box_t *box; +	int found; +	jas_image_t *image; +	jp2_dec_t *dec; +	bool samedtype; +	int dtype; +	unsigned int i; +	jp2_cmap_t *cmapd; +	jp2_pclr_t *pclrd; +	jp2_cdef_t *cdefd; +	unsigned int channo; +	int newcmptno; +	int_fast32_t *lutents; +#if 0 +	jp2_cdefchan_t *cdefent; +	int cmptno; +#endif +	jp2_cmapent_t *cmapent; +	jas_icchdr_t icchdr; +	jas_iccprof_t *iccprof; + +  // GeoJasper: dima - begin - temporary metadata buffers +  //jas_aux_buffer_t aux_buf; +  //aux_buf.id = 0; +  jas_metadata_boxes_t tmp_metadata; +  tmp_metadata.count = JAS_IMAGE_NUM_BOXES; +  for (i=0; i<tmp_metadata.count; ++i) +    tmp_metadata.boxes[i] = jas_box_init(); +  // GeoJasper: dima - end - temporary metadata buffers + +	dec = 0; +	box = 0; +	image = 0; + +	if (!(dec = jp2_dec_create())) { +		goto error; +	} + +	/* Get the first box.  This should be a JP box. */ +	if (!(box = jp2_box_get(in))) { +		jas_eprintf("error: cannot get box\n"); +		goto error; +	} +	if (box->type != JP2_BOX_JP) { +		jas_eprintf("error: expecting signature box\n"); +		goto error; +	} +	if (box->data.jp.magic != JP2_JP_MAGIC) { +		jas_eprintf("incorrect magic number\n"); +		goto error; +	} +	jp2_box_destroy(box); +	box = 0; + +	/* Get the second box.  This should be a FTYP box. */ +	if (!(box = jp2_box_get(in))) { +		goto error; +	} +	if (box->type != JP2_BOX_FTYP) { +		jas_eprintf("expecting file type box\n"); +		goto error; +	} +	jp2_box_destroy(box); +	box = 0; + +	/* Get more boxes... */ +	found = 0; +	while ((box = jp2_box_get(in))) { +		if (jas_getdbglevel() >= 1) { +			jas_eprintf("box type %s\n", box->info->name); +		} +		switch (box->type) { +		case JP2_BOX_JP2C: +			found = 1; +			break; +		case JP2_BOX_IHDR: +			if (!dec->ihdr) { +				dec->ihdr = box; +				box = 0; +			} +			break; +		case JP2_BOX_BPCC: +			if (!dec->bpcc) { +				dec->bpcc = box; +				box = 0; +			} +			break; +		case JP2_BOX_CDEF: +			if (!dec->cdef) { +				dec->cdef = box; +				box = 0; +			} +			break; +		case JP2_BOX_PCLR: +			if (!dec->pclr) { +				dec->pclr = box; +				box = 0; +			} +			break; +		case JP2_BOX_CMAP: +			if (!dec->cmap) { +				dec->cmap = box; +				box = 0; +			} +			break; +		case JP2_BOX_COLR: +			if (!dec->colr) { +				dec->colr = box; +				box = 0; +			} +			break; +    //------------------------------------------------------- +    case JP2_BOX_UUID: // GeoJasper: dima - begin extract uuid +      { +        int box_id = -1; +        if ( memcmp( box->data.uuid.uuid, msi_uuid, sizeof(msi_uuid) ) == 0 ) box_id = JAS_IMAGE_BOX_GEO; +        if ( memcmp( box->data.uuid.uuid, xmp_uuid, sizeof(xmp_uuid) ) == 0 ) box_id = JAS_IMAGE_BOX_XMP; + +        if( box_id >= 0 ) { +          jas_metadata_box_t *metabox = &tmp_metadata.boxes[box_id];  +          if ( jas_box_alloc( metabox, box->data.uuid.data_len ) ) { +            memcpy( metabox->id, box->data.uuid.uuid, sizeof(msi_uuid) ); +            memcpy( metabox->buf, box->data.uuid.data, metabox->size ); +          } // if box allocated +        } // if uuid box contains info to copy +      } + +			break; // GeoJasper: end - begin extract uuid +    //------------------------------------------------------- +		} +		if (box) { +			jp2_box_destroy(box); +			box = 0; +		} +		if (found) { +			break; +		} +	} + +  //------------------------------------------------------- +  // GeoJasper: dima - begin - print geojpeg2000 if needed +#if !defined( JAS_GEO_OMIT_PRINTING_CODE ) +  if ( (optstr) && ( strstr(optstr, "listgeo") != NULL ) ) { +    jas_metadata_box_t *metabox = &tmp_metadata.boxes[JAS_IMAGE_BOX_GEO];  +    long w=1, h=1; + +    if (dec->ihdr) { +      w = dec->ihdr->data.ihdr.width; +      h = dec->ihdr->data.ihdr.height; +    } +    if ( (memcmp(metabox->id, msi_uuid, sizeof(msi_uuid))==0) && metabox->buf != NULL ) +      printGTIFFromMemBufA( metabox->buf, metabox->size, w, h ); +    else +      jas_eprintf("geojasper info: GeoJp2 info not found!\n"); +    exit(0); +  } + +  if ( (optstr) && ( strstr(optstr, "listxmp") != NULL ) ) { +    jas_metadata_box_t *metabox = &tmp_metadata.boxes[JAS_IMAGE_BOX_XMP];  + +    if ( (memcmp(metabox->id, xmp_uuid, sizeof(xmp_uuid))==0) && metabox->buf != NULL ) { +      // xmp buffer in is not guaranteed to be null terminated... +      char *strbuf = (char *) jas_malloc(metabox->size+1); +      strncpy(strbuf, metabox->buf, metabox->size); +      strbuf[metabox->size] = 0;  +      fprintf( stdout, "%s\n", strbuf ); +      jas_free(strbuf); +    } else +      jas_eprintf("geojasper info: Adobe XMP info not found!\n"); +    exit(0); +  } + +  // simple check if we have boxes +  if ( (memcmp(tmp_metadata.boxes[JAS_IMAGE_BOX_GEO].id, msi_uuid, sizeof(msi_uuid))==0) &&  +       tmp_metadata.boxes[JAS_IMAGE_BOX_GEO].buf != NULL ) +    jas_eprintf("geojasper info: GeoJp2 found, size: %d\n", tmp_metadata.boxes[JAS_IMAGE_BOX_GEO].size); + +  if ( (memcmp(tmp_metadata.boxes[JAS_IMAGE_BOX_XMP].id, xmp_uuid, sizeof(xmp_uuid))==0) &&  +       tmp_metadata.boxes[JAS_IMAGE_BOX_XMP].buf != NULL ) +    jas_eprintf("geojasper info: Adobe XMP found, size: %d\n", tmp_metadata.boxes[JAS_IMAGE_BOX_XMP].size); + +#endif // #if !defined( JAS_GEO_OMIT_PRINTING_CODE ) +  // GeoJasper: dima - end - print geojpeg2000 if needed +  //------------------------------------------------------- + +	if (!found) { +		jas_eprintf("error: no code stream found\n"); +		goto error; +	} + +	if (!(dec->image = jpc_decode(in, optstr))) { +		jas_eprintf("error: cannot decode code stream\n"); +		goto error; +	} + +	/* An IHDR box must be present. */ +	if (!dec->ihdr) { +		jas_eprintf("error: missing IHDR box\n"); +		goto error; +	} + +	/* Does the number of components indicated in the IHDR box match +	  the value specified in the code stream? */ +	if (dec->ihdr->data.ihdr.numcmpts != JAS_CAST(unsigned int, jas_image_numcmpts(dec->image))) {  /* IMLIB - changed unit to unsigned int */ +		jas_eprintf("warning: number of components mismatch\n"); +	} + +	/* At least one component must be present. */ +	if (!jas_image_numcmpts(dec->image)) { +		jas_eprintf("error: no components\n"); +		goto error; +	} + +	/* Determine if all components have the same data type. */ +	samedtype = true; +	dtype = jas_image_cmptdtype(dec->image, 0); +	for (i = 1; i < JAS_CAST(unsigned int, jas_image_numcmpts(dec->image)); ++i) { /* IMLIB - changed unit to unsigned int */ +		if (jas_image_cmptdtype(dec->image, i) != dtype) { +			samedtype = false; +			break; +		} +	} + +	/* Is the component data type indicated in the IHDR box consistent +	  with the data in the code stream? */ +	if ((samedtype && dec->ihdr->data.ihdr.bpc != JP2_DTYPETOBPC(dtype)) || +	  (!samedtype && dec->ihdr->data.ihdr.bpc != JP2_IHDR_BPCNULL)) { +		jas_eprintf("warning: component data type mismatch\n"); +	} + +	/* Is the compression type supported? */ +	if (dec->ihdr->data.ihdr.comptype != JP2_IHDR_COMPTYPE) { +		jas_eprintf("error: unsupported compression type\n"); +		goto error; +	} + +	if (dec->bpcc) { +		/* Is the number of components indicated in the BPCC box +		  consistent with the code stream data? */ +		if (dec->bpcc->data.bpcc.numcmpts != JAS_CAST(unsigned int, jas_image_numcmpts( /* IMLIB - changed unit to unsigned int */ +		  dec->image))) { +			jas_eprintf("warning: number of components mismatch\n"); +		} +		/* Is the component data type information indicated in the BPCC +		  box consistent with the code stream data? */ +		if (!samedtype) { +			for (i = 0; i < JAS_CAST(unsigned int, jas_image_numcmpts(dec->image)); ++i) { /* IMLIB - changed unit to unsigned int */ +				if (jas_image_cmptdtype(dec->image, i) != JP2_BPCTODTYPE(dec->bpcc->data.bpcc.bpcs[i])) { +					jas_eprintf("warning: component data type mismatch\n"); +				} +			} +		} else { +			jas_eprintf("warning: superfluous BPCC box\n"); +		} +	} + +	/* A COLR box must be present. */ +	if (!dec->colr) { +		jas_eprintf("error: no COLR box\n"); +		goto error; +	} + +	switch (dec->colr->data.colr.method) { +	case JP2_COLR_ENUM: +		jas_image_setclrspc(dec->image, jp2_getcs(&dec->colr->data.colr)); +		break; +	case JP2_COLR_ICC: +		iccprof = jas_iccprof_createfrombuf(dec->colr->data.colr.iccp, +		  dec->colr->data.colr.iccplen); +		assert(iccprof); +		jas_iccprof_gethdr(iccprof, &icchdr); +		jas_eprintf("ICC Profile CS %08x\n", icchdr.colorspc); +		jas_image_setclrspc(dec->image, fromiccpcs(icchdr.colorspc)); +		dec->image->cmprof_ = jas_cmprof_createfromiccprof(iccprof); +		assert(dec->image->cmprof_); +		jas_iccprof_destroy(iccprof); +		break; +	} + +	/* If a CMAP box is present, a PCLR box must also be present. */ +	if (dec->cmap && !dec->pclr) { +		jas_eprintf("warning: missing PCLR box or superfluous CMAP box\n"); +		jp2_box_destroy(dec->cmap); +		dec->cmap = 0; +	} + +	/* If a CMAP box is not present, a PCLR box must not be present. */ +	if (!dec->cmap && dec->pclr) { +		jas_eprintf("warning: missing CMAP box or superfluous PCLR box\n"); +		jp2_box_destroy(dec->pclr); +		dec->pclr = 0; +	} + +	/* Determine the number of channels (which is essentially the number +	  of components after any palette mappings have been applied). */ +	dec->numchans = dec->cmap ? dec->cmap->data.cmap.numchans : JAS_CAST(unsigned int, jas_image_numcmpts(dec->image)); /* IMLIB - changed unit to unsigned int */ + +	/* Perform a basic sanity check on the CMAP box if present. */ +	if (dec->cmap) { +		for (i = 0; i < dec->numchans; ++i) { +			/* Is the component number reasonable? */ +			if (dec->cmap->data.cmap.ents[i].cmptno >= JAS_CAST(unsigned int, jas_image_numcmpts(dec->image))) { /* IMLIB - changed unit to unsigned int */ +				jas_eprintf("error: invalid component number in CMAP box\n"); +				goto error; +			} +			/* Is the LUT index reasonable? */ +			if (dec->cmap->data.cmap.ents[i].pcol >= dec->pclr->data.pclr.numchans) { +				jas_eprintf("error: invalid CMAP LUT index\n"); +				goto error; +			} +		} +	} + +	/* Allocate space for the channel-number to component-number LUT. */ +	if (!(dec->chantocmptlut = jas_malloc(dec->numchans * sizeof(uint_fast16_t)))) { +		jas_eprintf("error: no memory\n"); +		goto error; +	} + +	if (!dec->cmap) { +		for (i = 0; i < dec->numchans; ++i) { +			dec->chantocmptlut[i] = i; +		} +	} else { +		cmapd = &dec->cmap->data.cmap; +		pclrd = &dec->pclr->data.pclr; +		cdefd = &dec->cdef->data.cdef; +		for (channo = 0; channo < cmapd->numchans; ++channo) { +			cmapent = &cmapd->ents[channo]; +			if (cmapent->map == JP2_CMAP_DIRECT) { +				dec->chantocmptlut[channo] = channo; +			} else if (cmapent->map == JP2_CMAP_PALETTE) { +				lutents = jas_malloc(pclrd->numlutents * sizeof(int_fast32_t)); +				for (i = 0; i < pclrd->numlutents; ++i) { +					lutents[i] = pclrd->lutdata[cmapent->pcol + i * pclrd->numchans]; +				} +				newcmptno = jas_image_numcmpts(dec->image); +				jas_image_depalettize(dec->image, cmapent->cmptno, pclrd->numlutents, lutents, JP2_BPCTODTYPE(pclrd->bpc[cmapent->pcol]), newcmptno); +				dec->chantocmptlut[channo] = newcmptno; +				jas_free(lutents); +#if 0 +				if (dec->cdef) { +					cdefent = jp2_cdef_lookup(cdefd, channo); +					if (!cdefent) { +						abort(); +					} +				jas_image_setcmpttype(dec->image, newcmptno, jp2_getct(jas_image_clrspc(dec->image), cdefent->type, cdefent->assoc)); +				} else { +				jas_image_setcmpttype(dec->image, newcmptno, jp2_getct(jas_image_clrspc(dec->image), 0, channo + 1)); +				} +#endif +			} +		} +	} + +	/* Mark all components as being of unknown type. */ + +	for (i = 0; i < JAS_CAST(unsigned int, jas_image_numcmpts(dec->image)); ++i) { /* IMLIB - changed unit to unsigned int */ +		jas_image_setcmpttype(dec->image, i, JAS_IMAGE_CT_UNKNOWN); +	} + +	/* Determine the type of each component. */ +	if (dec->cdef) { +		for (i = 0; i < dec->numchans; ++i) { +			jas_image_setcmpttype(dec->image, +			  dec->chantocmptlut[dec->cdef->data.cdef.ents[i].channo], +			  jp2_getct(jas_image_clrspc(dec->image), +			  dec->cdef->data.cdef.ents[i].type, dec->cdef->data.cdef.ents[i].assoc)); +		} +	} else { +		for (i = 0; i < dec->numchans; ++i) { +			jas_image_setcmpttype(dec->image, dec->chantocmptlut[i], +			  jp2_getct(jas_image_clrspc(dec->image), 0, i + 1)); +		} +	} + +  // GeoJasper: dima - let's preserve the actual image data by marking unknown components as gray +	/* Delete any components that are not of interest. */ +  /* +	for (i = jas_image_numcmpts(dec->image); i > 0; --i) { +		if (jas_image_cmpttype(dec->image, i - 1) == JAS_IMAGE_CT_UNKNOWN) { +			jas_image_delcmpt(dec->image, i - 1); +		} +	} +  */ +  // GeoJasper: dima - let's preserve the actual image data by marking unknown components as gray +	for (i = jas_image_numcmpts(dec->image); i > 0; --i) { +		if (jas_image_cmpttype(dec->image, i-1) == JAS_IMAGE_CT_UNKNOWN) { +			jas_image_setcmpttype(dec->image, i-1, JAS_IMAGE_CT_GRAY_Y); +		} +	} + + +	/* Ensure that some components survived. */ +	if (!jas_image_numcmpts(dec->image)) { +		jas_eprintf("error: no components\n"); +		goto error; +	} +#if 0 +jas_eprintf("no of components is %d\n", jas_image_numcmpts(dec->image)); +#endif + +	/* Prevent the image from being destroyed later. */ + +  // GeoJasper: begin - dima - copy buffers to the output image +  for (i=0; i<tmp_metadata.count; ++i) { +    dec->image->metadata.boxes[i] = tmp_metadata.boxes[i]; +    tmp_metadata.boxes[i] = jas_box_init(); +  } +  // GeoJasper: end - dima - copy buffers to the output image + +	image = dec->image; +	dec->image = 0; + +	jp2_dec_destroy(dec); + +	return image; + +error: +	if (box) { +		jp2_box_destroy(box); +	} +	if (dec) { +		jp2_dec_destroy(dec); +	} +	return 0; +} + +int jp2_validate(jas_stream_t *in) +{ +	char buf[JP2_VALIDATELEN]; +	int i; +	int n; +#if 0 +	jas_stream_t *tmpstream; +	jp2_box_t *box; +#endif + +	assert(JAS_STREAM_MAXPUTBACK >= JP2_VALIDATELEN); + +	/* Read the validation data (i.e., the data used for detecting +	  the format). */ +	if ((n = jas_stream_read(in, buf, JP2_VALIDATELEN)) < 0) { +		return -1; +	} + +	/* Put the validation data back onto the stream, so that the +	  stream position will not be changed. */ +	for (i = n - 1; i >= 0; --i) { +		if (jas_stream_ungetc(in, buf[i]) == EOF) { +			return -1; +		} +	} + +	/* Did we read enough data? */ +	if (n < JP2_VALIDATELEN) { +		return -1; +	} + +	/* Is the box type correct? */ +	if (((buf[4] << 24) | (buf[5] << 16) | (buf[6] << 8) | buf[7]) != +	  JP2_BOX_JP) +	{ +		return -1; +	} + +	return 0; +} + +static jp2_dec_t *jp2_dec_create(void) +{ +	jp2_dec_t *dec; + +	if (!(dec = jas_malloc(sizeof(jp2_dec_t)))) { +		return 0; +	} +	dec->ihdr = 0; +	dec->bpcc = 0; +	dec->cdef = 0; +	dec->pclr = 0; +	dec->image = 0; +	dec->chantocmptlut = 0; +	dec->cmap = 0; +	dec->colr = 0; +	return dec; +} + +static void jp2_dec_destroy(jp2_dec_t *dec) +{ +	if (dec->ihdr) { +		jp2_box_destroy(dec->ihdr); +	} +	if (dec->bpcc) { +		jp2_box_destroy(dec->bpcc); +	} +	if (dec->cdef) { +		jp2_box_destroy(dec->cdef); +	} +	if (dec->pclr) { +		jp2_box_destroy(dec->pclr); +	} +	if (dec->image) { +		jas_image_destroy(dec->image); +	} +	if (dec->cmap) { +		jp2_box_destroy(dec->cmap); +	} +	if (dec->colr) { +		jp2_box_destroy(dec->colr); +	} +	if (dec->chantocmptlut) { +		jas_free(dec->chantocmptlut); +	} +	jas_free(dec); +} + +static int jp2_getct(int colorspace, int type, int assoc) +{ +	if (type == 1 && assoc == 0) { +		return JAS_IMAGE_CT_OPACITY; +	} +	if (type == 0 && assoc >= 1 && assoc <= 65534) { +		switch (colorspace) { +		case JAS_CLRSPC_FAM_RGB: +			switch (assoc) { +			case JP2_CDEF_RGB_R: +				return JAS_IMAGE_CT_COLOR(JAS_CLRSPC_CHANIND_RGB_R); +				break; +			case JP2_CDEF_RGB_G: +				return JAS_IMAGE_CT_COLOR(JAS_CLRSPC_CHANIND_RGB_G); +				break; +			case JP2_CDEF_RGB_B: +				return JAS_IMAGE_CT_COLOR(JAS_CLRSPC_CHANIND_RGB_B); +				break; +			} +			break; +		case JAS_CLRSPC_FAM_YCBCR: +			switch (assoc) { +			case JP2_CDEF_YCBCR_Y: +				return JAS_IMAGE_CT_COLOR(JAS_CLRSPC_CHANIND_YCBCR_Y); +				break; +			case JP2_CDEF_YCBCR_CB: +				return JAS_IMAGE_CT_COLOR(JAS_CLRSPC_CHANIND_YCBCR_CB); +				break; +			case JP2_CDEF_YCBCR_CR: +				return JAS_IMAGE_CT_COLOR(JAS_CLRSPC_CHANIND_YCBCR_CR); +				break; +			} +			break; +		case JAS_CLRSPC_FAM_GRAY: +			switch (assoc) { +			case JP2_CDEF_GRAY_Y: +				return JAS_IMAGE_CT_COLOR(JAS_CLRSPC_CHANIND_GRAY_Y); +				break; +			} +			break; +		default: +			return JAS_IMAGE_CT_COLOR(assoc - 1); +			break; +		} +	} +	return JAS_IMAGE_CT_UNKNOWN; +} + +static int jp2_getcs(jp2_colr_t *colr) +{ +	if (colr->method == JP2_COLR_ENUM) { +		switch (colr->csid) { +		case JP2_COLR_SRGB: +			return JAS_CLRSPC_SRGB; +			break; +		case JP2_COLR_SYCC: +			return JAS_CLRSPC_SYCBCR; +			break; +		case JP2_COLR_SGRAY: +			return JAS_CLRSPC_SGRAY; +			break; +		} +	} +	return JAS_CLRSPC_UNKNOWN; +} + +static int fromiccpcs(int cs) +{ +	switch (cs) { +	case ICC_CS_RGB: +		return JAS_CLRSPC_GENRGB; +		break; +	case ICC_CS_YCBCR: +		return JAS_CLRSPC_GENYCBCR; +		break; +	case ICC_CS_GRAY: +		return JAS_CLRSPC_GENGRAY; +		break; +	} +	return JAS_CLRSPC_UNKNOWN; +} diff --git a/src/libjasper/jp2/jp2_dec.h b/src/libjasper/jp2/jp2_dec.h new file mode 100644 index 0000000..1cb95a2 --- /dev/null +++ b/src/libjasper/jp2/jp2_dec.h @@ -0,0 +1,85 @@ +/* + * Copyright (c) 1999-2000 Image Power, Inc. and the University of + *   British Columbia. + * Copyright (c) 2001-2002 Michael David Adams. + * All rights reserved. + */ + +/* __START_OF_JASPER_LICENSE__ + *  + * JasPer License Version 2.0 + *  + * Copyright (c) 2001-2006 Michael David Adams + * Copyright (c) 1999-2000 Image Power, Inc. + * Copyright (c) 1999-2000 The University of British Columbia + *  + * All rights reserved. + *  + * Permission is hereby granted, free of charge, to any person (the + * "User") obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without restriction, + * including without limitation the rights to use, copy, modify, merge, + * publish, distribute, and/or sell copies of the Software, and to permit + * persons to whom the Software is furnished to do so, subject to the + * following conditions: + *  + * 1.  The above copyright notices and this permission notice (which + * includes the disclaimer below) shall be included in all copies or + * substantial portions of the Software. + *  + * 2.  The name of a copyright holder shall not be used to endorse or + * promote products derived from the Software without specific prior + * written permission. + *  + * THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL PART OF THIS + * LICENSE.  NO USE OF THE SOFTWARE IS AUTHORIZED HEREUNDER EXCEPT UNDER + * THIS DISCLAIMER.  THE SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS + * "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING + * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.  IN NO + * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL + * INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING + * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, + * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION + * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.  NO ASSURANCES ARE + * PROVIDED BY THE COPYRIGHT HOLDERS THAT THE SOFTWARE DOES NOT INFRINGE + * THE PATENT OR OTHER INTELLECTUAL PROPERTY RIGHTS OF ANY OTHER ENTITY. + * EACH COPYRIGHT HOLDER DISCLAIMS ANY LIABILITY TO THE USER FOR CLAIMS + * BROUGHT BY ANY OTHER ENTITY BASED ON INFRINGEMENT OF INTELLECTUAL + * PROPERTY RIGHTS OR OTHERWISE.  AS A CONDITION TO EXERCISING THE RIGHTS + * GRANTED HEREUNDER, EACH USER HEREBY ASSUMES SOLE RESPONSIBILITY TO SECURE + * ANY OTHER INTELLECTUAL PROPERTY RIGHTS NEEDED, IF ANY.  THE SOFTWARE + * IS NOT FAULT-TOLERANT AND IS NOT INTENDED FOR USE IN MISSION-CRITICAL + * SYSTEMS, SUCH AS THOSE USED IN THE OPERATION OF NUCLEAR FACILITIES, + * AIRCRAFT NAVIGATION OR COMMUNICATION SYSTEMS, AIR TRAFFIC CONTROL + * SYSTEMS, DIRECT LIFE SUPPORT MACHINES, OR WEAPONS SYSTEMS, IN WHICH + * THE FAILURE OF THE SOFTWARE OR SYSTEM COULD LEAD DIRECTLY TO DEATH, + * PERSONAL INJURY, OR SEVERE PHYSICAL OR ENVIRONMENTAL DAMAGE ("HIGH + * RISK ACTIVITIES").  THE COPYRIGHT HOLDERS SPECIFICALLY DISCLAIM ANY + * EXPRESS OR IMPLIED WARRANTY OF FITNESS FOR HIGH RISK ACTIVITIES. + *  + * __END_OF_JASPER_LICENSE__ + */ + +#ifndef JP2_DEC_H +#define JP2_DEC_H + +#include "jasper/jas_image.h" +#include "jasper/jas_stream.h" +#include "jp2_cod.h" + +typedef struct { + +	jp2_box_t *pclr; +	jp2_box_t *cdef; +	jp2_box_t *ihdr; +	jp2_box_t *bpcc; +	jp2_box_t *cmap; +	jp2_box_t *colr; +	jas_image_t *image; +	uint_fast16_t numchans; +	uint_fast16_t *chantocmptlut; + +} jp2_dec_t; + +#endif diff --git a/src/libjasper/jp2/jp2_enc.c b/src/libjasper/jp2/jp2_enc.c new file mode 100644 index 0000000..cb6299f --- /dev/null +++ b/src/libjasper/jp2/jp2_enc.c @@ -0,0 +1,469 @@ +/* + * Copyright (c) 1999-2000 Image Power, Inc. and the University of + *   British Columbia. + * Copyright (c) 2001-2003 Michael David Adams. + * All rights reserved. + +  GeoJasper revision: Dima (11/07/2003 17:29 - UUID) + */ + +/* __START_OF_JASPER_LICENSE__ + *  + * JasPer License Version 2.0 + *  + * Copyright (c) 2001-2006 Michael David Adams + * Copyright (c) 1999-2000 Image Power, Inc. + * Copyright (c) 1999-2000 The University of British Columbia + *  + * All rights reserved. + *  + * Permission is hereby granted, free of charge, to any person (the + * "User") obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without restriction, + * including without limitation the rights to use, copy, modify, merge, + * publish, distribute, and/or sell copies of the Software, and to permit + * persons to whom the Software is furnished to do so, subject to the + * following conditions: + *  + * 1.  The above copyright notices and this permission notice (which + * includes the disclaimer below) shall be included in all copies or + * substantial portions of the Software. + *  + * 2.  The name of a copyright holder shall not be used to endorse or + * promote products derived from the Software without specific prior + * written permission. + *  + * THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL PART OF THIS + * LICENSE.  NO USE OF THE SOFTWARE IS AUTHORIZED HEREUNDER EXCEPT UNDER + * THIS DISCLAIMER.  THE SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS + * "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING + * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.  IN NO + * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL + * INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING + * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, + * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION + * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.  NO ASSURANCES ARE + * PROVIDED BY THE COPYRIGHT HOLDERS THAT THE SOFTWARE DOES NOT INFRINGE + * THE PATENT OR OTHER INTELLECTUAL PROPERTY RIGHTS OF ANY OTHER ENTITY. + * EACH COPYRIGHT HOLDER DISCLAIMS ANY LIABILITY TO THE USER FOR CLAIMS + * BROUGHT BY ANY OTHER ENTITY BASED ON INFRINGEMENT OF INTELLECTUAL + * PROPERTY RIGHTS OR OTHERWISE.  AS A CONDITION TO EXERCISING THE RIGHTS + * GRANTED HEREUNDER, EACH USER HEREBY ASSUMES SOLE RESPONSIBILITY TO SECURE + * ANY OTHER INTELLECTUAL PROPERTY RIGHTS NEEDED, IF ANY.  THE SOFTWARE + * IS NOT FAULT-TOLERANT AND IS NOT INTENDED FOR USE IN MISSION-CRITICAL + * SYSTEMS, SUCH AS THOSE USED IN THE OPERATION OF NUCLEAR FACILITIES, + * AIRCRAFT NAVIGATION OR COMMUNICATION SYSTEMS, AIR TRAFFIC CONTROL + * SYSTEMS, DIRECT LIFE SUPPORT MACHINES, OR WEAPONS SYSTEMS, IN WHICH + * THE FAILURE OF THE SOFTWARE OR SYSTEM COULD LEAD DIRECTLY TO DEATH, + * PERSONAL INJURY, OR SEVERE PHYSICAL OR ENVIRONMENTAL DAMAGE ("HIGH + * RISK ACTIVITIES").  THE COPYRIGHT HOLDERS SPECIFICALLY DISCLAIM ANY + * EXPRESS OR IMPLIED WARRANTY OF FITNESS FOR HIGH RISK ACTIVITIES. + *  + * __END_OF_JASPER_LICENSE__ + */ + +/* + * JP2 Library + * + * $Id: jp2_enc.c,v 1.1 2008/10/17 06:14:59 scuri Exp $ + */ + +/******************************************************************************\ +* Includes. +\******************************************************************************/ + +#include <assert.h> +#include "jasper/jas_malloc.h" +#include "jasper/jas_image.h" +#include "jasper/jas_stream.h" +#include "jasper/jas_cm.h" +#include "jasper/jas_icc.h" +#include "jp2_cod.h" + +static uint_fast32_t jp2_gettypeasoc(int colorspace, int ctype); +static int clrspctojp2(jas_clrspc_t clrspc); + +/******************************************************************************\ +* Functions. +\******************************************************************************/ + +int jp2_encode(jas_image_t *image, jas_stream_t *out, char *optstr) +{ +	jp2_box_t *box; +	jp2_ftyp_t *ftyp; +	jp2_ihdr_t *ihdr; +	jas_stream_t *tmpstream; +	int allcmptssame; +	jp2_bpcc_t *bpcc; +	long len; +	uint_fast16_t cmptno; +	jp2_colr_t *colr; +	char buf[4096]; +	uint_fast32_t overhead; +	jp2_cdefchan_t *cdefchanent; +	jp2_cdef_t *cdef; +	int i; +	uint_fast32_t typeasoc; +jas_iccprof_t *iccprof; +jas_stream_t *iccstream; +int pos; +int needcdef; +int prec; +int sgnd; + +	box = 0; +	tmpstream = 0; + +	allcmptssame = 1; +	sgnd = jas_image_cmptsgnd(image, 0); +	prec = jas_image_cmptprec(image, 0); +	for (i = 1; i < jas_image_numcmpts(image); ++i) { +		if (jas_image_cmptsgnd(image, i) != sgnd || +		  jas_image_cmptprec(image, i) != prec) { +			allcmptssame = 0; +			break; +		} +	} + +	/* Output the signature box. */ + +	if (!(box = jp2_box_create(JP2_BOX_JP))) { +		goto error; +	} +	box->data.jp.magic = JP2_JP_MAGIC; +	if (jp2_box_put(box, out)) { +		goto error; +	} +	jp2_box_destroy(box); +	box = 0; + +	/* Output the file type box. */ + +	if (!(box = jp2_box_create(JP2_BOX_FTYP))) { +		goto error; +	} +	ftyp = &box->data.ftyp; +	ftyp->majver = JP2_FTYP_MAJVER; +	ftyp->minver = JP2_FTYP_MINVER; +	ftyp->numcompatcodes = 1; +	ftyp->compatcodes[0] = JP2_FTYP_COMPATCODE; +	if (jp2_box_put(box, out)) { +		goto error; +	} +	jp2_box_destroy(box); +	box = 0; + +	/* +	 * Generate the data portion of the JP2 header box. +	 * We cannot simply output the header for this box +	 * since we do not yet know the correct value for the length +	 * field. +	 */ + +	if (!(tmpstream = jas_stream_memopen(0, 0))) { +		goto error; +	} + +	/* Generate image header box. */ + +	if (!(box = jp2_box_create(JP2_BOX_IHDR))) { +		goto error; +	} +	ihdr = &box->data.ihdr; +	ihdr->width = jas_image_width(image); +	ihdr->height = jas_image_height(image); +	ihdr->numcmpts = jas_image_numcmpts(image); +	ihdr->bpc = allcmptssame ? JP2_SPTOBPC(jas_image_cmptsgnd(image, 0), +	  jas_image_cmptprec(image, 0)) : JP2_IHDR_BPCNULL; +	ihdr->comptype = JP2_IHDR_COMPTYPE; +	ihdr->csunk = 0; +	ihdr->ipr = 0; +	if (jp2_box_put(box, tmpstream)) { +		goto error; +	} +	jp2_box_destroy(box); +	box = 0; + +	/* Generate bits per component box. */ + +	if (!allcmptssame) { +		if (!(box = jp2_box_create(JP2_BOX_BPCC))) { +			goto error; +		} +		bpcc = &box->data.bpcc; +		bpcc->numcmpts = jas_image_numcmpts(image); +		if (!(bpcc->bpcs = jas_malloc(bpcc->numcmpts * +		  sizeof(uint_fast8_t)))) { +			goto error; +		} +		for (cmptno = 0; cmptno < bpcc->numcmpts; ++cmptno) { +			bpcc->bpcs[cmptno] = JP2_SPTOBPC(jas_image_cmptsgnd(image, +			  cmptno), jas_image_cmptprec(image, cmptno)); +		} +		if (jp2_box_put(box, tmpstream)) { +			goto error; +		} +		jp2_box_destroy(box); +		box = 0; +	} + +	/* Generate color specification box. */ + +	if (!(box = jp2_box_create(JP2_BOX_COLR))) { +		goto error; +	} +	colr = &box->data.colr; +	switch (jas_image_clrspc(image)) { +	case JAS_CLRSPC_SRGB: +	case JAS_CLRSPC_SYCBCR: +	case JAS_CLRSPC_SGRAY: +		colr->method = JP2_COLR_ENUM; +		colr->csid = clrspctojp2(jas_image_clrspc(image)); +		colr->pri = JP2_COLR_PRI; +		colr->approx = 0; +		break; +	default: +		colr->method = JP2_COLR_ICC; +		colr->pri = JP2_COLR_PRI; +		colr->approx = 0; +		iccprof = jas_iccprof_createfromcmprof(jas_image_cmprof(image)); +		assert(iccprof); +		iccstream = jas_stream_memopen(0, 0); +		assert(iccstream); +		if (jas_iccprof_save(iccprof, iccstream)) +			abort(); +		if ((pos = jas_stream_tell(iccstream)) < 0) +			abort(); +		colr->iccplen = pos; +		colr->iccp = jas_malloc(pos); +		assert(colr->iccp); +		jas_stream_rewind(iccstream); +		if (jas_stream_read(iccstream, colr->iccp, colr->iccplen) != colr->iccplen) +			abort(); +		jas_stream_close(iccstream); +		jas_iccprof_destroy(iccprof); +		break; +	} +	if (jp2_box_put(box, tmpstream)) { +		goto error; +	} +	jp2_box_destroy(box); +	box = 0; + +	needcdef = 1; +	switch (jas_clrspc_fam(jas_image_clrspc(image))) { +	case JAS_CLRSPC_FAM_RGB: +		if (jas_image_cmpttype(image, 0) == +		  JAS_IMAGE_CT_COLOR(JAS_CLRSPC_CHANIND_RGB_R) && +		  jas_image_cmpttype(image, 1) == +		  JAS_IMAGE_CT_COLOR(JAS_CLRSPC_CHANIND_RGB_G) && +		  jas_image_cmpttype(image, 2) == +		  JAS_IMAGE_CT_COLOR(JAS_CLRSPC_CHANIND_RGB_B)) +			needcdef = 0; +		break; +	case JAS_CLRSPC_FAM_YCBCR: +		if (jas_image_cmpttype(image, 0) == +		  JAS_IMAGE_CT_COLOR(JAS_CLRSPC_CHANIND_YCBCR_Y) && +		  jas_image_cmpttype(image, 1) == +		  JAS_IMAGE_CT_COLOR(JAS_CLRSPC_CHANIND_YCBCR_CB) && +		  jas_image_cmpttype(image, 2) == +		  JAS_IMAGE_CT_COLOR(JAS_CLRSPC_CHANIND_YCBCR_CR)) +			needcdef = 0; +		break; +	case JAS_CLRSPC_FAM_GRAY: +		if (jas_image_cmpttype(image, 0) == +		  JAS_IMAGE_CT_COLOR(JAS_IMAGE_CT_GRAY_Y)) +			needcdef = 0; +		break; +	default: +		abort(); +		break; +	} + +	if (needcdef) { +		if (!(box = jp2_box_create(JP2_BOX_CDEF))) { +			goto error; +		} +		cdef = &box->data.cdef; +		cdef->numchans = jas_image_numcmpts(image); +		cdef->ents = jas_malloc(cdef->numchans * sizeof(jp2_cdefchan_t)); +		for (i = 0; i < jas_image_numcmpts(image); ++i) { +			cdefchanent = &cdef->ents[i]; +			cdefchanent->channo = i; +			typeasoc = jp2_gettypeasoc(jas_image_clrspc(image), jas_image_cmpttype(image, i)); +			cdefchanent->type = typeasoc >> 16; +			cdefchanent->assoc = typeasoc & 0x7fff; +		} +		if (jp2_box_put(box, tmpstream)) { +			goto error; +		} +		jp2_box_destroy(box); +		box = 0; +	} + +	/* Determine the total length of the JP2 header box. */ + +	len = jas_stream_tell(tmpstream); +	jas_stream_rewind(tmpstream); + +	/* +	 * Output the JP2 header box and all of the boxes which it contains. +	 */ + +	if (!(box = jp2_box_create(JP2_BOX_JP2H))) { +		goto error; +	} +	box->len = len + JP2_BOX_HDRLEN(false); +	if (jp2_box_put(box, out)) { +		goto error; +	} +	jp2_box_destroy(box); +	box = 0; + +	if (jas_stream_copy(out, tmpstream, len)) { +		goto error; +	} + +	jas_stream_close(tmpstream); +	tmpstream = 0; + +	/* +	 * Output the UUID box +	*/ +  // GeoJasper: dima - write UUID if received any metadata +  if ( image->metadata.count > 0 ) { +    int b; +    for (b=0; b<image->metadata.count; ++b) { +      jas_metadata_box_t *metabox = &image->metadata.boxes[b];  + +      if ( metabox->size>0 && metabox->buf ) { +        if (!(box = jp2_box_create( JP2_BOX_UUID ))) +	  	    goto error; + +        memcpy( box->data.uuid.uuid, metabox->id, sizeof(msi_uuid) ); +        box->data.uuid.data_len = metabox->size; +        if ( !(box->data.uuid.data = (uint_fast8_t *)jas_malloc(metabox->size)) ) +          goto error; +        memcpy( box->data.uuid.data, metabox->buf, metabox->size ); +       +        if (jp2_box_put(box, out)) +			      goto error; + +	      jp2_box_destroy(box); +	      box = 0; +	    } // if box contains data +    } // for boxes +  } // if there are boxes +  // GeoJasper: dima - write UUID if received + + + +	/* +	 * Output the contiguous code stream box. +	 */ + +	if (!(box = jp2_box_create(JP2_BOX_JP2C))) { +		goto error; +	} +	box->len = 0; +	if (jp2_box_put(box, out)) { +		goto error; +	} +	jp2_box_destroy(box); +	box = 0; + +	/* Output the JPEG-2000 code stream. */ + +	overhead = jas_stream_getrwcount(out); +	sprintf(buf, "%s\n_jp2overhead=%lu\n", (optstr ? optstr : ""), +	  (unsigned long) overhead); + +	if (jpc_encode(image, out, buf)) { +		goto error; +	} + +	return 0; +	abort(); + +error: + +	if (box) { +		jp2_box_destroy(box); +	} +	if (tmpstream) { +		jas_stream_close(tmpstream); +	} +	return -1; +} + +static uint_fast32_t jp2_gettypeasoc(int colorspace, int ctype) +{ +	int type; +	int asoc; + +	if (ctype & JAS_IMAGE_CT_OPACITY) { +		type = JP2_CDEF_TYPE_OPACITY; +		asoc = JP2_CDEF_ASOC_ALL; +		goto done; +	} + +	type = JP2_CDEF_TYPE_UNSPEC; +	asoc = JP2_CDEF_ASOC_NONE; +	switch (jas_clrspc_fam(colorspace)) { +	case JAS_CLRSPC_FAM_RGB: +		switch (JAS_IMAGE_CT_COLOR(ctype)) { +		case JAS_IMAGE_CT_RGB_R: +			type = JP2_CDEF_TYPE_COLOR; +			asoc = JP2_CDEF_RGB_R; +			break; +		case JAS_IMAGE_CT_RGB_G: +			type = JP2_CDEF_TYPE_COLOR; +			asoc = JP2_CDEF_RGB_G; +			break; +		case JAS_IMAGE_CT_RGB_B: +			type = JP2_CDEF_TYPE_COLOR; +			asoc = JP2_CDEF_RGB_B; +			break; +		} +		break; +	case JAS_CLRSPC_FAM_YCBCR: +		switch (JAS_IMAGE_CT_COLOR(ctype)) { +		case JAS_IMAGE_CT_YCBCR_Y: +			type = JP2_CDEF_TYPE_COLOR; +			asoc = JP2_CDEF_YCBCR_Y; +			break; +		case JAS_IMAGE_CT_YCBCR_CB: +			type = JP2_CDEF_TYPE_COLOR; +			asoc = JP2_CDEF_YCBCR_CB; +			break; +		case JAS_IMAGE_CT_YCBCR_CR: +			type = JP2_CDEF_TYPE_COLOR; +			asoc = JP2_CDEF_YCBCR_CR; +			break; +		} +		break; +	case JAS_CLRSPC_FAM_GRAY: +		type = JP2_CDEF_TYPE_COLOR; +		asoc = JP2_CDEF_GRAY_Y; +		break; +	} + +done: +	return (type << 16) | asoc; +} + +static int clrspctojp2(jas_clrspc_t clrspc) +{ +	switch (clrspc) { +	case JAS_CLRSPC_SRGB: +		return JP2_COLR_SRGB; +	case JAS_CLRSPC_SYCBCR: +		return JP2_COLR_SYCC; +	case JAS_CLRSPC_SGRAY: +		return JP2_COLR_SGRAY; +	default: +		abort(); +		break; +	} +} | 
