public static Bitmap CropBMP(IXLIMHeader bclim, Bitmap img) { Rectangle cropRect = new Rectangle(0, 0, bclim.Width, bclim.Height); Bitmap src = img; Bitmap target = new Bitmap(cropRect.Width, cropRect.Height); using (Graphics g = Graphics.FromImage(target)) { g.DrawImage(src, new Rectangle(0, 0, target.Width, target.Height), cropRect, GraphicsUnit.Pixel); } Console.WriteLine($"Returning cropped {target.Width}"); return(target); }
private static Bitmap DecodeETC(IXLIMHeader bclim, Bitmap img, byte[] textureData, bool etc1A4) { /* http://jul.rustedlogic.net/thread.php?id=17312 * Much of this code is taken/modified from Tharsis. Thank you to Tharsis's creator, xdaniel. * https://github.com/xdanieldzd/Tharsis */ /* Get compressed data & handle to it */ //textureData = switchEndianness(textureData, 0x10); ushort[] input = new ushort[textureData.Length / sizeof(ushort)]; Buffer.BlockCopy(textureData, 0, input, 0, textureData.Length); GCHandle pInput = GCHandle.Alloc(input, GCHandleType.Pinned); /* Marshal data around, invoke ETC1.dll for conversion, etc */ uint size1 = 0; var w = (ushort)img.Width; var h = (ushort)img.Height; ETC1.ConvertETC1(IntPtr.Zero, ref size1, IntPtr.Zero, w, h, etc1A4); // true = etc1a4, false = etc1 uint[] output = new uint[size1]; GCHandle pOutput = GCHandle.Alloc(output, GCHandleType.Pinned); ETC1.ConvertETC1(pOutput.AddrOfPinnedObject(), ref size1, pInput.AddrOfPinnedObject(), w, h, etc1A4); pOutput.Free(); pInput.Free(); /* Unscramble if needed // could probably be done in ETC1Lib.dll, it's probably pretty ugly, but whatever... */ /* Non-square code blocks could need some cleanup, verification, etc. as well... */ uint[] finalized = new uint[output.Length]; // Act if it's square because BCLIM swizzling is stupid Buffer.BlockCopy(output, 0, finalized, 0, finalized.Length); byte[] tmp = new byte[finalized.Length]; Buffer.BlockCopy(finalized, 0, tmp, 0, tmp.Length); byte[] imgData = tmp; for (int i = 0; i < w; i++) { for (int j = 0; j < h; j++) { int k = (j + (i * img.Height)) * 4; img.SetPixel(i, j, Color.FromArgb(imgData[k + 3], imgData[k], imgData[k + 1], imgData[k + 2])); } } if (bclim is BFLIM) { return(img); } // Image is 13 instead of 12 // 24 34 img.RotateFlip(RotateFlipType.Rotate90FlipX); if (w > h) { // Image is now in appropriate order, but the shifting is messed up. Let's fix that. Bitmap img2 = new Bitmap(Math.Max(NextLargestPow2(bclim.Width), 16), Math.Max(NextLargestPow2(bclim.Height), 16)); for (int y = 0; y < Math.Max(NextLargestPow2(bclim.Width), 16); y += 8) { for (int x = 0; x < Math.Max(NextLargestPow2(bclim.Height), 16); x++) { for (int j = 0; j < 8; j++) // Treat every 8 vertical pixels as 1 pixel for purposes of calculation, add to offset later. { int x1 = (x + (y / 8 * h)) % img2.Width; // Reshift x int y1 = (x + (y / 8 * h)) / img2.Width * 8; // Reshift y img2.SetPixel(x1, y1 + j, img.GetPixel(x, y + j)); // Reswizzle } } } return(img2); } if (h > w) { Bitmap img2 = new Bitmap(Math.Max(NextLargestPow2(bclim.Width), 16), Math.Max(NextLargestPow2(bclim.Height), 16)); for (int y = 0; y < Math.Max(NextLargestPow2(bclim.Width), 16); y += 8) { for (int x = 0; x < Math.Max(NextLargestPow2(bclim.Height), 16); x++) { for (int j = 0; j < 8; j++) // Treat every 8 vertical pixels as 1 pixel for purposes of calculation, add to offset later. { int x1 = x % img2.Width; // Reshift x int y1 = (x + (y / 8 * h)) / img2.Width * 8; // Reshift y img2.SetPixel(x1, y1 + j, img.GetPixel(x, y + j)); // Reswizzle } } } return(img2); } return(img); }