pba*_*pba 6 java arrays bufferedimage
我需要将BufferedImages(RGB,无伪影)转换为字节数组进行发送.在进行单元测试时,我偶然发现了一个问题,无论是BufferedImage我的期望还是我的代码.
甲BufferedImage转换再次相同的字节数组后转换为字节阵列和回收率.我认为它是相同的图像.但是,如果我将原始图像和看似相同的背面转换图像转换为灰度图像,这会给我完全不同的图像(不仅仅是一个字节,真的不同!).显然,我希望灰度图像是相同的,因为源是相同的.任何人都可以开导我吗?我有点不对劲吗?
我有一个完整的剥离示例.
import java.awt.BasicStroke;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.color.ColorSpace;
import java.awt.image.BufferedImage;
import java.awt.image.BufferedImageOp;
import java.awt.image.ColorConvertOp;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Random;
import javax.imageio.ImageIO;
public class GreyImageProblem {
private static Random random = new Random();
private static int randInt(int from, int to) {
return random.nextInt(to-from+1)+from;
}
private static java.awt.Color randColor() {
return new java.awt.Color(randInt(0,256*256*256));
}
// a random image with different RGB colors
public static BufferedImage genImage() {
int width = randInt(180, 640);
int height = randInt(120, 480);
BufferedImage im = new BufferedImage(width, height,
BufferedImage.TYPE_INT_RGB);
Graphics2D graphics = im.createGraphics();
graphics.setStroke(new BasicStroke(6));
Rectangle rectangle = new Rectangle(0, 0, width, height);
for (int i=0; i < 42; i+=1) {
int x = randInt(0, width), y = randInt(0, height);
int sw = randInt(0, width)/10, sh = randInt(0, height)/10;
graphics.setColor(randColor());
rectangle.setBounds(x, y, sw, sh);
graphics.draw(rectangle);
}
return im;
}
// make it grey
public static BufferedImage toGrey(BufferedImage im) {
ColorSpace cs = ColorSpace.getInstance(ColorSpace.CS_GRAY);
BufferedImageOp op = new ColorConvertOp(cs, null);
return op.filter(im, null);
}
// make it byte array
public static byte[] toByteArray(BufferedImage im) {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
try {
ImageIO.write(im, "png", baos);
baos.flush();
byte[] ret = baos.toByteArray();
baos.close();
return ret;
} catch (IOException e) {
throw new RuntimeException(e);
}
}
// make it an image again
public static BufferedImage fromByteArray(byte[] ba) {
InputStream in = new ByteArrayInputStream(ba);
try {
BufferedImage im = ImageIO.read(in);
return im;
} catch (IOException e) {
throw new RuntimeException(e);
}
}
public static boolean sameByteArray(byte[] a, byte[] b) {
if (a.length != b.length) {
System.out.format("sameByteArray: a.length=%d, b.length=%d\n",
a.length, b.length);
return false;
}
for (int i=0; i < a.length; i++) {
if (a[i] != b[i]) {
return false;
}
}
return true;
}
public static void main(String[] args) {
BufferedImage image = genImage();
byte[] imagebytes = toByteArray(image);
BufferedImage imageAgain = fromByteArray(imagebytes);
BufferedImage imageGrey = toGrey(image);
BufferedImage imageAgainGrey = toGrey(imageAgain);
if (sameByteArray(imagebytes, toByteArray(imageAgain))) {
System.out.println("Both are the same images");
}
if (!sameByteArray(toByteArray(imageGrey), toByteArray(imageAgainGrey))) {
System.out.println("AAAAAAaaaaaaaaaaahhhhhhhhhhhh");
System.out.println("Why they have different grey images!!!!");
}
}
}
Run Code Online (Sandbox Code Playgroud)
谢谢你的帮助.
请注意,BufferedImage.TYPE_INT_RGB 将 (R,G,B) 三元组编码为 int 值。当你想将用 int 值编码的 DataBuffer 转换为 byte 时,你可以这样做:
BufferedImage imint = new BufferedImage(N, N, BufferedImage.TYPE_INT_RGB) ;
BufferedImage imbyte = new BufferedImage(imint.getWidth(), imint.getHeight(), BufferedImage.TYPE_3BYTE_BGR) ;
int[] databufferint = ((DataBufferInt)imint.getRaster().getDataBuffer()).getData() ;
byte[] databufferbyte = ((DataBufferByte)imbyte.getRaster().getDataBuffer()).getData() ;
for (int i=0 ; i < databufferint.length ; i++)
{
int R = (databufferint[i] & 0xFF0000) >> 16 ;
int G = (databufferint[i] & 0x00FF00) >> 8 ;
int B = databufferint[i] & 0x0000FF ;
databufferbyte[i*3] = (byte)B ;
databufferbyte[i*3+1] = (byte)G ;
databufferbyte[i*3+2] = (byte)R ;
}
Run Code Online (Sandbox Code Playgroud)
因此,您将获得 3 字节(24 位)编码,而不是 int(32 位)编码,这可以节省 25% 的内存(未使用的 alpha 通道)。但这仍然是一种颜色编码/表示。如果从 RGB 到灰度,您可以使用 CIE 601 或 CIE 709 转换,但之后就无法返回(该操作不是双射)。
| 归档时间: |
|
| 查看次数: |
1023 次 |
| 最近记录: |