将位图图像写入新的图像文件C ++ [英] Write Bitmap Image to a New Image File C++

查看:108
本文介绍了将位图图像写入新的图像文件C ++的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

大家好。我目前正在尝试从图像文件中复制标题和像素数据,并将其写入新的图像文件。我使用的是256色位图,并且测试时选择了150和90的固定高度和宽度像素。创建了一个新的文件图像文件,但在尝试加载时,会给出以下消息:Paint无法读取此文件。这不是一个有效的位图文件,或者目前不支持它的格式。经过多次尝试后会很感谢支​​持。下面是我正在使用的代码:



Hello all. I am currently trying to copy the header and pixel data from an image file and write this into a new image file. I am using a 256 colour bitmap and for testing have chosen a fixed height and width pixel of 150 and 90. A new file image file is created but when trying to load this, the following message is given: "Paint cannot read this file. This is not a valid bitmap file or its format is currently not supported. Would appreciate the support after many attempts. Below is the code I'm using:

02     const int height = 150;  

03     const int width = 90;  

05     unsigned char m_cHeaderData[1078];  

06     unsigned char** m_cImageData = new unsigned char* [height];  
  

08     for( int i = 0; i <height; i++)  

09     {  

10         m_cImageData[i] = new unsigned char [width];  

11     }  

12    

13     ifstream* m_pInFile;      

14     m_pInFile = new ifstream;  

15     m_pInFile->open("image.bmp", ios::in | ios::binary);  

16     m_pInFile->seekg(0, ios::beg);  

17     m_pInFile->read(reinterpret_cast<char*>(m_cHeaderData), 1078); 
       //bitmap bits start at offset 1078  

18    

19     for(int i = 0; i <height; i++)  

20     {  

21         m_pInFile->read(reinterpret_cast<char*>(m_cImageData[i]), width);   

22     }  

23    

24     m_pInFile->close();  

25    

26     ofstream* m_pOutFile;   

27     m_pOutFile = new ofstream;  

28     m_pOutFile->open("imageCopy.bmp", ios::out | ios::trunc | ios::binary);      

29     m_pOutFile->write(reinterpret_cast<char*>(m_cHeaderData), 1078);  

30     for(int i = 0; i <height; i++)      

31     {  

32         m_pOutFile->write(reinterpret_cast<char*>(m_cImageData[i]), width;  

33     }  

34     m_pOutFile->close();  


37     //deallocate memory:  

38     delete m_pInFile;  

39     delete m_pOutFile;  

40     for(int i = 0; i <height; i++)  

41     {  

42         delete[] m_cImageData[i];  

43     }  

44     delete[] m_cImageData;  

推荐答案

您应该看一下位图文件格式(维基百科 [ ^ ])。



您不应该使用固定的标题大小和固定属性。请改为从文件头读取数据。



即使您的位图文件具有使用的属性(标题大小为1078,256位颜色,匹配宽度和高度),不会创建一个正确的位图文件。这是因为数据被打包成行,其中每行的大小必须是4的倍数。宽度为90像素,每行存储92个字节而不是90个。



[更新]

您可以在网上搜索有关如何将位图文件读入内存的示例代码。可以在此处找到示例: http://www.cplusplus.com/articles/GwvU7k9E/ [ ^ ]和这里: https://graphics.stanford.edu/~mdfisher/Code/Engine/Bitmap.cpp.html [ ^ ]。



必须读取哪种数据取决于您想要做什么。如果要将映像写回新文件,则必须读取并解析必要的标头信息和映像位。因为有不同的标题版本(具有不同的大小)和可选的颜色表,您必须阅读它们,解析信息,并以相同的顺序将所有数据写入新文件。



还要注意,将图像位读入一个大缓冲区而不是为每一行分配缓冲区更有效。然后这个缓冲区包括步幅(行的填充字节)。
You should have a look at the bitmap file format (Wikipedia[^]).

You should not use a fixed header size and fixed properties. Read the data from the file header instead.

Even if your bitmap file has the used properties (header size of 1078, 256 bit colours, matching width and height) you will not create a proper bitmap file. This is because the data are packed in rows where the size of each row must be a multiple of 4. With a width of 90 pixels each row is stored in 92 bytes rather than 90.

[UPDATE]
You may search the the web for example code on how to read a bitmap file into memory. Examples can be found here: http://www.cplusplus.com/articles/GwvU7k9E/[^] and here: https://graphics.stanford.edu/~mdfisher/Code/Engine/Bitmap.cpp.html[^].

What kind of data must be read depends on what you want to do. If you want to write the image back to a new file, you must read and parse the necessary header information and the image bits. Because there are different header versions (with different sizes) and optional colour tables, you must read all of them them, parse the information, and write all data to the new file in the same order.

Note also that it is more efficient to read the image bits into one large buffer rather than allocating buffers for each row. Then this buffer includes the stride (the padding bytes for the rows).


正如 Jochen 所指出的,原始文件的每个水平行都包含 2 备用字节(因为位图步幅必须是 4 的倍数)。因此,您的复制文件实际上是 300 小于原始文件的字节。
As pointed out by Jochen each horizontal line of the original file contains 2 spare bytes (since bitmap stride must be multiple of 4). Hence your 'copy file' is actually 300 bytes smaller than the original one.


感谢您的回复。很有用。我已经测试并注意到,当我在程序中手动将宽度设置为4的倍数时,文件会打开(即使我保持原始图像的大小相同)。



原始图片大小为14.5k。

复制的图片(现在打开)大小为14.7k。



我之前我曾使用BITMAPFILEHEADER和BITMAPINFOHEADER在尝试读写之前提取图像的宽度和高度,但我仍面临同样的问题(复制的文件无法打开)。我甚至使用了bfOffBits的偏移值。



如何从头文件中正确读取?



如果宽度不是4的倍数,我应该将程序中的值更改为最接近的4的倍数吗?



感谢您的反馈意见。
Thanks for the reply. Very useful. I've tested and noticed that the file opens when I manually set the width to a multiple of 4 in the program (even though I keep the original image the same size).

The original image has size 14.5k.
And the copied image (which now opens) has size 14.7k.

I've used BITMAPFILEHEADER and BITMAPINFOHEADER before to extract the width and height of an image before trying to read and write, but I was still confronted with the same problem (that the copied file wouldn't open). I even used the offset value from bfOffBits.

How would I correctly 'read' from the header file?

Should the width turn out not to be a multiple of 4, should I change the value in the program to the nearest multiple of 4?

Thanks for your feedback in advance.


这篇关于将位图图像写入新的图像文件C ++的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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