不正确的位图复制/输出 [英] Incorrect Bitmap Copy/Output

查看:120
本文介绍了不正确的位图复制/输出的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

所以,我有一个问题搞清楚究竟是什么,试图读取任何24 bpp的位图图像,脚麻在同一文件夹重新创建它。它的工作原理与一个图像,而不是两个人,我已经与测试它。从位图读取时,我使用的头本身中的信息。可以说我有三个问题。 1)我是不是从位图看是否正确? 2)我是不是计算/使用/写正确的填充? 3)我是不是正确的输出?
第三确认没有与此形象和它的输出。

So I am having a problem figuring out exactly what is going wrong with trying to read any 24bpp bitmap image and re-create it in the same folder. It works with one image, but not two others that I have tested it with. When reading from the bitmap, I use the information found in the header itself. It could be said I have three questions. 1) Am I reading from bitmap correctly? 2) Am I calculating/using/writing the padding correctly? 3) Am I outputting correctly?. Third is confirmed no with this image and its output.

另外分配的二维数组的图像的原因是,我可以尝试90度旋转位图后者。

Also the reason for allocating an 2d array for the Images is so that I can latter try to rotate bitmaps by 90 degrees.

不幸的是,我不能发表图片,拍摄的图像是从这里开始,在rgb_24bpp.bmp
HTTP://pyglet.google$c$c.com/svn/主干/测试/图像/

Unfortunately I cannot post images, the image taken is from here, the rgb_24bpp.bmp http://pyglet.googlecode.com/svn/trunk/tests/image/

下面是用于从图象读出,并计算出填充的code

Here is the code used for reading from the image and to calculate the padding.

ifstream myBitmap("rgb_24bpp.bmp", ios::binary | ios::beg);

// Get the total file size in bytes, testing file access
begin = myBitmap.tellg();
myBitmap.seekg(0, ios::end);
end = myBitmap.tellg();

// Actually reading image file
myBitmap.seekg( 0, ios::beg);
myBitmap.read((char*)FileHeader, sizeof(BITMAPFILEHEADER));
myBitmap.read((char*)InfoHeader, sizeof(BITMAPINFOHEADER));
test = myBitmap.tellg();

RGBQUAD ** Image = new RGBQUAD*[InfoHeader->biWidth];
for (int i = 0; i < InfoHeader->biWidth; ++i) {
    Image[i] = new RGBQUAD[InfoHeader->biHeight];
}
int pitch = InfoHeader->biWidth * 3;

if (pitch % 4 != 0)
{
    pitch += 4 - (pitch % 4);
}

int padding = pitch - (InfoHeader->biWidth * 3);
cout << "padding: " << padding << endl;

myBitmap.seekg(FileHeader->bfOffBits, ios::beg);
for (int i = InfoHeader->biHeight; i > 0; --i) {
    for (int j = 0; j < InfoHeader->biWidth; ++j) {
        myBitmap.read((char*)&Image[j][i], sizeof(RGBQUAD));
    }
    if (padding != 0) myBitmap.read(PadBuffer, padding);
}
myBitmap.close();

开始/结束/测试都的streampos和印在控制台上进行调试。
这是用来输出code /重现图像。

begin/end/test are all of streampos and printed on console for debugging. And this is the code used to output/recreate the image.

ofstream BitmapOut("Output.bmp");
BitmapOut.write((char*)FileHeader, sizeof(BITMAPFILEHEADER));
BitmapOut.write((char*)InfoHeader, sizeof(BITMAPINFOHEADER));
for (int i = InfoHeader->biHeight; i > 0; --i) {
    for (int j = 0; j < InfoHeader->biWidth; ++j) {
        BitmapOut.write((char*)&Image[j][i], sizeof(RGBQUAD));
    }
    if (padding != 0) BitmapOut.write("\0\0\0\0\0\0\0", padding);
}

BitmapOut.close();

我已经证实,这两个标题确实是正确的,可以从他们正常在3个不同的测试中提取数据。
利用这个家伙code(对不起,这个项目是非商业性的,只有自学)。
在读.bmp文件C ++

通过注释掉保留在RGBQUAD和有效地做一个RGBTRI而不是例外。

With the exception of commenting out the reserved in the RGBQUAD and making effectively a RGBTRI instead.

推荐答案

您能做到这样的..另外,如果你不想做一个临时数组复制像素,可以轻松地阅读,搜索,阅读,搜索,等等。或者你可以阅读的一次。有这么多的方法来读取一个位图,并有效/无效的。你想怎么办呢这是由你决定。另一种有效的方式来做到这一点是要保存和BITMAPINFOHEADER BITMAPFILEHEADER。然后,当你决定写位图到磁盘,只写他们的头先则像素。 WAY更快,更简单。我没有这样做,在这个例子。我会离开,你要弄清楚。

You can do it like this.. Also, if you don't want to make a temporary array to copy the pixels, you can easily read, seek, read, seek, etc.. OR you can just read all at once. There are so many ways to read a bitmap and be efficient/inefficient. It's up to you how you want to do it. Another efficient way to do it is to SAVE the BitmapInfoHeader and BitmapFileHeader. Then when you decide to write the bitmap to the disk, just write them headers first then the pixels. WAY faster and easier.. I did NOT do that in this example. I'll leave that up to you to figure out.

下面是一个简单的code我写的回答你的问题。我preFER使用一维数组。

Here is a sample code I wrote for answering your question. I prefer to use 1-dimensional arrays.

#include <fstream>
#include <cstring>
#include <windows.h>

typedef struct
{
    unsigned int width, height;
    unsigned char* pixels;
} Bitmap;

void InitBitmap(Bitmap* bmp)
{
    if (bmp)
    {
        bmp->width = 0;
        bmp->height = 0;
        bmp->pixels = NULL;
    }
}

void FreeBitmap(Bitmap* bmp)
{
    if (bmp && bmp->pixels)
    {
        bmp->width = 0;
        bmp->height = 0;
        delete[] bmp->pixels;
        bmp->pixels = NULL;
    }
}

bool ReadBitmap(const char* FilePath, Bitmap* bmp)
{
    std::fstream hFile(FilePath, std::ios::in | std::ios::binary);

    if (!bmp || !hFile.is_open())
        return false;

    BITMAPINFO Info;
    BITMAPFILEHEADER Header;
    memset(&Info, 0, sizeof(Info));
    memset(&Header, 0, sizeof(Header));

    hFile.read((char*)&Header, sizeof(Header));
    hFile.read((char*)&Info.bmiHeader, sizeof(Info.bmiHeader));

    bmp->width = Info.bmiHeader.biWidth;
    bmp->height = Info.bmiHeader.biHeight < 0 ? -Info.bmiHeader.biHeight : Info.bmiHeader.biHeight;
    size_t size = Info.bmiHeader.biSizeImage;

    bmp->pixels = new unsigned char[size];
    hFile.seekg(Header.bfOffBits, std::ios::beg);
    hFile.read((char*)bmp->pixels, size);
    hFile.close();

    return true;
}

bool WriteBitmap(const char* FilePath, Bitmap* bmp)
{
    std::fstream hFile(FilePath, std::ios::out | std::ios::binary);

    if (!bmp || !hFile)
        return false;

    BITMAPINFO Info;
    BITMAPFILEHEADER Header;
    memset(&Info, 0, sizeof(Info));
    memset(&Header, 0, sizeof(Header));

    Info.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
    Info.bmiHeader.biWidth = bmp->width;
    Info.bmiHeader.biHeight = bmp->height;
    Info.bmiHeader.biPlanes = 1;
    Info.bmiHeader.biBitCount = 24;
    Info.bmiHeader.biCompression = BI_RGB;
    Info.bmiHeader.biSizeImage = 0;
    Header.bfType = 0x4D42;
    Header.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);
    size_t size = (((24 * bmp->width + 31) & ~31) / 8) * bmp->height;

    hFile.write((char*)&Header, sizeof(Header));
    hFile.write((char*)&Info.bmiHeader, sizeof(Info.bmiHeader));
    hFile.write((char*)bmp->pixels, size);
    hFile.close();
    return true;
}

int main()
{
    Bitmap bmp;
    InitBitmap(&bmp);

    ReadBitmap("C:/Users/Brandon/Desktop/foo.bmp", &bmp);
    WriteBitmap("C:/Users/Brandon/Desktop/foo2.bmp", &bmp);

    FreeBitmap(&bmp);
}

这篇关于不正确的位图复制/输出的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆