Чтение цветов BGR из растрового изображения на C - PullRequest
3 голосов
/ 19 марта 2011

Я пытался получить значения RGB из 24-битного файла BMP.Изображение, которое я использую, является крошечным изображением, все красные, поэтому конфигурация BGR всех пикселей должна быть B:0 G:0 R:255.Я делаю это:

int main(int argc, char **argv)
{
    principal();
    return 0;
}

typedef struct {
    unsigned char blue;
    unsigned char green;
    unsigned char red;
} rgb;

typedef struct {
    int ancho, alto;
    rgb *pixeles[MAX_COORD][MAX_COORD];
} tBitmapData;

void principal()
{

    FILE *fichero;
    tBitmapData *bmpdata = (tBitmapData *) malloc(sizeof(tBitmapData));
    rgb *pixel;
    int i, j, num_bytes;
    unsigned char *buffer_imag;
    char nombre[] = "imagen.bmp";
    fichero = fopen(nombre, "r");
    if (fichero == NULL)
            puts("No encontrado\n");
    else {
            fseek(fichero, 18, SEEK_SET);
            fread(&(bmpdata->ancho), sizeof((bmpdata->ancho)), 4, fichero);
            printf("Ancho: %d\n", bmpdata->ancho);
            fseek(fichero, 22, SEEK_SET);
            fread(&(bmpdata->alto), sizeof((bmpdata->alto)), 4, fichero);
            printf("Alto: %d\n", bmpdata->alto);
    }

    num_bytes = (bmpdata->alto * bmpdata->ancho * 3);
    fseek(fichero, 54, SEEK_SET);
    for (j = 0; j < bmpdata->alto; j++) {
            printf("R   G   B Fila %d\n", j + 1);
            for (i = 0; i < bmpdata->ancho; i++) {
                    pixel =
                        (rgb *) malloc(sizeof(rgb) * bmpdata->alto *
                                       bmpdata->ancho * 3);
                    fread(pixel, 1, sizeof(rgb), fichero);
                    printf("Pixel %d: B: %3d G: %d R: %d \n", i + 1,
                           pixel->blue, pixel->green, pixel->red);
            }
    }
    fclose(fichero);
}

Проблема в том, что когда я их печатаю, первые пиксели в порядке, B:0 G:0 R:255, но затем они начинают меняться на B:0 G:255 R:0, а затем на B:255 G:0 R:0.Если ширина составляет 10 пикселей, то изменение происходит каждые 10 пикселей.

Ответы [ 2 ]

5 голосов
/ 19 марта 2011

В формате файла BMP каждая строка данных пикселя может быть дополнена для округления до кратного 4 байта.

Если у вас есть 10 24-битных пикселей, это 30 байтов, за которыми следуют 2 байта заполнения. Ваш код не пропускает отступы.

2 голосов
/ 19 марта 2011

Я думаю, что ваши fread(3) звонки неверны:

        fread(&(bmpdata->ancho), sizeof((bmpdata->ancho)), 4, fichero);

Это просит прочитать 4*sizeof((bmpdata->ancho)) байт в int. Я предполагаю, что sizeof((bmpdata->ancho)) возвращает 4, так что я думаю, что вы набрасываетесь на несвязанную память этими двумя вызовами. Измените 4 на 1 - вы читаете только один элемент.

Вы никогда не используете num_bytes; удали это. Неиспользуемый код делает размышления об используемом коде намного сложнее. :)

Вы выделяете в три раза больше памяти, чем вам необходимо:

                pixel =
                    (rgb *) malloc(sizeof(rgb) * bmpdata->alto *
                                   bmpdata->ancho * 3);

3 выглядит как попытка учесть каждый из красного, зеленого, синего в вашей rgb структуре, но sizeof(rgb) уже знает правильный размер структуры. (Это может быть 4 байт, для удобного выравнивания для 32-разрядных процессоров, или это может быть 12 байт, опять же для выравнивания (каждый char на своей собственной 4 байтовой границе), или, может быть, даже 24 байты в 64-битных системах, которым действительно нравится работать с данными, выровненными по 8 границам байтов.)

И последнее, что я отмечу:

                fread(pixel, 1, sizeof(rgb), fichero);

Поскольку компилятору C разрешено вставлять дыры в структуры, вы не можете предполагать, что формат на диске соответствует определению структуры в памяти. Вам нужно либо использовать атрибут GNU C extension __packed__, либо прочитать данные из библиотеки или структур, предназначенных для формата bmp . Если это забавный проект для вас, то обязательно попробуйте маршрут __packed__: если он работает, хорошо, если он не работает, надеюсь, вы сможете узнать, почему нет, и переписать свой код, чтобы загрузить каждый элемент структурировать вручную. Если вы просто пытаетесь получить что-то, что может правильно анализировать растровые изображения, вы можете попытаться найти некоторые заранее написанные библиотеки, которые уже правильно анализируют изображения.

(И да, ОЧЕНЬ ВАЖНО для правильного разбора изображения; CVE содержит список искаженных образов эксплойтов , которые позволяют злоумышленникам контролировать программы, многие из них могут использоваться удаленно .)

...