C:灰度bmp到char数组并返回

时间:2018-04-02 18:01:58

标签: c image bitmap

我正在开发一个简单的程序,该程序应该将灰度24位bmp存储到数组中,操作数组然后从数组中创建另一个24位bmp。图像保证是正方形。该程序适用于尺寸为125x125或更小的图像,但为较大的图像输出垃圾,我无法弄清楚原因。代码和源图像如下:

SELECT FOR UPDATE

image used

2 个答案:

答案 0 :(得分:3)

这里的根本问题是调整,正如其他人在评论中所指出的那样。每条扫描线填充为四个字节的倍数。 (内存中的扫描线也必须以4字节边界开始,但这不适用于此。)对于较小的尺寸,你会变得“幸运”。

在24-bpp位图中,扫描线需要width * 3个字节的数据。要计算需要多少填充字节,首先计算“步幅”,然后减去实际数据量。

int data_bytes_per_row = 3 * size;  // your width is size
int stride = (data_bytes_per_row + 3) / 4 * 4;
int padding_bytes = stride - data_bytes_per_row;

现在你可以读取这样的数据:

int i = 0;
for (int row = 0; row < size; ++row) {
  for (int col = 0; col < size; ++col) {
    // need only every third byte
    img[i++] = fgetc(source);
    fgetc(source);
    fgetc(source);
  }
  for (int pad = 0; pad < padding_bytes; ++pad) {
    fgetc(source);
  }
}

同样,写作:

int i = 0;
for (int row = 0; row < size; ++row) {
  for (int col = 0; col < size; ++col) {
    // need to triple every byte
    fputc(img[i], dest);
    fputc(img[i], dest);
    fputc(img[i], dest);
    ++i;
  }
  for (int pad = 0; pad < padding_bytes; ++pad) {
    fputc('\0', dest);
  }
}

答案 1 :(得分:1)

24位位图每像素有3个字节。因此,如果您的图片有size * size像素,则总字节数为size * size * 3

填充也是24位位图中的主要问题。但如果这不是问题,您必须按如下方式更改代码:

unsigned char img[size*size*3];

每隔3个字节读取一次,因此您必须阅读i * 3,而不是i

for(int i = 0; i < size * size; i++)
{
    img[i * 3] = (char)fgetc(source);
    fgetc(source);
    fgetc(source);
}

每隔3个字节写一次:

for(int i = 0; i < size * size; i++)
{
    fputc(img[i * 3], dest);
    fputc(img[i * 3], dest);
    fputc(img[i * 3], dest);
}

要考虑填充,请改用此代码

int main(void)
{
    FILE *fin = fopen("source.bmp", "rb");
    FILE *fout = fopen("dest.bmp", "wb");

    char info[54] = { 0 };
    fread(info, sizeof(info), 1, fin);
    fwrite(info, sizeof(info), 1, fout);

    int width = *(int*)(info + 18);
    int height = *(int*)(info + 22);
    int bitcount = *(int*)(info + 28);
    if(memcmp(info, "BM", 2) != 0 || width < 1 || height < 1 || bitcount != 24)
        return 0;

    int stride = width * 3 + width % 4;
    char *buf = malloc(stride);
    for(int row = height - 1; row >= 0; row--)
    {
        fread(buf, 1, stride, fin);
        for(int col = 0; col < stride; col += 3)
        {
            unsigned char* p = (buf + col);
            unsigned char b = p[0];
            unsigned char g = p[1];
            unsigned char r = p[2];
            unsigned char gray = (unsigned char)(.3 * r + .6 * g + .1 * b);
            p[0] = p[1] = p[2] = gray;
        }
        fwrite(buf, 1, stride, fout);
    }

    return 0;
}