【问题标题】:I'm reading the RGB values of pixels from a BMP file and not getting the correct values我正在从 BMP 文件中读取像素的 RGB 值,但没有得到正确的值
【发布时间】:2020-01-09 19:09:34
【问题描述】:

我遵循此链接read pixel value in bmp file 上的代码能够读取像素的 RGB 值,当我将整个图像作为一种颜色并读取随机像素的值时,它们是正确的。在此之后,我尝试制作它,因此该功能也将尝试找出有多少种独特的颜色,因此我在图像中添加了一个具有不同颜色的框,但该功能仍然只能找到一种颜色。我想知道我是否可能没有查看 BMP 中包含的所有字节,但我不确定那会是怎样的,因为我是新手。

为了确保代码没有找到不同颜色的像素但未能将它们添加到唯一像素列表中,我尝试在找到与始终找到但没有输出的颜色不同时打印输出来自它。

struct Color {
int R = -1;
int G = -1;
int B = -1;
};

unsigned char* readBMP(char* filename) {
int i;
FILE* f = fopen(filename, "rb");
unsigned char info[54];
fread(info, sizeof(unsigned char), 54, f);

int width = *(int*)&info[18]; //the reason *(int*) is used here because there's an integer stored at 18 in the array that indicates how wide the BMP is
int height = *(int*)&info[22]; // same reasoning for *(int*)

int size = 3 * width * height;
unsigned char* data = new unsigned char[size];
fread(data, sizeof(unsigned char), size, f);
fclose(f);

// windows has BMP saved as BGR tuples and this switches it to RGB
for(i = 0; i < size; i += 3){
    unsigned char tmp = data[i];
    data[i] = data[i+2];
    data[i+2] = tmp;
}

i = 0; // i is the x value of the pixel that is having its RGB values checked
int j = 0; // j is the y value of the pixel that is having its RGB values checked
unsigned char R = data[3 * (i * width + j)]; // value of R of the pixel at (i,j)
unsigned char G = data[3 * (i * width + j) + 1]; // value of G of the pixel at (i,j)
unsigned char B = data[3 * (i * width + j) + 2]; // value of B of the pixel at (i,j)

std::cout << "value of R is " << int(R);
std::cout << " value of G is " << int(G);
std::cout << " value of B is " << int(B);

Color num_colors[5];
int count;
int z;
int flag;
int iterator;
int sum;
for(count = 0; count < size; count += 1){
    unsigned char R = data[3 * (i * width + j)];
    unsigned char G = data[3 * (i * width + j) + 1];
    unsigned char B = data[3 * (i * width + j) + 2];
    sum = int(R) + int(G) + int(B);
    if(sum != 301) {// 301 is the sum of the RGB values of the color that the program does manage to find
        std::cout << sum;
    }
    flag = 0;
    for(z = 0; z < 5; z += 1){
        if(num_colors[z].R == R && num_colors[z].G == G && num_colors[z].B == B){
            flag = 1;
        }
    }
    if(flag == 1){
        continue;
    }
    iterator = 0;
    while(num_colors[iterator].R != -1){
        iterator += 1;
    }
    num_colors[iterator].R = R;
    num_colors[iterator].G = G;
    num_colors[iterator].B = B;
}

int number = 0;
for(int r = 0; r < 5; r += 1){
    std::cout << "\nValue of R here: " << num_colors[r].R;
    if(num_colors[r].R != -1){
        number += 1;
    }
}
std::cout << "\nNumber of colors in image: " << number;
return data;
}

https://imgur.com/a/dXllIWL 这是我正在使用的图片,所以应该找到两种颜色,但代码只找到红色像素。

【问题讨论】:

  • 这是 BMP 的 OS/2 格式。如果这很重要。
  • 保重。这段代码玩得又快又松。 int width = *(int*)&amp;info[18]; 可能有效,但是...我们不知道 info 是否有礼貌地对齐,如果是,那么字节 18 可能不是(不容易被 4 整除)。另外,您必须绝对确定 int 是 32 位。最好的标准保证是 int 至少 16 位并且不大于 long

标签: c++ image bitmap bmp


【解决方案1】:

您的问题是您总是检查 (0,0) 处的 RGB 值

i = 0; // i is the x value of the pixel that is having its RGB values checked
int j = 0; // j is the y value of the pixel that is having its RGB values checked
...
for(count = 0; count < size; count += 1){
    unsigned char R = data[3 * (i * width + j)];
    unsigned char G = data[3 * (i * width + j) + 1];
    unsigned char B = data[3 * (i * width + j) + 2];

ij 定义了您正在检查的像素的 X 和 Y 位置,但请注意,您永远不会在循环中更改它们。你的循环会一遍又一遍地做同样的事情。您可能想要的是一个双循环,遍历图像中的所有坐标:

   for(int y=0; y<height; y++)
       for(int x=0; x<width; x++){
          unsigned char R = data[3 * (y * width + x) + 0];
          unsigned char G = data[3 * (y * width + x) + 1];
          unsigned char B = data[3 * (y * width + x) + 2];

【讨论】:

  • 啊,对不起,我刚刚意识到这一点并来到这里进行相应的编辑,我现在有那个设置,但我得到这个退出代码 -1073741819 (0xC0000005) 所以我会尝试排序下一个。
  • @HoneyBunchers 0xC0000005 是“嘿!那段记忆不属于你!啪!”的代码在调试器中运行程序。当错误导致程序崩溃时,调试器将为您提供检查程序状态的机会。如果崩溃不在您的代码中,请检查回溯以找出您上次触摸它的位置并检查使用的参数。如果您在代码中崩溃,请调查程序崩溃时使用了哪些变量。其中之一肯定是错误的。找出错误的原因可能需要更长的时间。
  • 啊,好的,谢谢!我认为这与内存有关,但我无法发现自己​​通过 try catch 访问我的数组越界,所以我有一些工作要尝试解决。
  • @HoneyBunchers 0xC0000005 是 C++ 以下内容捕获错误的结果。它不会导致带有 try/catch 的异常拦截。使用像std::vectorstd::array 这样的库容器,您可以将[index] 替换为.at(index) 并进行边界检查,这将引发异常。有时你也可以使用像 valgrind 这样的调试工具。在这种情况下,由于程序会礼貌地为您崩溃,您可以在标准调试器中运行并等待崩溃。除非代码在调试器中运行后立即拉出 Heisenbug。发生这种情况时糟透了。
猜你喜欢
  • 1970-01-01
  • 2013-04-10
  • 1970-01-01
  • 1970-01-01
  • 2012-03-06
  • 1970-01-01
  • 2012-09-17
  • 2021-10-08
  • 2019-03-11
相关资源
最近更新 更多