0

I followed the code at this link read pixel value in bmp file to be able to read the RGB values of pixels and when I have the entire image as one color and read a random pixel's values they are correct. After this I tried to make it so the function would also try and find how many unique colors there were so I added a box with a different color to the image but the function still only finds one color. I'm wondering if maybe I'm somehow not looking at all the bytes contained in the BMP but I'm not sure how that would be as I'm new to trying this stuff.

To make sure the code wasn't finding different colored pixels but failing to add them to the list of unique pixels I tried printing output when a color is found that is different from the one that is always found but no output ever came from it.

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://i.stack.imgur.com/QTZBx.jpg This is the picture I'm using so there should be two colors found but the code only finds red pixels.

Daniel A. White
  • 187,200
  • 47
  • 362
  • 445
HoneyBunchers
  • 45
  • 1
  • 7
  • That's the OS/2 format of a BMP. If that matters. – Eljay Sep 07 '19 at 01:20
  • Take care. This code is playing fast and loose. `int width = *(int*)&info[18];` is a probably works,but... We don't know if `info` is politely aligned and if it is, then byte 18 probably isn't (not easily divisible by 4). Plus you have to be absolutely certain that `int` is 32 bits. The best the standard guarantees is `int` is at least 16 bits and no larger than `long` – user4581301 Sep 07 '19 at 01:25

1 Answers1

0

Your problem is that you are always checking the RGB values at (0,0)

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];

i and j defines the X and Y position of the pixel you are checking, but notice that you never change those in the loop. Your loop will keep doing the same thing over and over again. What you probably want is a double loop, going through all coordinates in your image:

   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];
Sebastian Wahl
  • 324
  • 4
  • 11
  • Ah I'm sorry I just realized that and came here to edit accordingly, I have that setup now but I'm getting this exit code -1073741819 (0xC0000005) so I'll try to sort that out next. – HoneyBunchers Sep 07 '19 at 01:56
  • @HoneyBunchers 0xC0000005 is the code for "Hey! That memory doesn't belong to you! SLAP!" Run the program in a debugger. When the erro causes the program to crash, the debugger will give you the opportunity to inspect the program state. If the crash is not in your code, check the backtrace to find out where you last touched it and check the parameters used. If you crash in your code, investigate what variables the program was using when it went down. One of them is certainly wrong. Finding out why it's wrong might take a little longer. – user4581301 Sep 07 '19 at 03:04
  • Ah okay thank you! I figured it was something related to memory but I wasn't able to find myself accessing my arrays out of bounds with a try catch so I've got some work to try and figure it out. – HoneyBunchers Sep 07 '19 at 05:32
  • @HoneyBunchers 0xC0000005 is the result of the stuff below C++ trapping the error. It doesn't result in an exception intercept-able with a try/catch. With a library container like`std::vector` or `std::array` you can replace `[index]` with `.at(index)` and get bounds checking that will throw an exception. Sometimes you can also use a debugging tool like valgrind. In this case since the program politely crashes for you, you can run in a standard debugger and wait for the crash. Unless the code pulls a Heisenbug as soon as you run it in a debugger. Sucks when that happens. – user4581301 Sep 07 '19 at 06:12