Beispiel #1
0
        /// <summary>Matches based on the 128-byte header.</summary>
        /// <param name="loader"></param>
        /// <returns></returns>
        public override LoadMatchStrength LoadMatch(AssetLoader loader)
        {
            if (loader.Length < PcxHeader.ByteSize)
            {
                return(LoadMatchStrength.None);
            }
            PcxHeader header = new PcxHeader(loader.Reader);

            if (!header.IsValid)
            {
                return(LoadMatchStrength.None);
            }
            return(LoadMatchStrength.Strong);
        }
Beispiel #2
0
        /// <summary>Load the PCX image file.</summary>
        /// <param name="loader"></param>
        /// <returns></returns>
        public override Asset Load(AssetLoader loader)
        {
            BinaryReader reader = loader.Reader;
            PcxHeader header = new PcxHeader(reader);

            int pitch = (header.BitsPerPixel * header.ColorPlaneCount + 7) / 8 * header.SizeX;
            int[] data = new int[pitch * header.SizeY + 1];

            for (int row = 0; row < header.SizeY; row++) {
                switch (header.Compression) {
                    case PcxCompression.None:
                        for (int index = 0; index < pitch; index++)
                            data[pitch * row + index] = reader.ReadByte();
                        break;

                    case PcxCompression.RLE:
                        for (int offset = pitch * row, end = offset + header.BytesPerScanLine; offset < end; ) {
                            byte value = reader.ReadByte();

                            if (value < 0xC0) {
                                data[offset++] = value;
                            } else {
                                int runEnd = offset + value - 0xC0;
                                byte code = reader.ReadByte();

                                while (offset < runEnd)
                                    data[offset++] = code;
                            }
                        }
                        break;

                    default:
                        throw new NotImplementedException();
                }
            }

            PaletteAsset palette = null;

            if(header.ColorPlaneCount == 1) {
                if(reader.BaseStream.ReadByte() == PaletteMagic) {
                    palette = PaletteAsset.ReadRgb(Manager, loader.Name + " Palette", reader, 1 << header.BitsPerPixel, 255);
                }
            }

            if(palette != null)
                return new IndexedTextureAsset(loader, palette, header.SizeX, header.SizeY, data, pitch);
            else
                throw new NotImplementedException();
        }
Beispiel #3
0
        public static void Write(Stream stream, byte[] src, int w, int h, byte[] palette)
        {
            var hdr = new PcxHeader {
                manufacturer    = 10,
                version         = 5,
                encoding        = 1,
                xmin            = 0,
                ymin            = 0,
                xmax            = (ushort)(w - 1),
                ymax            = (ushort)(h - 1),
                bits_per_pixel  = 8,
                num_bits_planes = 1,
                bytes_per_line  = (ushort)w,
                h_scr_size      = 1,
                v_scr_size      = 1,
            };
            var hdrbuf = hdr.TypeCastStruct();

            stream.Write(hdrbuf, 0, hdrbuf.Length);

            // World's worst RLE compression, but I can't be bothered.
            for (var i = 0; i < src.Length; i++)
            {
                var ch = src[i];
                if (ch >= MARK)
                {
                    stream.WriteByte((byte)(MARK | 1));
                }
                stream.WriteByte(ch);
            }

            if (palette != null)
            {
                stream.WriteByte(0x0C);
                stream.Write(palette, 0, 768);
            }
        }
Beispiel #4
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);
            }
Beispiel #5
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;
            }
Beispiel #6
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);
        }
Beispiel #7
0
        public static Sprite Read(Stream stream)
        {
            PcxHeader header = stream.ReadStruct <PcxHeader>();

            if (header.bits_per_pixel != 8 || header.num_bits_planes != 1)
            {
                throw new Exception("Pcx is not a 256 color image");
            }

            int frame_w = header.xmax - header.xmin + 1;
            int frame_h = header.ymax - header.ymin + 1;

            byte[] frame;

            // uncompressed
            if (header.encoding == 0)
            {
                frame = stream.ReadBytes(frame_w * frame_h);
            }
            // rle compressed
            else
            {
                frame = new byte[frame_w * frame_h];
                int dstpos = 0;
                while (dstpos < frame.Length)
                {
                    int color = stream.ReadByte();
                    if (color < 0)
                    {
                        throw new Exception("Pcx corrupt header");
                    }
                    else if ((color & 0xc0) == 0xc0)
                    {
                        int count = color & 0x3f;
                        color = stream.ReadByte();
                        if (color < 0)
                        {
                            throw new Exception("Pcx corrupt header");
                        }
                        while (count-- > 0)
                        {
                            frame[dstpos++] = (byte)color;
                        }
                    }
                    else
                    {
                        frame[dstpos++] = (byte)color;
                    }
                }
            }

            // 256 color palette
            Palette palette = null;

            if (stream.ReadByte() == 0x0c)
            {
                palette = new Palette(stream, 0);
            }

            return(new Sprite(frame, frame_w, frame_h, palette));
        }
Beispiel #8
0
 /// <summary>Matches based on the 128-byte header.</summary>
 /// <param name="loader"></param>
 /// <returns></returns>
 public override LoadMatchStrength LoadMatch(AssetLoader loader)
 {
     if (loader.Length < PcxHeader.ByteSize)
         return LoadMatchStrength.None;
     PcxHeader header = new PcxHeader(loader.Reader);
     if (!header.IsValid)
         return LoadMatchStrength.None;
     return LoadMatchStrength.Strong;
 }
Beispiel #9
0
        /// <summary>Load the PCX image file.</summary>
        /// <param name="loader"></param>
        /// <returns></returns>
        public override Asset Load(AssetLoader loader)
        {
            BinaryReader reader = loader.Reader;
            PcxHeader    header = new PcxHeader(reader);

            int pitch = (header.BitsPerPixel * header.ColorPlaneCount + 7) / 8 * header.SizeX;

            int[] data = new int[pitch * header.SizeY + 1];

            for (int row = 0; row < header.SizeY; row++)
            {
                switch (header.Compression)
                {
                case PcxCompression.None:
                    for (int index = 0; index < pitch; index++)
                    {
                        data[pitch * row + index] = reader.ReadByte();
                    }
                    break;

                case PcxCompression.RLE:
                    for (int offset = pitch * row, end = offset + header.BytesPerScanLine; offset < end;)
                    {
                        byte value = reader.ReadByte();

                        if (value < 0xC0)
                        {
                            data[offset++] = value;
                        }
                        else
                        {
                            int  runEnd = offset + value - 0xC0;
                            byte code   = reader.ReadByte();

                            while (offset < runEnd)
                            {
                                data[offset++] = code;
                            }
                        }
                    }
                    break;

                default:
                    throw new NotImplementedException();
                }
            }

            PaletteAsset palette = null;

            if (header.ColorPlaneCount == 1)
            {
                if (reader.BaseStream.ReadByte() == PaletteMagic)
                {
                    palette = PaletteAsset.ReadRgb(Manager, loader.Name + " Palette", reader, 1 << header.BitsPerPixel, 255);
                }
            }

            if (palette != null)
            {
                return(new IndexedTextureAsset(loader, palette, header.SizeX, header.SizeY, data, pitch));
            }
            else
            {
                throw new NotImplementedException();
            }
        }