vx32

Local 9vx git repository for patches.
git clone git://r-36.net/vx32
Log | Files | Refs

jas_image.c (38009B)


      1 /*
      2  * Copyright (c) 1999-2000 Image Power, Inc. and the University of
      3  *   British Columbia.
      4  * Copyright (c) 2001-2003 Michael David Adams.
      5  * All rights reserved.
      6  */
      7 
      8 /* __START_OF_JASPER_LICENSE__
      9  * 
     10  * JasPer License Version 2.0
     11  * 
     12  * Copyright (c) 1999-2000 Image Power, Inc.
     13  * Copyright (c) 1999-2000 The University of British Columbia
     14  * Copyright (c) 2001-2003 Michael David Adams
     15  * 
     16  * All rights reserved.
     17  * 
     18  * Permission is hereby granted, free of charge, to any person (the
     19  * "User") obtaining a copy of this software and associated documentation
     20  * files (the "Software"), to deal in the Software without restriction,
     21  * including without limitation the rights to use, copy, modify, merge,
     22  * publish, distribute, and/or sell copies of the Software, and to permit
     23  * persons to whom the Software is furnished to do so, subject to the
     24  * following conditions:
     25  * 
     26  * 1.  The above copyright notices and this permission notice (which
     27  * includes the disclaimer below) shall be included in all copies or
     28  * substantial portions of the Software.
     29  * 
     30  * 2.  The name of a copyright holder shall not be used to endorse or
     31  * promote products derived from the Software without specific prior
     32  * written permission.
     33  * 
     34  * THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL PART OF THIS
     35  * LICENSE.  NO USE OF THE SOFTWARE IS AUTHORIZED HEREUNDER EXCEPT UNDER
     36  * THIS DISCLAIMER.  THE SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS
     37  * "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
     38  * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
     39  * PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.  IN NO
     40  * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL
     41  * INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING
     42  * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
     43  * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
     44  * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.  NO ASSURANCES ARE
     45  * PROVIDED BY THE COPYRIGHT HOLDERS THAT THE SOFTWARE DOES NOT INFRINGE
     46  * THE PATENT OR OTHER INTELLECTUAL PROPERTY RIGHTS OF ANY OTHER ENTITY.
     47  * EACH COPYRIGHT HOLDER DISCLAIMS ANY LIABILITY TO THE USER FOR CLAIMS
     48  * BROUGHT BY ANY OTHER ENTITY BASED ON INFRINGEMENT OF INTELLECTUAL
     49  * PROPERTY RIGHTS OR OTHERWISE.  AS A CONDITION TO EXERCISING THE RIGHTS
     50  * GRANTED HEREUNDER, EACH USER HEREBY ASSUMES SOLE RESPONSIBILITY TO SECURE
     51  * ANY OTHER INTELLECTUAL PROPERTY RIGHTS NEEDED, IF ANY.  THE SOFTWARE
     52  * IS NOT FAULT-TOLERANT AND IS NOT INTENDED FOR USE IN MISSION-CRITICAL
     53  * SYSTEMS, SUCH AS THOSE USED IN THE OPERATION OF NUCLEAR FACILITIES,
     54  * AIRCRAFT NAVIGATION OR COMMUNICATION SYSTEMS, AIR TRAFFIC CONTROL
     55  * SYSTEMS, DIRECT LIFE SUPPORT MACHINES, OR WEAPONS SYSTEMS, IN WHICH
     56  * THE FAILURE OF THE SOFTWARE OR SYSTEM COULD LEAD DIRECTLY TO DEATH,
     57  * PERSONAL INJURY, OR SEVERE PHYSICAL OR ENVIRONMENTAL DAMAGE ("HIGH
     58  * RISK ACTIVITIES").  THE COPYRIGHT HOLDERS SPECIFICALLY DISCLAIM ANY
     59  * EXPRESS OR IMPLIED WARRANTY OF FITNESS FOR HIGH RISK ACTIVITIES.
     60  * 
     61  * __END_OF_JASPER_LICENSE__
     62  */
     63 
     64 /*
     65  * Image Library
     66  *
     67  * $Id: jas_image.c 1918 2005-07-24 14:12:08Z baford $
     68  */
     69 
     70 /******************************************************************************\
     71 * Includes.
     72 \******************************************************************************/
     73 
     74 #include <stdlib.h>
     75 #include <stdio.h>
     76 #include <string.h>
     77 #include <assert.h>
     78 #include <ctype.h>
     79 
     80 #include "jasper/jas_math.h"
     81 #include "jasper/jas_image.h"
     82 #include "jasper/jas_malloc.h"
     83 #include "jasper/jas_string.h"
     84 
     85 /******************************************************************************\
     86 * Types.
     87 \******************************************************************************/
     88 
     89 #define	FLOORDIV(x, y) ((x) / (y))
     90 
     91 /******************************************************************************\
     92 * Local prototypes.
     93 \******************************************************************************/
     94 
     95 static jas_image_cmpt_t *jas_image_cmpt_create0(void);
     96 static void jas_image_cmpt_destroy(jas_image_cmpt_t *cmpt);
     97 static jas_image_cmpt_t *jas_image_cmpt_create(uint_fast32_t tlx, uint_fast32_t tly,
     98   uint_fast32_t hstep, uint_fast32_t vstep, uint_fast32_t width, uint_fast32_t
     99   height, uint_fast16_t depth, bool sgnd, uint_fast32_t inmem);
    100 static void jas_image_setbbox(jas_image_t *image);
    101 static jas_image_cmpt_t *jas_image_cmpt_copy(jas_image_cmpt_t *cmpt);
    102 static int jas_image_growcmpts(jas_image_t *image, int maxcmpts);
    103 static uint_fast32_t inttobits(jas_seqent_t v, int prec, bool sgnd);
    104 static jas_seqent_t bitstoint(uint_fast32_t v, int prec, bool sgnd);
    105 static int putint(jas_stream_t *out, int sgnd, int prec, long val);
    106 static int getint(jas_stream_t *in, int sgnd, int prec, long *val);
    107 static void jas_image_calcbbox2(jas_image_t *image, jas_image_coord_t *tlx,
    108   jas_image_coord_t *tly, jas_image_coord_t *brx, jas_image_coord_t *bry);
    109 static long uptomult(long x, long y);
    110 static long downtomult(long x, long y);
    111 static long convert(long val, int oldsgnd, int oldprec, int newsgnd,
    112   int newprec);
    113 static void jas_image_calcbbox2(jas_image_t *image, jas_image_coord_t *tlx,
    114   jas_image_coord_t *tly, jas_image_coord_t *brx, jas_image_coord_t *bry);
    115 
    116 /******************************************************************************\
    117 * Global data.
    118 \******************************************************************************/
    119 
    120 static int jas_image_numfmts = 0;
    121 static jas_image_fmtinfo_t jas_image_fmtinfos[JAS_IMAGE_MAXFMTS];
    122 
    123 /******************************************************************************\
    124 * Create and destroy operations.
    125 \******************************************************************************/
    126 
    127 jas_image_t *jas_image_create(int numcmpts, jas_image_cmptparm_t *cmptparms,
    128   int clrspc)
    129 {
    130 	jas_image_t *image;
    131 	uint_fast32_t rawsize;
    132 	uint_fast32_t inmem;
    133 	int cmptno;
    134 	jas_image_cmptparm_t *cmptparm;
    135 
    136 	if (!(image = jas_image_create0())) {
    137 		return 0;
    138 	}
    139 
    140 	image->clrspc_ = clrspc;
    141 	image->maxcmpts_ = numcmpts;
    142 	image->inmem_ = true;
    143 
    144 	/* Allocate memory for the per-component information. */
    145 	if (!(image->cmpts_ = jas_malloc(image->maxcmpts_ *
    146 	  sizeof(jas_image_cmpt_t *)))) {
    147 		jas_image_destroy(image);
    148 		return 0;
    149 	}
    150 	/* Initialize in case of failure. */
    151 	for (cmptno = 0; cmptno < image->maxcmpts_; ++cmptno) {
    152 		image->cmpts_[cmptno] = 0;
    153 	}
    154 
    155 	/* Compute the approximate raw size of the image. */
    156 	rawsize = 0;
    157 	for (cmptno = 0, cmptparm = cmptparms; cmptno < numcmpts; ++cmptno,
    158 	  ++cmptparm) {
    159 		rawsize += cmptparm->width * cmptparm->height *
    160 		  (cmptparm->prec + 7) / 8;
    161 	}
    162 	/* Decide whether to buffer the image data in memory, based on the
    163 	  raw size of the image. */
    164 	inmem = (rawsize < JAS_IMAGE_INMEMTHRESH);
    165 
    166 	/* Create the individual image components. */
    167 	for (cmptno = 0, cmptparm = cmptparms; cmptno < numcmpts; ++cmptno,
    168 	  ++cmptparm) {
    169 		if (!(image->cmpts_[cmptno] = jas_image_cmpt_create(cmptparm->tlx,
    170 		  cmptparm->tly, cmptparm->hstep, cmptparm->vstep,
    171 		  cmptparm->width, cmptparm->height, cmptparm->prec,
    172 		  cmptparm->sgnd, inmem))) {
    173 			jas_image_destroy(image);
    174 			return 0;
    175 		}
    176 		++image->numcmpts_;
    177 	}
    178 
    179 	/* Determine the bounding box for all of the components on the
    180 	  reference grid (i.e., the image area) */
    181 	jas_image_setbbox(image);
    182 
    183 	return image;
    184 }
    185 
    186 jas_image_t *jas_image_create0()
    187 {
    188 	jas_image_t *image;
    189 
    190 	if (!(image = jas_malloc(sizeof(jas_image_t)))) {
    191 		return 0;
    192 	}
    193 
    194 	image->tlx_ = 0;
    195 	image->tly_ = 0;
    196 	image->brx_ = 0;
    197 	image->bry_ = 0;
    198 	image->clrspc_ = JAS_CLRSPC_UNKNOWN;
    199 	image->numcmpts_ = 0;
    200 	image->maxcmpts_ = 0;
    201 	image->cmpts_ = 0;
    202 	image->inmem_ = true;
    203 	image->cmprof_ = 0;
    204 
    205 	return image;
    206 }
    207 
    208 jas_image_t *jas_image_copy(jas_image_t *image)
    209 {
    210 	jas_image_t *newimage;
    211 	int cmptno;
    212 
    213 	newimage = jas_image_create0();
    214 	if (jas_image_growcmpts(newimage, image->numcmpts_)) {
    215 		goto error;
    216 	}
    217 	for (cmptno = 0; cmptno < image->numcmpts_; ++cmptno) {
    218 		if (!(newimage->cmpts_[cmptno] = jas_image_cmpt_copy(image->cmpts_[cmptno]))) {
    219 			goto error;
    220 		}
    221 		++newimage->numcmpts_;
    222 	}
    223 
    224 	jas_image_setbbox(newimage);
    225 
    226 	if (image->cmprof_) {
    227 		if (!(newimage->cmprof_ = jas_cmprof_copy(image->cmprof_)))
    228 			goto error;
    229 	}
    230 
    231 	return newimage;
    232 error:
    233 	if (newimage) {
    234 		jas_image_destroy(newimage);
    235 	}
    236 	return 0;
    237 }
    238 
    239 static jas_image_cmpt_t *jas_image_cmpt_create0()
    240 {
    241 	jas_image_cmpt_t *cmpt;
    242 	if (!(cmpt = jas_malloc(sizeof(jas_image_cmpt_t)))) {
    243 		return 0;
    244 	}
    245 	memset(cmpt, 0, sizeof(jas_image_cmpt_t));
    246 	cmpt->type_ = JAS_IMAGE_CT_UNKNOWN;
    247 	return cmpt;
    248 }
    249 
    250 static jas_image_cmpt_t *jas_image_cmpt_copy(jas_image_cmpt_t *cmpt)
    251 {
    252 	jas_image_cmpt_t *newcmpt;
    253 
    254 	if (!(newcmpt = jas_image_cmpt_create0())) {
    255 		return 0;
    256 	}
    257 	newcmpt->tlx_ = cmpt->tlx_;
    258 	newcmpt->tly_ = cmpt->tly_;
    259 	newcmpt->hstep_ = cmpt->hstep_;
    260 	newcmpt->vstep_ = cmpt->vstep_;
    261 	newcmpt->width_ = cmpt->width_;
    262 	newcmpt->height_ = cmpt->height_;
    263 	newcmpt->prec_ = cmpt->prec_;
    264 	newcmpt->sgnd_ = cmpt->sgnd_;
    265 	newcmpt->cps_ = cmpt->cps_;
    266 	newcmpt->type_ = cmpt->type_;
    267 	if (!(newcmpt->stream_ = jas_stream_memopen(0, 0))) {
    268 		return 0;
    269 	}
    270 	if (jas_stream_seek(cmpt->stream_, 0, SEEK_SET)) {
    271 		return 0;
    272 	}
    273 	if (jas_stream_copy(newcmpt->stream_, cmpt->stream_, -1)) {
    274 		return 0;
    275 	}
    276 	if (jas_stream_seek(newcmpt->stream_, 0, SEEK_SET)) {
    277 		return 0;
    278 	}
    279 	return newcmpt;
    280 }
    281 
    282 void jas_image_destroy(jas_image_t *image)
    283 {
    284 	int i;
    285 
    286 	if (image->cmpts_) {
    287 		for (i = 0; i < image->numcmpts_; ++i) {
    288 			jas_image_cmpt_destroy(image->cmpts_[i]);
    289 			image->cmpts_[i] = 0;
    290 		}
    291 		jas_free(image->cmpts_);
    292 	}
    293 	if (image->cmprof_)
    294 		jas_cmprof_destroy(image->cmprof_);
    295 	jas_free(image);
    296 }
    297 
    298 static jas_image_cmpt_t *jas_image_cmpt_create(uint_fast32_t tlx, uint_fast32_t tly,
    299   uint_fast32_t hstep, uint_fast32_t vstep, uint_fast32_t width, uint_fast32_t
    300   height, uint_fast16_t depth, bool sgnd, uint_fast32_t inmem)
    301 {
    302 	jas_image_cmpt_t *cmpt;
    303 	long size;
    304 
    305 	if (!(cmpt = jas_malloc(sizeof(jas_image_cmpt_t)))) {
    306 		return 0;
    307 	}
    308 
    309 	cmpt->tlx_ = tlx;
    310 	cmpt->tly_ = tly;
    311 	cmpt->hstep_ = hstep;
    312 	cmpt->vstep_ = vstep;
    313 	cmpt->width_ = width;
    314 	cmpt->height_ = height;
    315 	cmpt->prec_ = depth;
    316 	cmpt->sgnd_ = sgnd;
    317 	cmpt->stream_ = 0;
    318 	cmpt->cps_ = (depth + 7) / 8;
    319 
    320 	size = cmpt->width_ * cmpt->height_ * cmpt->cps_;
    321 //	cmpt->stream_ = (inmem) ? jas_stream_memopen(0, size) : jas_stream_tmpfile();
    322 	cmpt->stream_ = jas_stream_memopen(0, size);	// XXX vx32 hack
    323 	if (!cmpt->stream_) {
    324 		jas_image_cmpt_destroy(cmpt);
    325 		return 0;
    326 	}
    327 
    328 	/* Zero the component data.  This isn't necessary, but it is
    329 	convenient for debugging purposes. */
    330 	if (jas_stream_seek(cmpt->stream_, size - 1, SEEK_SET) < 0 ||
    331 	  jas_stream_putc(cmpt->stream_, 0) == EOF ||
    332 	  jas_stream_seek(cmpt->stream_, 0, SEEK_SET) < 0) {
    333 		jas_image_cmpt_destroy(cmpt);
    334 		return 0;
    335 	}
    336 
    337 	return cmpt;
    338 }
    339 
    340 static void jas_image_cmpt_destroy(jas_image_cmpt_t *cmpt)
    341 {
    342 	if (cmpt->stream_) {
    343 		jas_stream_close(cmpt->stream_);
    344 	}
    345 	jas_free(cmpt);
    346 }
    347 
    348 /******************************************************************************\
    349 * Load and save operations.
    350 \******************************************************************************/
    351 
    352 jas_image_t *jas_image_decode(jas_stream_t *in, int fmt, char *optstr)
    353 {
    354 	jas_image_fmtinfo_t *fmtinfo;
    355 	jas_image_t *image;
    356 
    357 	image = 0;
    358 
    359 	/* If possible, try to determine the format of the input data. */
    360 	if (fmt < 0) {
    361 		if ((fmt = jas_image_getfmt(in)) < 0)
    362 			goto error;
    363 	}
    364 
    365 	/* Is it possible to decode an image represented in this format? */
    366 	if (!(fmtinfo = jas_image_lookupfmtbyid(fmt)))
    367 		goto error;
    368 	if (!fmtinfo->ops.decode)
    369 		goto error;
    370 
    371 	/* Decode the image. */
    372 	if (!(image = (*fmtinfo->ops.decode)(in, optstr)))
    373 		goto error;
    374 
    375 	/* Create a color profile if needed. */
    376 	if (!jas_clrspc_isunknown(image->clrspc_) &&
    377 	  !jas_clrspc_isgeneric(image->clrspc_) && !image->cmprof_) {
    378 		if (!(image->cmprof_ =
    379 		  jas_cmprof_createfromclrspc(jas_image_clrspc(image))))
    380 			goto error;
    381 	}
    382 
    383 	return image;
    384 error:
    385 	if (image)
    386 		jas_image_destroy(image);
    387 	return 0;
    388 }
    389 
    390 int jas_image_encode(jas_image_t *image, jas_stream_t *out, int fmt, char *optstr)
    391 {
    392 	jas_image_fmtinfo_t *fmtinfo;
    393 	if (!(fmtinfo = jas_image_lookupfmtbyid(fmt))) {
    394 		return -1;
    395 	}
    396 	return (fmtinfo->ops.encode) ? (*fmtinfo->ops.encode)(image, out,
    397 	  optstr) : (-1);
    398 }
    399 
    400 /******************************************************************************\
    401 * Component read and write operations.
    402 \******************************************************************************/
    403 
    404 int jas_image_readcmpt(jas_image_t *image, int cmptno, jas_image_coord_t x,
    405   jas_image_coord_t y, jas_image_coord_t width, jas_image_coord_t height,
    406   jas_matrix_t *data)
    407 {
    408 	jas_image_cmpt_t *cmpt;
    409 	jas_image_coord_t i;
    410 	jas_image_coord_t j;
    411 	int k;
    412 	jas_seqent_t v;
    413 	int c;
    414 	jas_seqent_t *dr;
    415 	jas_seqent_t *d;
    416 	int drs;
    417 
    418 	if (cmptno < 0 || cmptno >= image->numcmpts_) {
    419 		return -1;
    420 	}
    421 
    422 	cmpt = image->cmpts_[cmptno];
    423 	if (x >= cmpt->width_ || y >= cmpt->height_ ||
    424 	  x + width > cmpt->width_ ||
    425 	  y + height > cmpt->height_) {
    426 		return -1;
    427 	}
    428 
    429 	if (jas_matrix_numrows(data) != height || jas_matrix_numcols(data) != width) {
    430 		if (jas_matrix_resize(data, height, width)) {
    431 			return -1;
    432 		}
    433 	}
    434 
    435 	dr = jas_matrix_getref(data, 0, 0);
    436 	drs = jas_matrix_rowstep(data);
    437 	for (i = 0; i < height; ++i, dr += drs) {
    438 		d = dr;
    439 		if (jas_stream_seek(cmpt->stream_, (cmpt->width_ * (y + i) + x)
    440 		  * cmpt->cps_, SEEK_SET) < 0) {
    441 			return -1;
    442 		}
    443 		for (j = width; j > 0; --j, ++d) {
    444 			v = 0;
    445 			for (k = cmpt->cps_; k > 0; --k) {
    446 				if ((c = jas_stream_getc(cmpt->stream_)) == EOF) {
    447 					return -1;
    448 				}
    449 				v = (v << 8) | (c & 0xff);
    450 			}
    451 			*d = bitstoint(v, cmpt->prec_, cmpt->sgnd_);
    452 		}
    453 	}
    454 
    455 	return 0;
    456 }
    457 
    458 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,
    459   jas_image_coord_t height, jas_matrix_t *data)
    460 {
    461 	jas_image_cmpt_t *cmpt;
    462 	jas_image_coord_t i;
    463 	jas_image_coord_t j;
    464 	jas_seqent_t *d;
    465 	jas_seqent_t *dr;
    466 	int drs;
    467 	jas_seqent_t v;
    468 	int k;
    469 	int c;
    470 
    471 	if (cmptno < 0 || cmptno >= image->numcmpts_) {
    472 		return -1;
    473 	}
    474 
    475 	cmpt = image->cmpts_[cmptno];
    476 	if (x >= cmpt->width_ || y >= cmpt->height_ ||
    477 	  x + width > cmpt->width_ ||
    478 	  y + height > cmpt->height_) {
    479 		return -1;
    480 	}
    481 
    482 	if (jas_matrix_numrows(data) != height || jas_matrix_numcols(data) != width) {
    483 		return -1;
    484 	}
    485 
    486 	dr = jas_matrix_getref(data, 0, 0);
    487 	drs = jas_matrix_rowstep(data);
    488 	for (i = 0; i < height; ++i, dr += drs) {
    489 		d = dr;
    490 		if (jas_stream_seek(cmpt->stream_, (cmpt->width_ * (y + i) + x)
    491 		  * cmpt->cps_, SEEK_SET) < 0) {
    492 			return -1;
    493 		}
    494 		for (j = width; j > 0; --j, ++d) {
    495 			v = inttobits(*d, cmpt->prec_, cmpt->sgnd_);
    496 			for (k = cmpt->cps_; k > 0; --k) {
    497 				c = (v >> (8 * (cmpt->cps_ - 1))) & 0xff;
    498 				if (jas_stream_putc(cmpt->stream_,
    499 				  (unsigned char) c) == EOF) {
    500 					return -1;
    501 				}
    502 				v <<= 8;
    503 			}
    504 		}
    505 	}
    506 
    507 	return 0;
    508 }
    509 
    510 /******************************************************************************\
    511 * File format operations.
    512 \******************************************************************************/
    513 
    514 void jas_image_clearfmts()
    515 {
    516 	int i;
    517 	jas_image_fmtinfo_t *fmtinfo;
    518 	for (i = 0; i < jas_image_numfmts; ++i) {
    519 		fmtinfo = &jas_image_fmtinfos[i];
    520 		if (fmtinfo->name) {
    521 			jas_free(fmtinfo->name);
    522 			fmtinfo->name = 0;
    523 		}
    524 		if (fmtinfo->ext) {
    525 			jas_free(fmtinfo->ext);
    526 			fmtinfo->ext = 0;
    527 		}
    528 		if (fmtinfo->desc) {
    529 			jas_free(fmtinfo->desc);
    530 			fmtinfo->desc = 0;
    531 		}
    532 	}
    533 	jas_image_numfmts = 0;
    534 }
    535 
    536 int jas_image_addfmt(int id, char *name, char *ext, char *desc,
    537   jas_image_fmtops_t *ops)
    538 {
    539 	jas_image_fmtinfo_t *fmtinfo;
    540 	assert(id >= 0 && name && ext && ops);
    541 	if (jas_image_numfmts >= JAS_IMAGE_MAXFMTS) {
    542 		return -1;
    543 	}
    544 	fmtinfo = &jas_image_fmtinfos[jas_image_numfmts];
    545 	fmtinfo->id = id;
    546 	if (!(fmtinfo->name = jas_strdup(name))) {
    547 		return -1;
    548 	}
    549 	if (!(fmtinfo->ext = jas_strdup(ext))) {
    550 		jas_free(fmtinfo->name);
    551 		return -1;
    552 	}
    553 	if (!(fmtinfo->desc = jas_strdup(desc))) {
    554 		jas_free(fmtinfo->name);
    555 		jas_free(fmtinfo->ext);
    556 		return -1;
    557 	}
    558 	fmtinfo->ops = *ops;
    559 	++jas_image_numfmts;
    560 	return 0;
    561 }
    562 
    563 int jas_image_strtofmt(char *name)
    564 {
    565 	jas_image_fmtinfo_t *fmtinfo;
    566 	if (!(fmtinfo = jas_image_lookupfmtbyname(name))) {
    567 		return -1;
    568 	}
    569 	return fmtinfo->id;
    570 }
    571 
    572 char *jas_image_fmttostr(int fmt)
    573 {
    574 	jas_image_fmtinfo_t *fmtinfo;
    575 	if (!(fmtinfo = jas_image_lookupfmtbyid(fmt))) {
    576 		return 0;
    577 	}
    578 	return fmtinfo->name;
    579 }
    580 
    581 int jas_image_getfmt(jas_stream_t *in)
    582 {
    583 	jas_image_fmtinfo_t *fmtinfo;
    584 	int found;
    585 	int i;
    586 
    587 	/* Check for data in each of the supported formats. */
    588 	found = 0;
    589 	for (i = 0, fmtinfo = jas_image_fmtinfos; i < jas_image_numfmts; ++i,
    590 	  ++fmtinfo) {
    591 		if (fmtinfo->ops.validate) {
    592 			/* Is the input data valid for this format? */
    593 			if (!(*fmtinfo->ops.validate)(in)) {
    594 				found = 1;
    595 				break;
    596 			}
    597 		}
    598 	}
    599 	return found ? fmtinfo->id : (-1);
    600 }
    601 
    602 int jas_image_fmtfromname(char *name)
    603 {
    604 	int i;
    605 	char *ext;
    606 	jas_image_fmtinfo_t *fmtinfo;
    607 	/* Get the file name extension. */
    608 	if (!(ext = strrchr(name, '.'))) {
    609 		return -1;
    610 	}
    611 	++ext;
    612 	/* Try to find a format that uses this extension. */	
    613 	for (i = 0, fmtinfo = jas_image_fmtinfos; i < jas_image_numfmts; ++i,
    614 	  ++fmtinfo) {
    615 		/* Do we have a match? */
    616 		if (!strcmp(ext, fmtinfo->ext)) {
    617 			return fmtinfo->id;
    618 		}
    619 	}
    620 	return -1;
    621 }
    622 
    623 /******************************************************************************\
    624 * Miscellaneous operations.
    625 \******************************************************************************/
    626 
    627 uint_fast32_t jas_image_rawsize(jas_image_t *image)
    628 {
    629 	uint_fast32_t rawsize;
    630 	int cmptno;
    631 	jas_image_cmpt_t *cmpt;
    632 
    633 	rawsize = 0;
    634 	for (cmptno = 0; cmptno < image->numcmpts_; ++cmptno) {
    635 		cmpt = image->cmpts_[cmptno];
    636 		rawsize += (cmpt->width_ * cmpt->height_ * cmpt->prec_ +
    637 		  7) / 8;
    638 	}
    639 	return rawsize;
    640 }
    641 
    642 void jas_image_delcmpt(jas_image_t *image, int cmptno)
    643 {
    644 	if (cmptno >= image->numcmpts_) {
    645 		return;
    646 	}
    647 	jas_image_cmpt_destroy(image->cmpts_[cmptno]);
    648 	if (cmptno < image->numcmpts_) {
    649 		memmove(&image->cmpts_[cmptno], &image->cmpts_[cmptno + 1],
    650 		  (image->numcmpts_ - 1 - cmptno) * sizeof(jas_image_cmpt_t *));
    651 	}
    652 	--image->numcmpts_;
    653 
    654 	jas_image_setbbox(image);
    655 }
    656 
    657 int jas_image_addcmpt(jas_image_t *image, int cmptno,
    658   jas_image_cmptparm_t *cmptparm)
    659 {
    660 	jas_image_cmpt_t *newcmpt;
    661 	if (cmptno < 0)
    662 		cmptno = image->numcmpts_;
    663 	assert(cmptno >= 0 && cmptno <= image->numcmpts_);
    664 	if (image->numcmpts_ >= image->maxcmpts_) {
    665 		if (jas_image_growcmpts(image, image->maxcmpts_ + 128)) {
    666 			return -1;
    667 		}
    668 	}
    669 	if (!(newcmpt = jas_image_cmpt_create(cmptparm->tlx,
    670 	  cmptparm->tly, cmptparm->hstep, cmptparm->vstep,
    671 	  cmptparm->width, cmptparm->height, cmptparm->prec,
    672 	  cmptparm->sgnd, 1))) {
    673 		return -1;
    674 	}
    675 	if (cmptno < image->numcmpts_) {
    676 		memmove(&image->cmpts_[cmptno + 1], &image->cmpts_[cmptno],
    677 		  (image->numcmpts_ - cmptno) * sizeof(jas_image_cmpt_t *));
    678 	}
    679 	image->cmpts_[cmptno] = newcmpt;
    680 	++image->numcmpts_;
    681 
    682 	jas_image_setbbox(image);
    683 
    684 	return 0;
    685 }
    686 
    687 jas_image_fmtinfo_t *jas_image_lookupfmtbyid(int id)
    688 {
    689 	int i;
    690 	jas_image_fmtinfo_t *fmtinfo;
    691 
    692 	for (i = 0, fmtinfo = jas_image_fmtinfos; i < jas_image_numfmts; ++i, ++fmtinfo) {
    693 		if (fmtinfo->id == id) {
    694 			return fmtinfo;
    695 		}
    696 	}
    697 	return 0;
    698 }
    699 
    700 jas_image_fmtinfo_t *jas_image_lookupfmtbyname(const char *name)
    701 {
    702 	int i;
    703 	jas_image_fmtinfo_t *fmtinfo;
    704 
    705 	for (i = 0, fmtinfo = jas_image_fmtinfos; i < jas_image_numfmts; ++i, ++fmtinfo) {
    706 		if (!strcmp(fmtinfo->name, name)) {
    707 			return fmtinfo;
    708 		}
    709 	}
    710 	return 0;
    711 }
    712 
    713 
    714 
    715 
    716 
    717 static uint_fast32_t inttobits(jas_seqent_t v, int prec, bool sgnd)
    718 {
    719 	uint_fast32_t ret;
    720 	ret = ((sgnd && v < 0) ? ((1 << prec) + v) : v) & JAS_ONES(prec);
    721 	return ret;
    722 }
    723 
    724 static jas_seqent_t bitstoint(uint_fast32_t v, int prec, bool sgnd)
    725 {
    726 	jas_seqent_t ret;
    727 	v &= JAS_ONES(prec);
    728 	ret = (sgnd && (v & (1 << (prec - 1)))) ? (v - (1 << prec)) : v;
    729 	return ret;
    730 }
    731 
    732 static void jas_image_setbbox(jas_image_t *image)
    733 {
    734 	jas_image_cmpt_t *cmpt;
    735 	int cmptno;
    736 	int_fast32_t x;
    737 	int_fast32_t y;
    738 
    739 	if (image->numcmpts_ > 0) {
    740 		/* Determine the bounding box for all of the components on the
    741 		  reference grid (i.e., the image area) */
    742 		cmpt = image->cmpts_[0];
    743 		image->tlx_ = cmpt->tlx_;
    744 		image->tly_ = cmpt->tly_;
    745 		image->brx_ = cmpt->tlx_ + cmpt->hstep_ * (cmpt->width_ - 1) + 1;
    746 		image->bry_ = cmpt->tly_ + cmpt->vstep_ * (cmpt->height_ - 1) + 1;
    747 		for (cmptno = 1; cmptno < image->numcmpts_; ++cmptno) {
    748 			cmpt = image->cmpts_[cmptno];
    749 			if (image->tlx_ > cmpt->tlx_) {
    750 				image->tlx_ = cmpt->tlx_;
    751 			}
    752 			if (image->tly_ > cmpt->tly_) {
    753 				image->tly_ = cmpt->tly_;
    754 			}
    755 			x = cmpt->tlx_ + cmpt->hstep_ * (cmpt->width_ - 1) + 1;
    756 			if (image->brx_ < x) {
    757 				image->brx_ = x;
    758 			}
    759 			y = cmpt->tly_ + cmpt->vstep_ * (cmpt->height_ - 1) + 1;
    760 			if (image->bry_ < y) {
    761 				image->bry_ = y;
    762 			}
    763 		}
    764 	} else {
    765 		image->tlx_ = 0;
    766 		image->tly_ = 0;
    767 		image->brx_ = 0;
    768 		image->bry_ = 0;
    769 	}
    770 }
    771 
    772 static int jas_image_growcmpts(jas_image_t *image, int maxcmpts)
    773 {
    774 	jas_image_cmpt_t **newcmpts;
    775 	int cmptno;
    776 
    777 	newcmpts = (!image->cmpts_) ? jas_malloc(maxcmpts * sizeof(jas_image_cmpt_t *)) :
    778 	  jas_realloc(image->cmpts_, maxcmpts * sizeof(jas_image_cmpt_t *));
    779 	if (!newcmpts) {
    780 		return -1;
    781 	}
    782 	image->cmpts_ = newcmpts;
    783 	image->maxcmpts_ = maxcmpts;
    784 	for (cmptno = image->numcmpts_; cmptno < image->maxcmpts_; ++cmptno) {
    785 		image->cmpts_[cmptno] = 0;
    786 	}
    787 	return 0;
    788 }
    789 
    790 int jas_image_copycmpt(jas_image_t *dstimage, int dstcmptno, jas_image_t *srcimage,
    791   int srccmptno)
    792 {
    793 	jas_image_cmpt_t *newcmpt;
    794 	if (dstimage->numcmpts_ >= dstimage->maxcmpts_) {
    795 		if (jas_image_growcmpts(dstimage, dstimage->maxcmpts_ + 128)) {
    796 			return -1;
    797 		}
    798 	}
    799 	if (!(newcmpt = jas_image_cmpt_copy(srcimage->cmpts_[srccmptno]))) {
    800 		return -1;
    801 	}
    802 	if (dstcmptno < dstimage->numcmpts_) {
    803 		memmove(&dstimage->cmpts_[dstcmptno + 1], &dstimage->cmpts_[dstcmptno],
    804 		  (dstimage->numcmpts_ - dstcmptno) * sizeof(jas_image_cmpt_t *));
    805 	}
    806 	dstimage->cmpts_[dstcmptno] = newcmpt;
    807 	++dstimage->numcmpts_;
    808 
    809 	jas_image_setbbox(dstimage);
    810 	return 0;
    811 }
    812 
    813 void jas_image_dump(jas_image_t *image, FILE *out)
    814 {
    815 	long buf[1024];
    816 	int cmptno;
    817 	int n;
    818 	int i;
    819 	int width;
    820 	int height;
    821 	jas_image_cmpt_t *cmpt;
    822 	for (cmptno = 0; cmptno < image->numcmpts_; ++cmptno) {
    823 		cmpt = image->cmpts_[cmptno];
    824 		fprintf(out, "prec=%d, sgnd=%d, cmpttype=%d\n", cmpt->prec_,
    825 		  cmpt->sgnd_, (int)cmpt->type_);
    826 		width = jas_image_cmptwidth(image, cmptno);
    827 		height = jas_image_cmptheight(image, cmptno);
    828 		n = JAS_MIN(16, width);
    829 		if (jas_image_readcmpt2(image, cmptno, 0, 0, n, 1, buf)) {
    830 			abort();
    831 		}
    832 		for (i = 0; i < n; ++i) {
    833 			fprintf(out, " f(%d,%d)=%ld", i, 0, buf[i]);
    834 		}
    835 		fprintf(out, "\n");
    836 		if (jas_image_readcmpt2(image, cmptno, width - n, height - 1, n, 1, buf)) {
    837 			abort();
    838 		}
    839 		for (i = 0; i < n; ++i) {
    840 			fprintf(out, " f(%d,%d)=%ld", width - n + i, height - 1, buf[i]);
    841 		}
    842 		fprintf(out, "\n");
    843 	}
    844 }
    845 
    846 int jas_image_depalettize(jas_image_t *image, int cmptno, int numlutents,
    847   int_fast32_t *lutents, int dtype, int newcmptno)
    848 {
    849 	jas_image_cmptparm_t cmptparms;
    850 	int_fast32_t v;
    851 	int i;
    852 	int j;
    853 	jas_image_cmpt_t *cmpt;
    854 
    855 	cmpt = image->cmpts_[cmptno];
    856 	cmptparms.tlx = cmpt->tlx_;
    857 	cmptparms.tly = cmpt->tly_;
    858 	cmptparms.hstep = cmpt->hstep_;
    859 	cmptparms.vstep = cmpt->vstep_;
    860 	cmptparms.width = cmpt->width_;
    861 	cmptparms.height = cmpt->height_;
    862 	cmptparms.prec = JAS_IMAGE_CDT_GETPREC(dtype);
    863 	cmptparms.sgnd = JAS_IMAGE_CDT_GETSGND(dtype);
    864 
    865 	if (jas_image_addcmpt(image, newcmptno, &cmptparms)) {
    866 		return -1;
    867 	}
    868 	if (newcmptno <= cmptno) {
    869 		++cmptno;
    870 		cmpt = image->cmpts_[cmptno];
    871 	}
    872 
    873 	for (j = 0; j < cmpt->height_; ++j) {
    874 		for (i = 0; i < cmpt->width_; ++i) {
    875 			v = jas_image_readcmptsample(image, cmptno, i, j);
    876 			if (v < 0) {
    877 				v = 0;
    878 			} else if (v >= numlutents) {
    879 				v = numlutents - 1;
    880 			}
    881 			jas_image_writecmptsample(image, newcmptno, i, j,
    882 			  lutents[v]);
    883 		}
    884 	}
    885 	return 0;
    886 }
    887 
    888 int jas_image_readcmptsample(jas_image_t *image, int cmptno, int x, int y)
    889 {
    890 	jas_image_cmpt_t *cmpt;
    891 	uint_fast32_t v;
    892 	int k;
    893 	int c;
    894 
    895 	cmpt = image->cmpts_[cmptno];
    896 
    897 	if (jas_stream_seek(cmpt->stream_, (cmpt->width_ * y + x) * cmpt->cps_,
    898 	  SEEK_SET) < 0) {
    899 		return -1;
    900 	}
    901 	v = 0;
    902 	for (k = cmpt->cps_; k > 0; --k) {
    903 		if ((c = jas_stream_getc(cmpt->stream_)) == EOF) {
    904 			return -1;
    905 		}
    906 		v = (v << 8) | (c & 0xff);
    907 	}
    908 	return bitstoint(v, cmpt->prec_, cmpt->sgnd_);
    909 }
    910 
    911 void jas_image_writecmptsample(jas_image_t *image, int cmptno, int x, int y,
    912   int_fast32_t v)
    913 {
    914 	jas_image_cmpt_t *cmpt;
    915 	uint_fast32_t t;
    916 	int k;
    917 	int c;
    918 
    919 	cmpt = image->cmpts_[cmptno];
    920 
    921 	if (jas_stream_seek(cmpt->stream_, (cmpt->width_ * y + x) * cmpt->cps_,
    922 	  SEEK_SET) < 0) {
    923 		return;
    924 	}
    925 	t = inttobits(v, cmpt->prec_, cmpt->sgnd_);
    926 	for (k = cmpt->cps_; k > 0; --k) {
    927 		c = (t >> (8 * (cmpt->cps_ - 1))) & 0xff;
    928 		if (jas_stream_putc(cmpt->stream_, (unsigned char) c) == EOF) {
    929 			return;
    930 		}
    931 		t <<= 8;
    932 	}
    933 }
    934 
    935 int jas_image_getcmptbytype(jas_image_t *image, int ctype)
    936 {
    937 	int cmptno;
    938 
    939 	for (cmptno = 0; cmptno < image->numcmpts_; ++cmptno) {
    940 		if (image->cmpts_[cmptno]->type_ == ctype) {
    941 			return cmptno;
    942 		}
    943 	}
    944 	return -1;
    945 }
    946 
    947 
    948 
    949 
    950 
    951 
    952 
    953 
    954 
    955 
    956 
    957 
    958 
    959 
    960 
    961 
    962 /***********************************************/
    963 /***********************************************/
    964 /***********************************************/
    965 /***********************************************/
    966 
    967 int jas_image_readcmpt2(jas_image_t *image, int cmptno, jas_image_coord_t x,
    968   jas_image_coord_t y, jas_image_coord_t width, jas_image_coord_t height,
    969   long *buf)
    970 {
    971 	jas_image_cmpt_t *cmpt;
    972 	jas_image_coord_t i;
    973 	jas_image_coord_t j;
    974 	long v;
    975 	long *bufptr;
    976 
    977 	if (cmptno < 0 || cmptno >= image->numcmpts_)
    978 		goto error;
    979 	cmpt = image->cmpts_[cmptno];
    980 	if (x < 0 || x >= cmpt->width_ || y < 0 || y >= cmpt->height_ ||
    981 	  width < 0 || height < 0 || x + width > cmpt->width_ ||
    982 	  y + height > cmpt->height_)
    983 		goto error;
    984 
    985 	bufptr = buf;
    986 	for (i = 0; i < height; ++i) {
    987 		if (jas_stream_seek(cmpt->stream_, (cmpt->width_ * (y + i) + x)
    988 		  * cmpt->cps_, SEEK_SET) < 0)
    989 			goto error;
    990 		for (j = 0; j < width; ++j) {
    991 			if (getint(cmpt->stream_, cmpt->sgnd_, cmpt->prec_, &v))
    992 				goto error;
    993 			*bufptr++ = v;
    994 		}
    995 	}
    996 
    997 	return 0;
    998 error:
    999 	return -1;
   1000 }
   1001 
   1002 int jas_image_writecmpt2(jas_image_t *image, int cmptno, jas_image_coord_t x,
   1003   jas_image_coord_t y, jas_image_coord_t width, jas_image_coord_t height,
   1004   long *buf)
   1005 {
   1006 	jas_image_cmpt_t *cmpt;
   1007 	jas_image_coord_t i;
   1008 	jas_image_coord_t j;
   1009 	long v;
   1010 	long *bufptr;
   1011 
   1012 	if (cmptno < 0 || cmptno >= image->numcmpts_)
   1013 		goto error;
   1014 	cmpt = image->cmpts_[cmptno];
   1015 	if (x < 0 || x >= cmpt->width_ || y < 0 || y >= cmpt->height_ ||
   1016 	  width < 0 || height < 0 || x + width > cmpt->width_ ||
   1017 	  y + height > cmpt->height_)
   1018 		goto error;
   1019 
   1020 	bufptr = buf;
   1021 	for (i = 0; i < height; ++i) {
   1022 		if (jas_stream_seek(cmpt->stream_, (cmpt->width_ * (y + i) + x)
   1023 		  * cmpt->cps_, SEEK_SET) < 0)
   1024 			goto error;
   1025 		for (j = 0; j < width; ++j) {
   1026 			v = *bufptr++;
   1027 			if (putint(cmpt->stream_, cmpt->sgnd_, cmpt->prec_, v))
   1028 				goto error;
   1029 		}
   1030 	}
   1031 
   1032 	return 0;
   1033 error:
   1034 	return -1;
   1035 }
   1036 
   1037 int jas_image_sampcmpt(jas_image_t *image, int cmptno, int newcmptno,
   1038   jas_image_coord_t ho, jas_image_coord_t vo, jas_image_coord_t hs,
   1039   jas_image_coord_t vs, int sgnd, int prec)
   1040 {
   1041 	jas_image_cmpt_t *oldcmpt;
   1042 	jas_image_cmpt_t *newcmpt;
   1043 	int width;
   1044 	int height;
   1045 	jas_image_coord_t tlx;
   1046 	jas_image_coord_t tly;
   1047 	jas_image_coord_t brx;
   1048 	jas_image_coord_t bry;
   1049 	int i;
   1050 	int j;
   1051 	jas_image_cmptparm_t cmptparm;
   1052 	jas_image_coord_t ax;
   1053 	jas_image_coord_t ay;
   1054 	jas_image_coord_t bx;
   1055 	jas_image_coord_t by;
   1056 	jas_image_coord_t d0;
   1057 	jas_image_coord_t d1;
   1058 	jas_image_coord_t d2;
   1059 	jas_image_coord_t d3;
   1060 	jas_image_coord_t oldx;
   1061 	jas_image_coord_t oldy;
   1062 	jas_image_coord_t x;
   1063 	jas_image_coord_t y;
   1064 	long v;
   1065 	jas_image_coord_t cmptbrx;
   1066 	jas_image_coord_t cmptbry;
   1067 
   1068 	assert(cmptno >= 0 && cmptno < image->numcmpts_);
   1069 	oldcmpt = image->cmpts_[cmptno];
   1070 	assert(oldcmpt->tlx_ == 0 && oldcmpt->tly_ == 0);
   1071 	jas_image_calcbbox2(image, &tlx, &tly, &brx, &bry);
   1072 	width = FLOORDIV(brx - ho + hs, hs);
   1073 	height = FLOORDIV(bry - vo + vs, vs);
   1074 	cmptparm.tlx = ho;
   1075 	cmptparm.tly = vo;
   1076 	cmptparm.hstep = hs;
   1077 	cmptparm.vstep = vs;
   1078 	cmptparm.width = width;
   1079 	cmptparm.height = height;
   1080 	cmptparm.prec = prec;
   1081 	cmptparm.sgnd = sgnd;
   1082 	if (jas_image_addcmpt(image, newcmptno, &cmptparm))
   1083 		goto error;
   1084 cmptbrx = oldcmpt->tlx_ + (oldcmpt->width_ - 1) * oldcmpt->hstep_;
   1085 cmptbry = oldcmpt->tly_ + (oldcmpt->height_ - 1) * oldcmpt->vstep_;
   1086 	newcmpt = image->cmpts_[newcmptno];
   1087 	jas_stream_rewind(newcmpt->stream_);
   1088 	for (i = 0; i < height; ++i) {
   1089 		y = newcmpt->tly_ + newcmpt->vstep_ * i;
   1090 		for (j = 0; j < width; ++j) {
   1091 			x = newcmpt->tlx_ + newcmpt->hstep_ * j;
   1092 			ax = downtomult(x - oldcmpt->tlx_, oldcmpt->hstep_) + oldcmpt->tlx_;
   1093 			ay = downtomult(y - oldcmpt->tly_, oldcmpt->vstep_) + oldcmpt->tly_;
   1094 			bx = uptomult(x - oldcmpt->tlx_, oldcmpt->hstep_) + oldcmpt->tlx_;
   1095 			if (bx > cmptbrx)
   1096 				bx = cmptbrx;
   1097 			by = uptomult(y - oldcmpt->tly_, oldcmpt->vstep_) + oldcmpt->tly_;
   1098 			if (by > cmptbry)
   1099 				by = cmptbry;
   1100 			d0 = (ax - x) * (ax - x) + (ay - y) * (ay - y);
   1101 			d1 = (bx - x) * (bx - x) + (ay - y) * (ay - y);
   1102 			d2 = (bx - x) * (bx - x) + (by - y) * (by - y);
   1103 			d3 = (ax - x) * (ax - x) + (by - y) * (by - y);
   1104 			if (d0 <= d1 && d0 <= d2 && d0 <= d3) {
   1105 				oldx = (ax - oldcmpt->tlx_) / oldcmpt->hstep_;
   1106 				oldy = (ay - oldcmpt->tly_) / oldcmpt->vstep_;
   1107 			} else if (d1 <= d0 && d1 <= d2 && d1 <= d3) {
   1108 				oldx = (bx - oldcmpt->tlx_) / oldcmpt->hstep_;
   1109 				oldy = (ay - oldcmpt->tly_) / oldcmpt->vstep_;
   1110 			} else if (d2 <= d0 && d2 <= d1 && d1 <= d3) {
   1111 				oldx = (bx - oldcmpt->tlx_) / oldcmpt->hstep_;
   1112 				oldy = (by - oldcmpt->tly_) / oldcmpt->vstep_;
   1113 			} else {
   1114 				oldx = (ax - oldcmpt->tlx_) / oldcmpt->hstep_;
   1115 				oldy = (by - oldcmpt->tly_) / oldcmpt->vstep_;
   1116 			}
   1117 			assert(oldx >= 0 && oldx < oldcmpt->width_ &&
   1118 			  oldy >= 0 && oldy < oldcmpt->height_);
   1119 			if (jas_stream_seek(oldcmpt->stream_, oldcmpt->cps_ *
   1120 			  (oldy * oldcmpt->width_ + oldx), SEEK_SET) < 0)
   1121 				goto error;
   1122 			if (getint(oldcmpt->stream_, oldcmpt->sgnd_,
   1123 			  oldcmpt->prec_, &v))
   1124 				goto error;
   1125 			if (newcmpt->prec_ != oldcmpt->prec_ ||
   1126 			  newcmpt->sgnd_ != oldcmpt->sgnd_) {
   1127 				v = convert(v, oldcmpt->sgnd_, oldcmpt->prec_,
   1128 				  newcmpt->sgnd_, newcmpt->prec_);
   1129 			}
   1130 			if (putint(newcmpt->stream_, newcmpt->sgnd_,
   1131 			  newcmpt->prec_, v))
   1132 				goto error;
   1133 		}
   1134 	}
   1135 	return 0;
   1136 error:
   1137 	return -1;
   1138 }
   1139 
   1140 int jas_image_ishomosamp(jas_image_t *image)
   1141 {
   1142 	jas_image_coord_t hstep;
   1143 	jas_image_coord_t vstep;
   1144 	int result;
   1145 	int i;
   1146 	hstep = jas_image_cmpthstep(image, 0);
   1147 	vstep = jas_image_cmptvstep(image, 0);
   1148 	result = 1;
   1149 	for (i = 0; i < image->numcmpts_; ++i) {
   1150 		if (jas_image_cmpthstep(image, i) != hstep ||
   1151 		  jas_image_cmptvstep(image, i) != vstep) {
   1152 			result = 0;
   1153 			break;
   1154 		}
   1155 	}
   1156 	return result;
   1157 }
   1158 
   1159 /* Note: This function defines a bounding box differently. */
   1160 static void jas_image_calcbbox2(jas_image_t *image, jas_image_coord_t *tlx,
   1161   jas_image_coord_t *tly, jas_image_coord_t *brx, jas_image_coord_t *bry)
   1162 {
   1163 	jas_image_cmpt_t *cmpt;
   1164 	jas_image_coord_t tmptlx;
   1165 	jas_image_coord_t tmptly;
   1166 	jas_image_coord_t tmpbrx;
   1167 	jas_image_coord_t tmpbry;
   1168 	jas_image_coord_t t;
   1169 	int i;
   1170 	if (image->numcmpts_ > 0) {
   1171 		cmpt = image->cmpts_[0];
   1172 		tmptlx = cmpt->tlx_;
   1173 		tmptly = cmpt->tly_;
   1174 		tmpbrx = cmpt->tlx_ + cmpt->hstep_ * (cmpt->width_ - 1);
   1175 		tmpbry = cmpt->tly_ + cmpt->vstep_ * (cmpt->height_ - 1);
   1176 		for (i = 0; i < image->numcmpts_; ++i) {
   1177 			cmpt = image->cmpts_[i];
   1178 			if (cmpt->tlx_ < tmptlx)
   1179 				tmptlx = cmpt->tlx_;
   1180 			if (cmpt->tly_ < tmptly)
   1181 				tmptly = cmpt->tly_;
   1182 			t = cmpt->tlx_ + cmpt->hstep_ * (cmpt->width_ - 1);
   1183 			if (t > tmpbrx)
   1184 				tmpbrx = t;
   1185 			t = cmpt->tly_ + cmpt->vstep_ * (cmpt->height_ - 1);
   1186 			if (t > tmpbry)
   1187 				tmpbry = t;
   1188 		}
   1189 	} else {
   1190 		tmptlx = 0;
   1191 		tmptly = 0;
   1192 		tmpbrx = -1;
   1193 		tmpbry = -1;
   1194 	}
   1195 	*tlx = tmptlx;
   1196 	*tly = tmptly;
   1197 	*brx = tmpbrx;
   1198 	*bry = tmpbry;
   1199 }
   1200 
   1201 
   1202 
   1203 static int getint(jas_stream_t *in, int sgnd, int prec, long *val)
   1204 {
   1205 	long v;
   1206 	int n;
   1207 	int c;
   1208 	n = (prec + 7) / 8;
   1209 	v = 0;
   1210 	while (--n >= 0) {
   1211 		if ((c = jas_stream_getc(in)) == EOF)
   1212 			return -1;
   1213 		v = (v << 8) | c;
   1214 	}
   1215 	v &= ((1 << prec) - 1);
   1216 	if (sgnd) {
   1217 		/* XXX - Do something here. */
   1218 		abort();
   1219 	} else {
   1220 		*val = v;
   1221 	}
   1222 	return 0;
   1223 }
   1224 
   1225 static int putint(jas_stream_t *out, int sgnd, int prec, long val)
   1226 {
   1227 	int n;
   1228 	int c;
   1229 	if (sgnd) {
   1230 		/* XXX - Do something here. */
   1231 		abort();
   1232 	}
   1233 	val &= (1 << prec) - 1;
   1234 	n = (prec + 7) / 8;
   1235 	while (--n >= 0) {
   1236 		c = (val >> (n * 8)) & 0xff;
   1237 		if (jas_stream_putc(out, c) != c)
   1238 			return -1;
   1239 	}
   1240 	return 0;
   1241 }
   1242 
   1243 static long convert(long val, int oldsgnd, int oldprec, int newsgnd,
   1244   int newprec)
   1245 {
   1246 	if (newsgnd != oldsgnd) {
   1247 	}
   1248 	if (newprec != oldprec) {
   1249 		if (newprec > oldprec) {
   1250 			val <<= newprec - oldprec;
   1251 		} else if (oldprec > newprec) {
   1252 			val >>= oldprec - newprec;
   1253 		}
   1254 	}
   1255 	return val;
   1256 }
   1257 
   1258 static long downtomult(long x, long y)
   1259 {
   1260 	assert(x >= 0);
   1261 	return (x / y) * y;
   1262 }
   1263 
   1264 static long uptomult(long x, long y)
   1265 {
   1266 	assert(x >= 0);
   1267 	return ((x + y - 1) / y) * y;
   1268 }
   1269 
   1270 jas_image_t *jas_image_chclrspc(jas_image_t *image, jas_cmprof_t *outprof,
   1271   int intent)
   1272 {
   1273 	jas_image_t *inimage;
   1274 	int minhstep;
   1275 	int minvstep;
   1276 	int i;
   1277 	int j;
   1278 	int k;
   1279 	int n;
   1280 	int hstep;
   1281 	int vstep;
   1282 	int numinauxchans;
   1283 	int numoutauxchans;
   1284 	int numinclrchans;
   1285 	int numoutclrchans;
   1286 	int prec;
   1287 	jas_image_t *outimage;
   1288 	int cmpttype;
   1289 	int numoutchans;
   1290 	jas_cmprof_t *inprof;
   1291 	jas_cmprof_t *tmpprof;
   1292 	jas_image_cmptparm_t cmptparm;
   1293 	int width;
   1294 	int height;
   1295 	jas_cmxform_t *xform;
   1296 	jas_cmpixmap_t inpixmap;
   1297 	jas_cmpixmap_t outpixmap;
   1298 	jas_cmcmptfmt_t *incmptfmts;
   1299 	jas_cmcmptfmt_t *outcmptfmts;
   1300 
   1301 #if 0
   1302 fprintf(stderr, "IMAGE\n");
   1303 jas_image_dump(image, stderr);
   1304 #endif
   1305 
   1306 	if (!(inimage = jas_image_copy(image)))
   1307 		goto error;
   1308 	image = 0;
   1309 
   1310 	if (!jas_image_ishomosamp(inimage)) {
   1311 		minhstep = jas_image_cmpthstep(inimage, 0);
   1312 		minvstep = jas_image_cmptvstep(inimage, 0);
   1313 		for (i = 1; i < jas_image_numcmpts(inimage); ++i) {
   1314 			hstep = jas_image_cmpthstep(inimage, i);
   1315 			vstep = jas_image_cmptvstep(inimage, i);
   1316 			if (hstep < minhstep)
   1317 				minhstep = hstep;
   1318 			if (vstep < minvstep)
   1319 				minvstep = vstep;
   1320 		}
   1321 		n = jas_image_numcmpts(inimage);
   1322 		for (i = 0; i < n; ++i) {
   1323 			cmpttype = jas_image_cmpttype(inimage, i);
   1324 			if (jas_image_sampcmpt(inimage, i, i + 1, 0, 0, minhstep, minvstep, jas_image_cmptsgnd(inimage, i), jas_image_cmptprec(inimage, i)))
   1325 				goto error;
   1326 			jas_image_setcmpttype(inimage, i + 1, cmpttype);
   1327 			jas_image_delcmpt(inimage, i);
   1328 		}
   1329 	}
   1330 
   1331 	width = jas_image_cmptwidth(inimage, 0);
   1332 	height = jas_image_cmptheight(inimage, 0);
   1333 	hstep = jas_image_cmpthstep(inimage, 0);
   1334 	vstep = jas_image_cmptvstep(inimage, 0);
   1335 
   1336 	inprof = jas_image_cmprof(inimage);
   1337 	assert(inprof);
   1338 	numinclrchans = jas_clrspc_numchans(jas_cmprof_clrspc(inprof));
   1339 	numinauxchans = jas_image_numcmpts(inimage) - numinclrchans;
   1340 	numoutclrchans = jas_clrspc_numchans(jas_cmprof_clrspc(outprof));
   1341 	numoutauxchans = 0;
   1342 	numoutchans = numoutclrchans + numoutauxchans;
   1343 	prec = 8;
   1344 
   1345 	if (!(outimage = jas_image_create0()))
   1346 		goto error;
   1347 
   1348 	/* Create a component for each of the colorants. */
   1349 	for (i = 0; i < numoutclrchans; ++i) {
   1350 		cmptparm.tlx = 0;
   1351 		cmptparm.tly = 0;
   1352 		cmptparm.hstep = hstep;
   1353 		cmptparm.vstep = vstep;
   1354 		cmptparm.width = width;
   1355 		cmptparm.height = height;
   1356 		cmptparm.prec = prec;
   1357 		cmptparm.sgnd = 0;
   1358 		if (jas_image_addcmpt(outimage, -1, &cmptparm))
   1359 			goto error;
   1360 		jas_image_setcmpttype(outimage, i, JAS_IMAGE_CT_COLOR(i));
   1361 	}
   1362 #if 0
   1363 	/* Copy the auxiliary components without modification. */
   1364 	for (i = 0; i < jas_image_numcmpts(inimage); ++i) {
   1365 		if (!ISCOLOR(jas_image_cmpttype(inimage, i))) {
   1366 			jas_image_copycmpt(outimage, -1, inimage, i);
   1367 /* XXX - need to specify laydown of component on ref. grid */
   1368 		}
   1369 	}
   1370 #endif
   1371 
   1372 	if (!(tmpprof = jas_cmprof_copy(outprof)))
   1373 		goto error;
   1374 	assert(!jas_image_cmprof(outimage));
   1375 	jas_image_setcmprof(outimage, tmpprof);
   1376 	tmpprof = 0;
   1377 	jas_image_setclrspc(outimage, jas_cmprof_clrspc(outprof));
   1378 
   1379 	if (!(xform = jas_cmxform_create(inprof, outprof, 0, JAS_CMXFORM_OP_FWD, intent, 0)))
   1380 		goto error;
   1381 
   1382 	inpixmap.numcmpts = numinclrchans;
   1383 	incmptfmts = malloc(numinclrchans * sizeof(jas_cmcmptfmt_t));
   1384 	assert(incmptfmts);
   1385 	inpixmap.cmptfmts = incmptfmts;
   1386 	for (i = 0; i < numinclrchans; ++i) {
   1387 		j = jas_image_getcmptbytype(inimage, JAS_IMAGE_CT_COLOR(i));
   1388 		assert(j >= 0);
   1389 		if (!(incmptfmts[i].buf = malloc(width * sizeof(long))))
   1390 			goto error;
   1391 		incmptfmts[i].prec = jas_image_cmptprec(inimage, j);
   1392 		incmptfmts[i].sgnd = jas_image_cmptsgnd(inimage, j);
   1393 		incmptfmts[i].width = width;
   1394 		incmptfmts[i].height = 1;
   1395 	}
   1396 
   1397 	outpixmap.numcmpts = numoutclrchans;
   1398 	outcmptfmts = malloc(numoutclrchans * sizeof(jas_cmcmptfmt_t));
   1399 	assert(outcmptfmts);
   1400 	outpixmap.cmptfmts = outcmptfmts;
   1401 
   1402 	for (i = 0; i < numoutclrchans; ++i) {
   1403 		j = jas_image_getcmptbytype(outimage, JAS_IMAGE_CT_COLOR(i));
   1404 		assert(j >= 0);
   1405 		if (!(outcmptfmts[i].buf = malloc(width * sizeof(long))))
   1406 			goto error;
   1407 		outcmptfmts[i].prec = jas_image_cmptprec(outimage, j);
   1408 		outcmptfmts[i].sgnd = jas_image_cmptsgnd(outimage, j);
   1409 		outcmptfmts[i].width = width;
   1410 		outcmptfmts[i].height = 1;
   1411 	}
   1412 
   1413 	for (i = 0; i < height; ++i) {
   1414 		for (j = 0; j < numinclrchans; ++j) {
   1415 			k = jas_image_getcmptbytype(inimage, JAS_IMAGE_CT_COLOR(j));
   1416 			if (jas_image_readcmpt2(inimage, k, 0, i, width, 1, incmptfmts[j].buf))
   1417 				goto error;
   1418 		}
   1419 		jas_cmxform_apply(xform, &inpixmap, &outpixmap);
   1420 		for (j = 0; j < numoutclrchans; ++j) {
   1421 			k = jas_image_getcmptbytype(outimage, JAS_IMAGE_CT_COLOR(j));
   1422 			if (jas_image_writecmpt2(outimage, k, 0, i, width, 1, outcmptfmts[j].buf))
   1423 				goto error;
   1424 		}
   1425 	}
   1426 
   1427 	for (i = 0; i < numoutclrchans; ++i)
   1428 		jas_free(outcmptfmts[i].buf);
   1429 	jas_free(outcmptfmts);
   1430 	for (i = 0; i < numinclrchans; ++i)
   1431 		jas_free(incmptfmts[i].buf);
   1432 	jas_free(incmptfmts);
   1433 	jas_cmxform_destroy(xform);
   1434 	jas_image_destroy(inimage);
   1435 
   1436 #if 0
   1437 fprintf(stderr, "INIMAGE\n");
   1438 jas_image_dump(inimage, stderr);
   1439 fprintf(stderr, "OUTIMAGE\n");
   1440 jas_image_dump(outimage, stderr);
   1441 #endif
   1442 	return outimage;
   1443 error:
   1444 	return 0;
   1445 }