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 }