Home | History | Annotate | Download | only in libjasper
      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) 2001-2006 Michael David Adams
     13  * Copyright (c) 1999-2000 Image Power, Inc.
     14  * Copyright (c) 1999-2000 The University of British Columbia
     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,v 1.2 2008-05-26 09:40:52 vp153 Exp $
     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_alloc2(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->type_ = JAS_IMAGE_CT_UNKNOWN;
    310     cmpt->tlx_ = tlx;
    311     cmpt->tly_ = tly;
    312     cmpt->hstep_ = hstep;
    313     cmpt->vstep_ = vstep;
    314     cmpt->width_ = width;
    315     cmpt->height_ = height;
    316     cmpt->prec_ = depth;
    317     cmpt->sgnd_ = sgnd;
    318     cmpt->stream_ = 0;
    319     cmpt->cps_ = (depth + 7) / 8;
    320 
    321     size = cmpt->width_ * cmpt->height_ * cmpt->cps_;
    322     cmpt->stream_ = (inmem) ? jas_stream_memopen(0, size) : jas_stream_tmpfile();
    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 = jas_realloc2(image->cmpts_, maxcmpts, sizeof(jas_image_cmpt_t *));
    778     if (!newcmpts) {
    779         return -1;
    780     }
    781     image->cmpts_ = newcmpts;
    782     image->maxcmpts_ = maxcmpts;
    783     for (cmptno = image->numcmpts_; cmptno < image->maxcmpts_; ++cmptno) {
    784         image->cmpts_[cmptno] = 0;
    785     }
    786     return 0;
    787 }
    788 
    789 int jas_image_copycmpt(jas_image_t *dstimage, int dstcmptno, jas_image_t *srcimage,
    790   int srccmptno)
    791 {
    792     jas_image_cmpt_t *newcmpt;
    793     if (dstimage->numcmpts_ >= dstimage->maxcmpts_) {
    794         if (jas_image_growcmpts(dstimage, dstimage->maxcmpts_ + 128)) {
    795             return -1;
    796         }
    797     }
    798     if (!(newcmpt = jas_image_cmpt_copy(srcimage->cmpts_[srccmptno]))) {
    799         return -1;
    800     }
    801     if (dstcmptno < dstimage->numcmpts_) {
    802         memmove(&dstimage->cmpts_[dstcmptno + 1], &dstimage->cmpts_[dstcmptno],
    803           (dstimage->numcmpts_ - dstcmptno) * sizeof(jas_image_cmpt_t *));
    804     }
    805     dstimage->cmpts_[dstcmptno] = newcmpt;
    806     ++dstimage->numcmpts_;
    807 
    808     jas_image_setbbox(dstimage);
    809     return 0;
    810 }
    811 
    812 void jas_image_dump(jas_image_t *image, FILE *out)
    813 {
    814     long buf[1024];
    815     int cmptno;
    816     int n;
    817     int i;
    818     int width;
    819     int height;
    820     jas_image_cmpt_t *cmpt;
    821     for (cmptno = 0; cmptno < image->numcmpts_; ++cmptno) {
    822         cmpt = image->cmpts_[cmptno];
    823         fprintf(out, "prec=%d, sgnd=%d, cmpttype=%d\n", cmpt->prec_,
    824           cmpt->sgnd_, (int)cmpt->type_);
    825         width = jas_image_cmptwidth(image, cmptno);
    826         height = jas_image_cmptheight(image, cmptno);
    827         n = JAS_MIN(16, width);
    828         if (jas_image_readcmpt2(image, cmptno, 0, 0, n, 1, buf)) {
    829             abort();
    830         }
    831         for (i = 0; i < n; ++i) {
    832             fprintf(out, " f(%d,%d)=%ld", i, 0, buf[i]);
    833         }
    834         fprintf(out, "\n");
    835         if (jas_image_readcmpt2(image, cmptno, width - n, height - 1, n, 1, buf)) {
    836             abort();
    837         }
    838         for (i = 0; i < n; ++i) {
    839             fprintf(out, " f(%d,%d)=%ld", width - n + i, height - 1, buf[i]);
    840         }
    841         fprintf(out, "\n");
    842     }
    843 }
    844 
    845 int jas_image_depalettize(jas_image_t *image, int cmptno, int numlutents,
    846   int_fast32_t *lutents, int dtype, int newcmptno)
    847 {
    848     jas_image_cmptparm_t cmptparms;
    849     int_fast32_t v;
    850     int i;
    851     int j;
    852     jas_image_cmpt_t *cmpt;
    853 
    854     cmpt = image->cmpts_[cmptno];
    855     cmptparms.tlx = cmpt->tlx_;
    856     cmptparms.tly = cmpt->tly_;
    857     cmptparms.hstep = cmpt->hstep_;
    858     cmptparms.vstep = cmpt->vstep_;
    859     cmptparms.width = cmpt->width_;
    860     cmptparms.height = cmpt->height_;
    861     cmptparms.prec = JAS_IMAGE_CDT_GETPREC(dtype);
    862     cmptparms.sgnd = JAS_IMAGE_CDT_GETSGND(dtype);
    863 
    864     if (jas_image_addcmpt(image, newcmptno, &cmptparms)) {
    865         return -1;
    866     }
    867     if (newcmptno <= cmptno) {
    868         ++cmptno;
    869         cmpt = image->cmpts_[cmptno];
    870     }
    871 
    872     for (j = 0; j < cmpt->height_; ++j) {
    873         for (i = 0; i < cmpt->width_; ++i) {
    874             v = jas_image_readcmptsample(image, cmptno, i, j);
    875             if (v < 0) {
    876                 v = 0;
    877             } else if (v >= numlutents) {
    878                 v = numlutents - 1;
    879             }
    880             jas_image_writecmptsample(image, newcmptno, i, j,
    881               lutents[v]);
    882         }
    883     }
    884     return 0;
    885 }
    886 
    887 int jas_image_readcmptsample(jas_image_t *image, int cmptno, int x, int y)
    888 {
    889     jas_image_cmpt_t *cmpt;
    890     uint_fast32_t v;
    891     int k;
    892     int c;
    893 
    894     cmpt = image->cmpts_[cmptno];
    895 
    896     if (jas_stream_seek(cmpt->stream_, (cmpt->width_ * y + x) * cmpt->cps_,
    897       SEEK_SET) < 0) {
    898         return -1;
    899     }
    900     v = 0;
    901     for (k = cmpt->cps_; k > 0; --k) {
    902         if ((c = jas_stream_getc(cmpt->stream_)) == EOF) {
    903             return -1;
    904         }
    905         v = (v << 8) | (c & 0xff);
    906     }
    907     return bitstoint(v, cmpt->prec_, cmpt->sgnd_);
    908 }
    909 
    910 void jas_image_writecmptsample(jas_image_t *image, int cmptno, int x, int y,
    911   int_fast32_t v)
    912 {
    913     jas_image_cmpt_t *cmpt;
    914     uint_fast32_t t;
    915     int k;
    916     int c;
    917 
    918     cmpt = image->cmpts_[cmptno];
    919 
    920     if (jas_stream_seek(cmpt->stream_, (cmpt->width_ * y + x) * cmpt->cps_,
    921       SEEK_SET) < 0) {
    922         return;
    923     }
    924     t = inttobits(v, cmpt->prec_, cmpt->sgnd_);
    925     for (k = cmpt->cps_; k > 0; --k) {
    926         c = (t >> (8 * (cmpt->cps_ - 1))) & 0xff;
    927         if (jas_stream_putc(cmpt->stream_, (unsigned char) c) == EOF) {
    928             return;
    929         }
    930         t <<= 8;
    931     }
    932 }
    933 
    934 int jas_image_getcmptbytype(jas_image_t *image, int ctype)
    935 {
    936     int cmptno;
    937 
    938     for (cmptno = 0; cmptno < image->numcmpts_; ++cmptno) {
    939         if (image->cmpts_[cmptno]->type_ == ctype) {
    940             return cmptno;
    941         }
    942     }
    943     return -1;
    944 }
    945 
    946 
    947 
    948 
    949 
    950 
    951 
    952 
    953 
    954 
    955 
    956 
    957 
    958 
    959 
    960 
    961 /***********************************************/
    962 /***********************************************/
    963 /***********************************************/
    964 /***********************************************/
    965 
    966 int jas_image_readcmpt2(jas_image_t *image, int cmptno, jas_image_coord_t x,
    967   jas_image_coord_t y, jas_image_coord_t width, jas_image_coord_t height,
    968   long *buf)
    969 {
    970     jas_image_cmpt_t *cmpt;
    971     jas_image_coord_t i;
    972     jas_image_coord_t j;
    973     long v;
    974     long *bufptr;
    975 
    976     if (cmptno < 0 || cmptno >= image->numcmpts_)
    977         goto error;
    978     cmpt = image->cmpts_[cmptno];
    979     if (x < 0 || x >= cmpt->width_ || y < 0 || y >= cmpt->height_ ||
    980       width < 0 || height < 0 || x + width > cmpt->width_ ||
    981       y + height > cmpt->height_)
    982         goto error;
    983 
    984     bufptr = buf;
    985     for (i = 0; i < height; ++i) {
    986         if (jas_stream_seek(cmpt->stream_, (cmpt->width_ * (y + i) + x)
    987           * cmpt->cps_, SEEK_SET) < 0)
    988             goto error;
    989         for (j = 0; j < width; ++j) {
    990             if (getint(cmpt->stream_, cmpt->sgnd_, cmpt->prec_, &v))
    991                 goto error;
    992             *bufptr++ = v;
    993         }
    994     }
    995 
    996     return 0;
    997 error:
    998     return -1;
    999 }
   1000 
   1001 int jas_image_writecmpt2(jas_image_t *image, int cmptno, jas_image_coord_t x,
   1002   jas_image_coord_t y, jas_image_coord_t width, jas_image_coord_t height,
   1003   long *buf)
   1004 {
   1005     jas_image_cmpt_t *cmpt;
   1006     jas_image_coord_t i;
   1007     jas_image_coord_t j;
   1008     long v;
   1009     long *bufptr;
   1010 
   1011     if (cmptno < 0 || cmptno >= image->numcmpts_)
   1012         goto error;
   1013     cmpt = image->cmpts_[cmptno];
   1014     if (x < 0 || x >= cmpt->width_ || y < 0 || y >= cmpt->height_ ||
   1015       width < 0 || height < 0 || x + width > cmpt->width_ ||
   1016       y + height > cmpt->height_)
   1017         goto error;
   1018 
   1019     bufptr = buf;
   1020     for (i = 0; i < height; ++i) {
   1021         if (jas_stream_seek(cmpt->stream_, (cmpt->width_ * (y + i) + x)
   1022           * cmpt->cps_, SEEK_SET) < 0)
   1023             goto error;
   1024         for (j = 0; j < width; ++j) {
   1025             v = *bufptr++;
   1026             if (putint(cmpt->stream_, cmpt->sgnd_, cmpt->prec_, v))
   1027                 goto error;
   1028         }
   1029     }
   1030 
   1031     return 0;
   1032 error:
   1033     return -1;
   1034 }
   1035 
   1036 int jas_image_sampcmpt(jas_image_t *image, int cmptno, int newcmptno,
   1037   jas_image_coord_t ho, jas_image_coord_t vo, jas_image_coord_t hs,
   1038   jas_image_coord_t vs, int sgnd, int prec)
   1039 {
   1040     jas_image_cmpt_t *oldcmpt;
   1041     jas_image_cmpt_t *newcmpt;
   1042     int width;
   1043     int height;
   1044     jas_image_coord_t tlx;
   1045     jas_image_coord_t tly;
   1046     jas_image_coord_t brx;
   1047     jas_image_coord_t bry;
   1048     int i;
   1049     int j;
   1050     jas_image_cmptparm_t cmptparm;
   1051     jas_image_coord_t ax;
   1052     jas_image_coord_t ay;
   1053     jas_image_coord_t bx;
   1054     jas_image_coord_t by;
   1055     jas_image_coord_t d0;
   1056     jas_image_coord_t d1;
   1057     jas_image_coord_t d2;
   1058     jas_image_coord_t d3;
   1059     jas_image_coord_t oldx;
   1060     jas_image_coord_t oldy;
   1061     jas_image_coord_t x;
   1062     jas_image_coord_t y;
   1063     long v;
   1064     jas_image_coord_t cmptbrx;
   1065     jas_image_coord_t cmptbry;
   1066 
   1067     assert(cmptno >= 0 && cmptno < image->numcmpts_);
   1068     oldcmpt = image->cmpts_[cmptno];
   1069     assert(oldcmpt->tlx_ == 0 && oldcmpt->tly_ == 0);
   1070     jas_image_calcbbox2(image, &tlx, &tly, &brx, &bry);
   1071     width = FLOORDIV(brx - ho + hs, hs);
   1072     height = FLOORDIV(bry - vo + vs, vs);
   1073     cmptparm.tlx = ho;
   1074     cmptparm.tly = vo;
   1075     cmptparm.hstep = hs;
   1076     cmptparm.vstep = vs;
   1077     cmptparm.width = width;
   1078     cmptparm.height = height;
   1079     cmptparm.prec = prec;
   1080     cmptparm.sgnd = sgnd;
   1081     if (jas_image_addcmpt(image, newcmptno, &cmptparm))
   1082         goto error;
   1083 cmptbrx = oldcmpt->tlx_ + (oldcmpt->width_ - 1) * oldcmpt->hstep_;
   1084 cmptbry = oldcmpt->tly_ + (oldcmpt->height_ - 1) * oldcmpt->vstep_;
   1085     newcmpt = image->cmpts_[newcmptno];
   1086     jas_stream_rewind(newcmpt->stream_);
   1087     for (i = 0; i < height; ++i) {
   1088         y = newcmpt->tly_ + newcmpt->vstep_ * i;
   1089         for (j = 0; j < width; ++j) {
   1090             x = newcmpt->tlx_ + newcmpt->hstep_ * j;
   1091             ax = downtomult(x - oldcmpt->tlx_, oldcmpt->hstep_) + oldcmpt->tlx_;
   1092             ay = downtomult(y - oldcmpt->tly_, oldcmpt->vstep_) + oldcmpt->tly_;
   1093             bx = uptomult(x - oldcmpt->tlx_, oldcmpt->hstep_) + oldcmpt->tlx_;
   1094             if (bx > cmptbrx)
   1095                 bx = cmptbrx;
   1096             by = uptomult(y - oldcmpt->tly_, oldcmpt->vstep_) + oldcmpt->tly_;
   1097             if (by > cmptbry)
   1098                 by = cmptbry;
   1099             d0 = (ax - x) * (ax - x) + (ay - y) * (ay - y);
   1100             d1 = (bx - x) * (bx - x) + (ay - y) * (ay - y);
   1101             d2 = (bx - x) * (bx - x) + (by - y) * (by - y);
   1102             d3 = (ax - x) * (ax - x) + (by - y) * (by - y);
   1103             if (d0 <= d1 && d0 <= d2 && d0 <= d3) {
   1104                 oldx = (ax - oldcmpt->tlx_) / oldcmpt->hstep_;
   1105                 oldy = (ay - oldcmpt->tly_) / oldcmpt->vstep_;
   1106             } else if (d1 <= d0 && d1 <= d2 && d1 <= d3) {
   1107                 oldx = (bx - oldcmpt->tlx_) / oldcmpt->hstep_;
   1108                 oldy = (ay - oldcmpt->tly_) / oldcmpt->vstep_;
   1109             } else if (d2 <= d0 && d2 <= d1 && d1 <= d3) {
   1110                 oldx = (bx - oldcmpt->tlx_) / oldcmpt->hstep_;
   1111                 oldy = (by - oldcmpt->tly_) / oldcmpt->vstep_;
   1112             } else {
   1113                 oldx = (ax - oldcmpt->tlx_) / oldcmpt->hstep_;
   1114                 oldy = (by - oldcmpt->tly_) / oldcmpt->vstep_;
   1115             }
   1116             assert(oldx >= 0 && oldx < oldcmpt->width_ &&
   1117               oldy >= 0 && oldy < oldcmpt->height_);
   1118             if (jas_stream_seek(oldcmpt->stream_, oldcmpt->cps_ *
   1119               (oldy * oldcmpt->width_ + oldx), SEEK_SET) < 0)
   1120                 goto error;
   1121             if (getint(oldcmpt->stream_, oldcmpt->sgnd_,
   1122               oldcmpt->prec_, &v))
   1123                 goto error;
   1124             if (newcmpt->prec_ != oldcmpt->prec_ ||
   1125               newcmpt->sgnd_ != oldcmpt->sgnd_) {
   1126                 v = convert(v, oldcmpt->sgnd_, oldcmpt->prec_,
   1127                   newcmpt->sgnd_, newcmpt->prec_);
   1128             }
   1129             if (putint(newcmpt->stream_, newcmpt->sgnd_,
   1130               newcmpt->prec_, v))
   1131                 goto error;
   1132         }
   1133     }
   1134     return 0;
   1135 error:
   1136     return -1;
   1137 }
   1138 
   1139 int jas_image_ishomosamp(jas_image_t *image)
   1140 {
   1141     jas_image_coord_t hstep;
   1142     jas_image_coord_t vstep;
   1143     int result;
   1144     int i;
   1145     hstep = jas_image_cmpthstep(image, 0);
   1146     vstep = jas_image_cmptvstep(image, 0);
   1147     result = 1;
   1148     for (i = 0; i < image->numcmpts_; ++i) {
   1149         if (jas_image_cmpthstep(image, i) != hstep ||
   1150           jas_image_cmptvstep(image, i) != vstep) {
   1151             result = 0;
   1152             break;
   1153         }
   1154     }
   1155     return result;
   1156 }
   1157 
   1158 /* Note: This function defines a bounding box differently. */
   1159 static void jas_image_calcbbox2(jas_image_t *image, jas_image_coord_t *tlx,
   1160   jas_image_coord_t *tly, jas_image_coord_t *brx, jas_image_coord_t *bry)
   1161 {
   1162     jas_image_cmpt_t *cmpt;
   1163     jas_image_coord_t tmptlx;
   1164     jas_image_coord_t tmptly;
   1165     jas_image_coord_t tmpbrx;
   1166     jas_image_coord_t tmpbry;
   1167     jas_image_coord_t t;
   1168     int i;
   1169     if (image->numcmpts_ > 0) {
   1170         cmpt = image->cmpts_[0];
   1171         tmptlx = cmpt->tlx_;
   1172         tmptly = cmpt->tly_;
   1173         tmpbrx = cmpt->tlx_ + cmpt->hstep_ * (cmpt->width_ - 1);
   1174         tmpbry = cmpt->tly_ + cmpt->vstep_ * (cmpt->height_ - 1);
   1175         for (i = 0; i < image->numcmpts_; ++i) {
   1176             cmpt = image->cmpts_[i];
   1177             if (cmpt->tlx_ < tmptlx)
   1178                 tmptlx = cmpt->tlx_;
   1179             if (cmpt->tly_ < tmptly)
   1180                 tmptly = cmpt->tly_;
   1181             t = cmpt->tlx_ + cmpt->hstep_ * (cmpt->width_ - 1);
   1182             if (t > tmpbrx)
   1183                 tmpbrx = t;
   1184             t = cmpt->tly_ + cmpt->vstep_ * (cmpt->height_ - 1);
   1185             if (t > tmpbry)
   1186                 tmpbry = t;
   1187         }
   1188     } else {
   1189         tmptlx = 0;
   1190         tmptly = 0;
   1191         tmpbrx = -1;
   1192         tmpbry = -1;
   1193     }
   1194     *tlx = tmptlx;
   1195     *tly = tmptly;
   1196     *brx = tmpbrx;
   1197     *bry = tmpbry;
   1198 }
   1199 
   1200 
   1201 
   1202 static int getint(jas_stream_t *in, int sgnd, int prec, long *val)
   1203 {
   1204     long v;
   1205     int n;
   1206     int c;
   1207     n = (prec + 7) / 8;
   1208     v = 0;
   1209     while (--n >= 0) {
   1210         if ((c = jas_stream_getc(in)) == EOF)
   1211             return -1;
   1212         v = (v << 8) | c;
   1213     }
   1214     v &= ((1 << prec) - 1);
   1215     if (sgnd) {
   1216         /* XXX - Do something here. */
   1217         abort();
   1218     } else {
   1219         *val = v;
   1220     }
   1221     return 0;
   1222 }
   1223 
   1224 static int putint(jas_stream_t *out, int sgnd, int prec, long val)
   1225 {
   1226     int n;
   1227     int c;
   1228     if (sgnd) {
   1229         /* XXX - Do something here. */
   1230         abort();
   1231     }
   1232     val &= (1 << prec) - 1;
   1233     n = (prec + 7) / 8;
   1234     while (--n >= 0) {
   1235         c = (val >> (n * 8)) & 0xff;
   1236         if (jas_stream_putc(out, c) != c)
   1237             return -1;
   1238     }
   1239     return 0;
   1240 }
   1241 
   1242 static long convert(long val, int oldsgnd, int oldprec, int newsgnd,
   1243   int newprec)
   1244 {
   1245     if (newsgnd != oldsgnd) {
   1246     }
   1247     if (newprec != oldprec) {
   1248         if (newprec > oldprec) {
   1249             val <<= newprec - oldprec;
   1250         } else if (oldprec > newprec) {
   1251             val >>= oldprec - newprec;
   1252         }
   1253     }
   1254     return val;
   1255 }
   1256 
   1257 static long downtomult(long x, long y)
   1258 {
   1259     assert(x >= 0);
   1260     return (x / y) * y;
   1261 }
   1262 
   1263 static long uptomult(long x, long y)
   1264 {
   1265     assert(x >= 0);
   1266     return ((x + y - 1) / y) * y;
   1267 }
   1268 
   1269 jas_image_t *jas_image_chclrspc(jas_image_t *image, jas_cmprof_t *outprof,
   1270   int intent)
   1271 {
   1272     jas_image_t *inimage;
   1273     int minhstep;
   1274     int minvstep;
   1275     int i;
   1276     int j;
   1277     int k;
   1278     int n;
   1279     int hstep;
   1280     int vstep;
   1281     int numinauxchans;
   1282     int numoutauxchans;
   1283     int numinclrchans;
   1284     int numoutclrchans;
   1285     int prec;
   1286     jas_image_t *outimage;
   1287     int cmpttype;
   1288     int numoutchans;
   1289     jas_cmprof_t *inprof;
   1290     jas_cmprof_t *tmpprof;
   1291     jas_image_cmptparm_t cmptparm;
   1292     int width;
   1293     int height;
   1294     jas_cmxform_t *xform;
   1295     jas_cmpixmap_t inpixmap;
   1296     jas_cmpixmap_t outpixmap;
   1297     jas_cmcmptfmt_t *incmptfmts;
   1298     jas_cmcmptfmt_t *outcmptfmts;
   1299 
   1300 #if 0
   1301 jas_eprintf("IMAGE\n");
   1302 jas_image_dump(image, stderr);
   1303 #endif
   1304 
   1305     if (!(inimage = jas_image_copy(image)))
   1306         goto error;
   1307     image = 0;
   1308 
   1309     if (!jas_image_ishomosamp(inimage)) {
   1310         minhstep = jas_image_cmpthstep(inimage, 0);
   1311         minvstep = jas_image_cmptvstep(inimage, 0);
   1312         for (i = 1; i < jas_image_numcmpts(inimage); ++i) {
   1313             hstep = jas_image_cmpthstep(inimage, i);
   1314             vstep = jas_image_cmptvstep(inimage, i);
   1315             if (hstep < minhstep)
   1316                 minhstep = hstep;
   1317             if (vstep < minvstep)
   1318                 minvstep = vstep;
   1319         }
   1320         n = jas_image_numcmpts(inimage);
   1321         for (i = 0; i < n; ++i) {
   1322             cmpttype = jas_image_cmpttype(inimage, i);
   1323             if (jas_image_sampcmpt(inimage, i, i + 1, 0, 0, minhstep, minvstep, jas_image_cmptsgnd(inimage, i), jas_image_cmptprec(inimage, i)))
   1324                 goto error;
   1325             jas_image_setcmpttype(inimage, i + 1, cmpttype);
   1326             jas_image_delcmpt(inimage, i);
   1327         }
   1328     }
   1329 
   1330     width = jas_image_cmptwidth(inimage, 0);
   1331     height = jas_image_cmptheight(inimage, 0);
   1332     hstep = jas_image_cmpthstep(inimage, 0);
   1333     vstep = jas_image_cmptvstep(inimage, 0);
   1334 
   1335     inprof = jas_image_cmprof(inimage);
   1336     assert(inprof);
   1337     numinclrchans = jas_clrspc_numchans(jas_cmprof_clrspc(inprof));
   1338     numinauxchans = jas_image_numcmpts(inimage) - numinclrchans;
   1339     numoutclrchans = jas_clrspc_numchans(jas_cmprof_clrspc(outprof));
   1340     numoutauxchans = 0;
   1341     numoutchans = numoutclrchans + numoutauxchans;
   1342     prec = 8;
   1343 
   1344     if (!(outimage = jas_image_create0()))
   1345         goto error;
   1346 
   1347     /* Create a component for each of the colorants. */
   1348     for (i = 0; i < numoutclrchans; ++i) {
   1349         cmptparm.tlx = 0;
   1350         cmptparm.tly = 0;
   1351         cmptparm.hstep = hstep;
   1352         cmptparm.vstep = vstep;
   1353         cmptparm.width = width;
   1354         cmptparm.height = height;
   1355         cmptparm.prec = prec;
   1356         cmptparm.sgnd = 0;
   1357         if (jas_image_addcmpt(outimage, -1, &cmptparm))
   1358             goto error;
   1359         jas_image_setcmpttype(outimage, i, JAS_IMAGE_CT_COLOR(i));
   1360     }
   1361 #if 0
   1362     /* Copy the auxiliary components without modification. */
   1363     for (i = 0; i < jas_image_numcmpts(inimage); ++i) {
   1364         if (!ISCOLOR(jas_image_cmpttype(inimage, i))) {
   1365             jas_image_copycmpt(outimage, -1, inimage, i);
   1366 /* XXX - need to specify laydown of component on ref. grid */
   1367         }
   1368     }
   1369 #endif
   1370 
   1371     if (!(tmpprof = jas_cmprof_copy(outprof)))
   1372         goto error;
   1373     assert(!jas_image_cmprof(outimage));
   1374     jas_image_setcmprof(outimage, tmpprof);
   1375     tmpprof = 0;
   1376     jas_image_setclrspc(outimage, jas_cmprof_clrspc(outprof));
   1377 
   1378     if (!(xform = jas_cmxform_create(inprof, outprof, 0, JAS_CMXFORM_OP_FWD, intent, 0)))
   1379         goto error;
   1380 
   1381     inpixmap.numcmpts = numinclrchans;
   1382     incmptfmts = malloc(numinclrchans * sizeof(jas_cmcmptfmt_t));
   1383     assert(incmptfmts);
   1384     inpixmap.cmptfmts = incmptfmts;
   1385     for (i = 0; i < numinclrchans; ++i) {
   1386         j = jas_image_getcmptbytype(inimage, JAS_IMAGE_CT_COLOR(i));
   1387         assert(j >= 0);
   1388         if (!(incmptfmts[i].buf = malloc(width * sizeof(long))))
   1389             goto error;
   1390         incmptfmts[i].prec = jas_image_cmptprec(inimage, j);
   1391         incmptfmts[i].sgnd = jas_image_cmptsgnd(inimage, j);
   1392         incmptfmts[i].width = width;
   1393         incmptfmts[i].height = 1;
   1394     }
   1395 
   1396     outpixmap.numcmpts = numoutclrchans;
   1397     outcmptfmts = malloc(numoutclrchans * sizeof(jas_cmcmptfmt_t));
   1398     assert(outcmptfmts);
   1399     outpixmap.cmptfmts = outcmptfmts;
   1400 
   1401     for (i = 0; i < numoutclrchans; ++i) {
   1402         j = jas_image_getcmptbytype(outimage, JAS_IMAGE_CT_COLOR(i));
   1403         assert(j >= 0);
   1404         if (!(outcmptfmts[i].buf = malloc(width * sizeof(long))))
   1405             goto error;
   1406         outcmptfmts[i].prec = jas_image_cmptprec(outimage, j);
   1407         outcmptfmts[i].sgnd = jas_image_cmptsgnd(outimage, j);
   1408         outcmptfmts[i].width = width;
   1409         outcmptfmts[i].height = 1;
   1410     }
   1411 
   1412     for (i = 0; i < height; ++i) {
   1413         for (j = 0; j < numinclrchans; ++j) {
   1414             k = jas_image_getcmptbytype(inimage, JAS_IMAGE_CT_COLOR(j));
   1415             if (jas_image_readcmpt2(inimage, k, 0, i, width, 1, incmptfmts[j].buf))
   1416                 goto error;
   1417         }
   1418         jas_cmxform_apply(xform, &inpixmap, &outpixmap);
   1419         for (j = 0; j < numoutclrchans; ++j) {
   1420             k = jas_image_getcmptbytype(outimage, JAS_IMAGE_CT_COLOR(j));
   1421             if (jas_image_writecmpt2(outimage, k, 0, i, width, 1, outcmptfmts[j].buf))
   1422                 goto error;
   1423         }
   1424     }
   1425 
   1426     for (i = 0; i < numoutclrchans; ++i)
   1427         jas_free(outcmptfmts[i].buf);
   1428     jas_free(outcmptfmts);
   1429     for (i = 0; i < numinclrchans; ++i)
   1430         jas_free(incmptfmts[i].buf);
   1431     jas_free(incmptfmts);
   1432     jas_cmxform_destroy(xform);
   1433     jas_image_destroy(inimage);
   1434 
   1435 #if 0
   1436 jas_eprintf("INIMAGE\n");
   1437 jas_image_dump(inimage, stderr);
   1438 jas_eprintf("OUTIMAGE\n");
   1439 jas_image_dump(outimage, stderr);
   1440 #endif
   1441     return outimage;
   1442 error:
   1443     return 0;
   1444 }
   1445