8位、24位、32位图像数据转换
最近调用一个人体检测算法,算法要求输入的是图片的BGR数据,但是拿到的数据是32位Argb数据,算法无法正确进行人体检测,从网上百度文库中搜到一个C#代码,可以进行转换。网上的代码有点乱,整理了一下,记录留存。
整理后的代码如下:
1 class BitmapConvertHelp 2 { 3 struct BitmapFileHeader 4 { 5 //位图文件头 6 public UInt16 bfType; 7 public UInt32 bfSize; 8 public UInt16 bfReserved1; 9 public UInt16 bfReserved2; 10 public UInt32 bfOffBits; 11 } 12 13 struct BitmapInfoHeader 14 { 15 //位图信息头 16 public UInt32 biSize; 17 public UInt32 biWidth; 18 public UInt32 biHeight; 19 public UInt16 biPlanes; 20 public UInt16 biBitCount; 21 public UInt32 biCompression; 22 public UInt32 biSizeImage; 23 public UInt32 biXPelsPerMeter; 24 public UInt32 biYPelsPerMeter; 25 public UInt32 biClrUsed; 26 public UInt32 biClrImportant; 27 } 28 29 struct RGBQUAD 30 { 31 //位图调色板项 32 public byte rgbBlue; 33 public byte rgbGreen; 34 public byte rgbRed; 35 public byte rgbReserved; 36 } 37 38 private string filepath = null;//需打开的位图的路径 39 private string savepath = null;//转换后位图的保存路径 40 private BitmapFileHeader bfh; 41 private BitmapInfoHeader bih; 42 43 private 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]; 65 for (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); 73 using (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 //写入调色板 94 for (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); 104 unsafe 105 { 106 byte* ptr = (byte*)data.Scan0.ToPointer(); 107 //位图的指针 108 109 byte[] line = new byte[data.Stride]; 110 //保存位图的一行 111 for (int i = 0; i < data.Stride; i++) 112 line[i] = 0; 113 for (int i = 0; i < bmp.Height; i++) 114 { 115 for (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 128 public 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); 134 unsafe 135 { 136 byte* ptr8 = (byte*)data8.Scan0.ToPointer(); 137 byte* ptr24 = (byte*)data24.Scan0.ToPointer(); 138 for (int i = 0; i < bmp8.Height; i++) 139 { 140 for (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 156 public 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 163 unsafe 164 { 165 byte* ptr8 = (byte*)data8.Scan0.ToPointer(); 166 byte* ptr32 = (byte*)data32.Scan0.ToPointer(); 167 for (int i = 0; i < bmp8.Height; i++) 168 { 169 for (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 186 public 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 193 unsafe 194 { 195 byte* ptr24 = (byte*)data24.Scan0.ToPointer(); 196 byte* ptr8 = (byte*)data8.Scan0.ToPointer(); 197 for (int i = 0; i < bmp8.Height; i++) 198 { 199 for (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 213 public 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); 219 unsafe 220 { 221 byte* ptr32 = (byte*)data32.Scan0.ToPointer(); 222 223 byte* ptr8 = (byte*)data8.Scan0.ToPointer(); 224 for (int i = 0; i < bmp8.Height; i++) 225 { 226 for (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 241 public 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); 247 unsafe 248 { 249 byte* ptr32 = (byte*)data32.Scan0.ToPointer(); 250 byte* ptr24 = (byte*)data24.Scan0.ToPointer(); 251 for (int i = 0; i < bmp24.Height; i++) 252 { 253 for (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 270 public 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); 276 unsafe 277 { 278 byte* ptr24 = (byte*)data24.Scan0.ToPointer(); 279 byte* ptr32 = (byte*)data32.Scan0.ToPointer(); 280 for (int i = 0; i < bmp32.Height; i++) 281 { 282 for (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 }