//Much help from encoding thanks to this
        // https://github.com/Cruel/3dstex/blob/master/src/Encoder.cpp
        public static byte[] EncodeBlock(byte[] Input, int Width, int Height, PICASurfaceFormat PicaFormat)
        {
            int ImageSize = CalculateLength(Width, Height, PicaFormat);

            if (PicaFormat == PICASurfaceFormat.ETC1 ||
                PicaFormat == PICASurfaceFormat.ETC1A4)
            {
                return(new byte[ImageSize]);

                return(ETC1.ETC1Encode(Input, Width, Height, PicaFormat == PICASurfaceFormat.ETC1A4));
            }

            var mem = new System.IO.MemoryStream();

            using (var writer = new FileWriter(mem))
            {
                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 IOffs = (TX + X + ((TY + Y) * Width)) * 4;
                            if (PicaFormat == PICASurfaceFormat.RGBA8)
                            {
                                writer.Write(Input[IOffs + 3]);
                                writer.Write(Input[IOffs + 0]);
                                writer.Write(Input[IOffs + 1]);
                                writer.Write(Input[IOffs + 2]);
                            }
                            else if (PicaFormat == PICASurfaceFormat.RGB8)
                            {
                                writer.Write(Input[IOffs + 0]);
                                writer.Write(Input[IOffs + 1]);
                                writer.Write(Input[IOffs + 2]);
                            }
                            else if (PicaFormat == PICASurfaceFormat.A8)
                            {
                                writer.Write(Input[IOffs]);
                            }
                            else if (PicaFormat == PICASurfaceFormat.L8)
                            {
                                writer.Write(ConvertBRG8ToL(
                                                 new byte[]
                                {
                                    Input[IOffs + 0],
                                    Input[IOffs + 1],
                                    Input[IOffs + 2]
                                }));
                            }
                            else if (PicaFormat == PICASurfaceFormat.LA8)
                            {
                                writer.Write(Input[IOffs + 3]);
                                writer.Write(ConvertBRG8ToL(
                                                 new byte[]
                                {
                                    Input[IOffs + 0],
                                    Input[IOffs + 1],
                                    Input[IOffs + 2]
                                }));
                            }
                            else if (PicaFormat == PICASurfaceFormat.RGB565)
                            {
                                ushort R = (ushort)(Convert8To5(Input[IOffs + 0]));
                                ushort G = (ushort)(Convert8To6(Input[IOffs + 1]) << 5);
                                ushort B = (ushort)(Convert8To5(Input[IOffs + 2]) << 11);

                                writer.Write((ushort)(R | G | B));
                            }
                            else if (PicaFormat == PICASurfaceFormat.RGBA4)
                            {
                                ushort R = (ushort)(Convert8To4(Input[IOffs]) << 4);
                                ushort G = (ushort)(Convert8To4(Input[IOffs + 1]) << 8);
                                ushort B = (ushort)(Convert8To4(Input[IOffs + 2]) << 12);
                                ushort A = (ushort)(Convert8To4(Input[IOffs + 3]));

                                writer.Write((ushort)(R | G | B | A));
                            }
                            else if (PicaFormat == PICASurfaceFormat.RGBA5551)
                            {
                                ushort R = (ushort)(Convert8To5(Input[IOffs + 0]) << 1);
                                ushort G = (ushort)(Convert8To5(Input[IOffs + 1]) << 6);
                                ushort B = (ushort)(Convert8To5(Input[IOffs + 2]) << 11);
                                ushort A = (ushort)(Convert8To1(Input[IOffs + 3]));

                                writer.Write((ushort)(R | G | B | A));
                            }
                            else if (PicaFormat == PICASurfaceFormat.LA4)
                            {
                                byte A = Input[IOffs + 3];
                                byte L = ConvertBRG8ToL(
                                    new byte[]
                                {
                                    Input[IOffs + 0],
                                    Input[IOffs + 1],
                                    Input[IOffs + 2]
                                });
                                writer.Write((byte)((A >> 4) | (L & 0xF0)));
                            }
                            else if (PicaFormat == PICASurfaceFormat.L4)
                            {
                                //Todo this has issues
                                byte L1 = ConvertBRG8ToL(
                                    new byte[]
                                {
                                    Input[IOffs + 0],
                                    Input[IOffs + 1],
                                    Input[IOffs + 2]
                                });

                                writer.Write((byte)(L1 >> 4));
                            }
                            else if (PicaFormat == PICASurfaceFormat.A4)
                            {
                                //Todo this has issues
                                byte A1 = (byte)(Input[IOffs] >> 4);
                                byte A2 = (byte)(Input[IOffs + 3] & 0xF0);
                                writer.Write((byte)(A1 | A2));
                            }
                            else if (PicaFormat == PICASurfaceFormat.HiLo8)
                            {
                                writer.Write(Input[IOffs]);
                                writer.Write(Input[IOffs + 1]);
                            }
                        }
                    }
                }
            }

            byte[] newOutput = mem.ToArray();
            if (newOutput.Length > 0)
            {
                return(newOutput);
            }
            else
            {
                return(new byte[CalculateLength(Width, Height, PicaFormat)]);
            }
        }
        public static byte[] DecodeBlock(byte[] Input, int Width, int Height, PICASurfaceFormat picaFormat)
        {
            if (picaFormat == PICASurfaceFormat.ETC1 || picaFormat == PICASurfaceFormat.ETC1A4)
            {
                return(ETC1.ETC1Decompress(Input, Width, Height, picaFormat == PICASurfaceFormat.ETC1A4));
            }

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

            int Increment = FmtBPP[(int)picaFormat] / 8;

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

            int IOffset = 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 OOffet = (TX + X + ((Height - 1 - (TY + Y)) * Width)) * 4;

                        switch (picaFormat)
                        {
                        case PICASurfaceFormat.RGBA8:
                            Output[OOffet + 0] = Input[IOffset + 3];
                            Output[OOffet + 1] = Input[IOffset + 2];
                            Output[OOffet + 2] = Input[IOffset + 1];
                            Output[OOffet + 3] = Input[IOffset + 0];
                            break;

                        case PICASurfaceFormat.RGB8:
                            Output[OOffet + 0] = Input[IOffset + 2];
                            Output[OOffet + 1] = Input[IOffset + 1];
                            Output[OOffet + 2] = Input[IOffset + 0];
                            Output[OOffet + 3] = 0xff;
                            break;

                        case PICASurfaceFormat.RGBA5551:
                            DecodeRGBA5551(Output, OOffet, GetUShort(Input, IOffset));
                            break;

                        case PICASurfaceFormat.RGB565:
                            DecodeRGB565(Output, OOffet, GetUShort(Input, IOffset));
                            break;

                        case PICASurfaceFormat.RGBA4:
                            DecodeRGBA4(Output, OOffet, GetUShort(Input, IOffset));
                            break;

                        case PICASurfaceFormat.LA8:
                            Output[OOffet + 0] = Input[IOffset + 1];
                            Output[OOffet + 1] = Input[IOffset + 1];
                            Output[OOffet + 2] = Input[IOffset + 1];
                            Output[OOffet + 3] = Input[IOffset + 0];
                            break;

                        case PICASurfaceFormat.HiLo8:
                            Output[OOffet + 0] = Input[IOffset + 1];
                            Output[OOffet + 1] = Input[IOffset + 0];
                            Output[OOffet + 2] = 0;
                            Output[OOffet + 3] = 0xff;
                            break;

                        case PICASurfaceFormat.L8:
                            Output[OOffet + 0] = Input[IOffset];
                            Output[OOffet + 1] = Input[IOffset];
                            Output[OOffet + 2] = Input[IOffset];
                            Output[OOffet + 3] = 0xff;
                            break;

                        case PICASurfaceFormat.A8:
                            Output[OOffet + 0] = 0xff;
                            Output[OOffet + 1] = 0xff;
                            Output[OOffet + 2] = 0xff;
                            Output[OOffet + 3] = Input[IOffset];
                            break;

                        case PICASurfaceFormat.LA4:
                            Output[OOffet + 0] = (byte)((Input[IOffset] >> 4) | (Input[IOffset] & 0xf0));
                            Output[OOffet + 1] = (byte)((Input[IOffset] >> 4) | (Input[IOffset] & 0xf0));
                            Output[OOffet + 2] = (byte)((Input[IOffset] >> 4) | (Input[IOffset] & 0xf0));
                            Output[OOffet + 3] = (byte)((Input[IOffset] << 4) | (Input[IOffset] & 0x0f));
                            break;

                        case PICASurfaceFormat.L4:
                            int L = (Input[IOffset >> 1] >> ((IOffset & 1) << 2)) & 0xf;
                            Output[OOffet + 0] = (byte)((L << 4) | L);
                            Output[OOffet + 1] = (byte)((L << 4) | L);
                            Output[OOffet + 2] = (byte)((L << 4) | L);
                            Output[OOffet + 3] = 0xff;
                            break;

                        case PICASurfaceFormat.A4:
                            int A = (Input[IOffset >> 1] >> ((IOffset & 1) << 2)) & 0xf;
                            Output[OOffet + 0] = 0xff;
                            Output[OOffet + 1] = 0xff;
                            Output[OOffet + 2] = 0xff;
                            Output[OOffet + 3] = (byte)((A << 4) | A);
                            break;
                        }

                        IOffset += Increment;
                    }
                }
            }

            return(Output);
        }