C# PGM格式图像与BMP格式图像相互转换

C# PGM格式图像与BMP格式图像相互转换

关于PGM文件格式的详细介绍请参考https://blog.csdn.net/xiaoxin_ling/article/details/3980642

//PGM转BMP/BMP转PGM类
	class PGM2BMP
	{
    
    
		private static ColorPalette grayScale;//定义调色板类
		public Bitmap PGMToBitmap(string filePath)//PGM 转 BMP
		{
    
    
			using (FileStream fs = new FileStream(filePath, FileMode.Open))
			{
    
    
				using (BinaryReader reader = new BinaryReader(fs, Encoding.ASCII))
				{
    
    
					if (reader.ReadChar() == 'P' && reader.ReadChar() == '5')//针对P5类型的PGM文件,适用于P5类型的PGM文件,对于P2类型的PGM类型的图像文件需要修改
					{
    
    
						reader.ReadChar();               //读完当前行的结束符“\n”,切换至下一行
						if (reader.PeekChar() == '#')    //有的PGM文件中含有#开头的行,这个是comment
						{
    
    
							while (reader.PeekChar() != '\n')
							{
    
    
								reader.ReadChar();
							}
							reader.ReadChar();
						}

						StringBuilder sbTemp = new StringBuilder();
						int width = ReadNumber(reader, sbTemp);   //获取图片宽
						int height = ReadNumber(reader, sbTemp);  //获取图片高
						int level = ReadNumber(reader, sbTemp);   //获取图片像素中最高像素值
						bool bTwo = (level > 255);             //一个像素占字节数,默认占1byte

						Bitmap bmp = new Bitmap(width, height, PixelFormat.Format8bppIndexed);
						if (grayScale == null)
						{
    
    
							grayScale = bmp.Palette;
							for (int i = 0; i < 256; i++)
							{
    
    
								grayScale.Entries[i] = Color.FromArgb(i, i, i);
							}
						}
						bmp.Palette = grayScale;
						BitmapData dt = bmp.LockBits(new Rectangle(0, 0, width, height), ImageLockMode.WriteOnly, PixelFormat.Format8bppIndexed);
						int offset = dt.Stride - dt.Width;//位图要求像素宽为4的整数倍,因此当被转换图像宽不是4的整数倍时就会有偏差,最大位3个像素

						//指针的使用必须放在unsafe的区域里
						unsafe
						{
    
    
							byte* ptr = (byte*)dt.Scan0;

							for (int i = 0; i < height; i++)
							{
    
    
								for (int j = 0; j < width; j++)
								{
    
    
									byte v;
									if (bTwo)
									{
    
    
										v = (byte)(((double)((reader.ReadByte() << 8) + reader.ReadByte()) / level) * 255.0);
									}
									else
									{
    
    
										v = reader.ReadByte();
									}
									*ptr = v;
									ptr++;
								}
								ptr += offset;
							}
						}

						bmp.UnlockBits(dt);
						return bmp;
					}
					else
					{
    
    
						throw new InvalidOperationException("Target file is not a PGM file");
					}
				}
			}
		}

		public void SaveAsBitmap(string src, string dest)
		{
    
    
			PGMToBitmap(src).Save(dest, ImageFormat.Bmp);
		}

		private int ReadNumber(BinaryReader reader, StringBuilder sb)
		{
    
    
			char c = '\0';
			sb.Length = 0;
			while (Char.IsDigit(c = reader.ReadChar()))
			{
    
    
				sb.Append(c);
			}
			return int.Parse(sb.ToString());
		}

		/// <summary>
		/// 将bmp保存为PGM格式文件(P5)
		/// </summary>
		/// <param name="bm"></param>
		/// <param name="iw"></param>
		/// <param name="ih"></param>
		/// <param name="icolor"></param>
		/// <param name="filePath"></param>
		public void WritePGM(Bitmap bm, int iw, int ih, int icolor, string filePath)
		{
    
    
			string PGMINfo = "P5" + Convert.ToChar(10) + '#'
				+ "Generated by OpenCV 3.3.1-dev" + Convert.ToChar(10) +
				iw.ToString() + " " +
				ih.ToString() + Convert.ToChar(10) +
				icolor.ToString() + Convert.ToChar(10);

			FileStream OutputStream = File.Create(filePath);
			BinaryWriter PGMWriter = new BinaryWriter(OutputStream);
			byte[] PGMInfoBuffer = System.Text.ASCIIEncoding.Default.GetBytes(PGMINfo);
			PGMWriter.Write(PGMInfoBuffer);

			byte[] data = new byte[iw*ih];
			for (int j = 0; j < ih; j++)
			{
    
    
				for (int i = 0; i < iw; i++)
				{
    
    
					data[i + j * iw] = (byte)bm.GetPixel(i, j).R;
				}
			}
			PGMWriter.Write(data);
			PGMWriter.Close();
		}
	}

注意:类中使用了unsafe关键字,直接使用会报错,编译无法通过。
error CS0227: 不安全代码只会在使用 /unsafe 编译的情况下出现
解决:VS2017下,项目-》右键-》属性-》生成: 将“允许不安全代码(F)”勾选上,重新编译即可。
在这里插入图片描述
参考Demo链接https://download.csdn.net/download/CXYLVCHF/13986132

猜你喜欢

转载自blog.csdn.net/CXYLVCHF/article/details/111163999