/*static IEnumerable<Point> GetPointSequence(ImageSettings settings) * { * switch (settings.Format) * { * case Format.ATI1A: * case Format.ATI1L: * case Format.ATI2: * case Format.ETC1: * case Format.ETC1A4: * case Format.DXT1: * case Format.DXT3: * case Format.DXT5: * settings.TileSize = settings.TileSize + 3 & ~0x3; * break; * } * * int strideWidth = (settings.Width + 7) & ~7; * int strideHeight = (settings.Height + 7) & ~7; * if (settings.PadToPowerOf2) * { * strideWidth = 2 << (int)Math.Log(strideWidth - 1, 2); * strideHeight = 2 << (int)Math.Log(strideHeight - 1, 2); * } * * //stride TileSize * var tileSize = 0; * if (settings.ZOrder) * tileSize = 2 << (int)(Math.Log(((settings.TileSize + 7) & ~7) - 1, 2)); * else * tileSize = settings.TileSize; * int powTileSize = (int)Math.Pow(tileSize, 2); * * int stride = strideWidth; * switch (settings.Orientation) * { * case Orientation.Rotate90: * case Orientation.Transpose: * stride = strideHeight; * break; * } * * for (int i = 0; i < strideWidth * strideHeight; i++) * { * //in == order inside a tile * //out == order of tiles themselves * int x_out = 0, y_out = 0, x_in = 0, y_in = 0; * if (settings.ZOrder) * { * x_out = (i / powTileSize % (stride / tileSize)) * tileSize; * y_out = (i / powTileSize / (stride / tileSize)) * tileSize; * x_in = ZOrderX(tileSize, i); * y_in = ZOrderY(tileSize, i); * } * else * { * x_out = (i / powTileSize % (stride / tileSize)) * tileSize; * y_out = (i / powTileSize / (stride / tileSize)) * tileSize; * * switch (settings.Format) * { * case Format.ATI1A: * case Format.ATI1L: * case Format.ATI2: * case Format.ETC1: * case Format.ETC1A4: * case Format.DXT1: * case Format.DXT3: * case Format.DXT5: * x_in = (i % 4 + i % powTileSize / 16 * 4) % tileSize; * y_in = (i % 16 / 4 + i / (tileSize * 4) * 4) % tileSize; * break; * default: * x_in = i % powTileSize % tileSize; * y_in = i % powTileSize / tileSize; * break; * } * } * * switch (settings.Orientation) * { * case Orientation.Default: * yield return new Point(x_out + x_in, y_out + y_in); * break; * case Orientation.HorizontalFlip: * yield return new Point(stride - 1 - (x_out + x_in), y_out + y_in); * break; * case Orientation.Rotate90: * yield return new Point(y_out + y_in, stride - 1 - (x_out + x_in)); * break; * case Orientation.Transpose: * yield return new Point(y_out + y_in, x_out + x_in); * break; * case Orientation.TransposeTile: * yield return new Point(x_out + y_in, y_out + x_in); * break; * default: * throw new NotSupportedException($"Unknown orientation format {settings.Orientation}"); * } * } * } * static int ZOrderX(int tileSize, int count) * { * var div = tileSize / 2; * var x_in = count / div & div; * * while (div > 1) * { * div /= 2; * x_in |= count / div & div; * } * * return x_in; * } * static int ZOrderY(int tileSize, int count) * { * var div = tileSize; * var div2 = tileSize / 2; * var y_in = count / div & div2; * * while (div2 > 1) * { * div /= 2; * div2 /= 2; * y_in |= count / div & div2; * } * * return y_in; * }*/ /// <summary> /// Loads the binary data with given settings as an image /// </summary> /// <param name="tex"> /// Bytearray containing the binary image data /// </param> /// <param name="settings"> /// The settings determining the final image output /// </param> public static Bitmap Load(byte[] tex, ImageSettings settings) { int width = settings.Width, height = settings.Height; var points = GetPointSequence(settings); var bmp = new Bitmap(width, height); var data = bmp.LockBits(new Rectangle(0, 0, width, height), ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb); unsafe { var ptr = (int *)data.Scan0; foreach (var pair in points.Zip(settings.Format.Load(tex), Tuple.Create)) { int x = pair.Item1.X, y = pair.Item1.Y; if (0 <= x && x < width && 0 <= y && y < height) { var color = pair.Item2; if (settings.PixelShader != null) { color = settings.PixelShader(color); } ptr[data.Stride * y / 4 + x] = color.ToArgb(); } } } bmp.UnlockBits(data); return(bmp); }
/// <summary> /// Gives back a sequence of points, modified by Swizzles if applied /// </summary> static IEnumerable <Point> GetPointSequence(ImageSettings settings) { int strideWidth = (settings.Swizzle != null) ? settings.Swizzle.Width : settings.Width; int strideHeight = (settings.Swizzle != null) ? settings.Swizzle.Height : settings.Height; for (int i = 0; i < strideWidth * strideHeight; i++) { var point = new Point(i % strideWidth, i / strideWidth); if (settings.Swizzle != null) { point = settings.Swizzle.Get(point); } yield return(point); } }
static IEnumerable <Point> GetInnerTile(ImageSettings settings) { int tileSize = settings.TileSize; int powTileSize = (int)Math.Pow(tileSize, 2); for (int i = 0; i < powTileSize; i++) { if (settings.InnerSwizzle == null) { yield return(new Point(i % powTileSize % tileSize, i % powTileSize / tileSize)); } else { yield return(settings.InnerSwizzle.InnerLoad(i, tileSize)); } } }
/// <summary> /// Converts a given Bitmap, modified by given settings, in binary data /// </summary> /// <param name="bmp">The bitmap, which will be converted</param> /// <param name="settings">Settings like Format, Dimensions and Swizzles</param> /// <returns>byte[]</returns> public static byte[] Save(Bitmap bmp, ImageSettings settings) { var points = GetPointSequence(settings); var colors = new List <Color>(); foreach (var point in points) { int x = Clamp(point.X, 0, bmp.Width); int y = Clamp(point.Y, 0, bmp.Height); var color = bmp.GetPixel(x, y); if (settings.PixelShader != null) { color = settings.PixelShader(color); } colors.Add(color); } return(settings.Format.Save(colors)); }
/// <summary> /// Gives back a sequence of points, modified by Swizzles if applied /// </summary> static IEnumerable <Point> GetPointSequence(ImageSettings settings) { int tileSize = settings.TileSize; int powTileSize = (int)Math.Pow(tileSize, 2); int strideWidth = (settings.Width + (tileSize - 1)) & ~(tileSize - 1); int strideHeight = (settings.Height + (tileSize - 1)) & ~(tileSize - 1); if (settings.PadToPowerOf2) { strideWidth = 2 << (int)Math.Log(strideWidth - 1, 2); strideHeight = 2 << (int)Math.Log(strideHeight - 1, 2); } int stride = strideWidth; for (int i = 0; i < strideWidth * strideHeight; i += powTileSize) { var innerTile = GetInnerTile(settings); foreach (var point in innerTile) { if (settings.OuterSwizzle == null) { var point2 = new Point( ((i / powTileSize % (stride / tileSize)) * tileSize) + point.X, ((i / powTileSize / (stride / tileSize)) * tileSize) + point.Y); yield return(point2); } else { var point2 = settings.OuterSwizzle.OuterLoad(i, tileSize, strideWidth); point2.X += point.X; point2.Y += point.Y; yield return(point2); } } } }