public static unsafe Bitmap ExtractThumb(IniFile map) { var prevSection = map.GetSection("Preview"); var size = prevSection.ReadString("Size").Split(','); var previewSize = new Rectangle(int.Parse(size[0]), int.Parse(size[1]), int.Parse(size[2]), int.Parse(size[3])); var preview = new Bitmap(previewSize.Width, previewSize.Height, PixelFormat.Format24bppRgb); byte[] image = new byte[preview.Width * preview.Height * 3]; var prevDataSection = map.GetSection("PreviewPack"); var image_compressed = Convert.FromBase64String(prevDataSection.ConcatenatedValues()); Format5.DecodeInto(image_compressed, image, 5); // invert rgb->bgr BitmapData bmd = preview.LockBits(new Rectangle(0, 0, preview.Width, preview.Height), ImageLockMode.WriteOnly, PixelFormat.Format24bppRgb); int idx = 0; for (int y = 0; y < bmd.Height; y++) { byte *row = (byte *)bmd.Scan0 + bmd.Stride * y; byte *p = row; for (int x = 0; x < bmd.Width; x++) { byte b = image[idx++]; byte g = image[idx++]; byte r = image[idx++]; * p++ = r; * p++ = g; * p++ = b; } } preview.UnlockBits(bmd); return(preview); }
public void SerializeIsoMapPack5(IniFile.IniSection isoMapPack5) { int cells = (Width * 2 - 1) * Height; int lzoPackSize = cells * 11 + 4; // last 4 bytes contains a lzo pack header saying no more data is left var isoMapPack = new byte[lzoPackSize]; var isoMapPack2 = new byte[lzoPackSize]; long di = 0; foreach (var tile in this.isoTiles) { var bs = tile.ToMapPack5Entry().ToArray(); Array.Copy(bs, 0, isoMapPack, di, 11); di += 11; } var compressed = Format5.Encode(isoMapPack, 5); string compressed64 = Convert.ToBase64String(compressed); int i = 1; int idx = 0; isoMapPack5.Clear(); while (idx < compressed64.Length) { int adv = Math.Min(74, compressed64.Length - idx); isoMapPack5.SetValue(i++.ToString(), compressed64.Substring(idx, adv)); idx += adv; } }
/// <summary>Reads the tiles. </summary> private void ReadTiles() { var mapSection = GetSection("IsoMapPack5"); byte[] lzoData = Convert.FromBase64String(mapSection.ConcatenatedValues()); int cells = (FullSize.Width * 2 - 1) * FullSize.Height; int lzoPackSize = cells * 11 + 4; // last 4 bytes contains a lzo pack header saying no more data is left var isoMapPack = new byte[lzoPackSize]; uint totalDecompressSize = Format5.DecodeInto(lzoData, isoMapPack); var mf = new MemoryFile(isoMapPack); int numtiles = 0; for (int i = 0; i < cells; i++) { ushort rx = mf.ReadUInt16(); ushort ry = mf.ReadUInt16(); short tilenum = mf.ReadInt16(); short zero1 = mf.ReadInt16(); ushort subtile = mf.ReadByte(); short z = mf.ReadByte(); byte zero2 = mf.ReadByte(); int dx = rx - ry + FullSize.Width - 1; int dy = rx + ry - FullSize.Width - 1; numtiles++; if (dx >= 0 && dx < 2 * Tiles.Width && dy >= 0 && dy < 2 * Tiles.Height) { var tile = new IsoTile((ushort)dx, (ushort)dy, rx, ry, z, tilenum, subtile); Tiles[(ushort)dx, (ushort)dy / 2] = tile; } } // fix missing tiles // import tiles for (ushort y = 0; y < FullSize.Height; y++) { for (ushort x = 0; x <= FullSize.Width * 2 - 2; x++) { var isoTile = Tiles[x, y]; if (isoTile == null) { // fix null tiles to blank ushort dx = (ushort)(x); ushort dy = (ushort)(y * 2 + x % 2); ushort rx = (ushort)((dx + dy) / 2 + 1); ushort ry = (ushort)(dy - rx + FullSize.Width + 1); Tiles[x, y] = new IsoTile(dx, dy, rx, ry, 0, 0, 0); } } } Logger.Debug("Read {0} tiles", numtiles); }
/// <summary>Reads the overlay.</summary> private void ReadOverlay() { IniSection overlaySection = GetSection("OverlayPack"); if (overlaySection == null) { Logger.Info("OverlayPack section unavailable in {0}, overlay will be unavailable", Path.GetFileName(FileName)); return; } byte[] format80Data = Convert.FromBase64String(overlaySection.ConcatenatedValues()); var overlayPack = new byte[1 << 18]; Format5.DecodeInto(format80Data, overlayPack, 80); IniSection overlayDataSection = GetSection("OverlayDataPack"); if (overlayDataSection == null) { Logger.Debug("OverlayDataPack section unavailable in {0}, overlay will be unavailable", Path.GetFileName(FileName)); return; } format80Data = Convert.FromBase64String(overlayDataSection.ConcatenatedValues()); var overlayDataPack = new byte[1 << 18]; Format5.DecodeInto(format80Data, overlayDataPack, 80); for (int y = 0; y < FullSize.Height; y++) { for (int x = FullSize.Width * 2 - 2; x >= 0; x--) { var t = Tiles[x, y]; if (t == null) { continue; } int idx = t.Rx + 512 * t.Ry; byte overlay_id = overlayPack[idx]; if (overlay_id != 0xFF) { byte overlay_value = overlayDataPack[idx]; var ovl = new Overlay(overlay_id, overlay_value); ovl.Tile = t; Overlays.Add(ovl); } } } Logger.Debug("Read {0} overlay types", Overlays.Count); }
private byte[] GetEncoded(List <Tile> tileSet) { byte[] isoMapPack = new byte[tileSet.Count * 11 + 4]; long byteIndex = 0; foreach (Tile tile in tileSet) { byte[] tileInBytes = tile.GetTileForMapPack(); Array.Copy(tileInBytes, 0, isoMapPack, byteIndex, 11); byteIndex += 11; } return(Format5.Encode(isoMapPack, 5)); }
private byte[] GetEncoded(List <IsoTile> tileSetParam) { // A tile is of 11 bytes. Last 4 bytes of padding is used for termination byte[] isoMapPack = new byte[tileSetParam.Count * 11 + 4]; long di = 0; foreach (var tile in tileSetParam) { var bs = tile.ToMapPack5Entry().ToArray(); Array.Copy(bs, 0, isoMapPack, di, 11); di += 11; } return(Format5.Encode(isoMapPack, 5)); }
public static unsafe void InjectThumb(Bitmap preview, IniFile map) { BitmapData bmd = preview.LockBits(new Rectangle(0, 0, preview.Width, preview.Height), ImageLockMode.ReadOnly, PixelFormat.Format24bppRgb); byte[] image = new byte[preview.Width * preview.Height * 3]; int idx = 0; // invert rgb->bgr for (int y = 0; y < bmd.Height; y++) { byte *p = (byte *)bmd.Scan0 + bmd.Stride * y; for (int x = 0; x < bmd.Width; x++) { byte r = *p++; byte g = *p++; byte b = *p++; image[idx++] = b; image[idx++] = g; image[idx++] = r; } } // encode byte[] image_compressed = Format5.Encode(image, 5); // base64 encode string image_base64 = Convert.ToBase64String(image_compressed, Base64FormattingOptions.None); // now overwrite [Preview] and [PreviewPack], inserting them directly after [Basic] if not yet existing map.GetOrCreateSection("Preview").SetValue("Size", string.Format("0,0,{0},{1}", preview.Width, preview.Height)); var section = map.GetOrCreateSection("PreviewPack", "Preview"); section.Clear(); section.Index = 0; int rowNum = 1; for (int i = 0; i < image_base64.Length; i += 70) { section.SetValue(rowNum++.ToString(CultureInfo.InvariantCulture), image_base64.Substring(i, Math.Min(70, image_base64.Length - i))); } }
private void UpdateOverlaySections() { MapSection overlaySection = GetSection("OverlayPack"); MapSection overlayDataSection = GetSection("OverlayDataPack"); if (overlaySection != null && overlayDataSection != null) { byte[] overlayPack = new byte[1 << 18]; byte[] overlayDataPack = new byte[1 << 18]; for (int i = 0; i < 262144; i++) { overlayPack[i] = 0xFF; overlayDataPack[i] = 0; } if (overlays != null && overlays.Count > 0) { foreach (Overlay entry in overlays) { int location = (entry.MapY * 512) + entry.MapX; overlayPack[location] = (byte)entry.OverlayIndex; overlayDataPack[location] = (byte)entry.OverlayFrame; } } string oPackEncoded = Convert.ToBase64String(Format5.Encode(overlayPack, 80), Base64FormattingOptions.None); string oDataPackEncoded = Convert.ToBase64String(Format5.Encode(overlayDataPack, 80), Base64FormattingOptions.None); overlaySection.Entries.Clear(); overlayDataSection.Entries.Clear(); for (int i = 0, j = 1; i < oPackEncoded.Length; i += 70) { overlaySection.Entries.Add(j++.ToString(CultureInfo.InvariantCulture), oPackEncoded.Substring(i, Math.Min(70, oPackEncoded.Length - i))); } for (int i = 0, j = 1; i < oDataPackEncoded.Length; i += 70) { overlayDataSection.Entries.Add(j++.ToString(CultureInfo.InvariantCulture), oDataPackEncoded.Substring(i, Math.Min(70, oDataPackEncoded.Length - i))); } } }
private void InitializeOverlays() { MapSection overlaySection = GetSection("OverlayPack"); MapSection overlayDataSection = GetSection("OverlayDataPack"); if (overlaySection != null && overlayDataSection != null) { overlays = new List <Overlay>(); StringBuilder sb = new StringBuilder(); foreach (KeyValuePair <string, string> entry in overlaySection.Entries) { sb.Append(entry.Value); } byte[] format80Data = Convert.FromBase64String(sb.ToString()); byte[] overlayPack = new byte[1 << 18]; Format5.DecodeInto(format80Data, overlayPack, 80); sb.Clear(); foreach (KeyValuePair <string, string> entry in overlayDataSection.Entries) { sb.Append(entry.Value); } format80Data = Convert.FromBase64String(sb.ToString()); byte[] overlayDataPack = new byte[1 << 18]; Format5.DecodeInto(format80Data, overlayDataPack, 80); foreach (Tuple <int, int> cellCoordinate in coordList) { int location = cellCoordinate.Item1 + 512 * cellCoordinate.Item2; byte overlayIndex = overlayPack[location]; if (overlayIndex != 0xFF) { overlays.Add(new Overlay(overlayIndex, (int)overlayDataPack[location], cellCoordinate.Item1, cellCoordinate.Item2)); } } } }
private void InitializeTiles() { MapSection section = GetSection("IsoMapPack5"); if (section != null) { tiles = new List <Tile>(); StringBuilder sb = new StringBuilder(); foreach (KeyValuePair <string, string> entry in section.Entries) { sb.Append(entry.Value); } byte[] lzoData = Convert.FromBase64String(sb.ToString()); int cells = (MapWidth * 2 - 1) * MapHeight; int lzoPackSize = cells * 11 + 4; // last 4 bytes used for termination byte[] isoMapPack = new byte[lzoPackSize]; int j = 0; for (int i = 0; i < cells; i++) { isoMapPack[j] = 0x88; isoMapPack[j + 1] = 0x40; isoMapPack[j + 2] = 0x88; isoMapPack[j + 3] = 0x40; j += 11; } Format5.DecodeInto(lzoData, isoMapPack); foreach (Tuple <int, int> cellCoordinate in coordList) { tiles.Add(new Tile(0, 0, 0, 0, cellCoordinate.Item1, cellCoordinate.Item2)); } MemoryFile mf = new MemoryFile(isoMapPack); for (int i = 0; i < cells; i++) { int rx = (int)mf.ReadUInt16(); int ry = (int)mf.ReadUInt16(); int tileIndex = mf.ReadInt32(); byte subIndex = mf.ReadByte(); byte heightLevel = mf.ReadByte(); byte iceGrowth = mf.ReadByte(); if (tileIndex >= 65535) { tileIndex = 0; // Tile 0xFFFF used as empty/clear } if (rx < 512 && ry < 512) { int index = tiles.FindIndex(tile => tile.MapX == rx && tile.MapY == ry); if (index >= 0) { tiles[index].TileIndex = tileIndex; tiles[index].SubIndex = subIndex; tiles[index].Level = heightLevel; tiles[index].IceGrowth = iceGrowth; } } } } }
/// <summary>Reads the tiles. </summary> private void ReadTiles() { var mapSection = GetSection("IsoMapPack5"); byte[] lzoData = Convert.FromBase64String(mapSection.ConcatenatedValues()); int cells = (FullSize.Width * 2 - 1) * FullSize.Height; int lzoPackSize = cells * 11 + 4; // last 4 bytes contains a lzo pack header saying no more data is left var isoMapPack = new byte[lzoPackSize]; // In case, IsoMapPack5 contains less entries than the number of cells, fill up any number greater // than 511 and filter later. int j = 0; for (int i = 0; i < cells; i++) { isoMapPack[j] = 0x88; isoMapPack[j + 1] = 0x40; isoMapPack[j + 2] = 0x88; isoMapPack[j + 3] = 0x40; j += 11; } Format5.DecodeInto(lzoData, isoMapPack); // Fill level 0 clear tiles for all array values for (ushort y = 0; y < FullSize.Height; y++) { for (ushort x = 0; x <= FullSize.Width * 2 - 2; x++) { ushort dx = (ushort)(x); ushort dy = (ushort)(y * 2 + x % 2); ushort rx = (ushort)((dx + dy) / 2 + 1); ushort ry = (ushort)(dy - rx + FullSize.Width + 1); Tiles[x, y] = new IsoTile(dx, dy, rx, ry, 0, 0, 0, 0); } } // Overwrite with actual entries found in IsoMapPack5 var mf = new MemoryFile(isoMapPack); int numtiles = 0; for (int i = 0; i < cells; i++) { ushort rx = mf.ReadUInt16(); ushort ry = mf.ReadUInt16(); int tilenum = mf.ReadInt32(); byte subtile = mf.ReadByte(); byte z = mf.ReadByte(); byte icegrowth = mf.ReadByte(); if (tilenum >= 65535) { tilenum = 0; // Tile 0xFFFF used as empty/clear } if (rx <= 511 && ry <= 511) { int dx = rx - ry + FullSize.Width - 1; int dy = rx + ry - FullSize.Width - 1; numtiles++; if (dx >= 0 && dx < 2 * Tiles.Width && dy >= 0 && dy < 2 * Tiles.Height) { var tile = new IsoTile((ushort)dx, (ushort)dy, rx, ry, z, tilenum, subtile, icegrowth); Tiles[(ushort)dx, (ushort)dy / 2] = tile; } } } Logger.Debug("Read {0} tiles", numtiles); }