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;
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) {
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 }
|
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.image.BufferedImage;
29 import java.awt.image.ComponentColorModel;
30 import java.awt.image.ComponentSampleModel;
31 import java.awt.image.DataBuffer;
32 import java.awt.image.ColorModel;
33 import java.awt.image.SampleModel;
34 import sun.awt.image.ByteComponentRaster;
35 import sun.awt.image.ShortComponentRaster;
36 import sun.awt.image.IntegerComponentRaster;
37
38
39 class LCMSImageLayout {
40
41 public static int BYTES_SH(int x) {
42 return x;
43 }
44
45 public static int EXTRA_SH(int x) {
46 return x<<7;
47 }
48
49 public static int CHANNELS_SH(int x) {
50 return x<<3;
51 }
52
53 public static final int SWAPFIRST = 1<<14;
75 public static final int PT_ABGR_8 =
76 DOSWAP | EXTRA_SH(1) | CHANNELS_SH(3) | BYTES_SH(1);
77
78 public static final int PT_BGRA_8 = EXTRA_SH(1) | CHANNELS_SH(3) |
79 BYTES_SH(1) | DOSWAP | SWAPFIRST;
80
81 public static final int DT_BYTE = 0;
82 public static final int DT_SHORT = 1;
83 public static final int DT_INT = 2;
84 public static final int DT_DOUBLE = 3;
85
86
87 boolean isIntPacked = false;
88 int pixelType;
89 int dataType;
90 int width;
91 int height;
92 int nextRowOffset;
93 int offset;
94
95 /* This flag indicates whether the image can be processed
96 * at once by doTransfrom() native call. Otherwise, the
97 * image is processed scan by scan.
98 */
99 private boolean imageAtOnce = false;
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) {
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 private LCMSImageLayout() {
146 }
147
148 /* This method creates a layout object for given image.
149 * Returns null if the image is not supported by current implementation.
150 */
151 public static LCMSImageLayout createImageLayout(BufferedImage image) {
152 LCMSImageLayout l = new LCMSImageLayout();
153
154 ShortComponentRaster shortRaster;
155 IntegerComponentRaster intRaster;
156 ByteComponentRaster byteRaster;
157 switch (image.getType()) {
158 case BufferedImage.TYPE_INT_RGB:
159 l.pixelType = PT_ARGB_8;
160 l.isIntPacked = true;
161 break;
162 case BufferedImage.TYPE_INT_ARGB:
163 l.pixelType = PT_ARGB_8;
164 l.isIntPacked = true;
165 break;
166 case BufferedImage.TYPE_INT_BGR:
167 l.pixelType = PT_ABGR_8;
168 l.isIntPacked = true;
169 break;
170 case BufferedImage.TYPE_3BYTE_BGR:
171 l.pixelType = PT_BGR_8;
172 break;
173 case BufferedImage.TYPE_4BYTE_ABGR:
174 l.pixelType = PT_ABGR_8;
175 break;
176 case BufferedImage.TYPE_BYTE_GRAY:
177 l.pixelType = PT_GRAY_8;
178 break;
179 case BufferedImage.TYPE_USHORT_GRAY:
180 l.pixelType = PT_GRAY_16;
181 break;
182 default:
183 /* ColorConvertOp creates component images as
184 * default destination, so this kind of images
185 * has to be supported.
186 */
187 ColorModel cm = image.getColorModel();
188 if (cm instanceof ComponentColorModel) {
189 ComponentColorModel ccm = (ComponentColorModel) cm;
190
191 // verify whether the component size is fine
192 int[] cs = ccm.getComponentSize();
193 for (int s : cs) {
194 if (s != 8) {
195 return null;
196 }
197 }
198
199 /* Make sure that band order in the raster
200 * is the natural color order for image's color space.
201 */
202 SampleModel sm = image.getSampleModel();
203 if (sm instanceof ComponentSampleModel) {
204 ComponentSampleModel csm = (ComponentSampleModel) sm;
205
206 if (csm.getTransferType() != DataBuffer.TYPE_BYTE) {
207 // We may consider to support other data types later.
208 return null;
209 }
210 int[] bandOffsets = csm.getBandOffsets();
211 for (int i = 0; i < bandOffsets.length; i++) {
212 /* Now we accept only natural order of color bands,
213 * but the reversed order also can be handled with
214 * SWAP flag in the pixel format descriptor.
215 */
216 if (bandOffsets[i] != i) {
217 return null;
218 }
219 }
220 }
221 l.pixelType = CHANNELS_SH(cs.length) | BYTES_SH(1);
222 byteRaster = (ByteComponentRaster) image.getRaster();
223 l.nextRowOffset = byteRaster.getScanlineStride();
224 l.offset = byteRaster.getDataOffset(0);
225 l.dataArray = byteRaster.getDataStorage();
226 l.dataType = DT_BYTE;
227
228 l.width = image.getWidth();
229 l.height = image.getHeight();
230
231 if (l.nextRowOffset == l.width * byteRaster.getPixelStride()) {
232 l.imageAtOnce = true;
233 }
234
235 return l;
236
237 } else {
238 return null;
239 }
240
241 }
242
243 l.width = image.getWidth();
244 l.height = image.getHeight();
245
246 switch (image.getType()) {
247 case BufferedImage.TYPE_INT_RGB:
248 case BufferedImage.TYPE_INT_ARGB:
249 case BufferedImage.TYPE_INT_BGR:
250 intRaster = (IntegerComponentRaster)image.getRaster();
251 l.nextRowOffset = intRaster.getScanlineStride()*4;
252 l.offset = intRaster.getDataOffset(0)*4;
253 l.dataArray = intRaster.getDataStorage();
254 l.dataType = DT_INT;
255
256 if (l.nextRowOffset == l.width * 4 * intRaster.getPixelStride()) {
257 l.imageAtOnce = true;
258 }
259 break;
260
261 case BufferedImage.TYPE_3BYTE_BGR:
262 case BufferedImage.TYPE_4BYTE_ABGR:
263 byteRaster = (ByteComponentRaster) image.getRaster();
264 l.nextRowOffset = byteRaster.getScanlineStride();
265 int firstBand = image.getSampleModel().getNumBands() - 1;
266 l.offset = byteRaster.getDataOffset(firstBand);
267 l.dataArray = byteRaster.getDataStorage();
268 l.dataType = DT_BYTE;
269 if (l.nextRowOffset == l.width * byteRaster.getPixelStride()) {
270 l.imageAtOnce = true;
271 }
272 break;
273
274 case BufferedImage.TYPE_BYTE_GRAY:
275 byteRaster = (ByteComponentRaster)image.getRaster();
276 l.nextRowOffset = byteRaster.getScanlineStride();
277 l.offset = byteRaster.getDataOffset(0);
278 l.dataArray = byteRaster.getDataStorage();
279 l.dataType = DT_BYTE;
280
281 if (l.nextRowOffset == l.width * byteRaster.getPixelStride()) {
282 l.imageAtOnce = true;
283 }
284 break;
285
286 case BufferedImage.TYPE_USHORT_GRAY:
287 shortRaster = (ShortComponentRaster)image.getRaster();
288 l.nextRowOffset = shortRaster.getScanlineStride()*2;
289 l.offset = shortRaster.getDataOffset(0) * 2;
290 l.dataArray = shortRaster.getDataStorage();
291 l.dataType = DT_SHORT;
292
293 if (l.nextRowOffset == l.width * 2 *shortRaster.getPixelStride()) {
294 l.imageAtOnce = true;
295 }
296 break;
297 default:
298 return null;
299 }
300 return l;
301 }
302 }
|