public static Bitmap Load(byte[] tex, ImageSettings settings) { int width = settings.Width, height = settings.Height; var colors = GetColorsFromTexture(tex, settings); var points = GetPointSequence(settings); // Now we just need to merge the points with the colors 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(colors, 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); }
public static byte[] Save(Bitmap bmp, ImageSettings settings) { settings.Width = bmp.Width; settings.Height = bmp.Height; var points = GetPointSequence(settings); var ms = new MemoryStream(); var etc1encoder = new ETC1.Encoder(); Enum.TryParse <DXT.Formats>(settings.Format.ToString(), false, out var dxtFormat); var dxtencoder = new DXT.Encoder(dxtFormat); using (var bw = new BinaryWriterX(ms)) { 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); } switch (settings.Format) { case Format.L8: bw.Write(color.G); break; case Format.A8: bw.Write(color.A); break; case Format.LA44: bw.WriteNibble(color.A / 16); bw.WriteNibble(color.G / 16); break; case Format.LA88: bw.Write(color.A); bw.Write(color.G); break; case Format.HL88: bw.Write(color.G); bw.Write(color.R); break; case Format.RGB565: bw.Write((short)((color.R / 8 << 11) | (color.G / 4 << 5) | (color.B / 8))); break; case Format.RGB888: bw.Write(color.B); bw.Write(color.G); bw.Write(color.R); break; case Format.RGBA5551: bw.Write((short)((color.R / 8 << 11) | (color.G / 8 << 6) | (color.B / 8 << 1) | color.A / 128)); break; case Format.RGBA4444: bw.WriteNibble(color.A / 16); bw.WriteNibble(color.B / 16); bw.WriteNibble(color.G / 16); bw.WriteNibble(color.R / 16); break; case Format.RGBA8888: bw.Write(color.A); bw.Write(color.B); bw.Write(color.G); bw.Write(color.R); break; case Format.ETC1: case Format.ETC1A4: etc1encoder.Set(color, data => { if (settings.Format == Format.ETC1A4) { bw.Write(data.Alpha); } bw.WriteStruct(data.Block); }); break; case Format.DXT1: case Format.DXT5: dxtencoder.Set(color, data => { if (settings.Format == Format.DXT5) { bw.Write(data.alpha); } bw.Write(data.block); }); break; case Format.L4: bw.WriteNibble(color.G / 16); break; case Format.A4: bw.WriteNibble(color.A / 16); break; default: throw new NotSupportedException(); } } } return(ms.ToArray()); }