我尝试将图像转换为RGB565格式。 我读了这张图片:
BufferedImage bufImg = ImageIO.read(imagePathFile);
sendImg = new BufferedImage(CONTROLLER_LCD_WIDTH/*320*/, CONTROLLER_LCD_HEIGHT/*240*/, BufferedImage.TYPE_USHORT_565_RGB);
sendImg.getGraphics().drawImage(bufImg, 0, 0, CONTROLLER_LCD_WIDTH/*320*/, CONTROLLER_LCD_HEIGHT/*240*/, null);
就是这样:
然后我将其转换为RGB565:
int numByte=0;
byte[] OutputImageArray = new byte[CONTROLLER_LCD_WIDTH*CONTROLLER_LCD_HEIGHT*2];
int i=0;
int j=0;
int len = OutputImageArray.length;
for (i=0;i<CONTROLLER_LCD_WIDTH;i++) {
for (j=0;j<CONTROLLER_LCD_HEIGHT;j++) {
Color c = new Color(sendImg.getRGB(i, j));
int aRGBpix = sendImg.getRGB(i, j);
int alpha;
int red = c.getRed();
int green = c.getGreen();
int blue = c.getBlue();
//RGB888
red = (aRGBpix >> 16) & 0x0FF;
green = (aRGBpix >> 8) & 0x0FF;
blue = (aRGBpix >> 0) & 0x0FF;
alpha = (aRGBpix >> 24) & 0x0FF;
//RGB565
red = red >> 3;
green = green >> 2;
blue = blue >> 3;
//A pixel is represented by a 4-byte (32 bit) integer, like so:
//00000000 00000000 00000000 11111111
//^ Alpha ^Red ^Green ^Blue
//Converting to RGB565
short pixel_to_send = 0;
int pixel_to_send_int = 0;
pixel_to_send_int = (red << 11) | (green << 5) | (blue);
pixel_to_send = (short) pixel_to_send_int;
//dividing into bytes
byte byteH=(byte)((pixel_to_send >> 8) & 0x0FF);
byte byteL=(byte)(pixel_to_send & 0x0FF);
//Writing it to array - High-byte is second
OutputImageArray[numByte]=byteH;
OutputImageArray[numByte+1]=byteL;
numByte+=2;
}
}
然后我尝试从结果数组OutputImageArray
中恢复它:
i=0;
j=0;
numByte=0;
BufferedImage NewImg = new BufferedImage(CONTROLLER_LCD_WIDTH, CONTROLLER_LCD_HEIGHT, BufferedImage.TYPE_USHORT_565_RGB);
for (i=0;i<CONTROLLER_LCD_WIDTH;i++) {
for (j=0;j<CONTROLLER_LCD_HEIGHT;j++) {
int curPixel=0;
int alpha=0x0FF;
int red;
int green;
int blue;
byte byteL=0;
byte byteH=0;
byteH = OutputImageArray[numByte];
byteL = OutputImageArray[numByte+1];
curPixel= (byteH << 8) | (byteL);
//RGB565
red = (curPixel >> (6+5)) & 0x01F;
green = (curPixel >> 5) & 0x03F;
blue = (curPixel) & 0x01F;
//RGB888
red = red << 3;
green = green << 2;
blue = blue << 3;
//aRGB
curPixel = 0;
curPixel = (alpha << 24) | (red << 16) | (green << 8) | (blue);
NewImg.setRGB(i, j, curPixel);
numByte+=2;
}
}
我输出这个恢复的图像。但我发现它看起来很糟糕。
我预计图片质量会丢失。 但正如我所想,这张照片必须具有与前一张照片几乎相同的质量。这样对吗? 我的代码是对的吗?
答案 0 :(得分:1)
您看到这些黄色假象的原因仅仅是byteL
覆盖来自byteH
的位的负值,其中包含红色和(部分)绿色频道。让我解释一下。
请记住,如果一个字节中的最高位设置为1,则该值被视为负数(-128到-1而不是128到255),并将其转换为int
所有额外的高值-bits设置为1以保存相同的值(-128到-1)。
在你的程序中,当应用OR位运算符byteH
时,设置为1的这些额外位与|
中的值直接冲突,覆盖(饱和)红色和(部分)您试图提取和显示的绿色值。
curPixel = (byteH << 8) | (byteL); // BUG: issue with negative byteL values
解决方案是应用AND掩码以确保在应用OR位运算符之前消除任何不需要的位。
curPixel = byteL & 0xFF; // Convert byte to int to be within [0 , 255]
curPixel = (byteH << 8) | curPixel; // Apply OR bit-operator