//private class pcx_t //{ // public char manufacturer; // public char version; // public char encoding; // public char bits_per_pixel; // public short xmin, ymin, xmax, ymax; // public short hres, vres; // public int[] palette = new int[48]; // public char reserved; // public char color_planes; // public short bytes_per_line; // public short palette_type; // public byte[] filler = new byte[58]; // public byte[] data; // public pcx_t(byte[] raw) // { // manufacturer = (char)raw[0]; // version = (char)raw[1]; // encoding = (char)raw[2]; // bits_per_pixel = (char)raw[3]; // xmin = (short)((raw[4] + (raw[5] << 8)) & 0xff); // ymin = (short)((raw[6] + (raw[7] << 8)) & 0xff); // xmax = (short)((raw[8] + (raw[9] << 8)) & 0xff); // ymax = (short)((raw[10] + (raw[11] << 8)) & 0xff); // hres = (short)((raw[12] + (raw[13] << 8)) & 0xff); // vres = (short)((raw[14] + (raw[15] << 8)) & 0xff); // for (int i = 0; i < 48; i++) // palette[i] = (raw[16 + i] & 0xff); // reserved = (char)raw[64]; // color_planes = (char)raw[65]; // bytes_per_line = (short)((raw[66] + (raw[67] << 8)) & 0xff); // palette_type = (short)((raw[68] + (raw[69] << 8)) & 0xff); // for (int i = 0; i < 58; i++) // filler[i] = raw[70 + i]; // data = new byte[raw.Length - 128]; // for (int i = 0; i < raw.Length - 128; i++) // data[i] = raw[128 + i]; // } //} //private static byte[] imageData; //private static int imageWidth, imageHeight; //public static Image Load(Stream s) //{ // int[] palette, pic, ot, pix; // int k, x, y, len = 0, dataByte, runLength; // byte[] raw; // pcx_t pcx; // raw = new byte[s.Length]; // s.Read(raw, 0, (int)s.Length); // pcx = new pcx_t(raw); // raw = pcx.data; // if (pcx.manufacturer != 0x0a || pcx.version != 5 || pcx.encoding != 1 || pcx.bits_per_pixel != 8 || pcx.xmax >= 640 || pcx.ymax >= 480) // { // throw new Exception("Bad Pcx Data!"); // } // palette = new int[768]; // for (int i = 0; i < 768; i++) // { // if ((uint)(len - 128 - 768 + i) < pcx.data.Length) // { // palette[i] = pcx.data[len - 128 - 768 + i] & 0xff; // } // } // imageWidth = pcx.xmax + 1; // imageHeight = pcx.ymax + 1; // ot = new int[(pcx.ymax + 1) * (pcx.xmax + 1)]; // pic = ot; // pix = ot; // int pixcount = 0; // int rawcount = 0; // for (y = 0; y <= pcx.ymax; y++, pixcount += pcx.xmax + 1) // { // for (x = 0; x <= pcx.xmax; ) // { // dataByte = raw[rawcount++]; // if ((dataByte & 0xC0) == 0xC0) // { // runLength = dataByte & 0x3F; // dataByte = raw[rawcount++]; // } // else // runLength = 1; // while (runLength-- > 0) // pix[pixcount + x++] = dataByte & 0xff; // } // } // Image im = new Image(imageWidth, imageHeight); // imageData = new byte[imageWidth * imageHeight * 4]; // //convert to rgb format // for (k = 0; k < (imageWidth * imageHeight); k++) // { // imageData[k * 4] = (byte)palette[pic[k] * 3]; // imageData[k * 4 + 1] = (byte)palette[pic[k] * 3 + 1]; // imageData[k * 4 + 2] = (byte)palette[pic[k] * 3 + 2]; // imageData[k * 4 + 3] = 0xff; // } // uint ndx = 0; // for (uint yloc = 0; yloc < imageHeight; yloc++) // { // for (uint xloc = 0; xloc < imageWidth; xloc++) // { // im.SetPixel(xloc, yloc, new Pixel(imageData[ndx], imageData[ndx + 1], imageData[ndx + 2], imageData[ndx + 3])); // ndx += 4; // } // } // return im; //} #endregion #region Load public static Image Load(Stream input) { PcxPalette palette = null; uint[] numArray = null; Image im; PcxHeader header = new PcxHeader(input); #region Checks if (header.id != PcxId.ZSoftPCX) { throw new FormatException("Not a PCX file."); } if (((header.version != PcxVersion.Version3_0) && (header.version != PcxVersion.Version2_8_Palette)) && ((header.version != PcxVersion.Version2_8_DefaultPalette) && (header.version != PcxVersion.Version2_5))) { throw new FormatException("Unsupported PCX version: " + header.version.ToString()); } if (((header.bitsPerPixel != 1) && (header.bitsPerPixel != 2)) && ((header.bitsPerPixel != 4) && (header.bitsPerPixel != 8))) { throw new FormatException("Unsupported PCX bits per pixel: " + header.bitsPerPixel.ToString() + " bits per pixel"); } int width = (header.xMax - header.xMin) + 1; int height = (header.yMax - header.yMin) + 1; if (((width < 0) || (height < 0)) || ((width > 0xffff) || (height > 0xffff))) { throw new FormatException("Invalid image dimensions: (" + header.xMin.ToString() + "," + header.yMin.ToString() + ")-(" + header.xMax.ToString() + "," + header.yMax.ToString() + ")"); } int num3 = (header.bytesPerLine * 8) / header.bitsPerPixel; int BitDepth = header.bitsPerPixel * header.nPlanes; if ((((BitDepth != 1) && (BitDepth != 2)) && ((BitDepth != 4) && (BitDepth != 8))) && (BitDepth != 0x18)) { throw new FormatException("Unsupported PCX bit depth: " + BitDepth.ToString()); } #endregion #region Load Palette while (true) { if (BitDepth == 1) { palette = PcxPalette.FromEgaPalette(PcxPalette.MONO_PALETTE); break; } if (BitDepth >= 8) { if (BitDepth == 8) { long position = input.Position; input.Seek(-769L, SeekOrigin.End); if (input.ReadByte() != 12) { throw new FormatException("PCX palette marker not present in file"); } palette = new PcxPalette(input, 0x100); input.Seek(position, SeekOrigin.Begin); } else { palette = new PcxPalette(0x100); } break; } switch (header.version) { case PcxVersion.Version2_5: case PcxVersion.Version2_8_DefaultPalette: if (BitDepth == 2) { numArray = PcxPalette.CGA_PALETTE; palette = PcxPalette.FromEgaPalette(numArray); } break; default: numArray = new uint[0]; palette = PcxPalette.FromColorMap(header.colorMap); break; } if (numArray == null) { numArray = PcxPalette.EGA_PALETTE; } break; } #endregion im = new Image(width, height); uint[] array = new uint[width]; for (int y = 0; y < height; y++) { PcxByteReader byteReader = (header.encoding == PcxEncoding.RunLengthEncoded) ? ((PcxByteReader) new PcxRleByteReader(input)) : ((PcxByteReader) new PcxRawByteReader(input)); PcxIndexReader indxReader = new PcxIndexReader(byteReader, header.bitsPerPixel); for (int j = 0; j < header.nPlanes; j++) { for (int m = 0; m < num3; m++) { uint num10 = indxReader.ReadIndex(); if (m < width) { array[m] |= num10 << (j * header.bitsPerPixel); } } } for (int x = 0; x < width; x++) { Pixel bgra; uint TempC = array[x]; if (BitDepth == 24) { byte r = (byte)(TempC & 0xff); byte g = (byte)((TempC >> 8) & 0xff); byte b = (byte)((TempC >> 16) & 0xff); bgra = new Pixel(r, g, b, 255); } else { bgra = palette[TempC]; } im.SetPixel((uint)x, (uint)y, bgra); } } return(im); }
public bool Load(byte[] data) { Stream input = new MemoryStream(data); // // Load and validate header // PcxHeader header = new PcxHeader(input); if (header.id != PcxId.ZSoftPCX) { throw new FormatException("Not a PCX file."); } if (header.version != PcxVersion.Version3_0 && header.version != PcxVersion.Version2_8_Palette && header.version != PcxVersion.Version2_8_DefaultPalette && header.version != PcxVersion.Version2_5) { throw new FormatException(String.Format("Unsupported PCX version: {0}", header.version)); } if (header.bitsPerPixel != 1 && header.bitsPerPixel != 2 && header.bitsPerPixel != 4 && header.bitsPerPixel != 8) { throw new FormatException(String.Format("Unsupported PCX bits per pixel: {0} bits per pixel", header.bitsPerPixel)); } int width = header.xMax - header.xMin + 1; int height = header.yMax - header.yMin + 1; if (width < 0 || height < 0 || width > 0xffff || height > 0xffff) { throw new FormatException(String.Format("Invalid image dimensions: ({0},{1})-({2},{3})", header.xMin, header.yMin, header.xMax, header.yMax)); } // Pixels per line, including PCX's even-number-of-pixels buffer int pixelsPerLine = header.bytesPerLine * 8 /*bitsPerByte*/ / header.bitsPerPixel; // Bits per pixel, including all bit planes int bitsPerPixel = header.bitsPerPixel * header.nPlanes; if (bitsPerPixel != 1 && bitsPerPixel != 2 && bitsPerPixel != 4 && bitsPerPixel != 8 && bitsPerPixel != 24) { throw new FormatException(String.Format("Unsupported PCX bit depth: {0}", bitsPerPixel)); } // // Load the palette // if (bitsPerPixel == 1) { // HACK: Monochrome images don't always include a resonable palette in v3.0. // Default them to black and white in all cases palette = PcxPalette.FromEgaPalette(PcxPalette.MONO_PALETTE); } else if (bitsPerPixel < 8) { // 16-color palette in the ColorMap portion of the header switch (header.version) { case PcxVersion.Version2_5: case PcxVersion.Version2_8_DefaultPalette: { uint[] paletteEga; switch (bitsPerPixel) { // 4-color CGA palette case 2: paletteEga = PcxPalette.CGA_PALETTE; break; // 16-color EGA palette default: case 4: paletteEga = PcxPalette.EGA_PALETTE; break; } palette = PcxPalette.FromEgaPalette(paletteEga); break; } default: case PcxVersion.Version2_8_Palette: case PcxVersion.Version3_0: { palette = PcxPalette.FromColorMap(header.colorMap); break; } } } else if (bitsPerPixel == 8) { // 256-color palette is saved at the end of the file, with one byte marker long dataPosition = input.Position; input.Seek(-(1 + (256 * 3)), SeekOrigin.End); if (input.ReadByte() != PcxPaletteMarker) { throw new FormatException("PCX palette marker not present in file"); } palette = new PcxPalette(input, 256); input.Seek(dataPosition, SeekOrigin.Begin); } else { // Dummy palette for 24-bit images palette = new PcxPalette(256); } // // Load the pixel data // bitmap = new Bitmap(width, height); // Accumulate indices across bit planes uint[] indexBuffer = new uint[width]; for (int y = 0; y < height; y++) { Array.Clear(indexBuffer, 0, width); // Decode the RLE byte stream PcxByteReader byteReader = (header.encoding == PcxEncoding.RunLengthEncoded) ? new PcxRleByteReader(input) : (PcxByteReader) new PcxRawByteReader(input); // Read indices of a given length out of the byte stream PcxIndexReader indexReader = new PcxIndexReader(byteReader, header.bitsPerPixel); // Planes are stored consecutively for each scan line for (int plane = 0; plane < header.nPlanes; plane++) { for (int x = 0; x < pixelsPerLine; x++) { uint index = indexReader.ReadIndex(); // Account for padding bytes if (x < width) { indexBuffer[x] = indexBuffer[x] | (index << (plane * header.bitsPerPixel)); } } } for (int x = 0; x < width; x++) { uint index = indexBuffer[x]; Color color; if (bitsPerPixel == 24) { byte r = (byte)((index) & 0xff); byte g = (byte)((index >> 8) & 0xff); byte b = (byte)((index >> 16) & 0xff); color = Color.FromArgb(255, r, g, b); } else { color = palette[index]; } bitmap.SetPixel(x, y, color); } } return(true); }