如何使用非 ARGB 颜色空间设置 Java BufferedImages 中的像素?
How can I set pixels in Java BufferedImages using non-ARGB color spaces?
我正在编写一个需要使用 16 位“5-5-5”RGB 颜色(即,每种颜色 5 位和一位填充)的应用程序。为了处理这些图像,我使用了 AWT 提供的 BufferedImage class。 BufferedImage class 通过采用 ColorModel 对象或预定义图像类型常量特别允许使用非 RGB 颜色 space - 其中之一是我使用的 5-5-5 像素格式需要。
我的问题是:BufferedImage“setRGB()”方法在其描述中指出所提供的颜色值“假定为默认 RGB 颜色模型 TYPE_INT_ARGB 和默认 sRGB 颜色 space"(根据 BufferedImage 文档页面)。似乎也没有其他方法接受为不同颜色 space 设计的值。
有没有办法直接用 BufferedImage 使用我的非标准颜色 space,或者我是否必须依赖 class 的内部颜色转换机制来处理我所有的颜色?(或者我只是 misreading/misunderstanding 了解 class 的工作原理?)
BufferedImage.TYPE_USHORT_555_RGB
仍然使用完全标准的 RGB 颜色 space(实际上,它使用 sRGB
),所以我认为不会有不同的 颜色 space就是你要找的。
如果要在Java中进行绘画或其他操作,只需使用setRGB/getRGB()
和createGraphics()/Grapics2D
等常规方法即可。所有内容都将为您正确地转换为打包的 USHORT_555_RGB
格式。
例如:
BufferedImage image = new BufferedImage(w, h, BufferedImage.TYPE_USHORT_555_RGB);
// Do some custom painting
Graphics2D g = image.createGraphics();
g.drawImage(otherImage, 0, 0, null); // image type here does not matter
g.setColor(Color.ORANGE); // Color in sRGB, but does not matter
g.fillOval(0, 0, w, h);
g.dispose();
image.setRGB(0, h/2, w, 1, new int[w]); // Silly way to create a horizontal black line at the center of the image... Don't do this, use fillRect(0, h/2, 1, w)! ;-)
// image will still be USHORT_555_RGB *internally*
但是,如果您有 USHORT_555_RGB
格式的像素数据(即来自外部 library/api/service),将这些值直接设置为 raster/databuffer.或者,如果您需要将像素值传回相同的 library/api/service.
例如,使用 Raster
:
BufferedImage image = new BufferedImage(w, h, BufferedImage.TYPE_USHORT_555_RGB);
// Some fictional API. It's assumed that data.length == w * h
short[] apiPixels = api.getPixelsUSHORT_555_RGB(w, h);
WritableRaster raster = image.getRaster();
// Set short values to image
raster.setDataElements(0, 0, w, h, apiPixels);
// Get short values from image
short[] pixels = (short[]) raster.getDataElements(0, 0, w, h, null); // TYPE_USHORT_555_RGB -> always short[]
api.setPixels(pixels, w, h); // Another fictional API
或者,也可以使用 DataBuffer
:
BufferedImage image = new BufferedImage(w, h, BufferedImage.TYPE_USHORT_555_RGB);
// Some fictional API. It's assumed that data.length == w * h
short[] apiPixels = api.getPixelsUSHORT_555_RGB(w, h);
DataBufferUShort buffer = (DataBufferUShort) image.getRaster().getDataBuffer(); // TYPE_USHORT_555_RGB -> always DataBufferUShort
// Set short values to image
System.arraycopy(apiPixels, 0, buffer.getData(), 0, apiPixels.length);
// Get short values from image
api.setPixels(buffer.getData(), w, h);
在大多数情况下,使用哪种方法并不重要,但第一种方法(仅使用 Raster
)可能会保持对图像的管理,这将使图像 显示 在 Java 过程中在屏幕上更快。
PS:如果不同的颜色 space 确实是您所需要的(即来自外部 library/api/service 的像素阵列使用不同的颜色 space,并且您需要查看此颜色 space 中的像素),您可以使用自定义颜色 space 在 USHORT_555_RGB
样式中创建 BufferedImage
] 像这样:
// Either use one of the built-in color spaces, or load one from disk
ColorSpace colorSpace = ColorSpace.getInstance(ColorSpace.CS_LINEAR_RGB);
ColorSpace colorSpaceToo = new ICC_ColorSpace(ICC_Profile.getInstance(Files.newInputStream(new File("/path/to/custom_rgb_profile.icc").toPath())));
// Create a color model using your color space, TYPE_USHORT and 5/5/5 mask, no transparency
ColorModel colorModel = new DirectColorModel(colorSpace, 15, 0x7C00, 0x03E0, 0x001F, 0, false, DataBuffer.TYPE_USHORT);
// And finally, create an image from the color model and a compatible raster
BufferedImage imageToo = new BufferedImage(colorModel, colorModel.createCompatibleWritableRaster(w, h), colorModel.isAlphaPremultiplied(), null);
请记住,由于 Java2D 图形操作和 setRGB/getRGB
仍在使用 sRGB,现在对图像的所有操作都将在颜色 space 和颜色之间来回转换sRGB。性能不会那么好。
我正在编写一个需要使用 16 位“5-5-5”RGB 颜色(即,每种颜色 5 位和一位填充)的应用程序。为了处理这些图像,我使用了 AWT 提供的 BufferedImage class。 BufferedImage class 通过采用 ColorModel 对象或预定义图像类型常量特别允许使用非 RGB 颜色 space - 其中之一是我使用的 5-5-5 像素格式需要。
我的问题是:BufferedImage“setRGB()”方法在其描述中指出所提供的颜色值“假定为默认 RGB 颜色模型 TYPE_INT_ARGB 和默认 sRGB 颜色 space"(根据 BufferedImage 文档页面)。似乎也没有其他方法接受为不同颜色 space 设计的值。
有没有办法直接用 BufferedImage 使用我的非标准颜色 space,或者我是否必须依赖 class 的内部颜色转换机制来处理我所有的颜色?(或者我只是 misreading/misunderstanding 了解 class 的工作原理?)
BufferedImage.TYPE_USHORT_555_RGB
仍然使用完全标准的 RGB 颜色 space(实际上,它使用 sRGB
),所以我认为不会有不同的 颜色 space就是你要找的。
如果要在Java中进行绘画或其他操作,只需使用setRGB/getRGB()
和createGraphics()/Grapics2D
等常规方法即可。所有内容都将为您正确地转换为打包的 USHORT_555_RGB
格式。
例如:
BufferedImage image = new BufferedImage(w, h, BufferedImage.TYPE_USHORT_555_RGB);
// Do some custom painting
Graphics2D g = image.createGraphics();
g.drawImage(otherImage, 0, 0, null); // image type here does not matter
g.setColor(Color.ORANGE); // Color in sRGB, but does not matter
g.fillOval(0, 0, w, h);
g.dispose();
image.setRGB(0, h/2, w, 1, new int[w]); // Silly way to create a horizontal black line at the center of the image... Don't do this, use fillRect(0, h/2, 1, w)! ;-)
// image will still be USHORT_555_RGB *internally*
但是,如果您有 USHORT_555_RGB
格式的像素数据(即来自外部 library/api/service),将这些值直接设置为 raster/databuffer.或者,如果您需要将像素值传回相同的 library/api/service.
例如,使用 Raster
:
BufferedImage image = new BufferedImage(w, h, BufferedImage.TYPE_USHORT_555_RGB);
// Some fictional API. It's assumed that data.length == w * h
short[] apiPixels = api.getPixelsUSHORT_555_RGB(w, h);
WritableRaster raster = image.getRaster();
// Set short values to image
raster.setDataElements(0, 0, w, h, apiPixels);
// Get short values from image
short[] pixels = (short[]) raster.getDataElements(0, 0, w, h, null); // TYPE_USHORT_555_RGB -> always short[]
api.setPixels(pixels, w, h); // Another fictional API
或者,也可以使用 DataBuffer
:
BufferedImage image = new BufferedImage(w, h, BufferedImage.TYPE_USHORT_555_RGB);
// Some fictional API. It's assumed that data.length == w * h
short[] apiPixels = api.getPixelsUSHORT_555_RGB(w, h);
DataBufferUShort buffer = (DataBufferUShort) image.getRaster().getDataBuffer(); // TYPE_USHORT_555_RGB -> always DataBufferUShort
// Set short values to image
System.arraycopy(apiPixels, 0, buffer.getData(), 0, apiPixels.length);
// Get short values from image
api.setPixels(buffer.getData(), w, h);
在大多数情况下,使用哪种方法并不重要,但第一种方法(仅使用 Raster
)可能会保持对图像的管理,这将使图像 显示 在 Java 过程中在屏幕上更快。
PS:如果不同的颜色 space 确实是您所需要的(即来自外部 library/api/service 的像素阵列使用不同的颜色 space,并且您需要查看此颜色 space 中的像素),您可以使用自定义颜色 space 在 USHORT_555_RGB
样式中创建 BufferedImage
] 像这样:
// Either use one of the built-in color spaces, or load one from disk
ColorSpace colorSpace = ColorSpace.getInstance(ColorSpace.CS_LINEAR_RGB);
ColorSpace colorSpaceToo = new ICC_ColorSpace(ICC_Profile.getInstance(Files.newInputStream(new File("/path/to/custom_rgb_profile.icc").toPath())));
// Create a color model using your color space, TYPE_USHORT and 5/5/5 mask, no transparency
ColorModel colorModel = new DirectColorModel(colorSpace, 15, 0x7C00, 0x03E0, 0x001F, 0, false, DataBuffer.TYPE_USHORT);
// And finally, create an image from the color model and a compatible raster
BufferedImage imageToo = new BufferedImage(colorModel, colorModel.createCompatibleWritableRaster(w, h), colorModel.isAlphaPremultiplied(), null);
请记住,由于 Java2D 图形操作和 setRGB/getRGB
仍在使用 sRGB,现在对图像的所有操作都将在颜色 space 和颜色之间来回转换sRGB。性能不会那么好。