Exemple #1
0
            public override byte[] Encode(byte[] source, int sourceIndex, int width, int height)
            {
                // Destination data & index
                byte[] destination      = new byte[width * height * (PixelCodec.Bpp >> 3)];
                int    destinationIndex = 0;

                // Twiddle map
                int[] twiddleMap = MakeTwiddleMap(width);

                // Encode texture data
                for (int y = 0; y < height; y++)
                {
                    for (int x = 0; x < width; x++)
                    {
                        PixelCodec.EncodePixel(source, sourceIndex, destination, destinationIndex);
                        sourceIndex      += 4;
                        destinationIndex += (PixelCodec.Bpp >> 3);
                    }
                }

                return(destination);
            }
        public byte[] GetEncodedColorData(byte[] color, int index, bool bigEndian, PixelCodec pixelCodec)
        {
            byte[] data = new byte[pixelCodec == PixelCodec.ARGB8888 ? 4 : 2];
            switch (pixelCodec)
            {
            case PixelCodec.ARGB8888:
                if (bigEndian)
                {
                    data[0] = color[index];
                    data[1] = color[index + 1];
                    data[2] = color[index + 2];
                    data[3] = color[index + 3];
                }
                else
                {
                    data[0] = color[index + 3];
                    data[1] = color[index + 2];
                    data[2] = color[index + 1];
                    data[3] = color[index];
                }
                return(data);

            case PixelCodec.ARGB1555:
            case PixelCodec.ARGB4444:
            case PixelCodec.RGB565:
            default:
                if (bigEndian)
                {
                    data[0] = color[index + 1];
                    data[1] = color[index];
                }
                else
                {
                    data[0] = color[index];
                    data[1] = color[index + 1];
                }
                return(data);
            }
        }
Exemple #3
0
        public TexturePalette(bool gvp = false, PixelCodec codec = PixelCodec.RGB565)
        {
            StartBank  = 0;
            StartColor = 0;
            pixelCodec = codec;
            IsGVP      = gvp;
            Colors     = new List <Color>();
            int numcolor = 256;
            int red;
            int blue;
            int green;
            int gencolor = 0;

            for (int y = 0; y < 16; y++)
            {
                if (gencolor >= numcolor)
                {
                    break;
                }
                for (int x = 0; x < 16; x++)
                {
                    if (gencolor >= numcolor)
                    {
                        break;
                    }
                    int colorindex = x + 16 * y;
                    green = colorindex;
                    red   = x * 16;
                    blue  = y * 16;
                    Color rgb8   = Color.FromArgb(red, green, blue);
                    Color result = DecodeColor(EncodeColor(rgb8, pixelCodec), pixelCodec);
                    Colors.Add(result);
                    gencolor++;
                }
            }
        }
Exemple #4
0
        public MemoryStream EncodeTexture()
        {
            // Calculate what the length of the texture will be
            int textureLength = 16 + (TextureWidth * TextureHeight * DataCodec.Bpp / 8);

            if (HasGlobalIndex)
            {
                textureLength += 16;
            }
            if (DataCodec.PaletteEntries != 0 && !DataCodec.NeedsExternalPalette)
            {
                textureLength += (DataCodec.PaletteEntries * PixelCodec.Bpp / 8);
            }

            // Calculate the mipmap padding (if the texture contains mipmaps)
            int mipmapPadding = 0;

            if (DataCodec.HasMipmaps)
            {
                if (DataFormat == PvrDataFormat.SQUARE_TWIDDLED_MIPMAP)
                {
                    // A 1x1 mipmap takes up as much space as a 2x1 mipmap
                    // There are also 4 extra bytes at the end of the file
                    mipmapPadding  = (DataCodec.Bpp) >> 3;
                    textureLength += 4;
                }
                else if (DataFormat == PvrDataFormat.SQUARE_TWIDDLED_MIPMAP_ALT)
                {
                    // A 1x1 mipmap takes up as much space as a 2x2 mipmap
                    mipmapPadding = (3 * DataCodec.Bpp) >> 3;
                }

                textureLength += mipmapPadding;

                for (int size = 1; size < TextureWidth; size <<= 1)
                {
                    textureLength += Math.Max((size * size * DataCodec.Bpp) >> 3, 1);
                }
            }

            MemoryStream destination = new MemoryStream(textureLength);

            // Write out the GBIX header (if we are including one)
            if (HasGlobalIndex)
            {
                destination.WriteByte((byte)'G');
                destination.WriteByte((byte)'B');
                destination.WriteByte((byte)'I');
                destination.WriteByte((byte)'X');

                PTStream.WriteUInt32(destination, 8);
                PTStream.WriteUInt32(destination, GlobalIndex);
                PTStream.WriteUInt32(destination, 0);
            }

            // Write out the PVRT header
            destination.WriteByte((byte)'P');
            destination.WriteByte((byte)'V');
            destination.WriteByte((byte)'R');
            destination.WriteByte((byte)'T');

            if (HasGlobalIndex)
            {
                PTStream.WriteInt32(destination, textureLength - 24);
            }
            else
            {
                PTStream.WriteInt32(destination, textureLength - 8);
            }

            destination.WriteByte((byte)PixelFormat);
            destination.WriteByte((byte)DataFormat);
            PTStream.WriteUInt16(destination, 0);

            PTStream.WriteUInt16(destination, TextureWidth);
            PTStream.WriteUInt16(destination, TextureHeight);

            // If we have an internal palette, write it
            if (DataCodec.PaletteEntries != 0 && !DataCodec.NeedsExternalPalette)
            {
                byte[] palette = PixelCodec.EncodePalette(m_texturePalette, DataCodec.PaletteEntries);
                destination.Write(palette, 0, palette.Length);
            }

            // Write out any mipmaps
            if (DataCodec.HasMipmaps)
            {
                // Write out any padding bytes before the 1x1 mipmap
                for (int i = 0; i < mipmapPadding; i++)
                {
                    destination.WriteByte(0);
                }

                for (int size = 1; size < TextureWidth; size <<= 1)
                {
                    byte[] mipmapDecodedData = null;
                    if (DataCodec.NeedsExternalPalette)
                    {
                        if (DataCodec.VQ)
                        {
                            mipmapDecodedData = BitmapToRawVQResized(m_decodedBitmap, size, 1, m_codeBook);
                        }
                        else
                        {
                            mipmapDecodedData = BitmapToRawIndexedResized(m_decodedBitmap, size, 1, m_palette);
                        }
                    }
                    else
                    {
                        mipmapDecodedData = BitmapToRawResized(m_decodedBitmap, size, 1);
                    }

                    byte[] mipmapTextureData = DataCodec.Encode(mipmapDecodedData, 0, size, size);
                    destination.Write(mipmapTextureData, 0, mipmapTextureData.Length);
                }
            }

            // Write the texture data
            byte[] textureData = DataCodec.Encode(m_decodedData, TextureWidth, TextureHeight, null);
            destination.Write(textureData, 0, textureData.Length);

            // If the data format is square twiddled with mipmaps, write out the extra bytes.
            if (DataFormat == PvrDataFormat.SQUARE_TWIDDLED_MIPMAP)
            {
                destination.Write(new byte[] { 0, 0, 0, 0 }, 0, 4);
            }

            // Compress the texture
            if (CompressionFormat != PvrCompressionFormat.NONE)
            {
                CompressionCodec = PvrCompressionCodec.GetCompressionCodec(CompressionFormat);

                if (CompressionCodec != null)
                {
                    // Ok, we need to convert the current stream to an array, compress it, then write it back to a new stream
                    byte[] buffer = destination.ToArray();
                    buffer = CompressionCodec.Compress(buffer, (HasGlobalIndex ? 0x20 : 0x10), PixelCodec, DataCodec);

                    destination = new MemoryStream();
                    destination.Write(buffer, 0, buffer.Length);
                }
            }

            return(destination);
        }
Exemple #5
0
        public Color DecodeColor(byte[] rgb, PixelCodec codec)
        {
            int a = 255;
            int r;
            int g;
            int b;

            switch (codec)
            {
            case PixelCodec.ARGB1555:
                a = (byte)(((BitConverter.ToUInt16(rgb, 0) >> 15) & 0x01) * 0xFF);
                r = (byte)(((BitConverter.ToUInt16(rgb, 0) >> 10) & 0x1F) * 0xFF / 0x1F);
                g = (byte)(((BitConverter.ToUInt16(rgb, 0) >> 5) & 0x1F) * 0xFF / 0x1F);
                b = (byte)(((BitConverter.ToUInt16(rgb, 0) >> 0) & 0x1F) * 0xFF / 0x1F);
                break;

            case PixelCodec.ARGB4444:
                a = (byte)(((BitConverter.ToUInt16(rgb, 0) >> 12) & 0x0F) * 0xFF / 0x0F);
                r = (byte)(((BitConverter.ToUInt16(rgb, 0) >> 8) & 0x0F) * 0xFF / 0x0F);
                g = (byte)(((BitConverter.ToUInt16(rgb, 0) >> 4) & 0x0F) * 0xFF / 0x0F);
                b = (byte)(((BitConverter.ToUInt16(rgb, 0) >> 0) & 0x0F) * 0xFF / 0x0F);
                break;

            case PixelCodec.RGB5A3:
                ushort pixel = BitConverter.ToUInt16(rgb, 0);
                if ((pixel & 0x8000) != 0)     // RGB555
                {
                    a = 255;
                    r = (byte)(((BitConverter.ToUInt16(rgb, 0) >> 10) & 0x1F) * 0xFF / 0x1F);
                    g = (byte)(((BitConverter.ToUInt16(rgb, 0) >> 5) & 0x1F) * 0xFF / 0x1F);
                    b = (byte)(((BitConverter.ToUInt16(rgb, 0) >> 0) & 0x1F) * 0xFF / 0x1F);
                }
                else     // ARGB34444
                {
                    a = (byte)(((BitConverter.ToUInt16(rgb, 0) >> 12) & 0x07) * 0xFF / 0x07);
                    r = (byte)(((BitConverter.ToUInt16(rgb, 0) >> 8) & 0x0F) * 0xFF / 0x0F);
                    g = (byte)(((BitConverter.ToUInt16(rgb, 0) >> 4) & 0x0F) * 0xFF / 0x0F);
                    b = (byte)(((BitConverter.ToUInt16(rgb, 0) >> 0) & 0x0F) * 0xFF / 0x0F);
                }
                break;

            case PixelCodec.Intensity8A:
                a = rgb[0];
                r = rgb[1];
                g = rgb[1];
                b = rgb[1];
                break;

            case PixelCodec.ARGB8888:
                a = rgb[0];
                r = rgb[1];
                g = rgb[2];
                b = rgb[3];
                break;

            case PixelCodec.RGB565:
            default:
                r = (byte)(((BitConverter.ToUInt16(rgb, 0) >> 11) & 0x1F) * 0xFF / 0x1F);
                g = (byte)(((BitConverter.ToUInt16(rgb, 0) >> 5) & 0x3F) * 0xFF / 0x3F);
                b = (byte)(((BitConverter.ToUInt16(rgb, 0) >> 0) & 0x1F) * 0xFF / 0x1F);
                break;
            }
            return(Color.FromArgb(a, r, g, b));
        }
Exemple #6
0
        public byte[] EncodeColor(Color color, PixelCodec pixelCodec)
        {
            byte[] result = new byte[pixelCodec == PixelCodec.ARGB8888 ? 4 : 2];
            ushort pixel  = 0x0000;

            switch (pixelCodec)
            {
            case PixelCodec.ARGB1555:
                pixel    |= (ushort)((color.A >> 7) << 15);
                pixel    |= (ushort)((color.R >> 3) << 10);
                pixel    |= (ushort)((color.G >> 3) << 5);
                pixel    |= (ushort)((color.B >> 3) << 0);
                result[1] = (byte)((pixel >> 8) & 0xFF);
                result[0] = (byte)(pixel & 0xFF);
                break;

            case PixelCodec.ARGB4444:
                pixel    |= (ushort)((color.A >> 4) << 12);
                pixel    |= (ushort)((color.R >> 4) << 8);
                pixel    |= (ushort)((color.G >> 4) << 4);
                pixel    |= (ushort)((color.B >> 4) << 0);
                result[1] = (byte)((pixel >> 8) & 0xFF);
                result[0] = (byte)(pixel & 0xFF);
                break;

            case PixelCodec.ARGB8888:
                result[3] = color.A;
                result[2] = color.R;
                result[1] = color.G;
                result[0] = color.B;
                break;

            case PixelCodec.Intensity8A:
                result[1] = color.A;
                result[0] = (byte)((0.30 * color.R) + (0.59 * color.G) + (0.11 * color.B));
                break;

            case PixelCodec.RGB5A3:
                if (color.A <= 0xDA)     // Argb3444
                {
                    pixel |= (ushort)((color.A >> 5) << 12);
                    pixel |= (ushort)((color.R >> 4) << 8);
                    pixel |= (ushort)((color.G >> 4) << 4);
                    pixel |= (ushort)((color.B >> 4) << 0);
                }
                else     // Rgb555
                {
                    pixel |= 0x8000;
                    pixel |= (ushort)((color.R >> 3) << 10);
                    pixel |= (ushort)((color.G >> 3) << 5);
                    pixel |= (ushort)((color.B >> 3) << 0);
                }
                result[1] = (byte)(pixel & 0xFF);
                result[0] = (byte)((pixel >> 8) & 0xFF);
                break;

            case PixelCodec.RGB565:
            default:
                pixel    |= (ushort)((color.R >> 3) << 11);
                pixel    |= (ushort)((color.G >> 2) << 5);
                pixel    |= (ushort)((color.B >> 3) << 0);
                result[1] = (byte)((pixel >> 8) & 0xFF);
                result[0] = (byte)(pixel & 0xFF);
                break;
            }
            return(result);
        }
Exemple #7
0
        /// <summary>
        /// Internal write implementation of the sub classes.
        /// </summary>
        /// <param name="writer"></param>
        /// <exception cref="Exception">Expected DDS RGB24 or RGBA32 color format!</exception>
        /// <exception cref="InvalidOperationException">
        /// </exception>
        protected override void _Write(BinaryWriter writer)
        {
            long baseOffset = writer.BaseStream.Position;

            Bitmap bmp = CreateBitmap();

            //bmp.RotateFlip(RotateFlipType.RotateNoneFlipY);
            if (DataFormat == PvrDataFormat.DDS || DataFormat == PvrDataFormat.DDS_2)
            {
                if (!(PixelFormat == PvrPixelFormat.DDS_DXT1_RGB24 || PixelFormat == PvrPixelFormat.DDS_DXT3_RGBA32))
                {
                    throw new Exception("Expected DDS RGB24 or RGBA32 color format!");
                }

                byte[] ddsBuffer = null;
                if (PixelFormat == PvrPixelFormat.DDS_DXT1_RGB24)
                {
                    DDSFormatDetails ddsFormatDetails = new DDSFormatDetails(DDSFormat.DDS_DXT1);
                    ddsBuffer = DDSGeneral.Save(MipMaps, ddsFormatDetails, DDSGeneral.AlphaSettings.KeepAlpha, DDSGeneral.MipHandling.Default);
                }
                else if (PixelFormat == PvrPixelFormat.DDS_DXT3_RGBA32)
                {
                    DDSFormatDetails ddsFormatDetails = new DDSFormatDetails(DDSFormat.DDS_DXT3);
                    ddsBuffer = DDSGeneral.Save(MipMaps, ddsFormatDetails, DDSGeneral.AlphaSettings.KeepAlpha, DDSGeneral.MipHandling.Default);
                }
                if (HasGlobalIndex)
                {
                    writer.Write(m_gbix);
                    writer.Write(GlobalIndexSize);
                    writer.Write(GlobalIndex);
                }

                writer.Write(m_pvrt);
                writer.Write(ddsBuffer.Length + 16);
                writer.Write((byte)PixelFormat);
                writer.Write((byte)DataFormat);
                writer.Write((ushort)0);
                writer.Write((ushort)Width);
                writer.Write((ushort)Height);
                writer.Write(ddsBuffer);
            }
            else
            {
                // Set the data format and pixel format and load the appropiate codecs
                PixelCodec = PvrPixelCodec.GetPixelCodec(PixelFormat);
                DataCodec  = PvrDataCodec.GetDataCodec(DataFormat);

                // Make sure the pixel and data codecs exists and we can encode to it
                if (PixelCodec == null || !PixelCodec.CanEncode)
                {
                    throw new InvalidOperationException();
                }
                if (DataCodec == null || !DataCodec.CanEncode)
                {
                    throw new InvalidOperationException();
                }
                DataCodec.PixelCodec = PixelCodec;

                byte[] decodedData = null;
                if (DataCodec.PaletteEntries != 0)
                {
                    if (DataCodec.VQ)
                    {
                        decodedData = BitmapToRawVQ(bmp, DataCodec.PaletteEntries, out m_texturePalette);
                    }
                    else
                    {
                        // Convert the bitmap to an array containing indicies.
                        decodedData = BitmapToRawIndexed(bmp, DataCodec.PaletteEntries, out m_texturePalette);

                        // If this texture has an external palette file, set up the palette encoder
                        if (DataCodec.NeedsExternalPalette)
                        {
                            PaletteEncoder = new PvpPaletteEncoder(m_texturePalette, (ushort)DataCodec.PaletteEntries, PixelFormat, PixelCodec);
                        }
                    }
                }
                else
                {
                    decodedData = BitmapToRaw(bmp);
                }

                // Calculate what the length of the texture will be
                int textureLength = 16 + (int)(Width * Height * (DataCodec.Bpp / 8.0));
                if (HasGlobalIndex)
                {
                    textureLength += 16;
                }
                if (DataCodec.PaletteEntries != 0 && !DataCodec.NeedsExternalPalette)
                {
                    textureLength += (DataCodec.PaletteEntries * PixelCodec.Bpp / 8);
                }

                // Calculate the mipmap padding (if the texture contains mipmaps)
                int mipmapPadding = 0;
                if (DataCodec.HasMipmaps)
                {
                    if (DataFormat == PvrDataFormat.SQUARE_TWIDDLED_MIPMAP)
                    {
                        // A 1x1 mipmap takes up as much space as a 2x1 mipmap
                        // There are also 4 extra bytes at the end of the file
                        mipmapPadding  = (DataCodec.Bpp) >> 3;
                        textureLength += 4;
                    }
                    else if (DataFormat == PvrDataFormat.SQUARE_TWIDDLED_MIPMAP_ALT)
                    {
                        // A 1x1 mipmap takes up as much space as a 2x2 mipmap
                        mipmapPadding = (3 * DataCodec.Bpp) >> 3;
                    }

                    textureLength += mipmapPadding;
                    for (int size = 1; size < Width; size <<= 1)
                    {
                        textureLength += Math.Max((size * size * DataCodec.Bpp) >> 3, 1);
                    }
                }

                MemoryStream output       = new MemoryStream(textureLength);
                BinaryWriter outputWriter = new BinaryWriter(output);

                // Write out the GBIX header (if we are including one)
                if (HasGlobalIndex)
                {
                    outputWriter.Write(m_gbix);
                    outputWriter.Write(GlobalIndexSize);
                    outputWriter.Write(GlobalIndex);
                }

                // Write out the PVRT header
                outputWriter.Write(m_pvrt);
                if (HasGlobalIndex)
                {
                    outputWriter.Write(textureLength - 24);
                }
                else
                {
                    outputWriter.Write(textureLength - 8);
                }
                outputWriter.Write((byte)PixelFormat);
                outputWriter.Write((byte)DataFormat);
                outputWriter.Write((ushort)0);
                outputWriter.Write((ushort)Width);
                outputWriter.Write((ushort)Height);

                // If we have an internal palette, write it
                if (DataCodec.PaletteEntries != 0 && !DataCodec.NeedsExternalPalette)
                {
                    byte[] palette = PixelCodec.EncodePalette(m_texturePalette, DataCodec.PaletteEntries);
                    output.Write(palette, 0, palette.Length);
                }

                // Write out any mipmaps
                if (DataCodec.HasMipmaps)
                {
                    // Write out any padding bytes before the 1x1 mipmap
                    for (int i = 0; i < mipmapPadding; i++)
                    {
                        output.WriteByte(0);
                    }
                    for (int size = 1; size < Width; size <<= 1)
                    {
                        byte[] mipmapDecodedData = null;
                        if (DataCodec.NeedsExternalPalette)
                        {
                            if (DataCodec.VQ)
                            {
                                mipmapDecodedData = BitmapToRawVQResized(bmp, size, 1, m_codeBook);
                            }
                            else
                            {
                                mipmapDecodedData = BitmapToRawIndexedResized(bmp, size, 1, m_palette);
                            }
                        }
                        else
                        {
                            mipmapDecodedData = BitmapToRawResized(bmp, size, 1);
                        }
                        byte[] mipmapTextureData = DataCodec.Encode(mipmapDecodedData, 0, size, size);
                        output.Write(mipmapTextureData, 0, mipmapTextureData.Length);
                    }
                }

                // Write the texture data
                byte[] textureData = DataCodec.Encode(decodedData, Width, Height, null);
                output.Write(textureData, 0, textureData.Length);

                // If the data format is square twiddled with mipmaps, write out the extra bytes.
                if (DataFormat == PvrDataFormat.SQUARE_TWIDDLED_MIPMAP)
                {
                    output.Write(new byte[] { 0, 0, 0, 0 }, 0, 4);
                }

                // Compress the texture
                if (CompressionFormat != PvrCompressionFormat.NONE)
                {
                    CompressionCodec = PvrCompressionCodec.GetCompressionCodec(CompressionFormat);
                    if (CompressionCodec != null)
                    {
                        // Ok, we need to convert the current stream to an array, compress it, then write it back to a new stream
                        byte[] buffer = output.ToArray();
                        buffer = CompressionCodec.Compress(buffer, (HasGlobalIndex ? 0x20 : 0x10), PixelCodec, DataCodec);
                        writer.Write(buffer);
                    }
                }
                else
                {
                    writer.Write(output.GetBuffer());
                }
            }
        }