Exemple #1
0
        public static Bitmap DecodeBitmap(byte[] Input, int Width, int Height, PICATextureFormat Format)
        {
            byte[] Buffer = DecodeBuffer(Input, Width, Height, Format);

            byte[] Output = new byte[Buffer.Length];

            int Stride = Width * 4;

            for (int Y = 0; Y < Height; Y++)
            {
                int IOffs = Stride * Y;
                int OOffs = Stride * (Height - 1 - Y);

                for (int X = 0; X < Width; X++)
                {
                    Output[OOffs + 0] = Buffer[IOffs + 2];
                    Output[OOffs + 1] = Buffer[IOffs + 1];
                    Output[OOffs + 2] = Buffer[IOffs + 0];
                    Output[OOffs + 3] = Buffer[IOffs + 3];

                    IOffs += 4;
                    OOffs += 4;
                }
            }

            return(GetBitmap(Output, Width, Height));
        }
Exemple #2
0
        public static GFTextureFormat ToGFTextureFormat(this PICATextureFormat Format)
        {
            switch (Format)
            {
            case PICATextureFormat.RGB565: return(GFTextureFormat.RGB565);

            case PICATextureFormat.RGB8: return(GFTextureFormat.RGB8);

            case PICATextureFormat.RGBA8: return(GFTextureFormat.RGBA8);

            case PICATextureFormat.RGBA4: return(GFTextureFormat.RGBA4);

            case PICATextureFormat.RGBA5551: return(GFTextureFormat.RGBA5551);

            case PICATextureFormat.LA8: return(GFTextureFormat.LA8);

            case PICATextureFormat.HiLo8: return(GFTextureFormat.HiLo8);

            case PICATextureFormat.L8: return(GFTextureFormat.L8);

            case PICATextureFormat.A8: return(GFTextureFormat.A8);

            case PICATextureFormat.LA4: return(GFTextureFormat.LA4);

            case PICATextureFormat.L4: return(GFTextureFormat.L4);

            case PICATextureFormat.A4: return(GFTextureFormat.A4);

            case PICATextureFormat.ETC1: return(GFTextureFormat.ETC1);

            case PICATextureFormat.ETC1A4: return(GFTextureFormat.ETC1A4);

            default: throw new ArgumentException("Invalid format!");
            }
        }
Exemple #3
0
        public static int CalculateLength(int Width, int Height, PICATextureFormat Format)
        {
            int Length = (Width * Height * FmtBPP[(int)Format]) / 8;

            if ((Length & 0x7f) != 0)
            {
                Length = (Length & ~0x7f) + 0x80;
            }

            return(Length);
        }
Exemple #4
0
        public static byte[] Encode(Bitmap Img, PICATextureFormat Format)
        {
            byte[] Input = GetBuffer(Img);

            byte[] Output = new byte[CalculateLength(Img.Width, Img.Height, Format)];

            int OOffs = 0;

            if (Format == PICATextureFormat.ETC1 ||
                Format == PICATextureFormat.ETC1A4)
            {
                throw new NotImplementedException();
            }
            else
            {
                for (int TY = 0; TY < Img.Height; TY += 8)
                {
                    for (int TX = 0; TX < Img.Width; TX += 8)
                    {
                        for (int Px = 0; Px < 64; Px++)
                        {
                            int X = SwizzleLUT[Px] & 7;
                            int Y = (SwizzleLUT[Px] - X) >> 3;

                            int IOffs = (TX + X + ((TY + Y) * Img.Width)) * 4;

                            switch (Format)
                            {
                            case PICATextureFormat.RGBA8:
                                Output[OOffs + 0] = Input[IOffs + 3];
                                Output[OOffs + 1] = Input[IOffs + 0];
                                Output[OOffs + 2] = Input[IOffs + 1];
                                Output[OOffs + 3] = Input[IOffs + 2];

                                OOffs += 4;

                                break;

                            default: throw new NotImplementedException();
                            }
                        }
                    }
                }
            }

            return(Output);
        }
Exemple #5
0
        public static byte[] ETC1_Encode(byte[] Data, int Width, int Height, PICATextureFormat format)
        {
            byte[] Out_Data = null;

            // Os tiles com compressão ETC1 no 3DS estão embaralhados
            byte[] Out           = new byte[(Width * Height * 4)];
            int[]  Tile_Scramble = Get_ETC1_Scramble(Width, Height);

            int i = 0;

            for (int Tile_Y = 0; Tile_Y <= (Height / 4) - 1; Tile_Y++)
            {
                for (int Tile_X = 0; Tile_X <= (Width / 4) - 1; Tile_X++)
                {
                    int TX = Tile_Scramble[i] % (Width / 4);
                    int TY = (Tile_Scramble[i] - TX) / (Width / 4);
                    for (int Y = 0; Y <= 3; Y++)
                    {
                        for (int X = 0; X <= 3; X++)
                        {
                            int Out_Offset   = ((TX * 4) + X + ((((TY * 4) + Y)) * Width)) * 4;
                            int Image_Offset = ((Tile_X * 4) + X + (((Tile_Y * 4) + Y) * Width)) * 4;

                            Out[Out_Offset]     = Data[Image_Offset + 2];
                            Out[Out_Offset + 1] = Data[Image_Offset + 1];
                            Out[Out_Offset + 2] = Data[Image_Offset];
                            if (format == PICATextureFormat.ETC1A4)
                            {
                                Out[Out_Offset + 3] = Data[Image_Offset + 3];
                            }
                            else
                            {
                                Out[Out_Offset + 3] = 0xFF;
                            }
                        }
                    }
                    i += 1;
                }
            }

            Out_Data = new byte[((Width * Height) / (format == PICATextureFormat.ETC1 ? 2 : 1))];
            int Out_Data_Offset = 0;

            for (int Tile_Y = 0; Tile_Y <= (Height / 4) - 1; Tile_Y++)
            {
                for (int Tile_X = 0; Tile_X <= (Width / 4) - 1; Tile_X++)
                {
                    bool Flip         = false;
                    bool Difference   = false;
                    int  Block_Top    = 0;
                    int  Block_Bottom = 0;

                    // Teste do Difference Bit
                    int Diff_Match_V = 0;
                    int Diff_Match_H = 0;
                    for (int Y = 0; Y <= 3; Y++)
                    {
                        for (int X = 0; X <= 1; X++)
                        {
                            int Image_Offset_1 = ((Tile_X * 4) + X + (((Tile_Y * 4) + Y) * Width)) * 4;
                            int Image_Offset_2 = ((Tile_X * 4) + (2 + X) + (((Tile_Y * 4) + Y) * Width)) * 4;

                            byte Bits_R1 = Convert.ToByte(Out[Image_Offset_1] & 0xF8);
                            byte Bits_G1 = Convert.ToByte(Out[Image_Offset_1 + 1] & 0xF8);
                            byte Bits_B1 = Convert.ToByte(Out[Image_Offset_1 + 2] & 0xF8);

                            byte Bits_R2 = Convert.ToByte(Out[Image_Offset_2] & 0xF8);
                            byte Bits_G2 = Convert.ToByte(Out[Image_Offset_2 + 1] & 0xF8);
                            byte Bits_B2 = Convert.ToByte(Out[Image_Offset_2 + 2] & 0xF8);

                            if ((Bits_R1 == Bits_R2) & (Bits_G1 == Bits_G2) & (Bits_B1 == Bits_B2))
                            {
                                Diff_Match_V += 1;
                            }
                        }
                    }
                    for (int Y = 0; Y <= 1; Y++)
                    {
                        for (int X = 0; X <= 3; X++)
                        {
                            int Image_Offset_1 = ((Tile_X * 4) + X + (((Tile_Y * 4) + Y) * Width)) * 4;
                            int Image_Offset_2 = ((Tile_X * 4) + X + (((Tile_Y * 4) + (2 + Y)) * Width)) * 4;

                            byte Bits_R1 = Convert.ToByte(Out[Image_Offset_1] & 0xF8);
                            byte Bits_G1 = Convert.ToByte(Out[Image_Offset_1 + 1] & 0xF8);
                            byte Bits_B1 = Convert.ToByte(Out[Image_Offset_1 + 2] & 0xF8);

                            byte Bits_R2 = Convert.ToByte(Out[Image_Offset_2] & 0xF8);
                            byte Bits_G2 = Convert.ToByte(Out[Image_Offset_2 + 1] & 0xF8);
                            byte Bits_B2 = Convert.ToByte(Out[Image_Offset_2 + 2] & 0xF8);

                            if ((Bits_R1 == Bits_R2) & (Bits_G1 == Bits_G2) & (Bits_B1 == Bits_B2))
                            {
                                Diff_Match_H += 1;
                            }
                        }
                    }
                    if (Diff_Match_H == 8)
                    {
                        Difference = true;
                        Flip       = true;
                    }
                    else if (Diff_Match_V == 8)
                    {
                        Difference = true;
                    }
                    else
                    {
                        int Test_R1 = 0;
                        int Test_G1 = 0;
                        int Test_B1 = 0;
                        int Test_R2 = 0;
                        int Test_G2 = 0;
                        int Test_B2 = 0;
                        for (int Y = 0; Y <= 1; Y++)
                        {
                            for (int X = 0; X <= 1; X++)
                            {
                                int Image_Offset_1 = ((Tile_X * 4) + X + (((Tile_Y * 4) + Y) * Width)) * 4;
                                int Image_Offset_2 = ((Tile_X * 4) + (2 + X) + (((Tile_Y * 4) + (2 + Y)) * Width)) * 4;

                                Test_R1 += Out[Image_Offset_1];
                                Test_G1 += Out[Image_Offset_1 + 1];
                                Test_B1 += Out[Image_Offset_1 + 2];

                                Test_R2 += Out[Image_Offset_2];
                                Test_G2 += Out[Image_Offset_2 + 1];
                                Test_B2 += Out[Image_Offset_2 + 2];
                            }
                        }

                        Test_R1 /= 8;
                        Test_G1 /= 8;
                        Test_B1 /= 8;

                        Test_R2 /= 8;
                        Test_G2 /= 8;
                        Test_B2 /= 8;

                        int Test_Luma_1    = Convert.ToInt32(0.299F * Test_R1 + 0.587F * Test_G1 + 0.114F * Test_B1);
                        int Test_Luma_2    = Convert.ToInt32(0.299F * Test_R2 + 0.587F * Test_G2 + 0.114F * Test_B2);
                        int Test_Flip_Diff = Math.Abs(Test_Luma_1 - Test_Luma_2);
                        if (Test_Flip_Diff > 48)
                        {
                            Flip = true;
                        }
                    }

                    int Avg_R1 = 0;
                    int Avg_G1 = 0;
                    int Avg_B1 = 0;
                    int Avg_R2 = 0;
                    int Avg_G2 = 0;
                    int Avg_B2 = 0;

                    // Primeiro, cálcula a média de cores de cada bloco
                    if (Flip)
                    {
                        for (int Y = 0; Y <= 1; Y++)
                        {
                            for (int X = 0; X <= 3; X++)
                            {
                                int Image_Offset_1 = ((Tile_X * 4) + X + (((Tile_Y * 4) + Y) * Width)) * 4;
                                int Image_Offset_2 = ((Tile_X * 4) + X + (((Tile_Y * 4) + (2 + Y)) * Width)) * 4;

                                Avg_R1 += Out[Image_Offset_1];
                                Avg_G1 += Out[Image_Offset_1 + 1];
                                Avg_B1 += Out[Image_Offset_1 + 2];

                                Avg_R2 += Out[Image_Offset_2];
                                Avg_G2 += Out[Image_Offset_2 + 1];
                                Avg_B2 += Out[Image_Offset_2 + 2];
                            }
                        }
                    }
                    else
                    {
                        for (int Y = 0; Y <= 3; Y++)
                        {
                            for (int X = 0; X <= 1; X++)
                            {
                                int Image_Offset_1 = ((Tile_X * 4) + X + (((Tile_Y * 4) + Y) * Width)) * 4;
                                int Image_Offset_2 = ((Tile_X * 4) + (2 + X) + (((Tile_Y * 4) + Y) * Width)) * 4;

                                Avg_R1 += Out[Image_Offset_1];
                                Avg_G1 += Out[Image_Offset_1 + 1];
                                Avg_B1 += Out[Image_Offset_1 + 2];

                                Avg_R2 += Out[Image_Offset_2];
                                Avg_G2 += Out[Image_Offset_2 + 1];
                                Avg_B2 += Out[Image_Offset_2 + 2];
                            }
                        }
                    }

                    Avg_R1 /= 8;
                    Avg_G1 /= 8;
                    Avg_B1 /= 8;

                    Avg_R2 /= 8;
                    Avg_G2 /= 8;
                    Avg_B2 /= 8;

                    if (Difference)
                    {
                        // +============+
                        // | Difference |
                        // +============+
                        if ((Avg_R1 & 7) > 3)
                        {
                            Avg_R1 = Clip(Avg_R1 + 8); Avg_R2 = Clip(Avg_R2 + 8);
                        }
                        if ((Avg_G1 & 7) > 3)
                        {
                            Avg_G1 = Clip(Avg_G1 + 8); Avg_G2 = Clip(Avg_G2 + 8);
                        }
                        if ((Avg_B1 & 7) > 3)
                        {
                            Avg_B1 = Clip(Avg_B1 + 8); Avg_B2 = Clip(Avg_B2 + 8);
                        }

                        Block_Top = (Avg_R1 & 0xF8) | (((Avg_R2 - Avg_R1) / 8) & 7);
                        Block_Top = Block_Top | (((Avg_G1 & 0xF8) << 8) | ((((Avg_G2 - Avg_G1) / 8) & 7) << 8));
                        Block_Top = Block_Top | (((Avg_B1 & 0xF8) << 16) | ((((Avg_B2 - Avg_B1) / 8) & 7) << 16));

                        // Vamos ter certeza de que os mesmos valores obtidos pelo descompressor serão usados na comparação (modo Difference)
                        Avg_R1 = Block_Top & 0xF8;
                        Avg_G1 = (Block_Top & 0xF800) >> 8;
                        Avg_B1 = (Block_Top & 0xF80000) >> 16;

                        int R = Signed_Byte(Convert.ToByte(Avg_R1 >> 3)) + (Signed_Byte(Convert.ToByte((Block_Top & 7) << 5)) >> 5);
                        int G = Signed_Byte(Convert.ToByte(Avg_G1 >> 3)) + (Signed_Byte(Convert.ToByte((Block_Top & 0x700) >> 3)) >> 5);
                        int B = Signed_Byte(Convert.ToByte(Avg_B1 >> 3)) + (Signed_Byte(Convert.ToByte((Block_Top & 0x70000) >> 11)) >> 5);

                        Avg_R2 = R;
                        Avg_G2 = G;
                        Avg_B2 = B;

                        Avg_R1 = Avg_R1 + (Avg_R1 >> 5);
                        Avg_G1 = Avg_G1 + (Avg_G1 >> 5);
                        Avg_B1 = Avg_B1 + (Avg_B1 >> 5);

                        Avg_R2 = (Avg_R2 << 3) + (Avg_R2 >> 2);
                        Avg_G2 = (Avg_G2 << 3) + (Avg_G2 >> 2);
                        Avg_B2 = (Avg_B2 << 3) + (Avg_B2 >> 2);
                    }
                    else
                    {
                        // +============+
                        // | Individual |
                        // +============+
                        if ((Avg_R1 & 0xF) > 7)
                        {
                            Avg_R1 = Clip(Avg_R1 + 0x10);
                        }
                        if ((Avg_G1 & 0xF) > 7)
                        {
                            Avg_G1 = Clip(Avg_G1 + 0x10);
                        }
                        if ((Avg_B1 & 0xF) > 7)
                        {
                            Avg_B1 = Clip(Avg_B1 + 0x10);
                        }
                        if ((Avg_R2 & 0xF) > 7)
                        {
                            Avg_R2 = Clip(Avg_R2 + 0x10);
                        }
                        if ((Avg_G2 & 0xF) > 7)
                        {
                            Avg_G2 = Clip(Avg_G2 + 0x10);
                        }
                        if ((Avg_B2 & 0xF) > 7)
                        {
                            Avg_B2 = Clip(Avg_B2 + 0x10);
                        }

                        Block_Top = ((Avg_R2 & 0xF0) >> 4) | (Avg_R1 & 0xF0);
                        Block_Top = Block_Top | (((Avg_G2 & 0xF0) << 4) | ((Avg_G1 & 0xF0) << 8));
                        Block_Top = Block_Top | (((Avg_B2 & 0xF0) << 12) | ((Avg_B1 & 0xF0) << 16));

                        // Vamos ter certeza de que os mesmos valores obtidos pelo descompressor serão usados na comparação (modo Individual)
                        Avg_R1 = (Avg_R1 & 0xF0) + ((Avg_R1 & 0xF0) >> 4);
                        Avg_G1 = (Avg_G1 & 0xF0) + ((Avg_G1 & 0xF0) >> 4);
                        Avg_B1 = (Avg_B1 & 0xF0) + ((Avg_B1 & 0xF0) >> 4);

                        Avg_R2 = (Avg_R2 & 0xF0) + ((Avg_R2 & 0xF0) >> 4);
                        Avg_G2 = (Avg_G2 & 0xF0) + ((Avg_G2 & 0xF0) >> 4);
                        Avg_B2 = (Avg_B2 & 0xF0) + ((Avg_B2 & 0xF0) >> 4);
                    }

                    if (Flip)
                    {
                        Block_Top = Block_Top | 0x1000000;
                    }
                    if (Difference)
                    {
                        Block_Top = Block_Top | 0x2000000;
                    }

                    // Seleciona a melhor tabela para ser usada nos blocos
                    int   Mod_Table_1 = 0;
                    int[] Min_Diff_1  = new int[8];
                    for (int a = 0; a <= 7; a++)
                    {
                        Min_Diff_1[a] = 0;
                    }
                    for (int Y = 0; Y <= (Flip ? 1 : 3); Y++)
                    {
                        for (int X = 0; X <= (Flip ? 3 : 1); X++)
                        {
                            int Image_Offset = ((Tile_X * 4) + X + (((Tile_Y * 4) + Y) * Width)) * 4;
                            int Luma         = Convert.ToInt32(0.299F * Out[Image_Offset] + 0.587F * Out[Image_Offset + 1] + 0.114F * Out[Image_Offset + 2]);

                            for (int a = 0; a <= 7; a++)
                            {
                                int Optimal_Diff = 255 * 4;
                                for (int b = 0; b <= 3; b++)
                                {
                                    int CR = Clip(Avg_R1 + Modulation_Table[a, b]);
                                    int CG = Clip(Avg_G1 + Modulation_Table[a, b]);
                                    int CB = Clip(Avg_B1 + Modulation_Table[a, b]);

                                    int Test_Luma = Convert.ToInt32(0.299F * CR + 0.587F * CG + 0.114F * CB);
                                    int Diff      = Math.Abs(Luma - Test_Luma);
                                    if (Diff < Optimal_Diff)
                                    {
                                        Optimal_Diff = Diff;
                                    }
                                }
                                Min_Diff_1[a] += Optimal_Diff;
                            }
                        }
                    }

                    int Temp_1 = 255 * 8;
                    for (int a = 0; a <= 7; a++)
                    {
                        if (Min_Diff_1[a] < Temp_1)
                        {
                            Temp_1      = Min_Diff_1[a];
                            Mod_Table_1 = a;
                        }
                    }

                    int   Mod_Table_2 = 0;
                    int[] Min_Diff_2  = new int[8];
                    for (int a = 0; a <= 7; a++)
                    {
                        Min_Diff_2[a] = 0;
                    }
                    for (int Y = Flip ? 2 : 0; Y <= 3; Y++)
                    {
                        for (int X = Flip ? 0 : 2; X <= 3; X++)
                        {
                            int Image_Offset = ((Tile_X * 4) + X + (((Tile_Y * 4) + Y) * Width)) * 4;
                            int Luma         = Convert.ToInt32(0.299F * Out[Image_Offset] + 0.587F * Out[Image_Offset + 1] + 0.114F * Out[Image_Offset + 2]);

                            for (int a = 0; a <= 7; a++)
                            {
                                int Optimal_Diff = 255 * 4;
                                for (int b = 0; b <= 3; b++)
                                {
                                    int CR = Clip(Avg_R2 + Modulation_Table[a, b]);
                                    int CG = Clip(Avg_G2 + Modulation_Table[a, b]);
                                    int CB = Clip(Avg_B2 + Modulation_Table[a, b]);

                                    int Test_Luma = Convert.ToInt32(0.299F * CR + 0.587F * CG + 0.114F * CB);
                                    int Diff      = Math.Abs(Luma - Test_Luma);
                                    if (Diff < Optimal_Diff)
                                    {
                                        Optimal_Diff = Diff;
                                    }
                                }
                                Min_Diff_2[a] += Optimal_Diff;
                            }
                        }
                    }

                    int Temp_2 = 255 * 8;
                    for (int a = 0; a <= 7; a++)
                    {
                        if (Min_Diff_2[a] < Temp_2)
                        {
                            Temp_2      = Min_Diff_2[a];
                            Mod_Table_2 = a;
                        }
                    }

                    Block_Top = Block_Top | (Mod_Table_1 << 29);
                    Block_Top = Block_Top | (Mod_Table_2 << 26);

                    // Seleciona o melhor valor da tabela que mais se aproxima com a cor original
                    for (int Y = 0; Y <= (Flip ? 1 : 3); Y++)
                    {
                        for (int X = 0; X <= (Flip ? 3 : 1); X++)
                        {
                            int Image_Offset = ((Tile_X * 4) + X + (((Tile_Y * 4) + Y) * Width)) * 4;
                            int Luma         = Convert.ToInt32(0.299F * Out[Image_Offset] + 0.587F * Out[Image_Offset + 1] + 0.114F * Out[Image_Offset + 2]);

                            int Col_Diff        = 255;
                            int Pix_Table_Index = 0;
                            for (int b = 0; b <= 3; b++)
                            {
                                int CR = Clip(Avg_R1 + Modulation_Table[Mod_Table_1, b]);
                                int CG = Clip(Avg_G1 + Modulation_Table[Mod_Table_1, b]);
                                int CB = Clip(Avg_B1 + Modulation_Table[Mod_Table_1, b]);

                                int Test_Luma = Convert.ToInt32(0.299F * CR + 0.587F * CG + 0.114F * CB);
                                int Diff      = Math.Abs(Luma - Test_Luma);
                                if (Diff < Col_Diff)
                                {
                                    Col_Diff        = Diff;
                                    Pix_Table_Index = b;
                                }
                            }

                            int Index = X * 4 + Y;
                            if (Index < 8)
                            {
                                Block_Bottom = Block_Bottom | (((Pix_Table_Index & 2) >> 1) << (Index + 8));
                                Block_Bottom = Block_Bottom | ((Pix_Table_Index & 1) << (Index + 24));
                            }
                            else
                            {
                                Block_Bottom = Block_Bottom | (((Pix_Table_Index & 2) >> 1) << (Index - 8));
                                Block_Bottom = Block_Bottom | ((Pix_Table_Index & 1) << (Index + 8));
                            }
                        }
                    }

                    for (int Y = Flip ? 2 : 0; Y <= 3; Y++)
                    {
                        for (int X = Flip ? 0 : 2; X <= 3; X++)
                        {
                            int Image_Offset = ((Tile_X * 4) + X + (((Tile_Y * 4) + Y) * Width)) * 4;
                            int Luma         = Convert.ToInt32(0.299F * Out[Image_Offset] + 0.587F * Out[Image_Offset + 1] + 0.114F * Out[Image_Offset + 2]);

                            int Col_Diff        = 255;
                            int Pix_Table_Index = 0;
                            for (int b = 0; b <= 3; b++)
                            {
                                int CR = Clip(Avg_R2 + Modulation_Table[Mod_Table_2, b]);
                                int CG = Clip(Avg_G2 + Modulation_Table[Mod_Table_2, b]);
                                int CB = Clip(Avg_B2 + Modulation_Table[Mod_Table_2, b]);

                                int Test_Luma = Convert.ToInt32(0.299F * CR + 0.587F * CG + 0.114F * CB);
                                int Diff      = Math.Abs(Luma - Test_Luma);
                                if (Diff < Col_Diff)
                                {
                                    Col_Diff        = Diff;
                                    Pix_Table_Index = b;
                                }
                            }

                            int Index = X * 4 + Y;
                            if (Index < 8)
                            {
                                Block_Bottom = Block_Bottom | (((Pix_Table_Index & 2) >> 1) << (Index + 8));
                                Block_Bottom = Block_Bottom | ((Pix_Table_Index & 1) << (Index + 24));
                            }
                            else
                            {
                                Block_Bottom = Block_Bottom | (((Pix_Table_Index & 2) >> 1) << (Index - 8));
                                Block_Bottom = Block_Bottom | ((Pix_Table_Index & 1) << (Index + 8));
                            }
                        }
                    }

                    // Copia dados para a saída
                    byte[] Block = new byte[8];
                    Buffer.BlockCopy(BitConverter.GetBytes(Block_Top), 0, Block, 0, 4);
                    Buffer.BlockCopy(BitConverter.GetBytes(Block_Bottom), 0, Block, 4, 4);
                    byte[] New_Block = new byte[8];
                    for (int j = 0; j <= 7; j++)
                    {
                        New_Block[7 - j] = Block[j];
                    }
                    if (format == PICATextureFormat.ETC1A4)
                    {
                        byte[] Alphas       = new byte[8];
                        int    Alpha_Offset = 0;
                        for (int TX = 0; TX <= 3; TX++)
                        {
                            for (int TY = 0; TY <= 3; TY += 2)
                            {
                                int Img_Offset_1 = (Tile_X * 4 + TX + ((Tile_Y * 4 + TY) * Width)) * 4;
                                int Img_Offset_2 = (Tile_X * 4 + TX + ((Tile_Y * 4 + TY + 1) * Width)) * 4;

                                byte Alpha_1 = (byte)(Out[Img_Offset_1 + 3] >> 4);
                                byte Alpha_2 = (byte)(Out[Img_Offset_2 + 3] >> 4);

                                Alphas[Alpha_Offset] = (byte)(Alpha_1 | (Alpha_2 << 4));

                                Alpha_Offset += 1;
                            }
                        }

                        Buffer.BlockCopy(Alphas, 0, Out_Data, Out_Data_Offset, 8);
                        Buffer.BlockCopy(New_Block, 0, Out_Data, Out_Data_Offset + 8, 8);
                        Out_Data_Offset += 16;
                    }
                    else if (format == PICATextureFormat.ETC1)
                    {
                        Buffer.BlockCopy(New_Block, 0, Out_Data, Out_Data_Offset, 8);
                        Out_Data_Offset += 8;
                    }
                }
            }

            return(Out_Data);
        }
Exemple #6
0
        public static byte[] Encode(Bitmap Img, PICATextureFormat Format)
        {
            byte[] Input = GetBuffer(Img);

            byte[] Output = new byte[CalculateLength(Img.Width, Img.Height, Format)];

            int BPP = FmtBPP[(int)Format] / 8;

            if (BPP == 0)
            {
                BPP = 1;
            }

            int OOffs = 0;

            if (Format == PICATextureFormat.ETC1 ||
                Format == PICATextureFormat.ETC1A4)
            {
                return(ETC1_Encode(Input, Img.Width, Img.Height, Format));
            }
            else
            {
                for (int TY = 0; TY < Img.Height; TY += 8)
                {
                    for (int TX = 0; TX < Img.Width; TX += 8)
                    {
                        for (int Px = 0; Px < 64; Px++)
                        {
                            int X = SwizzleLUT[Px] & 7;
                            int Y = (SwizzleLUT[Px] - X) >> 3;

                            int IOffs = (TX + X + ((TY + Y) * Img.Width)) * 4;

                            switch (Format)
                            {
                            case PICATextureFormat.RGB8:
                                Array.Copy(Input, IOffs, Output, OOffs, 3);

                                break;

                            case PICATextureFormat.RGBA8:
                                Output[OOffs + 0] = Input[IOffs + 3];
                                Output[OOffs + 1] = Input[IOffs + 0];
                                Output[OOffs + 2] = Input[IOffs + 1];
                                Output[OOffs + 3] = Input[IOffs + 2];

                                break;

                            case PICATextureFormat.RGB565:
                                EncodeRGB565(Input, IOffs, Output, OOffs);

                                break;

                            case PICATextureFormat.L8:
                                Output[OOffs] = GetLuminosity(Input, IOffs);

                                break;

                            case PICATextureFormat.A8:
                                Output[OOffs] = Input[IOffs + 3];

                                break;

                            case PICATextureFormat.LA8:
                                Output[OOffs]     = GetLuminosity(Input, IOffs);
                                Output[OOffs + 1] = Input[IOffs + 3];

                                break;

                            case PICATextureFormat.HiLo8:
                                Array.Copy(Input, IOffs, Output, OOffs, 2);
                                break;

                            case PICATextureFormat.RGBA4:
                                EncodeRGBA4(Input, IOffs, Output, OOffs);

                                break;

                            case PICATextureFormat.RGBA5551:
                                EncodeRGBA5551(Input, IOffs, Output, OOffs);

                                break;

                            case PICATextureFormat.L4:
                            {
                                int ActualOOffs = OOffs / 2;
                                int Shift       = (OOffs & 1) * 4;
                                Output[ActualOOffs] |= (byte)((GetLuminosity(Input, IOffs) >> 4 & 0xF) << Shift);
                            }
                            break;

                            case PICATextureFormat.A4:
                            {
                                int ActualOOffs = OOffs / 2;
                                int Shift       = (OOffs & 1) * 4;
                                Output[ActualOOffs] |= (byte)((Input[IOffs + 3] >> 4 & 0xF) << Shift);
                            }
                            break;

                            case PICATextureFormat.LA4:
                                Output[OOffs] = (byte)(GetLuminosity(Input, IOffs) & 0xF0 | (Input[IOffs + 3] >> 4 & 0xf));
                                break;

                            default: throw new NotImplementedException();
                            }

                            OOffs += BPP;
                        }
                    }
                }
            }

            return(Output);
        }
Exemple #7
0
        public static byte[] DecodeBuffer(byte[] Input, int Width, int Height, PICATextureFormat Format)
        {
            if (Format == PICATextureFormat.ETC1 ||
                Format == PICATextureFormat.ETC1A4)
            {
                return(TextureCompression.ETC1Decompress(Input, Width, Height, Format == PICATextureFormat.ETC1A4));
            }
            else
            {
                int Increment = FmtBPP[(int)Format] / 8;

                if (Increment == 0)
                {
                    Increment = 1;
                }

                byte[] Output = new byte[Width * Height * 4];

                int IOffs = 0;

                for (int TY = 0; TY < Height; TY += 8)
                {
                    for (int TX = 0; TX < Width; TX += 8)
                    {
                        for (int Px = 0; Px < 64; Px++)
                        {
                            int X = SwizzleLUT[Px] & 7;
                            int Y = (SwizzleLUT[Px] - X) >> 3;

                            int OOffs = (TX + X + ((Height - 1 - (TY + Y)) * Width)) * 4;

                            switch (Format)
                            {
                            case PICATextureFormat.RGBA8:
                                Output[OOffs + 0] = Input[IOffs + 3];
                                Output[OOffs + 1] = Input[IOffs + 2];
                                Output[OOffs + 2] = Input[IOffs + 1];
                                Output[OOffs + 3] = Input[IOffs + 0];

                                break;

                            case PICATextureFormat.RGB8:
                                Output[OOffs + 0] = Input[IOffs + 2];
                                Output[OOffs + 1] = Input[IOffs + 1];
                                Output[OOffs + 2] = Input[IOffs + 0];
                                Output[OOffs + 3] = 0xff;

                                break;

                            case PICATextureFormat.RGBA5551:
                                DecodeRGBA5551(Output, OOffs, GetUShort(Input, IOffs));

                                break;

                            case PICATextureFormat.RGB565:
                                DecodeRGB565(Output, OOffs, GetUShort(Input, IOffs));

                                break;

                            case PICATextureFormat.RGBA4:
                                DecodeRGBA4(Output, OOffs, GetUShort(Input, IOffs));

                                break;

                            case PICATextureFormat.LA8:
                                Output[OOffs + 0] = Input[IOffs + 1];
                                Output[OOffs + 1] = Input[IOffs + 1];
                                Output[OOffs + 2] = Input[IOffs + 1];
                                Output[OOffs + 3] = Input[IOffs + 0];

                                break;

                            case PICATextureFormat.HiLo8:
                                Output[OOffs + 0] = Input[IOffs + 1];
                                Output[OOffs + 1] = Input[IOffs + 0];
                                Output[OOffs + 2] = 0;
                                Output[OOffs + 3] = 0xff;

                                break;

                            case PICATextureFormat.L8:
                                Output[OOffs + 0] = Input[IOffs];
                                Output[OOffs + 1] = Input[IOffs];
                                Output[OOffs + 2] = Input[IOffs];
                                Output[OOffs + 3] = 0xff;

                                break;

                            case PICATextureFormat.A8:
                                Output[OOffs + 0] = 0xff;
                                Output[OOffs + 1] = 0xff;
                                Output[OOffs + 2] = 0xff;
                                Output[OOffs + 3] = Input[IOffs];

                                break;

                            case PICATextureFormat.LA4:
                                Output[OOffs + 0] = (byte)((Input[IOffs] >> 4) | (Input[IOffs] & 0xf0));
                                Output[OOffs + 1] = (byte)((Input[IOffs] >> 4) | (Input[IOffs] & 0xf0));
                                Output[OOffs + 2] = (byte)((Input[IOffs] >> 4) | (Input[IOffs] & 0xf0));
                                Output[OOffs + 3] = (byte)((Input[IOffs] << 4) | (Input[IOffs] & 0x0f));

                                break;

                            case PICATextureFormat.L4:
                                int L = (Input[IOffs >> 1] >> ((IOffs & 1) << 2)) & 0xf;

                                Output[OOffs + 0] = (byte)((L << 4) | L);
                                Output[OOffs + 1] = (byte)((L << 4) | L);
                                Output[OOffs + 2] = (byte)((L << 4) | L);
                                Output[OOffs + 3] = 0xff;

                                break;

                            case PICATextureFormat.A4:
                                int A = (Input[IOffs >> 1] >> ((IOffs & 1) << 2)) & 0xf;

                                Output[OOffs + 0] = 0xff;
                                Output[OOffs + 1] = 0xff;
                                Output[OOffs + 2] = 0xff;
                                Output[OOffs + 3] = (byte)((A << 4) | A);

                                break;
                            }

                            IOffs += Increment;
                        }
                    }
                }

                return(Output);
            }
        }