Ejemplo n.º 1
0
            //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);
            }
Ejemplo n.º 2
0
        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);
        }