使用BMP - 加载和保存

时间:2015-11-12 21:49:53

标签: c++ bmp

与朋友们一起,我们正在尝试编写应用程序来处理BMP文件,我们将尽可能简化它,因为我们刚刚开始学习C和C ++。使用新的实际尺寸的线条复制效果很好,但现在我想添加灰度效果并出现另一个问题:图片的右侧移动到左边 - 检查图片。是什么导致了这个问题?

#include <iostream>
#include <fstream>
#include <stdio.h>
#include <unistd.h>


using namespace std;

void ReadBMP()
{
    FILE* f = fopen("test2.bmp", "rb");
    FILE* w = fopen("zapis.bmp", "wb");

    if(f == NULL)
        throw "Argument Exception";

    unsigned char info[54];
    fread(info, sizeof(unsigned char), 54, f);
    fwrite(info, sizeof(unsigned char), 54, w);

    int width = *(int*)&info[18];
    int height = *(int*)&info[22];

    cout << endl;
    cout << "Width: " << width << endl;
    cout << "Height: " << height << endl;



    int realwidth = 3*width+(4 - ((3*width)%4))%4;
    int volume = height * realwidth;
    unsigned char* data = new unsigned char[volume];

    fwrite(info, sizeof(unsigned char), 54, w);

    fread(data, sizeof(unsigned char), volume, f);
    unsigned char color = 0;

    for(int i = 0; i < volume; i+=3)
    {
        color = 0;
        color+=data[i]*0.114;
        color+=data[i+1]*0.587;
        color+=data[i+2]*0.299;
        data[i] = color;
        data[i+1] = color;
        data[i+2] = color;
    }


    fwrite(data, sizeof(unsigned char), volume, w);



    fclose(f);
    fclose(w);
    delete(data);
}

int main()
{
    ReadBMP();
    return 0;
}

Input image

Output image

3 个答案:

答案 0 :(得分:1)

您的图像数据大小公式错误。首先,您需要通过将宽度乘以每个像素的字节数(24位图像为3),然后向上舍入到最接近的4的倍数来找到音高。然后将音高乘以高度;

int byte_width = width * 3;
int pitch = byte_width + (4 - byte_width % 4) % 4;
int volume = pitch * height;

答案 1 :(得分:0)

正如我在自己的代码中看到的那样(大约20年前写的),图像的每一行都由0或更多空字节补充以对齐起始字节。看来,你计算错误的对齐方式。

只需复制&amp;粘贴在这里:

unsigned short paddingSize;
unsigned short bitsPerLine = width * bitsPerPixel;

if(1 == bitsPerPixel || 4 == bitsPerPixel)
{
  if(bitsPerLine % 8)
    bitsPerLine += 8;

  paddingSize = (bitsPerLine/8) % 2;
}
else if(8 == bitsPerPixel)
  paddingSize = 0x0003 & ~((bitsPerLine/8) % 4 - 1);
else
  paddingSize = (bitsPerLine/8) % 2;

每一行的实际大小为calculatedSize + paddingSize,其中calculatedSize是行的精确大小,以字节为单位,即ceil(bitsPerLine/8)(bitsPerLine + 7)/8 ic C / C ++。

我可以对代码说些什么,它已经过调试并且可以正常工作。但我不记得为什么所有这些检查都在这里。

答案 2 :(得分:0)

unsigned char info[54];
fread(info, sizeof(unsigned char), 54, f);
// fwrite(info, sizeof(unsigned char), 54, w); --- comment this line !!!!!!! 

int width = *(int*)&info[18];
int height = *(int*)&info[22];

您不必要地将标题写入文件两次。