1 /* 2 * Copyright (c) 2009, 2014, 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 package com.sun.javafx.iio.common; 27 28 import com.sun.javafx.geom.Point2D; 29 import com.sun.javafx.geom.Rectangle; 30 import com.sun.javafx.iio.ImageFrame; 31 import com.sun.javafx.iio.ImageMetadata; 32 import com.sun.javafx.iio.ImageStorage.ImageType; 33 import java.io.EOFException; 34 import java.io.File; 35 import java.io.FileInputStream; 36 import java.io.IOException; 37 import java.io.InputStream; 38 import java.net.URL; 39 import java.nio.Buffer; 40 import java.nio.ByteBuffer; 41 42 /** 43 * A set of format-independent convenience methods useful in image loading 44 * and saving. 45 */ 46 public class ImageTools { 47 48 /** 49 * The percentage increment between progress report updates. 50 */ 51 public static final int PROGRESS_INTERVAL = 5; 52 53 /** 54 * See the general contract of the <code>readFully</code> 55 * method of <code>DataInput</code>. 56 * <p> 57 * Bytes 58 * for this operation are read from the specified 59 * input stream. 60 * 61 * @param stream the stream from which to read the data. 62 * @param b the buffer into which the data is read. 63 * @param off the start offset of the data. 64 * @param len the number of bytes to read. 65 * @exception EOFException if this input stream reaches the end before 66 * reading all the bytes. 67 * @exception IOException if another I/O error occurs. 68 */ 69 public static int readFully(InputStream stream, 70 byte[] b, int off, int len) throws IOException { 71 if (len < 0) { 72 throw new IndexOutOfBoundsException(); 73 } 74 int requestedLength = len; 75 // Fix 4430357 - if off + len < 0, overflow occurred 76 if (off < 0 || len < 0 || off + len > b.length || off + len < 0) { 77 throw new IndexOutOfBoundsException("off < 0 || len < 0 || off + len > b.length!"); 78 } 79 80 while (len > 0) { 81 int nbytes = stream.read(b, off, len); 82 if (nbytes == -1) { 83 throw new EOFException(); 84 } 85 off += nbytes; 86 len -= nbytes; 87 } 88 89 return requestedLength; 90 } 91 92 /** 93 * See the general contract of the <code>readFully</code> 94 * method of <code>DataInput</code>. 95 * <p> 96 * Bytes 97 * for this operation are read from the contained 98 * input stream. 99 * 100 * @param stream the stream from which to read the data. 101 * @param b the buffer into which the data is read. 102 * @exception EOFException if this input stream reaches the end before 103 * reading all the bytes. 104 * @exception IOException if another I/O error occurs. 105 */ 106 public static int readFully(InputStream stream, byte[] b) throws IOException { 107 return readFully(stream, b, 0, b.length); 108 } 109 110 /** 111 * Skips over <code>n</code> bytes of data from the input stream. 112 * @param stream the stream to skip. 113 * @param n the number of bytes to be skipped. 114 * @exception EOFException if this input stream reaches the end before 115 * skipping all the bytes. 116 * @exception IOException if another I/O error occurs. 117 */ 118 public static void skipFully(InputStream stream, long n) throws IOException { 119 while (n > 0) { 120 long skipped = stream.skip(n); 121 if (skipped <= 0) { 122 // check if the EOF is reached 123 if (stream.read() == -1) { 124 throw new EOFException(); 125 } 126 n--; 127 } else { 128 n -= skipped; 129 } 130 } 131 } 132 // public static PixelFormat getPixelFormat(ImageType type) { 133 // PixelFormat format; 134 // switch (type) { 135 // case GRAY: 136 // format = PixelFormat.BYTE_GRAY; 137 // break; 138 // case GRAY_ALPHA: 139 // case GRAY_ALPHA_PRE: 140 // format = PixelFormat.BYTE_RGBA_PRE; 141 // break; 142 // case PALETTE: 143 // format = PixelFormat.BYTE_RGB; 144 // break; 145 // case PALETTE_ALPHA: 146 // case PALETTE_ALPHA_PRE: 147 // format = PixelFormat.BYTE_RGBA_PRE; 148 // break; 149 // case RGB: 150 // format = PixelFormat.BYTE_RGB; 151 // break; 152 // case RGBA: 153 // case RGBA_PRE: 154 // format = PixelFormat.BYTE_RGBA_PRE; 155 // break; 156 // default: 157 // // This should not be possible ... 158 // throw new IllegalArgumentException("Unknown ImageType " + type); 159 // } 160 // 161 // return format; 162 // } 163 // public static boolean isConversionACopy(ImageType type, PixelFormat format) { 164 // return (type == ImageType.GRAY && format == PixelFormat.BYTE_GRAY) || 165 // (type == ImageType.RGB && format == PixelFormat.BYTE_RGB) || 166 // (type == ImageType.RGBA_PRE && format == PixelFormat.BYTE_RGBA_PRE); 167 // } 168 public static ImageType getConvertedType(ImageType type) { 169 ImageType retType = type; 170 switch (type) { 171 case GRAY: 172 retType = ImageType.GRAY; 173 break; 174 case GRAY_ALPHA: 175 case GRAY_ALPHA_PRE: 176 case PALETTE_ALPHA: 177 case PALETTE_ALPHA_PRE: 178 case PALETTE_TRANS: 179 case RGBA: 180 retType = ImageType.RGBA_PRE; 181 break; 182 case PALETTE: 183 case RGB: 184 retType = ImageType.RGB; 185 break; 186 case RGBA_PRE: 187 retType = ImageType.RGBA_PRE; 188 break; 189 default: 190 throw new IllegalArgumentException("Unsupported ImageType " + type); 191 } 192 return retType; 193 } 194 195 public static byte[] createImageArray(ImageType type, int width, int height) { 196 int numBands = 0; 197 switch (type) { 198 case GRAY: 199 case PALETTE: 200 case PALETTE_ALPHA: 201 case PALETTE_ALPHA_PRE: 202 numBands = 1; 203 break; 204 case GRAY_ALPHA: 205 case GRAY_ALPHA_PRE: 206 numBands = 2; 207 break; 208 case RGB: 209 numBands = 3; 210 break; 211 case RGBA: 212 case RGBA_PRE: 213 numBands = 4; 214 break; 215 default: 216 throw new IllegalArgumentException("Unsupported ImageType " + type); 217 } 218 return new byte[width * height * numBands]; 219 } 220 221 public static ImageFrame convertImageFrame(ImageFrame frame) { 222 ImageFrame retFrame; 223 ImageType type = frame.getImageType(); 224 ImageType convertedType = getConvertedType(type); 225 if (convertedType == type) { 226 retFrame = frame; 227 } else { 228 byte[] inArray = null; 229 Buffer buf = frame.getImageData(); 230 if (!(buf instanceof ByteBuffer)) { 231 throw new IllegalArgumentException("!(frame.getImageData() instanceof ByteBuffer)"); 232 } 233 ByteBuffer bbuf = (ByteBuffer) buf; 234 if (bbuf.hasArray()) { 235 inArray = bbuf.array(); 236 } else { 237 inArray = new byte[bbuf.capacity()]; 238 bbuf.get(inArray); 239 } 240 int width = frame.getWidth(); 241 int height = frame.getHeight(); 242 int inStride = frame.getStride(); 243 byte[] outArray = createImageArray(convertedType, width, height); 244 ByteBuffer newBuf = ByteBuffer.wrap(outArray); 245 int outStride = outArray.length / height; 246 byte[][] palette = frame.getPalette(); 247 ImageMetadata metadata = frame.getMetadata(); 248 int transparentIndex = metadata.transparentIndex != null ? metadata.transparentIndex : 0; 249 convert(width, height, type, 250 inArray, 0, inStride, outArray, 0, outStride, 251 palette, transparentIndex, false); 252 ImageMetadata imd = new ImageMetadata(metadata.gamma, 253 metadata.blackIsZero, null, 254 metadata.backgroundColor, null, 255 metadata.delayTime, metadata.loopCount, 256 metadata.imageWidth, metadata.imageHeight, 257 metadata.imageLeftPosition, metadata.imageTopPosition, 258 metadata.disposalMethod); 259 retFrame = new ImageFrame(convertedType, newBuf, width, height, 260 outStride, null, imd); 261 } 262 return retFrame; 263 } 264 265 public static byte[] convert(int width, int height, ImageType inputType, 266 byte[] input, int inputOffset, int inRowStride, 267 byte[] output, int outputOffset, int outRowStride, 268 byte[][] palette, int transparentIndex, boolean skipTransparent) { 269 // 270 // Take care of the layouts that are a direct copy. 271 // 272 if (inputType == ImageType.GRAY || 273 inputType == ImageType.RGB || 274 inputType == ImageType.RGBA_PRE) { 275 if (input != output) { 276 int bytesPerRow = width; 277 if (inputType == ImageType.RGB) { 278 bytesPerRow *= 3; 279 } else if (inputType == ImageType.RGBA_PRE) { 280 bytesPerRow *= 4; 281 } 282 if (height == 1) { 283 System.arraycopy(input, inputOffset, output, outputOffset, bytesPerRow); 284 } else { 285 int inRowOffset = inputOffset; 286 int outRowOffset = outputOffset; 287 for (int row = 0; row < height; row++) { 288 System.arraycopy(input, inRowOffset, output, outRowOffset, bytesPerRow); 289 inRowOffset += inRowStride; 290 outRowOffset += outRowStride; 291 } 292 } 293 } 294 } else if (inputType == ImageType.GRAY_ALPHA || inputType == ImageType.GRAY_ALPHA_PRE) { 295 int inOffset = inputOffset; 296 int outOffset = outputOffset; 297 if (inputType == ImageType.GRAY_ALPHA) { 298 for (int y = 0; y < height; y++) { 299 int inOff = inOffset; 300 int outOff = outOffset; 301 for (int x = 0; x < width; x++) { 302 // copy input to local variables in case operating in place 303 byte gray = input[inOff++]; 304 int alpha = input[inOff++] & 0xff; 305 float f = alpha / 255.0F; 306 gray = (byte) (f * (gray & 0xff)); 307 output[outOff++] = gray; 308 output[outOff++] = gray; 309 output[outOff++] = gray; 310 output[outOff++] = (byte) alpha; 311 } 312 inOffset += inRowStride; 313 outOffset += outRowStride; 314 } 315 } else { 316 for (int y = 0; y < height; y++) { 317 int inOff = inOffset; 318 int outOff = outOffset; 319 for (int x = 0; x < width; x++) { 320 // copy input to local variables in case operating in place 321 byte gray = input[inOff++]; 322 output[outOff++] = gray; 323 output[outOff++] = gray; 324 output[outOff++] = gray; 325 output[outOff++] = input[inOff++]; 326 } 327 inOffset += inRowStride; 328 outOffset += outRowStride; 329 } 330 } 331 } else if (inputType == ImageType.PALETTE) { 332 int inOffset = inputOffset; 333 int outOffset = outputOffset; 334 byte[] red = palette[0]; 335 byte[] green = palette[1]; 336 byte[] blue = palette[2]; 337 int inOff = inOffset; 338 int outOff = outOffset; 339 //loop through the scanline and mask for the value if each byte. 340 //the byte is an index into the palette array for that pixel. 341 for (int x = 0; x < width; x++) { 342 int index = (input[inOff++] & 0xff); 343 344 output[outOff++] = red[index]; 345 output[outOff++] = green[index]; 346 output[outOff++] = blue[index]; 347 348 outOffset += outRowStride; 349 } 350 } else if (inputType == ImageType.PALETTE_ALPHA) { 351 int inOffset = inputOffset; 352 int outOffset = outputOffset; 353 byte[] red = palette[0]; 354 byte[] green = palette[1]; 355 byte[] blue = palette[2]; 356 byte[] alpha = palette[3]; 357 int inOff = inOffset; 358 int outOff = outOffset; 359 for (int x = 0; x < width; x++) { 360 int index = input[inOff++] & 0xff; 361 byte r = red[index]; 362 byte g = green[index]; 363 byte b = blue[index]; 364 int a = alpha[index] & 0xff; 365 float f = a / 255.0F; 366 output[outOff++] = (byte) (f * (r & 0xff)); 367 output[outOff++] = (byte) (f * (g & 0xff)); 368 output[outOff++] = (byte) (f * (b & 0xff)); 369 output[outOff++] = (byte) a; 370 } 371 inOffset += inRowStride; 372 outOffset += outRowStride; 373 } else if (inputType == ImageType.PALETTE_ALPHA_PRE) { 374 int inOffset = inputOffset; 375 int outOffset = outputOffset; 376 byte[] red = palette[0]; 377 byte[] green = palette[1]; 378 byte[] blue = palette[2]; 379 byte[] alpha = palette[3]; 380 for (int y = 0; y < height; y++) { 381 int inOff = inOffset; 382 int outOff = outOffset; 383 for (int x = 0; x < width; x++) { 384 int index = input[inOff++] & 0xff; 385 output[outOff++] = red[index]; 386 output[outOff++] = green[index]; 387 output[outOff++] = blue[index]; 388 output[outOff++] = alpha[index]; 389 } 390 inOffset += inRowStride; 391 outOffset += outRowStride; 392 } 393 } else if (inputType == ImageType.PALETTE_TRANS) { 394 int inOffset = inputOffset; 395 int outOffset = outputOffset; 396 for (int y = 0; y < height; y++) { 397 int inOff = inOffset; 398 int outOff = outOffset; 399 byte[] red = palette[0]; 400 byte[] green = palette[1]; 401 byte[] blue = palette[2]; 402 for (int x = 0; x < width; x++) { 403 int index = input[inOff++] & 0xff; 404 if (index == transparentIndex) { 405 if (skipTransparent) { 406 outOff+=4; 407 } else { 408 output[outOff++] = (byte) 0; 409 output[outOff++] = (byte) 0; 410 output[outOff++] = (byte) 0; 411 output[outOff++] = (byte) 0; 412 } 413 } else { 414 output[outOff++] = red[index]; 415 output[outOff++] = green[index]; 416 output[outOff++] = blue[index]; 417 output[outOff++] = (byte) 255; 418 } 419 } 420 inOffset += inRowStride; 421 outOffset += outRowStride; 422 } 423 } else if (inputType == ImageType.RGBA) { 424 int inOffset = inputOffset; 425 int outOffset = outputOffset; 426 for (int y = 0; y < height; y++) { 427 int inOff = inOffset; 428 int outOff = outOffset; 429 for (int x = 0; x < width; x++) { 430 // copy input to local variables in case operating in place 431 byte red = input[inOff++]; 432 byte green = input[inOff++]; 433 byte blue = input[inOff++]; 434 int alpha = input[inOff++] & 0xff; 435 float f = alpha / 255.0F; 436 output[outOff++] = (byte) (f * (red & 0xff)); 437 output[outOff++] = (byte) (f * (green & 0xff)); 438 output[outOff++] = (byte) (f * (blue & 0xff)); 439 output[outOff++] = (byte) alpha; 440 } 441 // System.arraycopy(input, inOffset, output, outOffset, width*4); 442 inOffset += inRowStride; 443 outOffset += outRowStride; 444 } 445 } else { 446 throw new UnsupportedOperationException("Unsupported ImageType " + 447 inputType); 448 } 449 450 return output; 451 } 452 453 public static String getScaledImageName(String path) { 454 StringBuilder result = new StringBuilder(); 455 int slash = path.lastIndexOf('/'); 456 String name = (slash < 0) ? path : path.substring(slash + 1); 457 int dot = name.lastIndexOf("."); 458 if (dot < 0) { 459 dot = name.length(); 460 } 461 if (slash >= 0) { 462 result.append(path.substring(0, slash + 1)); 463 } 464 result.append(name.substring(0, dot)); 465 result.append("@2x"); 466 result.append(name.substring(dot)); 467 return result.toString(); 468 } 469 470 public static InputStream createInputStream(String input) throws IOException { 471 InputStream stream = null; 472 473 // there should be a central utility for mapping these Strings to their 474 // inputStreams 475 try { 476 File file = new File(input); 477 if (file.exists()) { 478 stream = new FileInputStream(file); 479 } 480 } catch (Exception e) { 481 // ignore exception and try as url. 482 } 483 if (stream == null) { 484 URL url = new URL(input); 485 stream = url.openStream(); 486 } 487 return stream; 488 } 489 490 // Helper for computeUpdatedPixels method 491 private static void computeUpdatedPixels(int sourceOffset, 492 int sourceExtent, 493 int destinationOffset, 494 int dstMin, 495 int dstMax, 496 int sourceSubsampling, 497 int passStart, 498 int passExtent, 499 int passPeriod, 500 int[] vals, 501 int offset) { 502 // We need to satisfy the congruences: 503 // dst = destinationOffset + (src - sourceOffset)/sourceSubsampling 504 // 505 // src - passStart == 0 (mod passPeriod) 506 // src - sourceOffset == 0 (mod sourceSubsampling) 507 // 508 // subject to the inequalities: 509 // 510 // src >= passStart 511 // src < passStart + passExtent 512 // src >= sourceOffset 513 // src < sourceOffset + sourceExtent 514 // dst >= dstMin 515 // dst <= dstmax 516 // 517 // where 518 // 519 // dst = destinationOffset + (src - sourceOffset)/sourceSubsampling 520 // 521 // For now we use a brute-force approach although we could 522 // attempt to analyze the congruences. If passPeriod and 523 // sourceSubsamling are relatively prime, the period will be 524 // their product. If they share a common factor, either the 525 // period will be equal to the larger value, or the sequences 526 // will be completely disjoint, depending on the relationship 527 // between passStart and sourceOffset. Since we only have to do this 528 // twice per image (once each for X and Y), it seems cheap enough 529 // to do it the straightforward way. 530 531 boolean gotPixel = false; 532 int firstDst = -1; 533 int secondDst = -1; 534 int lastDst = -1; 535 536 for (int i = 0; i < passExtent; i++) { 537 int src = passStart + i * passPeriod; 538 if (src < sourceOffset) { 539 continue; 540 } 541 if ((src - sourceOffset) % sourceSubsampling != 0) { 542 continue; 543 } 544 if (src >= sourceOffset + sourceExtent) { 545 break; 546 } 547 548 int dst = destinationOffset + 549 (src - sourceOffset) / sourceSubsampling; 550 if (dst < dstMin) { 551 continue; 552 } 553 if (dst > dstMax) { 554 break; 555 } 556 557 if (!gotPixel) { 558 firstDst = dst; // Record smallest valid pixel 559 gotPixel = true; 560 } else if (secondDst == -1) { 561 secondDst = dst; // Record second smallest valid pixel 562 } 563 lastDst = dst; // Record largest valid pixel 564 } 565 566 vals[offset] = firstDst; 567 568 // If we never saw a valid pixel, set width to 0 569 if (!gotPixel) { 570 vals[offset + 2] = 0; 571 } else { 572 vals[offset + 2] = lastDst - firstDst + 1; 573 } 574 575 // The period is given by the difference of any two adjacent pixels 576 vals[offset + 4] = Math.max(secondDst - firstDst, 1); 577 } 578 579 /** 580 * A utility method that computes the exact set of destination 581 * pixels that will be written during a particular decoding pass. 582 * The intent is to simplify the work done by readers in combining 583 * the source region, source subsampling, and destination offset 584 * information obtained from the <code>ImageReadParam</code> with 585 * the offsets and periods of a progressive or interlaced decoding 586 * pass. 587 * 588 * @param sourceRegion a <code>Rectangle</code> containing the 589 * source region being read, offset by the source subsampling 590 * offsets, and clipped against the source bounds, as returned by 591 * the <code>getSourceRegion</code> method. 592 * @param destinationOffset a <code>Point</code> containing the 593 * coordinates of the upper-left pixel to be written in the 594 * destination. 595 * @param dstMinX the smallest X coordinate (inclusive) of the 596 * destination <code>Raster</code>. 597 * @param dstMinY the smallest Y coordinate (inclusive) of the 598 * destination <code>Raster</code>. 599 * @param dstMaxX the largest X coordinate (inclusive) of the destination 600 * <code>Raster</code>. 601 * @param dstMaxY the largest Y coordinate (inclusive) of the destination 602 * <code>Raster</code>. 603 * @param sourceXSubsampling the X subsampling factor. 604 * @param sourceYSubsampling the Y subsampling factor. 605 * @param passXStart the smallest source X coordinate (inclusive) 606 * of the current progressive pass. 607 * @param passYStart the smallest source Y coordinate (inclusive) 608 * of the current progressive pass. 609 * @param passWidth the width in pixels of the current progressive 610 * pass. 611 * @param passHeight the height in pixels of the current progressive 612 * pass. 613 * @param passPeriodX the X period (horizontal spacing between 614 * pixels) of the current progressive pass. 615 * @param passPeriodY the Y period (vertical spacing between 616 * pixels) of the current progressive pass. 617 * 618 * @return an array of 6 <code>int</code>s containing the 619 * destination min X, min Y, width, height, X period and Y period 620 * of the region that will be updated. 621 */ 622 public static int[] computeUpdatedPixels(Rectangle sourceRegion, 623 Point2D destinationOffset, 624 int dstMinX, 625 int dstMinY, 626 int dstMaxX, 627 int dstMaxY, 628 int sourceXSubsampling, 629 int sourceYSubsampling, 630 int passXStart, 631 int passYStart, 632 int passWidth, 633 int passHeight, 634 int passPeriodX, 635 int passPeriodY) { 636 int[] vals = new int[6]; 637 computeUpdatedPixels(sourceRegion.x, sourceRegion.width, 638 (int) (destinationOffset.x + 0.5F), 639 dstMinX, dstMaxX, sourceXSubsampling, 640 passXStart, passWidth, passPeriodX, 641 vals, 0); 642 computeUpdatedPixels(sourceRegion.y, sourceRegion.height, 643 (int) (destinationOffset.y + 0.5F), 644 dstMinY, dstMaxY, sourceYSubsampling, 645 passYStart, passHeight, passPeriodY, 646 vals, 1); 647 return vals; 648 } 649 650 public static int[] computeDimensions(int sourceWidth, int sourceHeight, 651 int maxWidth, int maxHeight, boolean preserveAspectRatio) { 652 // ensure non-negative dimensions (0 implies default) 653 int finalWidth = maxWidth < 0 ? 0 : maxWidth; 654 int finalHeight = maxHeight < 0 ? 0 : maxHeight; 655 656 if(finalWidth == 0 && finalHeight == 0) { 657 // default to source dimensions 658 finalWidth = sourceWidth; 659 finalHeight = sourceHeight; 660 } else if (finalWidth != sourceWidth || finalHeight != sourceHeight) { 661 if (preserveAspectRatio) { 662 // compute the final dimensions 663 if (finalWidth == 0) { 664 finalWidth = (int) ((float) sourceWidth * finalHeight / sourceHeight); 665 } else if (finalHeight == 0) { 666 finalHeight = (int) ((float) sourceHeight * finalWidth / sourceWidth); 667 } else { 668 float scale = Math.min((float) finalWidth / sourceWidth, (float) finalHeight / sourceHeight); 669 finalWidth = (int) (sourceWidth * scale); 670 finalHeight = (int) (sourceHeight * scale); 671 } 672 } else { 673 // set final dimensions to default if zero 674 if (finalHeight == 0) { 675 finalHeight = sourceHeight; 676 } 677 if (finalWidth == 0) { 678 finalWidth = sourceWidth; 679 } 680 } 681 682 683 // clamp dimensions to positive values 684 if (finalWidth == 0) { 685 finalWidth = 1; 686 } 687 if (finalHeight == 0) { 688 finalHeight = 1; 689 } 690 } 691 692 693 return new int[]{finalWidth, finalHeight}; 694 } 695 // public static final java.awt.image.BufferedImage getAsBufferedImage(Image prismImage) { 696 // java.awt.image.BufferedImage image = null; 697 // 698 // int width = prismImage.getWidth(); 699 // int height = prismImage.getHeight(); 700 // int scanlineStride = prismImage.getScanlineStride(); 701 // byte[] pixels = ((java.nio.ByteBuffer) prismImage.getPixelBuffer()).array(); 702 // switch (prismImage.getPixelFormat()) { 703 // case BYTE_GRAY: { 704 // image = new java.awt.image.BufferedImage(width, height, 705 // java.awt.image.BufferedImage.TYPE_BYTE_GRAY); 706 // java.awt.image.DataBufferByte db = 707 // (java.awt.image.DataBufferByte) image.getRaster().getDataBuffer(); 708 // byte[] data = db.getData(); 709 // System.arraycopy(pixels, 0, data, 0, width * height); 710 // } 711 // break; 712 // case BYTE_RGB: { 713 // image = new java.awt.image.BufferedImage(width, height, 714 // java.awt.image.BufferedImage.TYPE_3BYTE_BGR); 715 // for (int y = 0; y < height; y++) { 716 // int off = y * scanlineStride; 717 // for (int x = 0; x < width; x++) { 718 // int rgb = ((pixels[off++] & 0xff) << 16) | 719 // ((pixels[off++] & 0xff) << 8) | 720 // (pixels[off++] & 0xff); 721 // image.setRGB(x, y, rgb); 722 // } 723 // } 724 // } 725 // break; 726 // case BYTE_RGBA_PRE: { 727 // image = new java.awt.image.BufferedImage(width, height, 728 // java.awt.image.BufferedImage.TYPE_4BYTE_ABGR_PRE); 729 //// for (int y = 0; y < height; y++) { 730 //// int off = y * scanlineStride; 731 //// for (int x = 0; x < width; x++) { 732 //// int rgb = ((pixels[off++] & 0xff) << 16) | 733 //// ((pixels[off++] & 0xff) << 8) | 734 //// (pixels[off++] & 0xff) | 735 //// ((pixels[off++] & 0xff) << 24); 736 //// image.setRGB(x, y, rgb); 737 //// } 738 //// } 739 // java.awt.image.DataBufferByte db = 740 // (java.awt.image.DataBufferByte) image.getRaster().getDataBuffer(); 741 // byte[] data = db.getData(); 742 // for (int y = 0; y < height; y++) { 743 // int offPrism = y * scanlineStride; 744 // int offImage = y * width * 4; 745 // for (int x = 0; x < width; x++) { 746 // data[offImage++] = pixels[offPrism + 3]; // A 747 // data[offImage++] = pixels[offPrism + 2]; // B 748 // data[offImage++] = pixels[offPrism + 1]; // G 749 // data[offImage++] = pixels[offPrism]; // R 750 // offPrism += 4; 751 // } 752 // } 753 // } 754 // break; 755 // default: 756 // throw new UnsupportedOperationException("Unsupported test case " + 757 // prismImage.getPixelFormat()); 758 // } 759 // 760 // return image; 761 // } 762 }