protected override void GetUnpalettedTools(ushort version, byte clutFormat, byte depth, int colorsCount, int width, int height, byte[] data, byte[] userData,
                                                   out Encoding.ColorCodec imageCodec,
                                                   out Filters.ImageFilter imgFilter)
        {
            switch (depth)
            {
            case 3:     //RGBA32bit 2 planes
                imageCodec = ColorCodec.CODEC_32BIT_ARGB;
                imgFilter  = new ImageFilterComposer {
                    new GamecubePlanarFilter(), new TileFilter(32, 4, 4, width, height)
                };
                break;

            case 4:     //DXT1
                imageCodec = new ColorCodecDXT1Gamecube(width, height);
                imgFilter  = null;
                break;

            case 0xA:     // I8
                imageCodec = ColorCodec.CODEC_8BIT_I8;
                imgFilter  = new TileFilter(8, 8, 4, width, height);
                break;

            case 0xB:     // IA8
                imageCodec = ColorCodec.CODEC_16BITBE_IA8;
                imgFilter  = new TileFilter(16, 4, 4, width, height);
                break;

            default:
                throw new TextureFormatException("Usupported unpalletted image format " + depth);
            }
        }
        public override TextureFormat Open(System.IO.Stream formatData)
        {
            if (!IsValidFormat(formatData))
            {
                throw new TextureFormatException("Not a valid TPL Texture!");
            }

            BinaryReader reader = new BinaryReader(formatData);

            reader.BaseStream.Position += 4;

            ByteOrder order = ByteOrder.BigEndian;

            int  texturesCount    = (int)reader.ReadUInt32(order);
            uint imageTableOffset = reader.ReadUInt32(order);

            reader.BaseStream.Position = imageTableOffset;

            TPLTexture texture = new TPLTexture();

            for (int i = 0; i < texturesCount; i++)
            {
                TextureFormat segment = null;

                //image table
                uint imageHeaderOffset   = reader.ReadUInt32(order);
                uint offsetPaletteHeader = reader.ReadUInt32(order);

                long oldPos = reader.BaseStream.Position;

                reader.BaseStream.Position = imageHeaderOffset;

                int  height        = reader.ReadUInt16(order);
                int  width         = reader.ReadUInt16(order);
                uint format        = reader.ReadUInt32(order);
                uint imgDataOffset = reader.ReadUInt32(order);

                ColorCodec  colorCodec = null;
                IndexCodec  idxCodec   = null;
                ImageFilter imgFilter  = null;

                ushort entryCount    = 0;
                ushort unknown       = 0;//this might be a set of flags denoting whether the palette is internal to the tpl image or external.
                uint   paletteFormat = 0;
                uint   palDataOffset = 0;
                bool   isIndexed     = false;

                int imgDataSize = 0;
                int palDataSize = 0;

                switch (format)
                {
                case 0:     //I4
                    colorCodec  = ColorCodec.CODEC_4BITBE_I4;
                    imgFilter   = new TileFilter(4, 8, 8, width, height);
                    imgDataSize = colorCodec.GetBytesNeededForEncode(width, height, imgFilter);
                    break;

                case 1:     //I8
                    colorCodec  = ColorCodec.CODEC_8BIT_I8;
                    imgFilter   = new TileFilter(8, 8, 4, width, height);
                    imgDataSize = colorCodec.GetBytesNeededForEncode(width, height, imgFilter);
                    break;

                case 2:     //IA4
                    colorCodec  = ColorCodec.CODEC_8BITBE_IA4;
                    imgFilter   = new TileFilter(8, 8, 4, width, height);
                    imgDataSize = colorCodec.GetBytesNeededForEncode(width, height, imgFilter);
                    break;

                case 3:     //IA8
                    colorCodec  = ColorCodec.CODEC_16BITBE_IA8;
                    imgFilter   = new TileFilter(16, 4, 4, width, height);
                    imgDataSize = colorCodec.GetBytesNeededForEncode(width, height, imgFilter);
                    break;

                case 4:     //RGB565
                    colorCodec  = ColorCodec.CODEC_16BITBE_RGB565;
                    imgFilter   = new TileFilter(16, 4, 4, width, height);
                    imgDataSize = colorCodec.GetBytesNeededForEncode(width, height, imgFilter);
                    break;

                case 5:     //RGB5A3
                    colorCodec  = ColorCodec.CODEC_16BITBE_RGB5A3;
                    imgFilter   = new TileFilter(16, 4, 4, width, height);
                    imgDataSize = colorCodec.GetBytesNeededForEncode(width, height, imgFilter);
                    break;

                case 6:     //RGBA32 2 planes
                    colorCodec = ColorCodec.CODEC_32BIT_ARGB;
                    imgFilter  = new ImageFilterComposer {
                        new GamecubePlanarFilter(),
                        new TileFilter(32, 4, 4, width, height)
                    };
                    imgDataSize = colorCodec.GetBytesNeededForEncode(width, height, imgFilter);
                    break;

                case 8:     //C4
                case 9:     //C8
                    isIndexed = true;
                    reader.BaseStream.Position = offsetPaletteHeader;

                    entryCount = reader.ReadUInt16(order);
                    unknown    = reader.ReadUInt16(order);

                    paletteFormat = reader.ReadUInt32(order);
                    palDataOffset = reader.ReadUInt32(order);

                    switch (paletteFormat)
                    {
                    case 0:
                        colorCodec = ColorCodec.CODEC_16BITBE_IA8;
                        break;

                    case 1:
                        colorCodec = ColorCodec.CODEC_16BITBE_RGB565;
                        break;

                    case 2:
                        colorCodec = ColorCodec.CODEC_16BITBE_RGB5A3;
                        break;

                    default:
                        throw new TextureFormatException("Unsupported palette format " + paletteFormat);
                    }
                    palDataSize = colorCodec.GetBytesNeededForEncode(entryCount, 1);

                    if (format == 8)
                    {
                        idxCodec  = IndexCodec.FromBitPerPixel(4, order);
                        imgFilter = new TileFilter(4, 8, 8, width, height);
                    }
                    else
                    {
                        idxCodec  = IndexCodec.FromBitPerPixel(8, order);
                        imgFilter = new TileFilter(8, 8, 4, width, height);
                    }

                    imgDataSize = idxCodec.GetBytesNeededForEncode(width, height, imgFilter);
                    break;

                case 0xA:     //C14X2
                    throw new TextureFormatException("C14X2 not implemented yet!");
                    break;

                case 0xE:     //DXT1 (aka CMPR)
                    colorCodec  = new ColorCodecDXT1Gamecube(width, height);
                    imgDataSize = colorCodec.GetBytesNeededForEncode(width, height);
                    break;

                default:
                    throw new TextureFormatException("Unsupported TPL image format " + format);
                }

                reader.BaseStream.Position = imgDataOffset;
                byte[] imgData = reader.ReadBytes(imgDataSize);

                if (isIndexed)
                {
                    reader.BaseStream.Position = palDataOffset;
                    byte[] palData = reader.ReadBytes(palDataSize);

                    PalettedTextureFormat.Builder builder = new PalettedTextureFormat.Builder();
                    segment = builder.SetIndexCodec(idxCodec)
                              .SetPaletteCodec(colorCodec)
                              .SetImageFilter(imgFilter)
                              .Build(imgData, palData, width, height);
                }
                else
                {
                    GenericTextureFormat.Builder builder = new GenericTextureFormat.Builder();
                    segment = builder.SetColorCodec(colorCodec)
                              .SetImageFilter(imgFilter)
                              .Build(imgData, width, height);
                }

                segment.FormatSpecificData.Put <uint>(FORMAT_KEY, format)
                .Put <uint>(UNKNOWN_KEY, unknown)
                .Put <uint>(PALETTEFORMAT_KEY, paletteFormat);

                texture.TextureFormats.Add(segment);

                reader.BaseStream.Position = oldPos;
            }

            return(texture);
        }