Skip to content

Commit 117c5b1

Browse files
committedApr 21, 2023
8279216: Investigate implementation of premultiplied alpha in the Little-CMS 2.13
Reviewed-by: prr
1 parent 723037a commit 117c5b1

File tree

5 files changed

+508
-30
lines changed

5 files changed

+508
-30
lines changed
 

‎src/java.desktop/share/classes/sun/java2d/cmm/lcms/LCMSImageLayout.java

+30-15
Original file line numberDiff line numberDiff line change
@@ -52,16 +52,22 @@ private static int EXTRA_SH(int x) {
5252
static int CHANNELS_SH(int x) {
5353
return x << 3;
5454
}
55+
56+
static int PREMUL_SH(int x) {
57+
return x << 23;
58+
}
5559
private static final int SWAPFIRST = 1 << 14;
5660
private static final int DOSWAP = 1 << 10;
57-
private static final int PT_GRAY_8 = CHANNELS_SH(1) | BYTES_SH(1);
58-
private static final int PT_GRAY_16 = CHANNELS_SH(1) | BYTES_SH(2);
59-
private static final int PT_RGB_8 = CHANNELS_SH(3) | BYTES_SH(1);
60-
private static final int PT_RGBA_8 = PT_RGB_8 | EXTRA_SH(1);
61-
private static final int PT_ARGB_8 = PT_RGBA_8 | SWAPFIRST;
62-
private static final int PT_BGR_8 = PT_RGB_8 | DOSWAP;
63-
private static final int PT_ABGR_8 = PT_BGR_8 | EXTRA_SH(1);
64-
// private static final int PT_BGRA_8 = PT_ABGR_8 | SWAPFIRST;
61+
private static final int PT_GRAY_8 = CHANNELS_SH(1) | BYTES_SH(1);
62+
private static final int PT_GRAY_16 = CHANNELS_SH(1) | BYTES_SH(2);
63+
private static final int PT_RGB_8 = CHANNELS_SH(3) | BYTES_SH(1);
64+
private static final int PT_RGBA_8 = PT_RGB_8 | EXTRA_SH(1);
65+
private static final int PT_ARGB_8 = PT_RGBA_8 | SWAPFIRST;
66+
private static final int PT_ARGB_8_PREMUL = PT_ARGB_8 | PREMUL_SH(1);
67+
private static final int PT_BGR_8 = PT_RGB_8 | DOSWAP;
68+
private static final int PT_ABGR_8 = PT_BGR_8 | EXTRA_SH(1);
69+
private static final int PT_ABGR_8_PREMUL = PT_ABGR_8 | PREMUL_SH(1);
70+
// private static final int PT_BGRA_8 = PT_ABGR_8 | SWAPFIRST;
6571
private static final int SWAP_ENDIAN =
6672
ByteOrder.nativeOrder() == LITTLE_ENDIAN ? DOSWAP : 0;
6773
private static final int DT_BYTE = 0;
@@ -148,6 +154,9 @@ static LCMSImageLayout createImageLayout(BufferedImage image) {
148154
case BufferedImage.TYPE_INT_RGB:
149155
l.pixelType = PT_ARGB_8 ^ SWAP_ENDIAN;
150156
break;
157+
case BufferedImage.TYPE_INT_ARGB_PRE:
158+
l.pixelType = PT_ARGB_8_PREMUL ^ SWAP_ENDIAN;
159+
break;
151160
case BufferedImage.TYPE_INT_ARGB:
152161
l.pixelType = PT_ARGB_8 ^ SWAP_ENDIAN;
153162
break;
@@ -160,6 +169,9 @@ static LCMSImageLayout createImageLayout(BufferedImage image) {
160169
case BufferedImage.TYPE_4BYTE_ABGR:
161170
l.pixelType = PT_ABGR_8;
162171
break;
172+
case BufferedImage.TYPE_4BYTE_ABGR_PRE:
173+
l.pixelType = PT_ABGR_8_PREMUL;
174+
break;
163175
case BufferedImage.TYPE_BYTE_GRAY:
164176
l.pixelType = PT_GRAY_8;
165177
break;
@@ -172,18 +184,15 @@ static LCMSImageLayout createImageLayout(BufferedImage image) {
172184
* has to be supported.
173185
*/
174186
ColorModel cm = image.getColorModel();
175-
// lcms as of now does not support pre-alpha
176-
if (!cm.isAlphaPremultiplied()
177-
&& cm instanceof ComponentColorModel ccm)
178-
{
187+
if (cm instanceof ComponentColorModel ccm) {
179188
// verify whether the component size is fine
180189
int[] cs = ccm.getComponentSize();
181190
for (int s : cs) {
182191
if (s != 8) {
183192
return null;
184193
}
185194
}
186-
return createImageLayout(image.getRaster(), cm.hasAlpha());
195+
return createImageLayout(image.getRaster(), cm);
187196
}
188197
return null;
189198
}
@@ -194,6 +203,7 @@ static LCMSImageLayout createImageLayout(BufferedImage image) {
194203
switch (image.getType()) {
195204
case BufferedImage.TYPE_INT_RGB:
196205
case BufferedImage.TYPE_INT_ARGB:
206+
case BufferedImage.TYPE_INT_ARGB_PRE:
197207
case BufferedImage.TYPE_INT_BGR:
198208
do {
199209
IntegerComponentRaster intRaster = (IntegerComponentRaster)
@@ -209,13 +219,14 @@ static LCMSImageLayout createImageLayout(BufferedImage image) {
209219

210220
case BufferedImage.TYPE_3BYTE_BGR:
211221
case BufferedImage.TYPE_4BYTE_ABGR:
222+
case BufferedImage.TYPE_4BYTE_ABGR_PRE:
212223
do {
213224
ByteComponentRaster byteRaster = (ByteComponentRaster)
214225
image.getRaster();
215226
l.nextRowOffset = byteRaster.getScanlineStride();
216227
l.nextPixelOffset = byteRaster.getPixelStride();
217228

218-
int firstBand = image.getSampleModel().getNumBands() - 1;
229+
int firstBand = byteRaster.getSampleModel().getNumBands() - 1;
219230
l.offset = byteRaster.getDataOffset(firstBand);
220231
l.dataArray = byteRaster.getDataStorage();
221232
l.dataArrayLength = byteRaster.getDataStorage().length;
@@ -320,7 +331,7 @@ private static int safeMult(int a, int b) {
320331
return checkIndex(res, Integer.MAX_VALUE);
321332
}
322333

323-
static LCMSImageLayout createImageLayout(Raster r, boolean hasAlpha) {
334+
static LCMSImageLayout createImageLayout(Raster r, ColorModel cm) {
324335
LCMSImageLayout l = new LCMSImageLayout();
325336
if (r instanceof ByteComponentRaster &&
326337
r.getSampleModel() instanceof ComponentSampleModel) {
@@ -329,8 +340,12 @@ static LCMSImageLayout createImageLayout(Raster r, boolean hasAlpha) {
329340
ComponentSampleModel csm = (ComponentSampleModel)r.getSampleModel();
330341

331342
int numBands = br.getNumBands();
343+
boolean hasAlpha = cm != null && cm.hasAlpha();
332344
l.pixelType = (hasAlpha ? CHANNELS_SH(numBands - 1) | EXTRA_SH(1)
333345
: CHANNELS_SH(numBands)) | BYTES_SH(1);
346+
if (hasAlpha && cm.isAlphaPremultiplied()) {
347+
l.pixelType |= PREMUL_SH(1);
348+
}
334349

335350
int[] bandOffsets = csm.getBandOffsets();
336351
BandOrder order = BandOrder.getBandOrder(bandOffsets);

‎src/java.desktop/share/classes/sun/java2d/cmm/lcms/LCMSTransform.java

+8-12
Original file line numberDiff line numberDiff line change
@@ -127,19 +127,15 @@ private void doTransform(LCMSImageLayout in, LCMSImageLayout out) {
127127
}
128128

129129
/**
130-
* Returns {@code true} if lcms may supports this format directly.
130+
* Returns {@code true} if lcms may support this format directly.
131131
*/
132132
private static boolean isLCMSSupport(BufferedImage src, BufferedImage dst) {
133-
if (!dst.getColorModel().hasAlpha()) {
134-
return true;
135-
}
136-
// lcms as of now does not support pre-alpha
137-
if (src.isAlphaPremultiplied() || dst.isAlphaPremultiplied()) {
138-
return false;
139-
}
133+
boolean dstAlpha = dst.getColorModel().hasAlpha();
134+
boolean srcAlpha = src.getColorModel().hasAlpha();
135+
boolean srcPre = srcAlpha && src.getColorModel().isAlphaPremultiplied();
136+
// lcms does not convert pre-alpha for transparent src if dst is opaque
140137
// lcms does not set correct alpha for transparent dst if src is opaque
141-
// is it feature or bug?
142-
return dst.getColorModel().hasAlpha() == src.getColorModel().hasAlpha();
138+
return !dstAlpha && !srcPre || dstAlpha == srcAlpha;
143139
}
144140

145141
public void colorConvert(BufferedImage src, BufferedImage dst) {
@@ -424,9 +420,9 @@ public void colorConvert(Raster src, WritableRaster dst,
424420
public void colorConvert(Raster src, WritableRaster dst) {
425421

426422
LCMSImageLayout srcIL, dstIL;
427-
dstIL = LCMSImageLayout.createImageLayout(dst, false);
423+
dstIL = LCMSImageLayout.createImageLayout(dst, null);
428424
if (dstIL != null) {
429-
srcIL = LCMSImageLayout.createImageLayout(src, false);
425+
srcIL = LCMSImageLayout.createImageLayout(src, null);
430426
if (srcIL != null) {
431427
doTransform(srcIL, dstIL);
432428
return;

‎test/jdk/sun/java2d/cmm/ColorConvertOp/ColCvtAlphaDifferentSrcDst.java

+123-3
Original file line numberDiff line numberDiff line change
@@ -23,11 +23,18 @@
2323

2424
import java.awt.AlphaComposite;
2525
import java.awt.Graphics2D;
26+
import java.awt.Transparency;
2627
import java.awt.color.ColorSpace;
2728
import java.awt.color.ICC_ColorSpace;
2829
import java.awt.color.ICC_Profile;
2930
import java.awt.image.BufferedImage;
3031
import java.awt.image.ColorConvertOp;
32+
import java.awt.image.ColorModel;
33+
import java.awt.image.ComponentColorModel;
34+
import java.awt.image.DataBuffer;
35+
import java.awt.image.DirectColorModel;
36+
import java.awt.image.Raster;
37+
import java.awt.image.WritableRaster;
3138

3239
import static java.awt.image.BufferedImage.TYPE_3BYTE_BGR;
3340
import static java.awt.image.BufferedImage.TYPE_4BYTE_ABGR;
@@ -45,19 +52,27 @@
4552

4653
/*
4754
* @test
48-
* @bug 8012229 8300725
55+
* @bug 8012229 8300725 8279216
4956
* @summary one more test to check the alpha channel
5057
*/
5158
public final class ColCvtAlphaDifferentSrcDst {
5259

5360
private static final int WIDTH = 256;
5461
private static final int HEIGHT = 256;
5562

63+
private static final int TYPE_CUSTOM_4BYTE_ABGR_PRE = -1;
64+
private static final int TYPE_CUSTOM_4BYTE_ARGB_PRE = -2;
65+
private static final int TYPE_CUSTOM_4BYTE_RGBA_PRE = -3;
66+
private static final int TYPE_CUSTOM_4BYTE_GABR_PRE = -4;
67+
private static final int TYPE_CUSTOM_INT_ARGB_PRE = -5;
68+
private static final int TYPE_CUSTOM_INT_GABR_PRE = -6;
69+
5670
public static void main(String[] args) throws Exception {
5771
differentToOpaqueDst();
5872
differentToTransparentDst(TYPE_INT_ARGB);
5973
differentToTransparentDst(TYPE_4BYTE_ABGR);
6074
differentToTransparentDst(TYPE_INT_ARGB_PRE);
75+
differentToTransparentDst(TYPE_4BYTE_ABGR_PRE);
6176
differentToNullDst();
6277
}
6378

@@ -97,7 +112,16 @@ private static void differentToOpaqueDst() {
97112
opaqueDst(TYPE_INT_ARGB, TYPE_INT_BGR);
98113
opaqueDst(TYPE_4BYTE_ABGR, TYPE_INT_BGR);
99114

100-
// It is unclear how to hangle pre colors in the opaque DST
115+
// compare the "fast" and "slow" paths
116+
opaqueDst(TYPE_4BYTE_ABGR_PRE, TYPE_CUSTOM_4BYTE_ABGR_PRE);
117+
opaqueDst(TYPE_4BYTE_ABGR_PRE, TYPE_CUSTOM_4BYTE_ARGB_PRE);
118+
opaqueDst(TYPE_4BYTE_ABGR_PRE, TYPE_CUSTOM_4BYTE_RGBA_PRE);
119+
opaqueDst(TYPE_4BYTE_ABGR_PRE, TYPE_CUSTOM_4BYTE_GABR_PRE);
120+
121+
opaqueDst(TYPE_INT_ARGB_PRE, TYPE_CUSTOM_INT_ARGB_PRE);
122+
opaqueDst(TYPE_INT_ARGB_PRE, TYPE_CUSTOM_INT_GABR_PRE);
123+
124+
// It is unclear how to handle pre colors in the opaque DST
101125
//opaqueDst(TYPE_INT_ARGB_PRE, TYPE_4BYTE_ABGR_PRE);
102126
//opaqueDst(TYPE_4BYTE_ABGR_PRE, TYPE_INT_BGR);
103127
}
@@ -196,7 +220,15 @@ private static void validate(BufferedImage img1, BufferedImage img2,
196220
}
197221

198222
private static BufferedImage createSrc(int type) {
199-
BufferedImage img = new BufferedImage(WIDTH, HEIGHT, type);
223+
BufferedImage img = switch (type) {
224+
case TYPE_CUSTOM_4BYTE_ABGR_PRE -> TYPE_4BYTE_ABGR_PRE();
225+
case TYPE_CUSTOM_4BYTE_ARGB_PRE -> TYPE_4BYTE_ARGB_PRE();
226+
case TYPE_CUSTOM_4BYTE_RGBA_PRE -> TYPE_4BYTE_RGBA_PRE();
227+
case TYPE_CUSTOM_4BYTE_GABR_PRE -> TYPE_4BYTE_GABR_PRE();
228+
case TYPE_CUSTOM_INT_ARGB_PRE -> TYPE_INT_ARGB_PRE();
229+
case TYPE_CUSTOM_INT_GABR_PRE -> TYPE_INT_GABR_PRE();
230+
default -> new BufferedImage(WIDTH, HEIGHT, type);
231+
};
200232
fill(img);
201233
return img;
202234
}
@@ -220,4 +252,92 @@ private static void fill(BufferedImage image) {
220252
}
221253
}
222254
}
255+
256+
private static BufferedImage TYPE_4BYTE_RGBA_PRE() {
257+
ColorSpace cs = ColorSpace.getInstance(ColorSpace.CS_sRGB);
258+
int[] nBits = {8, 8, 8, 8};
259+
int[] bOffs = {0, 1, 2, 3};
260+
ColorModel colorModel = new ComponentColorModel(cs, nBits, true, true,
261+
Transparency.TRANSLUCENT,
262+
DataBuffer.TYPE_BYTE);
263+
WritableRaster raster = Raster.createInterleavedRaster(DataBuffer.TYPE_BYTE,
264+
WIDTH, HEIGHT,
265+
WIDTH * 4, 4,
266+
bOffs, null);
267+
return new BufferedImage(colorModel, raster, true, null);
268+
}
269+
270+
private static BufferedImage TYPE_4BYTE_ABGR_PRE() {
271+
ColorSpace cs = ColorSpace.getInstance(ColorSpace.CS_sRGB);
272+
int[] nBits = {8, 8, 8, 8};
273+
int[] bOffs = {3, 2, 1, 0};
274+
ColorModel colorModel = new ComponentColorModel(cs, nBits, true, true,
275+
Transparency.TRANSLUCENT,
276+
DataBuffer.TYPE_BYTE);
277+
WritableRaster raster = Raster.createInterleavedRaster(DataBuffer.TYPE_BYTE,
278+
WIDTH, HEIGHT,
279+
WIDTH * 4, 4,
280+
bOffs, null);
281+
return new BufferedImage(colorModel, raster, true, null);
282+
}
283+
284+
private static BufferedImage TYPE_4BYTE_ARGB_PRE() {
285+
ColorSpace cs = ColorSpace.getInstance(ColorSpace.CS_sRGB);
286+
int[] nBits = {8, 8, 8, 8};
287+
int[] bOffs = {1, 2, 3, 0};
288+
ColorModel colorModel = new ComponentColorModel(cs, nBits, true, true,
289+
Transparency.TRANSLUCENT,
290+
DataBuffer.TYPE_BYTE);
291+
WritableRaster raster = Raster.createInterleavedRaster(DataBuffer.TYPE_BYTE,
292+
WIDTH, HEIGHT,
293+
WIDTH * 4, 4,
294+
bOffs, null);
295+
return new BufferedImage(colorModel, raster, true, null);
296+
}
297+
298+
private static BufferedImage TYPE_4BYTE_GABR_PRE() {
299+
ColorSpace cs = ColorSpace.getInstance(ColorSpace.CS_sRGB);
300+
int[] nBits = {8, 8, 8, 8};
301+
int[] bOffs = {3, 0, 2, 1};
302+
ColorModel colorModel = new ComponentColorModel(cs, nBits, true, false,
303+
Transparency.TRANSLUCENT,
304+
DataBuffer.TYPE_BYTE);
305+
WritableRaster raster = Raster.createInterleavedRaster(DataBuffer.TYPE_BYTE,
306+
WIDTH, HEIGHT,
307+
WIDTH * 4, 4,
308+
bOffs, null);
309+
return new BufferedImage(colorModel, raster, true, null);
310+
}
311+
312+
private static BufferedImage TYPE_INT_ARGB_PRE() {
313+
ColorModel colorModel = new DirectColorModel(
314+
ColorSpace.getInstance(ColorSpace.CS_sRGB),
315+
32,
316+
0x00ff0000, // Red
317+
0x0000ff00, // Green
318+
0x000000ff, // Blue
319+
0xff000000, // Alpha
320+
true, // Alpha Premultiplied
321+
DataBuffer.TYPE_INT
322+
);
323+
WritableRaster raster = colorModel.createCompatibleWritableRaster(WIDTH,
324+
HEIGHT);
325+
return new BufferedImage(colorModel, raster, true, null);
326+
}
327+
328+
private static BufferedImage TYPE_INT_GABR_PRE() {
329+
ColorModel colorModel = new DirectColorModel(
330+
ColorSpace.getInstance(ColorSpace.CS_sRGB),
331+
32,
332+
0x000000ff, // Red
333+
0xff000000, // Green
334+
0x0000ff00, // Blue
335+
0x00ff0000, // Alpha
336+
true, // Alpha Premultiplied
337+
DataBuffer.TYPE_INT
338+
);
339+
WritableRaster raster = colorModel.createCompatibleWritableRaster(WIDTH,
340+
HEIGHT);
341+
return new BufferedImage(colorModel, raster, true, null);
342+
}
223343
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,264 @@
1+
/*
2+
* Copyright Amazon.com Inc. 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.
8+
*
9+
* This code is distributed in the hope that it will be useful, but WITHOUT
10+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12+
* version 2 for more details (a copy is included in the LICENSE file that
13+
* accompanied this code).
14+
*
15+
* You should have received a copy of the GNU General Public License version
16+
* 2 along with this work; if not, write to the Free Software Foundation,
17+
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18+
*
19+
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20+
* or visit www.oracle.com if you need additional information or have any
21+
* questions.
22+
*/
23+
24+
import java.awt.AlphaComposite;
25+
import java.awt.Color;
26+
import java.awt.Graphics2D;
27+
import java.awt.Transparency;
28+
import java.awt.color.ColorSpace;
29+
import java.awt.image.BufferedImage;
30+
import java.awt.image.ColorConvertOp;
31+
import java.awt.image.ColorModel;
32+
import java.awt.image.ComponentColorModel;
33+
import java.awt.image.DataBuffer;
34+
import java.awt.image.DirectColorModel;
35+
import java.awt.image.Raster;
36+
import java.awt.image.WritableRaster;
37+
import java.util.Arrays;
38+
39+
import static java.awt.image.BufferedImage.TYPE_4BYTE_ABGR_PRE;
40+
import static java.awt.image.BufferedImage.TYPE_INT_ARGB_PRE;
41+
42+
/**
43+
* @test
44+
* @bug 8279216
45+
* @summary Verifies implementation of premultiplied alpha
46+
*/
47+
public final class PremultipliedAlpha {
48+
49+
private static final int SIZE = 256;
50+
51+
private static final int COLOR_TOLERANCE = 2;
52+
53+
private enum Type {
54+
TYPE_ARGB_PRE,
55+
TYPE_4BYTE_ABGR_PRE,
56+
TYPE_CUSTOM_ARGB_PRE,
57+
TYPE_CUSTOM_GABR_PRE,
58+
TYPE_CUSTOM_4BYTE_ABGR_PRE,
59+
TYPE_CUSTOM_4BYTE_ARGB_PRE,
60+
TYPE_CUSTOM_4BYTE_RGBA_PRE,
61+
TYPE_CUSTOM_4BYTE_GABR_PRE,
62+
TYPE_CUSTOM_4USHORT_8bit_ARGB_PRE,
63+
TYPE_CUSTOM_4INT_8bit_ARGB_PRE,
64+
}
65+
66+
private static final ColorSpace[] CSs = {
67+
ColorSpace.getInstance(ColorSpace.CS_CIEXYZ),
68+
ColorSpace.getInstance(ColorSpace.CS_GRAY),
69+
ColorSpace.getInstance(ColorSpace.CS_LINEAR_RGB),
70+
ColorSpace.getInstance(ColorSpace.CS_PYCC),
71+
ColorSpace.getInstance(ColorSpace.CS_sRGB)
72+
};
73+
74+
public static void main(String[] args) {
75+
for (ColorSpace cs : CSs) {
76+
for (Type dst : Type.values()) {
77+
BufferedImage gold = null;
78+
for (Type src : Type.values()) {
79+
BufferedImage from = createSrc(src);
80+
BufferedImage to = createDst(dst);
81+
ColorConvertOp op = new ColorConvertOp(cs, null);
82+
op.filter(from, to);
83+
if (gold == null) {
84+
gold = to;
85+
} else {
86+
validate(gold, to);
87+
}
88+
}
89+
}
90+
}
91+
}
92+
93+
private static void validate(BufferedImage img1, BufferedImage img2) {
94+
for (int a = 0; a < SIZE; a++) {
95+
for (int c = 0; c < SIZE; c++) {
96+
int[] pixel1 = img1.getRaster().getPixel(c, a, (int[]) null);
97+
int[] pixel2 = img2.getRaster().getPixel(c, a, (int[]) null);
98+
if (pixel1.length != pixel2.length) {
99+
throw new RuntimeException();
100+
}
101+
for (int i = 0 ; i < pixel1.length; ++i) {
102+
if (Math.abs(pixel1[i] - pixel2[i]) >= COLOR_TOLERANCE) {
103+
System.out.println("c = " + c);
104+
System.out.println("a = " + a);
105+
System.err.println("rgb1 = " + Arrays.toString(pixel1));
106+
System.err.println("rgb2 = " + Arrays.toString(pixel2));
107+
throw new RuntimeException();
108+
}
109+
}
110+
}
111+
}
112+
}
113+
114+
private static BufferedImage createDst(Type type) {
115+
BufferedImage img = createSrc(type);
116+
Graphics2D g = img.createGraphics();
117+
g.setComposite(AlphaComposite.Clear);
118+
g.fillRect(0, 0, SIZE, SIZE);
119+
g.dispose();
120+
return img;
121+
}
122+
123+
private static BufferedImage createSrc(Type type) {
124+
BufferedImage bi = switch (type) {
125+
case TYPE_ARGB_PRE -> new BufferedImage(SIZE, SIZE, TYPE_INT_ARGB_PRE);
126+
case TYPE_CUSTOM_ARGB_PRE -> TYPE_ARGB_PRE();
127+
case TYPE_CUSTOM_GABR_PRE -> TYPE_GABR_PRE();
128+
case TYPE_4BYTE_ABGR_PRE -> new BufferedImage(SIZE, SIZE, TYPE_4BYTE_ABGR_PRE);
129+
case TYPE_CUSTOM_4BYTE_ARGB_PRE -> TYPE_4BYTE_ARGB_PRE();
130+
case TYPE_CUSTOM_4BYTE_ABGR_PRE -> TYPE_4BYTE_ABGR_PRE();
131+
case TYPE_CUSTOM_4BYTE_RGBA_PRE -> TYPE_4BYTE_RGBA_PRE();
132+
case TYPE_CUSTOM_4BYTE_GABR_PRE -> TYPE_4BYTE_GABR_PRE();
133+
case TYPE_CUSTOM_4USHORT_8bit_ARGB_PRE -> TYPE_4USHORT_ARGB_8bit_PRE();
134+
case TYPE_CUSTOM_4INT_8bit_ARGB_PRE -> TYPE_4INT_ARGB_8bit_PRE();
135+
};
136+
fill(bi);
137+
return bi;
138+
}
139+
140+
private static BufferedImage TYPE_ARGB_PRE() {
141+
ColorModel colorModel = new DirectColorModel(
142+
ColorSpace.getInstance(ColorSpace.CS_sRGB),
143+
32,
144+
0x00ff0000, // Red
145+
0x0000ff00, // Green
146+
0x000000ff, // Blue
147+
0xff000000, // Alpha
148+
true, // Alpha Premultiplied
149+
DataBuffer.TYPE_INT
150+
);
151+
WritableRaster raster = colorModel.createCompatibleWritableRaster(SIZE,
152+
SIZE);
153+
return new BufferedImage(colorModel, raster, true, null);
154+
}
155+
156+
private static BufferedImage TYPE_GABR_PRE() {
157+
ColorModel colorModel = new DirectColorModel(
158+
ColorSpace.getInstance(ColorSpace.CS_sRGB),
159+
32,
160+
0x000000ff, // Red
161+
0xff000000, // Green
162+
0x0000ff00, // Blue
163+
0x00ff0000, // Alpha
164+
true, // Alpha Premultiplied
165+
DataBuffer.TYPE_INT
166+
);
167+
WritableRaster raster = colorModel.createCompatibleWritableRaster(SIZE,
168+
SIZE);
169+
return new BufferedImage(colorModel, raster, true, null);
170+
}
171+
172+
private static BufferedImage TYPE_4BYTE_RGBA_PRE() {
173+
ColorSpace cs = ColorSpace.getInstance(ColorSpace.CS_sRGB);
174+
int[] nBits = {8, 8, 8, 8};
175+
int[] bOffs = {0, 1, 2, 3};
176+
ColorModel colorModel = new ComponentColorModel(cs, nBits, true, true,
177+
Transparency.TRANSLUCENT,
178+
DataBuffer.TYPE_BYTE);
179+
WritableRaster raster = Raster.createInterleavedRaster(DataBuffer.TYPE_BYTE,
180+
SIZE, SIZE,
181+
SIZE * 4, 4,
182+
bOffs, null);
183+
return new BufferedImage(colorModel, raster, true, null);
184+
}
185+
186+
private static BufferedImage TYPE_4BYTE_ABGR_PRE() {
187+
ColorSpace cs = ColorSpace.getInstance(ColorSpace.CS_sRGB);
188+
int[] nBits = {8, 8, 8, 8};
189+
int[] bOffs = {3, 2, 1, 0};
190+
ColorModel colorModel = new ComponentColorModel(cs, nBits, true, true,
191+
Transparency.TRANSLUCENT,
192+
DataBuffer.TYPE_BYTE);
193+
WritableRaster raster = Raster.createInterleavedRaster(DataBuffer.TYPE_BYTE,
194+
SIZE, SIZE,
195+
SIZE * 4, 4,
196+
bOffs, null);
197+
return new BufferedImage(colorModel, raster, true, null);
198+
}
199+
200+
private static BufferedImage TYPE_4BYTE_ARGB_PRE() {
201+
ColorSpace cs = ColorSpace.getInstance(ColorSpace.CS_sRGB);
202+
int[] nBits = {8, 8, 8, 8};
203+
int[] bOffs = {1, 2, 3, 0};
204+
ColorModel colorModel = new ComponentColorModel(cs, nBits, true, true,
205+
Transparency.TRANSLUCENT,
206+
DataBuffer.TYPE_BYTE);
207+
WritableRaster raster = Raster.createInterleavedRaster(DataBuffer.TYPE_BYTE,
208+
SIZE, SIZE,
209+
SIZE * 4, 4,
210+
bOffs, null);
211+
return new BufferedImage(colorModel, raster, true, null);
212+
}
213+
214+
private static BufferedImage TYPE_4BYTE_GABR_PRE() {
215+
ColorSpace cs = ColorSpace.getInstance(ColorSpace.CS_sRGB);
216+
int[] nBits = {8, 8, 8, 8};
217+
int[] bOffs = {3, 0, 2, 1};
218+
ColorModel colorModel = new ComponentColorModel(cs, nBits, true, false,
219+
Transparency.TRANSLUCENT,
220+
DataBuffer.TYPE_BYTE);
221+
WritableRaster raster = Raster.createInterleavedRaster(DataBuffer.TYPE_BYTE,
222+
SIZE, SIZE,
223+
SIZE * 4, 4,
224+
bOffs, null);
225+
return new BufferedImage(colorModel, raster, true, null);
226+
}
227+
228+
private static BufferedImage TYPE_4INT_ARGB_8bit_PRE() {
229+
ColorSpace cs = ColorSpace.getInstance(ColorSpace.CS_sRGB);
230+
int[] nBits = {8, 8, 8, 8};
231+
ColorModel colorModel = new ComponentColorModel(cs, nBits, true, true,
232+
Transparency.TRANSLUCENT,
233+
DataBuffer.TYPE_INT);
234+
WritableRaster raster = colorModel.createCompatibleWritableRaster(SIZE,
235+
SIZE);
236+
return new BufferedImage(colorModel, raster, true, null);
237+
}
238+
239+
private static BufferedImage TYPE_4USHORT_ARGB_8bit_PRE() {
240+
ColorSpace cs = ColorSpace.getInstance(ColorSpace.CS_sRGB);
241+
int[] nBits = {8, 8, 8, 8};
242+
ColorModel colorModel = new ComponentColorModel(cs, nBits, true, true,
243+
Transparency.TRANSLUCENT,
244+
DataBuffer.TYPE_USHORT);
245+
WritableRaster raster = colorModel.createCompatibleWritableRaster(SIZE,
246+
SIZE);
247+
return new BufferedImage(colorModel, raster, true, null);
248+
}
249+
250+
private static void fill(BufferedImage image) {
251+
// Graphics2D g = image.createGraphics();
252+
// g.setComposite(AlphaComposite.Src);
253+
for (int a = 0; a < SIZE; ++a) {
254+
for (int c = 0; c < SIZE; ++c) {
255+
Color c1 = new Color(a, c, c, a);
256+
// g.setColor(c1);
257+
//TODO CANNOT USE fillrect, does not work for custom types!
258+
// g.fillRect(c, a, 1, 1);
259+
image.setRGB(c,a , c1.getRGB());
260+
}
261+
}
262+
// g.dispose();
263+
}
264+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
/*
2+
* Copyright Amazon.com Inc. 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.
8+
*
9+
* This code is distributed in the hope that it will be useful, but WITHOUT
10+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12+
* version 2 for more details (a copy is included in the LICENSE file that
13+
* accompanied this code).
14+
*
15+
* You should have received a copy of the GNU General Public License version
16+
* 2 along with this work; if not, write to the Free Software Foundation,
17+
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18+
*
19+
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20+
* or visit www.oracle.com if you need additional information or have any
21+
* questions.
22+
*/
23+
24+
import java.awt.color.ColorSpace;
25+
import java.awt.image.BufferedImage;
26+
import java.awt.image.ColorConvertOp;
27+
import java.awt.image.SampleModel;
28+
29+
/**
30+
* @test
31+
* @bug 8279216
32+
* @summary behavior checked by this test is not specified, this test just
33+
* defends against accidental changes
34+
*/
35+
public final class SkipSampleModel {
36+
37+
private static int[] TYPES = {
38+
BufferedImage.TYPE_INT_RGB,
39+
BufferedImage.TYPE_INT_ARGB,
40+
BufferedImage.TYPE_INT_ARGB_PRE,
41+
BufferedImage.TYPE_INT_BGR,
42+
BufferedImage.TYPE_3BYTE_BGR,
43+
BufferedImage.TYPE_4BYTE_ABGR,
44+
BufferedImage.TYPE_4BYTE_ABGR_PRE,
45+
BufferedImage.TYPE_USHORT_565_RGB,
46+
BufferedImage.TYPE_USHORT_555_RGB,
47+
BufferedImage.TYPE_BYTE_GRAY,
48+
BufferedImage.TYPE_USHORT_GRAY,
49+
BufferedImage.TYPE_BYTE_BINARY,
50+
BufferedImage.TYPE_BYTE_INDEXED
51+
};
52+
53+
private static final ColorSpace[] CSs = {
54+
ColorSpace.getInstance(ColorSpace.CS_CIEXYZ),
55+
ColorSpace.getInstance(ColorSpace.CS_GRAY),
56+
ColorSpace.getInstance(ColorSpace.CS_LINEAR_RGB),
57+
ColorSpace.getInstance(ColorSpace.CS_PYCC),
58+
ColorSpace.getInstance(ColorSpace.CS_sRGB)
59+
};
60+
61+
public static void main(String[] args) {
62+
for (ColorSpace cs : CSs) {
63+
ColorConvertOp op = new ColorConvertOp(cs, null);
64+
for (int srcType : TYPES) {
65+
for (int dstType : TYPES) {
66+
BufferedImage src = new BufferedImage(1, 1, srcType) {
67+
@Override
68+
public SampleModel getSampleModel() {
69+
throw new AssertionError();
70+
}
71+
};
72+
BufferedImage dst = new BufferedImage(1, 1, dstType) {
73+
@Override
74+
public SampleModel getSampleModel() {
75+
throw new AssertionError();
76+
}
77+
};
78+
op.filter(src, dst);
79+
}
80+
}
81+
}
82+
}
83+
}

0 commit comments

Comments
 (0)
Please sign in to comment.