1 /* 2 * Copyright (c) 2007, 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 sun.java2d.cmm.lcms; 27 28 import java.awt.Graphics2D; 29 import java.awt.image.BufferedImage; 30 import java.awt.image.ComponentColorModel; 31 import java.awt.image.Raster; 32 import java.awt.image.WritableRaster; 33 import java.awt.image.SinglePixelPackedSampleModel; 34 import java.awt.image.ComponentSampleModel; 35 import java.awt.image.DataBuffer; 36 import java.awt.image.DataBufferByte; 37 import java.awt.image.DataBufferUShort; 38 import java.awt.image.DataBufferInt; 39 import java.awt.image.ColorModel; 40 import sun.awt.image.ByteComponentRaster; 41 import sun.awt.image.ShortComponentRaster; 42 import sun.awt.image.IntegerComponentRaster; 43 44 45 class LCMSImageLayout { 46 47 public static int BYTES_SH(int x) { 48 return x; 49 } 50 51 public static int EXTRA_SH(int x) { 52 return x<<7; 53 } 54 55 public static int CHANNELS_SH(int x) { 56 return x<<3; 57 } 58 59 public static final int SWAPFIRST = 1<<14; 60 61 public static final int DOSWAP = 1<<10; 62 63 public static final int PT_RGB_8 = 64 CHANNELS_SH(3) | BYTES_SH(1); 65 66 public static final int PT_GRAY_8 = 67 CHANNELS_SH(1) | BYTES_SH(1); 68 69 public static final int PT_GRAY_16 = 70 CHANNELS_SH(1) | BYTES_SH(2); 71 72 public static final int PT_RGBA_8 = 73 EXTRA_SH(1) | CHANNELS_SH(3) | BYTES_SH(1); 74 75 public static final int PT_ARGB_8 = 76 EXTRA_SH(1) | CHANNELS_SH(3) | BYTES_SH(1) | SWAPFIRST; 77 78 public static final int PT_BGR_8 = 79 DOSWAP | CHANNELS_SH(3) | BYTES_SH(1); 80 81 public static final int PT_ABGR_8 = 82 DOSWAP | EXTRA_SH(1) | CHANNELS_SH(3) | BYTES_SH(1); 83 84 public static final int PT_BGRA_8 = EXTRA_SH(1) | CHANNELS_SH(3) | 85 BYTES_SH(1) | DOSWAP | SWAPFIRST; 86 87 public static final int DT_BYTE = 0; 88 public static final int DT_SHORT = 1; 89 public static final int DT_INT = 2; 90 public static final int DT_DOUBLE = 3; 91 92 93 boolean isIntPacked = false; 94 int pixelType; 95 int dataType; 96 int width; 97 int height; 98 int nextRowOffset; 99 int offset; 100 101 Object dataArray; 102 private LCMSImageLayout(int np, int pixelType, int pixelSize) { 103 this.pixelType = pixelType; 104 width = np; 105 height = 1; 106 nextRowOffset = np*pixelSize; 107 offset = 0; 108 } 109 110 private LCMSImageLayout(int width, int height, int pixelType, 111 int pixelSize) { 112 this.pixelType = pixelType; 113 this.width = width; 114 this.height = height; 115 nextRowOffset = width*pixelSize; 116 offset = 0; 117 } 118 119 120 public LCMSImageLayout(byte[] data, int np, int pixelType, int pixelSize) { 121 this(np, pixelType, pixelSize); 122 dataType = DT_BYTE; 123 dataArray = data; 124 } 125 126 public LCMSImageLayout(short[] data, int np, int pixelType, int pixelSize) { 127 this(np, pixelType, pixelSize); 128 dataType = DT_SHORT; 129 dataArray = data; 130 } 131 132 public LCMSImageLayout(int[] data, int np, int pixelType, int pixelSize) { 133 this(np, pixelType, pixelSize); 134 dataType = DT_INT; 135 dataArray = data; 136 } 137 138 public LCMSImageLayout(double[] data, int np, int pixelType, int pixelSize) 139 { 140 this(np, pixelType, pixelSize); 141 dataType = DT_DOUBLE; 142 dataArray = data; 143 } 144 145 public LCMSImageLayout(BufferedImage image) { 146 ShortComponentRaster shortRaster; 147 IntegerComponentRaster intRaster; 148 ByteComponentRaster byteRaster; 149 switch (image.getType()) { 150 case BufferedImage.TYPE_INT_RGB: 151 pixelType = PT_ARGB_8; 152 isIntPacked = true; 153 break; 154 case BufferedImage.TYPE_INT_ARGB: 155 pixelType = PT_ARGB_8; 156 isIntPacked = true; 157 break; 158 case BufferedImage.TYPE_INT_BGR: 159 pixelType = PT_ABGR_8; 160 isIntPacked = true; 161 break; 162 case BufferedImage.TYPE_3BYTE_BGR: 163 pixelType = PT_BGR_8; 164 break; 165 case BufferedImage.TYPE_4BYTE_ABGR: 166 pixelType = PT_ABGR_8; 167 break; 168 case BufferedImage.TYPE_BYTE_GRAY: 169 pixelType = PT_GRAY_8; 170 break; 171 case BufferedImage.TYPE_USHORT_GRAY: 172 pixelType = PT_GRAY_16; 173 break; 174 default: 175 // TODO: Add support for some images having 176 // SinglePixelPackedModel and ComponentSampleModel 177 throw new IllegalArgumentException( 178 "CMMImageLayout - bad image type passed to constructor"); 179 } 180 181 width = image.getWidth(); 182 height = image.getHeight(); 183 184 switch (image.getType()) { 185 case BufferedImage.TYPE_INT_RGB: 186 case BufferedImage.TYPE_INT_ARGB: 187 case BufferedImage.TYPE_INT_BGR: 188 intRaster = (IntegerComponentRaster)image.getRaster(); 189 nextRowOffset = intRaster.getScanlineStride()*4; 190 offset = intRaster.getDataOffset(0)*4; 191 dataArray = intRaster.getDataStorage(); 192 dataType = DT_INT; 193 break; 194 195 case BufferedImage.TYPE_3BYTE_BGR: 196 case BufferedImage.TYPE_4BYTE_ABGR: 197 byteRaster = (ByteComponentRaster)image.getRaster(); 198 nextRowOffset = byteRaster.getScanlineStride(); 199 int firstBand = image.getSampleModel().getNumBands() - 1; 200 offset = byteRaster.getDataOffset(firstBand); 201 dataArray = byteRaster.getDataStorage(); 202 dataType = DT_BYTE; 203 break; 204 205 case BufferedImage.TYPE_BYTE_GRAY: 206 byteRaster = (ByteComponentRaster)image.getRaster(); 207 nextRowOffset = byteRaster.getScanlineStride(); 208 offset = byteRaster.getDataOffset(0); 209 dataArray = byteRaster.getDataStorage(); 210 dataType = DT_BYTE; 211 break; 212 213 case BufferedImage.TYPE_USHORT_GRAY: 214 shortRaster = (ShortComponentRaster)image.getRaster(); 215 nextRowOffset = shortRaster.getScanlineStride()*2; 216 offset = shortRaster.getDataOffset(0) * 2; 217 dataArray = shortRaster.getDataStorage(); 218 dataType = DT_SHORT; 219 break; 220 } 221 } 222 223 public static boolean isSupported(BufferedImage image) { 224 switch (image.getType()) { 225 case BufferedImage.TYPE_INT_RGB: 226 case BufferedImage.TYPE_INT_ARGB: 227 case BufferedImage.TYPE_INT_BGR: 228 case BufferedImage.TYPE_3BYTE_BGR: 229 case BufferedImage.TYPE_4BYTE_ABGR: 230 case BufferedImage.TYPE_BYTE_GRAY: 231 case BufferedImage.TYPE_USHORT_GRAY: 232 return true; 233 } 234 return false; 235 } 236 }