服务器之家:专注于VPS、云服务器配置技术及软件下载分享
分类导航

PHP教程|ASP.NET教程|Java教程|ASP教程|编程技术|正则表达式|C/C++|IOS|C#|Swift|Android|VB|R语言|JavaScript|易语言|vb.net|

服务器之家 - 编程语言 - C/C++ - 利用C/C++二进制读写png文件的方法示例

利用C/C++二进制读写png文件的方法示例

2021-04-25 14:29Datrilla C/C++

最近在做项目的时候遇到了这个问题,所以想着总结下,方法自己和有需要的朋友,下面这篇文章主要介绍了利用C/C++二进制读写png文件的方法,需要的朋友可以参考借鉴,下面来一起看看吧。

前言

二进制文件不是以ASCII代码存放数据的,它将内存中数据存储形式不加转换地传送到磁盘文件,因此它又称为内存数据的映像文件。因为文件中的信息不是字符数据,而是字节中的二进制形式的信息,因此它又称为字节文件。

对二进制文件的操作也需要先打开文件,用完后要关闭文件。在打开时要用ios::binary指定为以二进制形式传送和存储。二进制文件除了可以作为输入文件或输出文件外,还可以是既能输入又能输出的文件。这是和ASCII文件不同的地方。

需求

最近为了弄OpenGl的纹理代码,发现书上没有图片像素的获取,然后就想写个来获取png的,结果花了一天的时间没弄清楚为什么出现数据个别正确其他的却是205

利用C/C++二进制读写png文件的方法示例

突然想起来以前弄软工的时候虽然那个网站只完成了登入注册和文本显示,但是想在数据库中存储图片的时候了解到1存图片地址,2存图片二进制数据。

没错就是二进制。然后拿起C++的翻开找啊找,弄了个ifstream iOS::binary的,成功数据正常。
时隔一天才又想起来r和rb好像是有区别的。没错,那些知识确实没有记住。然后就把C的也改ok了

以下代码只有最简单的读写。地址定位啥的,个别注释中有。如果要改动png的格式甚么的就要再了解一下png的数据结构
如果要十进制的话就跟着注释改一下

mm.png

利用C/C++二进制读写png文件的方法示例

实例代码如下

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
#include<iostream>
#include<fstream>
using namespace std;
typedef unsigned char byte;
 /*
class PngMsg
{
private :
 unsigned char markMsg[8]; //十进制,相当于16进制89.50.4e.47.0d.0a.1a.0a;
 char widthloc;
 char heigtMsgloc;
 char BitDepthloc;//图像深度
 char ColorTypeloc;
 char CompressionMethodloc;//压缩方法(LZ77派生算法)
 char FilterMethodloc;//滤波器方法
 char InterlaceMethodloc;
public:
 PngMsg()
 {
 markMsg[0] = 137;markMsg[1] = 80; markMsg[2] = 78;markMsg[3] = 71; markMsg[4] = 13;markMsg[5] = 10; markMsg[6] = 26; markMsg[7] = 10;
 widthloc = 'a';
 heigtMsgloc = 'b';
 BitDepthloc = 'c';//图像深度
 ColorTypeloc = 'd';
 CompressionMethodloc = 'e';//压缩方法(LZ77派生算法)
 FilterMethodloc = 'f';//滤波器方法
 InterlaceMethodloc = 'g';
 }
 long int getMsg(char loc)
 {
 if (loc == 'a')return 0x10;
 if (loc == 'b')return 0x14;
 if (loc == 'c')return 0x15;
 if (loc == 'd')return 0x16;
 if (loc == 'e')return 0x17;
 if (loc == 'f')return 0x18;
 if (loc == 'g')return 0x19;
 }
 unsigned char width[4];//图像宽度,单位像素
 unsigned char height[4];//图像高度,单位像素
 unsigned char BitDepth;
 //图像深度
 //索引彩色1.2.4.8;灰度1.2.4.8.16;真彩色8.16
 unsigned char ColorType;
 //0灰度1.2.4.8.16;2真彩色8.16;3索引彩色1.2.4.8
 //4带α通道数据的灰度8.16;6带α通道数据的真彩色8.16
 unsigned char CompressionMethod;//压缩方法(LZ77派生算法)
 unsigned char FilterMethod;//滤波器方法
 unsigned char InterlaceMethod;//0:非隔行扫描;1:Adam7
};*/
 
 
//===============================
 
 
//===============
//二进制读入。书上写ASCII码读取和二进制读取,如果对象是字母,那么一致。如果是数字,那么不一致
//书中说明【文件中数据的组织形式,分为ASCII文件(一个字节存放一个ASCII代码)和二进制文件(内部文件,存储形式原样在磁盘上存放),】
//字符,内存存储=ASCII=二进制形式
//数值数据,内存存储和ASCII码不同。
//样例内存整数100000.
//----------------------------------------------------------------
//内存地址 0x00 01 02 03
//内存 00000000 00000000 00100111 00010000【大端模式下】
//----------------------------------------------------------------
//二进制 00000000 00000000 00100111 00010000
//----------------------------------------------------------------
//ASCII 00110001 00110000 00110000 00110000 00110000 00110000【6个字节】
//ASCII码对应 1的49 0的48 0的48 0的48 0的48 0的48
//----------------------------------------------------------------
 
 
 
//只有含‘写'的不存在的文件会新建,其他会报错
 
//r只读;w只写;a尾增(附加/写);文本ASCII
//rb读;wb写;ab尾增;二进制
//以下读写↓
//r+;w+;a+;文本ASCII
//rb+;wb+;ab+二进制
void writeImage(byte*imgbuf, int size)
{
 //FILE* fp = fopen(shaderFile, "wb");
 //由于vs甚么安全性的原因,不让使用fopen,用下面的fopen_s代替;
 FILE*imgPo;
 fopen_s(&imgPo, "mag.png", "wb");//这里是用二进制读取,read-r;binary-b;因为只弄r结果出错!!弄了后面那个的再来看这个才发现是这个的问题!!
 if (imgPo == NULL)return;
 fwrite(imgbuf, sizeof(char),size,imgPo);
 fclose(imgPo);
}
void readImageFile(const char* Imgname)
{
 //FILE* fp = fopen(shaderFile, "rb");
 //由于vs甚么安全性的原因,不让使用fopen,用下面的fopen_s代替;
 FILE*imgP;
 fopen_s(&imgP,Imgname,"rb");//这里是用二进制读取,read-r;binary-b;因为只弄r结果出错!!弄了后面那个的再来看这个才发现是这个的问题!!
 if (imgP == NULL)return ;
 fseek(imgP, 0L, SEEK_END);
 long size = ftell(imgP);
 byte*imgbuf = new byte[size+ 1];
 fseek(imgP,0x0L,SEEK_SET);//图片源
 fread(imgbuf, sizeof(imgbuf[0]), size, imgP);
 /*for (int j = 0; j < size; j++)
 cout << (imgbuf[j] & 0xff) << ":";*/
 fclose(imgP);
 
 writeImage(imgbuf, size);
}
 
 
//===========================================================
 
 
void WriteImage(byte*imgbuf, int size)
{
 
 ofstream imgFo("Image2.png", ios::binary);
 if (!imgFo)
 {
 cerr << "open error!" << endl;
 abort();
 }
 imgFo.write((char*)imgbuf, size);//一次性写入后面注释的是循环写入
 
 /* for (int i = 0; i < size; i++)
 {
 char ct = (imgbuf[i] & 0xFF);
 imgFo.write(&ct, sizeof(char));
 
 //byte ct = (imgbuf[i] & 0xFF);
 //imgFo.write((char*)&ct, sizeof(byte));
 //尝试这样输出的是否正确.
 //byte是我自己给名的unsigned char,出来的是对的,用char也可以。都是一个字节。
 
 }*/
 imgFo.close();
}
void ReadImageFile(const char* Imgname)
{
 ifstream imgF(Imgname, ios::binary);
 if (!imgF) {
 cerr << "open error!" << endl;
 abort();
 }
 imgF.seekg(0, ios::end);
 int size = imgF.tellg();
 //查了C++Library Reference才知道怎么得到size。
 /*int pixscnt;
 byte width[4], height[4];
 
 imgF.seekg(0x10);
 imgF.read((char*)&width, sizeof(width));
 
 imgF.seekg(0x14);
 imgF.read((char*)&height, sizeof(height));
 
 for (int i = 0; i < 4; i++)
 cout << (width[i] & 0xff) << ":";
 
 for (int i = 0; i < 4; i++)
 cout << (height[i] & 0xff) << ":";
 
 pixscnt = (width[2] * (0x100) + width[3])*(height[2] * (0x100) + height[3]);
 cout << pixscnt << endl;//像素
 cout << size << endl;*/
 byte*imgbuf = new byte[size];
 //imgF.seekg(0x10);
 imgF.seekg(0,ios::beg);
 imgF.read((char*)imgbuf, size);//一次性读入,书上的不知是错的还是旧的不可行。后面注释的是循环读入
 /*for (int i = 0; i<size; i++)
 imgF.read( (char*)&imgbuf[i], sizeof(byte));*/
 imgF.close();
 /*for (int i = 0; i < size; i++)
 {
 cout << hex << (imgbuf[i] & 0xff) << ":";
 if (i % 4 == 0)cout << endl;
 } */
WriteImage(imgbuf, size);
}
 
int main()
{
 readImageFile("mm.png");//C/C++的
 ReadImageFile("mm.png");//C++的
 system("pause");
 return 0;
}

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作能带来一定的帮助,如果有疑问大家可以留言交流。

原文链接:http://blog.csdn.net/u014646950/article/details/51100185

延伸 · 阅读

精彩推荐
  • C/C++OpenCV实现拼接图像的简单方法

    OpenCV实现拼接图像的简单方法

    这篇文章主要为大家详细介绍了OpenCV实现拼接图像的简单方法,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...

    iteye_183805102021-07-29
  • C/C++使用C++制作简单的web服务器(续)

    使用C++制作简单的web服务器(续)

    本文承接上文《使用C++制作简单的web服务器》,把web服务器做的功能稍微强大些,主要增加的功能是从文件中读取网页并返回给客户端,而不是把网页代码...

    C++教程网5492021-02-22
  • C/C++C语言实现双人五子棋游戏

    C语言实现双人五子棋游戏

    这篇文章主要为大家详细介绍了C语言实现双人五子棋游戏,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...

    两片空白7312021-11-12
  • C/C++关于C语言中E-R图的详解

    关于C语言中E-R图的详解

    今天小编就为大家分享一篇关于关于C语言中E-R图的详解,小编觉得内容挺不错的,现在分享给大家,具有很好的参考价值,需要的朋友一起跟随小编来看看...

    Struggler095962021-07-12
  • C/C++C语言main函数的三种形式实例详解

    C语言main函数的三种形式实例详解

    这篇文章主要介绍了 C语言main函数的三种形式实例详解的相关资料,需要的朋友可以参考下...

    ieearth6912021-05-16
  • C/C++c/c++实现获取域名的IP地址

    c/c++实现获取域名的IP地址

    本文给大家汇总介绍了使用c/c++实现获取域名的IP地址的几种方法以及这些方法的核心函数gethostbyname的详细用法,非常的实用,有需要的小伙伴可以参考下...

    C++教程网10262021-03-16
  • C/C++深入C++拷贝构造函数的总结详解

    深入C++拷贝构造函数的总结详解

    本篇文章是对C++中拷贝构造函数进行了总结与介绍。需要的朋友参考下...

    C++教程网5182020-11-30
  • C/C++c/c++内存分配大小实例讲解

    c/c++内存分配大小实例讲解

    在本篇文章里小编给大家整理了一篇关于c/c++内存分配大小实例讲解内容,有需要的朋友们可以跟着学习参考下。...

    jihite5172022-02-22