最近由于工作需要,要实现一个简单的gis系统。要求能够显示同一区域的多种分辨率的地图。由于图片有大有小,当图片很大的时候如果将整张图片读入内存,将会消耗大量的内存,效率不高。所以考虑将大的图片切割成小块保存,根据显示时候的需要调用指定区域的图片,拼接起来显示。
下面是我切割图片的代码;仅供参考,希望能对大家有所帮助
BMPSpliter.h
1
// BMPSpliter.h: interface for the BMPSpliter class.
2
//
3
//////////////////////////////////////////////////////////////////////
4
5
#if !defined(AFX_BMPSPLITER_H__1B6BD900_9C6F_4BCD_8B77_2BC47F32D1D0__INCLUDED_)
6
#define AFX_BMPSPLITER_H__1B6BD900_9C6F_4BCD_8B77_2BC47F32D1D0__INCLUDED_
7
8
#if _MSC_VER > 1000
9
#pragma once
10
#endif // _MSC_VER > 1000
11
class BMPSpliter : public CObject
12
{
13
public:
14
BOOL ReadFile();
15
16
void SetSourceFileName(CString fileName);
17
void SetDestDirectory(CString pdestDir);
18
void SetStartNumber(int startNumber);
19
20
21
BOOL Split(int XPxCount, int YPxCount);
22
BOOL ReadFile(CString fileName);
23
BMPSpliter();
24
virtual ~BMPSpliter();
25
private:
26
CString SourceFileName;
27
CString DestDirectory;
28
int StartNumber;
29
int GetTheLineOffset(int XNum, int XPxCount);
30
int GetOneLineSize(int XPxCount);
31
32
int GetTheTileSize(int XPxCount, int YPxCount);
33
LPBYTE GetTheTile( int XNum, int YNum,int XPxCount, int YPxCount );
34
LPBYTE lpbmpBody;
35
BITMAPINFO bitmapInfo;
36
BITMAPINFOHEADER bmpInfoHeader;
37
BITMAPFILEHEADER fileHeader;
38
BOOL WriteFile(CString fileName,LPBYTE bmpBody, int count, int height, int width);
39
40
};
41
42
#endif // !defined(AFX_BMPSPLITER_H__1B6BD900_9C6F_4BCD_8B77_2BC47F32D1D0__INCLUDED_)
43

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

BMPSpliter.cpp
1
// BMPSpliter.cpp: implementation of the BMPSpliter class.
2
//
3
//////////////////////////////////////////////////////////////////////
4
//////////////////////////////////////////////////////////////////////////
5
//只能构处理24位色以上的图片。
6
//用户只要指定要切割的图片,以及切割后图片的宽度和高度,该类即会按照从左到右、
7
//从下到上的顺序来切割图片;
8
//通过SetDestDirectory()用户可以指定切割后图片的存放目录;
9
//通过SetStartNumber()可以指定切割后图片的起始编号;
10
//////////////////////////////////////////////////////////////////////////
11
#include "stdafx.h"
12
#include "SplitBMP.h"
13
#include "BMPSpliter.h"
14
#include <math.h>
15
#ifdef _DEBUG
16
#undef THIS_FILE
17
static char THIS_FILE[]=__FILE__;
18
#define new DEBUG_NEW
19
#endif
20
21
//////////////////////////////////////////////////////////////////////
22
// Construction/Destruction
23
//////////////////////////////////////////////////////////////////////
24
25
BMPSpliter::BMPSpliter()
26
{
27
SetStartNumber(0);
28
lpbmpBody = NULL;
29
SetDestDirectory("map");
30
SetSourceFileName("");
31
}
32
33
BMPSpliter::~BMPSpliter()
34
{
35
if(lpbmpBody!=NULL)
36
delete [] lpbmpBody;
37
lpbmpBody =NULL;
38
}
39
40
BOOL BMPSpliter::ReadFile(CString fileName)
41
{
42
SetSourceFileName(fileName);
43
return ReadFile();
44
}
45
46
BOOL BMPSpliter::Split( int XPxCount, int YPxCount )
47
{
48
if(lpbmpBody == NULL)
49
return FALSE;
50
if(SourceFileName.IsEmpty())
51
return FALSE;
52
double temp = XPxCount;
53
int XCount = (int)ceil(bmpInfoHeader.biWidth/temp);
54
temp = YPxCount;
55
int YCount = (int)ceil(bmpInfoHeader.biHeight/temp);
56
LPBYTE bmpBody;
57
CString fileName;
58
CString msg;
59
for (int j = 0; j <YCount ; j++)
60
{
61
for (int i = 0; i <XCount ; i++)
62
{
63
bmpBody = GetTheTile(i,j, XPxCount,YPxCount);
64
fileName.Format("%s\\%d.bmp",DestDirectory,i+j*XCount+this->StartNumber);
65
if (!WriteFile(fileName,bmpBody,GetTheTileSize(XPxCount,YPxCount),XPxCount,YPxCount))
66
{
67
msg.Format("%s 写入失败!",fileName);
68
//messagePrinter(msg);
69
return FALSE;
70
}
71
}
72
}
73
return TRUE;
74
// return WriteFile("map\\A.bmp",lpbmpBody,bmpInfoHeader.biSizeImage,bmpInfoHeader.biHeight,bmpInfoHeader.biWidth);
75
}
76
77
BOOL BMPSpliter::WriteFile(CString fileName,LPBYTE bmpBody, int count, int height, int width)
78
{
79
CFile file;
80
if (!file.Open(fileName,CFile::modeCreate|CFile::modeWrite))
81
return FALSE;
82
BITMAPFILEHEADER header = this->fileHeader;
83
header.bfSize = 54 + count;
84
BITMAPINFOHEADER infoHeader = this->bmpInfoHeader;
85
infoHeader.biHeight = height;
86
infoHeader.biWidth = width;
87
infoHeader.biSizeImage = count;
88
try
89
{
90
file.Seek(0,CFile::begin);
91
file.Write( (LPVOID)&header, sizeof(BITMAPFILEHEADER));
92
file.Write( (LPVOID)&infoHeader, sizeof(BITMAPINFOHEADER));
93
file.Write( (LPVOID)bmpBody, count);
94
file.Flush();
95
}
96
catch (CException* e)
97
{
98
file.Close();
99
return FALSE;
100
}
101
file.Close();
102
return TRUE;
103
}
104
105
106
107
LPBYTE BMPSpliter::GetTheTile( int XNum, int YNum,int XPxCount, int YPxCount )
108
{
109
//根据参数计算要读取的区域
110
//如果超越了原图的边界,用空白补齐;
111
LPBYTE lpbody= NULL;
112
int count = GetOneLineSize(XPxCount);
113
count = count * YPxCount;
114
lpbody = (LPBYTE) new char[count];
115
FillMemory(lpbody,count,0xFF);
116
int StartPos = GetOneLineSize(bmpInfoHeader.biWidth)*YPxCount*YNum + (bmpInfoHeader.biBitCount/8)*XPxCount*XNum;
117
int OneLineOffset = GetTheLineOffset(XNum, XPxCount);
118
int LineStartPos = 0;
119
for (int i = 0; i < YPxCount ; i++)
120
{
121
LineStartPos = StartPos + GetOneLineSize(bmpInfoHeader.biWidth)*i;
122
CopyMemory(&lpbody[GetOneLineSize(XPxCount)*i],&lpbmpBody[LineStartPos],OneLineOffset);
123
}
124
return lpbody;
125
126
}
127
128
int BMPSpliter::GetTheTileSize( int XPxCount, int YPxCount )
129
{
130
//根据参数来计算该Tile的图像体的大小。
131
int result = GetOneLineSize(XPxCount);
132
result = result*YPxCount;
133
return result;
134
}
135
136
137
int BMPSpliter::GetOneLineSize(int XPxCount)
138
{
139
int result = (((XPxCount*bmpInfoHeader.biBitCount)+31)>>5)<<2;
140
return result;
141
}
142
143
int BMPSpliter::GetTheLineOffset(int XNum, int XPxCount)
144
{
145
int result = XPxCount*(bmpInfoHeader.biBitCount/8);
146
int sourceBmpLengthPerLine = bmpInfoHeader.biWidth*(bmpInfoHeader.biBitCount/8);
147
if( result*(XNum+1)>sourceBmpLengthPerLine)
148
result = sourceBmpLengthPerLine - (result*XNum);
149
return result;
150
}
151
152
153
void BMPSpliter::SetStartNumber(int startNumber)
154
{
155
StartNumber = startNumber;
156
}
157
158
void BMPSpliter::SetDestDirectory(CString destDir )
159
{
160
this->DestDirectory = destDir;
161
CFileFind ff;
162
if(!ff.FindFile(DestDirectory+"\\*.*"))
163
CreateDirectory(DestDirectory+"\\",NULL);
164
}
165
166
void BMPSpliter::SetSourceFileName(CString fileName)
167
{
168
SourceFileName = fileName;
169
}
170
171
BOOL BMPSpliter::ReadFile()
172
{
173
CFile file;
174
file.Open(SourceFileName,CFile::modeRead);
175
try
176
{
177
int counts = file.Read((LPVOID)&fileHeader,sizeof(BITMAPFILEHEADER));
178
if (counts!=sizeof(BITMAPFILEHEADER))
179
throw new CException;
180
if(fileHeader.bfType != 0x4d42)
181
throw new CException;
182
//文件头信息->位图信息->位图数据
183
//bfOffBits为从文件开始到数据内容之间的距离
184
int size = fileHeader.bfOffBits - sizeof(BITMAPFILEHEADER);
185
//bmpInfoHeader = (LPBITMAPINFOHEADER) new char[size];
186
// BITMAPINFOHEADER和颜色表
187
counts = file.Read(&bmpInfoHeader, sizeof(BITMAPINFOHEADER));
188
if (counts!=sizeof(BITMAPINFOHEADER))
189
throw new CException;
190
//如果为16位色或者更小,则无法处理
191
if(bmpInfoHeader.biBitCount<=16)
192
throw new CException;
193
//如果图像是压缩的,则也无法处理
194
if(bmpInfoHeader.biCompression !=BI_RGB)
195
throw new CException;
196
//读取图像内容
197
file.Seek(fileHeader.bfOffBits,CFile::begin);
198
lpbmpBody = (LPBYTE)new char[bmpInfoHeader.biSizeImage];
199
counts = file.Read(lpbmpBody,bmpInfoHeader.biSizeImage);
200
}
201
catch (CException* e)
202
{
203
AfxMessageBox("Read File Error");
204
return FALSE;
205
}
206
return TRUE;
207
}
208

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

188

189

190

191

192

193

194

195

196

197

198

199

200

201

202

203

204

205

206

207

208

一个简单例子:
1
BMPSpliter spliter;
2
spliter.ReadFile("map\\Source.bmp");
3
spliter.SetDestDirectory("splitResult");
4
spliter.SetStartNumber(16);
5
spliter.Split(256,256);

2

3

4

5
