//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); }