从位图读取颜色字节(RGB)

时间:2017-09-21 23:58:42

标签: c bitmap

我遇到的问题是我所做的代码应该以bmp(位图)格式显示图像每个像素的RGB颜色值的字节。

我知道在windows api中如何以更实际的方式使用位图,但由于我希望最终代码在操作系统方面是可移植的,我创建了结构,我只是阅读C的基础知识

以下是代码:

#include <stdio.h>
#include <stdlib.h>

unsigned char *readBMP(char *filename, int *size) {
    int width, height;
    unsigned char *data;
    unsigned char info[54];

    FILE *file = fopen(filename, "rb");
    if (file == NULL)
        return 0;

    fread(info, sizeof(unsigned char), 54, file); // read the 54-byte header

    // extract image height and width from header
    width = *(int *) &info[18];
    height = *(int *) &info[22];

    *size = 3 * width * height;
    data = (unsigned char *) malloc(*size * sizeof(unsigned char)); // allocate 3 bytes per pixel
    fread(data, sizeof(unsigned char), (size_t) *size, file); // read the rest of the data at once

    for (int i = 0; i < *size; i += 3) {
        unsigned char tmp = data[i];
        data[i] = data[i + 2];
        data[i + 2] = tmp;
    }

    fclose(file);
    return data;
}

int main() {
    int size = 0;
    char filename[] = "output.bmp";
    unsigned char *data = readBMP(filename, &size);

    for (int i = 0; i < size; i++) {
        printf("%d. %d\n", i + 1, (int) data[i]);
        if ((i + 1) % 3 == 0)
            printf("\n");
    }

    free(data);
    return 0;
}

像素的RGB代码:

(0, 0, 0), (0, 0, 255),
(0, 255, 0), (0, 255, 255),
(255, 0, 0), (255, 0, 255);

我试图“读取”的图像是2x3像素位图:https://prnt.sc/gnygch

我的输出是:

1. 255
2. 0
3. 0

4. 255
5. 0
6. 255

7. 0
8. 0
9. 0

10. 255
11. 0
12. 255

13. 0
14. 0
15. 255

16. 0
17. 0
18. 0

第一个读数甚至匹配位图底部的像素,但其他读数与其他像素不匹配,至少不按照排列顺序排列。

谁能看到我做错了什么?

1 个答案:

答案 0 :(得分:1)

位图的大小不是width * height * 3。应使用

计算
size = ((width * bitcount + 31) / 32) * 4 * height;

在这种情况下,bitcount为24。

必须填充24位位图中的行。您还需要确保您正在读取24位位图。对于32位位图需要不同的算法,托盘位图需要不同的算法。

从下到上读取行。

以下是24位的示例。

您可能仍会遇到此代码的其他问题。最好将库用于这些功能。如果您不想使用Windows功能,请使用可在不同操作系统上使用的第三方库。那里有很多这样的图书馆。

int main()
{
    int width, height, padding, bitcount, size;
    unsigned char *data = 0;
    unsigned char info[54] = { 0 };
    FILE *file = fopen("output.bmp", "rb");
    if(!file)
        return 0;

    fread(info, 1, 54, file);
    width = *(int*)(info + 18);
    height = *(int*)(info + 22);
    bitcount = *(int*)(info + 28);
    size = ((width * bitcount + 31) / 32) * 4 * height;
    padding = width % 4;
    if(bitcount != 24) //this code works for 24-bit bitmap only
        goto error;

    data = malloc(size);
    fread(data, 1, size, file);
    for(int row = height - 1; row >= 0; row--)
    {
        for(int col = 0; col < width; col++)
        {
            int p = (row * width + col) * 3 + row * padding;
            printf("%02X%02X%02X ", data[p + 0], data[p + 1], data[p + 2]);
        }
        printf("\n");
    }

error:
    if(file) fclose(file);
    if(data) free(data);
    return 0;
}