Java图像转换为RGB565

时间:2011-11-30 00:45:38

标签: java image rgb

我尝试将图像转换为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);

就是这样:

picture before convertation

然后我将其转换为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;

    }
}

我输出这个恢复的图像。但我发现它看起来很糟糕。

enter image description here

我预计图片质量会丢失。 但正如我所想,这张照片必须具有与前一张照片几乎相同的质量。这样对吗? 我的代码是对的吗?

1 个答案:

答案 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