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/base | |
First commit - moving from LuaForge to SourceForge
Diffstat (limited to 'src/libjasper/base')
| -rw-r--r-- | src/libjasper/base/jas_cm.c | 1282 | ||||
| -rw-r--r-- | src/libjasper/base/jas_debug.c | 137 | ||||
| -rw-r--r-- | src/libjasper/base/jas_getopt.c | 168 | ||||
| -rw-r--r-- | src/libjasper/base/jas_icc.c | 1722 | ||||
| -rw-r--r-- | src/libjasper/base/jas_iccdata.c | 517 | ||||
| -rw-r--r-- | src/libjasper/base/jas_image.c | 1516 | ||||
| -rw-r--r-- | src/libjasper/base/jas_init.c | 170 | ||||
| -rw-r--r-- | src/libjasper/base/jas_malloc.c | 131 | ||||
| -rw-r--r-- | src/libjasper/base/jas_seq.c | 454 | ||||
| -rw-r--r-- | src/libjasper/base/jas_stream.c | 1151 | ||||
| -rw-r--r-- | src/libjasper/base/jas_string.c | 96 | ||||
| -rw-r--r-- | src/libjasper/base/jas_tmr.c | 149 | ||||
| -rw-r--r-- | src/libjasper/base/jas_tvp.c | 237 | ||||
| -rw-r--r-- | src/libjasper/base/jas_version.c | 67 | 
14 files changed, 7797 insertions, 0 deletions
diff --git a/src/libjasper/base/jas_cm.c b/src/libjasper/base/jas_cm.c new file mode 100644 index 0000000..efeec99 --- /dev/null +++ b/src/libjasper/base/jas_cm.c @@ -0,0 +1,1282 @@ +/* + * Copyright (c) 2002-2003 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__ + */ + +/* + * Color Management + * + * $Id: jas_cm.c,v 1.1 2008/10/17 06:14:59 scuri Exp $ + */ + +#include <jasper/jas_config.h> +#include <math.h> +#include <stdlib.h> +#include <assert.h> +#include <jasper/jas_cm.h> +#include <jasper/jas_icc.h> +#include <jasper/jas_init.h> +#include <jasper/jas_stream.h> +#include <jasper/jas_malloc.h> +#include <jasper/jas_math.h> + +static jas_cmprof_t *jas_cmprof_create(void); +static void jas_cmshapmatlut_cleanup(jas_cmshapmatlut_t *); +static jas_cmreal_t jas_cmshapmatlut_lookup(jas_cmshapmatlut_t *lut, jas_cmreal_t x); + +static void jas_cmpxform_destroy(jas_cmpxform_t *pxform); +static jas_cmpxform_t *jas_cmpxform_copy(jas_cmpxform_t *pxform); + +static void jas_cmshapmat_destroy(jas_cmpxform_t *pxform); +static int jas_cmshapmat_apply(jas_cmpxform_t *pxform, jas_cmreal_t *in, +  jas_cmreal_t *out, int cnt); + +static int jas_cmputint(long **bufptr, int sgnd, int prec, long val); +static int jas_cmgetint(long **bufptr, int sgnd, int prec, long *val); +static int jas_cmpxformseq_append(jas_cmpxformseq_t *pxformseq, +  jas_cmpxformseq_t *othpxformseq); +static int jas_cmpxformseq_appendcnvt(jas_cmpxformseq_t *pxformseq, +  int, int); +static int jas_cmpxformseq_resize(jas_cmpxformseq_t *pxformseq, int n); + +static int mono(jas_iccprof_t *prof, int op, jas_cmpxformseq_t **pxformseq); +static int triclr(jas_iccprof_t *prof, int op, jas_cmpxformseq_t **retpxformseq); + +static void jas_cmpxformseq_destroy(jas_cmpxformseq_t *pxformseq); +static int jas_cmpxformseq_delete(jas_cmpxformseq_t *pxformseq, int i); +static jas_cmpxformseq_t *jas_cmpxformseq_create(void); +static jas_cmpxformseq_t *jas_cmpxformseq_copy(jas_cmpxformseq_t *pxformseq); +static int jas_cmshapmat_invmat(jas_cmreal_t out[3][4], jas_cmreal_t in[3][4]); +static int jas_cmpxformseq_insertpxform(jas_cmpxformseq_t *pxformseq, +  int i, jas_cmpxform_t *pxform); + +#define	SEQFWD(intent)	(intent) +#define	SEQREV(intent)	(4 + (intent)) +#define	SEQSIM(intent)	(8 + (intent)) +#define	SEQGAM		12 + +#define fwdpxformseq(prof, intent) \ +  (((prof)->pxformseqs[SEQFWD(intent)]) ? \ +  ((prof)->pxformseqs[SEQFWD(intent)]) : \ +  ((prof)->pxformseqs[SEQFWD(0)])) + +#define revpxformseq(prof, intent) \ +  (((prof)->pxformseqs[SEQREV(intent)]) ? \ +  ((prof)->pxformseqs[SEQREV(intent)]) : \ +  ((prof)->pxformseqs[SEQREV(0)])) + +#define simpxformseq(prof, intent) \ +  (((prof)->pxformseqs[SEQSIM(intent)]) ? \ +  ((prof)->pxformseqs[SEQSIM(intent)]) : \ +  ((prof)->pxformseqs[SEQSIM(0)])) + +#define gampxformseq(prof)	((prof)->pxformseqs[SEQGAM]) + +static int icctoclrspc(int iccclrspc, int refflag); +static jas_cmpxform_t *jas_cmpxform_create0(void); +static jas_cmpxform_t *jas_cmpxform_createshapmat(void); +static void jas_cmshapmatlut_init(jas_cmshapmatlut_t *lut); +static int jas_cmshapmatlut_set(jas_cmshapmatlut_t *lut, jas_icccurv_t *curv); + +static jas_cmpxformops_t shapmat_ops = {jas_cmshapmat_destroy, jas_cmshapmat_apply, 0}; +static jas_cmprof_t *jas_cmprof_createsycc(void); + +/******************************************************************************\ +* Color profile class. +\******************************************************************************/ + +jas_cmprof_t *jas_cmprof_createfromclrspc(int clrspc) +{ +	jas_iccprof_t *iccprof; +	jas_cmprof_t *prof; + +	iccprof = 0; +	prof = 0; +	switch (clrspc) { +	case JAS_CLRSPC_SYCBCR: +		if (!(prof = jas_cmprof_createsycc())) +			goto error; +		break; +	default: +		if (!(iccprof = jas_iccprof_createfromclrspc(clrspc))) +			goto error; +		if (!(prof = jas_cmprof_createfromiccprof(iccprof))) +			goto error; +		jas_iccprof_destroy(iccprof); +		iccprof = 0; +		if (!jas_clrspc_isgeneric(clrspc)) +			prof->clrspc = clrspc; +		break; +	} +	return prof; +error: +	if (iccprof) +		jas_iccprof_destroy(iccprof); +	return 0; +} + +static jas_cmprof_t *jas_cmprof_createsycc() +{ +	jas_cmprof_t *prof; +	jas_cmpxform_t *fwdpxform; +	jas_cmpxform_t *revpxform; +	jas_cmshapmat_t *fwdshapmat; +	jas_cmshapmat_t *revshapmat; +	int i; +	int j; + +	if (!(prof = jas_cmprof_createfromclrspc(JAS_CLRSPC_SRGB))) +		goto error; +	prof->clrspc = JAS_CLRSPC_SYCBCR; +	assert(prof->numchans == 3 && prof->numrefchans == 3); +	assert(prof->refclrspc == JAS_CLRSPC_CIEXYZ); +	if (!(fwdpxform = jas_cmpxform_createshapmat())) +		goto error; +	fwdpxform->numinchans = 3; +	fwdpxform->numoutchans = 3; +	fwdshapmat = &fwdpxform->data.shapmat; +	fwdshapmat->mono = 0; +	fwdshapmat->order = 0; +	fwdshapmat->useluts = 0; +	fwdshapmat->usemat = 1; +	fwdshapmat->mat[0][0] = 1.0; +	fwdshapmat->mat[0][1] = 0.0; +	fwdshapmat->mat[0][2] = 1.402; +	fwdshapmat->mat[1][0] = 1.0; +	fwdshapmat->mat[1][1] = -0.34413; +	fwdshapmat->mat[1][2] = -0.71414; +	fwdshapmat->mat[2][0] = 1.0; +	fwdshapmat->mat[2][1] = 1.772; +	fwdshapmat->mat[2][2] = 0.0; +	fwdshapmat->mat[0][3] = -0.5 * (1.402); +	fwdshapmat->mat[1][3] = -0.5 * (-0.34413 - 0.71414); +	fwdshapmat->mat[2][3] = -0.5 * (1.772); +	if (!(revpxform = jas_cmpxform_createshapmat())) +		goto error; +	revpxform->numinchans = 3; +	revpxform->numoutchans = 3; +	revshapmat = &revpxform->data.shapmat; +	revshapmat->mono = 0; +	revshapmat->order = 1; +	revshapmat->useluts = 0; +	revshapmat->usemat = 1; +	jas_cmshapmat_invmat(revshapmat->mat, fwdshapmat->mat); + +	for (i = 0; i < JAS_CMXFORM_NUMINTENTS; ++i) { +		j = SEQFWD(i); +		if (prof->pxformseqs[j]) { +			if (jas_cmpxformseq_insertpxform(prof->pxformseqs[j], 0, +			  fwdpxform)) +				goto error; +		} +		j = SEQREV(i); +		if (prof->pxformseqs[j]) { +			if (jas_cmpxformseq_insertpxform(prof->pxformseqs[j], +			  -1, revpxform)) +				goto error; +		} +	} + +	jas_cmpxform_destroy(fwdpxform); +	jas_cmpxform_destroy(revpxform); +	return prof; +error: +	return 0; +} + +jas_cmprof_t *jas_cmprof_createfromiccprof(jas_iccprof_t *iccprof) +{ +	jas_cmprof_t *prof; +	jas_icchdr_t icchdr; +	jas_cmpxformseq_t *fwdpxformseq; +	jas_cmpxformseq_t *revpxformseq; + +	prof = 0; +	fwdpxformseq = 0; +	revpxformseq = 0; + +	if (!(prof = jas_cmprof_create())) +		goto error; +	jas_iccprof_gethdr(iccprof, &icchdr); +	if (!(prof->iccprof = jas_iccprof_copy(iccprof))) +		goto error; +	prof->clrspc = icctoclrspc(icchdr.colorspc, 0); +	prof->refclrspc = icctoclrspc(icchdr.refcolorspc, 1); +	prof->numchans = jas_clrspc_numchans(prof->clrspc); +	prof->numrefchans = jas_clrspc_numchans(prof->refclrspc); + +	if (prof->numchans == 1) { +		if (mono(prof->iccprof, 0, &fwdpxformseq)) +			goto error; +		if (mono(prof->iccprof, 1, &revpxformseq)) +			goto error; +	} else if (prof->numchans == 3) { +		if (triclr(prof->iccprof, 0, &fwdpxformseq)) +			goto error; +		if (triclr(prof->iccprof, 1, &revpxformseq)) +			goto error; +	} +	prof->pxformseqs[SEQFWD(0)] = fwdpxformseq; +	prof->pxformseqs[SEQREV(0)] = revpxformseq; + +#if 0 +	if (prof->numchans > 1) { +		lut(prof->iccprof, 0, PER, &pxformseq); +		pxformseqs_set(prof, SEQFWD(PER), pxformseq); +		lut(prof->iccprof, 1, PER, &pxformseq); +		pxformseqs_set(prof, SEQREV(PER), pxformseq); +		lut(prof->iccprof, 0, CLR, &pxformseq); +		pxformseqs_set(prof, SEQREV(CLR), pxformseq); +		lut(prof->iccprof, 1, CLR, &pxformseq); +		pxformseqs_set(prof, SEQREV(CLR), pxformseq); +		lut(prof->iccprof, 0, SAT, &pxformseq); +		pxformseqs_set(prof, SEQREV(SAT), pxformseq); +		lut(prof->iccprof, 1, SAT, &pxformseq); +		pxformseqs_set(prof, SEQREV(SAT), pxformseq); +	} +#endif + +	return prof; + +error: +	if (fwdpxformseq) { +		jas_cmpxformseq_destroy(fwdpxformseq); +	} +	if (revpxformseq) { +		jas_cmpxformseq_destroy(revpxformseq); +	} +	if (prof) { +		jas_cmprof_destroy(prof); +	} + +	return 0; +} + +static jas_cmprof_t *jas_cmprof_create() +{ +	int i; +	jas_cmprof_t *prof; +	if (!(prof = jas_malloc(sizeof(jas_cmprof_t)))) +		return 0; +	memset(prof, 0, sizeof(jas_cmprof_t)); +	prof->iccprof = 0; +	for (i = 0; i < JAS_CMPROF_NUMPXFORMSEQS; ++i) +		prof->pxformseqs[i] = 0; +	return prof; +} + +void jas_cmprof_destroy(jas_cmprof_t *prof) +{  +	int i; +	for (i = 0; i < JAS_CMPROF_NUMPXFORMSEQS; ++i) { +		if (prof->pxformseqs[i]) { +			jas_cmpxformseq_destroy(prof->pxformseqs[i]); +			prof->pxformseqs[i] = 0; +		} +	} +	if (prof->iccprof) +		jas_iccprof_destroy(prof->iccprof); +	jas_free(prof); +} + +jas_cmprof_t *jas_cmprof_copy(jas_cmprof_t *prof) +{ +	jas_cmprof_t *newprof; +	int i; + +	if (!(newprof = jas_cmprof_create())) +		goto error; +	newprof->clrspc = prof->clrspc; +	newprof->numchans = prof->numchans; +	newprof->refclrspc = prof->refclrspc; +	newprof->numrefchans = prof->numrefchans; +	newprof->iccprof = jas_iccprof_copy(prof->iccprof); +	for (i = 0; i < JAS_CMPROF_NUMPXFORMSEQS; ++i) { +		if (prof->pxformseqs[i]) { +			if (!(newprof->pxformseqs[i] = jas_cmpxformseq_copy(prof->pxformseqs[i]))) +				goto error; +		} +	} +	return newprof; +error: +	return 0; +} + +/******************************************************************************\ +* Transform class. +\******************************************************************************/ + +jas_cmxform_t *jas_cmxform_create(jas_cmprof_t *inprof, jas_cmprof_t *outprof, +  jas_cmprof_t *prfprof, int op, int intent, int optimize) +{ +	jas_cmxform_t *xform; +	jas_cmpxformseq_t *inpxformseq; +	jas_cmpxformseq_t *outpxformseq; +	jas_cmpxformseq_t *altoutpxformseq; +	jas_cmpxformseq_t *prfpxformseq; +	int prfintent; + +	/* Avoid compiler warnings about unused parameters. */ +	optimize = 0; + +	prfintent = intent; + +	if (!(xform = jas_malloc(sizeof(jas_cmxform_t)))) +		goto error; +	if (!(xform->pxformseq = jas_cmpxformseq_create())) +		goto error; + +	switch (op) { +	case JAS_CMXFORM_OP_FWD: +		inpxformseq = fwdpxformseq(inprof, intent); +		outpxformseq = revpxformseq(outprof, intent); +		if (!inpxformseq || !outpxformseq) +			goto error; +		if (jas_cmpxformseq_append(xform->pxformseq, inpxformseq) || +		  jas_cmpxformseq_appendcnvt(xform->pxformseq, +		  inprof->refclrspc, outprof->refclrspc) || +		  jas_cmpxformseq_append(xform->pxformseq, outpxformseq)) +			goto error; +		xform->numinchans = jas_clrspc_numchans(inprof->clrspc); +		xform->numoutchans = jas_clrspc_numchans(outprof->clrspc); +		break; +	case JAS_CMXFORM_OP_REV: +		outpxformseq = fwdpxformseq(outprof, intent); +		inpxformseq = revpxformseq(inprof, intent); +		if (!outpxformseq || !inpxformseq) +			goto error; +		if (jas_cmpxformseq_append(xform->pxformseq, outpxformseq) || +		  jas_cmpxformseq_appendcnvt(xform->pxformseq, +		  outprof->refclrspc, inprof->refclrspc) || +		  jas_cmpxformseq_append(xform->pxformseq, inpxformseq)) +			goto error; +		xform->numinchans = jas_clrspc_numchans(outprof->clrspc); +		xform->numoutchans = jas_clrspc_numchans(inprof->clrspc); +		break; +	case JAS_CMXFORM_OP_PROOF: +		assert(prfprof); +		inpxformseq = fwdpxformseq(inprof, intent); +		prfpxformseq = fwdpxformseq(prfprof, prfintent); +		if (!inpxformseq || !prfpxformseq) +			goto error; +		outpxformseq = simpxformseq(outprof, intent); +		altoutpxformseq = 0; +		if (!outpxformseq) { +			outpxformseq = revpxformseq(outprof, intent); +			altoutpxformseq = fwdpxformseq(outprof, intent); +			if (!outpxformseq || !altoutpxformseq) +				goto error; +		} +		if (jas_cmpxformseq_append(xform->pxformseq, inpxformseq) || +		  jas_cmpxformseq_appendcnvt(xform->pxformseq, +		  inprof->refclrspc, outprof->refclrspc)) +			goto error; +		if (altoutpxformseq) { +			if (jas_cmpxformseq_append(xform->pxformseq, outpxformseq) || +			  jas_cmpxformseq_append(xform->pxformseq, altoutpxformseq)) +				goto error; +		} else { +			if (jas_cmpxformseq_append(xform->pxformseq, outpxformseq)) +				goto error; +		} +		if (jas_cmpxformseq_appendcnvt(xform->pxformseq, +		  outprof->refclrspc, inprof->refclrspc) || +		  jas_cmpxformseq_append(xform->pxformseq, prfpxformseq)) +			goto error; +		xform->numinchans = jas_clrspc_numchans(inprof->clrspc); +		xform->numoutchans = jas_clrspc_numchans(prfprof->clrspc); +		break; +	case JAS_CMXFORM_OP_GAMUT: +		inpxformseq = fwdpxformseq(inprof, intent); +		outpxformseq = gampxformseq(outprof); +		if (!inpxformseq || !outpxformseq) +			goto error; +		if (jas_cmpxformseq_append(xform->pxformseq, inpxformseq) || +		  jas_cmpxformseq_appendcnvt(xform->pxformseq, +		  inprof->refclrspc, outprof->refclrspc) || +		  jas_cmpxformseq_append(xform->pxformseq, outpxformseq)) +			goto error; +		xform->numinchans = jas_clrspc_numchans(inprof->clrspc); +		xform->numoutchans = 1; +		break; +	} +	return xform; +error: +	return 0; +} + +#define	APPLYBUFSIZ	2048 +int jas_cmxform_apply(jas_cmxform_t *xform, jas_cmpixmap_t *in, jas_cmpixmap_t *out) +{ +	jas_cmcmptfmt_t *fmt; +	jas_cmreal_t buf[2][APPLYBUFSIZ]; +	jas_cmpxformseq_t *pxformseq; +	int i; +	int j; +	int width; +	int height; +	int total; +	int n; +	jas_cmreal_t *inbuf; +	jas_cmreal_t *outbuf; +	jas_cmpxform_t *pxform; +	long *dataptr; +	int maxchans; +	int bufmax; +	int m; +	int bias; +	jas_cmreal_t scale; +	long v; +	jas_cmreal_t *bufptr; + +	if (xform->numinchans > in->numcmpts || xform->numoutchans > out->numcmpts) +		goto error; + +	fmt = &in->cmptfmts[0]; +	width = fmt->width; +	height = fmt->height; +	for (i = 1; i < xform->numinchans; ++i) { +		fmt = &in->cmptfmts[i]; +		if (fmt->width != width || fmt->height != height) { +			goto error; +		} +	} +	for (i = 0; i < xform->numoutchans; ++i) { +		fmt = &out->cmptfmts[i]; +		if (fmt->width != width || fmt->height != height) { +			goto error; +		} +	} + +	maxchans = 0; +	pxformseq = xform->pxformseq; +	for (i = 0; i < pxformseq->numpxforms; ++i) { +		pxform = pxformseq->pxforms[i]; +		if (pxform->numinchans > maxchans) { +			maxchans = pxform->numinchans; +		} +		if (pxform->numoutchans > maxchans) { +			maxchans = pxform->numoutchans; +		} +	} +	bufmax = APPLYBUFSIZ / maxchans; +	assert(bufmax > 0); + +	total = width * height; +	n = 0; +	while (n < total) { + +		inbuf = &buf[0][0]; +		m = JAS_MIN(total - n, bufmax); + +		for (i = 0; i < xform->numinchans; ++i) { +			fmt = &in->cmptfmts[i]; +			scale = (double)((1 << fmt->prec) - 1); +			bias = fmt->sgnd ? (1 << (fmt->prec - 1)) : 0; +			dataptr = &fmt->buf[n]; +			bufptr = &inbuf[i]; +			for (j = 0; j < m; ++j) { +				if (jas_cmgetint(&dataptr, fmt->sgnd, fmt->prec, &v)) +					goto error; +				*bufptr = (v - bias) / scale; +				bufptr += xform->numinchans; +			} +		} + +		inbuf = &buf[0][0]; +		outbuf = inbuf; +		for (i = 0; i < pxformseq->numpxforms; ++i) { +			pxform = pxformseq->pxforms[i]; +			if (pxform->numoutchans > pxform->numinchans) { +				outbuf = (inbuf == &buf[0][0]) ? &buf[1][0] : &buf[0][0]; +			} else { +				outbuf = inbuf; +			} +			if ((*pxform->ops->apply)(pxform, inbuf, outbuf, m)) +				goto error; +			inbuf = outbuf; +		} + +		for (i = 0; i < xform->numoutchans; ++i) { +			fmt = &out->cmptfmts[i]; +			scale = (double)((1 << fmt->prec) - 1); +			bias = fmt->sgnd ? (1 << (fmt->prec - 1)) : 0; +			bufptr = &outbuf[i]; +			dataptr = &fmt->buf[n]; +			for (j = 0; j < m; ++j) { +				v = (*bufptr) * scale + bias; +				bufptr += xform->numoutchans; +				if (jas_cmputint(&dataptr, fmt->sgnd, fmt->prec, v)) +					goto error; +			} +		} +	 +		n += m; +	} +	 +	return 0; +error: +	return -1; +} + +void jas_cmxform_destroy(jas_cmxform_t *xform) +{ +	if (xform->pxformseq) +		jas_cmpxformseq_destroy(xform->pxformseq); +	jas_free(xform); +} + +/******************************************************************************\ +* Primitive transform sequence class. +\******************************************************************************/ + +static jas_cmpxformseq_t *jas_cmpxformseq_create() +{ +	jas_cmpxformseq_t *pxformseq; +	pxformseq = 0; +	if (!(pxformseq = jas_malloc(sizeof(jas_cmpxformseq_t)))) +		goto error; +	pxformseq->pxforms = 0; +	pxformseq->numpxforms = 0; +	pxformseq->maxpxforms = 0; +	if (jas_cmpxformseq_resize(pxformseq, 16)) +		goto error; +	return pxformseq; +error: +	if (pxformseq) +		jas_cmpxformseq_destroy(pxformseq); +	return 0; +} + +static jas_cmpxformseq_t *jas_cmpxformseq_copy(jas_cmpxformseq_t *pxformseq) +{ +	jas_cmpxformseq_t *newpxformseq; + +	if (!(newpxformseq = jas_cmpxformseq_create())) +		goto error; +	if (jas_cmpxformseq_append(newpxformseq, pxformseq)) +		goto error; +	return newpxformseq; +error: +	return 0; +} + +static void jas_cmpxformseq_destroy(jas_cmpxformseq_t *pxformseq) +{ +	while (pxformseq->numpxforms > 0) +		jas_cmpxformseq_delete(pxformseq, pxformseq->numpxforms - 1); +	if (pxformseq->pxforms) +		jas_free(pxformseq->pxforms); +	jas_free(pxformseq); +} + +static int jas_cmpxformseq_delete(jas_cmpxformseq_t *pxformseq, int i) +{ +	assert(i >= 0 && i < pxformseq->numpxforms); +	if (i != pxformseq->numpxforms - 1) +		abort(); +	jas_cmpxform_destroy(pxformseq->pxforms[i]); +	pxformseq->pxforms[i] = 0; +	--pxformseq->numpxforms; +	return 0; +} + +static int jas_cmpxformseq_appendcnvt(jas_cmpxformseq_t *pxformseq, +  int dstclrspc, int srcclrspc) +{ +	if (dstclrspc == srcclrspc) +		return 0; +	abort(); +	/* Avoid compiler warnings about unused parameters. */ +	pxformseq = 0; +	return -1; +} + +static int jas_cmpxformseq_insertpxform(jas_cmpxformseq_t *pxformseq, +  int i, jas_cmpxform_t *pxform) +{ +	jas_cmpxform_t *tmppxform; +	int n; +	if (i < 0) +		i = pxformseq->numpxforms; +	assert(i >= 0 && i <= pxformseq->numpxforms); +	if (pxformseq->numpxforms >= pxformseq->maxpxforms) { +		if (jas_cmpxformseq_resize(pxformseq, pxformseq->numpxforms + +		  16)) +			goto error; +	} +	assert(pxformseq->numpxforms < pxformseq->maxpxforms); +	if (!(tmppxform = jas_cmpxform_copy(pxform))) +		goto error; +	n = pxformseq->numpxforms - i; +	if (n > 0) { +		memmove(&pxformseq->pxforms[i + 1], &pxformseq->pxforms[i], +		  n * sizeof(jas_cmpxform_t *)); +	} +	pxformseq->pxforms[i] = tmppxform; +	++pxformseq->numpxforms; +	return 0; +error: +	return -1; +} + +static int jas_cmpxformseq_append(jas_cmpxformseq_t *pxformseq, +  jas_cmpxformseq_t *othpxformseq) +{ +	int n; +	int i; +	jas_cmpxform_t *pxform; +	jas_cmpxform_t *othpxform; +	n = pxformseq->numpxforms + othpxformseq->numpxforms; +	if (n > pxformseq->maxpxforms) { +		if (jas_cmpxformseq_resize(pxformseq, n)) +			goto error; +	} +	for (i = 0; i < othpxformseq->numpxforms; ++i) { +		othpxform = othpxformseq->pxforms[i]; +		if (!(pxform = jas_cmpxform_copy(othpxform))) +			goto error; +		pxformseq->pxforms[pxformseq->numpxforms] = pxform; +		++pxformseq->numpxforms; +	} +	return 0; +error: +	return -1; +} + +static int jas_cmpxformseq_resize(jas_cmpxformseq_t *pxformseq, int n) +{ +	jas_cmpxform_t **p; +	assert(n >= pxformseq->numpxforms); +	p = (!pxformseq->pxforms) ? jas_malloc(n * sizeof(jas_cmpxform_t *)) : +	  jas_realloc(pxformseq->pxforms, n * sizeof(jas_cmpxform_t *)); +	if (!p) { +		return -1; +	} +	pxformseq->pxforms = p; +	pxformseq->maxpxforms = n; +	return 0; +} + +/******************************************************************************\ +* Primitive transform class. +\******************************************************************************/ + +static jas_cmpxform_t *jas_cmpxform_create0() +{ +	jas_cmpxform_t *pxform; +	if (!(pxform = jas_malloc(sizeof(jas_cmpxform_t)))) +		return 0; +	memset(pxform, 0, sizeof(jas_cmpxform_t)); +	pxform->refcnt = 0; +	pxform->ops = 0; +	return pxform; +} + +static void jas_cmpxform_destroy(jas_cmpxform_t *pxform) +{ +	if (--pxform->refcnt <= 0) { +		(*pxform->ops->destroy)(pxform); +		jas_free(pxform); +	} +} + +static jas_cmpxform_t *jas_cmpxform_copy(jas_cmpxform_t *pxform) +{ +	++pxform->refcnt; +	return pxform; +} + +/******************************************************************************\ +* Shaper matrix class. +\******************************************************************************/ + +static jas_cmpxform_t *jas_cmpxform_createshapmat() +{ +	int i; +	int j; +	jas_cmpxform_t *pxform; +	jas_cmshapmat_t *shapmat; +	if (!(pxform = jas_cmpxform_create0())) +		return 0; +	pxform->ops = &shapmat_ops; +	shapmat = &pxform->data.shapmat; +	shapmat->mono = 0; +	shapmat->order = 0; +	shapmat->useluts = 0; +	shapmat->usemat = 0; +	for (i = 0; i < 3; ++i) +		jas_cmshapmatlut_init(&shapmat->luts[i]); +	for (i = 0; i < 3; ++i) { +		for (j = 0; j < 4; ++j) +			shapmat->mat[i][j] = 0.0; +	} +	++pxform->refcnt; +	return pxform; +} + +static void jas_cmshapmat_destroy(jas_cmpxform_t *pxform) +{ +	jas_cmshapmat_t *shapmat = &pxform->data.shapmat; +	int i; +	for (i = 0; i < 3; ++i) +		jas_cmshapmatlut_cleanup(&shapmat->luts[i]); +} + +static int jas_cmshapmat_apply(jas_cmpxform_t *pxform, jas_cmreal_t *in, +  jas_cmreal_t *out, int cnt) +{ +	jas_cmshapmat_t *shapmat = &pxform->data.shapmat; +	jas_cmreal_t *src; +	jas_cmreal_t *dst; +	jas_cmreal_t a0; +	jas_cmreal_t a1; +	jas_cmreal_t a2; +	jas_cmreal_t b0; +	jas_cmreal_t b1; +	jas_cmreal_t b2; +	src = in; +	dst = out; +	if (!shapmat->mono) { +		while (--cnt >= 0) { +			a0 = *src++; +			a1 = *src++; +			a2 = *src++; +			if (!shapmat->order && shapmat->useluts) { +				a0 = jas_cmshapmatlut_lookup(&shapmat->luts[0], a0); +				a1 = jas_cmshapmatlut_lookup(&shapmat->luts[1], a1); +				a2 = jas_cmshapmatlut_lookup(&shapmat->luts[2], a2); +			} +			if (shapmat->usemat) { +				b0 = shapmat->mat[0][0] * a0 +				  + shapmat->mat[0][1] * a1 +				  + shapmat->mat[0][2] * a2 +				  + shapmat->mat[0][3]; +				b1 = shapmat->mat[1][0] * a0 +				  + shapmat->mat[1][1] * a1 +				  + shapmat->mat[1][2] * a2 +				  + shapmat->mat[1][3]; +				b2 = shapmat->mat[2][0] * a0 +				  + shapmat->mat[2][1] * a1 +				  + shapmat->mat[2][2] * a2 +				  + shapmat->mat[2][3]; +				a0 = b0; +				a1 = b1; +				a2 = b2; +			} +			if (shapmat->order && shapmat->useluts) { +				a0 = jas_cmshapmatlut_lookup(&shapmat->luts[0], a0); +				a1 = jas_cmshapmatlut_lookup(&shapmat->luts[1], a1); +				a2 = jas_cmshapmatlut_lookup(&shapmat->luts[2], a2); +			} +			*dst++ = a0; +			*dst++ = a1; +			*dst++ = a2; +		} +	} else { +		if (!shapmat->order) { +			while (--cnt >= 0) { +				a0 = *src++; +				if (shapmat->useluts) +					a0 = jas_cmshapmatlut_lookup(&shapmat->luts[0], a0); +				a2 = a0 * shapmat->mat[2][0]; +				a1 = a0 * shapmat->mat[1][0]; +				a0 = a0 * shapmat->mat[0][0]; +				*dst++ = a0; +				*dst++ = a1; +				*dst++ = a2; +			} +		} else { +assert(0); +			while (--cnt >= 0) { +				a0 = *src++; +				src++; +				src++; +				a0 = a0 * shapmat->mat[0][0]; +				if (shapmat->useluts) +					a0 = jas_cmshapmatlut_lookup(&shapmat->luts[0], a0); +				*dst++ = a0; +			} +		} +	} + +	return 0; +} + +static void jas_cmshapmatlut_init(jas_cmshapmatlut_t *lut) +{ +	lut->data = 0; +	lut->size = 0; +} + +static void jas_cmshapmatlut_cleanup(jas_cmshapmatlut_t *lut) +{ +	if (lut->data) { +		jas_free(lut->data); +		lut->data = 0; +	} +	lut->size = 0; +} + +static double gammafn(double x, double gamma) +{ +	if (x == 0.0) +		return 0.0; +	return pow(x, gamma); +} + +static int jas_cmshapmatlut_set(jas_cmshapmatlut_t *lut, jas_icccurv_t *curv) +{ +	jas_cmreal_t gamma; +	int i; +	gamma = 0; +	jas_cmshapmatlut_cleanup(lut); +	if (curv->numents == 0) { +		lut->size = 2; +		if (!(lut->data = jas_malloc(lut->size * sizeof(jas_cmreal_t)))) +			goto error; +		lut->data[0] = 0.0; +		lut->data[1] = 1.0; +	} else if (curv->numents == 1) { +		lut->size = 256; +		if (!(lut->data = jas_malloc(lut->size * sizeof(jas_cmreal_t)))) +			goto error; +		gamma = curv->ents[0] / 256.0; +		for (i = 0; i < lut->size; ++i) { +			lut->data[i] = gammafn(i / (double) (lut->size - 1), gamma); +		} +	} else { +		lut->size = curv->numents; +		if (!(lut->data = jas_malloc(lut->size * sizeof(jas_cmreal_t)))) +			goto error; +		for (i = 0; i < lut->size; ++i) { +			lut->data[i] = curv->ents[i] / 65535.0; +		} +	} +	return 0; +error: +	return -1; +} + +static jas_cmreal_t jas_cmshapmatlut_lookup(jas_cmshapmatlut_t *lut, jas_cmreal_t x) +{ +	jas_cmreal_t t; +	int lo; +	int hi; +	t = x * (lut->size - 1); +	lo = floor(t); +	if (lo < 0) +		return lut->data[0]; +	hi = ceil(t); +	if (hi >= lut->size) +		return lut->data[lut->size - 1]; +	return lut->data[lo] + (t - lo) * (lut->data[hi] - lut->data[lo]); +} + +static int jas_cmshapmatlut_invert(jas_cmshapmatlut_t *invlut, +  jas_cmshapmatlut_t *lut, int n) +{ +	int i; +	int j; +	int k; +	jas_cmreal_t ax; +	jas_cmreal_t ay; +	jas_cmreal_t bx; +	jas_cmreal_t by; +	jas_cmreal_t sx; +	jas_cmreal_t sy; +	assert(n >= 2); +	if (invlut->data) { +		jas_free(invlut->data); +		invlut->data = 0; +	} +	/* The sample values should be nondecreasing. */ +	for (i = 1; i < lut->size; ++i) { +		if (lut->data[i - 1] > lut->data[i]) { +			assert(0); +			return -1; +		} +	} +	if (!(invlut->data = jas_malloc(n * sizeof(jas_cmreal_t)))) +		return -1; +	invlut->size = n; +	for (i = 0; i < invlut->size; ++i) { +		sy = ((double) i) / (invlut->size - 1); +		sx = 1.0; +		for (j = 0; j < lut->size; ++j) { +			ay = lut->data[j]; +			if (sy == ay) { +				for (k = j + 1; k < lut->size; ++k) { +					by = lut->data[k]; +					if (by != sy) +						break; +#if 0 +assert(0); +#endif +				} +				if (k < lut->size) { +					--k; +					ax = ((double) j) / (lut->size - 1); +					bx = ((double) k) / (lut->size - 1); +					sx = (ax + bx) / 2.0; +				} +				break; +			} +			if (j < lut->size - 1) { +				by = lut->data[j + 1]; +				if (sy > ay && sy < by) { +					ax = ((double) j) / (lut->size - 1); +					bx = ((double) j + 1) / (lut->size - 1); +					sx = ax + +					  (sy - ay) / (by - ay) * (bx - ax); +					break; +				} +			} +		} +		invlut->data[i] = sx; +	} +#if 0 +for (i=0;i<lut->size;++i) +	jas_eprintf("lut[%d]=%f ", i, lut->data[i]); +for (i=0;i<invlut->size;++i) +	jas_eprintf("invlut[%d]=%f ", i, invlut->data[i]); +#endif +	return 0; +} + +static int jas_cmshapmat_invmat(jas_cmreal_t out[3][4], jas_cmreal_t in[3][4]) +{ +	jas_cmreal_t d; +	d = in[0][0] * (in[1][1] * in[2][2] - in[1][2] * in[2][1]) +	  - in[0][1] * (in[1][0] * in[2][2] - in[1][2] * in[2][0]) +	  + in[0][2] * (in[1][0] * in[2][1] - in[1][1] * in[2][0]); +#if 0 +jas_eprintf("delta=%f\n", d); +#endif +	if (JAS_ABS(d) < 1e-6) +		return -1; +	out[0][0] = (in[1][1] * in[2][2] - in[1][2] * in[2][1]) / d; +	out[1][0] = -(in[1][0] * in[2][2] - in[1][2] * in[2][0]) / d; +	out[2][0] = (in[1][0] * in[2][1] - in[1][1] * in[2][0]) / d; +	out[0][1] = -(in[0][1] * in[2][2] - in[0][2] * in[2][1]) / d; +	out[1][1] = (in[0][0] * in[2][2] - in[0][2] * in[2][0]) / d; +	out[2][1] = -(in[0][0] * in[2][1] - in[0][1] * in[2][0]) / d; +	out[0][2] = (in[0][1] * in[1][2] - in[0][2] * in[1][1]) / d; +	out[1][2] = -(in[0][0] * in[1][2] - in[1][0] * in[0][2]) / d; +	out[2][2] = (in[0][0] * in[1][1] - in[0][1] * in[1][0]) / d; +	out[0][3] = -in[0][3]; +	out[1][3] = -in[1][3]; +	out[2][3] = -in[2][3]; +#if 0 +jas_eprintf("[ %f %f %f %f ]\n[ %f %f %f %f ]\n[ %f %f %f %f ]\n", +in[0][0], in[0][1], in[0][2], in[0][3], +in[1][0], in[1][1], in[1][2], in[1][3], +in[2][0], in[2][1], in[2][2], in[2][3]); +jas_eprintf("[ %f %f %f %f ]\n[ %f %f %f %f ]\n[ %f %f %f %f ]\n", +out[0][0], out[0][1], out[0][2], out[0][3], +out[1][0], out[1][1], out[1][2], out[1][3], +out[2][0], out[2][1], out[2][2], out[2][3]); +#endif +	return 0; +} + +/******************************************************************************\ +* +\******************************************************************************/ + +static int icctoclrspc(int iccclrspc, int refflag) +{ +	if (refflag) { +		switch (iccclrspc) { +		case JAS_ICC_COLORSPC_XYZ: +			return JAS_CLRSPC_CIEXYZ; +		case JAS_ICC_COLORSPC_LAB: +			return JAS_CLRSPC_CIELAB; +		default: +			abort(); +			break; +		} +	} else { +		switch (iccclrspc) { +		case JAS_ICC_COLORSPC_YCBCR: +			return JAS_CLRSPC_GENYCBCR; +		case JAS_ICC_COLORSPC_RGB: +			return JAS_CLRSPC_GENRGB; +		case JAS_ICC_COLORSPC_GRAY: +			return JAS_CLRSPC_GENGRAY; +		default: +			abort(); +			break; +		} +	} +} + +static int mono(jas_iccprof_t *iccprof, int op, jas_cmpxformseq_t **retpxformseq) +{ +	jas_iccattrval_t *graytrc; +	jas_cmshapmat_t *shapmat; +	jas_cmpxform_t *pxform; +	jas_cmpxformseq_t *pxformseq; +	jas_cmshapmatlut_t lut; + +	jas_cmshapmatlut_init(&lut); +	if (!(graytrc = jas_iccprof_getattr(iccprof, JAS_ICC_TAG_GRYTRC)) || +	  graytrc->type != JAS_ICC_TYPE_CURV) +		goto error; +	if (!(pxform = jas_cmpxform_createshapmat())) +		goto error; +	shapmat = &pxform->data.shapmat; +	if (!(pxformseq = jas_cmpxformseq_create())) +		goto error; +	if (jas_cmpxformseq_insertpxform(pxformseq, -1, pxform)) +		goto error; + +	pxform->numinchans = 1; +	pxform->numoutchans = 3; + +	shapmat->mono = 1; +	shapmat->useluts = 1; +	shapmat->usemat = 1; +	if (!op) { +		shapmat->order = 0; +		shapmat->mat[0][0] = 0.9642; +		shapmat->mat[1][0] = 1.0; +		shapmat->mat[2][0] = 0.8249; +		if (jas_cmshapmatlut_set(&shapmat->luts[0], &graytrc->data.curv)) +			goto error; +	} else { +		shapmat->order = 1; +		shapmat->mat[0][0] = 1.0 / 0.9642; +		shapmat->mat[1][0] = 1.0; +		shapmat->mat[2][0] = 1.0 / 0.8249; +		jas_cmshapmatlut_init(&lut); +		if (jas_cmshapmatlut_set(&lut, &graytrc->data.curv)) +			goto error; +		if (jas_cmshapmatlut_invert(&shapmat->luts[0], &lut, lut.size)) +			goto error; +		jas_cmshapmatlut_cleanup(&lut); +	} +	jas_iccattrval_destroy(graytrc); +	jas_cmpxform_destroy(pxform); +	*retpxformseq = pxformseq; +	return 0; +error: +	return -1; +} + +static int triclr(jas_iccprof_t *iccprof, int op, jas_cmpxformseq_t **retpxformseq) +{ +	int i; +	jas_iccattrval_t *trcs[3]; +	jas_iccattrval_t *cols[3]; +	jas_cmshapmat_t *shapmat; +	jas_cmpxform_t *pxform; +	jas_cmpxformseq_t *pxformseq; +	jas_cmreal_t mat[3][4]; +	jas_cmshapmatlut_t lut; + +	pxform = 0; +	pxformseq = 0; +	for (i = 0; i < 3; ++i) { +		trcs[i] = 0; +		cols[i] = 0; +	} +	jas_cmshapmatlut_init(&lut); + +	if (!(trcs[0] = jas_iccprof_getattr(iccprof, JAS_ICC_TAG_REDTRC)) || +	  !(trcs[1] = jas_iccprof_getattr(iccprof, JAS_ICC_TAG_GRNTRC)) || +	  !(trcs[2] = jas_iccprof_getattr(iccprof, JAS_ICC_TAG_BLUTRC)) || +	  !(cols[0] = jas_iccprof_getattr(iccprof, JAS_ICC_TAG_REDMATCOL)) || +	  !(cols[1] = jas_iccprof_getattr(iccprof, JAS_ICC_TAG_GRNMATCOL)) || +	  !(cols[2] = jas_iccprof_getattr(iccprof, JAS_ICC_TAG_BLUMATCOL))) +		goto error; +	for (i = 0; i < 3; ++i) { +		if (trcs[i]->type != JAS_ICC_TYPE_CURV || +		  cols[i]->type != JAS_ICC_TYPE_XYZ) +			goto error; +	} +	if (!(pxform = jas_cmpxform_createshapmat())) +		goto error; +	pxform->numinchans = 3; +	pxform->numoutchans = 3; +	shapmat = &pxform->data.shapmat; +	if (!(pxformseq = jas_cmpxformseq_create())) +		goto error; +	if (jas_cmpxformseq_insertpxform(pxformseq, -1, pxform)) +		goto error; +	shapmat->mono = 0; +	shapmat->useluts = 1; +	shapmat->usemat = 1; +	if (!op) { +		shapmat->order = 0; +		for (i = 0; i < 3; ++i) { +			shapmat->mat[0][i] = cols[i]->data.xyz.x / 65536.0; +			shapmat->mat[1][i] = cols[i]->data.xyz.y / 65536.0; +			shapmat->mat[2][i] = cols[i]->data.xyz.z / 65536.0; +		} +		for (i = 0; i < 3; ++i) +			shapmat->mat[i][3] = 0.0; +		for (i = 0; i < 3; ++i) { +			if (jas_cmshapmatlut_set(&shapmat->luts[i], &trcs[i]->data.curv)) +				goto error; +		} +	} else { +		shapmat->order = 1; +		for (i = 0; i < 3; ++i) { +			mat[0][i] = cols[i]->data.xyz.x / 65536.0; +			mat[1][i] = cols[i]->data.xyz.y / 65536.0; +			mat[2][i] = cols[i]->data.xyz.z / 65536.0; +		} +		for (i = 0; i < 3; ++i) +			mat[i][3] = 0.0; +		if (jas_cmshapmat_invmat(shapmat->mat, mat)) +			goto error; +		for (i = 0; i < 3; ++i) { +			jas_cmshapmatlut_init(&lut); +			if (jas_cmshapmatlut_set(&lut, &trcs[i]->data.curv)) +				goto error; +			if (jas_cmshapmatlut_invert(&shapmat->luts[i], &lut, lut.size)) +				goto error; +			jas_cmshapmatlut_cleanup(&lut); +		} +	} +	for (i = 0; i < 3; ++i) { +		jas_iccattrval_destroy(trcs[i]); +		jas_iccattrval_destroy(cols[i]); +	} +	jas_cmpxform_destroy(pxform); +	*retpxformseq = pxformseq; +	return 0; + +error: + +	for (i = 0; i < 3; ++i) { +		if (trcs[i]) { +			jas_iccattrval_destroy(trcs[i]); +		} +		if (cols[i]) { +			jas_iccattrval_destroy(cols[i]); +		} +	} +	if (pxformseq) { +		jas_cmpxformseq_destroy(pxformseq); +	} +	if (pxform) { +		jas_cmpxform_destroy(pxform); +	} + +	return -1; +} + +static int jas_cmgetint(long **bufptr, int sgnd, int prec, long *val) +{ +	long v; +	int m; +	v = **bufptr; +	if (sgnd) { +		m = (1 << (prec - 1)); +		if (v < -m || v >= m) +			return -1; +	} else { +		if (v < 0 || v >= (1 << prec)) +			return -1; +	} +	++(*bufptr); +	*val = v; +	return 0; +} + +static int jas_cmputint(long **bufptr, int sgnd, int prec, long val) +{ +	int m; +	if (sgnd) { +		m = (1 << (prec - 1)); +		if (val < -m || val >= m) +			return -1; +	} else { +		if (val < 0 || val >= (1 << prec)) +			return -1; +	} +	**bufptr = val; +	++(*bufptr); +	return 0; +} + +int jas_clrspc_numchans(int clrspc) +{ +	switch (jas_clrspc_fam(clrspc)) { +	case JAS_CLRSPC_FAM_XYZ: +	case JAS_CLRSPC_FAM_LAB: +	case JAS_CLRSPC_FAM_RGB: +	case JAS_CLRSPC_FAM_YCBCR: +		return 3; +		break; +	case JAS_CLRSPC_FAM_GRAY: +		return 1; +		break; +	default: +		abort(); +		break; +	} +} + +jas_iccprof_t *jas_iccprof_createfromcmprof(jas_cmprof_t *prof) +{ +	return jas_iccprof_copy(prof->iccprof); +} diff --git a/src/libjasper/base/jas_debug.c b/src/libjasper/base/jas_debug.c new file mode 100644 index 0000000..8a762d5 --- /dev/null +++ b/src/libjasper/base/jas_debug.c @@ -0,0 +1,137 @@ +/* + * 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__ + */ + +/******************************************************************************\ +* Includes. +\******************************************************************************/ + +#include <stdarg.h> +#include <stdio.h> + +#include "jasper/jas_types.h" +#include "jasper/jas_debug.h" + +/******************************************************************************\ +* Local data. +\******************************************************************************/ + +static int jas_dbglevel = 0; +/* The debug level. */ + +/******************************************************************************\ +* Code for getting/setting the debug level. +\******************************************************************************/ + +/* Set the library debug level. */ +int jas_setdbglevel(int dbglevel) +{ +	int olddbglevel; + +	/* Save the old debug level. */ +	olddbglevel = jas_dbglevel; + +	/* Change the debug level. */ +	jas_dbglevel = dbglevel; + +	/* Return the old debug level. */ +	return olddbglevel; +} + +/* Get the library debug level. */ +int jas_getdbglevel() +{ +	return jas_dbglevel; +} + +/******************************************************************************\ +* Code. +\******************************************************************************/ + +/* Perform formatted output to standard error. */ +int jas_eprintf(const char *fmt, ...) +{ +	int ret; +	va_list ap; + +	va_start(ap, fmt); +	ret = vfprintf(stderr, fmt, ap); +	va_end(ap); +	return ret; +} + +/* Dump memory to a stream. */ +int jas_memdump(FILE *out, void *data, size_t len) +{ +	size_t i; +	size_t j; +	uchar *dp; +	dp = data; +	for (i = 0; i < len; i += 16) { +		fprintf(out, "%04x:", i); +		for (j = 0; j < 16; ++j) { +			if (i + j < len) { +				fprintf(out, " %02x", dp[i + j]); +			} +		} +		fprintf(out, "\n"); +	} +	return 0; +} diff --git a/src/libjasper/base/jas_getopt.c b/src/libjasper/base/jas_getopt.c new file mode 100644 index 0000000..efb472e --- /dev/null +++ b/src/libjasper/base/jas_getopt.c @@ -0,0 +1,168 @@ +/* + * 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__ + */ + +/* + * Command Line Option Parsing Library + * + * $Id: jas_getopt.c,v 1.1 2008/10/17 06:14:59 scuri Exp $ + */ + +/******************************************************************************\ +* Includes. +\******************************************************************************/ + +#include <stdio.h> +#include <string.h> + +#include "jasper/jas_getopt.h" +#include "jasper/jas_math.h" + +/******************************************************************************\ +* Global data. +\******************************************************************************/ + +int jas_optind = 0; +int jas_opterr = 1; +char *jas_optarg = 0; + +/******************************************************************************\ +* Code. +\******************************************************************************/ + +static jas_opt_t *jas_optlookup(jas_opt_t *opts, char *name) +{ +	jas_opt_t *opt; + +	for (opt = opts; opt->id >= 0 && opt->name; ++opt) { +		if (!strcmp(opt->name, name)) { +			return opt; +		} +	} +	return 0; +} + +int jas_getopt(int argc, char **argv, jas_opt_t *opts) +{ +	char *cp; +	int id; +	int hasarg; +	jas_opt_t *opt; +	char *s; + +	if (!jas_optind) { +		jas_optind = JAS_MIN(1, argc); +	} +	while (jas_optind < argc) { +		s = cp = argv[jas_optind]; +		if (*cp == '-') { +			/* We are processing an option. */ +			++jas_optind; +			if (*++cp == '-') { +				/* We are processing a long option. */ +				++cp; +				if (*cp == '\0') { +					/* This is the end of the options. */ +					return JAS_GETOPT_EOF; +				} +				if (!(opt = jas_optlookup(opts, cp))) { +					if (jas_opterr) { +						jas_eprintf("unknown long option %s\n", s); +					} +					return JAS_GETOPT_ERR; +				} +				hasarg = (opt->flags & JAS_OPT_HASARG) != 0; +				id = opt->id; +			} else { +				/* We are processing a short option. */ +				if (strlen(cp) != 1 || +				  !(opt = jas_optlookup(opts, cp))) { +					if (jas_opterr) { +						jas_eprintf("unknown short option %s\n", s); +					} +					return JAS_GETOPT_ERR; +				} +				hasarg = (opt->flags & JAS_OPT_HASARG) != 0; +				id = opt->id; +			} +			if (hasarg) { +				/* The option has an argument. */ +				if (jas_optind >= argc) { +					if (jas_opterr) { +						jas_eprintf("missing argument for option %s\n", s); +					} +					return JAS_GETOPT_ERR; +				} +				jas_optarg = argv[jas_optind]; +				++jas_optind; +			} else { +				/* The option does not have an argument. */ +				jas_optarg = 0; +			} +			return id; +		} else { +			/* We are not processing an option. */ +			return JAS_GETOPT_EOF; +		} +	} +	return JAS_GETOPT_EOF; +} diff --git a/src/libjasper/base/jas_icc.c b/src/libjasper/base/jas_icc.c new file mode 100644 index 0000000..e5a0a2e --- /dev/null +++ b/src/libjasper/base/jas_icc.c @@ -0,0 +1,1722 @@ +/* + * Copyright (c) 2002-2003 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__ + */ + +#include <assert.h> +#include <jasper/jas_config.h> +#include <jasper/jas_types.h> +#include <jasper/jas_malloc.h> +#include <jasper/jas_debug.h> +#include <jasper/jas_icc.h> +#include <jasper/jas_cm.h> +#include <jasper/jas_stream.h> +#include <jasper/jas_string.h> + +#include <stdlib.h> +#include <ctype.h> + +#define	jas_iccputuint8(out, val)	jas_iccputuint(out, 1, val) +#define	jas_iccputuint16(out, val)	jas_iccputuint(out, 2, val) +#define	jas_iccputsint32(out, val)	jas_iccputsint(out, 4, val) +#define	jas_iccputuint32(out, val)	jas_iccputuint(out, 4, val) +#define	jas_iccputuint64(out, val)	jas_iccputuint(out, 8, val) + +static jas_iccattrval_t *jas_iccattrval_create0(void); + +static int jas_iccgetuint(jas_stream_t *in, int n, ulonglong *val); +static int jas_iccgetuint8(jas_stream_t *in, jas_iccuint8_t *val); +static int jas_iccgetuint16(jas_stream_t *in, jas_iccuint16_t *val); +static int jas_iccgetsint32(jas_stream_t *in, jas_iccsint32_t *val); +static int jas_iccgetuint32(jas_stream_t *in, jas_iccuint32_t *val); +static int jas_iccgetuint64(jas_stream_t *in, jas_iccuint64_t *val); +static int jas_iccputuint(jas_stream_t *out, int n, ulonglong val); +static int jas_iccputsint(jas_stream_t *out, int n, longlong val); +static jas_iccprof_t *jas_iccprof_create(void); +static int jas_iccprof_readhdr(jas_stream_t *in, jas_icchdr_t *hdr); +static int jas_iccprof_writehdr(jas_stream_t *out, jas_icchdr_t *hdr); +static int jas_iccprof_gettagtab(jas_stream_t *in, jas_icctagtab_t *tagtab); +static void jas_iccprof_sorttagtab(jas_icctagtab_t *tagtab); +static int jas_iccattrtab_lookup(jas_iccattrtab_t *attrtab, jas_iccuint32_t name); +static jas_iccattrtab_t *jas_iccattrtab_copy(jas_iccattrtab_t *attrtab); +static jas_iccattrvalinfo_t *jas_iccattrvalinfo_lookup(jas_iccsig_t name); +static int jas_iccgettime(jas_stream_t *in, jas_icctime_t *time); +static int jas_iccgetxyz(jas_stream_t *in, jas_iccxyz_t *xyz); +static int jas_icctagtabent_cmp(const void *src, const void *dst); + +static void jas_icccurv_destroy(jas_iccattrval_t *attrval); +static int jas_icccurv_copy(jas_iccattrval_t *attrval, +  jas_iccattrval_t *othattrval); +static int jas_icccurv_input(jas_iccattrval_t *attrval, jas_stream_t *in, +  int cnt); +static int jas_icccurv_getsize(jas_iccattrval_t *attrval); +static int jas_icccurv_output(jas_iccattrval_t *attrval, jas_stream_t *out); +static void jas_icccurv_dump(jas_iccattrval_t *attrval, FILE *out); + +static void jas_icctxtdesc_destroy(jas_iccattrval_t *attrval); +static int jas_icctxtdesc_copy(jas_iccattrval_t *attrval, +  jas_iccattrval_t *othattrval); +static int jas_icctxtdesc_input(jas_iccattrval_t *attrval, jas_stream_t *in, +  int cnt); +static int jas_icctxtdesc_getsize(jas_iccattrval_t *attrval); +static int jas_icctxtdesc_output(jas_iccattrval_t *attrval, jas_stream_t *out); +static void jas_icctxtdesc_dump(jas_iccattrval_t *attrval, FILE *out); + +static void jas_icctxt_destroy(jas_iccattrval_t *attrval); +static int jas_icctxt_copy(jas_iccattrval_t *attrval, +  jas_iccattrval_t *othattrval); +static int jas_icctxt_input(jas_iccattrval_t *attrval, jas_stream_t *in, +  int cnt); +static int jas_icctxt_getsize(jas_iccattrval_t *attrval); +static int jas_icctxt_output(jas_iccattrval_t *attrval, jas_stream_t *out); +static void jas_icctxt_dump(jas_iccattrval_t *attrval, FILE *out); + +static int jas_iccxyz_input(jas_iccattrval_t *attrval, jas_stream_t *in, +  int cnt); +static int jas_iccxyz_getsize(jas_iccattrval_t *attrval); +static int jas_iccxyz_output(jas_iccattrval_t *attrval, jas_stream_t *out); +static void jas_iccxyz_dump(jas_iccattrval_t *attrval, FILE *out); + +static jas_iccattrtab_t *jas_iccattrtab_create(void); +static void jas_iccattrtab_destroy(jas_iccattrtab_t *tab); +static int jas_iccattrtab_resize(jas_iccattrtab_t *tab, int maxents); +static int jas_iccattrtab_add(jas_iccattrtab_t *attrtab, int i, +  jas_iccuint32_t name, jas_iccattrval_t *val); +static int jas_iccattrtab_replace(jas_iccattrtab_t *attrtab, int i, +  jas_iccuint32_t name, jas_iccattrval_t *val); +static void jas_iccattrtab_delete(jas_iccattrtab_t *attrtab, int i); +static long jas_iccpadtomult(long x, long y); +static int jas_iccattrtab_get(jas_iccattrtab_t *attrtab, int i, +  jas_iccattrname_t *name, jas_iccattrval_t **val); +static int jas_iccprof_puttagtab(jas_stream_t *out, jas_icctagtab_t *tagtab); + +static void jas_icclut16_destroy(jas_iccattrval_t *attrval); +static int jas_icclut16_copy(jas_iccattrval_t *attrval, +  jas_iccattrval_t *othattrval); +static int jas_icclut16_input(jas_iccattrval_t *attrval, jas_stream_t *in, +  int cnt); +static int jas_icclut16_getsize(jas_iccattrval_t *attrval); +static int jas_icclut16_output(jas_iccattrval_t *attrval, jas_stream_t *out); +static void jas_icclut16_dump(jas_iccattrval_t *attrval, FILE *out); + +static void jas_icclut8_destroy(jas_iccattrval_t *attrval); +static int jas_icclut8_copy(jas_iccattrval_t *attrval, +  jas_iccattrval_t *othattrval); +static int jas_icclut8_input(jas_iccattrval_t *attrval, jas_stream_t *in, +  int cnt); +static int jas_icclut8_getsize(jas_iccattrval_t *attrval); +static int jas_icclut8_output(jas_iccattrval_t *attrval, jas_stream_t *out); +static void jas_icclut8_dump(jas_iccattrval_t *attrval, FILE *out); + +static int jas_iccputtime(jas_stream_t *out, jas_icctime_t *ctime); +static int jas_iccputxyz(jas_stream_t *out, jas_iccxyz_t *xyz); + +static long jas_iccpowi(int x, int n); + +static char *jas_iccsigtostr(int sig, char *buf); + + +jas_iccattrvalinfo_t jas_iccattrvalinfos[] = { +	{JAS_ICC_TYPE_CURV, {jas_icccurv_destroy, jas_icccurv_copy, +	  jas_icccurv_input, jas_icccurv_output, jas_icccurv_getsize, +	  jas_icccurv_dump}}, +	{JAS_ICC_TYPE_XYZ, {0, 0, jas_iccxyz_input, jas_iccxyz_output, +	  jas_iccxyz_getsize, jas_iccxyz_dump}}, +	{JAS_ICC_TYPE_TXTDESC, {jas_icctxtdesc_destroy, +	  jas_icctxtdesc_copy, jas_icctxtdesc_input, jas_icctxtdesc_output, +	  jas_icctxtdesc_getsize, jas_icctxtdesc_dump}}, +	{JAS_ICC_TYPE_TXT, {jas_icctxt_destroy, jas_icctxt_copy, +	  jas_icctxt_input, jas_icctxt_output, jas_icctxt_getsize, +	  jas_icctxt_dump}}, +	{JAS_ICC_TYPE_LUT8, {jas_icclut8_destroy, jas_icclut8_copy, +	  jas_icclut8_input, jas_icclut8_output, jas_icclut8_getsize, +	  jas_icclut8_dump}}, +	{JAS_ICC_TYPE_LUT16, {jas_icclut16_destroy, jas_icclut16_copy, +	  jas_icclut16_input, jas_icclut16_output, jas_icclut16_getsize, +	  jas_icclut16_dump}}, +	{0, {0, 0, 0, 0, 0, 0}} +}; + +typedef struct { +	jas_iccuint32_t tag; +	char *name; +} jas_icctaginfo_t; + +/******************************************************************************\ +* profile class +\******************************************************************************/ + +static jas_iccprof_t *jas_iccprof_create() +{ +	jas_iccprof_t *prof; +	prof = 0; +	if (!(prof = jas_malloc(sizeof(jas_iccprof_t)))) { +		goto error; +	} +	if (!(prof->attrtab = jas_iccattrtab_create())) +		goto error; +	memset(&prof->hdr, 0, sizeof(jas_icchdr_t)); +	prof->tagtab.numents = 0; +	prof->tagtab.ents = 0; +	return prof; +error: +	if (prof) +		jas_iccprof_destroy(prof); +	return 0; +} + +jas_iccprof_t *jas_iccprof_copy(jas_iccprof_t *prof) +{ +	jas_iccprof_t *newprof; +	newprof = 0; +	if (!(newprof = jas_iccprof_create())) +		goto error; +	newprof->hdr = prof->hdr; +	newprof->tagtab.numents = 0; +	newprof->tagtab.ents = 0; +	assert(newprof->attrtab); +	jas_iccattrtab_destroy(newprof->attrtab); +	if (!(newprof->attrtab = jas_iccattrtab_copy(prof->attrtab))) +		goto error; +	return newprof; +error: +	if (newprof) +		jas_iccprof_destroy(newprof); +	return 0; +} + +void jas_iccprof_destroy(jas_iccprof_t *prof) +{ +	if (prof->attrtab) +		jas_iccattrtab_destroy(prof->attrtab); +	if (prof->tagtab.ents) +		jas_free(prof->tagtab.ents); +	jas_free(prof); +} + +void jas_iccprof_dump(jas_iccprof_t *prof, FILE *out) +{ +	jas_iccattrtab_dump(prof->attrtab, out); +} + +jas_iccprof_t *jas_iccprof_load(jas_stream_t *in) +{ +	jas_iccprof_t *prof; +	int numtags; +	long curoff; +	long reloff; +	long prevoff; +	jas_iccsig_t type; +	jas_iccattrval_t *attrval; +	jas_iccattrval_t *prevattrval; +	jas_icctagtabent_t *tagtabent; +	jas_iccattrvalinfo_t *attrvalinfo; +	int i; +	int len; + +	prof = 0; +	attrval = 0; + +	if (!(prof = jas_iccprof_create())) { +		goto error; +	} + +	if (jas_iccprof_readhdr(in, &prof->hdr)) { +		jas_eprintf("cannot get header\n"); +		goto error; +	} +	if (jas_iccprof_gettagtab(in, &prof->tagtab)) { +		jas_eprintf("cannot get tab table\n"); +		goto error; +	} +	jas_iccprof_sorttagtab(&prof->tagtab); + +	numtags = prof->tagtab.numents; +	curoff = JAS_ICC_HDRLEN + 4 + 12 * numtags; +	prevoff = 0; +	prevattrval = 0; +	for (i = 0; i < numtags; ++i) { +		tagtabent = &prof->tagtab.ents[i]; +		if (tagtabent->off == JAS_CAST(jas_iccuint32_t, prevoff)) { +			if (prevattrval) { +				if (!(attrval = jas_iccattrval_clone(prevattrval))) +					goto error; +				if (jas_iccprof_setattr(prof, tagtabent->tag, attrval)) +					goto error; +				jas_iccattrval_destroy(attrval); +			} else { +#if 0 +				jas_eprintf("warning: skipping unknown tag type\n"); +#endif +			} +			continue; +		} +		reloff = tagtabent->off - curoff; +		if (reloff > 0) { +			if (jas_stream_gobble(in, reloff) != reloff) +				goto error; +			curoff += reloff; +		} else if (reloff < 0) { +			/* This should never happen since we read the tagged +			element data in a single pass. */ +			abort(); +		} +		prevoff = curoff; +		if (jas_iccgetuint32(in, &type)) { +			goto error; +		} +		if (jas_stream_gobble(in, 4) != 4) { +			goto error; +		} +		curoff += 8; +		if (!(attrvalinfo = jas_iccattrvalinfo_lookup(type))) { +#if 0 +			jas_eprintf("warning: skipping unknown tag type\n"); +#endif +			prevattrval = 0; +			continue; +		} +		if (!(attrval = jas_iccattrval_create(type))) { +			goto error; +		} +		len = tagtabent->len - 8; +		if ((*attrval->ops->input)(attrval, in, len)) { +			goto error; +		} +		curoff += len; +		if (jas_iccprof_setattr(prof, tagtabent->tag, attrval)) { +			goto error; +		} +		prevattrval = attrval; /* This is correct, but slimey. */ +		jas_iccattrval_destroy(attrval); +		attrval = 0; +	} + +	return prof; + +error: +	if (prof) +		jas_iccprof_destroy(prof); +	if (attrval) +		jas_iccattrval_destroy(attrval); +	return 0; +} + +int jas_iccprof_save(jas_iccprof_t *prof, jas_stream_t *out) +{ +	long curoff; +	long reloff; +	long newoff; +	int i; +	int j; +	jas_icctagtabent_t *tagtabent; +	jas_icctagtabent_t *sharedtagtabent; +	jas_icctagtabent_t *tmptagtabent; +	jas_iccuint32_t attrname; +	jas_iccattrval_t *attrval; +	jas_icctagtab_t *tagtab; + +	tagtab = &prof->tagtab; +	if (!(tagtab->ents = jas_malloc(prof->attrtab->numattrs * +	  sizeof(jas_icctagtabent_t)))) +		goto error; +	tagtab->numents = prof->attrtab->numattrs; +	curoff = JAS_ICC_HDRLEN + 4 + 12 * tagtab->numents; +	for (i = 0; i < JAS_CAST(int, tagtab->numents); ++i) { +		tagtabent = &tagtab->ents[i]; +		if (jas_iccattrtab_get(prof->attrtab, i, &attrname, &attrval)) +			goto error; +		assert(attrval->ops->output); +		tagtabent->tag = attrname; +		tagtabent->data = &attrval->data; +		sharedtagtabent = 0; +		for (j = 0; j < i; ++j) { +			tmptagtabent = &tagtab->ents[j]; +			if (tagtabent->data == tmptagtabent->data) { +				sharedtagtabent = tmptagtabent; +				break; +			} +		} +		if (sharedtagtabent) { +			tagtabent->off = sharedtagtabent->off; +			tagtabent->len = sharedtagtabent->len; +			tagtabent->first = sharedtagtabent; +		} else { +			tagtabent->off = curoff; +			tagtabent->len = (*attrval->ops->getsize)(attrval) + 8; +			tagtabent->first = 0; +			if (i < JAS_CAST(int, tagtab->numents - 1)) { +				curoff = jas_iccpadtomult(curoff + tagtabent->len, 4); +			} else { +				curoff += tagtabent->len; +			} +		} +		jas_iccattrval_destroy(attrval); +	} +	prof->hdr.size = curoff; +	if (jas_iccprof_writehdr(out, &prof->hdr)) +		goto error; +	if (jas_iccprof_puttagtab(out, &prof->tagtab)) +		goto error; +	curoff = JAS_ICC_HDRLEN + 4 + 12 * tagtab->numents; +	for (i = 0; i < JAS_CAST(int, tagtab->numents);) { +		tagtabent = &tagtab->ents[i]; +		assert(curoff == JAS_CAST(long, tagtabent->off)); +		if (jas_iccattrtab_get(prof->attrtab, i, &attrname, &attrval)) +			goto error; +		if (jas_iccputuint32(out, attrval->type) || jas_stream_pad(out, +		  4, 0) != 4) +			goto error; +		if ((*attrval->ops->output)(attrval, out)) +			goto error; +		jas_iccattrval_destroy(attrval); +		curoff += tagtabent->len; +		++i; +		while (i < JAS_CAST(int, tagtab->numents) && +		  tagtab->ents[i].first) +			++i; +		newoff = (i < JAS_CAST(int, tagtab->numents)) ? +		  tagtab->ents[i].off : prof->hdr.size; +		reloff = newoff - curoff; +		assert(reloff >= 0); +		if (reloff > 0) { +			if (jas_stream_pad(out, reloff, 0) != reloff) +				goto error; +			curoff += reloff; +		} +	}	 +	return 0; +error: +	/* XXX - need to free some resources here */ +	return -1; +} + +static int jas_iccprof_writehdr(jas_stream_t *out, jas_icchdr_t *hdr) +{ +	if (jas_iccputuint32(out, hdr->size) || +	  jas_iccputuint32(out, hdr->cmmtype) || +	  jas_iccputuint32(out, hdr->version) || +	  jas_iccputuint32(out, hdr->clas) || +	  jas_iccputuint32(out, hdr->colorspc) || +	  jas_iccputuint32(out, hdr->refcolorspc) || +	  jas_iccputtime(out, &hdr->ctime) || +	  jas_iccputuint32(out, hdr->magic) || +	  jas_iccputuint32(out, hdr->platform) || +	  jas_iccputuint32(out, hdr->flags) || +	  jas_iccputuint32(out, hdr->maker) || +	  jas_iccputuint32(out, hdr->model) || +	  jas_iccputuint64(out, hdr->attr) || +	  jas_iccputuint32(out, hdr->intent) || +	  jas_iccputxyz(out, &hdr->illum) || +	  jas_iccputuint32(out, hdr->creator) || +	  jas_stream_pad(out, 44, 0) != 44) +		return -1; +	return 0; +} + +static int jas_iccprof_puttagtab(jas_stream_t *out, jas_icctagtab_t *tagtab) +{ +	int i; +	jas_icctagtabent_t *tagtabent; +	if (jas_iccputuint32(out, tagtab->numents)) +		goto error; +	for (i = 0; i < JAS_CAST(int, tagtab->numents); ++i) { +		tagtabent = &tagtab->ents[i]; +		if (jas_iccputuint32(out, tagtabent->tag) || +		  jas_iccputuint32(out, tagtabent->off) || +		  jas_iccputuint32(out, tagtabent->len)) +			goto error; +	} +	return 0; +error: +	return -1; +} + +static int jas_iccprof_readhdr(jas_stream_t *in, jas_icchdr_t *hdr) +{ +	if (jas_iccgetuint32(in, &hdr->size) || +	  jas_iccgetuint32(in, &hdr->cmmtype) || +	  jas_iccgetuint32(in, &hdr->version) || +	  jas_iccgetuint32(in, &hdr->clas) || +	  jas_iccgetuint32(in, &hdr->colorspc) || +	  jas_iccgetuint32(in, &hdr->refcolorspc) || +	  jas_iccgettime(in, &hdr->ctime) || +	  jas_iccgetuint32(in, &hdr->magic) || +	  jas_iccgetuint32(in, &hdr->platform) || +	  jas_iccgetuint32(in, &hdr->flags) || +	  jas_iccgetuint32(in, &hdr->maker) || +	  jas_iccgetuint32(in, &hdr->model) || +	  jas_iccgetuint64(in, &hdr->attr) || +	  jas_iccgetuint32(in, &hdr->intent) || +	  jas_iccgetxyz(in, &hdr->illum) || +	  jas_iccgetuint32(in, &hdr->creator) || +	  jas_stream_gobble(in, 44) != 44) +		return -1; +	return 0; +} + +static int jas_iccprof_gettagtab(jas_stream_t *in, jas_icctagtab_t *tagtab) +{ +	int i; +	jas_icctagtabent_t *tagtabent; + +	if (tagtab->ents) { +		jas_free(tagtab->ents); +		tagtab->ents = 0; +	} +	if (jas_iccgetuint32(in, &tagtab->numents)) +		goto error; +	if (!(tagtab->ents = jas_malloc(tagtab->numents * +	  sizeof(jas_icctagtabent_t)))) +		goto error; +	tagtabent = tagtab->ents; +	for (i = 0; i < JAS_CAST(long, tagtab->numents); ++i) { +		if (jas_iccgetuint32(in, &tagtabent->tag) || +		jas_iccgetuint32(in, &tagtabent->off) || +		jas_iccgetuint32(in, &tagtabent->len)) +			goto error; +		++tagtabent; +	} +	return 0; +error: +	if (tagtab->ents) { +		jas_free(tagtab->ents); +		tagtab->ents = 0; +	} +	return -1; +} + +jas_iccattrval_t *jas_iccprof_getattr(jas_iccprof_t *prof, +  jas_iccattrname_t name) +{ +	int i; +	jas_iccattrval_t *attrval; +	if ((i = jas_iccattrtab_lookup(prof->attrtab, name)) < 0) +		goto error; +	if (!(attrval = jas_iccattrval_clone(prof->attrtab->attrs[i].val))) +		goto error; +	return attrval; +error: +	return 0; +} + +int jas_iccprof_setattr(jas_iccprof_t *prof, jas_iccattrname_t name, +  jas_iccattrval_t *val) +{ +	int i; +	if ((i = jas_iccattrtab_lookup(prof->attrtab, name)) >= 0) { +		if (val) { +			if (jas_iccattrtab_replace(prof->attrtab, i, name, val)) +				goto error; +		} else { +			jas_iccattrtab_delete(prof->attrtab, i); +		} +	} else { +		if (val) { +			if (jas_iccattrtab_add(prof->attrtab, -1, name, val)) +				goto error; +		} else { +			/* NOP */ +		} +	} +	return 0; +error: +	return -1; +} + +int jas_iccprof_gethdr(jas_iccprof_t *prof, jas_icchdr_t *hdr) +{ +	*hdr = prof->hdr; +	return 0; +} + +int jas_iccprof_sethdr(jas_iccprof_t *prof, jas_icchdr_t *hdr) +{ +	prof->hdr = *hdr; +	return 0; +} + +static void jas_iccprof_sorttagtab(jas_icctagtab_t *tagtab) +{ +	qsort(tagtab->ents, tagtab->numents, sizeof(jas_icctagtabent_t), +	  jas_icctagtabent_cmp); +} + +static int jas_icctagtabent_cmp(const void *src, const void *dst) +{ +	jas_icctagtabent_t *srctagtabent = JAS_CAST(jas_icctagtabent_t *, src); +	jas_icctagtabent_t *dsttagtabent = JAS_CAST(jas_icctagtabent_t *, dst); +	if (srctagtabent->off > dsttagtabent->off) { +		return 1; +	} else if (srctagtabent->off < dsttagtabent->off) { +		return -1; +	} +	return 0; +} + +static jas_iccattrvalinfo_t *jas_iccattrvalinfo_lookup(jas_iccsig_t type) +{ +	jas_iccattrvalinfo_t *info; +	info = jas_iccattrvalinfos; +	for (info = jas_iccattrvalinfos; info->type; ++info) { +		if (info->type == type) { +			return info; +		} +	} +	return 0; +} + +static int jas_iccgettime(jas_stream_t *in, jas_icctime_t *time) +{ +	if (jas_iccgetuint16(in, &time->year) || +	  jas_iccgetuint16(in, &time->month) || +	  jas_iccgetuint16(in, &time->day) || +	  jas_iccgetuint16(in, &time->hour) || +	  jas_iccgetuint16(in, &time->min) || +	  jas_iccgetuint16(in, &time->sec)) { +		return -1; +	} +	return 0; +} + +static int jas_iccgetxyz(jas_stream_t *in, jas_iccxyz_t *xyz) +{ +	if (jas_iccgetsint32(in, &xyz->x) || +	  jas_iccgetsint32(in, &xyz->y) || +	  jas_iccgetsint32(in, &xyz->z)) { +		return -1; +	} +	return 0; +} + +static int jas_iccputtime(jas_stream_t *out, jas_icctime_t *time) +{ +	jas_iccputuint16(out, time->year); +	jas_iccputuint16(out, time->month); +	jas_iccputuint16(out, time->day); +	jas_iccputuint16(out, time->hour); +	jas_iccputuint16(out, time->min); +	jas_iccputuint16(out, time->sec); +	return 0; +} + +static int jas_iccputxyz(jas_stream_t *out, jas_iccxyz_t *xyz) +{ +	jas_iccputuint32(out, xyz->x); +	jas_iccputuint32(out, xyz->y); +	jas_iccputuint32(out, xyz->z); +	return 0; +} + +/******************************************************************************\ +* attribute table class +\******************************************************************************/ + +static jas_iccattrtab_t *jas_iccattrtab_create() +{ +	jas_iccattrtab_t *tab; +	tab = 0; +	if (!(tab = jas_malloc(sizeof(jas_iccattrtab_t)))) +		goto error; +	tab->maxattrs = 0; +	tab->numattrs = 0; +	tab->attrs = 0; +	if (jas_iccattrtab_resize(tab, 32)) +		goto error; +	return tab; +error: +	if (tab) +		jas_iccattrtab_destroy(tab); +	return 0; +} + +static jas_iccattrtab_t *jas_iccattrtab_copy(jas_iccattrtab_t *attrtab) +{ +	jas_iccattrtab_t *newattrtab; +	int i; +	if (!(newattrtab = jas_iccattrtab_create())) +		goto error; +	for (i = 0; i < attrtab->numattrs; ++i) { +		if (jas_iccattrtab_add(newattrtab, i, attrtab->attrs[i].name, +		  attrtab->attrs[i].val)) +			goto error; +	} +	return newattrtab; +error: +	return 0; +} + +static void jas_iccattrtab_destroy(jas_iccattrtab_t *tab) +{ +	if (tab->attrs) { +		while (tab->numattrs > 0) { +			jas_iccattrtab_delete(tab, 0); +		} +		jas_free(tab->attrs); +	} +	jas_free(tab); +} + +void jas_iccattrtab_dump(jas_iccattrtab_t *attrtab, FILE *out) +{ +	int i; +	jas_iccattr_t *attr; +	jas_iccattrval_t *attrval; +	jas_iccattrvalinfo_t *info; +	char buf[16]; +	fprintf(out, "numattrs=%d\n", attrtab->numattrs); +	fprintf(out, "---\n"); +	for (i = 0; i < attrtab->numattrs; ++i) { +		attr = &attrtab->attrs[i]; +		attrval = attr->val; +		info = jas_iccattrvalinfo_lookup(attrval->type); +		if (!info) abort(); +		fprintf(out, "attrno=%d; attrname=\"%s\"(0x%08x); attrtype=\"%s\"(0x%08x)\n", +		  i, +		  jas_iccsigtostr(attr->name, &buf[0]), +		  attr->name, +		  jas_iccsigtostr(attrval->type, &buf[8]), +		  attrval->type +		  ); +		jas_iccattrval_dump(attrval, out); +		fprintf(out, "---\n"); +	} +} + +static int jas_iccattrtab_resize(jas_iccattrtab_t *tab, int maxents) +{ +	jas_iccattr_t *newattrs; +	assert(maxents >= tab->numattrs); +	newattrs = tab->attrs ? jas_realloc(tab->attrs, maxents * +	  sizeof(jas_iccattr_t)) : jas_malloc(maxents * sizeof(jas_iccattr_t)); +	if (!newattrs) +		return -1; +	tab->attrs = newattrs; +	tab->maxattrs = maxents; +	return 0; +} + +static int jas_iccattrtab_add(jas_iccattrtab_t *attrtab, int i, +  jas_iccuint32_t name, jas_iccattrval_t *val) +{ +	int n; +	jas_iccattr_t *attr; +	jas_iccattrval_t *tmpattrval; +	tmpattrval = 0; +	if (i < 0) { +		i = attrtab->numattrs; +	} +	assert(i >= 0 && i <= attrtab->numattrs); +	if (attrtab->numattrs >= attrtab->maxattrs) { +		if (jas_iccattrtab_resize(attrtab, attrtab->numattrs + 32)) { +			goto error; +		} +	} +	if (!(tmpattrval = jas_iccattrval_clone(val))) +		goto error; +	n = attrtab->numattrs - i; +	if (n > 0) +		memmove(&attrtab->attrs[i + 1], &attrtab->attrs[i], +		  n * sizeof(jas_iccattr_t)); +	attr = &attrtab->attrs[i]; +	attr->name = name; +	attr->val = tmpattrval; +	++attrtab->numattrs; +	return 0; +error: +	if (tmpattrval) +		jas_iccattrval_destroy(tmpattrval); +	return -1; +} + +static int jas_iccattrtab_replace(jas_iccattrtab_t *attrtab, int i, +  jas_iccuint32_t name, jas_iccattrval_t *val) +{ +	jas_iccattrval_t *newval; +	jas_iccattr_t *attr; +	if (!(newval = jas_iccattrval_clone(val))) +		goto error; +	attr = &attrtab->attrs[i]; +	jas_iccattrval_destroy(attr->val); +	attr->name = name; +	attr->val = newval; +	return 0; +error: +	return -1; +} + +static void jas_iccattrtab_delete(jas_iccattrtab_t *attrtab, int i) +{ +	int n; +	jas_iccattrval_destroy(attrtab->attrs[i].val); +	if ((n = attrtab->numattrs - i - 1) > 0) +		memmove(&attrtab->attrs[i], &attrtab->attrs[i + 1], +		  n * sizeof(jas_iccattr_t)); +	--attrtab->numattrs; +} + +static int jas_iccattrtab_get(jas_iccattrtab_t *attrtab, int i, +  jas_iccattrname_t *name, jas_iccattrval_t **val) +{ +	jas_iccattr_t *attr; +	if (i < 0 || i >= attrtab->numattrs) +		goto error; +	attr = &attrtab->attrs[i]; +	*name = attr->name; +	if (!(*val = jas_iccattrval_clone(attr->val))) +		goto error; +	return 0; +error: +	return -1; +} + +static int jas_iccattrtab_lookup(jas_iccattrtab_t *attrtab, +  jas_iccuint32_t name) +{ +	int i; +	jas_iccattr_t *attr; +	for (i = 0; i < attrtab->numattrs; ++i) { +		attr = &attrtab->attrs[i]; +		if (attr->name == name) +			return i; +	} +	return -1; +} + +/******************************************************************************\ +* attribute value class +\******************************************************************************/ + +jas_iccattrval_t *jas_iccattrval_create(jas_iccuint32_t type) +{ +	jas_iccattrval_t *attrval; +	jas_iccattrvalinfo_t *info; + +	if (!(info = jas_iccattrvalinfo_lookup(type))) +		goto error; +	if (!(attrval = jas_iccattrval_create0())) +		goto error; +	attrval->ops = &info->ops; +	attrval->type = type; +	++attrval->refcnt; +	memset(&attrval->data, 0, sizeof(attrval->data)); +	return attrval; +error: +	return 0; +} + +jas_iccattrval_t *jas_iccattrval_clone(jas_iccattrval_t *attrval) +{ +	++attrval->refcnt; +	return attrval; +} + +void jas_iccattrval_destroy(jas_iccattrval_t *attrval) +{ +#if 0 +jas_eprintf("refcnt=%d\n", attrval->refcnt); +#endif +	if (--attrval->refcnt <= 0) { +		if (attrval->ops->destroy) +			(*attrval->ops->destroy)(attrval); +		jas_free(attrval); +	} +} + +void jas_iccattrval_dump(jas_iccattrval_t *attrval, FILE *out) +{ +	char buf[8]; +	jas_iccsigtostr(attrval->type, buf); +	fprintf(out, "refcnt = %d; type = 0x%08x %s\n", attrval->refcnt, +	  attrval->type, jas_iccsigtostr(attrval->type, &buf[0])); +	if (attrval->ops->dump) { +		(*attrval->ops->dump)(attrval, out); +	} +} + +int jas_iccattrval_allowmodify(jas_iccattrval_t **attrvalx) +{ +	jas_iccattrval_t *newattrval; +	jas_iccattrval_t *attrval = *attrvalx; +	newattrval = 0; +	if (attrval->refcnt > 1) { +		if (!(newattrval = jas_iccattrval_create0())) +			goto error; +		newattrval->ops = attrval->ops; +		newattrval->type = attrval->type; +		++newattrval->refcnt; +		if (newattrval->ops->copy) { +			if ((*newattrval->ops->copy)(newattrval, attrval)) +				goto error; +		} else { +			memcpy(&newattrval->data, &attrval->data, +			  sizeof(newattrval->data)); +		} +		*attrvalx = newattrval; +	} +	return 0; +error: +	if (newattrval) { +		jas_free(newattrval); +	} +	return -1; +} + +static jas_iccattrval_t *jas_iccattrval_create0() +{ +	jas_iccattrval_t *attrval; +	if (!(attrval = jas_malloc(sizeof(jas_iccattrval_t)))) +		return 0; +	memset(attrval, 0, sizeof(jas_iccattrval_t)); +	attrval->refcnt = 0; +	attrval->ops = 0; +	attrval->type = 0; +	return attrval; +} + +/******************************************************************************\ +* +\******************************************************************************/ + +static int jas_iccxyz_input(jas_iccattrval_t *attrval, jas_stream_t *in, +  int len) +{ +	if (len != 4 * 3) abort(); +	return jas_iccgetxyz(in, &attrval->data.xyz); +} + +static int jas_iccxyz_output(jas_iccattrval_t *attrval, jas_stream_t *out) +{ +	jas_iccxyz_t *xyz = &attrval->data.xyz; +	if (jas_iccputuint32(out, xyz->x) || +	  jas_iccputuint32(out, xyz->y) || +	  jas_iccputuint32(out, xyz->z)) +		return -1; +	return 0; +} + +static int jas_iccxyz_getsize(jas_iccattrval_t *attrval) +{ +	/* Avoid compiler warnings about unused parameters. */ +	attrval = 0; + +	return 12; +} + +static void jas_iccxyz_dump(jas_iccattrval_t *attrval, FILE *out) +{ +	jas_iccxyz_t *xyz = &attrval->data.xyz; +	fprintf(out, "(%f, %f, %f)\n", xyz->x / 65536.0, xyz->y / 65536.0, xyz->z / 65536.0); +} + +/******************************************************************************\ +* attribute table class +\******************************************************************************/ + +static void jas_icccurv_destroy(jas_iccattrval_t *attrval) +{ +	jas_icccurv_t *curv = &attrval->data.curv; +	if (curv->ents) +		jas_free(curv->ents); +} + +static int jas_icccurv_copy(jas_iccattrval_t *attrval, +  jas_iccattrval_t *othattrval) +{ +	/* Avoid compiler warnings about unused parameters. */ +	attrval = 0; +	othattrval = 0; + +	/* Not yet implemented. */ +	abort(); +	return -1; +} + +static int jas_icccurv_input(jas_iccattrval_t *attrval, jas_stream_t *in, +  int cnt) +{ +	jas_icccurv_t *curv = &attrval->data.curv; +	unsigned int i; + +	curv->numents = 0; +	curv->ents = 0; + +	if (jas_iccgetuint32(in, &curv->numents)) +		goto error; +	if (!(curv->ents = jas_malloc(curv->numents * sizeof(jas_iccuint16_t)))) +		goto error; +	for (i = 0; i < curv->numents; ++i) { +		if (jas_iccgetuint16(in, &curv->ents[i])) +			goto error; +	} + +	if (JAS_CAST(int, 4 + 2 * curv->numents) != cnt) +		goto error; +	return 0; + +error: +	jas_icccurv_destroy(attrval); +	return -1; +} + +static int jas_icccurv_getsize(jas_iccattrval_t *attrval) +{ +	jas_icccurv_t *curv = &attrval->data.curv; +	return 4 + 2 * curv->numents; +} + +static int jas_icccurv_output(jas_iccattrval_t *attrval, jas_stream_t *out) +{ +	jas_icccurv_t *curv = &attrval->data.curv; +	unsigned int i; + +	if (jas_iccputuint32(out, curv->numents)) +		goto error; +	for (i = 0; i < curv->numents; ++i) { +		if (jas_iccputuint16(out, curv->ents[i])) +			goto error; +	} +	return 0; +error: +	return -1; +} + +static void jas_icccurv_dump(jas_iccattrval_t *attrval, FILE *out) +{ +	int i; +	jas_icccurv_t *curv = &attrval->data.curv; +	fprintf(out, "number of entires = %d\n", curv->numents); +	if (curv->numents == 1) { +		fprintf(out, "gamma = %f\n", curv->ents[0] / 256.0); +	} else { +		for (i = 0; i < JAS_CAST(int, curv->numents); ++i) { +			if (i < 3 || i >= JAS_CAST(int, curv->numents) - 3) { +				fprintf(out, "entry[%d] = %f\n", i, curv->ents[i] / 65535.0); +			} +		} +	} +} + +/******************************************************************************\ +* +\******************************************************************************/ + +static void jas_icctxtdesc_destroy(jas_iccattrval_t *attrval) +{ +	jas_icctxtdesc_t *txtdesc = &attrval->data.txtdesc; +	if (txtdesc->ascdata) +		jas_free(txtdesc->ascdata); +	if (txtdesc->ucdata) +		jas_free(txtdesc->ucdata); +} + +static int jas_icctxtdesc_copy(jas_iccattrval_t *attrval, +  jas_iccattrval_t *othattrval) +{ +	jas_icctxtdesc_t *txtdesc = &attrval->data.txtdesc; + +	/* Avoid compiler warnings about unused parameters. */ +	attrval = 0; +	othattrval = 0; +	txtdesc = 0; + +	/* Not yet implemented. */ +	abort(); +	return -1; +} + +static int jas_icctxtdesc_input(jas_iccattrval_t *attrval, jas_stream_t *in, +  int cnt) +{ +	int n; +	int c; +	jas_icctxtdesc_t *txtdesc = &attrval->data.txtdesc; +	txtdesc->ascdata = 0; +	txtdesc->ucdata = 0; +	if (jas_iccgetuint32(in, &txtdesc->asclen)) +		goto error; +	if (!(txtdesc->ascdata = jas_malloc(txtdesc->asclen))) +		goto error; +	if (jas_stream_read(in, txtdesc->ascdata, txtdesc->asclen) != +	  JAS_CAST(int, txtdesc->asclen)) +		goto error; +	txtdesc->ascdata[txtdesc->asclen - 1] = '\0'; +	if (jas_iccgetuint32(in, &txtdesc->uclangcode) || +	  jas_iccgetuint32(in, &txtdesc->uclen)) +		goto error; +	if (!(txtdesc->ucdata = jas_malloc(txtdesc->uclen * 2))) +		goto error; +	if (jas_stream_read(in, txtdesc->ucdata, txtdesc->uclen * 2) != +	  JAS_CAST(int, txtdesc->uclen * 2)) +		goto error; +	if (jas_iccgetuint16(in, &txtdesc->sccode)) +		goto error; +	if ((c = jas_stream_getc(in)) == EOF) +		goto error; +	txtdesc->maclen = c; +	if (jas_stream_read(in, txtdesc->macdata, 67) != 67) +		goto error; +	txtdesc->asclen = strlen(txtdesc->ascdata) + 1; +#define WORKAROUND_BAD_PROFILES +#ifdef WORKAROUND_BAD_PROFILES +	n = txtdesc->asclen + txtdesc->uclen * 2 + 15 + 67; +	if (n > cnt) { +		return -1; +	} +	if (n < cnt) { +		if (jas_stream_gobble(in, cnt - n) != cnt - n) +			goto error; +	} +#else +	if (txtdesc->asclen + txtdesc->uclen * 2 + 15 + 67 != cnt) +		return -1; +#endif +	return 0; +error: +	jas_icctxtdesc_destroy(attrval); +	return -1; +} + +static int jas_icctxtdesc_getsize(jas_iccattrval_t *attrval) +{ +	jas_icctxtdesc_t *txtdesc = &attrval->data.txtdesc; +	return strlen(txtdesc->ascdata) + 1 + txtdesc->uclen * 2 + 15 + 67; +} + +static int jas_icctxtdesc_output(jas_iccattrval_t *attrval, jas_stream_t *out) +{ +	jas_icctxtdesc_t *txtdesc = &attrval->data.txtdesc; +	if (jas_iccputuint32(out, txtdesc->asclen) || +	  jas_stream_puts(out, txtdesc->ascdata) || +	  jas_stream_putc(out, 0) == EOF || +	  jas_iccputuint32(out, txtdesc->uclangcode) || +	  jas_iccputuint32(out, txtdesc->uclen) || +	  jas_stream_write(out, txtdesc->ucdata, txtdesc->uclen * 2) != JAS_CAST(int, txtdesc->uclen * 2) || +	  jas_iccputuint16(out, txtdesc->sccode) || +	  jas_stream_putc(out, txtdesc->maclen) == EOF) +		goto error; +	if (txtdesc->maclen > 0) { +		if (jas_stream_write(out, txtdesc->macdata, 67) != 67) +			goto error; +	} else { +		if (jas_stream_pad(out, 67, 0) != 67) +			goto error; +	} +	return 0; +error: +	return -1; +} + +static void jas_icctxtdesc_dump(jas_iccattrval_t *attrval, FILE *out) +{ +	jas_icctxtdesc_t *txtdesc = &attrval->data.txtdesc; +	fprintf(out, "ascii = \"%s\"\n", txtdesc->ascdata); +	fprintf(out, "uclangcode = %d; uclen = %d\n", txtdesc->uclangcode, +	  txtdesc->uclen); +	fprintf(out, "sccode = %d\n", txtdesc->sccode); +	fprintf(out, "maclen = %d\n", txtdesc->maclen); +} + +/******************************************************************************\ +* +\******************************************************************************/ + +static void jas_icctxt_destroy(jas_iccattrval_t *attrval) +{ +	jas_icctxt_t *txt = &attrval->data.txt; +	if (txt->string) +		jas_free(txt->string); +} + +static int jas_icctxt_copy(jas_iccattrval_t *attrval, +  jas_iccattrval_t *othattrval) +{ +	jas_icctxt_t *txt = &attrval->data.txt; +	jas_icctxt_t *othtxt = &othattrval->data.txt; +	if (!(txt->string = jas_strdup(othtxt->string))) +		return -1; +	return 0; +} + +static int jas_icctxt_input(jas_iccattrval_t *attrval, jas_stream_t *in, +  int cnt) +{ +	jas_icctxt_t *txt = &attrval->data.txt; +	txt->string = 0; +	if (!(txt->string = jas_malloc(cnt))) +		goto error; +	if (jas_stream_read(in, txt->string, cnt) != cnt) +		goto error; +	txt->string[cnt - 1] = '\0'; +	if (JAS_CAST(int, strlen(txt->string)) + 1 != cnt) +		goto error; +	return 0; +error: +	if (txt->string) +		jas_free(txt->string); +	return -1; +} + +static int jas_icctxt_getsize(jas_iccattrval_t *attrval) +{ +	jas_icctxt_t *txt = &attrval->data.txt; +	return strlen(txt->string) + 1; +} + +static int jas_icctxt_output(jas_iccattrval_t *attrval, jas_stream_t *out) +{ +	jas_icctxt_t *txt = &attrval->data.txt; +	if (jas_stream_puts(out, txt->string) || +	  jas_stream_putc(out, 0) == EOF) +		return -1; +	return 0; +} + +static void jas_icctxt_dump(jas_iccattrval_t *attrval, FILE *out) +{ +	jas_icctxt_t *txt = &attrval->data.txt; +	fprintf(out, "string = \"%s\"\n", txt->string); +} + +/******************************************************************************\ +* +\******************************************************************************/ + +static void jas_icclut8_destroy(jas_iccattrval_t *attrval) +{ +	jas_icclut8_t *lut8 = &attrval->data.lut8; +	if (lut8->clut) +		jas_free(lut8->clut); +	if (lut8->intabs) +		jas_free(lut8->intabs); +	if (lut8->intabsbuf) +		jas_free(lut8->intabsbuf); +	if (lut8->outtabs) +		jas_free(lut8->outtabs); +	if (lut8->outtabsbuf) +		jas_free(lut8->outtabsbuf); +} + +static int jas_icclut8_copy(jas_iccattrval_t *attrval, +  jas_iccattrval_t *othattrval) +{ +	jas_icclut8_t *lut8 = &attrval->data.lut8; +	/* Avoid compiler warnings about unused parameters. */ +	attrval = 0; +	othattrval = 0; +	lut8 = 0; +	abort(); +	return -1; +} + +static int jas_icclut8_input(jas_iccattrval_t *attrval, jas_stream_t *in, +  int cnt) +{ +	int i; +	int j; +	int clutsize; +	jas_icclut8_t *lut8 = &attrval->data.lut8; +	lut8->clut = 0; +	lut8->intabs = 0; +	lut8->intabsbuf = 0; +	lut8->outtabs = 0; +	lut8->outtabsbuf = 0; +	if (jas_iccgetuint8(in, &lut8->numinchans) || +	  jas_iccgetuint8(in, &lut8->numoutchans) || +	  jas_iccgetuint8(in, &lut8->clutlen) || +	  jas_stream_getc(in) == EOF) +		goto error; +	for (i = 0; i < 3; ++i) { +		for (j = 0; j < 3; ++j) { +			if (jas_iccgetsint32(in, &lut8->e[i][j])) +				goto error; +		} +	} +	if (jas_iccgetuint16(in, &lut8->numintabents) || +	  jas_iccgetuint16(in, &lut8->numouttabents)) +		goto error; +	clutsize = jas_iccpowi(lut8->clutlen, lut8->numinchans) * lut8->numoutchans; +	if (!(lut8->clut = jas_malloc(clutsize * sizeof(jas_iccuint8_t))) || +	  !(lut8->intabsbuf = jas_malloc(lut8->numinchans * +	  lut8->numintabents * sizeof(jas_iccuint8_t))) || +	  !(lut8->intabs = jas_malloc(lut8->numinchans * +	  sizeof(jas_iccuint8_t *)))) +		goto error; +	for (i = 0; i < lut8->numinchans; ++i) +		lut8->intabs[i] = &lut8->intabsbuf[i * lut8->numintabents]; +	if (!(lut8->outtabsbuf = jas_malloc(lut8->numoutchans * +	  lut8->numouttabents * sizeof(jas_iccuint8_t))) || +	  !(lut8->outtabs = jas_malloc(lut8->numoutchans * +	  sizeof(jas_iccuint8_t *)))) +		goto error; +	for (i = 0; i < lut8->numoutchans; ++i) +		lut8->outtabs[i] = &lut8->outtabsbuf[i * lut8->numouttabents]; +	for (i = 0; i < lut8->numinchans; ++i) { +		for (j = 0; j < JAS_CAST(int, lut8->numintabents); ++j) { +			if (jas_iccgetuint8(in, &lut8->intabs[i][j])) +				goto error; +		} +	} +	for (i = 0; i < lut8->numoutchans; ++i) { +		for (j = 0; j < JAS_CAST(int, lut8->numouttabents); ++j) { +			if (jas_iccgetuint8(in, &lut8->outtabs[i][j])) +				goto error; +		} +	} +	for (i = 0; i < clutsize; ++i) { +		if (jas_iccgetuint8(in, &lut8->clut[i])) +			goto error; +	} +	if (JAS_CAST(int, 44 + lut8->numinchans * lut8->numintabents + +	  lut8->numoutchans * lut8->numouttabents + +	  jas_iccpowi(lut8->clutlen, lut8->numinchans) * lut8->numoutchans) != +	  cnt) +		goto error; +	return 0; +error: +	jas_icclut8_destroy(attrval); +	return -1; +} + +static int jas_icclut8_getsize(jas_iccattrval_t *attrval) +{ +	jas_icclut8_t *lut8 = &attrval->data.lut8; +	return 44 + lut8->numinchans * lut8->numintabents + +	  lut8->numoutchans * lut8->numouttabents + +	  jas_iccpowi(lut8->clutlen, lut8->numinchans) * lut8->numoutchans; +} + +static int jas_icclut8_output(jas_iccattrval_t *attrval, jas_stream_t *out) +{ +	jas_icclut8_t *lut8 = &attrval->data.lut8; +	int i; +	int j; +	int n; +	lut8->clut = 0; +	lut8->intabs = 0; +	lut8->intabsbuf = 0; +	lut8->outtabs = 0; +	lut8->outtabsbuf = 0; +	if (jas_stream_putc(out, lut8->numinchans) == EOF || +	  jas_stream_putc(out, lut8->numoutchans) == EOF || +	  jas_stream_putc(out, lut8->clutlen) == EOF || +	  jas_stream_putc(out, 0) == EOF) +		goto error; +	for (i = 0; i < 3; ++i) { +		for (j = 0; j < 3; ++j) { +			if (jas_iccputsint32(out, lut8->e[i][j])) +				goto error; +		} +	} +	if (jas_iccputuint16(out, lut8->numintabents) || +	  jas_iccputuint16(out, lut8->numouttabents)) +		goto error; +	n = lut8->numinchans * lut8->numintabents; +	for (i = 0; i < n; ++i) { +		if (jas_iccputuint8(out, lut8->intabsbuf[i])) +			goto error; +	} +	n = lut8->numoutchans * lut8->numouttabents; +	for (i = 0; i < n; ++i) { +		if (jas_iccputuint8(out, lut8->outtabsbuf[i])) +			goto error; +	} +	n = jas_iccpowi(lut8->clutlen, lut8->numinchans) * lut8->numoutchans; +	for (i = 0; i < n; ++i) { +		if (jas_iccputuint8(out, lut8->clut[i])) +			goto error; +	} +	return 0; +error: +	return -1; +} + +static void jas_icclut8_dump(jas_iccattrval_t *attrval, FILE *out) +{ +	jas_icclut8_t *lut8 = &attrval->data.lut8; +	int i; +	int j; +	fprintf(out, "numinchans=%d, numoutchans=%d, clutlen=%d\n", +	  lut8->numinchans, lut8->numoutchans, lut8->clutlen); +	for (i = 0; i < 3; ++i) { +		for (j = 0; j < 3; ++j) { +			fprintf(out, "e[%d][%d]=%f ", i, j, lut8->e[i][j] / 65536.0); +		} +		fprintf(out, "\n"); +	} +	fprintf(out, "numintabents=%d, numouttabents=%d\n", +	  lut8->numintabents, lut8->numouttabents); +} + +/******************************************************************************\ +* +\******************************************************************************/ + +static void jas_icclut16_destroy(jas_iccattrval_t *attrval) +{ +	jas_icclut16_t *lut16 = &attrval->data.lut16; +	if (lut16->clut) +		jas_free(lut16->clut); +	if (lut16->intabs) +		jas_free(lut16->intabs); +	if (lut16->intabsbuf) +		jas_free(lut16->intabsbuf); +	if (lut16->outtabs) +		jas_free(lut16->outtabs); +	if (lut16->outtabsbuf) +		jas_free(lut16->outtabsbuf); +} + +static int jas_icclut16_copy(jas_iccattrval_t *attrval, +  jas_iccattrval_t *othattrval) +{ +	/* Avoid compiler warnings about unused parameters. */ +	attrval = 0; +	othattrval = 0; +	/* Not yet implemented. */ +	abort(); +	return -1; +} + +static int jas_icclut16_input(jas_iccattrval_t *attrval, jas_stream_t *in, +  int cnt) +{ +	int i; +	int j; +	int clutsize; +	jas_icclut16_t *lut16 = &attrval->data.lut16; +	lut16->clut = 0; +	lut16->intabs = 0; +	lut16->intabsbuf = 0; +	lut16->outtabs = 0; +	lut16->outtabsbuf = 0; +	if (jas_iccgetuint8(in, &lut16->numinchans) || +	  jas_iccgetuint8(in, &lut16->numoutchans) || +	  jas_iccgetuint8(in, &lut16->clutlen) || +	  jas_stream_getc(in) == EOF) +		goto error; +	for (i = 0; i < 3; ++i) { +		for (j = 0; j < 3; ++j) { +			if (jas_iccgetsint32(in, &lut16->e[i][j])) +				goto error; +		} +	} +	if (jas_iccgetuint16(in, &lut16->numintabents) || +	  jas_iccgetuint16(in, &lut16->numouttabents)) +		goto error; +	clutsize = jas_iccpowi(lut16->clutlen, lut16->numinchans) * lut16->numoutchans; +	if (!(lut16->clut = jas_malloc(clutsize * sizeof(jas_iccuint16_t))) || +	  !(lut16->intabsbuf = jas_malloc(lut16->numinchans * +	  lut16->numintabents * sizeof(jas_iccuint16_t))) || +	  !(lut16->intabs = jas_malloc(lut16->numinchans * +	  sizeof(jas_iccuint16_t *)))) +		goto error; +	for (i = 0; i < lut16->numinchans; ++i) +		lut16->intabs[i] = &lut16->intabsbuf[i * lut16->numintabents]; +	if (!(lut16->outtabsbuf = jas_malloc(lut16->numoutchans * +	  lut16->numouttabents * sizeof(jas_iccuint16_t))) || +	  !(lut16->outtabs = jas_malloc(lut16->numoutchans * +	  sizeof(jas_iccuint16_t *)))) +		goto error; +	for (i = 0; i < lut16->numoutchans; ++i) +		lut16->outtabs[i] = &lut16->outtabsbuf[i * lut16->numouttabents]; +	for (i = 0; i < lut16->numinchans; ++i) { +		for (j = 0; j < JAS_CAST(int, lut16->numintabents); ++j) { +			if (jas_iccgetuint16(in, &lut16->intabs[i][j])) +				goto error; +		} +	} +	for (i = 0; i < lut16->numoutchans; ++i) { +		for (j = 0; j < JAS_CAST(int, lut16->numouttabents); ++j) { +			if (jas_iccgetuint16(in, &lut16->outtabs[i][j])) +				goto error; +		} +	} +	for (i = 0; i < clutsize; ++i) { +		if (jas_iccgetuint16(in, &lut16->clut[i])) +			goto error; +	} +	if (JAS_CAST(int, 44 + 2 * (lut16->numinchans * lut16->numintabents + +          lut16->numoutchans * lut16->numouttabents + +          jas_iccpowi(lut16->clutlen, lut16->numinchans) * +	  lut16->numoutchans)) != cnt) +		goto error; +	return 0; +error: +	jas_icclut16_destroy(attrval); +	return -1; +} + +static int jas_icclut16_getsize(jas_iccattrval_t *attrval) +{ +	jas_icclut16_t *lut16 = &attrval->data.lut16; +	return 44 + 2 * (lut16->numinchans * lut16->numintabents + +	  lut16->numoutchans * lut16->numouttabents + +	  jas_iccpowi(lut16->clutlen, lut16->numinchans) * lut16->numoutchans); +} + +static int jas_icclut16_output(jas_iccattrval_t *attrval, jas_stream_t *out) +{ +	jas_icclut16_t *lut16 = &attrval->data.lut16; +	int i; +	int j; +	int n; +	if (jas_stream_putc(out, lut16->numinchans) == EOF || +	  jas_stream_putc(out, lut16->numoutchans) == EOF || +	  jas_stream_putc(out, lut16->clutlen) == EOF || +	  jas_stream_putc(out, 0) == EOF) +		goto error; +	for (i = 0; i < 3; ++i) { +		for (j = 0; j < 3; ++j) { +			if (jas_iccputsint32(out, lut16->e[i][j])) +				goto error; +		} +	} +	if (jas_iccputuint16(out, lut16->numintabents) || +	  jas_iccputuint16(out, lut16->numouttabents)) +		goto error; +	n = lut16->numinchans * lut16->numintabents; +	for (i = 0; i < n; ++i) { +		if (jas_iccputuint16(out, lut16->intabsbuf[i])) +			goto error; +	} +	n = lut16->numoutchans * lut16->numouttabents; +	for (i = 0; i < n; ++i) { +		if (jas_iccputuint16(out, lut16->outtabsbuf[i])) +			goto error; +	} +	n = jas_iccpowi(lut16->clutlen, lut16->numinchans) * lut16->numoutchans; +	for (i = 0; i < n; ++i) { +		if (jas_iccputuint16(out, lut16->clut[i])) +			goto error; +	} +	return 0; +error: +	return -1; +} + +static void jas_icclut16_dump(jas_iccattrval_t *attrval, FILE *out) +{ +	jas_icclut16_t *lut16 = &attrval->data.lut16; +	int i; +	int j; +	fprintf(out, "numinchans=%d, numoutchans=%d, clutlen=%d\n", +	  lut16->numinchans, lut16->numoutchans, lut16->clutlen); +	for (i = 0; i < 3; ++i) { +		for (j = 0; j < 3; ++j) { +			fprintf(out, "e[%d][%d]=%f ", i, j, lut16->e[i][j] / 65536.0); +		} +		fprintf(out, "\n"); +	} +	fprintf(out, "numintabents=%d, numouttabents=%d\n", +	  lut16->numintabents, lut16->numouttabents); +} + +/******************************************************************************\ +* +\******************************************************************************/ + +static int jas_iccgetuint(jas_stream_t *in, int n, ulonglong *val) +{ +	int i; +	int c; +	ulonglong v; +	v = 0; +	for (i = n; i > 0; --i) { +		if ((c = jas_stream_getc(in)) == EOF) +			return -1; +		v = (v << 8) | c; +	} +	*val = v; +	return 0; +} + +static int jas_iccgetuint8(jas_stream_t *in, jas_iccuint8_t *val) +{ +	int c; +	if ((c = jas_stream_getc(in)) == EOF) +		return -1; +	*val = c; +	return 0; +} + +static int jas_iccgetuint16(jas_stream_t *in, jas_iccuint16_t *val) +{ +	ulonglong tmp; +	if (jas_iccgetuint(in, 2, &tmp)) +		return -1; +	*val = tmp; +	return 0; +} + +static int jas_iccgetsint32(jas_stream_t *in, jas_iccsint32_t *val) +{ +	ulonglong tmp; +	if (jas_iccgetuint(in, 4, &tmp)) +		return -1; +	*val = (tmp & 0x80000000) ? (-JAS_CAST(longlong, (((~tmp) & +	  0x7fffffff) + 1))) : JAS_CAST(longlong, tmp); +	return 0; +} + +static int jas_iccgetuint32(jas_stream_t *in, jas_iccuint32_t *val) +{ +	ulonglong tmp; +	if (jas_iccgetuint(in, 4, &tmp)) +		return -1; +	*val = tmp; +	return 0; +} + +static int jas_iccgetuint64(jas_stream_t *in, jas_iccuint64_t *val) +{ +	ulonglong tmp; +	if (jas_iccgetuint(in, 8, &tmp)) +		return -1; +	*val = tmp; +	return 0; +} + +static int jas_iccputuint(jas_stream_t *out, int n, ulonglong val) +{ +	int i; +	int c; +	for (i = n; i > 0; --i) { +		c = (val >> (8 * (i - 1))) & 0xff; +		if (jas_stream_putc(out, c) == EOF) +			return -1; +	} +	return 0; +} + +static int jas_iccputsint(jas_stream_t *out, int n, longlong val) +{ +	ulonglong tmp; +	tmp = (val < 0) ? (abort(), 0) : val; +	return jas_iccputuint(out, n, tmp); +} + +/******************************************************************************\ +* +\******************************************************************************/ + +static char *jas_iccsigtostr(int sig, char *buf) +{ +	int n; +	int c; +	char *bufptr; +	bufptr = buf; +	for (n = 4; n > 0; --n) { +		c = (sig >> 24) & 0xff; +		if (isalpha(c) || isdigit(c)) { +			*bufptr++ = c; +		} +		sig <<= 8; +	} +	*bufptr = '\0'; +	return buf; +} + +static long jas_iccpadtomult(long x, long y) +{ +	return ((x + y - 1) / y) * y; +} + +static long jas_iccpowi(int x, int n) +{ +	long y; +	y = 1; +	while (--n >= 0) +		y *= x; +	return y; +} + + +jas_iccprof_t *jas_iccprof_createfrombuf(uchar *buf, int len) +{ +	jas_stream_t *in; +	jas_iccprof_t *prof; +	if (!(in = jas_stream_memopen(JAS_CAST(char *, buf), len))) +		goto error; +	if (!(prof = jas_iccprof_load(in))) +		goto error; +	jas_stream_close(in); +	return prof; +error: +	return 0; +} + +jas_iccprof_t *jas_iccprof_createfromclrspc(int clrspc) +{ +	jas_iccprof_t *prof; +	switch (clrspc) { +	case JAS_CLRSPC_SRGB: +		prof = jas_iccprof_createfrombuf(jas_iccprofdata_srgb, +		  jas_iccprofdata_srgblen); +		break; +	case JAS_CLRSPC_SGRAY: +		prof = jas_iccprof_createfrombuf(jas_iccprofdata_sgray, +		  jas_iccprofdata_sgraylen); +		break; +	default: +		prof = 0; +		break; +	} +	return prof; +} diff --git a/src/libjasper/base/jas_iccdata.c b/src/libjasper/base/jas_iccdata.c new file mode 100644 index 0000000..bf68bf0 --- /dev/null +++ b/src/libjasper/base/jas_iccdata.c @@ -0,0 +1,517 @@ +/* + * Copyright (c) 2002-2003 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__ + */ + +#include <jasper/jas_config.h> +#include <jasper/jas_types.h> + +uchar jas_iccprofdata_srgb[] = +{ +	0x00, 0x00, 0x0c, 0x48, 0x4c, 0x69, 0x6e, 0x6f, +	0x02, 0x10, 0x00, 0x00, 0x6d, 0x6e, 0x74, 0x72, +	0x52, 0x47, 0x42, 0x20, 0x58, 0x59, 0x5a, 0x20, +	0x07, 0xce, 0x00, 0x02, 0x00, 0x09, 0x00, 0x06, +	0x00, 0x31, 0x00, 0x00, 0x61, 0x63, 0x73, 0x70, +	0x4d, 0x53, 0x46, 0x54, 0x00, 0x00, 0x00, 0x00, +	0x49, 0x45, 0x43, 0x20, 0x73, 0x52, 0x47, 0x42, +	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf6, 0xd6, +	0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0xd3, 0x2d, +	0x48, 0x50, 0x20, 0x20, 0x00, 0x00, 0x00, 0x00, +	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +	0x00, 0x00, 0x00, 0x11, 0x63, 0x70, 0x72, 0x74, +	0x00, 0x00, 0x01, 0x50, 0x00, 0x00, 0x00, 0x33, +	0x64, 0x65, 0x73, 0x63, 0x00, 0x00, 0x01, 0x84, +	0x00, 0x00, 0x00, 0x6c, 0x77, 0x74, 0x70, 0x74, +	0x00, 0x00, 0x01, 0xf0, 0x00, 0x00, 0x00, 0x14, +	0x62, 0x6b, 0x70, 0x74, 0x00, 0x00, 0x02, 0x04, +	0x00, 0x00, 0x00, 0x14, 0x72, 0x58, 0x59, 0x5a, +	0x00, 0x00, 0x02, 0x18, 0x00, 0x00, 0x00, 0x14, +	0x67, 0x58, 0x59, 0x5a, 0x00, 0x00, 0x02, 0x2c, +	0x00, 0x00, 0x00, 0x14, 0x62, 0x58, 0x59, 0x5a, +	0x00, 0x00, 0x02, 0x40, 0x00, 0x00, 0x00, 0x14, +	0x64, 0x6d, 0x6e, 0x64, 0x00, 0x00, 0x02, 0x54, +	0x00, 0x00, 0x00, 0x70, 0x64, 0x6d, 0x64, 0x64, +	0x00, 0x00, 0x02, 0xc4, 0x00, 0x00, 0x00, 0x88, +	0x76, 0x75, 0x65, 0x64, 0x00, 0x00, 0x03, 0x4c, +	0x00, 0x00, 0x00, 0x86, 0x76, 0x69, 0x65, 0x77, +	0x00, 0x00, 0x03, 0xd4, 0x00, 0x00, 0x00, 0x24, +	0x6c, 0x75, 0x6d, 0x69, 0x00, 0x00, 0x03, 0xf8, +	0x00, 0x00, 0x00, 0x14, 0x6d, 0x65, 0x61, 0x73, +	0x00, 0x00, 0x04, 0x0c, 0x00, 0x00, 0x00, 0x24, +	0x74, 0x65, 0x63, 0x68, 0x00, 0x00, 0x04, 0x30, +	0x00, 0x00, 0x00, 0x0c, 0x72, 0x54, 0x52, 0x43, +	0x00, 0x00, 0x04, 0x3c, 0x00, 0x00, 0x08, 0x0c, +	0x67, 0x54, 0x52, 0x43, 0x00, 0x00, 0x04, 0x3c, +	0x00, 0x00, 0x08, 0x0c, 0x62, 0x54, 0x52, 0x43, +	0x00, 0x00, 0x04, 0x3c, 0x00, 0x00, 0x08, 0x0c, +	0x74, 0x65, 0x78, 0x74, 0x00, 0x00, 0x00, 0x00, +	0x43, 0x6f, 0x70, 0x79, 0x72, 0x69, 0x67, 0x68, +	0x74, 0x20, 0x28, 0x63, 0x29, 0x20, 0x31, 0x39, +	0x39, 0x38, 0x20, 0x48, 0x65, 0x77, 0x6c, 0x65, +	0x74, 0x74, 0x2d, 0x50, 0x61, 0x63, 0x6b, 0x61, +	0x72, 0x64, 0x20, 0x43, 0x6f, 0x6d, 0x70, 0x61, +	0x6e, 0x79, 0x00, 0x00, 0x64, 0x65, 0x73, 0x63, +	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, +	0x73, 0x52, 0x47, 0x42, 0x20, 0x49, 0x45, 0x43, +	0x36, 0x31, 0x39, 0x36, 0x36, 0x2d, 0x32, 0x2e, +	0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +	0x00, 0x00, 0x00, 0x00, 0x12, 0x73, 0x52, 0x47, +	0x42, 0x20, 0x49, 0x45, 0x43, 0x36, 0x31, 0x39, +	0x36, 0x36, 0x2d, 0x32, 0x2e, 0x31, 0x00, 0x00, +	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +	0x58, 0x59, 0x5a, 0x20, 0x00, 0x00, 0x00, 0x00, +	0x00, 0x00, 0xf3, 0x51, 0x00, 0x01, 0x00, 0x00, +	0x00, 0x01, 0x16, 0xcc, 0x58, 0x59, 0x5a, 0x20, +	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +	0x58, 0x59, 0x5a, 0x20, 0x00, 0x00, 0x00, 0x00, +	0x00, 0x00, 0x6f, 0xa2, 0x00, 0x00, 0x38, 0xf5, +	0x00, 0x00, 0x03, 0x90, 0x58, 0x59, 0x5a, 0x20, +	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x62, 0x99, +	0x00, 0x00, 0xb7, 0x85, 0x00, 0x00, 0x18, 0xda, +	0x58, 0x59, 0x5a, 0x20, 0x00, 0x00, 0x00, 0x00, +	0x00, 0x00, 0x24, 0xa0, 0x00, 0x00, 0x0f, 0x84, +	0x00, 0x00, 0xb6, 0xcf, 0x64, 0x65, 0x73, 0x63, +	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x16, +	0x49, 0x45, 0x43, 0x20, 0x68, 0x74, 0x74, 0x70, +	0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x69, +	0x65, 0x63, 0x2e, 0x63, 0x68, 0x00, 0x00, 0x00, +	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +	0x16, 0x49, 0x45, 0x43, 0x20, 0x68, 0x74, 0x74, +	0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, +	0x69, 0x65, 0x63, 0x2e, 0x63, 0x68, 0x00, 0x00, +	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +	0x00, 0x00, 0x00, 0x00, 0x64, 0x65, 0x73, 0x63, +	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2e, +	0x49, 0x45, 0x43, 0x20, 0x36, 0x31, 0x39, 0x36, +	0x36, 0x2d, 0x32, 0x2e, 0x31, 0x20, 0x44, 0x65, +	0x66, 0x61, 0x75, 0x6c, 0x74, 0x20, 0x52, 0x47, +	0x42, 0x20, 0x63, 0x6f, 0x6c, 0x6f, 0x75, 0x72, +	0x20, 0x73, 0x70, 0x61, 0x63, 0x65, 0x20, 0x2d, +	0x20, 0x73, 0x52, 0x47, 0x42, 0x00, 0x00, 0x00, +	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +	0x2e, 0x49, 0x45, 0x43, 0x20, 0x36, 0x31, 0x39, +	0x36, 0x36, 0x2d, 0x32, 0x2e, 0x31, 0x20, 0x44, +	0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x20, 0x52, +	0x47, 0x42, 0x20, 0x63, 0x6f, 0x6c, 0x6f, 0x75, +	0x72, 0x20, 0x73, 0x70, 0x61, 0x63, 0x65, 0x20, +	0x2d, 0x20, 0x73, 0x52, 0x47, 0x42, 0x00, 0x00, +	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +	0x00, 0x00, 0x00, 0x00, 0x64, 0x65, 0x73, 0x63, +	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2c, +	0x52, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, +	0x65, 0x20, 0x56, 0x69, 0x65, 0x77, 0x69, 0x6e, +	0x67, 0x20, 0x43, 0x6f, 0x6e, 0x64, 0x69, 0x74, +	0x69, 0x6f, 0x6e, 0x20, 0x69, 0x6e, 0x20, 0x49, +	0x45, 0x43, 0x36, 0x31, 0x39, 0x36, 0x36, 0x2d, +	0x32, 0x2e, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, +	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2c, 0x52, +	0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, +	0x20, 0x56, 0x69, 0x65, 0x77, 0x69, 0x6e, 0x67, +	0x20, 0x43, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, +	0x6f, 0x6e, 0x20, 0x69, 0x6e, 0x20, 0x49, 0x45, +	0x43, 0x36, 0x31, 0x39, 0x36, 0x36, 0x2d, 0x32, +	0x2e, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +	0x00, 0x00, 0x00, 0x00, 0x76, 0x69, 0x65, 0x77, +	0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0xa4, 0xfe, +	0x00, 0x14, 0x5f, 0x2e, 0x00, 0x10, 0xcf, 0x14, +	0x00, 0x03, 0xed, 0xcc, 0x00, 0x04, 0x13, 0x0b, +	0x00, 0x03, 0x5c, 0x9e, 0x00, 0x00, 0x00, 0x01, +	0x58, 0x59, 0x5a, 0x20, 0x00, 0x00, 0x00, 0x00, +	0x00, 0x4c, 0x09, 0x56, 0x00, 0x50, 0x00, 0x00, +	0x00, 0x57, 0x1f, 0xe7, 0x6d, 0x65, 0x61, 0x73, +	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, +	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +	0x00, 0x00, 0x02, 0x8f, 0x00, 0x00, 0x00, 0x02, +	0x73, 0x69, 0x67, 0x20, 0x00, 0x00, 0x00, 0x00, +	0x43, 0x52, 0x54, 0x20, 0x63, 0x75, 0x72, 0x76, +	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, +	0x00, 0x00, 0x00, 0x05, 0x00, 0x0a, 0x00, 0x0f, +	0x00, 0x14, 0x00, 0x19, 0x00, 0x1e, 0x00, 0x23, +	0x00, 0x28, 0x00, 0x2d, 0x00, 0x32, 0x00, 0x37, +	0x00, 0x3b, 0x00, 0x40, 0x00, 0x45, 0x00, 0x4a, +	0x00, 0x4f, 0x00, 0x54, 0x00, 0x59, 0x00, 0x5e, +	0x00, 0x63, 0x00, 0x68, 0x00, 0x6d, 0x00, 0x72, +	0x00, 0x77, 0x00, 0x7c, 0x00, 0x81, 0x00, 0x86, +	0x00, 0x8b, 0x00, 0x90, 0x00, 0x95, 0x00, 0x9a, +	0x00, 0x9f, 0x00, 0xa4, 0x00, 0xa9, 0x00, 0xae, +	0x00, 0xb2, 0x00, 0xb7, 0x00, 0xbc, 0x00, 0xc1, +	0x00, 0xc6, 0x00, 0xcb, 0x00, 0xd0, 0x00, 0xd5, +	0x00, 0xdb, 0x00, 0xe0, 0x00, 0xe5, 0x00, 0xeb, +	0x00, 0xf0, 0x00, 0xf6, 0x00, 0xfb, 0x01, 0x01, +	0x01, 0x07, 0x01, 0x0d, 0x01, 0x13, 0x01, 0x19, +	0x01, 0x1f, 0x01, 0x25, 0x01, 0x2b, 0x01, 0x32, +	0x01, 0x38, 0x01, 0x3e, 0x01, 0x45, 0x01, 0x4c, +	0x01, 0x52, 0x01, 0x59, 0x01, 0x60, 0x01, 0x67, +	0x01, 0x6e, 0x01, 0x75, 0x01, 0x7c, 0x01, 0x83, +	0x01, 0x8b, 0x01, 0x92, 0x01, 0x9a, 0x01, 0xa1, +	0x01, 0xa9, 0x01, 0xb1, 0x01, 0xb9, 0x01, 0xc1, +	0x01, 0xc9, 0x01, 0xd1, 0x01, 0xd9, 0x01, 0xe1, +	0x01, 0xe9, 0x01, 0xf2, 0x01, 0xfa, 0x02, 0x03, +	0x02, 0x0c, 0x02, 0x14, 0x02, 0x1d, 0x02, 0x26, +	0x02, 0x2f, 0x02, 0x38, 0x02, 0x41, 0x02, 0x4b, +	0x02, 0x54, 0x02, 0x5d, 0x02, 0x67, 0x02, 0x71, +	0x02, 0x7a, 0x02, 0x84, 0x02, 0x8e, 0x02, 0x98, +	0x02, 0xa2, 0x02, 0xac, 0x02, 0xb6, 0x02, 0xc1, +	0x02, 0xcb, 0x02, 0xd5, 0x02, 0xe0, 0x02, 0xeb, +	0x02, 0xf5, 0x03, 0x00, 0x03, 0x0b, 0x03, 0x16, +	0x03, 0x21, 0x03, 0x2d, 0x03, 0x38, 0x03, 0x43, +	0x03, 0x4f, 0x03, 0x5a, 0x03, 0x66, 0x03, 0x72, +	0x03, 0x7e, 0x03, 0x8a, 0x03, 0x96, 0x03, 0xa2, +	0x03, 0xae, 0x03, 0xba, 0x03, 0xc7, 0x03, 0xd3, +	0x03, 0xe0, 0x03, 0xec, 0x03, 0xf9, 0x04, 0x06, +	0x04, 0x13, 0x04, 0x20, 0x04, 0x2d, 0x04, 0x3b, +	0x04, 0x48, 0x04, 0x55, 0x04, 0x63, 0x04, 0x71, +	0x04, 0x7e, 0x04, 0x8c, 0x04, 0x9a, 0x04, 0xa8, +	0x04, 0xb6, 0x04, 0xc4, 0x04, 0xd3, 0x04, 0xe1, +	0x04, 0xf0, 0x04, 0xfe, 0x05, 0x0d, 0x05, 0x1c, +	0x05, 0x2b, 0x05, 0x3a, 0x05, 0x49, 0x05, 0x58, +	0x05, 0x67, 0x05, 0x77, 0x05, 0x86, 0x05, 0x96, +	0x05, 0xa6, 0x05, 0xb5, 0x05, 0xc5, 0x05, 0xd5, +	0x05, 0xe5, 0x05, 0xf6, 0x06, 0x06, 0x06, 0x16, +	0x06, 0x27, 0x06, 0x37, 0x06, 0x48, 0x06, 0x59, +	0x06, 0x6a, 0x06, 0x7b, 0x06, 0x8c, 0x06, 0x9d, +	0x06, 0xaf, 0x06, 0xc0, 0x06, 0xd1, 0x06, 0xe3, +	0x06, 0xf5, 0x07, 0x07, 0x07, 0x19, 0x07, 0x2b, +	0x07, 0x3d, 0x07, 0x4f, 0x07, 0x61, 0x07, 0x74, +	0x07, 0x86, 0x07, 0x99, 0x07, 0xac, 0x07, 0xbf, +	0x07, 0xd2, 0x07, 0xe5, 0x07, 0xf8, 0x08, 0x0b, +	0x08, 0x1f, 0x08, 0x32, 0x08, 0x46, 0x08, 0x5a, +	0x08, 0x6e, 0x08, 0x82, 0x08, 0x96, 0x08, 0xaa, +	0x08, 0xbe, 0x08, 0xd2, 0x08, 0xe7, 0x08, 0xfb, +	0x09, 0x10, 0x09, 0x25, 0x09, 0x3a, 0x09, 0x4f, +	0x09, 0x64, 0x09, 0x79, 0x09, 0x8f, 0x09, 0xa4, +	0x09, 0xba, 0x09, 0xcf, 0x09, 0xe5, 0x09, 0xfb, +	0x0a, 0x11, 0x0a, 0x27, 0x0a, 0x3d, 0x0a, 0x54, +	0x0a, 0x6a, 0x0a, 0x81, 0x0a, 0x98, 0x0a, 0xae, +	0x0a, 0xc5, 0x0a, 0xdc, 0x0a, 0xf3, 0x0b, 0x0b, +	0x0b, 0x22, 0x0b, 0x39, 0x0b, 0x51, 0x0b, 0x69, +	0x0b, 0x80, 0x0b, 0x98, 0x0b, 0xb0, 0x0b, 0xc8, +	0x0b, 0xe1, 0x0b, 0xf9, 0x0c, 0x12, 0x0c, 0x2a, +	0x0c, 0x43, 0x0c, 0x5c, 0x0c, 0x75, 0x0c, 0x8e, +	0x0c, 0xa7, 0x0c, 0xc0, 0x0c, 0xd9, 0x0c, 0xf3, +	0x0d, 0x0d, 0x0d, 0x26, 0x0d, 0x40, 0x0d, 0x5a, +	0x0d, 0x74, 0x0d, 0x8e, 0x0d, 0xa9, 0x0d, 0xc3, +	0x0d, 0xde, 0x0d, 0xf8, 0x0e, 0x13, 0x0e, 0x2e, +	0x0e, 0x49, 0x0e, 0x64, 0x0e, 0x7f, 0x0e, 0x9b, +	0x0e, 0xb6, 0x0e, 0xd2, 0x0e, 0xee, 0x0f, 0x09, +	0x0f, 0x25, 0x0f, 0x41, 0x0f, 0x5e, 0x0f, 0x7a, +	0x0f, 0x96, 0x0f, 0xb3, 0x0f, 0xcf, 0x0f, 0xec, +	0x10, 0x09, 0x10, 0x26, 0x10, 0x43, 0x10, 0x61, +	0x10, 0x7e, 0x10, 0x9b, 0x10, 0xb9, 0x10, 0xd7, +	0x10, 0xf5, 0x11, 0x13, 0x11, 0x31, 0x11, 0x4f, +	0x11, 0x6d, 0x11, 0x8c, 0x11, 0xaa, 0x11, 0xc9, +	0x11, 0xe8, 0x12, 0x07, 0x12, 0x26, 0x12, 0x45, +	0x12, 0x64, 0x12, 0x84, 0x12, 0xa3, 0x12, 0xc3, +	0x12, 0xe3, 0x13, 0x03, 0x13, 0x23, 0x13, 0x43, +	0x13, 0x63, 0x13, 0x83, 0x13, 0xa4, 0x13, 0xc5, +	0x13, 0xe5, 0x14, 0x06, 0x14, 0x27, 0x14, 0x49, +	0x14, 0x6a, 0x14, 0x8b, 0x14, 0xad, 0x14, 0xce, +	0x14, 0xf0, 0x15, 0x12, 0x15, 0x34, 0x15, 0x56, +	0x15, 0x78, 0x15, 0x9b, 0x15, 0xbd, 0x15, 0xe0, +	0x16, 0x03, 0x16, 0x26, 0x16, 0x49, 0x16, 0x6c, +	0x16, 0x8f, 0x16, 0xb2, 0x16, 0xd6, 0x16, 0xfa, +	0x17, 0x1d, 0x17, 0x41, 0x17, 0x65, 0x17, 0x89, +	0x17, 0xae, 0x17, 0xd2, 0x17, 0xf7, 0x18, 0x1b, +	0x18, 0x40, 0x18, 0x65, 0x18, 0x8a, 0x18, 0xaf, +	0x18, 0xd5, 0x18, 0xfa, 0x19, 0x20, 0x19, 0x45, +	0x19, 0x6b, 0x19, 0x91, 0x19, 0xb7, 0x19, 0xdd, +	0x1a, 0x04, 0x1a, 0x2a, 0x1a, 0x51, 0x1a, 0x77, +	0x1a, 0x9e, 0x1a, 0xc5, 0x1a, 0xec, 0x1b, 0x14, +	0x1b, 0x3b, 0x1b, 0x63, 0x1b, 0x8a, 0x1b, 0xb2, +	0x1b, 0xda, 0x1c, 0x02, 0x1c, 0x2a, 0x1c, 0x52, +	0x1c, 0x7b, 0x1c, 0xa3, 0x1c, 0xcc, 0x1c, 0xf5, +	0x1d, 0x1e, 0x1d, 0x47, 0x1d, 0x70, 0x1d, 0x99, +	0x1d, 0xc3, 0x1d, 0xec, 0x1e, 0x16, 0x1e, 0x40, +	0x1e, 0x6a, 0x1e, 0x94, 0x1e, 0xbe, 0x1e, 0xe9, +	0x1f, 0x13, 0x1f, 0x3e, 0x1f, 0x69, 0x1f, 0x94, +	0x1f, 0xbf, 0x1f, 0xea, 0x20, 0x15, 0x20, 0x41, +	0x20, 0x6c, 0x20, 0x98, 0x20, 0xc4, 0x20, 0xf0, +	0x21, 0x1c, 0x21, 0x48, 0x21, 0x75, 0x21, 0xa1, +	0x21, 0xce, 0x21, 0xfb, 0x22, 0x27, 0x22, 0x55, +	0x22, 0x82, 0x22, 0xaf, 0x22, 0xdd, 0x23, 0x0a, +	0x23, 0x38, 0x23, 0x66, 0x23, 0x94, 0x23, 0xc2, +	0x23, 0xf0, 0x24, 0x1f, 0x24, 0x4d, 0x24, 0x7c, +	0x24, 0xab, 0x24, 0xda, 0x25, 0x09, 0x25, 0x38, +	0x25, 0x68, 0x25, 0x97, 0x25, 0xc7, 0x25, 0xf7, +	0x26, 0x27, 0x26, 0x57, 0x26, 0x87, 0x26, 0xb7, +	0x26, 0xe8, 0x27, 0x18, 0x27, 0x49, 0x27, 0x7a, +	0x27, 0xab, 0x27, 0xdc, 0x28, 0x0d, 0x28, 0x3f, +	0x28, 0x71, 0x28, 0xa2, 0x28, 0xd4, 0x29, 0x06, +	0x29, 0x38, 0x29, 0x6b, 0x29, 0x9d, 0x29, 0xd0, +	0x2a, 0x02, 0x2a, 0x35, 0x2a, 0x68, 0x2a, 0x9b, +	0x2a, 0xcf, 0x2b, 0x02, 0x2b, 0x36, 0x2b, 0x69, +	0x2b, 0x9d, 0x2b, 0xd1, 0x2c, 0x05, 0x2c, 0x39, +	0x2c, 0x6e, 0x2c, 0xa2, 0x2c, 0xd7, 0x2d, 0x0c, +	0x2d, 0x41, 0x2d, 0x76, 0x2d, 0xab, 0x2d, 0xe1, +	0x2e, 0x16, 0x2e, 0x4c, 0x2e, 0x82, 0x2e, 0xb7, +	0x2e, 0xee, 0x2f, 0x24, 0x2f, 0x5a, 0x2f, 0x91, +	0x2f, 0xc7, 0x2f, 0xfe, 0x30, 0x35, 0x30, 0x6c, +	0x30, 0xa4, 0x30, 0xdb, 0x31, 0x12, 0x31, 0x4a, +	0x31, 0x82, 0x31, 0xba, 0x31, 0xf2, 0x32, 0x2a, +	0x32, 0x63, 0x32, 0x9b, 0x32, 0xd4, 0x33, 0x0d, +	0x33, 0x46, 0x33, 0x7f, 0x33, 0xb8, 0x33, 0xf1, +	0x34, 0x2b, 0x34, 0x65, 0x34, 0x9e, 0x34, 0xd8, +	0x35, 0x13, 0x35, 0x4d, 0x35, 0x87, 0x35, 0xc2, +	0x35, 0xfd, 0x36, 0x37, 0x36, 0x72, 0x36, 0xae, +	0x36, 0xe9, 0x37, 0x24, 0x37, 0x60, 0x37, 0x9c, +	0x37, 0xd7, 0x38, 0x14, 0x38, 0x50, 0x38, 0x8c, +	0x38, 0xc8, 0x39, 0x05, 0x39, 0x42, 0x39, 0x7f, +	0x39, 0xbc, 0x39, 0xf9, 0x3a, 0x36, 0x3a, 0x74, +	0x3a, 0xb2, 0x3a, 0xef, 0x3b, 0x2d, 0x3b, 0x6b, +	0x3b, 0xaa, 0x3b, 0xe8, 0x3c, 0x27, 0x3c, 0x65, +	0x3c, 0xa4, 0x3c, 0xe3, 0x3d, 0x22, 0x3d, 0x61, +	0x3d, 0xa1, 0x3d, 0xe0, 0x3e, 0x20, 0x3e, 0x60, +	0x3e, 0xa0, 0x3e, 0xe0, 0x3f, 0x21, 0x3f, 0x61, +	0x3f, 0xa2, 0x3f, 0xe2, 0x40, 0x23, 0x40, 0x64, +	0x40, 0xa6, 0x40, 0xe7, 0x41, 0x29, 0x41, 0x6a, +	0x41, 0xac, 0x41, 0xee, 0x42, 0x30, 0x42, 0x72, +	0x42, 0xb5, 0x42, 0xf7, 0x43, 0x3a, 0x43, 0x7d, +	0x43, 0xc0, 0x44, 0x03, 0x44, 0x47, 0x44, 0x8a, +	0x44, 0xce, 0x45, 0x12, 0x45, 0x55, 0x45, 0x9a, +	0x45, 0xde, 0x46, 0x22, 0x46, 0x67, 0x46, 0xab, +	0x46, 0xf0, 0x47, 0x35, 0x47, 0x7b, 0x47, 0xc0, +	0x48, 0x05, 0x48, 0x4b, 0x48, 0x91, 0x48, 0xd7, +	0x49, 0x1d, 0x49, 0x63, 0x49, 0xa9, 0x49, 0xf0, +	0x4a, 0x37, 0x4a, 0x7d, 0x4a, 0xc4, 0x4b, 0x0c, +	0x4b, 0x53, 0x4b, 0x9a, 0x4b, 0xe2, 0x4c, 0x2a, +	0x4c, 0x72, 0x4c, 0xba, 0x4d, 0x02, 0x4d, 0x4a, +	0x4d, 0x93, 0x4d, 0xdc, 0x4e, 0x25, 0x4e, 0x6e, +	0x4e, 0xb7, 0x4f, 0x00, 0x4f, 0x49, 0x4f, 0x93, +	0x4f, 0xdd, 0x50, 0x27, 0x50, 0x71, 0x50, 0xbb, +	0x51, 0x06, 0x51, 0x50, 0x51, 0x9b, 0x51, 0xe6, +	0x52, 0x31, 0x52, 0x7c, 0x52, 0xc7, 0x53, 0x13, +	0x53, 0x5f, 0x53, 0xaa, 0x53, 0xf6, 0x54, 0x42, +	0x54, 0x8f, 0x54, 0xdb, 0x55, 0x28, 0x55, 0x75, +	0x55, 0xc2, 0x56, 0x0f, 0x56, 0x5c, 0x56, 0xa9, +	0x56, 0xf7, 0x57, 0x44, 0x57, 0x92, 0x57, 0xe0, +	0x58, 0x2f, 0x58, 0x7d, 0x58, 0xcb, 0x59, 0x1a, +	0x59, 0x69, 0x59, 0xb8, 0x5a, 0x07, 0x5a, 0x56, +	0x5a, 0xa6, 0x5a, 0xf5, 0x5b, 0x45, 0x5b, 0x95, +	0x5b, 0xe5, 0x5c, 0x35, 0x5c, 0x86, 0x5c, 0xd6, +	0x5d, 0x27, 0x5d, 0x78, 0x5d, 0xc9, 0x5e, 0x1a, +	0x5e, 0x6c, 0x5e, 0xbd, 0x5f, 0x0f, 0x5f, 0x61, +	0x5f, 0xb3, 0x60, 0x05, 0x60, 0x57, 0x60, 0xaa, +	0x60, 0xfc, 0x61, 0x4f, 0x61, 0xa2, 0x61, 0xf5, +	0x62, 0x49, 0x62, 0x9c, 0x62, 0xf0, 0x63, 0x43, +	0x63, 0x97, 0x63, 0xeb, 0x64, 0x40, 0x64, 0x94, +	0x64, 0xe9, 0x65, 0x3d, 0x65, 0x92, 0x65, 0xe7, +	0x66, 0x3d, 0x66, 0x92, 0x66, 0xe8, 0x67, 0x3d, +	0x67, 0x93, 0x67, 0xe9, 0x68, 0x3f, 0x68, 0x96, +	0x68, 0xec, 0x69, 0x43, 0x69, 0x9a, 0x69, 0xf1, +	0x6a, 0x48, 0x6a, 0x9f, 0x6a, 0xf7, 0x6b, 0x4f, +	0x6b, 0xa7, 0x6b, 0xff, 0x6c, 0x57, 0x6c, 0xaf, +	0x6d, 0x08, 0x6d, 0x60, 0x6d, 0xb9, 0x6e, 0x12, +	0x6e, 0x6b, 0x6e, 0xc4, 0x6f, 0x1e, 0x6f, 0x78, +	0x6f, 0xd1, 0x70, 0x2b, 0x70, 0x86, 0x70, 0xe0, +	0x71, 0x3a, 0x71, 0x95, 0x71, 0xf0, 0x72, 0x4b, +	0x72, 0xa6, 0x73, 0x01, 0x73, 0x5d, 0x73, 0xb8, +	0x74, 0x14, 0x74, 0x70, 0x74, 0xcc, 0x75, 0x28, +	0x75, 0x85, 0x75, 0xe1, 0x76, 0x3e, 0x76, 0x9b, +	0x76, 0xf8, 0x77, 0x56, 0x77, 0xb3, 0x78, 0x11, +	0x78, 0x6e, 0x78, 0xcc, 0x79, 0x2a, 0x79, 0x89, +	0x79, 0xe7, 0x7a, 0x46, 0x7a, 0xa5, 0x7b, 0x04, +	0x7b, 0x63, 0x7b, 0xc2, 0x7c, 0x21, 0x7c, 0x81, +	0x7c, 0xe1, 0x7d, 0x41, 0x7d, 0xa1, 0x7e, 0x01, +	0x7e, 0x62, 0x7e, 0xc2, 0x7f, 0x23, 0x7f, 0x84, +	0x7f, 0xe5, 0x80, 0x47, 0x80, 0xa8, 0x81, 0x0a, +	0x81, 0x6b, 0x81, 0xcd, 0x82, 0x30, 0x82, 0x92, +	0x82, 0xf4, 0x83, 0x57, 0x83, 0xba, 0x84, 0x1d, +	0x84, 0x80, 0x84, 0xe3, 0x85, 0x47, 0x85, 0xab, +	0x86, 0x0e, 0x86, 0x72, 0x86, 0xd7, 0x87, 0x3b, +	0x87, 0x9f, 0x88, 0x04, 0x88, 0x69, 0x88, 0xce, +	0x89, 0x33, 0x89, 0x99, 0x89, 0xfe, 0x8a, 0x64, +	0x8a, 0xca, 0x8b, 0x30, 0x8b, 0x96, 0x8b, 0xfc, +	0x8c, 0x63, 0x8c, 0xca, 0x8d, 0x31, 0x8d, 0x98, +	0x8d, 0xff, 0x8e, 0x66, 0x8e, 0xce, 0x8f, 0x36, +	0x8f, 0x9e, 0x90, 0x06, 0x90, 0x6e, 0x90, 0xd6, +	0x91, 0x3f, 0x91, 0xa8, 0x92, 0x11, 0x92, 0x7a, +	0x92, 0xe3, 0x93, 0x4d, 0x93, 0xb6, 0x94, 0x20, +	0x94, 0x8a, 0x94, 0xf4, 0x95, 0x5f, 0x95, 0xc9, +	0x96, 0x34, 0x96, 0x9f, 0x97, 0x0a, 0x97, 0x75, +	0x97, 0xe0, 0x98, 0x4c, 0x98, 0xb8, 0x99, 0x24, +	0x99, 0x90, 0x99, 0xfc, 0x9a, 0x68, 0x9a, 0xd5, +	0x9b, 0x42, 0x9b, 0xaf, 0x9c, 0x1c, 0x9c, 0x89, +	0x9c, 0xf7, 0x9d, 0x64, 0x9d, 0xd2, 0x9e, 0x40, +	0x9e, 0xae, 0x9f, 0x1d, 0x9f, 0x8b, 0x9f, 0xfa, +	0xa0, 0x69, 0xa0, 0xd8, 0xa1, 0x47, 0xa1, 0xb6, +	0xa2, 0x26, 0xa2, 0x96, 0xa3, 0x06, 0xa3, 0x76, +	0xa3, 0xe6, 0xa4, 0x56, 0xa4, 0xc7, 0xa5, 0x38, +	0xa5, 0xa9, 0xa6, 0x1a, 0xa6, 0x8b, 0xa6, 0xfd, +	0xa7, 0x6e, 0xa7, 0xe0, 0xa8, 0x52, 0xa8, 0xc4, +	0xa9, 0x37, 0xa9, 0xa9, 0xaa, 0x1c, 0xaa, 0x8f, +	0xab, 0x02, 0xab, 0x75, 0xab, 0xe9, 0xac, 0x5c, +	0xac, 0xd0, 0xad, 0x44, 0xad, 0xb8, 0xae, 0x2d, +	0xae, 0xa1, 0xaf, 0x16, 0xaf, 0x8b, 0xb0, 0x00, +	0xb0, 0x75, 0xb0, 0xea, 0xb1, 0x60, 0xb1, 0xd6, +	0xb2, 0x4b, 0xb2, 0xc2, 0xb3, 0x38, 0xb3, 0xae, +	0xb4, 0x25, 0xb4, 0x9c, 0xb5, 0x13, 0xb5, 0x8a, +	0xb6, 0x01, 0xb6, 0x79, 0xb6, 0xf0, 0xb7, 0x68, +	0xb7, 0xe0, 0xb8, 0x59, 0xb8, 0xd1, 0xb9, 0x4a, +	0xb9, 0xc2, 0xba, 0x3b, 0xba, 0xb5, 0xbb, 0x2e, +	0xbb, 0xa7, 0xbc, 0x21, 0xbc, 0x9b, 0xbd, 0x15, +	0xbd, 0x8f, 0xbe, 0x0a, 0xbe, 0x84, 0xbe, 0xff, +	0xbf, 0x7a, 0xbf, 0xf5, 0xc0, 0x70, 0xc0, 0xec, +	0xc1, 0x67, 0xc1, 0xe3, 0xc2, 0x5f, 0xc2, 0xdb, +	0xc3, 0x58, 0xc3, 0xd4, 0xc4, 0x51, 0xc4, 0xce, +	0xc5, 0x4b, 0xc5, 0xc8, 0xc6, 0x46, 0xc6, 0xc3, +	0xc7, 0x41, 0xc7, 0xbf, 0xc8, 0x3d, 0xc8, 0xbc, +	0xc9, 0x3a, 0xc9, 0xb9, 0xca, 0x38, 0xca, 0xb7, +	0xcb, 0x36, 0xcb, 0xb6, 0xcc, 0x35, 0xcc, 0xb5, +	0xcd, 0x35, 0xcd, 0xb5, 0xce, 0x36, 0xce, 0xb6, +	0xcf, 0x37, 0xcf, 0xb8, 0xd0, 0x39, 0xd0, 0xba, +	0xd1, 0x3c, 0xd1, 0xbe, 0xd2, 0x3f, 0xd2, 0xc1, +	0xd3, 0x44, 0xd3, 0xc6, 0xd4, 0x49, 0xd4, 0xcb, +	0xd5, 0x4e, 0xd5, 0xd1, 0xd6, 0x55, 0xd6, 0xd8, +	0xd7, 0x5c, 0xd7, 0xe0, 0xd8, 0x64, 0xd8, 0xe8, +	0xd9, 0x6c, 0xd9, 0xf1, 0xda, 0x76, 0xda, 0xfb, +	0xdb, 0x80, 0xdc, 0x05, 0xdc, 0x8a, 0xdd, 0x10, +	0xdd, 0x96, 0xde, 0x1c, 0xde, 0xa2, 0xdf, 0x29, +	0xdf, 0xaf, 0xe0, 0x36, 0xe0, 0xbd, 0xe1, 0x44, +	0xe1, 0xcc, 0xe2, 0x53, 0xe2, 0xdb, 0xe3, 0x63, +	0xe3, 0xeb, 0xe4, 0x73, 0xe4, 0xfc, 0xe5, 0x84, +	0xe6, 0x0d, 0xe6, 0x96, 0xe7, 0x1f, 0xe7, 0xa9, +	0xe8, 0x32, 0xe8, 0xbc, 0xe9, 0x46, 0xe9, 0xd0, +	0xea, 0x5b, 0xea, 0xe5, 0xeb, 0x70, 0xeb, 0xfb, +	0xec, 0x86, 0xed, 0x11, 0xed, 0x9c, 0xee, 0x28, +	0xee, 0xb4, 0xef, 0x40, 0xef, 0xcc, 0xf0, 0x58, +	0xf0, 0xe5, 0xf1, 0x72, 0xf1, 0xff, 0xf2, 0x8c, +	0xf3, 0x19, 0xf3, 0xa7, 0xf4, 0x34, 0xf4, 0xc2, +	0xf5, 0x50, 0xf5, 0xde, 0xf6, 0x6d, 0xf6, 0xfb, +	0xf7, 0x8a, 0xf8, 0x19, 0xf8, 0xa8, 0xf9, 0x38, +	0xf9, 0xc7, 0xfa, 0x57, 0xfa, 0xe7, 0xfb, 0x77, +	0xfc, 0x07, 0xfc, 0x98, 0xfd, 0x29, 0xfd, 0xba, +	0xfe, 0x4b, 0xfe, 0xdc, 0xff, 0x6d, 0xff, 0xff +}; + +int jas_iccprofdata_srgblen = sizeof(jas_iccprofdata_srgb); + +uchar jas_iccprofdata_sgray[] = { +	0x00, 0x00, 0x01, 0x8a, 0x00, 0x00, 0x00, 0x00, +	0x02, 0x20, 0x00, 0x00, 0x73, 0x63, 0x6e, 0x72, +	0x47, 0x52, 0x41, 0x59, 0x58, 0x59, 0x5a, 0x20, +	0x07, 0xd3, 0x00, 0x01, 0x00, 0x1f, 0x00, 0x0d, +	0x00, 0x35, 0x00, 0x21, 0x61, 0x63, 0x73, 0x70, +	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, +	0x4b, 0x4f, 0x44, 0x41, 0x73, 0x47, 0x72, 0x79, +	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf6, 0xd6, +	0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0xd3, 0x2d, +	0x4a, 0x50, 0x45, 0x47, 0x00, 0x00, 0x00, 0x00, +	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +	0x00, 0x00, 0x00, 0x04, 0x64, 0x65, 0x73, 0x63, +	0x00, 0x00, 0x00, 0xb4, 0x00, 0x00, 0x00, 0x86, +	0x63, 0x70, 0x72, 0x74, 0x00, 0x00, 0x01, 0x3c, +	0x00, 0x00, 0x00, 0x2b, 0x77, 0x74, 0x70, 0x74, +	0x00, 0x00, 0x01, 0x68, 0x00, 0x00, 0x00, 0x14, +	0x6b, 0x54, 0x52, 0x43, 0x00, 0x00, 0x01, 0x7c, +	0x00, 0x00, 0x00, 0x0e, 0x64, 0x65, 0x73, 0x63, +	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2c, +	0x52, 0x65, 0x73, 0x74, 0x72, 0x69, 0x63, 0x74, +	0x65, 0x64, 0x20, 0x49, 0x43, 0x43, 0x20, 0x70, +	0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x20, 0x64, +	0x65, 0x73, 0x63, 0x72, 0x69, 0x62, 0x69, 0x6e, +	0x67, 0x20, 0x73, 0x52, 0x47, 0x42, 0x2d, 0x67, +	0x72, 0x65, 0x79, 0x00, 0x00, 0x00, 0x00, 0x00, +	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +	0x00, 0x00, 0x00, 0x00, 0x74, 0x65, 0x78, 0x74, +	0x00, 0x00, 0x00, 0x00, 0x43, 0x6f, 0x70, 0x79, +	0x72, 0x69, 0x67, 0x68, 0x74, 0x20, 0x32, 0x30, +	0x30, 0x33, 0x20, 0x73, 0x52, 0x47, 0x42, 0x2d, +	0x67, 0x72, 0x65, 0x79, 0x20, 0x52, 0x65, 0x66, +	0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x00, 0x00, +	0x58, 0x59, 0x5a, 0x20, 0x00, 0x00, 0x00, 0x00, +	0x00, 0x00, 0xf3, 0x54, 0x00, 0x01, 0x00, 0x00, +	0x00, 0x01, 0x16, 0xcf, 0x63, 0x75, 0x72, 0x76, +	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, +	0x01, 0xcd +}; + +int jas_iccprofdata_sgraylen = sizeof(jas_iccprofdata_sgray); diff --git a/src/libjasper/base/jas_image.c b/src/libjasper/base/jas_image.c new file mode 100644 index 0000000..3f5af8c --- /dev/null +++ b/src/libjasper/base/jas_image.c @@ -0,0 +1,1516 @@ +/* + * 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 <dima@dimin.net> +   11/07/2003 15:00 - dima - aux_buf added for j_image_t +   22/09/2003 14:40 - dima - small correction in jas_image_writecmpt +   2007-04-23 12:23 - dima - updated for a vector of metadata boxes + */ + +/* __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__ + */ + +/* + * Image Library + * + * $Id: jas_image.c,v 1.1 2008/10/17 06:14:59 scuri Exp $ + */ + +/******************************************************************************\ +* Includes. +\******************************************************************************/ + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <assert.h> +#include <ctype.h> + +#include "jasper/jas_math.h" +#include "jasper/jas_image.h" +#include "jasper/jas_malloc.h" +#include "jasper/jas_string.h" + +/******************************************************************************\ +* GeoJasper: dima - progress functions +\******************************************************************************/ + +#if !defined( JAS_PROGRESS_PROC_DEFINED ) +  #define JAS_PROGRESS_PROC_DEFINED +  jas_progress_proc_t   progress_proc   = NULL; +  jas_test_abort_proc_t test_abort_proc = NULL; +#endif + +void jas_set_progress_proc( jas_progress_proc_t new_proc ) { +  progress_proc = new_proc; +} + +void jas_do_progress( int done, int total, char *descr ) { +  if (progress_proc != NULL) progress_proc( done, total, descr ); +} + +void jas_set_test_abort_proc( jas_test_abort_proc_t new_proc ) { +  test_abort_proc = new_proc; +} + +int jas_test_abort( ) { +  if (test_abort_proc != NULL) return test_abort_proc(); +  else return 0; +} + +/******************************************************************************\ +* Types. +\******************************************************************************/ + +#define	FLOORDIV(x, y) ((x) / (y)) + +/******************************************************************************\ +* Local prototypes. +\******************************************************************************/ + +static jas_image_cmpt_t *jas_image_cmpt_create0(void); +static void jas_image_cmpt_destroy(jas_image_cmpt_t *cmpt); +static jas_image_cmpt_t *jas_image_cmpt_create(uint_fast32_t tlx, uint_fast32_t tly, +  uint_fast32_t hstep, uint_fast32_t vstep, uint_fast32_t width, uint_fast32_t +  height, uint_fast16_t depth, bool sgnd, uint_fast32_t inmem); +static void jas_image_setbbox(jas_image_t *image); +static jas_image_cmpt_t *jas_image_cmpt_copy(jas_image_cmpt_t *cmpt); +static int jas_image_growcmpts(jas_image_t *image, int maxcmpts); +static uint_fast32_t inttobits(jas_seqent_t v, int prec, bool sgnd); +static jas_seqent_t bitstoint(uint_fast32_t v, int prec, bool sgnd); +static int putint(jas_stream_t *out, int sgnd, int prec, long val); +static int getint(jas_stream_t *in, int sgnd, int prec, long *val); +static void jas_image_calcbbox2(jas_image_t *image, jas_image_coord_t *tlx, +  jas_image_coord_t *tly, jas_image_coord_t *brx, jas_image_coord_t *bry); +static long uptomult(long x, long y); +static long downtomult(long x, long y); +static long convert(long val, int oldsgnd, int oldprec, int newsgnd, +  int newprec); +static void jas_image_calcbbox2(jas_image_t *image, jas_image_coord_t *tlx, +  jas_image_coord_t *tly, jas_image_coord_t *brx, jas_image_coord_t *bry); + +/******************************************************************************\ +* Global data. +\******************************************************************************/ + +static int jas_image_numfmts = 0; +static jas_image_fmtinfo_t jas_image_fmtinfos[JAS_IMAGE_MAXFMTS]; + +/******************************************************************************\ +* Create and destroy operations. +\******************************************************************************/ + +jas_image_t *jas_image_create(int numcmpts, jas_image_cmptparm_t *cmptparms, +  int clrspc) +{ +	jas_image_t *image; +	uint_fast32_t rawsize; +	uint_fast32_t inmem; +	int cmptno; +	jas_image_cmptparm_t *cmptparm; + +	if (!(image = jas_image_create0())) { +		return 0; +	} + +	image->clrspc_ = clrspc; +	image->maxcmpts_ = numcmpts; +	image->inmem_ = true; + +	/* Allocate memory for the per-component information. */ +	if (!(image->cmpts_ = jas_malloc(image->maxcmpts_ * +	  sizeof(jas_image_cmpt_t *)))) { +		jas_image_destroy(image); +		return 0; +	} +	/* Initialize in case of failure. */ +	for (cmptno = 0; cmptno < image->maxcmpts_; ++cmptno) { +		image->cmpts_[cmptno] = 0; +	} + +	/* Compute the approximate raw size of the image. */ +	rawsize = 0; +	for (cmptno = 0, cmptparm = cmptparms; cmptno < numcmpts; ++cmptno, +	  ++cmptparm) { +		rawsize += cmptparm->width * cmptparm->height * +		  (cmptparm->prec + 7) / 8; +	} +	/* Decide whether to buffer the image data in memory, based on the +	  raw size of the image. */ +	inmem = (rawsize < JAS_IMAGE_INMEMTHRESH); + +	/* Create the individual image components. */ +	for (cmptno = 0, cmptparm = cmptparms; cmptno < numcmpts; ++cmptno, +	  ++cmptparm) { +		if (!(image->cmpts_[cmptno] = jas_image_cmpt_create(cmptparm->tlx, +		  cmptparm->tly, cmptparm->hstep, cmptparm->vstep, +		  cmptparm->width, cmptparm->height, cmptparm->prec, +		  cmptparm->sgnd, inmem))) { +			jas_image_destroy(image); +			return 0; +		} +		++image->numcmpts_; +	} + +	/* Determine the bounding box for all of the components on the +	  reference grid (i.e., the image area) */ +	jas_image_setbbox(image); + +	return image; +} + +// GeoJasper: begin - dima - metadata box buffer utils +jas_metadata_box_t jas_box_init( void ) { +  jas_metadata_box_t box; +  memset( (void *)box.id, 0, 16 ); +  box.size = 0; +  box.buf  = NULL; +  return box; +} + +bool jas_box_alloc ( jas_metadata_box_t *box, unsigned long size ) { +  if (box == NULL) return false; +  *box = jas_box_init();         +  if ( box->buf = (uint_fast8_t *) jas_malloc( size ) ) +    box->size = size; +  return (bool) box->buf; +} + +void jas_box_free( jas_metadata_box_t *box ) { +  if (box == NULL) return; +  if ( (box->size != 0) && (box->buf != NULL) ) +    jas_free(box->buf); +  *box = jas_box_init(); +} +// GeoJasper: end   - dima - metadata box buffer utils + +jas_image_t *jas_image_create0() +{ +	jas_image_t *image; + +	if (!(image = jas_malloc(sizeof(jas_image_t)))) { +		return 0; +	} + +	image->tlx_ = 0; +	image->tly_ = 0; +	image->brx_ = 0; +	image->bry_ = 0; +	image->clrspc_ = JAS_CLRSPC_UNKNOWN; +	image->numcmpts_ = 0; +	image->maxcmpts_ = 0; +	image->cmpts_ = 0; +	image->inmem_ = true; +	image->cmprof_ = 0; + +  // GeoJasper: begin - dima - buffer defines +  { +    int i; +    image->metadata.count = JAS_IMAGE_NUM_BOXES; +    for (i=0; i<image->metadata.count; ++i) +      image->metadata.boxes[i] = jas_box_init(); +  } +  // GeoJasper: end - dima - buffer defines + +	return image; +} + +jas_image_t *jas_image_copy(jas_image_t *image) +{ +	jas_image_t *newimage; +	int cmptno; + +	newimage = jas_image_create0(); +	if (jas_image_growcmpts(newimage, image->numcmpts_)) { +		goto error; +	} +	for (cmptno = 0; cmptno < image->numcmpts_; ++cmptno) { +		if (!(newimage->cmpts_[cmptno] = jas_image_cmpt_copy(image->cmpts_[cmptno]))) { +			goto error; +		} +		++newimage->numcmpts_; +	} + +	jas_image_setbbox(newimage); + +	if (image->cmprof_) { +		if (!(newimage->cmprof_ = jas_cmprof_copy(image->cmprof_))) +			goto error; +	} + +	return newimage; +error: +	if (newimage) { +		jas_image_destroy(newimage); +	} +	return 0; +} + +static jas_image_cmpt_t *jas_image_cmpt_create0() +{ +	jas_image_cmpt_t *cmpt; +	if (!(cmpt = jas_malloc(sizeof(jas_image_cmpt_t)))) { +		return 0; +	} +	memset(cmpt, 0, sizeof(jas_image_cmpt_t)); +	cmpt->type_ = JAS_IMAGE_CT_UNKNOWN; +	return cmpt; +} + +static jas_image_cmpt_t *jas_image_cmpt_copy(jas_image_cmpt_t *cmpt) +{ +	jas_image_cmpt_t *newcmpt; + +	if (!(newcmpt = jas_image_cmpt_create0())) { +		return 0; +	} +	newcmpt->tlx_ = cmpt->tlx_; +	newcmpt->tly_ = cmpt->tly_; +	newcmpt->hstep_ = cmpt->hstep_; +	newcmpt->vstep_ = cmpt->vstep_; +	newcmpt->width_ = cmpt->width_; +	newcmpt->height_ = cmpt->height_; +	newcmpt->prec_ = cmpt->prec_; +	newcmpt->sgnd_ = cmpt->sgnd_; +	newcmpt->cps_ = cmpt->cps_; +	newcmpt->type_ = cmpt->type_; +	if (!(newcmpt->stream_ = jas_stream_memopen(0, 0))) { +		return 0; +	} +	if (jas_stream_seek(cmpt->stream_, 0, SEEK_SET)) { +		return 0; +	} +	if (jas_stream_copy(newcmpt->stream_, cmpt->stream_, -1)) { +		return 0; +	} +	if (jas_stream_seek(newcmpt->stream_, 0, SEEK_SET)) { +		return 0; +	} +	return newcmpt; +} + +void jas_image_destroy(jas_image_t *image) +{ +	int i; + +  // GeoJasper: begin - dima - free buffers +  for (i=0; i<image->metadata.count; ++i) +    jas_box_free( &image->metadata.boxes[i] ); +  // GeoJasper: end - dima - free buffers + +	if (image->cmpts_) { +		for (i = 0; i < image->numcmpts_; ++i) { +			jas_image_cmpt_destroy(image->cmpts_[i]); +			image->cmpts_[i] = 0; +		} +		jas_free(image->cmpts_); +	} +	if (image->cmprof_) +		jas_cmprof_destroy(image->cmprof_); +	jas_free(image); +} + +static jas_image_cmpt_t *jas_image_cmpt_create(uint_fast32_t tlx, uint_fast32_t tly, +  uint_fast32_t hstep, uint_fast32_t vstep, uint_fast32_t width, uint_fast32_t +  height, uint_fast16_t depth, bool sgnd, uint_fast32_t inmem) +{ +	jas_image_cmpt_t *cmpt; +	long size; + +	if (!(cmpt = jas_malloc(sizeof(jas_image_cmpt_t)))) { +		return 0; +	} + +	cmpt->type_ = JAS_IMAGE_CT_UNKNOWN; +	cmpt->tlx_ = tlx; +	cmpt->tly_ = tly; +	cmpt->hstep_ = hstep; +	cmpt->vstep_ = vstep; +	cmpt->width_ = width; +	cmpt->height_ = height; +	cmpt->prec_ = depth; +	cmpt->sgnd_ = sgnd; +	cmpt->stream_ = 0; +	cmpt->cps_ = (depth + 7) / 8; + +	size = cmpt->width_ * cmpt->height_ * cmpt->cps_; +	cmpt->stream_ = (inmem) ? jas_stream_memopen(0, size) : jas_stream_tmpfile(); +	if (!cmpt->stream_) { +		jas_image_cmpt_destroy(cmpt); +		return 0; +	} + +	/* Zero the component data.  This isn't necessary, but it is +	convenient for debugging purposes. */ +	if (jas_stream_seek(cmpt->stream_, size - 1, SEEK_SET) < 0 || +	  jas_stream_putc(cmpt->stream_, 0) == EOF || +	  jas_stream_seek(cmpt->stream_, 0, SEEK_SET) < 0) { +		jas_image_cmpt_destroy(cmpt); +		return 0; +	} + +	return cmpt; +} + +static void jas_image_cmpt_destroy(jas_image_cmpt_t *cmpt) +{ +	if (cmpt->stream_) { +		jas_stream_close(cmpt->stream_); +	} +	jas_free(cmpt); +} + +/******************************************************************************\ +* Load and save operations. +\******************************************************************************/ + +jas_image_t *jas_image_decode(jas_stream_t *in, int fmt, char *optstr) +{ +	jas_image_fmtinfo_t *fmtinfo; +	jas_image_t *image; + +	image = 0; + +	/* If possible, try to determine the format of the input data. */ +	if (fmt < 0) { +		if ((fmt = jas_image_getfmt(in)) < 0) +			goto error; +	} + +	/* Is it possible to decode an image represented in this format? */ +	if (!(fmtinfo = jas_image_lookupfmtbyid(fmt))) +		goto error; +	if (!fmtinfo->ops.decode) +		goto error; + +	/* Decode the image. */ +	if (!(image = (*fmtinfo->ops.decode)(in, optstr))) +		goto error; + +	/* Create a color profile if needed. */ +	if (!jas_clrspc_isunknown(image->clrspc_) && +	  !jas_clrspc_isgeneric(image->clrspc_) && !image->cmprof_) { +		if (!(image->cmprof_ = +		  jas_cmprof_createfromclrspc(jas_image_clrspc(image)))) +			goto error; +	} + +	return image; +error: +	if (image) +		jas_image_destroy(image); +	return 0; +} + +int jas_image_encode(jas_image_t *image, jas_stream_t *out, int fmt, char *optstr) +{ +	jas_image_fmtinfo_t *fmtinfo; +	if (!(fmtinfo = jas_image_lookupfmtbyid(fmt))) { +		return -1; +	} +	return (fmtinfo->ops.encode) ? (*fmtinfo->ops.encode)(image, out, +	  optstr) : (-1); +} + +/******************************************************************************\ +* Component read and write operations. +\******************************************************************************/ + +int jas_image_readcmpt(jas_image_t *image, int cmptno, jas_image_coord_t x, +  jas_image_coord_t y, jas_image_coord_t width, jas_image_coord_t height, +  jas_matrix_t *data) +{ +	jas_image_cmpt_t *cmpt; +	jas_image_coord_t i; +	jas_image_coord_t j; +	int k; +	jas_seqent_t v; +	int c; +	jas_seqent_t *dr; +	jas_seqent_t *d; +	int drs; + +	if (cmptno < 0 || cmptno >= image->numcmpts_) { +		return -1; +	} + +	cmpt = image->cmpts_[cmptno]; +	if (x >= cmpt->width_ || y >= cmpt->height_ || +	  x + width > cmpt->width_ || +	  y + height > cmpt->height_) { +		return -1; +	} + +	if (jas_matrix_numrows(data) != height || jas_matrix_numcols(data) != width) { +		if (jas_matrix_resize(data, height, width)) { +			return -1; +		} +	} + +	dr = jas_matrix_getref(data, 0, 0); +	drs = jas_matrix_rowstep(data); +	for (i = 0; i < height; ++i, dr += drs) { +		d = dr; +		if (jas_stream_seek(cmpt->stream_, (cmpt->width_ * (y + i) + x) +		  * cmpt->cps_, SEEK_SET) < 0) { +			return -1; +		} +		for (j = width; j > 0; --j, ++d) { +			v = 0; +			for (k = cmpt->cps_; k > 0; --k) { +				if ((c = jas_stream_getc(cmpt->stream_)) == EOF) { +					return -1; +				} +				v = (v << 8) | (c & 0xff); +			} +			*d = bitstoint(v, cmpt->prec_, cmpt->sgnd_); +		} +	} + +	return 0; +} + +int jas_image_writecmpt(jas_image_t *image, int cmptno, jas_image_coord_t x, jas_image_coord_t y, jas_image_coord_t width, +  jas_image_coord_t height, jas_matrix_t *data) +{ +	jas_image_cmpt_t *cmpt; +	jas_image_coord_t i; +	jas_image_coord_t j; +	jas_seqent_t *d; +	jas_seqent_t *dr; +	int drs; +	jas_seqent_t v; +	int k; +	int c; + +	if (cmptno < 0 || cmptno >= image->numcmpts_) { +		return -1; +	} + +	cmpt = image->cmpts_[cmptno]; +	if (x >= cmpt->width_ || y >= cmpt->height_ || +	  x + width > cmpt->width_ || +	  y + height > cmpt->height_) { +		return -1; +	} + +	if (jas_matrix_numrows(data) < height || jas_matrix_numcols(data) < width) { +		return -1; +	}	// GeoJasper: dima, change != to < + +	dr = jas_matrix_getref(data, 0, 0); +	drs = jas_matrix_rowstep(data); +	for (i = 0; i < height; ++i, dr += drs) { +		d = dr; +		if (jas_stream_seek(cmpt->stream_, (cmpt->width_ * (y + i) + x) +		  * cmpt->cps_, SEEK_SET) < 0) { +			return -1; +		} +		for (j = width; j > 0; --j, ++d) { +			v = inttobits(*d, cmpt->prec_, cmpt->sgnd_); +			for (k = cmpt->cps_; k > 0; --k) { +				c = (v >> (8 * (cmpt->cps_ - 1))) & 0xff; +				if (jas_stream_putc(cmpt->stream_, +				  (unsigned char) c) == EOF) { +					return -1; +				} +				v <<= 8; +			} +		} +	} + +	return 0; +} + +/******************************************************************************\ +* File format operations. +\******************************************************************************/ + +void jas_image_clearfmts() +{ +	int i; +	jas_image_fmtinfo_t *fmtinfo; +	for (i = 0; i < jas_image_numfmts; ++i) { +		fmtinfo = &jas_image_fmtinfos[i]; +		if (fmtinfo->name) { +			jas_free(fmtinfo->name); +			fmtinfo->name = 0; +		} +		if (fmtinfo->ext) { +			jas_free(fmtinfo->ext); +			fmtinfo->ext = 0; +		} +		if (fmtinfo->desc) { +			jas_free(fmtinfo->desc); +			fmtinfo->desc = 0; +		} +	} +	jas_image_numfmts = 0; +} + +int jas_image_addfmt(int id, char *name, char *ext, char *desc, +  jas_image_fmtops_t *ops) +{ +	jas_image_fmtinfo_t *fmtinfo; +	assert(id >= 0 && name && ext && ops); +	if (jas_image_numfmts >= JAS_IMAGE_MAXFMTS) { +		return -1; +	} +	fmtinfo = &jas_image_fmtinfos[jas_image_numfmts]; +	fmtinfo->id = id; +	if (!(fmtinfo->name = jas_strdup(name))) { +		return -1; +	} +	if (!(fmtinfo->ext = jas_strdup(ext))) { +		jas_free(fmtinfo->name); +		return -1; +	} +	if (!(fmtinfo->desc = jas_strdup(desc))) { +		jas_free(fmtinfo->name); +		jas_free(fmtinfo->ext); +		return -1; +	} +	fmtinfo->ops = *ops; +	++jas_image_numfmts; +	return 0; +} + +int jas_image_strtofmt(char *name) +{ +	jas_image_fmtinfo_t *fmtinfo; +	if (!(fmtinfo = jas_image_lookupfmtbyname(name))) { +		return -1; +	} +	return fmtinfo->id; +} + +char *jas_image_fmttostr(int fmt) +{ +	jas_image_fmtinfo_t *fmtinfo; +	if (!(fmtinfo = jas_image_lookupfmtbyid(fmt))) { +		return 0; +	} +	return fmtinfo->name; +} + +int jas_image_getfmt(jas_stream_t *in) +{ +	jas_image_fmtinfo_t *fmtinfo; +	int found; +	int i; + +	/* Check for data in each of the supported formats. */ +	found = 0; +	for (i = 0, fmtinfo = jas_image_fmtinfos; i < jas_image_numfmts; ++i, +	  ++fmtinfo) { +		if (fmtinfo->ops.validate) { +			/* Is the input data valid for this format? */ +			if (!(*fmtinfo->ops.validate)(in)) { +				found = 1; +				break; +			} +		} +	} +	return found ? fmtinfo->id : (-1); +} + +int jas_image_fmtfromname(char *name) +{ +	int i; +	char *ext; +	jas_image_fmtinfo_t *fmtinfo; +	/* Get the file name extension. */ +	if (!(ext = strrchr(name, '.'))) { +		return -1; +	} +	++ext; +	/* Try to find a format that uses this extension. */	 +	for (i = 0, fmtinfo = jas_image_fmtinfos; i < jas_image_numfmts; ++i, +	  ++fmtinfo) { +		/* Do we have a match? */ +		if (!strcmp(ext, fmtinfo->ext)) { +			return fmtinfo->id; +		} +	} +	return -1; +} + +/******************************************************************************\ +* Miscellaneous operations. +\******************************************************************************/ + +uint_fast32_t jas_image_rawsize(jas_image_t *image) +{ +	uint_fast32_t rawsize; +	int cmptno; +	jas_image_cmpt_t *cmpt; + +	rawsize = 0; +	for (cmptno = 0; cmptno < image->numcmpts_; ++cmptno) { +		cmpt = image->cmpts_[cmptno]; +		rawsize += (cmpt->width_ * cmpt->height_ * cmpt->prec_ + +		  7) / 8; +	} +	return rawsize; +} + +void jas_image_delcmpt(jas_image_t *image, int cmptno) +{ +	if (cmptno >= image->numcmpts_) { +		return; +	} +	jas_image_cmpt_destroy(image->cmpts_[cmptno]); +	if (cmptno < image->numcmpts_) { +		memmove(&image->cmpts_[cmptno], &image->cmpts_[cmptno + 1], +		  (image->numcmpts_ - 1 - cmptno) * sizeof(jas_image_cmpt_t *)); +	} +	--image->numcmpts_; + +	jas_image_setbbox(image); +} + +int jas_image_addcmpt(jas_image_t *image, int cmptno, +  jas_image_cmptparm_t *cmptparm) +{ +	jas_image_cmpt_t *newcmpt; +	if (cmptno < 0) +		cmptno = image->numcmpts_; +	assert(cmptno >= 0 && cmptno <= image->numcmpts_); +	if (image->numcmpts_ >= image->maxcmpts_) { +		if (jas_image_growcmpts(image, image->maxcmpts_ + 128)) { +			return -1; +		} +	} +	if (!(newcmpt = jas_image_cmpt_create(cmptparm->tlx, +	  cmptparm->tly, cmptparm->hstep, cmptparm->vstep, +	  cmptparm->width, cmptparm->height, cmptparm->prec, +	  cmptparm->sgnd, 1))) { +		return -1; +	} +	if (cmptno < image->numcmpts_) { +		memmove(&image->cmpts_[cmptno + 1], &image->cmpts_[cmptno], +		  (image->numcmpts_ - cmptno) * sizeof(jas_image_cmpt_t *)); +	} +	image->cmpts_[cmptno] = newcmpt; +	++image->numcmpts_; + +	jas_image_setbbox(image); + +	return 0; +} + +jas_image_fmtinfo_t *jas_image_lookupfmtbyid(int id) +{ +	int i; +	jas_image_fmtinfo_t *fmtinfo; + +	for (i = 0, fmtinfo = jas_image_fmtinfos; i < jas_image_numfmts; ++i, ++fmtinfo) { +		if (fmtinfo->id == id) { +			return fmtinfo; +		} +	} +	return 0; +} + +jas_image_fmtinfo_t *jas_image_lookupfmtbyname(const char *name) +{ +	int i; +	jas_image_fmtinfo_t *fmtinfo; + +	for (i = 0, fmtinfo = jas_image_fmtinfos; i < jas_image_numfmts; ++i, ++fmtinfo) { +		if (!strcmp(fmtinfo->name, name)) { +			return fmtinfo; +		} +	} +	return 0; +} + + + + + +static uint_fast32_t inttobits(jas_seqent_t v, int prec, bool sgnd) +{ +	uint_fast32_t ret; +	ret = ((sgnd && v < 0) ? ((1 << prec) + v) : v) & JAS_ONES(prec); +	return ret; +} + +static jas_seqent_t bitstoint(uint_fast32_t v, int prec, bool sgnd) +{ +	jas_seqent_t ret; +	v &= JAS_ONES(prec); +	ret = (sgnd && (v & (1 << (prec - 1)))) ? (v - (1 << prec)) : v; +	return ret; +} + +static void jas_image_setbbox(jas_image_t *image) +{ +	jas_image_cmpt_t *cmpt; +	int cmptno; +	int_fast32_t x; +	int_fast32_t y; + +	if (image->numcmpts_ > 0) { +		/* Determine the bounding box for all of the components on the +		  reference grid (i.e., the image area) */ +		cmpt = image->cmpts_[0]; +		image->tlx_ = cmpt->tlx_; +		image->tly_ = cmpt->tly_; +		image->brx_ = cmpt->tlx_ + cmpt->hstep_ * (cmpt->width_ - 1) + 1; +		image->bry_ = cmpt->tly_ + cmpt->vstep_ * (cmpt->height_ - 1) + 1; +		for (cmptno = 1; cmptno < image->numcmpts_; ++cmptno) { +			cmpt = image->cmpts_[cmptno]; +			if (image->tlx_ > cmpt->tlx_) { +				image->tlx_ = cmpt->tlx_; +			} +			if (image->tly_ > cmpt->tly_) { +				image->tly_ = cmpt->tly_; +			} +			x = cmpt->tlx_ + cmpt->hstep_ * (cmpt->width_ - 1) + 1; +			if (image->brx_ < x) { +				image->brx_ = x; +			} +			y = cmpt->tly_ + cmpt->vstep_ * (cmpt->height_ - 1) + 1; +			if (image->bry_ < y) { +				image->bry_ = y; +			} +		} +	} else { +		image->tlx_ = 0; +		image->tly_ = 0; +		image->brx_ = 0; +		image->bry_ = 0; +	} +} + +static int jas_image_growcmpts(jas_image_t *image, int maxcmpts) +{ +	jas_image_cmpt_t **newcmpts; +	int cmptno; + +	newcmpts = (!image->cmpts_) ? jas_malloc(maxcmpts * sizeof(jas_image_cmpt_t *)) : +	  jas_realloc(image->cmpts_, maxcmpts * sizeof(jas_image_cmpt_t *)); +	if (!newcmpts) { +		return -1; +	} +	image->cmpts_ = newcmpts; +	image->maxcmpts_ = maxcmpts; +	for (cmptno = image->numcmpts_; cmptno < image->maxcmpts_; ++cmptno) { +		image->cmpts_[cmptno] = 0; +	} +	return 0; +} + +int jas_image_copycmpt(jas_image_t *dstimage, int dstcmptno, jas_image_t *srcimage, +  int srccmptno) +{ +	jas_image_cmpt_t *newcmpt; +	if (dstimage->numcmpts_ >= dstimage->maxcmpts_) { +		if (jas_image_growcmpts(dstimage, dstimage->maxcmpts_ + 128)) { +			return -1; +		} +	} +	if (!(newcmpt = jas_image_cmpt_copy(srcimage->cmpts_[srccmptno]))) { +		return -1; +	} +	if (dstcmptno < dstimage->numcmpts_) { +		memmove(&dstimage->cmpts_[dstcmptno + 1], &dstimage->cmpts_[dstcmptno], +		  (dstimage->numcmpts_ - dstcmptno) * sizeof(jas_image_cmpt_t *)); +	} +	dstimage->cmpts_[dstcmptno] = newcmpt; +	++dstimage->numcmpts_; + +	jas_image_setbbox(dstimage); +	return 0; +} + +void jas_image_dump(jas_image_t *image, FILE *out) +{ +	long buf[1024]; +	int cmptno; +	int n; +	int i; +	int width; +	int height; +	jas_image_cmpt_t *cmpt; +	for (cmptno = 0; cmptno < image->numcmpts_; ++cmptno) { +		cmpt = image->cmpts_[cmptno]; +		fprintf(out, "prec=%d, sgnd=%d, cmpttype=%d\n", cmpt->prec_, +		  cmpt->sgnd_, cmpt->type_); +		width = jas_image_cmptwidth(image, cmptno); +		height = jas_image_cmptheight(image, cmptno); +		n = JAS_MIN(16, width); +		if (jas_image_readcmpt2(image, cmptno, 0, 0, n, 1, buf)) { +			abort(); +		} +		for (i = 0; i < n; ++i) { +			fprintf(out, " f(%d,%d)=%ld", i, 0, buf[i]); +		} +		fprintf(out, "\n"); +		if (jas_image_readcmpt2(image, cmptno, width - n, height - 1, n, 1, buf)) { +			abort(); +		} +		for (i = 0; i < n; ++i) { +			fprintf(out, " f(%d,%d)=%ld", width - n + i, height - 1, buf[i]); +		} +		fprintf(out, "\n"); +	} +} + +int jas_image_depalettize(jas_image_t *image, int cmptno, int numlutents, +  int_fast32_t *lutents, int dtype, int newcmptno) +{ +	jas_image_cmptparm_t cmptparms; +	int_fast32_t v; +	int i; +	int j; +	jas_image_cmpt_t *cmpt; + +	cmpt = image->cmpts_[cmptno]; +	cmptparms.tlx = cmpt->tlx_; +	cmptparms.tly = cmpt->tly_; +	cmptparms.hstep = cmpt->hstep_; +	cmptparms.vstep = cmpt->vstep_; +	cmptparms.width = cmpt->width_; +	cmptparms.height = cmpt->height_; +	cmptparms.prec = JAS_IMAGE_CDT_GETPREC(dtype); +	cmptparms.sgnd = JAS_IMAGE_CDT_GETSGND(dtype); + +	if (jas_image_addcmpt(image, newcmptno, &cmptparms)) { +		return -1; +	} +	if (newcmptno <= cmptno) { +		++cmptno; +		cmpt = image->cmpts_[cmptno]; +	} + +	for (j = 0; j < cmpt->height_; ++j) { +		for (i = 0; i < cmpt->width_; ++i) { +			v = jas_image_readcmptsample(image, cmptno, i, j); +			if (v < 0) { +				v = 0; +			} else if (v >= numlutents) { +				v = numlutents - 1; +			} +			jas_image_writecmptsample(image, newcmptno, i, j, +			  lutents[v]); +		} +	} +	return 0; +} + +int jas_image_readcmptsample(jas_image_t *image, int cmptno, int x, int y) +{ +	jas_image_cmpt_t *cmpt; +	uint_fast32_t v; +	int k; +	int c; + +	cmpt = image->cmpts_[cmptno]; + +	if (jas_stream_seek(cmpt->stream_, (cmpt->width_ * y + x) * cmpt->cps_, +	  SEEK_SET) < 0) { +		return -1; +	} +	v = 0; +	for (k = cmpt->cps_; k > 0; --k) { +		if ((c = jas_stream_getc(cmpt->stream_)) == EOF) { +			return -1; +		} +		v = (v << 8) | (c & 0xff); +	} +	return bitstoint(v, cmpt->prec_, cmpt->sgnd_); +} + +void jas_image_writecmptsample(jas_image_t *image, int cmptno, int x, int y, +  int_fast32_t v) +{ +	jas_image_cmpt_t *cmpt; +	uint_fast32_t t; +	int k; +	int c; + +	cmpt = image->cmpts_[cmptno]; + +	if (jas_stream_seek(cmpt->stream_, (cmpt->width_ * y + x) * cmpt->cps_, +	  SEEK_SET) < 0) { +		return; +	} +	t = inttobits(v, cmpt->prec_, cmpt->sgnd_); +	for (k = cmpt->cps_; k > 0; --k) { +		c = (t >> (8 * (cmpt->cps_ - 1))) & 0xff; +		if (jas_stream_putc(cmpt->stream_, (unsigned char) c) == EOF) { +			return; +		} +		t <<= 8; +	} +} + +int jas_image_getcmptbytype(jas_image_t *image, int ctype) +{ +	int cmptno; + +	for (cmptno = 0; cmptno < image->numcmpts_; ++cmptno) { +		if (image->cmpts_[cmptno]->type_ == ctype) { +			return cmptno; +		} +	} +	return -1; +} + + + + + + + + + + + + + + + + +/***********************************************/ +/***********************************************/ +/***********************************************/ +/***********************************************/ + +int jas_image_readcmpt2(jas_image_t *image, int cmptno, jas_image_coord_t x, +  jas_image_coord_t y, jas_image_coord_t width, jas_image_coord_t height, +  long *buf) +{ +	jas_image_cmpt_t *cmpt; +	jas_image_coord_t i; +	jas_image_coord_t j; +	long v; +	long *bufptr; + +	if (cmptno < 0 || cmptno >= image->numcmpts_) +		goto error; +	cmpt = image->cmpts_[cmptno]; +	if (x < 0 || x >= cmpt->width_ || y < 0 || y >= cmpt->height_ || +	  width < 0 || height < 0 || x + width > cmpt->width_ || +	  y + height > cmpt->height_) +		goto error; + +	bufptr = buf; +	for (i = 0; i < height; ++i) { +		if (jas_stream_seek(cmpt->stream_, (cmpt->width_ * (y + i) + x) +		  * cmpt->cps_, SEEK_SET) < 0) +			goto error; +		for (j = 0; j < width; ++j) { +			if (getint(cmpt->stream_, cmpt->sgnd_, cmpt->prec_, &v)) +				goto error; +			*bufptr++ = v; +		} +	} + +	return 0; +error: +	return -1; +} + +int jas_image_writecmpt2(jas_image_t *image, int cmptno, jas_image_coord_t x, +  jas_image_coord_t y, jas_image_coord_t width, jas_image_coord_t height, +  long *buf) +{ +	jas_image_cmpt_t *cmpt; +	jas_image_coord_t i; +	jas_image_coord_t j; +	long v; +	long *bufptr; + +	if (cmptno < 0 || cmptno >= image->numcmpts_) +		goto error; +	cmpt = image->cmpts_[cmptno]; +	if (x < 0 || x >= cmpt->width_ || y < 0 || y >= cmpt->height_ || +	  width < 0 || height < 0 || x + width > cmpt->width_ || +	  y + height > cmpt->height_) +		goto error; + +	bufptr = buf; +	for (i = 0; i < height; ++i) { +		if (jas_stream_seek(cmpt->stream_, (cmpt->width_ * (y + i) + x) +		  * cmpt->cps_, SEEK_SET) < 0) +			goto error; +		for (j = 0; j < width; ++j) { +			v = *bufptr++; +			if (putint(cmpt->stream_, cmpt->sgnd_, cmpt->prec_, v)) +				goto error; +		} +	} + +	return 0; +error: +	return -1; +} + +int jas_image_sampcmpt(jas_image_t *image, int cmptno, int newcmptno, +  jas_image_coord_t ho, jas_image_coord_t vo, jas_image_coord_t hs, +  jas_image_coord_t vs, int sgnd, int prec) +{ +	jas_image_cmpt_t *oldcmpt; +	jas_image_cmpt_t *newcmpt; +	int width; +	int height; +	jas_image_coord_t tlx; +	jas_image_coord_t tly; +	jas_image_coord_t brx; +	jas_image_coord_t bry; +	int i; +	int j; +	jas_image_cmptparm_t cmptparm; +	jas_image_coord_t ax; +	jas_image_coord_t ay; +	jas_image_coord_t bx; +	jas_image_coord_t by; +	jas_image_coord_t d0; +	jas_image_coord_t d1; +	jas_image_coord_t d2; +	jas_image_coord_t d3; +	jas_image_coord_t oldx; +	jas_image_coord_t oldy; +	jas_image_coord_t x; +	jas_image_coord_t y; +	long v; +	jas_image_coord_t cmptbrx; +	jas_image_coord_t cmptbry; + +	assert(cmptno >= 0 && cmptno < image->numcmpts_); +	oldcmpt = image->cmpts_[cmptno]; +	assert(oldcmpt->tlx_ == 0 && oldcmpt->tly_ == 0); +	jas_image_calcbbox2(image, &tlx, &tly, &brx, &bry); +	width = FLOORDIV(brx - ho + hs, hs); +	height = FLOORDIV(bry - vo + vs, vs); +	cmptparm.tlx = ho; +	cmptparm.tly = vo; +	cmptparm.hstep = hs; +	cmptparm.vstep = vs; +	cmptparm.width = width; +	cmptparm.height = height; +	cmptparm.prec = prec; +	cmptparm.sgnd = sgnd; +	if (jas_image_addcmpt(image, newcmptno, &cmptparm)) +		goto error; +cmptbrx = oldcmpt->tlx_ + (oldcmpt->width_ - 1) * oldcmpt->hstep_; +cmptbry = oldcmpt->tly_ + (oldcmpt->height_ - 1) * oldcmpt->vstep_; +	newcmpt = image->cmpts_[newcmptno]; +	jas_stream_rewind(newcmpt->stream_); +	for (i = 0; i < height; ++i) { +		y = newcmpt->tly_ + newcmpt->vstep_ * i; +		for (j = 0; j < width; ++j) { +			x = newcmpt->tlx_ + newcmpt->hstep_ * j; +			ax = downtomult(x - oldcmpt->tlx_, oldcmpt->hstep_) + oldcmpt->tlx_; +			ay = downtomult(y - oldcmpt->tly_, oldcmpt->vstep_) + oldcmpt->tly_; +			bx = uptomult(x - oldcmpt->tlx_, oldcmpt->hstep_) + oldcmpt->tlx_; +			if (bx > cmptbrx) +				bx = cmptbrx; +			by = uptomult(y - oldcmpt->tly_, oldcmpt->vstep_) + oldcmpt->tly_; +			if (by > cmptbry) +				by = cmptbry; +			d0 = (ax - x) * (ax - x) + (ay - y) * (ay - y); +			d1 = (bx - x) * (bx - x) + (ay - y) * (ay - y); +			d2 = (bx - x) * (bx - x) + (by - y) * (by - y); +			d3 = (ax - x) * (ax - x) + (by - y) * (by - y); +			if (d0 <= d1 && d0 <= d2 && d0 <= d3) { +				oldx = (ax - oldcmpt->tlx_) / oldcmpt->hstep_; +				oldy = (ay - oldcmpt->tly_) / oldcmpt->vstep_; +			} else if (d1 <= d0 && d1 <= d2 && d1 <= d3) { +				oldx = (bx - oldcmpt->tlx_) / oldcmpt->hstep_; +				oldy = (ay - oldcmpt->tly_) / oldcmpt->vstep_; +			} else if (d2 <= d0 && d2 <= d1 && d1 <= d3) { +				oldx = (bx - oldcmpt->tlx_) / oldcmpt->hstep_; +				oldy = (by - oldcmpt->tly_) / oldcmpt->vstep_; +			} else { +				oldx = (ax - oldcmpt->tlx_) / oldcmpt->hstep_; +				oldy = (by - oldcmpt->tly_) / oldcmpt->vstep_; +			} +			assert(oldx >= 0 && oldx < oldcmpt->width_ && +			  oldy >= 0 && oldy < oldcmpt->height_); +			if (jas_stream_seek(oldcmpt->stream_, oldcmpt->cps_ * +			  (oldy * oldcmpt->width_ + oldx), SEEK_SET) < 0) +				goto error; +			if (getint(oldcmpt->stream_, oldcmpt->sgnd_, +			  oldcmpt->prec_, &v)) +				goto error; +			if (newcmpt->prec_ != oldcmpt->prec_ || +			  newcmpt->sgnd_ != oldcmpt->sgnd_) { +				v = convert(v, oldcmpt->sgnd_, oldcmpt->prec_, +				  newcmpt->sgnd_, newcmpt->prec_); +			} +			if (putint(newcmpt->stream_, newcmpt->sgnd_, +			  newcmpt->prec_, v)) +				goto error; +		} +	} +	return 0; +error: +	return -1; +} + +int jas_image_ishomosamp(jas_image_t *image) +{ +	jas_image_coord_t hstep; +	jas_image_coord_t vstep; +	int result; +	int i; +	hstep = jas_image_cmpthstep(image, 0); +	vstep = jas_image_cmptvstep(image, 0); +	result = 1; +	for (i = 0; i < image->numcmpts_; ++i) { +		if (jas_image_cmpthstep(image, i) != hstep || +		  jas_image_cmptvstep(image, i) != vstep) { +			result = 0; +			break; +		} +	} +	return result; +} + +/* Note: This function defines a bounding box differently. */ +static void jas_image_calcbbox2(jas_image_t *image, jas_image_coord_t *tlx, +  jas_image_coord_t *tly, jas_image_coord_t *brx, jas_image_coord_t *bry) +{ +	jas_image_cmpt_t *cmpt; +	jas_image_coord_t tmptlx; +	jas_image_coord_t tmptly; +	jas_image_coord_t tmpbrx; +	jas_image_coord_t tmpbry; +	jas_image_coord_t t; +	int i; +	if (image->numcmpts_ > 0) { +		cmpt = image->cmpts_[0]; +		tmptlx = cmpt->tlx_; +		tmptly = cmpt->tly_; +		tmpbrx = cmpt->tlx_ + cmpt->hstep_ * (cmpt->width_ - 1); +		tmpbry = cmpt->tly_ + cmpt->vstep_ * (cmpt->height_ - 1); +		for (i = 0; i < image->numcmpts_; ++i) { +			cmpt = image->cmpts_[i]; +			if (cmpt->tlx_ < tmptlx) +				tmptlx = cmpt->tlx_; +			if (cmpt->tly_ < tmptly) +				tmptly = cmpt->tly_; +			t = cmpt->tlx_ + cmpt->hstep_ * (cmpt->width_ - 1); +			if (t > tmpbrx) +				tmpbrx = t; +			t = cmpt->tly_ + cmpt->vstep_ * (cmpt->height_ - 1); +			if (t > tmpbry) +				tmpbry = t; +		} +	} else { +		tmptlx = 0; +		tmptly = 0; +		tmpbrx = -1; +		tmpbry = -1; +	} +	*tlx = tmptlx; +	*tly = tmptly; +	*brx = tmpbrx; +	*bry = tmpbry; +} + + + +static int getint(jas_stream_t *in, int sgnd, int prec, long *val) +{ +	long v; +	int n; +	int c; +	n = (prec + 7) / 8; +	v = 0; +	while (--n >= 0) { +		if ((c = jas_stream_getc(in)) == EOF) +			return -1; +		v = (v << 8) | c; +	} +	v &= ((1 << prec) - 1); +	if (sgnd) { +		/* XXX - Do something here. */ +		abort(); +	} else { +		*val = v; +	} +	return 0; +} + +static int putint(jas_stream_t *out, int sgnd, int prec, long val) +{ +	int n; +	int c; +	if (sgnd) { +		/* XXX - Do something here. */ +		abort(); +	} +	val &= (1 << prec) - 1; +	n = (prec + 7) / 8; +	while (--n >= 0) { +		c = (val >> (n * 8)) & 0xff; +		if (jas_stream_putc(out, c) != c) +			return -1; +	} +	return 0; +} + +static long convert(long val, int oldsgnd, int oldprec, int newsgnd, +  int newprec) +{ +	if (newsgnd != oldsgnd) { +	} +	if (newprec != oldprec) { +		if (newprec > oldprec) { +			val <<= newprec - oldprec; +		} else if (oldprec > newprec) { +			val >>= oldprec - newprec; +		} +	} +	return val; +} + +static long downtomult(long x, long y) +{ +	assert(x >= 0); +	return (x / y) * y; +} + +static long uptomult(long x, long y) +{ +	assert(x >= 0); +	return ((x + y - 1) / y) * y; +} + +jas_image_t *jas_image_chclrspc(jas_image_t *image, jas_cmprof_t *outprof, +  int intent) +{ +	jas_image_t *inimage; +	int minhstep; +	int minvstep; +	int i; +	int j; +	int k; +	int n; +	int hstep; +	int vstep; +	int numinauxchans; +	int numoutauxchans; +	int numinclrchans; +	int numoutclrchans; +	int prec; +	jas_image_t *outimage; +	int cmpttype; +	int numoutchans; +	jas_cmprof_t *inprof; +	jas_cmprof_t *tmpprof; +	jas_image_cmptparm_t cmptparm; +	int width; +	int height; +	jas_cmxform_t *xform; +	jas_cmpixmap_t inpixmap; +	jas_cmpixmap_t outpixmap; +	jas_cmcmptfmt_t *incmptfmts; +	jas_cmcmptfmt_t *outcmptfmts; + +#if 0 +jas_eprintf("IMAGE\n"); +jas_image_dump(image, stderr); +#endif + +	if (!(inimage = jas_image_copy(image))) +		goto error; +	image = 0; + +	if (!jas_image_ishomosamp(inimage)) { +		minhstep = jas_image_cmpthstep(inimage, 0); +		minvstep = jas_image_cmptvstep(inimage, 0); +		for (i = 1; i < jas_image_numcmpts(inimage); ++i) { +			hstep = jas_image_cmpthstep(inimage, i); +			vstep = jas_image_cmptvstep(inimage, i); +			if (hstep < minhstep) +				minhstep = hstep; +			if (vstep < minvstep) +				minvstep = vstep; +		} +		n = jas_image_numcmpts(inimage); +		for (i = 0; i < n; ++i) { +			cmpttype = jas_image_cmpttype(inimage, i); +			if (jas_image_sampcmpt(inimage, i, i + 1, 0, 0, minhstep, minvstep, jas_image_cmptsgnd(inimage, i), jas_image_cmptprec(inimage, i))) +				goto error; +			jas_image_setcmpttype(inimage, i + 1, cmpttype); +			jas_image_delcmpt(inimage, i); +		} +	} + +	width = jas_image_cmptwidth(inimage, 0); +	height = jas_image_cmptheight(inimage, 0); +	hstep = jas_image_cmpthstep(inimage, 0); +	vstep = jas_image_cmptvstep(inimage, 0); + +	inprof = jas_image_cmprof(inimage); +	assert(inprof); +	numinclrchans = jas_clrspc_numchans(jas_cmprof_clrspc(inprof)); +	numinauxchans = jas_image_numcmpts(inimage) - numinclrchans; +	numoutclrchans = jas_clrspc_numchans(jas_cmprof_clrspc(outprof)); +	numoutauxchans = 0; +	numoutchans = numoutclrchans + numoutauxchans; +	prec = 8; + +	if (!(outimage = jas_image_create0())) +		goto error; + +	/* Create a component for each of the colorants. */ +	for (i = 0; i < numoutclrchans; ++i) { +		cmptparm.tlx = 0; +		cmptparm.tly = 0; +		cmptparm.hstep = hstep; +		cmptparm.vstep = vstep; +		cmptparm.width = width; +		cmptparm.height = height; +		cmptparm.prec = prec; +		cmptparm.sgnd = 0; +		if (jas_image_addcmpt(outimage, -1, &cmptparm)) +			goto error; +		jas_image_setcmpttype(outimage, i, JAS_IMAGE_CT_COLOR(i)); +	} +#if 0 +	/* Copy the auxiliary components without modification. */ +	for (i = 0; i < jas_image_numcmpts(inimage); ++i) { +		if (!ISCOLOR(jas_image_cmpttype(inimage, i))) { +			jas_image_copycmpt(outimage, -1, inimage, i); +/* XXX - need to specify laydown of component on ref. grid */ +		} +	} +#endif + +	if (!(tmpprof = jas_cmprof_copy(outprof))) +		goto error; +	assert(!jas_image_cmprof(outimage)); +	jas_image_setcmprof(outimage, tmpprof); +	tmpprof = 0; +	jas_image_setclrspc(outimage, jas_cmprof_clrspc(outprof)); + +	if (!(xform = jas_cmxform_create(inprof, outprof, 0, JAS_CMXFORM_OP_FWD, intent, 0))) +		goto error; + +	inpixmap.numcmpts = numinclrchans; +	incmptfmts = malloc(numinclrchans * sizeof(jas_cmcmptfmt_t)); +	assert(incmptfmts); +	inpixmap.cmptfmts = incmptfmts; +	for (i = 0; i < numinclrchans; ++i) { +		j = jas_image_getcmptbytype(inimage, JAS_IMAGE_CT_COLOR(i)); +		assert(j >= 0); +		if (!(incmptfmts[i].buf = malloc(width * sizeof(long)))) +			goto error; +		incmptfmts[i].prec = jas_image_cmptprec(inimage, j); +		incmptfmts[i].sgnd = jas_image_cmptsgnd(inimage, j); +		incmptfmts[i].width = width; +		incmptfmts[i].height = 1; +	} + +	outpixmap.numcmpts = numoutclrchans; +	outcmptfmts = malloc(numoutclrchans * sizeof(jas_cmcmptfmt_t)); +	assert(outcmptfmts); +	outpixmap.cmptfmts = outcmptfmts; + +	for (i = 0; i < numoutclrchans; ++i) { +		j = jas_image_getcmptbytype(outimage, JAS_IMAGE_CT_COLOR(i)); +		assert(j >= 0); +		if (!(outcmptfmts[i].buf = malloc(width * sizeof(long)))) +			goto error; +		outcmptfmts[i].prec = jas_image_cmptprec(outimage, j); +		outcmptfmts[i].sgnd = jas_image_cmptsgnd(outimage, j); +		outcmptfmts[i].width = width; +		outcmptfmts[i].height = 1; +	} + +	for (i = 0; i < height; ++i) { +		for (j = 0; j < numinclrchans; ++j) { +			k = jas_image_getcmptbytype(inimage, JAS_IMAGE_CT_COLOR(j)); +			if (jas_image_readcmpt2(inimage, k, 0, i, width, 1, incmptfmts[j].buf)) +				goto error; +		} +		jas_cmxform_apply(xform, &inpixmap, &outpixmap); +		for (j = 0; j < numoutclrchans; ++j) { +			k = jas_image_getcmptbytype(outimage, JAS_IMAGE_CT_COLOR(j)); +			if (jas_image_writecmpt2(outimage, k, 0, i, width, 1, outcmptfmts[j].buf)) +				goto error; +		} +	} + +	for (i = 0; i < numoutclrchans; ++i) +		jas_free(outcmptfmts[i].buf); +	jas_free(outcmptfmts); +	for (i = 0; i < numinclrchans; ++i) +		jas_free(incmptfmts[i].buf); +	jas_free(incmptfmts); +	jas_cmxform_destroy(xform); +	jas_image_destroy(inimage); + +#if 0 +jas_eprintf("INIMAGE\n"); +jas_image_dump(inimage, stderr); +jas_eprintf("OUTIMAGE\n"); +jas_image_dump(outimage, stderr); +#endif +	return outimage; +error: +	return 0; +} diff --git a/src/libjasper/base/jas_init.c b/src/libjasper/base/jas_init.c new file mode 100644 index 0000000..960d1e9 --- /dev/null +++ b/src/libjasper/base/jas_init.c @@ -0,0 +1,170 @@ +/* + * 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__ + */ + +/******************************************************************************\ +* Includes. +\******************************************************************************/ + +#include "jasper/jas_types.h" +#include "jasper/jas_image.h" +#include "jasper/jas_init.h" + +/******************************************************************************\ +* Code. +\******************************************************************************/ + +/* Initialize the image format table. */ +int jas_init() +{ +	jas_image_fmtops_t fmtops; +	int fmtid; + +	fmtid = 0; + +#if !defined(EXCLUDE_MIF_SUPPORT) +	fmtops.decode = mif_decode; +	fmtops.encode = mif_encode; +	fmtops.validate = mif_validate; +	jas_image_addfmt(fmtid, "mif", "mif", "My Image Format (MIF)", &fmtops); +	++fmtid; +#endif + +#if !defined(EXCLUDE_PNM_SUPPORT) +	fmtops.decode = pnm_decode; +	fmtops.encode = pnm_encode; +	fmtops.validate = pnm_validate; +	jas_image_addfmt(fmtid, "pnm", "pnm", "Portable Graymap/Pixmap (PNM)", +	  &fmtops); +	jas_image_addfmt(fmtid, "pnm", "pgm", "Portable Graymap/Pixmap (PNM)", +	  &fmtops); +	jas_image_addfmt(fmtid, "pnm", "ppm", "Portable Graymap/Pixmap (PNM)", +	  &fmtops); +	++fmtid; +#endif + +#if !defined(EXCLUDE_BMP_SUPPORT) +	fmtops.decode = bmp_decode; +	fmtops.encode = bmp_encode; +	fmtops.validate = bmp_validate; +	jas_image_addfmt(fmtid, "bmp", "bmp", "Microsoft Bitmap (BMP)", &fmtops); +	++fmtid; +#endif + +#if !defined(EXCLUDE_RAS_SUPPORT) +	fmtops.decode = ras_decode; +	fmtops.encode = ras_encode; +	fmtops.validate = ras_validate; +	jas_image_addfmt(fmtid, "ras", "ras", "Sun Rasterfile (RAS)", &fmtops); +	++fmtid; +#endif + +#if !defined(EXCLUDE_JP2_SUPPORT) +	fmtops.decode = jp2_decode; +	fmtops.encode = jp2_encode; +	fmtops.validate = jp2_validate; +	jas_image_addfmt(fmtid, "jp2", "jp2", +	  "JPEG-2000 JP2 File Format Syntax (ISO/IEC 15444-1)", &fmtops); +	++fmtid; +	fmtops.decode = jpc_decode; +	fmtops.encode = jpc_encode; +	fmtops.validate = jpc_validate; +	jas_image_addfmt(fmtid, "jpc", "jpc", +	  "JPEG-2000 Code Stream Syntax (ISO/IEC 15444-1)", &fmtops); +	++fmtid; +#endif + +#if !defined(EXCLUDE_JPG_SUPPORT) +	fmtops.decode = jpg_decode; +	fmtops.encode = jpg_encode; +	fmtops.validate = jpg_validate; +	jas_image_addfmt(fmtid, "jpg", "jpg", "JPEG (ISO/IEC 10918-1)", &fmtops); +	++fmtid; +#endif + +#if !defined(EXCLUDE_PGX_SUPPORT) +	fmtops.decode = pgx_decode; +	fmtops.encode = pgx_encode; +	fmtops.validate = pgx_validate; +	jas_image_addfmt(fmtid, "pgx", "pgx", "JPEG-2000 VM Format (PGX)", &fmtops); +	++fmtid; +#endif + +#if !defined(EXCLUDE_TIFF_SUPPORT) +	fmtops.decode = tiff_decode; +	fmtops.encode = tiff_encode; +	fmtops.validate = tiff_validate; +	jas_image_addfmt(fmtid, "tif", "tif", "Tagged Image File (TIFF)", &fmtops); +	++fmtid; +#endif + +	/* We must not register the JasPer library exit handler until after +	at least one memory allocation is performed.  This is desirable +	as it ensures that the JasPer exit handler is called before the +	debug memory allocator exit handler. */ +	atexit(jas_cleanup); + +	return 0; +} + +void jas_cleanup() +{ +	jas_image_clearfmts(); +} diff --git a/src/libjasper/base/jas_malloc.c b/src/libjasper/base/jas_malloc.c new file mode 100644 index 0000000..77f2bc6 --- /dev/null +++ b/src/libjasper/base/jas_malloc.c @@ -0,0 +1,131 @@ +/* + * 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__ + */ + +/* + * Memory Allocator + * + * $Id: jas_malloc.c,v 1.1 2008/10/17 06:14:59 scuri Exp $ + */ + +/******************************************************************************\ +* Includes. +\******************************************************************************/ + +#include <stdio.h> +#include <stdlib.h> + +/* We need the prototype for memset. */ +#include <string.h> + +#include "jasper/jas_malloc.h" + +/******************************************************************************\ +* Code. +\******************************************************************************/ + +#if defined(DEBUG_MEMALLOC) +#include "../../../local/src/memalloc.c" +#endif + +#if !defined(DEBUG_MEMALLOC) + +#define MEMALLOC_ALIGNMENT	32 +#define MEMALLOC_ALIGN2 +#undef MEMALLOC_ALIGN2 + +void *jas_malloc(size_t size) +{ +#if defined(MEMALLOC_ALIGN2) +	void *ptr; +abort(); +	if (posix_memalign(&ptr, MEMALLOC_ALIGNMENT, size)) { +		return 0; +	} +	return ptr; +#endif +	return malloc(size); +} + +void jas_free(void *ptr) +{ +	free(ptr); +} + +void *jas_realloc(void *ptr, size_t size) +{ +	return realloc(ptr, size); +} + +void *jas_calloc(size_t nmemb, size_t size) +{ +	void *ptr; +	size_t n; +	n = nmemb * size; +	if (!(ptr = jas_malloc(n * sizeof(char)))) { +		return 0; +	} +	memset(ptr, 0, n); +	return ptr; +} + +#endif diff --git a/src/libjasper/base/jas_seq.c b/src/libjasper/base/jas_seq.c new file mode 100644 index 0000000..fcf14f0 --- /dev/null +++ b/src/libjasper/base/jas_seq.c @@ -0,0 +1,454 @@ +/* + * 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__ + */ + +/* + * Sequence/Matrix Library + * + * $Id: jas_seq.c,v 1.1 2008/10/17 06:14:59 scuri Exp $ + */ + +/******************************************************************************\ +* Includes. +\******************************************************************************/ + +#include <stdlib.h> +#include <assert.h> +#include <math.h> + +#include "jasper/jas_seq.h" +#include "jasper/jas_malloc.h" +#include "jasper/jas_math.h" + +/******************************************************************************\ +* Constructors and destructors. +\******************************************************************************/ + +jas_matrix_t *jas_seq2d_create(int xstart, int ystart, int xend, int yend) +{ +	jas_matrix_t *matrix; +	assert(xstart <= xend && ystart <= yend); +	if (!(matrix = jas_matrix_create(yend - ystart, xend - xstart))) { +		return 0; +	} +	matrix->xstart_ = xstart; +	matrix->ystart_ = ystart; +	matrix->xend_ = xend; +	matrix->yend_ = yend; +	return matrix; +} + +jas_matrix_t *jas_matrix_create(int numrows, int numcols) +{ +	jas_matrix_t *matrix; +	int i; + +	if (!(matrix = jas_malloc(sizeof(jas_matrix_t)))) { +		return 0; +	} +	matrix->flags_ = 0; +	matrix->numrows_ = numrows; +	matrix->numcols_ = numcols; +	matrix->rows_ = 0; +	matrix->maxrows_ = numrows; +	matrix->data_ = 0; +	matrix->datasize_ = numrows * numcols; + +	if (matrix->maxrows_ > 0) { +		if (!(matrix->rows_ = jas_malloc(matrix->maxrows_ * +		  sizeof(jas_seqent_t *)))) { +			jas_matrix_destroy(matrix); +			return 0; +		} +	} + +	if (matrix->datasize_ > 0) { +		if (!(matrix->data_ = jas_malloc(matrix->datasize_ * +		  sizeof(jas_seqent_t)))) { +			jas_matrix_destroy(matrix); +			return 0; +		} +	} + +	for (i = 0; i < numrows; ++i) { +		matrix->rows_[i] = &matrix->data_[i * matrix->numcols_]; +	} + +	for (i = 0; i < matrix->datasize_; ++i) { +		matrix->data_[i] = 0; +	} + +	matrix->xstart_ = 0; +	matrix->ystart_ = 0; +	matrix->xend_ = matrix->numcols_; +	matrix->yend_ = matrix->numrows_; + +	return matrix; +} + +void jas_matrix_destroy(jas_matrix_t *matrix) +{ +	if (matrix->data_) { +		assert(!(matrix->flags_ & JAS_MATRIX_REF)); +		jas_free(matrix->data_); +		matrix->data_ = 0; +	} +	if (matrix->rows_) { +		jas_free(matrix->rows_); +		matrix->rows_ = 0; +	} +	jas_free(matrix); +} + +jas_seq2d_t *jas_seq2d_copy(jas_seq2d_t *x) +{ +	jas_matrix_t *y; +	int i; +	int j; +	y = jas_seq2d_create(jas_seq2d_xstart(x), jas_seq2d_ystart(x), jas_seq2d_xend(x), +	  jas_seq2d_yend(x)); +	assert(y); +	for (i = 0; i < x->numrows_; ++i) { +		for (j = 0; j < x->numcols_; ++j) { +			*jas_matrix_getref(y, i, j) = jas_matrix_get(x, i, j); +		} +	} +	return y; +} + +jas_matrix_t *jas_matrix_copy(jas_matrix_t *x) +{ +	jas_matrix_t *y; +	int i; +	int j; +	y = jas_matrix_create(x->numrows_, x->numcols_); +	for (i = 0; i < x->numrows_; ++i) { +		for (j = 0; j < x->numcols_; ++j) { +			*jas_matrix_getref(y, i, j) = jas_matrix_get(x, i, j); +		} +	} +	return y; +} + +/******************************************************************************\ +* Bind operations. +\******************************************************************************/ + +void jas_seq2d_bindsub(jas_matrix_t *s, jas_matrix_t *s1, int xstart, int ystart, +  int xend, int yend) +{ +	jas_matrix_bindsub(s, s1, ystart - s1->ystart_, xstart - s1->xstart_, +	  yend - s1->ystart_ - 1, xend - s1->xstart_ - 1); +} + +void jas_matrix_bindsub(jas_matrix_t *mat0, jas_matrix_t *mat1, int r0, int c0, +  int r1, int c1) +{ +	int i; + +	if (mat0->data_) { +		if (!(mat0->flags_ & JAS_MATRIX_REF)) { +			jas_free(mat0->data_); +		} +		mat0->data_ = 0; +		mat0->datasize_ = 0; +	} +	if (mat0->rows_) { +		jas_free(mat0->rows_); +		mat0->rows_ = 0; +	} +	mat0->flags_ |= JAS_MATRIX_REF; +	mat0->numrows_ = r1 - r0 + 1; +	mat0->numcols_ = c1 - c0 + 1; +	mat0->maxrows_ = mat0->numrows_; +	mat0->rows_ = jas_malloc(mat0->maxrows_ * sizeof(jas_seqent_t *)); +	for (i = 0; i < mat0->numrows_; ++i) { +		mat0->rows_[i] = mat1->rows_[r0 + i] + c0; +	} + +	mat0->xstart_ = mat1->xstart_ + c0; +	mat0->ystart_ = mat1->ystart_ + r0; +	mat0->xend_ = mat0->xstart_ + mat0->numcols_; +	mat0->yend_ = mat0->ystart_ + mat0->numrows_; +} + +/******************************************************************************\ +* Arithmetic operations. +\******************************************************************************/ + +int jas_matrix_cmp(jas_matrix_t *mat0, jas_matrix_t *mat1) +{ +	int i; +	int j; + +	if (mat0->numrows_ != mat1->numrows_ || mat0->numcols_ != +	  mat1->numcols_) { +		return 1; +	} +	for (i = 0; i < mat0->numrows_; i++) { +		for (j = 0; j < mat0->numcols_; j++) { +			if (jas_matrix_get(mat0, i, j) != jas_matrix_get(mat1, i, j)) { +				return 1; +			} +		} +	} +	return 0; +} + +void jas_matrix_divpow2(jas_matrix_t *matrix, int n) +{ +	int i; +	int j; +	jas_seqent_t *rowstart; +	int rowstep; +	jas_seqent_t *data; + +	rowstep = jas_matrix_rowstep(matrix); +	for (i = matrix->numrows_, rowstart = matrix->rows_[0]; i > 0; --i, +	  rowstart += rowstep) { +		for (j = matrix->numcols_, data = rowstart; j > 0; --j, +		  ++data) { +			*data = (*data >= 0) ? ((*data) >> n) : +			  (-((-(*data)) >> n)); +		} +	} +} + +void jas_matrix_clip(jas_matrix_t *matrix, jas_seqent_t minval, jas_seqent_t maxval) +{ +	int i; +	int j; +	jas_seqent_t v; +	jas_seqent_t *rowstart; +	jas_seqent_t *data; +	int rowstep; + +	rowstep = jas_matrix_rowstep(matrix); +	for (i = matrix->numrows_, rowstart = matrix->rows_[0]; i > 0; --i, +	  rowstart += rowstep) { +		data = rowstart; +		for (j = matrix->numcols_, data = rowstart; j > 0; --j, +		  ++data) { +			v = *data; +			if (v < minval) { +				*data = minval; +			} else if (v > maxval) { +				*data = maxval; +			} +		} +	} +} + +void jas_matrix_asr(jas_matrix_t *matrix, int n) +{ +	int i; +	int j; +	jas_seqent_t *rowstart; +	int rowstep; +	jas_seqent_t *data; + +	assert(n >= 0); +	rowstep = jas_matrix_rowstep(matrix); +	for (i = matrix->numrows_, rowstart = matrix->rows_[0]; i > 0; --i, +	  rowstart += rowstep) { +		for (j = matrix->numcols_, data = rowstart; j > 0; --j, +		  ++data) { +			*data >>= n; +		} +	} +} + +void jas_matrix_asl(jas_matrix_t *matrix, int n) +{ +	int i; +	int j; +	jas_seqent_t *rowstart; +	int rowstep; +	jas_seqent_t *data; + +	rowstep = jas_matrix_rowstep(matrix); +	for (i = matrix->numrows_, rowstart = matrix->rows_[0]; i > 0; --i, +	  rowstart += rowstep) { +		for (j = matrix->numcols_, data = rowstart; j > 0; --j, +		  ++data) { +			*data <<= n; +		} +	} +} + +/******************************************************************************\ +* Code. +\******************************************************************************/ + +int jas_matrix_resize(jas_matrix_t *matrix, int numrows, int numcols) +{ +	int size; +	int i; + +	size = numrows * numcols; +	if (size > matrix->datasize_ || numrows > matrix->maxrows_) { +		return -1; +	} + +	matrix->numrows_ = numrows; +	matrix->numcols_ = numcols; + +	for (i = 0; i < numrows; ++i) { +		matrix->rows_[i] = &matrix->data_[numcols * i]; +	} + +	return 0; +} + +void jas_matrix_setall(jas_matrix_t *matrix, jas_seqent_t val) +{ +	int i; +	int j; +	jas_seqent_t *rowstart; +	int rowstep; +	jas_seqent_t *data; + +	rowstep = jas_matrix_rowstep(matrix); +	for (i = matrix->numrows_, rowstart = matrix->rows_[0]; i > 0; --i, +	  rowstart += rowstep) { +		for (j = matrix->numcols_, data = rowstart; j > 0; --j, +		  ++data) { +			*data = val; +		} +	} +} + +jas_matrix_t *jas_seq2d_input(FILE *in) +{ +	jas_matrix_t *matrix; +	int i; +	int j; +	long x; +	int numrows; +	int numcols; +	int xoff; +	int yoff; + +	if (fscanf(in, "%d %d", &xoff, &yoff) != 2) +		return 0; +	if (fscanf(in, "%d %d", &numcols, &numrows) != 2) +		return 0; +	if (!(matrix = jas_seq2d_create(xoff, yoff, xoff + numcols, yoff + numrows))) +		return 0; + +	if (jas_matrix_numrows(matrix) != numrows || jas_matrix_numcols(matrix) != numcols) { +		abort(); +	} + +	/* Get matrix data. */ +	for (i = 0; i < jas_matrix_numrows(matrix); i++) { +		for (j = 0; j < jas_matrix_numcols(matrix); j++) { +			if (fscanf(in, "%ld", &x) != 1) { +				jas_matrix_destroy(matrix); +				return 0; +			} +			jas_matrix_set(matrix, i, j, JAS_CAST(jas_seqent_t, x)); +		} +	} + +	return matrix; +} + +int jas_seq2d_output(jas_matrix_t *matrix, FILE *out) +{ +#define MAXLINELEN	80 +	int i; +	int j; +	jas_seqent_t x; +	char buf[MAXLINELEN + 1]; +	char sbuf[MAXLINELEN + 1]; +	int n; + +	fprintf(out, "%d %d\n", jas_seq2d_xstart(matrix), +	  jas_seq2d_ystart(matrix)); +	fprintf(out, "%d %d\n", jas_matrix_numcols(matrix), +	  jas_matrix_numrows(matrix)); + +	buf[0] = '\0'; +	for (i = 0; i < jas_matrix_numrows(matrix); ++i) { +		for (j = 0; j < jas_matrix_numcols(matrix); ++j) { +			x = jas_matrix_get(matrix, i, j); +			sprintf(sbuf, "%s%4ld", (strlen(buf) > 0) ? " " : "", +			  JAS_CAST(long, x)); +			n = strlen(buf); +			if (n + strlen(sbuf) > MAXLINELEN) { +				fputs(buf, out); +				fputs("\n", out); +				buf[0] = '\0'; +			} +			strcat(buf, sbuf); +			if (j == jas_matrix_numcols(matrix) - 1) { +				fputs(buf, out); +				fputs("\n", out); +				buf[0] = '\0'; +			} +		} +	} +	fputs(buf, out); + +	return 0; +} diff --git a/src/libjasper/base/jas_stream.c b/src/libjasper/base/jas_stream.c new file mode 100644 index 0000000..f2b6d3a --- /dev/null +++ b/src/libjasper/base/jas_stream.c @@ -0,0 +1,1151 @@ +/* + * Copyright (c) 1999-2000 Image Power, Inc. and the University of + *   British Columbia. + * Copyright (c) 2001-2003 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__ + */ + +/* + * I/O Stream Library + * + * $Id: jas_stream.c,v 1.1 2008/10/17 06:14:59 scuri Exp $ + */ + +/******************************************************************************\ +* Includes. +\******************************************************************************/ + +#include <assert.h> +#if defined(HAVE_FCNTL_H) +#include <fcntl.h> +#endif +#include <stdlib.h> +#include <stdarg.h> +#include <stdio.h> +#include <ctype.h> +#if defined(HAVE_UNISTD_H) +#include <unistd.h> +#endif +#if defined(WIN32) || defined(HAVE_IO_H) +#include <io.h> +#endif + +#include "jasper/jas_types.h" +#include "jasper/jas_stream.h" +#include "jasper/jas_malloc.h" +#include "jasper/jas_math.h" + +/******************************************************************************\ +* Local function prototypes. +\******************************************************************************/ + +static int jas_strtoopenmode(const char *s); +static void jas_stream_destroy(jas_stream_t *stream); +jas_stream_t *jas_stream_create(void);  /* IMLIB - removed static, so it can be used in jas_binfile.c */ +void jas_stream_initbuf(jas_stream_t *stream, int bufmode, char *buf,  /* IMLIB - removed static, so it can be used in jas_binfile.c */ +  int bufsize); + +static int mem_read(jas_stream_obj_t *obj, char *buf, int cnt); +static int mem_write(jas_stream_obj_t *obj, char *buf, int cnt); +static long mem_seek(jas_stream_obj_t *obj, long offset, int origin); +static int mem_close(jas_stream_obj_t *obj); + +static int sfile_read(jas_stream_obj_t *obj, char *buf, int cnt); +static int sfile_write(jas_stream_obj_t *obj, char *buf, int cnt); +static long sfile_seek(jas_stream_obj_t *obj, long offset, int origin); +static int sfile_close(jas_stream_obj_t *obj); + +static int file_read(jas_stream_obj_t *obj, char *buf, int cnt); +static int file_write(jas_stream_obj_t *obj, char *buf, int cnt); +static long file_seek(jas_stream_obj_t *obj, long offset, int origin); +static int file_close(jas_stream_obj_t *obj); + +/******************************************************************************\ +* Local data. +\******************************************************************************/ + +static jas_stream_ops_t jas_stream_fileops = { +	file_read, +	file_write, +	file_seek, +	file_close +}; + +static jas_stream_ops_t jas_stream_sfileops = { +	sfile_read, +	sfile_write, +	sfile_seek, +	sfile_close +}; + +static jas_stream_ops_t jas_stream_memops = { +	mem_read, +	mem_write, +	mem_seek, +	mem_close +}; + +/******************************************************************************\ +* Code for opening and closing streams. +\******************************************************************************/ + +jas_stream_t *jas_stream_create()  /* IMLIB - removed static, so it can be used in jas_binfile.c */ +{ +	jas_stream_t *stream; + +	if (!(stream = jas_malloc(sizeof(jas_stream_t)))) { +		return 0; +	} +	stream->openmode_ = 0; +	stream->bufmode_ = 0; +	stream->flags_ = 0; +	stream->bufbase_ = 0; +	stream->bufstart_ = 0; +	stream->bufsize_ = 0; +	stream->ptr_ = 0; +	stream->cnt_ = 0; +	stream->ops_ = 0; +	stream->obj_ = 0; +	stream->rwcnt_ = 0; +	stream->rwlimit_ = -1; + +	return stream; +} + +jas_stream_t *jas_stream_memopen(char *buf, int bufsize) +{ +	jas_stream_t *stream; +	jas_stream_memobj_t *obj; + +	if (!(stream = jas_stream_create())) { +		return 0; +	} + +	/* A stream associated with a memory buffer is always opened +	for both reading and writing in binary mode. */ +	stream->openmode_ = JAS_STREAM_READ | JAS_STREAM_WRITE | JAS_STREAM_BINARY; + +	/* Since the stream data is already resident in memory, buffering +	is not necessary. */ +	/* But... It still may be faster to use buffering anyways. */ +	jas_stream_initbuf(stream, JAS_STREAM_FULLBUF, 0, 0); + +	/* Select the operations for a memory stream. */ +	stream->ops_ = &jas_stream_memops; + +	/* Allocate memory for the underlying memory stream object. */ +	if (!(obj = jas_malloc(sizeof(jas_stream_memobj_t)))) { +		jas_stream_destroy(stream); +		return 0; +	} +	stream->obj_ = (void *) obj; + +	/* Initialize a few important members of the memory stream object. */ +	obj->myalloc_ = 0; +	obj->buf_ = 0; + +	/* If the buffer size specified is nonpositive, then the buffer +	is allocated internally and automatically grown as needed. */ +	if (bufsize <= 0) { +		obj->bufsize_ = 1024; +		obj->growable_ = 1; +	} else { +		obj->bufsize_ = bufsize; +		obj->growable_ = 0; +	} +	if (buf) { +		obj->buf_ = (unsigned char *) buf; +	} else { +		obj->buf_ = jas_malloc(obj->bufsize_ * sizeof(char)); +		obj->myalloc_ = 1; +	} +	if (!obj->buf_) { +		jas_stream_close(stream); +		return 0; +	} + +	if (bufsize > 0 && buf) { +		/* If a buffer was supplied by the caller and its length is positive, +		  make the associated buffer data appear in the stream initially. */ +		obj->len_ = bufsize; +	} else { +		/* The stream is initially empty. */ +		obj->len_ = 0; +	} +	obj->pos_ = 0; +	 +	return stream; +} + +jas_stream_t *jas_stream_fopen(const char *filename, const char *mode) +{ +	jas_stream_t *stream; +	jas_stream_fileobj_t *obj; +	int openflags; + +	/* Allocate a stream object. */ +	if (!(stream = jas_stream_create())) { +		return 0; +	} + +	/* Parse the mode string. */ +	stream->openmode_ = jas_strtoopenmode(mode); + +	/* Determine the correct flags to use for opening the file. */ +	if ((stream->openmode_ & JAS_STREAM_READ) && +	  (stream->openmode_ & JAS_STREAM_WRITE)) { +		openflags = O_RDWR; +	} else if (stream->openmode_ & JAS_STREAM_READ) { +		openflags = O_RDONLY; +	} else if (stream->openmode_ & JAS_STREAM_WRITE) { +		openflags = O_WRONLY; +	} else { +		openflags = 0; +	} +	if (stream->openmode_ & JAS_STREAM_APPEND) { +		openflags |= O_APPEND; +	} +	if (stream->openmode_ & JAS_STREAM_BINARY) { +		openflags |= O_BINARY; +	} +	if (stream->openmode_ & JAS_STREAM_CREATE) { +		openflags |= O_CREAT | O_TRUNC; +	} + +	/* Allocate space for the underlying file stream object. */ +	if (!(obj = jas_malloc(sizeof(jas_stream_fileobj_t)))) { +		jas_stream_destroy(stream); +		return 0; +	} +	obj->fd = -1; +	obj->flags = 0; +	//obj->pathname[0] = '\0'; +  strncpy(obj->pathname, filename, DIM_MAX_FILE_NAME); // GeoJasper: dima +	stream->obj_ = (void *) obj; + +	/* Select the operations for a file stream object. */ +	stream->ops_ = &jas_stream_fileops; + +	/* Open the underlying file. */ +	if ((obj->fd = open(filename, openflags, JAS_STREAM_PERMS)) < 0) { +		jas_stream_destroy(stream); +		return 0; +	} + +	/* By default, use full buffering for this type of stream. */ +	jas_stream_initbuf(stream, JAS_STREAM_FULLBUF, 0, 0); + +	return stream; +} + +jas_stream_t *jas_stream_freopen(const char *path, const char *mode, FILE *fp) +{ +	jas_stream_t *stream; +	int openflags; + +	/* Eliminate compiler warning about unused variable. */ +	path = 0; + +	/* Allocate a stream object. */ +	if (!(stream = jas_stream_create())) { +		return 0; +	} + +	/* Parse the mode string. */ +	stream->openmode_ = jas_strtoopenmode(mode); + +	/* Determine the correct flags to use for opening the file. */ +	if ((stream->openmode_ & JAS_STREAM_READ) && +	  (stream->openmode_ & JAS_STREAM_WRITE)) { +		openflags = O_RDWR; +	} else if (stream->openmode_ & JAS_STREAM_READ) { +		openflags = O_RDONLY; +	} else if (stream->openmode_ & JAS_STREAM_WRITE) { +		openflags = O_WRONLY; +	} else { +		openflags = 0; +	} +	if (stream->openmode_ & JAS_STREAM_APPEND) { +		openflags |= O_APPEND; +	} +	if (stream->openmode_ & JAS_STREAM_BINARY) { +		openflags |= O_BINARY; +	} +	if (stream->openmode_ & JAS_STREAM_CREATE) { +		openflags |= O_CREAT | O_TRUNC; +	} + +	stream->obj_ = JAS_CAST(void *, fp); + +	/* Select the operations for a file stream object. */ +	stream->ops_ = &jas_stream_sfileops; + +	/* By default, use full buffering for this type of stream. */ +	jas_stream_initbuf(stream, JAS_STREAM_FULLBUF, 0, 0); + +	return stream; +} + +jas_stream_t *jas_stream_tmpfile() +{ +	jas_stream_t *stream; +	jas_stream_fileobj_t *obj; + +	if (!(stream = jas_stream_create())) { +		return 0; +	} + +	/* A temporary file stream is always opened for both reading and +	writing in binary mode. */ +	stream->openmode_ = JAS_STREAM_READ | JAS_STREAM_WRITE | JAS_STREAM_BINARY; + +	/* Allocate memory for the underlying temporary file object. */ +	if (!(obj = jas_malloc(sizeof(jas_stream_fileobj_t)))) { +		jas_stream_destroy(stream); +		return 0; +	} +	obj->fd = -1; +	obj->flags = 0; +	obj->pathname[0] = '\0'; +	stream->obj_ = obj; + +	/* Choose a file name. */ +	tmpnam(obj->pathname); + +	/* Open the underlying file. */ +	if ((obj->fd = open(obj->pathname, O_CREAT | O_EXCL | O_RDWR | O_TRUNC | O_BINARY, +	  JAS_STREAM_PERMS)) < 0) { +		jas_stream_destroy(stream); +		return 0; +	} + +	/* Unlink the file so that it will disappear if the program +	terminates abnormally. */ +	/* Under UNIX, one can unlink an open file and continue to do I/O +	on it.  Not all operating systems support this functionality, however. +	For example, under Microsoft Windows the unlink operation will fail, +	since the file is open. */ +	if (unlink(obj->pathname)) { +		/* We will try unlinking the file again after it is closed. */ +		obj->flags |= JAS_STREAM_FILEOBJ_DELONCLOSE; +	} + +	/* Use full buffering. */ +	jas_stream_initbuf(stream, JAS_STREAM_FULLBUF, 0, 0); + +	stream->ops_ = &jas_stream_fileops; + +	return stream; +} + +jas_stream_t *jas_stream_fdopen(int fd, const char *mode) +{ +	jas_stream_t *stream; +	jas_stream_fileobj_t *obj; + +	/* Allocate a stream object. */ +	if (!(stream = jas_stream_create())) { +		return 0; +	} + +	/* Parse the mode string. */ +	stream->openmode_ = jas_strtoopenmode(mode); + +#if defined(WIN32) +	/* Argh!!!  Someone ought to banish text mode (i.e., O_TEXT) to the +	  greatest depths of purgatory! */ +	/* Ensure that the file descriptor is in binary mode, if the caller +	  has specified the binary mode flag.  Arguably, the caller ought to +	  take care of this, but text mode is a ugly wart anyways, so we save +	  the caller some grief by handling this within the stream library. */ +	/* This ugliness is mainly for the benefit of those who run the +	  JasPer software under Windows from shells that insist on opening +	  files in text mode.  For example, in the Cygwin environment, +	  shells often open files in text mode when I/O redirection is +	  used.  Grr... */ +	if (stream->openmode_ & JAS_STREAM_BINARY) { +		setmode(fd, O_BINARY); +	} +#endif + +	/* Allocate space for the underlying file stream object. */ +	if (!(obj = jas_malloc(sizeof(jas_stream_fileobj_t)))) { +		jas_stream_destroy(stream); +		return 0; +	} +	obj->fd = fd; +	obj->flags = 0; +	obj->pathname[0] = '\0'; +	stream->obj_ = (void *) obj; + +	/* Do not close the underlying file descriptor when the stream is +	closed. */ +	obj->flags |= JAS_STREAM_FILEOBJ_NOCLOSE; + +	/* By default, use full buffering for this type of stream. */ +	jas_stream_initbuf(stream, JAS_STREAM_FULLBUF, 0, 0); + +	/* Select the operations for a file stream object. */ +	stream->ops_ = &jas_stream_fileops; + +	return stream; +} + +static void jas_stream_destroy(jas_stream_t *stream) +{ +	/* If the memory for the buffer was allocated with malloc, free +	this memory. */ +	if ((stream->bufmode_ & JAS_STREAM_FREEBUF) && stream->bufbase_) { +		jas_free(stream->bufbase_); +		stream->bufbase_ = 0; +	} +	jas_free(stream); +} + +int jas_stream_close(jas_stream_t *stream) +{ +	/* Flush buffer if necessary. */ +	jas_stream_flush(stream); + +	/* Close the underlying stream object. */ +	(*stream->ops_->close_)(stream->obj_); + +	jas_stream_destroy(stream); + +	return 0; +} + +/******************************************************************************\ +* Code for reading and writing streams. +\******************************************************************************/ + +int jas_stream_getc_func(jas_stream_t *stream) +{ +	assert(stream->ptr_ - stream->bufbase_ <= stream->bufsize_ + +	  JAS_STREAM_MAXPUTBACK); +	return jas_stream_getc_macro(stream); +} + +int jas_stream_putc_func(jas_stream_t *stream, int c) +{ +	assert(stream->ptr_ - stream->bufstart_ <= stream->bufsize_); +	return jas_stream_putc_macro(stream, c); +} + +int jas_stream_ungetc(jas_stream_t *stream, int c) +{ +	if (!stream->ptr_ || stream->ptr_ == stream->bufbase_) { +		return -1; +	} + +	/* Reset the EOF indicator (since we now have at least one character +	  to read). */ +	stream->flags_ &= ~JAS_STREAM_EOF; + +	--stream->rwcnt_; +	--stream->ptr_; +	++stream->cnt_; +	*stream->ptr_ = c; +	return 0; +} + +int jas_stream_read(jas_stream_t *stream, void *buf, int cnt) +{ +	int n; +	int c; +	char *bufptr; + +	bufptr = buf; + +	n = 0; +	while (n < cnt) { +		if ((c = jas_stream_getc(stream)) == EOF) { +			return n; +		} +		*bufptr++ = c; +		++n; +	} + +	return n; +} + +int jas_stream_write(jas_stream_t *stream, const void *buf, int cnt) +{ +	int n; +	const char *bufptr; + +	bufptr = buf; + +	n = 0; +	while (n < cnt) { +		if (jas_stream_putc(stream, *bufptr) == EOF) { +			return n; +		} +		++bufptr; +		++n; +	} + +	return n; +} + +/* Note: This function uses a fixed size buffer.  Therefore, it cannot +  handle invocations that will produce more output than can be held +  by the buffer. */ +int jas_stream_printf(jas_stream_t *stream, const char *fmt, ...) +{ +	va_list ap; +	char buf[4096]; +	int ret; + +	va_start(ap, fmt); +	ret = vsprintf(buf, fmt, ap); +	jas_stream_puts(stream, buf); +	va_end(ap); +	return ret; +} + +int jas_stream_puts(jas_stream_t *stream, const char *s) +{ +	while (*s != '\0') { +		if (jas_stream_putc_macro(stream, *s) == EOF) { +			return -1; +		} +		++s; +	} +	return 0; +} + +char *jas_stream_gets(jas_stream_t *stream, char *buf, int bufsize) +{ +	int c; +	char *bufptr; +	assert(bufsize > 0); + +	bufptr = buf; +	while (bufsize > 1) { +		if ((c = jas_stream_getc(stream)) == EOF) { +			break; +		} +		*bufptr++ = c; +		--bufsize; +		if (c == '\n') { +			break; +		} +	} +	*bufptr = '\0'; +	return buf; +} + +int jas_stream_gobble(jas_stream_t *stream, int n) +{ +	int m; +	m = n; +	for (m = n; m > 0; --m) { +		if (jas_stream_getc(stream) == EOF) { +			return n - m; +		} +	} +	return n; +} + +int jas_stream_pad(jas_stream_t *stream, int n, int c) +{ +	int m; +	m = n; +	for (m = n; m > 0; --m) { +		if (jas_stream_putc(stream, c) == EOF) +			return n - m; +	} +	return n; +} + +/******************************************************************************\ +* Code for getting and setting the stream position. +\******************************************************************************/ + +int jas_stream_isseekable(jas_stream_t *stream) +{ +	if (stream->ops_ == &jas_stream_memops) { +		return 1; +	} else if (stream->ops_ == &jas_stream_fileops) { +		if ((*stream->ops_->seek_)(stream->obj_, 0, SEEK_CUR) < 0) { +			return 0; +		} +		return 1; +	} else { +		return 0; +	} +} + +int jas_stream_rewind(jas_stream_t *stream) +{ +	return jas_stream_seek(stream, 0, SEEK_SET); +} + +long jas_stream_seek(jas_stream_t *stream, long offset, int origin) +{ +	long newpos; + +	/* The buffer cannot be in use for both reading and writing. */ +	assert(!((stream->bufmode_ & JAS_STREAM_RDBUF) && (stream->bufmode_ & +	  JAS_STREAM_WRBUF))); + +	/* Reset the EOF indicator (since we may not be at the EOF anymore). */ +	stream->flags_ &= ~JAS_STREAM_EOF; + +	if (stream->bufmode_ & JAS_STREAM_RDBUF) { +		if (origin == SEEK_CUR) { +			offset -= stream->cnt_; +		} +	} else if (stream->bufmode_ & JAS_STREAM_WRBUF) { +		if (jas_stream_flush(stream)) { +			return -1; +		} +	} +	stream->cnt_ = 0; +	stream->ptr_ = stream->bufstart_; +	stream->bufmode_ &= ~(JAS_STREAM_RDBUF | JAS_STREAM_WRBUF); + +	if ((newpos = (*stream->ops_->seek_)(stream->obj_, offset, origin)) +	  < 0) { +		return -1; +	} + +	return newpos; +} + +long jas_stream_tell(jas_stream_t *stream) +{ +	int adjust; +	int offset; + +	if (stream->bufmode_ & JAS_STREAM_RDBUF) { +		adjust = -stream->cnt_; +	} else if (stream->bufmode_ & JAS_STREAM_WRBUF) { +		adjust = stream->ptr_ - stream->bufstart_; +	} else { +		adjust = 0; +	} + +	if ((offset = (*stream->ops_->seek_)(stream->obj_, 0, SEEK_CUR)) < 0) { +		return -1; +	} + +	return offset + adjust; +} + +/******************************************************************************\ +* Buffer initialization code. +\******************************************************************************/ + +void jas_stream_initbuf(jas_stream_t *stream, int bufmode, char *buf, /* IMLIB - removed static, so it can be used in jas_binfile.c */ +  int bufsize) +{ +	/* If this function is being called, the buffer should not have been +	  initialized yet. */ +	assert(!stream->bufbase_); + +	if (bufmode != JAS_STREAM_UNBUF) { +		/* The full- or line-buffered mode is being employed. */ +		if (!buf) { +			/* The caller has not specified a buffer to employ, so allocate +			  one. */ +			if ((stream->bufbase_ = jas_malloc(JAS_STREAM_BUFSIZE + +			  JAS_STREAM_MAXPUTBACK))) { +				stream->bufmode_ |= JAS_STREAM_FREEBUF; +				stream->bufsize_ = JAS_STREAM_BUFSIZE; +			} else { +				/* The buffer allocation has failed.  Resort to unbuffered +				  operation. */ +				stream->bufbase_ = stream->tinybuf_; +				stream->bufsize_ = 1; +			} +		} else { +			/* The caller has specified a buffer to employ. */ +			/* The buffer must be large enough to accommodate maximum +			  putback. */ +			assert(bufsize > JAS_STREAM_MAXPUTBACK); +			stream->bufbase_ = JAS_CAST(uchar *, buf); +			stream->bufsize_ = bufsize - JAS_STREAM_MAXPUTBACK; +		} +	} else { +		/* The unbuffered mode is being employed. */ +		/* A buffer should not have been supplied by the caller. */ +		assert(!buf); +		/* Use a trivial one-character buffer. */ +		stream->bufbase_ = stream->tinybuf_; +		stream->bufsize_ = 1; +	} +	stream->bufstart_ = &stream->bufbase_[JAS_STREAM_MAXPUTBACK]; +	stream->ptr_ = stream->bufstart_; +	stream->cnt_ = 0; +	stream->bufmode_ |= bufmode & JAS_STREAM_BUFMODEMASK; +} + +/******************************************************************************\ +* Buffer filling and flushing code. +\******************************************************************************/ + +int jas_stream_flush(jas_stream_t *stream) +{ +	if (stream->bufmode_ & JAS_STREAM_RDBUF) { +		return 0; +	} +	return jas_stream_flushbuf(stream, EOF); +} + +int jas_stream_fillbuf(jas_stream_t *stream, int getflag) +{ +	int c; + +	/* The stream must not be in an error or EOF state. */ +	if ((stream->flags_ & (JAS_STREAM_ERRMASK)) != 0) { +		return EOF; +	} + +	/* The stream must be open for reading. */ +	if ((stream->openmode_ & JAS_STREAM_READ) == 0) { +		return EOF; +	} + +	/* Make a half-hearted attempt to confirm that the buffer is not +	currently being used for writing.  This check is not intended +	to be foolproof! */ +	assert((stream->bufmode_ & JAS_STREAM_WRBUF) == 0); + +	assert(stream->ptr_ - stream->bufstart_ <= stream->bufsize_); + +	/* Mark the buffer as being used for reading. */ +	stream->bufmode_ |= JAS_STREAM_RDBUF; + +	/* Read new data into the buffer. */ +	stream->ptr_ = stream->bufstart_; +	if ((stream->cnt_ = (*stream->ops_->read_)(stream->obj_, +	  (char *) stream->bufstart_, stream->bufsize_)) <= 0) { +		if (stream->cnt_ < 0) { +			stream->flags_ |= JAS_STREAM_ERR; +		} else { +			stream->flags_ |= JAS_STREAM_EOF; +		} +		stream->cnt_ = 0; +		return EOF; +	} + +	assert(stream->cnt_ > 0); +	/* Get or peek at the first character in the buffer. */ +	c = (getflag) ? jas_stream_getc2(stream) : (*stream->ptr_); + +	return c; +} + +int jas_stream_flushbuf(jas_stream_t *stream, int c) +{ +	int len; +	int n; + +	/* The stream should not be in an error or EOF state. */ +	if ((stream->flags_ & (JAS_STREAM_ERRMASK)) != 0) { +		return EOF; +	} + +	/* The stream must be open for writing. */ +	if ((stream->openmode_ & (JAS_STREAM_WRITE | JAS_STREAM_APPEND)) == 0) { +		return EOF; +	} + +	/* The buffer should not currently be in use for reading. */ +	assert(!(stream->bufmode_ & JAS_STREAM_RDBUF)); + +	/* Note: Do not use the quantity stream->cnt to determine the number +	of characters in the buffer!  Depending on how this function was +	called, the stream->cnt value may be "off-by-one". */ +	len = stream->ptr_ - stream->bufstart_; +	if (len > 0) { +		n = (*stream->ops_->write_)(stream->obj_, (char *) +		  stream->bufstart_, len); +		if (n != len) { +			stream->flags_ |= JAS_STREAM_ERR; +			return EOF; +		} +	} +	stream->cnt_ = stream->bufsize_; +	stream->ptr_ = stream->bufstart_; + +	stream->bufmode_ |= JAS_STREAM_WRBUF; + +	if (c != EOF) { +		assert(stream->cnt_ > 0); +		return jas_stream_putc2(stream, c); +	} + +	return 0; +} + +/******************************************************************************\ +* Miscellaneous code. +\******************************************************************************/ + +static int jas_strtoopenmode(const char *s) +{ +	int openmode = 0; +	while (*s != '\0') { +		switch (*s) { +		case 'r': +			openmode |= JAS_STREAM_READ; +			break; +		case 'w': +			openmode |= JAS_STREAM_WRITE | JAS_STREAM_CREATE; +			break; +		case 'b': +			openmode |= JAS_STREAM_BINARY; +			break; +		case 'a': +			openmode |= JAS_STREAM_APPEND; +			break; +		case '+': +			openmode |= JAS_STREAM_READ | JAS_STREAM_WRITE; +			break; +		default: +			break; +		} +		++s; +	} +	return openmode; +} + +int jas_stream_copy(jas_stream_t *out, jas_stream_t *in, int n) +{ +	int all; +	int c; +	int m; + +	all = (n < 0) ? 1 : 0; + +	m = n; +	while (all || m > 0) { +		if ((c = jas_stream_getc_macro(in)) == EOF) { +			/* The next character of input could not be read. */ +			/* Return with an error if an I/O error occured +			  (not including EOF) or if an explicit copy count +			  was specified. */ +			return (!all || jas_stream_error(in)) ? (-1) : 0; +		} +		if (jas_stream_putc_macro(out, c) == EOF) { +			return -1; +		} +		--m; +	} +	return 0; +} + +long jas_stream_setrwcount(jas_stream_t *stream, long rwcnt) +{ +	int old; + +	old = stream->rwcnt_; +	stream->rwcnt_ = rwcnt; +	return old; +} + +int jas_stream_display(jas_stream_t *stream, FILE *fp, int n) +{ +	unsigned char buf[16]; +	int i; +	int j; +	int m; +	int c; +	int display; +	int cnt; + +	cnt = n - (n % 16); +	display = 1; + +	for (i = 0; i < n; i += 16) { +		if (n > 16 && i > 0) { +			display = (i >= cnt) ? 1 : 0; +		} +		if (display) { +			fprintf(fp, "%08x:", i); +		} +		m = JAS_MIN(n - i, 16); +		for (j = 0; j < m; ++j) { +			if ((c = jas_stream_getc(stream)) == EOF) { +				abort(); +				return -1; +			} +			buf[j] = c; +		} +		if (display) { +			for (j = 0; j < m; ++j) { +				fprintf(fp, " %02x", buf[j]); +			} +			fputc(' ', fp); +			for (; j < 16; ++j) { +				fprintf(fp, "   "); +			} +			for (j = 0; j < m; ++j) { +				if (isprint(buf[j])) { +					fputc(buf[j], fp); +				} else { +					fputc(' ', fp); +				} +			} +			fprintf(fp, "\n"); +		} + + +	} +	return 0; +} + +long jas_stream_length(jas_stream_t *stream) +{ +	long oldpos; +	long pos; +	if ((oldpos = jas_stream_tell(stream)) < 0) { +		return -1; +	} +	if (jas_stream_seek(stream, 0, SEEK_END) < 0) { +		return -1; +	} +	if ((pos = jas_stream_tell(stream)) < 0) { +		return -1; +	} +	if (jas_stream_seek(stream, oldpos, SEEK_SET) < 0) { +		return -1; +	} +	return pos; +} + +/******************************************************************************\ +* Memory stream object. +\******************************************************************************/ + +static int mem_read(jas_stream_obj_t *obj, char *buf, int cnt) +{ +	int n; +	jas_stream_memobj_t *m = (jas_stream_memobj_t *)obj; +	n = m->len_ - m->pos_; +	cnt = JAS_MIN(n, cnt); +	memcpy(buf, &m->buf_[m->pos_], cnt); +	m->pos_ += cnt; +	return cnt; +} + +static int mem_resize(jas_stream_memobj_t *m, int bufsize) +{ +	unsigned char *buf; + +	assert(m->buf_); +	if (!(buf = jas_realloc(m->buf_, bufsize * sizeof(unsigned char)))) { +		return -1; +	} +	m->buf_ = buf; +	m->bufsize_ = bufsize; +	return 0; +} + +static int mem_write(jas_stream_obj_t *obj, char *buf, int cnt) +{ +	int n; +	int ret; +	jas_stream_memobj_t *m = (jas_stream_memobj_t *)obj; +	long newbufsize; +	long newpos; + +	newpos = m->pos_ + cnt; +	if (newpos > m->bufsize_ && m->growable_) { +		newbufsize = m->bufsize_; +		while (newbufsize < newpos) { +			newbufsize <<= 1; +			assert(newbufsize >= 0); +		} +		if (mem_resize(m, newbufsize)) { +			return -1; +		} +	} +	if (m->pos_ > m->len_) { +		/* The current position is beyond the end of the file, so +		  pad the file to the current position with zeros. */ +		n = JAS_MIN(m->pos_, m->bufsize_) - m->len_; +		if (n > 0) { +			memset(&m->buf_[m->len_], 0, n); +			m->len_ += n; +		} +		if (m->pos_ != m->len_) { +			/* The buffer is not big enough. */ +			return 0; +		} +	} +	n = m->bufsize_ - m->pos_; +	ret = JAS_MIN(n, cnt); +	if (ret > 0) { +		memcpy(&m->buf_[m->pos_], buf, ret); +		m->pos_ += ret; +	} +	if (m->pos_ > m->len_) { +		m->len_ = m->pos_; +	} +assert(ret == cnt); +	return ret; +} + +static long mem_seek(jas_stream_obj_t *obj, long offset, int origin) +{ +	jas_stream_memobj_t *m = (jas_stream_memobj_t *)obj; +	long newpos; + +	switch (origin) { +	case SEEK_SET: +		newpos = offset; +		break; +	case SEEK_END: +		newpos = m->len_ - offset; +		break; +	case SEEK_CUR: +		newpos = m->pos_ + offset; +		break; +	default: +		abort(); +		break; +	} +	if (newpos < 0) { +		return -1; +	} +	m->pos_ = newpos; + +	return m->pos_; +} + +static int mem_close(jas_stream_obj_t *obj) +{ +	jas_stream_memobj_t *m = (jas_stream_memobj_t *)obj; +	if (m->myalloc_ && m->buf_) { +		jas_free(m->buf_); +		m->buf_ = 0; +	} +	jas_free(obj); +	return 0; +} + +/******************************************************************************\ +* File stream object. +\******************************************************************************/ + +static int file_read(jas_stream_obj_t *obj, char *buf, int cnt) +{ +	jas_stream_fileobj_t *fileobj = JAS_CAST(jas_stream_fileobj_t *, obj); +	return read(fileobj->fd, buf, cnt); +} + +static int file_write(jas_stream_obj_t *obj, char *buf, int cnt) +{ +	jas_stream_fileobj_t *fileobj = JAS_CAST(jas_stream_fileobj_t *, obj); +	return write(fileobj->fd, buf, cnt); +} + +static long file_seek(jas_stream_obj_t *obj, long offset, int origin) +{ +	jas_stream_fileobj_t *fileobj = JAS_CAST(jas_stream_fileobj_t *, obj); +	return lseek(fileobj->fd, offset, origin); +} + +static int file_close(jas_stream_obj_t *obj) +{ +	jas_stream_fileobj_t *fileobj = JAS_CAST(jas_stream_fileobj_t *, obj); +	int ret; +	ret = close(fileobj->fd); +	if (fileobj->flags & JAS_STREAM_FILEOBJ_DELONCLOSE) { +		unlink(fileobj->pathname); +	} +	jas_free(fileobj); +	return ret; +} + +/******************************************************************************\ +* Stdio file stream object. +\******************************************************************************/ + +static int sfile_read(jas_stream_obj_t *obj, char *buf, int cnt) +{ +	FILE *fp; +	fp = JAS_CAST(FILE *, obj); +	return fread(buf, 1, cnt, fp); +} + +static int sfile_write(jas_stream_obj_t *obj, char *buf, int cnt) +{ +	FILE *fp; +	fp = JAS_CAST(FILE *, obj); +	return fwrite(buf, 1, cnt, fp); +} + +static long sfile_seek(jas_stream_obj_t *obj, long offset, int origin) +{ +	FILE *fp; +	fp = JAS_CAST(FILE *, obj); +	return fseek(fp, offset, origin); +} + +static int sfile_close(jas_stream_obj_t *obj) +{ +	FILE *fp; +	fp = JAS_CAST(FILE *, obj); +	return fclose(fp); +} diff --git a/src/libjasper/base/jas_string.c b/src/libjasper/base/jas_string.c new file mode 100644 index 0000000..787e703 --- /dev/null +++ b/src/libjasper/base/jas_string.c @@ -0,0 +1,96 @@ +/* + * 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__ + */ + +/* + * String Library + * + * $Id: jas_string.c,v 1.1 2008/10/17 06:14:59 scuri Exp $ + */ + +/******************************************************************************\ +* Includes +\******************************************************************************/ + +#include <string.h> + +#include "jasper/jas_malloc.h" +#include "jasper/jas_string.h" + +/******************************************************************************\ +* Miscellaneous Functions +\******************************************************************************/ + +/* This function is equivalent to the popular but non-standard (and +  not-always-available) strdup function. */ + +char *jas_strdup(const char *s) +{ +	int n; +	char *p; +	n = strlen(s) + 1; +	if (!(p = jas_malloc(n * sizeof(char)))) { +		return 0; +	} +	strcpy(p, s); +	return p; +} diff --git a/src/libjasper/base/jas_tmr.c b/src/libjasper/base/jas_tmr.c new file mode 100644 index 0000000..942a083 --- /dev/null +++ b/src/libjasper/base/jas_tmr.c @@ -0,0 +1,149 @@ +/* + * Copyright (c) 2004 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__ + */ + +/* + * Timing Routines + * + * $Id: jas_tmr.c,v 1.1 2008/10/17 06:14:59 scuri Exp $ + */ + +/******************************************************************************\ +* Includes. +\******************************************************************************/ + +#include <stdio.h> +#include <stdlib.h> +#include <time.h> + +#include "jasper/jas_tmr.h" + +/******************************************************************************\ +* Code. +\******************************************************************************/ + +#if defined(HAVE_GETTIMEOFDAY) + +void jas_tmr_start(jas_tmr_t *tmr) +{ +	if (gettimeofday(&tmr->start, 0)) { +		abort(); +	} +} + +void jas_tmr_stop(jas_tmr_t *tmr) +{ +	if (gettimeofday(&tmr->stop, 0)) { +		abort(); +	} +} + +double jas_tmr_get(jas_tmr_t *tmr) +{ +	double t0; +	double t1; +	t0 = ((double) tmr->start.tv_sec) + ((double) tmr->start.tv_usec) / 1e6; +	t1 = ((double) tmr->stop.tv_sec) + ((double) tmr->stop.tv_usec) / 1e6; +	return t1 - t0; +} + +#elif defined(HAVE_GETRUSAGE) + +void jas_tmr_start(jas_tmr_t *tmr) +{ +	if (getrusage(RUSAGE_SELF, &tmr->start) < 0) { +		abort(); +	} +} + +void jas_tmr_stop(jas_tmr_t *tmr) +{ +	if (getrusage(RUSAGE_SELF, &tmr->stop) < 0) { +		abort(); +	} +} + +double jas_tmr_get(jas_tmr_t *tmr) +{ +	double t; +	t = ((tmr->stop.ru_utime.tv_sec * 1e6 + tmr->stop.ru_utime.tv_usec) - +	  (tmr->start.ru_utime.tv_sec * 1e6 + tmr->start.ru_utime.tv_usec)) / 1e6; +	t += ((tmr->stop.ru_stime.tv_sec * 1e6 + tmr->stop.ru_stime.tv_usec) - +	  (tmr->start.ru_stime.tv_sec * 1e6 + tmr->start.ru_stime.tv_usec)) / 1e6; +	return t; +} + +#else + +void jas_tmr_start(jas_tmr_t *tmr) +{ +} + +void jas_tmr_stop(jas_tmr_t *tmr) +{ +} + +double jas_tmr_get(jas_tmr_t *tmr) +{ +	return 0.0; +} + +#endif + diff --git a/src/libjasper/base/jas_tvp.c b/src/libjasper/base/jas_tvp.c new file mode 100644 index 0000000..4c23476 --- /dev/null +++ b/src/libjasper/base/jas_tvp.c @@ -0,0 +1,237 @@ +/* + * 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__ + */ + +/* + * Tag-Value Parser Library + * + * $Id: jas_tvp.c,v 1.1 2008/10/17 06:14:59 scuri Exp $ + */ + +/******************************************************************************\ +* Includes. +\******************************************************************************/ + +#include <assert.h> +#include <stdio.h> +#include <ctype.h> +#include <stdlib.h> + +#include "jasper/jas_malloc.h" +#include "jasper/jas_string.h" +#include "jasper/jas_tvp.h" + +/******************************************************************************\ +* Macros. +\******************************************************************************/ + +/* Is the specified character valid for a tag name? */ +#define	JAS_TVP_ISTAG(x) \ +	(isalpha(x) || (x) == '_' || isdigit(x)) + +/******************************************************************************\ +* Code for creating and destroying a tag-value parser. +\******************************************************************************/ + +jas_tvparser_t *jas_tvparser_create(const char *s) +{ +	jas_tvparser_t *tvp; +	if (!(tvp = jas_malloc(sizeof(jas_tvparser_t)))) { +		return 0; +	} +	if (!(tvp->buf = jas_strdup(s))) { +		jas_tvparser_destroy(tvp); +		return 0; +	} +	tvp->pos = tvp->buf; +	tvp->tag = 0; +	tvp->val = 0; +	return tvp; +} + +void jas_tvparser_destroy(jas_tvparser_t *tvp) +{ +	if (tvp->buf) { +		jas_free(tvp->buf); +	} +	jas_free(tvp); +} + +/******************************************************************************\ +* Main parsing code. +\******************************************************************************/ + +/* Get the next tag-value pair. */ +int jas_tvparser_next(jas_tvparser_t *tvp) +{ +	char *p; +	char *tag; +	char *val; + +	/* Skip any leading whitespace. */ +	p = tvp->pos; +	while (*p != '\0' && isspace(*p)) { +		++p; +	} + +	/* Has the end of the input data been reached? */ +	if (*p == '\0') { +		/* No more tags are present. */ +		tvp->pos = p; +		return 1; +	} + +	/* Does the tag name begin with a valid character? */ +	if (!JAS_TVP_ISTAG(*p)) { +		return -1; +	} + +	/* Remember where the tag name begins. */ +	tag = p; + +	/* Find the end of the tag name. */ +	while (*p != '\0' && JAS_TVP_ISTAG(*p)) { +		++p; +	} + +	/* Has the end of the input data been reached? */ +	if (*p == '\0') { +		/* The value field is empty. */ +		tvp->tag = tag; +		tvp->val = ""; +		tvp->pos = p; +		return 0; +	} + +	/* Is a value field not present? */ +	if (*p != '=') { +		if (*p != '\0' && !isspace(*p)) { +			return -1; +		} +		*p++ = '\0'; +		tvp->tag = tag; +		tvp->val = ""; +		tvp->pos = p; +		return 0; +	} + +	*p++ = '\0'; + +	val = p; +	while (*p != '\0' && !isspace(*p)) { +		++p; +	} + +	if (*p != '\0') { +		*p++ = '\0'; +	} + +	tvp->pos = p; +	tvp->tag = tag; +	tvp->val = val; + +	return 0; +} + +/******************************************************************************\ +* Code for querying the current tag/value. +\******************************************************************************/ + +/* Get the current tag. */ +char *jas_tvparser_gettag(jas_tvparser_t *tvp) +{ +	return tvp->tag; +} + +/* Get the current value. */ +char *jas_tvparser_getval(jas_tvparser_t *tvp) +{ +	return tvp->val; +} + +/******************************************************************************\ +* Miscellaneous code. +\******************************************************************************/ + +/* Lookup a tag by name. */ +jas_taginfo_t *jas_taginfos_lookup(jas_taginfo_t *taginfos, const char *name) +{ +	jas_taginfo_t *taginfo; +	taginfo = taginfos; +	while (taginfo->id >= 0) { +		if (!strcmp(taginfo->name, name)) { +			return taginfo; +		} +		++taginfo; +	} +	return 0; +} + +/* This function is simply for convenience. */ +/* One can avoid testing for the special case of a null pointer, by +  using this function.   This function never returns a null pointer.  */ +jas_taginfo_t *jas_taginfo_nonull(jas_taginfo_t *taginfo) +{ +	static jas_taginfo_t invalidtaginfo = { +		-1, 0 +	}; +	 +	return taginfo ? taginfo : &invalidtaginfo; +} diff --git a/src/libjasper/base/jas_version.c b/src/libjasper/base/jas_version.c new file mode 100644 index 0000000..f56f253 --- /dev/null +++ b/src/libjasper/base/jas_version.c @@ -0,0 +1,67 @@ +/* + * 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__ + */ + +#include "jasper/jas_version.h" + +const char *jas_getversion() +{ +	return JAS_VERSION; +}  | 
