1

我试图将图像上任何给定像素的 RGB 值转换为 12 位二进制,每个通道由 4 位表示。例如,如果一个像素在“255”处有红色通道,或者二进制“11111111”。我希望将其转换为“1111”。

我有一个代码工作,但它相当慢,我想知道是否有更好的方法来做到这一点。

这就是我所做的。

  1. 我使用 getRGB(x, y) 方法来获取一个像素的 RGB 值。例如-4278864
  2. 我将其转换为 3 个单独的通道,例如 r 190 g 181 b 176
  3. 我将它除以 16 以获得相当于 4 位表示的整数
  4. 我将数字转换为二进制。
  5. 如果生成的二进制小于 4 位,则在二进制前面添加 0。
  6. 连接到 12 位二进制以表示 12 位颜色输出。例如 101110111011

这是我的代码:

import java.awt.Component;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;

public class LoadImageApp extends Component {
    private static int[] rgbArray;
    private static double bitPerColor = 4.0;

    public static void main(String[] args) {

       BufferedImage img = null;
       String fileName = "Image.jpg";

       try {
           //Read in new image file
           img = ImageIO.read(new File("src/"+fileName));
       } 
       catch (IOException e){
       }

       if (img == null) {
             System.out.println("No image loaded");
        } 
       else {

                //Get RGB Value
                int val = img.getRGB(500, 500);
                System.out.println("rgbValue from getRGB is: " + val);


                //Convert to three separate channels
                int a = (0xff000000 & val) >>> 24;
                int r = (0x00ff0000 & val) >> 16;
                int g = (0x0000ff00 & val) >> 8;
                int b = (0x000000ff & val);

                System.out.println("rgbValue in RGB is: ");
                System.out.println("a " + a + " r " + r + " g " + g + " b " + b);

                double power = Math.pow(2.0, bitPerColor);
                //Convert each channel to binary
                String r4bit = Integer.toBinaryString((int)(r/(power)));
                String g4bit = Integer.toBinaryString((int)(g/(power)));
                String b4bit = Integer.toBinaryString((int)(b/(power)));



                //Convert concatonate 0's in front to get desired bit count
                int rDifference = (int)bitPerColor - r4bit.length();
                int gDifference = (int)bitPerColor - g4bit.length();
                int bDifference = (int)bitPerColor - b4bit.length();


                for (int i = rDifference; i > 0; i--){
                    r4bit="0"+r4bit;}

                for (int i = gDifference; i > 0; i--){
                    g4bit = "0"+g4bit;}

                for (int i = bDifference; i > 0; i--){
                    b4bit = "0"+b4bit;}

                //Concatonate three channel together to form one binary
                String rgbValue = r4bit + g4bit + b4bit;

                System.out.println("rgbValue in binary is: " + rgbValue);


           }     
       }
}

这一切都可以按需要正常工作。然而,读取一个像素需要 2-3 秒,这真的非常非常难看,而且速度很慢。我希望使用代码一次读取图像的一部分,但我可以用 AGES 对它进行成像。

因此,我们将不胜感激任何帮助。

提前致谢。

4

4 回答 4

5

您的原始代码(十六进制)是0x00rrggbb. 您想将其转换为0x00000rgb. 这将做到:

int rgb24 = ....;
int rgb12 = (rgb24 & 0x00f00000) >> 12 + 
            (rgb24 & 0x0000f000) >> 8  + 
            (rgb24 & 0x000000f0) >> 4;

如果你想“四舍五入”到最接近的颜色而不是截断你可以这样做:

int r = (rgb24 & 0x00ff0000);
int g = (rgb24 & 0x0000ff00);
int b = (rgb24 & 0x000000ff);
r += (r >= 0x00f00000) ? 0x00080000 : 0;
g += (g >= 0x0000f000) ? 0x00000800 : 0;
b += (b >= 0x000000f0) ? 0x00000008 : 0;
int rgb12 = (r & 0x00f00000) >> 12 + (g & 0x0000f000) >> 8 + (b & 0x000000f0) >> 4;

这会向上取整,但前提是高 4 位还不是 1111(当您有溢出的风险时)。

于 2012-05-11T02:51:39.510 回答
2

有一些事情可能会减慢速度,例如...

  1. 分别从BufferedImage
  2. 在循环中多次使用Math.pow()和可能Integer.toBinaryString()
  3. 一直使用Strings,而不是像intor之类的数字short。如果你想要一个,也许在最后从-->进行String一次转换。shortString

我可能会尝试做这样的事情......

// Get all the pixels
int pixelCount = imageWidth*imageHeight;
int[] pixelArray = new int[pixelCount];
img.getRGB(0,0,imageWidth,imageHeight,pixelArray,0,1);

// For storing the 4-bit data
short[] convertedArray = new short[pixelCount];

// calculate the conversion factor a single time
double power = Math.pow(2.0, bitPerColor);

// Loop over the pixels
for (int p=0;p<pixelCount;p++){
    int pixel = pixelArray[p];

    // Convert into separate channels
    int a = (0xff000000 & val) >>> 24;
    int r = (0x00ff0000 & val) >> 16;
    int g = (0x0000ff00 & val) >> 8;
    int b = (0x000000ff & val);

    // Convert to 4-bit
    a /= power;
    r /= power;
    g /= power;
    b /= power;

    // Create the short for the pixel (4 channels * 4 bits = a 2-byte short)
    short newPixel = (a & 0x0000000f) << 24 | (r & 0x0000000f) << 16 | (g & 0x0000000f) << 8 | (b & 0x0000000f);
    convertedArray[p] = newPixel;

    // If you want to have the value as a String, do it here.
    String binary = Short.toBinaryString(newPixel);
}
于 2012-05-11T02:51:03.237 回答
0

顺便说一句,我注意到您使用字符串加运算符进行追加。我知道这是简单的代码,但是在循环中需要一些工作。运算符调用构造函数来执行其功能。循环到底有多大?

可能不使用加号运算符,而是使用其他类,如 StringBuilder 或与之等效的 Java。告诉我你最终使用哪个类。通过计时代码进行调查!

当您想查看可能的瓶颈时,请先查看堆或堆栈中的 LOOPS,因为可能有很多代码执行。这应该是某处的编码规则......

试试看,玩得开心。请投票给我的答案。我需要一个徽章和更多积分:-)

汤米奎

于 2012-05-11T02:44:51.923 回答
-1

使用 SetRGB 设置时我在 RGB 中收集的值是否会为我提供二进制图像,其中图像存在的区域为白色,而图像不存在的区域为黑色?

于 2013-11-15T06:15:04.513 回答