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