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