public static System.Drawing.Color[] QuantizeFrame(SPR2Frame frame, out byte[] bytes) { var bmps = frame.GetPixelAlpha(frame.Width, frame.Height, new Vector2()); /* * SimplePaletteQuantizer.Quantizers.IColorQuantizer quantizer = new DistinctSelectionQuantizer(); * * using (ImageBuffer buffer = new ImageBuffer(bmps[0], ImageLockMode.ReadOnly)) * { * quantizer.Prepare(buffer); * buffer.ScanColors(quantizer, 4); // 4 = parallel task count * } * * Bitmap quantpx = new Bitmap(bmps[0].Width, bmps[0].Height, PixelFormat.Format8bppIndexed); * ImageBuffer.DitherImage(bmps[0], quantpx, new JarvisJudiceNinkeDitherer(), quantizer, 255, 4);*/ var quantpx = (Bitmap)ImageBuffer.QuantizeImage(bmps[0], new DistinctSelectionQuantizer(), null, 255, 4); var palt = quantpx.Palette.Entries; var data = quantpx.LockBits(new System.Drawing.Rectangle(0, 0, quantpx.Width, quantpx.Height), ImageLockMode.ReadOnly, PixelFormat.Format8bppIndexed); bytes = new byte[data.Height * data.Width]; // copy the bytes from bitmap to array for (int i = 0; i < data.Height; i++) { Marshal.Copy(data.Scan0 + i * data.Stride, bytes, i * data.Width, data.Width); } return(palt); }
/// <summary> /// Reads a SPR2 chunk from a stream. /// </summary> /// <param name="iff">An Iff instance.</param> /// <param name="stream">A Stream object holding a SPR2 chunk.</param> public override void Read(IffFile iff, Stream stream) { using (var io = IoBuffer.FromStream(stream, ByteOrder.LITTLE_ENDIAN)) { var version = io.ReadUInt32(); uint spriteCount = 0; if (version == 1000) { spriteCount = io.ReadUInt32(); DefaultPaletteID = io.ReadUInt32(); var offsetTable = new uint[spriteCount]; for (var i = 0; i < spriteCount; i++) { offsetTable[i] = io.ReadUInt32(); } Frames = new SPR2Frame[spriteCount]; for (var i = 0; i < spriteCount; i++) { var frame = new SPR2Frame(this); io.Seek(SeekOrigin.Begin, offsetTable[i]); var guessedSize = ((i + 1 < offsetTable.Length) ? offsetTable[i + 1] : (uint)stream.Length) - offsetTable[i]; frame.Read(version, io, guessedSize); Frames[i] = frame; } } else if (version == 1001) { DefaultPaletteID = io.ReadUInt32(); spriteCount = io.ReadUInt32(); Frames = new SPR2Frame[spriteCount]; for (var i = 0; i < spriteCount; i++) { var frame = new SPR2Frame(this); frame.Read(version, io, 0); Frames[i] = frame; } } } }
private void NewRotation(int num) { Content.Content.Get().Changes.BlockingResMod(new ResAction(() => { var oldToNew = new Dictionary<int, int>(); var old = GraphicChunk.Frames; var oldLen = old.Length; var result = new SPR2Frame[oldLen+num*3]; var index = 0; for (int j = 0; j < 3; j++) { for (int i = 0; i < oldLen / 3; i++) { oldToNew.Add(j * (oldLen / 3) + i, index); result[index++] = old[j * (oldLen / 3) + i]; } for (int i=0; i<num; i++) result[index++] = new SPR2Frame(GraphicChunk) { PaletteID = (ushort)GraphicChunk.DefaultPaletteID }; } GraphicChunk.Frames = result; foreach (var dgrp in GraphicChunk.ChunkParent.List<DGRP>()) { foreach (var img in dgrp.Images) { foreach (var spr in img.Sprites) { if (spr.SpriteID == GraphicChunk.ChunkID) { var oldspr = spr.SpriteFrameIndex; if (oldToNew.ContainsKey((int)spr.SpriteFrameIndex)) spr.SpriteFrameIndex = (uint)oldToNew[(int)spr.SpriteFrameIndex]; else spr.SpriteFrameIndex = 0; if (oldspr != spr.SpriteFrameIndex) Content.Content.Get().Changes.ChunkChanged(dgrp); } } } } }, GraphicChunk)); SetActiveResource(GraphicChunk, ActiveIff); FrameList.SelectedIndex = FrameList.Items.Count - 1; }
public static void WriteFrame(SPR2Frame frame, IoWriter output) { var bytes = frame.PalData; var col = frame.PixelData; var zs = frame.ZBufferData; int index = 0; int blankLines = 0; for (int y = 0; y < frame.Height; y++) { byte lastCmd = 0; List <byte> dataBuf = new List <byte>(); int rlecount = 0; bool anySolid = false; var scanStream = new MemoryStream(); var scanOut = IoWriter.FromStream(scanStream, ByteOrder.LITTLE_ENDIAN); for (int x = 0; x < frame.Width; x++) { byte plt = bytes[index]; byte a = col[index].A; byte z = zs[index]; var cmd = getCmd(plt, a, z); if (x == 0 || cmd != lastCmd) { if (x != 0) { //write a command to write the last sequence of pixels scanOut.WriteUInt16((ushort)(((int)lastCmd << 13) | rlecount)); if ((dataBuf.Count % 2) != 0) { dataBuf.Add(0); } scanOut.WriteBytes(dataBuf.ToArray()); dataBuf.Clear(); } lastCmd = cmd; rlecount = 0; } switch (cmd) { case 0x1: case 0x2: dataBuf.Add(z); dataBuf.Add(plt); if (cmd == 0x2) { dataBuf.Add((byte)Math.Ceiling(a / 8.2258064516129032258064516129032)); } anySolid = true; break; case 0x6: dataBuf.Add(plt); anySolid = true; break; default: break; } rlecount++; index++; } if (anySolid) { //write a command to write the last sequence of pixels scanOut.WriteUInt16((ushort)(((int)lastCmd << 13) | rlecount)); if ((dataBuf.Count % 2) != 0) { dataBuf.Add(0); } scanOut.WriteBytes(dataBuf.ToArray()); dataBuf.Clear(); } var scanData = scanStream.ToArray(); if (scanData.Length == 0) { blankLines++; //line is transparent } else { if (blankLines > 0) { //add transparent lines before our new command output.WriteUInt16((ushort)((0x4 << 13) | blankLines)); blankLines = 0; } output.WriteUInt16((ushort)(scanData.Length + 2)); output.WriteBytes(scanData); } } if (blankLines > 0) { //add transparent lines before our new command output.WriteUInt16((ushort)((0x4 << 13) | blankLines)); blankLines = 0; } output.WriteUInt16((ushort)(0x5 << 13)); return; }
public static void WriteFrame(SPR2Frame frame, IoWriter output) { var bytes = frame.PalData; var col = frame.PixelData; var zs = frame.ZBufferData; int index = 0; int blankLines = 0; for (int y=0; y<frame.Height; y++) { byte lastCmd = 0; List<byte> dataBuf = new List<byte>(); int rlecount = 0; bool anySolid = false; var scanStream = new MemoryStream(); var scanOut = IoWriter.FromStream(scanStream, ByteOrder.LITTLE_ENDIAN); for (int x=0; x<frame.Width; x++) { byte plt = bytes[index]; byte a = col[index].A; byte z = zs[index]; var cmd = getCmd(plt, a, z); if (x == 0 || cmd != lastCmd) { if (x != 0) { //write a command to write the last sequence of pixels scanOut.WriteUInt16((ushort)(((int)lastCmd<<13)|rlecount)); if ((dataBuf.Count % 2) != 0) dataBuf.Add(0); scanOut.WriteBytes(dataBuf.ToArray()); dataBuf.Clear(); } lastCmd = cmd; rlecount = 0; } switch (cmd) { case 0x1: case 0x2: dataBuf.Add(z); dataBuf.Add(plt); if (cmd == 0x2) dataBuf.Add((byte)Math.Ceiling(a/ 8.2258064516129032258064516129032)); anySolid = true; break; case 0x6: dataBuf.Add(plt); anySolid = true; break; default: break; } rlecount++; index++; } if (anySolid) { //write a command to write the last sequence of pixels scanOut.WriteUInt16((ushort)(((int)lastCmd << 13) | rlecount)); if ((dataBuf.Count % 2) != 0) dataBuf.Add(0); scanOut.WriteBytes(dataBuf.ToArray()); dataBuf.Clear(); } var scanData = scanStream.ToArray(); if (scanData.Length == 0) blankLines++; //line is transparent else { if (blankLines > 0) { //add transparent lines before our new command output.WriteUInt16((ushort)((0x4<<13) | blankLines)); blankLines = 0; } output.WriteUInt16((ushort)(scanData.Length+2)); output.WriteBytes(scanData); } } if (blankLines > 0) { //add transparent lines before our new command output.WriteUInt16((ushort)((0x4 << 13) | blankLines)); blankLines = 0; } output.WriteUInt16((ushort)(0x5<<13)); return; }
public static Microsoft.Xna.Framework.Color[] QuantizeFrame(SPR2Frame frame, out byte[] bytes) { var bmps = GetPixelAlpha(frame, frame.Width, frame.Height, new Vector2()); var quantpx = (Bitmap)ImageBuffer.QuantizeImage(bmps[0], new DistinctSelectionQuantizer(), null, 255, 4); var palt = quantpx.Palette.Entries; var data = quantpx.LockBits(new System.Drawing.Rectangle(0, 0, quantpx.Width, quantpx.Height), ImageLockMode.ReadOnly, PixelFormat.Format8bppIndexed); bytes = new byte[data.Height * data.Width]; // copy the bytes from bitmap to array for (int i = 0; i < data.Height; i++) { Marshal.Copy(data.Scan0 + i * data.Stride, bytes, i * data.Width, data.Width); } var result = new Microsoft.Xna.Framework.Color[palt.Length]; for (int i=0; i<palt.Length; i++) { var c = palt[i]; result[i] = new Microsoft.Xna.Framework.Color(c.R, c.G, c.B, c.A); } return result; }
public static System.Drawing.Image[] GetPixelAlpha(SPR2Frame sprite, int tWidth, int tHeight, Vector2 pos) { var result = new System.Drawing.Bitmap[3]; var locks = new BitmapData[3]; var data = new byte[3][]; for (int i = 0; i < 3; i++) { result[i] = new System.Drawing.Bitmap(tWidth, tHeight, PixelFormat.Format24bppRgb); locks[i] = result[i].LockBits(new System.Drawing.Rectangle(0, 0, tWidth, tHeight), ImageLockMode.ReadWrite, PixelFormat.Format32bppRgb); data[i] = new byte[locks[i].Stride * locks[i].Height]; } int index = 0; for (int y = 0; y < tHeight; y++) { for (int x = 0; x < tWidth; x++) { Microsoft.Xna.Framework.Color col; byte depth = 255; if (x >= pos.X && x < pos.X + sprite.Width && y >= pos.Y && y < pos.Y + sprite.Height) { col = sprite.PixelData[(int)(x - pos.X) + (int)(y - pos.Y) * sprite.Width]; if (col.A == 0) col = new Microsoft.Xna.Framework.Color(0xFF, 0xFF, 0x00, 0x00); if (sprite.ZBufferData != null) { depth = sprite.ZBufferData[(int)(x - pos.X) + (int)(y - pos.Y) * sprite.Width]; } } else { col = new Microsoft.Xna.Framework.Color(0xFF, 0xFF, 0x00, 0x00); } data[0][index] = col.B; data[0][index + 1] = col.G; data[0][index + 2] = col.R; data[0][index + 3] = 255; data[1][index] = col.A; data[1][index + 1] = col.A; data[1][index + 2] = col.A; data[1][index + 3] = 255; data[2][index] = depth; data[2][index + 1] = depth; data[2][index + 2] = depth; data[2][index + 3] = 255; index += 4; } } for (int i = 0; i < 3; i++) { Marshal.Copy(data[i], 0, locks[i].Scan0, data[i].Length); result[i].UnlockBits(locks[i]); } return result; }
/// <summary> /// Generates windows bitmaps for the appearance of this sprite. /// </summary> /// <param name="tWidth"></param> /// <param name="tHeight"></param> /// <returns>Array of three images, [Color, Alpha, Depth].</returns> public static System.Drawing.Image[] GetPixelAlpha(SPR2Frame sprite, int tWidth, int tHeight) { return GetPixelAlpha(sprite, tWidth, tHeight, sprite.Position); }