1 /* 2 * Copyright (c) 2007, 2016, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 /********************************************************************** 27 ********************************************************************** 28 ********************************************************************** 29 *** COPYRIGHT (c) Eastman Kodak Company, 1997 *** 30 *** As an unpublished work pursuant to Title 17 of the United *** 31 *** States Code. All rights reserved. *** 32 ********************************************************************** 33 ********************************************************************** 34 **********************************************************************/ 35 36 package sun.java2d.cmm.lcms; 37 38 import java.awt.color.ICC_Profile; 39 import java.awt.color.CMMException; 40 import java.awt.color.ColorSpace; 41 import java.awt.image.BufferedImage; 42 import java.awt.image.Raster; 43 import java.awt.image.WritableRaster; 44 import java.awt.image.ColorModel; 45 import java.awt.image.SampleModel; 46 import java.awt.image.DataBuffer; 47 import sun.java2d.cmm.*; 48 import sun.java2d.cmm.lcms.*; 49 import static sun.java2d.cmm.lcms.LCMSImageLayout.ImageLayoutException; 50 51 52 public class LCMSTransform implements ColorTransform { 53 long ID; 54 private int inFormatter = 0; 55 private boolean isInIntPacked = false; 56 private int outFormatter = 0; 57 private boolean isOutIntPacked = false; 58 59 ICC_Profile[] profiles; 60 LCMSProfile[] lcmsProfiles; 61 int renderType; 62 int transformType; 63 64 private int numInComponents = -1; 65 private int numOutComponents = -1; 66 67 private Object disposerReferent = new Object(); 68 69 /* the class initializer */ 70 static { 71 if (ProfileDeferralMgr.deferring) { ProfileDeferralMgr.activateProfiles()72 ProfileDeferralMgr.activateProfiles(); 73 } 74 } 75 LCMSTransform(ICC_Profile profile, int renderType, int transformType)76 public LCMSTransform(ICC_Profile profile, int renderType, 77 int transformType) 78 { 79 /* Actually, it is not a complete transform but just part of it */ 80 profiles = new ICC_Profile[1]; 81 profiles[0] = profile; 82 lcmsProfiles = new LCMSProfile[1]; 83 lcmsProfiles[0] = LCMS.getProfileID(profile); 84 this.renderType = (renderType == ColorTransform.Any)? 85 ICC_Profile.icPerceptual : renderType; 86 this.transformType = transformType; 87 88 /* Note that ICC_Profile.getNumComponents() is quite expensive 89 * (it may results in a reading of the profile header). 90 * So, here we cache the number of components of input and 91 * output profiles for further usage. 92 */ 93 numInComponents = profiles[0].getNumComponents(); 94 numOutComponents = profiles[profiles.length - 1].getNumComponents(); 95 } 96 LCMSTransform(ColorTransform[] transforms)97 public LCMSTransform (ColorTransform[] transforms) { 98 int size = 0; 99 for (int i=0; i < transforms.length; i++) { 100 size+=((LCMSTransform)transforms[i]).profiles.length; 101 } 102 profiles = new ICC_Profile[size]; 103 lcmsProfiles = new LCMSProfile[size]; 104 int j = 0; 105 for (int i=0; i < transforms.length; i++) { 106 LCMSTransform curTrans = (LCMSTransform)transforms[i]; 107 System.arraycopy(curTrans.profiles, 0, profiles, j, 108 curTrans.profiles.length); 109 System.arraycopy(curTrans.lcmsProfiles, 0, lcmsProfiles, j, 110 curTrans.lcmsProfiles.length); 111 j += curTrans.profiles.length; 112 } 113 renderType = ((LCMSTransform)transforms[0]).renderType; 114 115 /* Note that ICC_Profile.getNumComponents() is quite expensive 116 * (it may results in a reading of the profile header). 117 * So, here we cache the number of components of input and 118 * output profiles for further usage. 119 */ 120 numInComponents = profiles[0].getNumComponents(); 121 numOutComponents = profiles[profiles.length - 1].getNumComponents(); 122 } 123 getNumInComponents()124 public int getNumInComponents() { 125 return numInComponents; 126 } 127 getNumOutComponents()128 public int getNumOutComponents() { 129 return numOutComponents; 130 } 131 doTransform(LCMSImageLayout in, LCMSImageLayout out)132 private synchronized void doTransform(LCMSImageLayout in, 133 LCMSImageLayout out) { 134 // update native transfrom if needed 135 if (ID == 0L || 136 inFormatter != in.pixelType || isInIntPacked != in.isIntPacked || 137 outFormatter != out.pixelType || isOutIntPacked != out.isIntPacked) 138 { 139 140 if (ID != 0L) { 141 // Disposer will destroy forgotten transform 142 disposerReferent = new Object(); 143 } 144 inFormatter = in.pixelType; 145 isInIntPacked = in.isIntPacked; 146 147 outFormatter = out.pixelType; 148 isOutIntPacked = out.isIntPacked; 149 150 ID = LCMS.createTransform(lcmsProfiles, renderType, 151 inFormatter, isInIntPacked, 152 outFormatter, isOutIntPacked, 153 disposerReferent); 154 } 155 156 LCMS.colorConvert(this, in, out); 157 } 158 colorConvert(BufferedImage src, BufferedImage dst)159 public void colorConvert(BufferedImage src, BufferedImage dst) { 160 LCMSImageLayout srcIL, dstIL; 161 try { 162 if (!dst.getColorModel().hasAlpha()) { 163 dstIL = LCMSImageLayout.createImageLayout(dst); 164 165 if (dstIL != null) { 166 srcIL = LCMSImageLayout.createImageLayout(src); 167 if (srcIL != null) { 168 doTransform(srcIL, dstIL); 169 return; 170 } 171 } 172 } 173 } catch (ImageLayoutException e) { 174 throw new CMMException("Unable to convert images"); 175 } 176 177 Raster srcRas = src.getRaster(); 178 WritableRaster dstRas = dst.getRaster(); 179 ColorModel srcCM = src.getColorModel(); 180 ColorModel dstCM = dst.getColorModel(); 181 int w = src.getWidth(); 182 int h = src.getHeight(); 183 int srcNumComp = srcCM.getNumColorComponents(); 184 int dstNumComp = dstCM.getNumColorComponents(); 185 int precision = 8; 186 float maxNum = 255.0f; 187 for (int i = 0; i < srcNumComp; i++) { 188 if (srcCM.getComponentSize(i) > 8) { 189 precision = 16; 190 maxNum = 65535.0f; 191 } 192 } 193 for (int i = 0; i < dstNumComp; i++) { 194 if (dstCM.getComponentSize(i) > 8) { 195 precision = 16; 196 maxNum = 65535.0f; 197 } 198 } 199 float[] srcMinVal = new float[srcNumComp]; 200 float[] srcInvDiffMinMax = new float[srcNumComp]; 201 ColorSpace cs = srcCM.getColorSpace(); 202 for (int i = 0; i < srcNumComp; i++) { 203 srcMinVal[i] = cs.getMinValue(i); 204 srcInvDiffMinMax[i] = maxNum / (cs.getMaxValue(i) - srcMinVal[i]); 205 } 206 cs = dstCM.getColorSpace(); 207 float[] dstMinVal = new float[dstNumComp]; 208 float[] dstDiffMinMax = new float[dstNumComp]; 209 for (int i = 0; i < dstNumComp; i++) { 210 dstMinVal[i] = cs.getMinValue(i); 211 dstDiffMinMax[i] = (cs.getMaxValue(i) - dstMinVal[i]) / maxNum; 212 } 213 boolean dstHasAlpha = dstCM.hasAlpha(); 214 boolean needSrcAlpha = srcCM.hasAlpha() && dstHasAlpha; 215 float[] dstColor; 216 if (dstHasAlpha) { 217 dstColor = new float[dstNumComp + 1]; 218 } else { 219 dstColor = new float[dstNumComp]; 220 } 221 if (precision == 8) { 222 byte[] srcLine = new byte[w * srcNumComp]; 223 byte[] dstLine = new byte[w * dstNumComp]; 224 Object pixel; 225 float[] color; 226 float[] alpha = null; 227 if (needSrcAlpha) { 228 alpha = new float[w]; 229 } 230 int idx; 231 // TODO check for src npixels = dst npixels 232 try { 233 srcIL = new LCMSImageLayout( 234 srcLine, srcLine.length/getNumInComponents(), 235 LCMSImageLayout.CHANNELS_SH(getNumInComponents()) | 236 LCMSImageLayout.BYTES_SH(1), getNumInComponents()); 237 dstIL = new LCMSImageLayout( 238 dstLine, dstLine.length/getNumOutComponents(), 239 LCMSImageLayout.CHANNELS_SH(getNumOutComponents()) | 240 LCMSImageLayout.BYTES_SH(1), getNumOutComponents()); 241 } catch (ImageLayoutException e) { 242 throw new CMMException("Unable to convert images"); 243 } 244 // process each scanline 245 for (int y = 0; y < h; y++) { 246 // convert src scanline 247 pixel = null; 248 color = null; 249 idx = 0; 250 for (int x = 0; x < w; x++) { 251 pixel = srcRas.getDataElements(x, y, pixel); 252 color = srcCM.getNormalizedComponents(pixel, color, 0); 253 for (int i = 0; i < srcNumComp; i++) { 254 srcLine[idx++] = (byte) 255 ((color[i] - srcMinVal[i]) * srcInvDiffMinMax[i] + 256 0.5f); 257 } 258 if (needSrcAlpha) { 259 alpha[x] = color[srcNumComp]; 260 } 261 } 262 // color convert srcLine to dstLine 263 doTransform(srcIL, dstIL); 264 265 // convert dst scanline 266 pixel = null; 267 idx = 0; 268 for (int x = 0; x < w; x++) { 269 for (int i = 0; i < dstNumComp; i++) { 270 dstColor[i] = ((float) (dstLine[idx++] & 0xff)) * 271 dstDiffMinMax[i] + dstMinVal[i]; 272 } 273 if (needSrcAlpha) { 274 dstColor[dstNumComp] = alpha[x]; 275 } else if (dstHasAlpha) { 276 dstColor[dstNumComp] = 1.0f; 277 } 278 pixel = dstCM.getDataElements(dstColor, 0, pixel); 279 dstRas.setDataElements(x, y, pixel); 280 } 281 } 282 } else { 283 short[] srcLine = new short[w * srcNumComp]; 284 short[] dstLine = new short[w * dstNumComp]; 285 Object pixel; 286 float[] color; 287 float[] alpha = null; 288 if (needSrcAlpha) { 289 alpha = new float[w]; 290 } 291 int idx; 292 try { 293 srcIL = new LCMSImageLayout( 294 srcLine, srcLine.length/getNumInComponents(), 295 LCMSImageLayout.CHANNELS_SH(getNumInComponents()) | 296 LCMSImageLayout.BYTES_SH(2), getNumInComponents()*2); 297 298 dstIL = new LCMSImageLayout( 299 dstLine, dstLine.length/getNumOutComponents(), 300 LCMSImageLayout.CHANNELS_SH(getNumOutComponents()) | 301 LCMSImageLayout.BYTES_SH(2), getNumOutComponents()*2); 302 } catch (ImageLayoutException e) { 303 throw new CMMException("Unable to convert images"); 304 } 305 // process each scanline 306 for (int y = 0; y < h; y++) { 307 // convert src scanline 308 pixel = null; 309 color = null; 310 idx = 0; 311 for (int x = 0; x < w; x++) { 312 pixel = srcRas.getDataElements(x, y, pixel); 313 color = srcCM.getNormalizedComponents(pixel, color, 0); 314 for (int i = 0; i < srcNumComp; i++) { 315 srcLine[idx++] = (short) 316 ((color[i] - srcMinVal[i]) * srcInvDiffMinMax[i] + 317 0.5f); 318 } 319 if (needSrcAlpha) { 320 alpha[x] = color[srcNumComp]; 321 } 322 } 323 // color convert srcLine to dstLine 324 doTransform(srcIL, dstIL); 325 326 // convert dst scanline 327 pixel = null; 328 idx = 0; 329 for (int x = 0; x < w; x++) { 330 for (int i = 0; i < dstNumComp; i++) { 331 dstColor[i] = ((float) (dstLine[idx++] & 0xffff)) * 332 dstDiffMinMax[i] + dstMinVal[i]; 333 } 334 if (needSrcAlpha) { 335 dstColor[dstNumComp] = alpha[x]; 336 } else if (dstHasAlpha) { 337 dstColor[dstNumComp] = 1.0f; 338 } 339 pixel = dstCM.getDataElements(dstColor, 0, pixel); 340 dstRas.setDataElements(x, y, pixel); 341 } 342 } 343 } 344 } 345 colorConvert(Raster src, WritableRaster dst, float[] srcMinVal, float[]srcMaxVal, float[] dstMinVal, float[]dstMaxVal)346 public void colorConvert(Raster src, WritableRaster dst, 347 float[] srcMinVal, float[]srcMaxVal, 348 float[] dstMinVal, float[]dstMaxVal) { 349 LCMSImageLayout srcIL, dstIL; 350 351 // Can't pass src and dst directly to CMM, so process per scanline 352 SampleModel srcSM = src.getSampleModel(); 353 SampleModel dstSM = dst.getSampleModel(); 354 int srcTransferType = src.getTransferType(); 355 int dstTransferType = dst.getTransferType(); 356 boolean srcIsFloat, dstIsFloat; 357 if ((srcTransferType == DataBuffer.TYPE_FLOAT) || 358 (srcTransferType == DataBuffer.TYPE_DOUBLE)) { 359 srcIsFloat = true; 360 } else { 361 srcIsFloat = false; 362 } 363 if ((dstTransferType == DataBuffer.TYPE_FLOAT) || 364 (dstTransferType == DataBuffer.TYPE_DOUBLE)) { 365 dstIsFloat = true; 366 } else { 367 dstIsFloat = false; 368 } 369 int w = src.getWidth(); 370 int h = src.getHeight(); 371 int srcNumBands = src.getNumBands(); 372 int dstNumBands = dst.getNumBands(); 373 float[] srcScaleFactor = new float[srcNumBands]; 374 float[] dstScaleFactor = new float[dstNumBands]; 375 float[] srcUseMinVal = new float[srcNumBands]; 376 float[] dstUseMinVal = new float[dstNumBands]; 377 for (int i = 0; i < srcNumBands; i++) { 378 if (srcIsFloat) { 379 srcScaleFactor[i] = 65535.0f / (srcMaxVal[i] - srcMinVal[i]); 380 srcUseMinVal[i] = srcMinVal[i]; 381 } else { 382 if (srcTransferType == DataBuffer.TYPE_SHORT) { 383 srcScaleFactor[i] = 65535.0f / 32767.0f; 384 } else { 385 srcScaleFactor[i] = 65535.0f / 386 ((float) ((1 << srcSM.getSampleSize(i)) - 1)); 387 } 388 srcUseMinVal[i] = 0.0f; 389 } 390 } 391 for (int i = 0; i < dstNumBands; i++) { 392 if (dstIsFloat) { 393 dstScaleFactor[i] = (dstMaxVal[i] - dstMinVal[i]) / 65535.0f; 394 dstUseMinVal[i] = dstMinVal[i]; 395 } else { 396 if (dstTransferType == DataBuffer.TYPE_SHORT) { 397 dstScaleFactor[i] = 32767.0f / 65535.0f; 398 } else { 399 dstScaleFactor[i] = 400 ((float) ((1 << dstSM.getSampleSize(i)) - 1)) / 401 65535.0f; 402 } 403 dstUseMinVal[i] = 0.0f; 404 } 405 } 406 int ys = src.getMinY(); 407 int yd = dst.getMinY(); 408 int xs, xd; 409 float sample; 410 short[] srcLine = new short[w * srcNumBands]; 411 short[] dstLine = new short[w * dstNumBands]; 412 int idx; 413 try { 414 srcIL = new LCMSImageLayout( 415 srcLine, srcLine.length/getNumInComponents(), 416 LCMSImageLayout.CHANNELS_SH(getNumInComponents()) | 417 LCMSImageLayout.BYTES_SH(2), getNumInComponents()*2); 418 419 dstIL = new LCMSImageLayout( 420 dstLine, dstLine.length/getNumOutComponents(), 421 LCMSImageLayout.CHANNELS_SH(getNumOutComponents()) | 422 LCMSImageLayout.BYTES_SH(2), getNumOutComponents()*2); 423 } catch (ImageLayoutException e) { 424 throw new CMMException("Unable to convert rasters"); 425 } 426 // process each scanline 427 for (int y = 0; y < h; y++, ys++, yd++) { 428 // get src scanline 429 xs = src.getMinX(); 430 idx = 0; 431 for (int x = 0; x < w; x++, xs++) { 432 for (int i = 0; i < srcNumBands; i++) { 433 sample = src.getSampleFloat(xs, ys, i); 434 srcLine[idx++] = (short) 435 ((sample - srcUseMinVal[i]) * srcScaleFactor[i] + 0.5f); 436 } 437 } 438 439 // color convert srcLine to dstLine 440 doTransform(srcIL, dstIL); 441 442 // store dst scanline 443 xd = dst.getMinX(); 444 idx = 0; 445 for (int x = 0; x < w; x++, xd++) { 446 for (int i = 0; i < dstNumBands; i++) { 447 sample = ((dstLine[idx++] & 0xffff) * dstScaleFactor[i]) + 448 dstUseMinVal[i]; 449 dst.setSample(xd, yd, i, sample); 450 } 451 } 452 } 453 } 454 colorConvert(Raster src, WritableRaster dst)455 public void colorConvert(Raster src, WritableRaster dst) { 456 457 LCMSImageLayout srcIL, dstIL; 458 dstIL = LCMSImageLayout.createImageLayout(dst); 459 if (dstIL != null) { 460 srcIL = LCMSImageLayout.createImageLayout(src); 461 if (srcIL != null) { 462 doTransform(srcIL, dstIL); 463 return; 464 } 465 } 466 // Can't pass src and dst directly to CMM, so process per scanline 467 SampleModel srcSM = src.getSampleModel(); 468 SampleModel dstSM = dst.getSampleModel(); 469 int srcTransferType = src.getTransferType(); 470 int dstTransferType = dst.getTransferType(); 471 int w = src.getWidth(); 472 int h = src.getHeight(); 473 int srcNumBands = src.getNumBands(); 474 int dstNumBands = dst.getNumBands(); 475 int precision = 8; 476 float maxNum = 255.0f; 477 for (int i = 0; i < srcNumBands; i++) { 478 if (srcSM.getSampleSize(i) > 8) { 479 precision = 16; 480 maxNum = 65535.0f; 481 } 482 } 483 for (int i = 0; i < dstNumBands; i++) { 484 if (dstSM.getSampleSize(i) > 8) { 485 precision = 16; 486 maxNum = 65535.0f; 487 } 488 } 489 float[] srcScaleFactor = new float[srcNumBands]; 490 float[] dstScaleFactor = new float[dstNumBands]; 491 for (int i = 0; i < srcNumBands; i++) { 492 if (srcTransferType == DataBuffer.TYPE_SHORT) { 493 srcScaleFactor[i] = maxNum / 32767.0f; 494 } else { 495 srcScaleFactor[i] = maxNum / 496 ((float) ((1 << srcSM.getSampleSize(i)) - 1)); 497 } 498 } 499 for (int i = 0; i < dstNumBands; i++) { 500 if (dstTransferType == DataBuffer.TYPE_SHORT) { 501 dstScaleFactor[i] = 32767.0f / maxNum; 502 } else { 503 dstScaleFactor[i] = 504 ((float) ((1 << dstSM.getSampleSize(i)) - 1)) / maxNum; 505 } 506 } 507 int ys = src.getMinY(); 508 int yd = dst.getMinY(); 509 int xs, xd; 510 int sample; 511 if (precision == 8) { 512 byte[] srcLine = new byte[w * srcNumBands]; 513 byte[] dstLine = new byte[w * dstNumBands]; 514 int idx; 515 // TODO check for src npixels = dst npixels 516 try { 517 srcIL = new LCMSImageLayout( 518 srcLine, srcLine.length/getNumInComponents(), 519 LCMSImageLayout.CHANNELS_SH(getNumInComponents()) | 520 LCMSImageLayout.BYTES_SH(1), getNumInComponents()); 521 dstIL = new LCMSImageLayout( 522 dstLine, dstLine.length/getNumOutComponents(), 523 LCMSImageLayout.CHANNELS_SH(getNumOutComponents()) | 524 LCMSImageLayout.BYTES_SH(1), getNumOutComponents()); 525 } catch (ImageLayoutException e) { 526 throw new CMMException("Unable to convert rasters"); 527 } 528 // process each scanline 529 for (int y = 0; y < h; y++, ys++, yd++) { 530 // get src scanline 531 xs = src.getMinX(); 532 idx = 0; 533 for (int x = 0; x < w; x++, xs++) { 534 for (int i = 0; i < srcNumBands; i++) { 535 sample = src.getSample(xs, ys, i); 536 srcLine[idx++] = (byte) 537 ((sample * srcScaleFactor[i]) + 0.5f); 538 } 539 } 540 541 // color convert srcLine to dstLine 542 doTransform(srcIL, dstIL); 543 544 // store dst scanline 545 xd = dst.getMinX(); 546 idx = 0; 547 for (int x = 0; x < w; x++, xd++) { 548 for (int i = 0; i < dstNumBands; i++) { 549 sample = (int) (((dstLine[idx++] & 0xff) * 550 dstScaleFactor[i]) + 0.5f); 551 dst.setSample(xd, yd, i, sample); 552 } 553 } 554 } 555 } else { 556 short[] srcLine = new short[w * srcNumBands]; 557 short[] dstLine = new short[w * dstNumBands]; 558 int idx; 559 560 try { 561 srcIL = new LCMSImageLayout( 562 srcLine, srcLine.length/getNumInComponents(), 563 LCMSImageLayout.CHANNELS_SH(getNumInComponents()) | 564 LCMSImageLayout.BYTES_SH(2), getNumInComponents()*2); 565 566 dstIL = new LCMSImageLayout( 567 dstLine, dstLine.length/getNumOutComponents(), 568 LCMSImageLayout.CHANNELS_SH(getNumOutComponents()) | 569 LCMSImageLayout.BYTES_SH(2), getNumOutComponents()*2); 570 } catch (ImageLayoutException e) { 571 throw new CMMException("Unable to convert rasters"); 572 } 573 // process each scanline 574 for (int y = 0; y < h; y++, ys++, yd++) { 575 // get src scanline 576 xs = src.getMinX(); 577 idx = 0; 578 for (int x = 0; x < w; x++, xs++) { 579 for (int i = 0; i < srcNumBands; i++) { 580 sample = src.getSample(xs, ys, i); 581 srcLine[idx++] = (short) 582 ((sample * srcScaleFactor[i]) + 0.5f); 583 } 584 } 585 586 // color convert srcLine to dstLine 587 doTransform(srcIL, dstIL); 588 589 // store dst scanline 590 xd = dst.getMinX(); 591 idx = 0; 592 for (int x = 0; x < w; x++, xd++) { 593 for (int i = 0; i < dstNumBands; i++) { 594 sample = (int) (((dstLine[idx++] & 0xffff) * 595 dstScaleFactor[i]) + 0.5f); 596 dst.setSample(xd, yd, i, sample); 597 } 598 } 599 } 600 } 601 } 602 603 /* convert an array of colors in short format */ 604 /* each color is a contiguous set of array elements */ 605 /* the number of colors is (size of the array) / (number of input/output 606 components */ colorConvert(short[] src, short[] dst)607 public short[] colorConvert(short[] src, short[] dst) { 608 609 if (dst == null) { 610 dst = new short [(src.length/getNumInComponents())*getNumOutComponents()]; 611 } 612 613 try { 614 LCMSImageLayout srcIL = new LCMSImageLayout( 615 src, src.length/getNumInComponents(), 616 LCMSImageLayout.CHANNELS_SH(getNumInComponents()) | 617 LCMSImageLayout.BYTES_SH(2), getNumInComponents()*2); 618 619 LCMSImageLayout dstIL = new LCMSImageLayout( 620 dst, dst.length/getNumOutComponents(), 621 LCMSImageLayout.CHANNELS_SH(getNumOutComponents()) | 622 LCMSImageLayout.BYTES_SH(2), getNumOutComponents()*2); 623 624 doTransform(srcIL, dstIL); 625 626 return dst; 627 } catch (ImageLayoutException e) { 628 throw new CMMException("Unable to convert data"); 629 } 630 } 631 colorConvert(byte[] src, byte[] dst)632 public byte[] colorConvert(byte[] src, byte[] dst) { 633 if (dst == null) { 634 dst = new byte [(src.length/getNumInComponents())*getNumOutComponents()]; 635 } 636 637 try { 638 LCMSImageLayout srcIL = new LCMSImageLayout( 639 src, src.length/getNumInComponents(), 640 LCMSImageLayout.CHANNELS_SH(getNumInComponents()) | 641 LCMSImageLayout.BYTES_SH(1), getNumInComponents()); 642 643 LCMSImageLayout dstIL = new LCMSImageLayout( 644 dst, dst.length/getNumOutComponents(), 645 LCMSImageLayout.CHANNELS_SH(getNumOutComponents()) | 646 LCMSImageLayout.BYTES_SH(1), getNumOutComponents()); 647 648 doTransform(srcIL, dstIL); 649 650 return dst; 651 } catch (ImageLayoutException e) { 652 throw new CMMException("Unable to convert data"); 653 } 654 } 655 } 656