#region References using System; using System.Drawing; using System.Drawing.Imaging; using System.IO; #endregion namespace Ultima { public sealed class MultiMap { private static byte[] m_StreamBuffer; /// /// Returns Bitmap /// /// public static unsafe Bitmap GetMultiMap() { string path = Files.GetFilePath("Multimap.rle"); if (path != null) { using (var fs = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read)) { using (var bin = new BinaryReader(fs)) { int width, height; byte pixel; int count; int x, i; x = 0; ushort c = 0; width = bin.ReadInt32(); height = bin.ReadInt32(); var multimap = new Bitmap(width, height, Settings.PixelFormat); BitmapData bd = multimap.LockBits( new Rectangle(0, 0, multimap.Width, multimap.Height), ImageLockMode.WriteOnly, Settings.PixelFormat); var line = (ushort*)bd.Scan0; int delta = bd.Stride >> 1; ushort* cur = line; var len = (int)(bin.BaseStream.Length - bin.BaseStream.Position); if (m_StreamBuffer == null || m_StreamBuffer.Length < len) { m_StreamBuffer = new byte[len]; } bin.Read(m_StreamBuffer, 0, len); int j = 0; while (j != len) { pixel = m_StreamBuffer[j++]; count = (pixel & 0x7f); if ((pixel & 0x80) != 0) { c = 0x8000; //Color.Black; } else { c = 0xffff; //Color.White; } for (i = 0; i < count; ++i) { cur[x++] = c; if (x >= width) { cur += delta; x = 0; } } } multimap.UnlockBits(bd); return multimap; } } } return null; } /// /// Saves Bitmap to rle Format /// /// /// public static unsafe void SaveMultiMap(Bitmap image, BinaryWriter bin) { bin.Write(2560); // width bin.Write(2048); // height byte data = 1; byte mask = 0x0; ushort curcolor = 0; BitmapData bd = image.LockBits( new Rectangle(0, 0, image.Width, image.Height), ImageLockMode.ReadOnly, Settings.PixelFormat); var line = (ushort*)bd.Scan0; int delta = bd.Stride >> 1; ushort* cur = line; curcolor = cur[0]; //init for (int y = 0; y < image.Height; ++y, line += delta) { cur = line; for (int x = 0; x < image.Width; ++x) { ushort c = cur[x]; if (c == curcolor) { ++data; if (data == 0x7f) { if (curcolor == 0xffff) { mask = 0x0; } else { mask = 0x80; } data |= mask; bin.Write(data); data = 1; } } else { if (curcolor == 0xffff) { mask = 0x0; } else { mask = 0x80; } data |= mask; bin.Write(data); curcolor = c; data = 1; } } } if (curcolor == 0xffff) { mask = 0x0; } else { mask = 0x80; } data |= mask; bin.Write(data); image.UnlockBits(bd); } /// /// reads facet0*.mul into Bitmap /// /// facet id /// Bitmap public static unsafe Bitmap GetFacetImage(int id) { Bitmap bmp; string path = Files.GetFilePath(String.Format("facet0{0}.mul", id)); if (path != null) { using (var reader = new BinaryReader(new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read))) { int width = reader.ReadInt16(); int height = reader.ReadInt16(); bmp = new Bitmap(width, height); BitmapData bd = bmp.LockBits( new Rectangle(0, 0, bmp.Width, bmp.Height), ImageLockMode.WriteOnly, Settings.PixelFormat); var line = (ushort*)bd.Scan0; int delta = bd.Stride >> 1; for (int y = 0; y < height; y++, line += delta) { int colorsCount = reader.ReadInt32() / 3; ushort* endline = line + delta; ushort* cur = line; ushort* end; for (int c = 0; c < colorsCount; c++) { byte count = reader.ReadByte(); short color = reader.ReadInt16(); end = cur + count; while (cur < end) { if (cur > endline) { break; } *cur++ = (ushort)(color ^ 0x8000); } } } bmp.UnlockBits(bd); } return bmp; } return null; } /// /// Stores Image into facet.mul format /// /// /// public static unsafe void SaveFacetImage(string path, Bitmap sourceBitmap) { int width = sourceBitmap.Width; int height = sourceBitmap.Height; using ( var writer = new BinaryWriter(new FileStream(path, FileMode.Create, FileAccess.ReadWrite, FileShare.ReadWrite))) { writer.Write((short)width); writer.Write((short)height); BitmapData bd = sourceBitmap.LockBits( new Rectangle(0, 0, width, height), ImageLockMode.ReadOnly, Settings.PixelFormat); var line = (ushort*)bd.Scan0; int delta = bd.Stride >> 1; for (int y = 0; y < height; y++, line += delta) { long pos = writer.BaseStream.Position; writer.Write(0); //bytes count for current line int colorsAtLine = 0; int colorsCount = 0; int x = 0; while (x < width) { ushort hue = line[x]; while (x < width && colorsCount < byte.MaxValue && hue == line[x]) { ++colorsCount; ++x; } writer.Write((byte)colorsCount); writer.Write((ushort)(hue ^ 0x8000)); colorsAtLine++; colorsCount = 0; } long currpos = writer.BaseStream.Position; writer.BaseStream.Seek(pos, SeekOrigin.Begin); writer.Write(colorsAtLine * 3); //byte count writer.BaseStream.Seek(currpos, SeekOrigin.Begin); } } } } }