最近调⽤⼀个⼈体检测算法,算法要求输⼊的是图⽚的BGR数据,但是拿到的数据是32位Argb数据,算法⽆法正确进⾏⼈体检测,从⽹上百度⽂库中搜到⼀个C#代码,可以进⾏转换。⽹上的代码有点乱,整理了⼀下,记录留存。 整理后的代码如下:
1class BitmapConvertHelp
2 {
3struct BitmapFileHeader
4 {
5//位图⽂件头
6public UInt16 bfType;
7public UInt32 bfSize;
8public UInt16 bfReserved1;
9public UInt16 bfReserved2;
10public UInt32 bfOffBits;
11 }
12
13struct BitmapInfoHeader
14 {
15//位图信息头
16public UInt32 biSize;
17public UInt32 biWidth;
18public UInt32 biHeight;
19public UInt16 biPlanes;
20public UInt16 biBitCount;
21public UInt32 biCompression;
22public UInt32 biSizeImage;
23public UInt32 biXPelsPerMeter;
24public UInt32 biYPelsPerMeter;
25public UInt32 biClrUsed;
26public UInt32 biClrImportant;
27 }
28
29struct RGBQUAD
30 {
31//位图调⾊板项
32public byte rgbBlue;
33public byte rgbGreen;
34public byte rgbRed;
35public byte rgbReserved;
36 }
37
38private string filepath = null;//需打开的位图的路径
39private string savepath = null;//转换后位图的保存路径
40private BitmapFileHeader bfh;
41private BitmapInfoHeader bih;
42
43private void Save8Bits(Bitmap bmp)
44 {
45//为位图⽂件头赋值
46 bfh.bfOffBits = 1078;
47 bfh.bfReserved1 = 0;
48 bfh.bfReserved2 = 0;
49 bfh.bfSize = 14;
50 bfh.bfType = 19778;
代码转换51//为位图信息头赋值
52 bih.biBitCount = 8;
53 bih.biClrImportant = 0;
54 bih.biClrUsed = 0;
55 bih.biCompression = 0;
56 bih.biHeight = (uint)bmp.Height;
57 bih.biPlanes = 1;
58 bih.biSize = 40;
59 bih.biSizeImage = (uint)(bmp.Height * ((bmp.Width * 8 + 31) / 32 * 4));
60 bih.biWidth = (uint)bmp.Width;
61 bih.biXPelsPerMeter = 0;
62 bih.biYPelsPerMeter = 0;
63//构造256⾊的调⾊板,⾮索引图
64 RGBQUAD[] pal = new RGBQUAD[256];
65for (int i = 0; i < 256; i++)
66 {
67 pal[i].rgbBlue = (byte)i;
68 pal[i].rgbGreen = (byte)i;
69 pal[i].rgbRed = (byte)i;
70 pal[i].rgbReserved = 0;
71 }
72 FileInfo f = new FileInfo(savepath);
73using (BinaryWriter bw = new BinaryWriter(f.OpenWrite()))
74 {
75//写⼊⽂件头
76 bw.Write(bfh.bfType);
77 bw.Write(bfh.bfSize);
78 bw.Write(bfh.bfReserved1);
79 bw.Write(bfh.bfReserved2);
80 bw.Write(bfh.bfOffBits);
81//写⼊信息头
82 bw.Write(bih.biSize);
83 bw.Write(bih.biWidth);
84 bw.Write(bih.biHeight);
85 bw.Write(bih.biPlanes);
86 bw.Write(bih.biBitCount);
87 bw.Write(bih.biCompression);
88 bw.Write(bih.biSizeImage);
89 bw.Write(bih.biXPelsPerMeter);
90 bw.Write(bih.biYPelsPerMeter);
91 bw.Write(bih.biClrUsed);
92 bw.Write(bih.biClrImportant);
93//写⼊调⾊板
94for (int i = 0; i < 256; i++)
95 {
96 bw.Write(pal[i].rgbBlue);
97 bw.Write(pal[i].rgbGreen);
98 bw.Write(pal[i].rgbRed);
99 bw.Write(pal[i].rgbReserved);
100 }
101//位图上下翻转
102 bmp.RotateFlip(RotateFlipType.Rotate180FlipX);
103 BitmapData data = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height), ImageLockMode.ReadOnly, PixelFormat.Format8bppIndexed); 104unsafe
105 {
106byte* ptr = (byte*)data.Scan0.ToPointer();
107//位图的指针
108
109byte[] line = new byte[data.Stride];
110//保存位图的⼀⾏
111for (int i = 0; i < data.Stride; i++)
112 line[i] = 0;
113for (int i = 0; i < bmp.Height; i++)
114 {
115for (int j = 0; j < bmp.Width; j++)
116 {
117 line[j] = *ptr++;
118 }
119 ptr += data.Stride - bmp.Width;//指针跳过对齐的字节
120 bw.Write(line, 0, line.Length);//写⼊位图的⼀⾏
121 }
122 }
123 bw.Close();
124 bmp.UnlockBits(data);
125 }
126 }
127
128public void Bit8To24()
129 {
130 Bitmap bmp8 = new Bitmap(filepath);
131 BitmapData data8 = bmp8.LockBits(new Rectangle(0, 0, bmp8.Width, bmp8.Height), ImageLockMode.ReadOnly, PixelFormat.Format8bppIndexed); 132 Bitmap bmp24 = new Bitmap(bmp8.Width, bmp8.Height, PixelFormat.Format24bppRgb);
133 BitmapData data24 = bmp24.LockBits(new Rectangle(0, 0, bmp24.Width, bmp24.Height), ImageLockMode.WriteOnly, PixelFormat.Format24bppRgb); 134unsafe
135 {
136byte* ptr8 = (byte*)data8.Scan0.ToPointer();
137byte* ptr24 = (byte*)data24.Scan0.ToPointer();
138for (int i = 0; i < bmp8.Height; i++)
139 {
140for (int j = 0; j < bmp8.Width; j++)
141 {
142//⽤8位位图的灰度值填充24位位图的R、G、B值
143 *ptr24++ = *ptr8;
144 *ptr24++ = *ptr8;
145 *ptr24++ = *ptr8++;
146 }
147 ptr8 += data8.Stride - bmp8.Width; //跳过对齐字节
148 ptr24 += data24.Stride - bmp8.Width * 3; //跳过对齐字节
149 }
150 }
151 bmp8.UnlockBits(data8);
152 bmp24.UnlockBits(data24);
153 bmp24.Save(savepath);
154 }
155
156public void Bit8To32()
157 {
158 Bitmap bmp8 = new Bitmap(filepath);
159 BitmapData data8 = bmp8.LockBits(new Rectangle(0, 0, bmp8.Width, bmp8.Height), ImageLockMode.ReadOnly, PixelFormat.Format8bppIndexed); 160 Bitmap bmp32 = new Bitmap(bmp8.Width, bmp8.Height, PixelFormat.Format32bppArgb);
161 BitmapData data32 = bmp32.LockBits(new Rectangle(0, 0, bmp32.Width, bmp32.Height), ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb); 162
163unsafe
164 {
165byte* ptr8 = (byte*)data8.Scan0.ToPointer();
166byte* ptr32 = (byte*)data32.Scan0.ToPointer();
167for (int i = 0; i < bmp8.Height; i++)
168 {
169for (int j = 0; j < bmp8.Width; j++)
170 {
171//⽤8位位图的灰度值,填充32位位图的RGB值,透明度为100%
172 *ptr32++ = *ptr8;
173 *ptr32++ = *ptr8;
174 *ptr32++ = *ptr8++;
175 *ptr32++ = 255;
176 }
177 ptr8 += data8.Stride - bmp8.Width;
178 ptr32 += data32.Stride - bmp8.Width * 4;
179 }
180 }
181 bmp8.UnlockBits(data8);
182 bmp32.UnlockBits(data32);
183 bmp32.Save(savepath);
184 }
185
186public void Bit24To8()
187 {
188 Bitmap bmp24 = new Bitmap(filepath);
189 BitmapData data24 = bmp24.LockBits(new Rectangle(0, 0, bmp24.Width, bmp24.Height), ImageLockMode.ReadOnly, PixelFormat.Format24bppRgb); 190 Bitmap bmp8 = new Bitmap(bmp24.Width, bmp24.Height, PixelFormat.Format8bppIndexed);
191 BitmapData data8 = bmp8.LockBits(new Rectangle(0, 0, bmp8.Width, bmp8.Height), ImageLockMode.WriteOnly, PixelFormat.Format8bppIndexed); 192
193unsafe
194 {
195byte* ptr24 = (byte*)data24.Scan0.ToPointer();
196byte* ptr8 = (byte*)data8.Scan0.ToPointer();
197for (int i = 0; i < bmp8.Height; i++)
198 {
199for (int j = 0; j < bmp8.Width; j++)
200 {
201//⽤RGB值的均值作为8位位图的灰度值
202 *ptr8++=(byte)(((int)(*ptr24++)+(int)(*ptr24++)+(int)(*ptr24++))/3);
203 }
204 ptr24 += data24.Stride - bmp8.Width * 3;
205 ptr8 += data8.Stride - bmp8.Width;
206 }
207 }
208 bmp8.UnlockBits(data8);
209 bmp24.UnlockBits(data24);
210 Save8Bits(bmp8);
211 }
212
213public void Bit32To8()
214 {
215 Bitmap bmp32 = new Bitmap(filepath);
216 BitmapData data32 = bmp32.LockBits(new Rectangle(0, 0, bmp32.Width, bmp32.Height), ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb); 217 Bitmap bmp8 = new Bitmap(bmp32.Width, bmp32.Height, PixelFormat.Format8bppIndexed);
218 BitmapData data8 = bmp8.LockBits(new Rectangle(0, 0, bmp8.Width, bmp8.Height), ImageLockMode.WriteOnly, PixelFormat.Format8bppIndexed); 219unsafe
220 {
221byte* ptr32 = (byte*)data32.Scan0.ToPointer();
222
223byte* ptr8 = (byte*)data8.Scan0.ToPointer();
224for (int i = 0; i < bmp8.Height; i++)
225 {
226for (int j = 0; j < bmp8.Width; j++)
227 {
228//⽤32位位图的RGB值的均值作为8位位图的灰度值
229 *ptr8++ = (byte)(((int)(*ptr32++) + (int)(*ptr32++) + (int)(*ptr32++)) / 3);
230 ptr32++;//跳过透明度字节
231 }
232 ptr32 += data32.Stride - bmp32.Width * 4;
233 ptr8 += data8.Stride - bmp8.Width;
234 }
235 }
236 bmp8.UnlockBits(data8);
237 bmp32.UnlockBits(data32);
238 Save8Bits(bmp8);
239 }
240
241public void Bit32To24()
242 {
243 Bitmap bmp32 = new Bitmap(filepath);
244 BitmapData data32 = bmp32.LockBits(new Rectangle(0, 0, bmp32.Width, bmp32.Height), ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb); 245 Bitmap bmp24 = new Bitmap(bmp32.Width, bmp32.Height, PixelFormat.Format24bppRgb);
246 BitmapData data24 = bmp24.LockBits(new Rectangle(0, 0, bmp24.Width, bmp24.Height), ImageLockMode.WriteOnly, PixelFormat.Format24bppRgb); 247unsafe
248 {
249byte* ptr32 = (byte*)data32.Scan0.ToPointer();
250byte* ptr24 = (byte*)data24.Scan0.ToPointer();
251for (int i = 0; i < bmp24.Height; i++)
252 {
253for (int j = 0; j < bmp24.Width; j++)
254 {
255//将32位位图的RGB值赋值给24位位图的RGB值
256 *ptr24++ = *ptr32++;
257 *ptr24++ = *ptr32++;
258 *ptr24++ = *ptr32++;
259 ptr32++;//跳过透明度字节
260 }
261 ptr24 += data24.Stride - bmp24.Width * 3;
262 ptr32 += data32.Stride - bmp32.Width * 4;
263 }
264 }
265 bmp32.UnlockBits(data32);
266 bmp24.UnlockBits(data24);
267 bmp24.Save(savepath);
268 }
269
270public void Bit24To32()
271 {
272 Bitmap bmp24 = new Bitmap(filepath);
273 BitmapData data24 = bmp24.LockBits(new Rectangle(0, 0, bmp24.Width, bmp24.Height),
ImageLockMode.ReadOnly, PixelFormat.Format24bppRgb); 274 Bitmap bmp32 = new Bitmap(bmp24.Width, bmp24.Height, PixelFormat.Format32bppArgb);
275 BitmapData data32 = bmp32.LockBits(new Rectangle(0, 0, bmp32.Width, bmp32.Height), ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb); 276unsafe
277 {
278byte* ptr24 = (byte*)data24.Scan0.ToPointer();
279byte* ptr32 = (byte*)data32.Scan0.ToPointer();
280for (int i = 0; i < bmp32.Height; i++)
281 {
282for (int j = 0; j < bmp32.Width; j++)
283 {
284//将24位位图的RGB值赋值给32位位图的RGB分量
285 *ptr32++ = *ptr24++;
286 *ptr32++ = *ptr24++;
287 *ptr32++ = *ptr24++;
288 *ptr32++ = 255;//设透明度为100%
289 }
290 ptr24 += data24.Stride - bmp24.Width * 3;
291 ptr32 += data32.Stride - bmp32.Width * 4;
292 }
293 }
294 bmp32.UnlockBits(data32);
295 bmp24.UnlockBits(data24);
296 bmp32.Save(savepath);
297 }
298 }