Example #1
0
        private bool Initalize(Bitmap source, GimPaletteFormat paletteFormat, GimDataFormat dataFormat)
        {
            // Make sure this bitmap's dimensions are valid
            if (!HasValidDimensions(source.Width, source.Height))
            {
                return(false);
            }

            textureWidth  = (ushort)source.Width;
            textureHeight = (ushort)source.Height;

            // Set default values
            hasMetadata = true;
            metadata    = new GimMetadata();

            // Set the data format and palette format and load the appropiate codecs
            this.dataFormat = dataFormat;
            dataCodec       = GimDataCodec.GetDataCodec(dataFormat);

            // Make sure the data codec exists and we can encode to it
            if (dataCodec == null || !dataCodec.CanEncode)
            {
                return(false);
            }

            // Only palettized formats require a pixel codec.
            if (dataCodec.PaletteEntries != 0)
            {
                this.paletteFormat = paletteFormat;
                pixelCodec         = GimPixelCodec.GetPixelCodec(paletteFormat);

                // Make sure the pixel codec exists and we can encode to it
                if (pixelCodec == null || !pixelCodec.CanEncode)
                {
                    return(false);
                }

                dataCodec.PixelCodec = pixelCodec;

                // Convert the bitmap to an array containing indicies.
                decodedData = BitmapToRawIndexed(source, dataCodec.PaletteEntries, out texturePalette);
            }
            else
            {
                this.paletteFormat = GimPaletteFormat.Unknown;
                pixelCodec         = null;

                // Convert the bitmap to an array
                decodedData = BitmapToRaw(source);
            }

            return(true);
        }
Example #2
0
        // Decodes a texture
        private byte[] DecodeTexture()
        {
            // Make sure we can decode this texture
            if (!canDecode)
            {
                throw new CannotDecodeTextureException("Cannot decode texture. The palette format and/or data format may not be supported.");
            }

            if (paletteOffset != -1) // The texture contains an embedded palette
            {
                dataCodec.SetPalette(encodedData, paletteOffset, paletteEntries);
            }

            if (swizzled)
            {
                return(dataCodec.Decode(GimDataCodec.UnSwizzle(encodedData, dataOffset, textureWidth, textureHeight, dataCodec.Bpp), 0, textureWidth, textureHeight));
            }

            return(dataCodec.Decode(encodedData, dataOffset, textureWidth, textureHeight));
        }
Example #3
0
        private void Initalize()
        {
            // Check to see if what we are dealing with is a GIM texture
            if (!Is(encodedData))
            {
                throw new NotAValidTextureException("This is not a valid GIM texture.");
            }

            // Initalize some things
            paletteFormat = GimPaletteFormat.Unknown;
            dataFormat = GimDataFormat.Unknown;

            paletteEntries = 0;
            paletteOffset = -1;
            dataOffset = -1;

            hasMetadata = false;

            // A GIM is constructed of different chunks. They do not necessarily have to be in order.
            int eofOffset = -1;

            int offset = 0x10;
            int previousOffset = offset;
            while (offset < encodedData.Length)
            {
                // EOF offset chunk
                if (encodedData[offset] == 0x02)
                {
                    eofOffset = BitConverter.ToInt32(encodedData, offset + 0x04) + 16;

                    // Go to the next chunk
                    offset += BitConverter.ToInt32(encodedData, offset + 0x08);
                }

                // Metadata offset chunk
                else if (encodedData[offset] == 0x03)
                {
                    // Skip this chunk. It's not necessary for decoding this texture.
                    offset += BitConverter.ToInt32(encodedData, offset + 0x08);
                }

                // Texture data
                else if (encodedData[offset] == 0x04)
                {
                    // Get the data format
                    dataFormat = (GimDataFormat)encodedData[offset + 0x14];

                    // Get the data codec and make sure we can decode using it
                    dataCodec = GimDataCodec.GetDataCodec(dataFormat);

                    // Check to see if the texture data is swizzled
                    swizzled = (BitConverter.ToUInt16(encodedData, offset + 0x16) == 1);

                    // Get the texture's width and height
                    textureWidth  = BitConverter.ToUInt16(encodedData, offset + 0x18);
                    textureHeight = BitConverter.ToUInt16(encodedData, offset + 0x1A);

                    // Some textures do not have a width that is a multiple or 16 or a height that is a multiple of 8.
                    // We'll just do it the lazy way and set their width/height to a multiple of 16/8.
                    if (textureWidth % 16 != 0)
                    {
                        textureWidth = (ushort)PTMethods.RoundUp(textureWidth, 16);
                    }
                    if (textureHeight % 8 != 0)
                    {
                        textureHeight = (ushort)PTMethods.RoundUp(textureHeight, 8);
                    }

                    // Set the offset of the texture data
                    dataOffset = offset + 0x50;

                    // Go to the next chunk
                    offset += BitConverter.ToInt32(encodedData, offset + 0x08);
                }

                // Palette data
                else if (encodedData[offset] == 0x05)
                {
                    // Get the palette format
                    paletteFormat = (GimPaletteFormat)encodedData[offset + 0x14];

                    // Get the pixel codec and make sure we can decode using it
                    pixelCodec = GimPixelCodec.GetPixelCodec(paletteFormat);

                    // Get the number of entries in the palette
                    paletteEntries = BitConverter.ToUInt16(encodedData, offset + 0x18);

                    // Set the offset of the palette data
                    paletteOffset = offset + 0x50;

                    // Go to the next chunk
                    offset += BitConverter.ToInt32(encodedData, offset + 0x08);
                }

                // Metadata chunk
                else if (encodedData[offset] == 0xFF)
                {
                    // Read in some metadata
                    hasMetadata = true;
                    metadata = new GimMetadata();

                    int metadataOffset = 0x10;

                    metadata.OriginalFilename = PTMethods.StringFromBytes(encodedData, offset + metadataOffset);
                    metadataOffset += metadata.OriginalFilename.Length + 1;

                    metadata.User = PTMethods.StringFromBytes(encodedData, offset + metadataOffset);
                    metadataOffset += metadata.User.Length + 1;

                    metadata.Timestamp = PTMethods.StringFromBytes(encodedData, offset + metadataOffset);
                    metadataOffset += metadata.Timestamp.Length + 1;

                    metadata.Program = PTMethods.StringFromBytes(encodedData, offset + metadataOffset);
                    metadataOffset += metadata.Program.Length + 1;

                    // Go to the next chunk
                    offset += BitConverter.ToInt32(encodedData, offset + 0x08);
                }

                // Invalid chunk
                else
                {
                    return;
                }

                // Make sure we are actually advancing in the file, so we don't end up reaching a negative offset
                // or ending up in an infinite loop
                if (offset <= previousOffset)
                {
                    return;
                }
                previousOffset = offset;
            }

            // If all went well, offset should be equal to eofOffset
            if (offset != eofOffset)
            {
                return;
            }

            // If this is a non-palettized format, make sure we have a data codec
            if (dataCodec != null && dataCodec.PaletteEntries == 0)
            {
                canDecode = true;
            }

            // If this is a palettized format, make sure we have a palette codec, a data codec,
            // and that the number of palette entires is less than or equal to what this data format supports
            if (dataCodec != null && dataCodec.PaletteEntries != 0 && pixelCodec != null && paletteEntries <= dataCodec.PaletteEntries)
            {
                // Set the data format's pixel codec
                dataCodec.PixelCodec = pixelCodec;

                canDecode = true;
            }

            initalized = true;
        }
        private bool Initalize(Bitmap source, GimPaletteFormat paletteFormat, GimDataFormat dataFormat)
        {
            // Make sure this bitmap's dimensions are valid
            if (!HasValidDimensions(source.Width, source.Height))
                return false;

            textureWidth = (ushort)source.Width;
            textureHeight = (ushort)source.Height;

            // Set default values
            hasMetadata = true;
            metadata = new GimMetadata();

            // Set the data format and palette format and load the appropiate codecs
            this.dataFormat = dataFormat;
            dataCodec = GimDataCodec.GetDataCodec(dataFormat);

            // Make sure the data codec exists and we can encode to it
            if (dataCodec == null || !dataCodec.CanEncode) return false;

            // Only palettized formats require a pixel codec.
            if (dataCodec.PaletteEntries != 0)
            {
                this.paletteFormat = paletteFormat;
                pixelCodec = GimPixelCodec.GetPixelCodec(paletteFormat);

                // Make sure the pixel codec exists and we can encode to it
                if (pixelCodec == null || !pixelCodec.CanEncode) return false;

                dataCodec.PixelCodec = pixelCodec;

                // Convert the bitmap to an array containing indicies.
                decodedData = BitmapToRawIndexed(source, dataCodec.PaletteEntries, out texturePalette);
            }
            else
            {
                this.paletteFormat = GimPaletteFormat.Unknown;
                pixelCodec = null;

                // Convert the bitmap to an array
                decodedData = BitmapToRaw(source);
            }

            return true;
        }
Example #5
0
        private void Initalize()
        {
            // Check to see if what we are dealing with is a GIM texture
            if (!Is(encodedData))
            {
                throw new NotAValidTextureException("This is not a valid GIM texture.");
            }

            // Initalize some things
            paletteFormat = GimPaletteFormat.Unknown;
            dataFormat    = GimDataFormat.Unknown;

            paletteEntries = 0;
            paletteOffset  = -1;
            dataOffset     = -1;

            hasMetadata = false;

            // A GIM is constructed of different chunks. They do not necessarily have to be in order.
            int eofOffset = -1;

            int offset         = 0x10;
            int previousOffset = offset;

            while (offset < encodedData.Length)
            {
                // EOF offset chunk
                if (encodedData[offset] == 0x02)
                {
                    eofOffset = BitConverter.ToInt32(encodedData, offset + 0x04) + 16;

                    // Go to the next chunk
                    offset += BitConverter.ToInt32(encodedData, offset + 0x08);
                }

                // Metadata offset chunk
                else if (encodedData[offset] == 0x03)
                {
                    // Skip this chunk. It's not necessary for decoding this texture.
                    offset += BitConverter.ToInt32(encodedData, offset + 0x08);
                }

                // Texture data
                else if (encodedData[offset] == 0x04)
                {
                    // Get the data format
                    dataFormat = (GimDataFormat)encodedData[offset + 0x14];

                    // Get the data codec and make sure we can decode using it
                    dataCodec = GimDataCodec.GetDataCodec(dataFormat);

                    // Check to see if the texture data is swizzled
                    swizzled = (BitConverter.ToUInt16(encodedData, offset + 0x16) == 1);

                    // Get the texture's width and height
                    textureWidth  = BitConverter.ToUInt16(encodedData, offset + 0x18);
                    textureHeight = BitConverter.ToUInt16(encodedData, offset + 0x1A);

                    // Some textures do not have a width that is a multiple or 16 or a height that is a multiple of 8.
                    // We'll just do it the lazy way and set their width/height to a multiple of 16/8.
                    if (textureWidth % 16 != 0)
                    {
                        textureWidth = (ushort)PTMethods.RoundUp(textureWidth, 16);
                    }
                    if (textureHeight % 8 != 0)
                    {
                        textureHeight = (ushort)PTMethods.RoundUp(textureHeight, 8);
                    }

                    // Set the offset of the texture data
                    dataOffset = offset + 0x50;

                    // Go to the next chunk
                    offset += BitConverter.ToInt32(encodedData, offset + 0x08);
                }

                // Palette data
                else if (encodedData[offset] == 0x05)
                {
                    // Get the palette format
                    paletteFormat = (GimPaletteFormat)encodedData[offset + 0x14];

                    // Get the pixel codec and make sure we can decode using it
                    pixelCodec = GimPixelCodec.GetPixelCodec(paletteFormat);

                    // Get the number of entries in the palette
                    paletteEntries = BitConverter.ToUInt16(encodedData, offset + 0x18);

                    // Set the offset of the palette data
                    paletteOffset = offset + 0x50;

                    // Go to the next chunk
                    offset += BitConverter.ToInt32(encodedData, offset + 0x08);
                }

                // Metadata chunk
                else if (encodedData[offset] == 0xFF)
                {
                    // Read in some metadata
                    hasMetadata = true;
                    metadata    = new GimMetadata();

                    int metadataOffset = 0x10;

                    metadata.OriginalFilename = PTMethods.StringFromBytes(encodedData, offset + metadataOffset);
                    metadataOffset           += metadata.OriginalFilename.Length + 1;

                    metadata.User   = PTMethods.StringFromBytes(encodedData, offset + metadataOffset);
                    metadataOffset += metadata.User.Length + 1;

                    metadata.Timestamp = PTMethods.StringFromBytes(encodedData, offset + metadataOffset);
                    metadataOffset    += metadata.Timestamp.Length + 1;

                    metadata.Program = PTMethods.StringFromBytes(encodedData, offset + metadataOffset);
                    metadataOffset  += metadata.Program.Length + 1;

                    // Go to the next chunk
                    offset += BitConverter.ToInt32(encodedData, offset + 0x08);
                }

                // Invalid chunk
                else
                {
                    return;
                }

                // Make sure we are actually advancing in the file, so we don't end up reaching a negative offset
                // or ending up in an infinite loop
                if (offset <= previousOffset)
                {
                    return;
                }
                previousOffset = offset;
            }

            // If all went well, offset should be equal to eofOffset
            if (offset != eofOffset)
            {
                return;
            }

            // If this is a non-palettized format, make sure we have a data codec
            if (dataCodec != null && dataCodec.PaletteEntries == 0)
            {
                canDecode = true;
            }

            // If this is a palettized format, make sure we have a palette codec, a data codec,
            // and that the number of palette entires is less than or equal to what this data format supports
            if (dataCodec != null && dataCodec.PaletteEntries != 0 && pixelCodec != null && paletteEntries <= dataCodec.PaletteEntries)
            {
                // Set the data format's pixel codec
                dataCodec.PixelCodec = pixelCodec;

                canDecode = true;
            }

            initalized = true;
        }
Example #6
0
        // Encodes a texture
        private MemoryStream EncodeTexture()
        {
            // Get the lengths of the various chunks
            int eofOffsetChunkLength      = 16,
                metadataOffsetChunkLength = 16,
                paletteDataChunkLength    = 0,
                textureDataChunkLength    = 0,
                metadataChunkLength       = 0;

            if (dataCodec.PaletteEntries != 0)
            {
                paletteDataChunkLength = 80 + (dataCodec.PaletteEntries * (pixelCodec.Bpp >> 3));
            }

            textureDataChunkLength = 80 + ((textureWidth * textureHeight * dataCodec.Bpp) >> 3);

            if (hasMetadata)
            {
                metadataChunkLength = 16;

                if (metadata.OriginalFilename != null)
                {
                    metadataChunkLength += metadata.OriginalFilename.Length;
                }
                metadataChunkLength++;

                if (metadata.User != null)
                {
                    metadataChunkLength += metadata.User.Length;
                }
                metadataChunkLength++;

                if (metadata.Timestamp != null)
                {
                    metadataChunkLength += metadata.Timestamp.Length;
                }
                metadataChunkLength++;

                if (metadata.Program != null)
                {
                    metadataChunkLength += metadata.Program.Length;
                }
                metadataChunkLength++;
            }

            // Calculate what the length of the texture will be
            int textureLength = 16 +
                                eofOffsetChunkLength +
                                metadataOffsetChunkLength +
                                paletteDataChunkLength +
                                textureDataChunkLength +
                                metadataChunkLength;

            MemoryStream destination = new MemoryStream(textureLength);

            // Write the GIM header
            PTStream.WriteCString(destination, "MIG.00.1PSP", 12);
            PTStream.WriteUInt32(destination, 0);

            // Write the EOF offset chunk
            PTStream.WriteUInt16(destination, 0x02);
            PTStream.WriteUInt16(destination, 0);
            PTStream.WriteInt32(destination, textureLength - 16);
            PTStream.WriteInt32(destination, eofOffsetChunkLength);
            PTStream.WriteUInt32(destination, 16);

            // Write the metadata offset chunk
            PTStream.WriteUInt16(destination, 0x03);
            PTStream.WriteUInt16(destination, 0);

            if (hasMetadata)
            {
                PTStream.WriteInt32(destination, textureLength - metadataChunkLength - 32);
            }
            else
            {
                PTStream.WriteInt32(destination, textureLength - 32);
            }

            PTStream.WriteInt32(destination, metadataOffsetChunkLength);
            PTStream.WriteUInt32(destination, 16);

            // Write the palette data, if we have a palette
            if (dataCodec.PaletteEntries != 0)
            {
                PTStream.WriteUInt16(destination, 0x05);
                PTStream.WriteUInt16(destination, 0);
                PTStream.WriteInt32(destination, paletteDataChunkLength);
                PTStream.WriteInt32(destination, paletteDataChunkLength);
                PTStream.WriteUInt32(destination, 16);

                PTStream.WriteUInt16(destination, 48);
                PTStream.WriteUInt16(destination, 0);
                PTStream.WriteUInt16(destination, (byte)paletteFormat);
                PTStream.WriteUInt16(destination, 0);
                PTStream.WriteUInt16(destination, (ushort)dataCodec.PaletteEntries);
                destination.Write(new byte[] { 0x01, 0x00, 0x20, 0x00, 0x10, 0x00 }, 0, 6);

                destination.Write(new byte[] { 0x01, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00 }, 0, 8);
                PTStream.WriteUInt32(destination, 0x30);
                PTStream.WriteUInt32(destination, 0x40);

                PTStream.WriteInt32(destination, paletteDataChunkLength - 16);
                PTStream.WriteUInt32(destination, 0);
                destination.Write(new byte[] { 0x02, 0x00, 0x01, 0x00, 0x03, 0x00, 0x01, 0x00 }, 0, 8);

                destination.Write(new byte[] { 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, 0, 16);

                byte[] palette = pixelCodec.EncodePalette(texturePalette, dataCodec.PaletteEntries);
                destination.Write(palette, 0, palette.Length);
            }

            // Write the texture data
            PTStream.WriteUInt16(destination, 0x04);
            PTStream.WriteUInt16(destination, 0);
            PTStream.WriteInt32(destination, textureDataChunkLength);
            PTStream.WriteInt32(destination, textureDataChunkLength);
            PTStream.WriteUInt32(destination, 16);

            PTStream.WriteUInt16(destination, 48);
            PTStream.WriteUInt16(destination, 0);
            PTStream.WriteUInt16(destination, (byte)dataFormat);
            PTStream.WriteUInt16(destination, 1); // Always swizzled
            PTStream.WriteUInt16(destination, textureWidth);
            PTStream.WriteUInt16(destination, textureHeight);

            if (dataCodec.PaletteEntries != 0)
            {
                // For palettized textures, this is the bpp for this data format
                PTStream.WriteUInt16(destination, (ushort)dataCodec.Bpp);
            }
            else
            {
                // For non-palettized textures, this is always specified as 32bpp
                PTStream.WriteUInt16(destination, 32);
            }

            PTStream.WriteUInt16(destination, 16);

            destination.Write(new byte[] { 0x08, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00 }, 0, 16);

            PTStream.WriteInt32(destination, textureDataChunkLength - 16);
            PTStream.WriteUInt32(destination, 0);
            destination.Write(new byte[] { 0x01, 0x00, 0x01, 0x00, 0x03, 0x00, 0x01, 0x00 }, 0, 8);

            destination.Write(new byte[] { 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, 0, 16);

            byte[] textureData = GimDataCodec.Swizzle(dataCodec.Encode(decodedData, 0, textureWidth, textureHeight), 0, textureWidth, textureHeight, dataCodec.Bpp);
            destination.Write(textureData, 0, textureData.Length);

            // Write the metadata, only if we are including it
            if (hasMetadata)
            {
                PTStream.WriteUInt16(destination, 0xFF);
                PTStream.WriteUInt16(destination, 0);
                PTStream.WriteInt32(destination, metadataChunkLength);
                PTStream.WriteInt32(destination, metadataChunkLength);
                PTStream.WriteUInt32(destination, 16);

                PTStream.WriteCString(destination, metadata.OriginalFilename);
                PTStream.WriteCString(destination, metadata.User);
                PTStream.WriteCString(destination, metadata.Timestamp);
                PTStream.WriteCString(destination, metadata.Program);
            }
            return(destination);
        }