Cosmos/source2/Users/Orvid/Orvid.Graphics.Dependancies/Image Formats/PnmImage.cs

721 lines
25 KiB
C#

// Please note, everything below this
// point was originally from a plugin
// for Paint.Net, the plugin is available here:
// http://forums.getpaint.net/index.php?/topic/17202-pnm-file-type-plugin/
//
//
// The source has been modified for use in this library.
//
// This disclaimer was last
// modified on August 9, 2011.
using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.Drawing;
using ShaniSoft.IO.DataWriter;
using ShaniSoft.IO.DataReader;
using ShaniSoft.Drawing.PnmReader;
using ShaniSoft.Drawing.PnmWriter;
namespace ShaniSoft
{
#region Drawing
namespace Drawing
{
#region Pnm
public class Pnm
{
public static PnmType DetectType(Image im)
{
bool flag = true;
for (int i = 0; i < im.Height; i++)
{
for (int j = 0; j < im.Width; j++)
{
Color pixel = ((Bitmap)im).GetPixel(j, i);
if ((pixel.R != pixel.G) || (pixel.R != pixel.B))
{
return PnmType.Ppm;
}
if (flag && ((((pixel.R > 0) || (pixel.R < 0xff)) || ((pixel.G > 0) || (pixel.G < 0xff))) || ((pixel.B > 0) || (pixel.B < 0xff))))
{
flag = false;
}
}
}
if (!flag)
{
return PnmType.Pgm;
}
return PnmType.Pbm;
}
public static Image ReadPnm(Stream inputStream)
{
char ch;
string str;
string magicWord = ((char)inputStream.ReadByte()).ToString() + ((char)inputStream.ReadByte()).ToString();
inputStream.ReadByte();
PnmEncoding pNMEncoding = PnmFactory.GetPNMEncoding(magicWord);
IPnmDataReader iPNMDataReader = PnmFactory.GetIPNMDataReader(inputStream, pNMEncoding);
if (iPNMDataReader == null)
{
throw new Exception("Currently only Binary and ASCII encoding is supported");
}
IPnmReader iPNMReader = PnmFactory.GetIPNMReader(PnmFactory.GetPNMType(magicWord));
if (iPNMReader == null)
{
throw new Exception("Currently only PBM, PGM and PNM Image Types are supported");
}
do
{
str = iPNMDataReader.ReadLine();
if (str.Length == 0)
{
ch = '#';
}
else
{
ch = str.Substring(0, 1).ToCharArray(0, 1)[0];
}
}
while (ch == '#');
string[] strArray = str.Split(new char[] { ' ' });
int width = int.Parse(strArray[0]);
int height = int.Parse(strArray[1]);
if (magicWord != "P1")
{
do
{
str = iPNMDataReader.ReadLine();
if (str.Length == 0)
{
ch = '#';
}
else
{
ch = str.Substring(0, 1).ToCharArray(0, 1)[0];
}
}
while (ch == '#');
if (int.Parse(str) != 0xff)
{
Console.WriteLine("Warning, max value for pixels in this image is not 255");
}
}
return iPNMReader.ReadImageData(iPNMDataReader, width, height);
}
public static void WritePnm(Stream fs, Image im, PnmEncoding encoding, PnmType ptype)
{
IPnmDataWriter iPNMDataWriter = PnmFactory.GetIPNMDataWriter(fs, encoding);
if (iPNMDataWriter == null)
{
throw new Exception("Currently only Binary and ASCII encoding is supported");
}
try
{
iPNMDataWriter.WriteLine(PnmFactory.GetMagicWord(ptype, encoding));
iPNMDataWriter.WriteLine(im.Width.ToString() + " " + im.Height.ToString());
if (ptype != PnmType.Pbm)
{
iPNMDataWriter.WriteLine("255");
}
PnmFactory.GetIPNMWriter(ptype).WriteImageData(iPNMDataWriter, im);
}
catch
{
throw;
}
}
}
#endregion
#region PnmFactory
internal class PnmFactory
{
internal static IPnmDataReader GetIPNMDataReader(Stream fs, PnmEncoding encoding)
{
switch (encoding)
{
case PnmEncoding.BinaryEncoding:
return new BinaryDataReader(fs);
case PnmEncoding.ASCIIEncoding:
return new ASCIIDataReader(fs);
}
return null;
}
internal static IPnmDataWriter GetIPNMDataWriter(Stream fs, PnmEncoding encoding)
{
switch (encoding)
{
case PnmEncoding.BinaryEncoding:
return new BinaryDataWriter(fs);
case PnmEncoding.ASCIIEncoding:
return new ASCIIDataWriter(fs);
}
return null;
}
internal static IPnmReader GetIPNMReader(PnmType ptype)
{
switch (ptype)
{
case PnmType.Pbm:
return new PbmReader();
case PnmType.Pgm:
return new PgmReader();
case PnmType.Ppm:
return new PpmReader();
}
return null;
}
internal static IPnmWriter GetIPNMWriter(PnmType ptype)
{
switch (ptype)
{
case PnmType.Pbm:
return new PbmWriter();
case PnmType.Pgm:
return new PgmWriter();
case PnmType.Ppm:
return new PpmWriter();
}
return null;
}
internal static string GetMagicWord(PnmType ptype, PnmEncoding encoding)
{
if ((ptype == PnmType.Pgm) && (encoding == PnmEncoding.ASCIIEncoding))
{
return "P2";
}
if ((ptype != PnmType.Pgm) || (encoding != PnmEncoding.BinaryEncoding))
{
if ((ptype == PnmType.Ppm) && (encoding == PnmEncoding.ASCIIEncoding))
{
return "P3";
}
if ((ptype == PnmType.Ppm) && (encoding == PnmEncoding.BinaryEncoding))
{
return "P6";
}
if ((ptype == PnmType.Pbm) && (encoding == PnmEncoding.ASCIIEncoding))
{
return "P1";
}
if ((ptype == PnmType.Pbm) && (encoding == PnmEncoding.BinaryEncoding))
{
throw new Exception("PBM files are only written in ASCII encoding.");
}
}
return "P5";
}
internal static string GetMaxPixel(PnmType ptype)
{
if (ptype == PnmType.Pbm)
{
return "-1";
}
return "255";
}
internal static PnmEncoding GetPNMEncoding(string MagicWord)
{
switch (MagicWord)
{
case "P1":
case "P2":
case "P3":
return PnmEncoding.ASCIIEncoding;
case "P5":
case "P6":
return PnmEncoding.BinaryEncoding;
}
return PnmEncoding.BinaryEncoding;
}
internal static PnmType GetPNMType(string MagicWord)
{
switch (MagicWord)
{
case "P1":
return PnmType.Pbm;
case "P2":
case "P5":
return PnmType.Pgm;
case "P6":
case "P3":
return PnmType.Ppm;
}
return PnmType.Pgm;
}
}
#endregion
#region PnmType
public enum PnmType
{
Pbm,
Pgm,
Ppm
}
#endregion
#region PnmEncoding
public enum PnmEncoding
{
BinaryEncoding,
ASCIIEncoding
}
#endregion
#region PnmReader
namespace PnmReader
{
#region IPnmReader
internal abstract class IPnmReader
{
public abstract Image ReadImageData(IPnmDataReader dr, int width, int height);
}
#endregion
#region PbmReader
internal class PbmReader : IPnmReader
{
public override Image ReadImageData(IPnmDataReader dr, int width, int height)
{
Image image;
try
{
int count = (dr is ASCIIDataReader) ? width : ((int)Math.Ceiling((double)(((double)width) / 8.0)));
Bitmap bitmap = new Bitmap(width, height, System.Drawing.Imaging.PixelFormat.Format8bppIndexed);
System.Drawing.Imaging.BitmapData bitmapdata = bitmap.LockBits(new Rectangle(0, 0, width, height), System.Drawing.Imaging.ImageLockMode.WriteOnly, System.Drawing.Imaging.PixelFormat.Format8bppIndexed);
System.Drawing.Imaging.ColorPalette palette = bitmap.Palette;
palette.Entries[0] = Color.Black;
palette.Entries[1] = Color.White;
bitmap.Palette = palette;
byte[] data = new byte[height * bitmapdata.Stride];
for (int i = 0; i < height; i++)
{
dr.Read(data, i * bitmapdata.Stride, count);
}
System.Runtime.InteropServices.Marshal.Copy(data, 0, bitmapdata.Scan0, data.Length);
bitmap.UnlockBits(bitmapdata);
image = bitmap;
}
catch
{
throw;
}
finally
{
dr.Close();
}
return image;
}
}
#endregion
#region PgmReader
internal class PgmReader : IPnmReader
{
public override Image ReadImageData(IPnmDataReader dr, int width, int height)
{
Image image;
try
{
Bitmap bitmap = new Bitmap(width, height, System.Drawing.Imaging.PixelFormat.Format8bppIndexed);
System.Drawing.Imaging.BitmapData bitmapdata = bitmap.LockBits(new Rectangle(0, 0, width, height), System.Drawing.Imaging.ImageLockMode.WriteOnly, System.Drawing.Imaging.PixelFormat.Format8bppIndexed);
System.Drawing.Imaging.ColorPalette palette = bitmap.Palette;
for (int i = 0; i < palette.Entries.Length; i++)
{
palette.Entries[i] = Color.FromArgb(i, i, i);
}
bitmap.Palette = palette;
byte[] data = new byte[height * bitmapdata.Stride];
for (int j = 0; j < height; j++)
{
dr.Read(data, j * bitmapdata.Stride, width);
}
System.Runtime.InteropServices.Marshal.Copy(data, 0, bitmapdata.Scan0, data.Length);
bitmap.UnlockBits(bitmapdata);
image = bitmap;
}
catch
{
throw;
}
finally
{
dr.Close();
}
return image;
}
}
#endregion
#region PpmReader
internal class PpmReader : IPnmReader
{
public override Image ReadImageData(IPnmDataReader dr, int width, int height)
{
Image image;
try
{
Bitmap bitmap = new Bitmap(width, height, System.Drawing.Imaging.PixelFormat.Format24bppRgb);
System.Drawing.Imaging.BitmapData bitmapdata = bitmap.LockBits(new Rectangle(0, 0, width, height), System.Drawing.Imaging.ImageLockMode.WriteOnly, System.Drawing.Imaging.PixelFormat.Format24bppRgb);
byte[] data = new byte[height * bitmapdata.Stride];
for (int i = 0; i < height; i++)
{
dr.Read(data, i * bitmapdata.Stride, width * 3);
}
System.Runtime.InteropServices.Marshal.Copy(data, 0, bitmapdata.Scan0, data.Length);
bitmap.UnlockBits(bitmapdata);
image = bitmap;
}
catch
{
throw;
}
finally
{
dr.Close();
}
return image;
}
}
#endregion
}
#endregion
#region PnmWriter
namespace PnmWriter
{
#region IPnmWriter
internal abstract class IPnmWriter
{
public abstract void WriteImageData(IPnmDataWriter dw, Image im);
}
#endregion
#region PbmWriter
internal class PbmWriter : IPnmWriter
{
public override void WriteImageData(IPnmDataWriter dw, Image im)
{
int num = 0;
for (int i = 0; i < im.Height; i++)
{
for (int j = 0; j < im.Width; j++)
{
Color pixel = ((Bitmap)im).GetPixel(j, i);
int num4 = (pixel.R + pixel.G) + pixel.B;
if (num4 > 0)
{
dw.WriteByte(1);
}
else
{
dw.WriteByte(0);
}
num++;
if ((dw is ASCIIDataWriter) && (num >= 0x22))
{
num = 0;
dw.WriteLine(string.Empty);
}
}
}
dw.Close();
}
}
#endregion
#region PgmWriter
internal class PgmWriter : IPnmWriter
{
public override void WriteImageData(IPnmDataWriter dw, Image im)
{
StringBuilder builder = new StringBuilder();
for (int i = 0; i < im.Height; i++)
{
for (int j = 0; j < im.Width; j++)
{
Color pixel = ((Bitmap)im).GetPixel(j, i);
int num3 = (int)(((pixel.R * 0.3) + (pixel.G * 0.59)) + (pixel.B * 0.11));
if (dw is ASCIIDataWriter)
{
string str = num3.ToString();
if ((builder.Length + str.Length) >= 70)
{
dw.WriteLine(string.Empty);
builder.Remove(0, builder.Length);
}
else
{
builder.Append(str);
}
}
dw.WriteByte((byte)num3);
}
}
dw.Close();
}
}
#endregion
#region PpmWriter
internal class PpmWriter : IPnmWriter
{
public override void WriteImageData(IPnmDataWriter dw, Image im)
{
StringBuilder builder = new StringBuilder();
for (int i = 0; i < im.Height; i++)
{
for (int j = 0; j < im.Width; j++)
{
Color pixel = ((Bitmap)im).GetPixel(j, i);
if (dw is ASCIIDataWriter)
{
string str = string.Concat(new object[] { pixel.R, " ", pixel.G, " ", pixel.B, " " });
if ((builder.Length + str.Length) >= 70)
{
dw.WriteLine(string.Empty);
builder.Remove(0, builder.Length);
}
else
{
builder.Append(str);
}
}
dw.WriteByte(pixel.R);
dw.WriteByte(pixel.G);
dw.WriteByte(pixel.B);
}
}
dw.Close();
}
}
#endregion
}
#endregion
}
#endregion
#region IO
namespace IO
{
#region DataReader
namespace DataReader
{
#region ASCIIDataReader
internal class ASCIIDataReader : IPnmDataReader
{
private StreamReader sr;
private System.Collections.Queue toks = new System.Collections.Queue();
private char[] WhiteSpaces = new char[] { ' ', '\t', '\r', '\n' };
public ASCIIDataReader(Stream fs)
{
this.sr = new StreamReader(fs, Encoding.ASCII);
}
public override void Close()
{
}
public override int Read(byte[] data, int index, int count)
{
int num = 0;
try
{
while (num < count)
{
data[index + num] = this.ReadByte();
num++;
}
}
catch
{
}
return num;
}
public override byte ReadByte()
{
if ((this.toks != null) && (this.toks.Count > 0))
{
return byte.Parse(this.toks.Dequeue().ToString());
}
string str = this.sr.ReadLine();
if (str == null)
{
throw new Exception("Unexpected end of file");
}
foreach (string str2 in str.Split(this.WhiteSpaces))
{
if (str2.Length > 0)
{
this.toks.Enqueue(str2);
}
}
return this.ReadByte();
}
public override string ReadLine()
{
return this.sr.ReadLine();
}
}
#endregion
#region BinaryDataReader
internal class BinaryDataReader : IPnmDataReader
{
private BinaryReader br;
private char EndLine = '\n';
public BinaryDataReader(Stream fs)
{
this.br = new BinaryReader(fs);
}
public override void Close()
{
}
public override int Read(byte[] data, int start, int length)
{
return this.br.Read(data, start, length);
}
public override byte ReadByte()
{
return this.br.ReadByte();
}
public override string ReadLine()
{
StringBuilder builder = new StringBuilder();
for (byte i = this.br.ReadByte(); i != this.EndLine; i = this.br.ReadByte())
{
builder.Append(((char)i).ToString());
}
return builder.ToString();
}
}
#endregion
#region IPnmDataReader
internal abstract class IPnmDataReader
{
public abstract void Close();
public abstract int Read(byte[] data, int index, int count);
public abstract byte ReadByte();
public abstract string ReadLine();
}
#endregion
}
#endregion
#region DataWriter
namespace DataWriter
{
#region ASCIIDataWriter
internal class ASCIIDataWriter : IPnmDataWriter
{
private StreamWriter sw;
public ASCIIDataWriter(Stream fs)
{
this.sw = new StreamWriter(fs);
}
public override void Close()
{
this.sw.Flush();
}
public override void WriteByte(byte data)
{
this.sw.Write(data.ToString() + " ");
}
public override void WriteLine(string line)
{
this.sw.WriteLine(line);
}
}
#endregion
#region BinaryDataWriter
internal class BinaryDataWriter : IPnmDataWriter
{
private BinaryWriter bw;
public BinaryDataWriter(Stream fs)
{
this.bw = new BinaryWriter(fs);
}
public override void Close()
{
this.bw.Flush();
}
public override void WriteByte(byte data)
{
this.bw.Write(data);
}
public override void WriteLine(string line)
{
this.bw.Write(Encoding.ASCII.GetBytes(line + "\n"));
}
}
#endregion
#region IPnmDataWriter
internal abstract class IPnmDataWriter
{
public abstract void Close();
public abstract void WriteByte(byte data);
public abstract void WriteLine(string line);
}
#endregion
}
#endregion
}
#endregion
}