private static MagickImage Decode(AwesomeReader ar, ImageEncoding encoding, uint bpp, uint mipmap, uint width, uint height, uint bpl, bool ps2Texture = false) { // Image starts at bottom left corner switch (encoding) { case ImageEncoding.BMP: return(DecodeBMP(ar, bpp, width, height, bpl)); case ImageEncoding.DXT1: return(bpp == 8 ? DecodeBMP(ar, bpp, width, height, bpl, false) : DecodeDXT(ar, bpp, width, height, encoding)); case ImageEncoding.DXT5: case ImageEncoding.ATI2: return(DecodeDXT(ar, bpp, width, height, encoding)); } return(null); }
public static Matrix FromStream(AwesomeReader ar) { // Reads from stream, usually embedded inside milo directories and mesh files Matrix mat = new Matrix(); mat.M11 = ar.ReadSingle(); // M11 mat.M12 = ar.ReadSingle(); // M12 mat.M13 = ar.ReadSingle(); // M13 mat.M21 = ar.ReadSingle(); // M21 mat.M22 = ar.ReadSingle(); // M22 mat.M23 = ar.ReadSingle(); // M23 mat.M31 = ar.ReadSingle(); // M31 mat.M32 = ar.ReadSingle(); // M32 mat.M33 = ar.ReadSingle(); // M33 mat.M41 = ar.ReadSingle(); // M41 mat.M42 = ar.ReadSingle(); // M42 mat.M43 = ar.ReadSingle(); // M43 mat.M44 = 1.0f; // M44 - Implicit return(mat); }
public static HMXImage FromStream(Stream input) { /* Header size = 32 bytes * ====================== * BYTE - Always 1 * BYTE - Bits Per Pixel - Can be 4, 8, 24, or 32 (But usually either 4 or 8) * INT32 - Image Format/Encoding * BYTE - MipMaps count * INT16 - Width * INT16 - Height * INT16 - Bytes Per Line * BYTES - 19 bytes of zero'd data */ /* Header size = 16 bytes * ====================== * BYTE - Always 0 * BYTE - Bits Per Pixel - Can be 4, 8, 24, or 32 (But usually either 4 or 8) * BYTE - Always 0 (Image Format/Encoding) * BYTE - Awlays 0 MipMaps count * INT16 - Width * INT16 - Height * INT16 - Bytes Per Line * BYTES - 6 bytes of zero'd data */ if (input.Position == input.Length) { return(null); // End of stream; } using (AwesomeReader ar = new AwesomeReader(input)) { ImageEncoding encoding; bool valid; uint bpp, width, height, bpl, mipmap; byte firstByte = ar.ReadByte(); if (firstByte != 0 && firstByte != 1) { return(null); } bpp = ar.ReadByte(); switch (bpp) { case 4: case 8: case 24: case 32: break; default: return(null); // Probably should do something else } if (firstByte == 1) { // Guesses endianess ar.BigEndian = DetermineEndianess(ar.ReadBytes(4), out encoding, out valid); if (!valid) { return(null); // Maybe do something else later } // Reads rest of header mipmap = ar.ReadByte(); // Mipmap count } else { // Xbox OG texture encoding = ImageEncoding.BMP; ar.BaseStream.Position += 2; mipmap = 0; } width = ar.ReadUInt16(); height = ar.ReadUInt16(); bpl = ar.ReadUInt16(); ar.BaseStream.Position += (firstByte == 1) ? 19 : 6; // Decodes image var magic = Decode(ar, encoding, bpp, mipmap, width, height, bpl, firstByte == 1); HMXImage image = new HMXImage(magic); image.Encoding = encoding; image.BigEndian = ar.BigEndian; return(image); } }
private static MagickImage DecodeDXT(AwesomeReader ar, uint bpp, uint width, uint height, ImageEncoding encoding, bool x360 = true) { uint imageSize; string compression; switch (encoding) { default: case ImageEncoding.DXT1: imageSize = (width * height) / 2; // 4bpp compression = "DXT1"; break; case ImageEncoding.DXT5: imageSize = width * height; // 8bpp compression = "DXT5"; break; case ImageEncoding.ATI2: imageSize = width * height; // 8bpp compression = "ATI2"; break; } if (encoding == ImageEncoding.DXT1) { const int PIXELS_PER_BLOCK = 16; int blockSize = (PIXELS_PER_BLOCK * (int)bpp) / 8; byte[] data = ar.ReadBytes((int)imageSize); if (x360) { SwapBytes(data); } Color FromRGB565(int c) => Color.FromArgb( 0xFF, (c & 0b1111_1000_0000_0000) >> 8, (c & 0b0000_0111_1110_0000) >> 3, (c & 0b0000_0000_0001_1111) << 3); Color MultiplyColor(Color c, float mult) => Color.FromArgb( (int)(c.A * mult), (int)(c.R * mult), (int)(c.G * mult), (int)(c.B * mult)); Color AddColors(Color a, Color b) => Color.FromArgb( a.A + b.A, a.R + b.R, a.G + b.G, a.B + b.B); int idx = 0; var colors = new Color[4]; var pixels = new Color[16]; int w, h; var imageBytes = new byte[width * height * 4]; // 32-bit color for (int y = 0; y < (height >> 2); y++) { for (int x = 0; x < (width >> 2); x++) { // Colors - 4 bytes colors[0] = FromRGB565(data[idx] | data[idx + 1] << 8); colors[1] = FromRGB565(data[idx + 2] | data[idx + 3] << 8); colors[2] = AddColors(MultiplyColor(colors[0], 0.66f), MultiplyColor(colors[1], 0.33f)); colors[3] = AddColors(MultiplyColor(colors[0], 0.33f), MultiplyColor(colors[1], 0.66f)); //colors[2] = AddColors(MultiplyColor(colors[0], 0.5f), MultiplyColor(colors[1], 0.5f)); //colors[3] = Color.FromArgb(0); // Indices - 4 bytes (16 pixels) pixels[0] = colors[(data[idx + 4] & 0b00_00_00_11)]; // Row 1