public void Render(string name, Bitmap bitmap, int planeCount, Destination destination) { if (bitmap.PixelFormat != PixelFormat.Format8bppIndexed) { throw new InvalidOperationException("Only 8bpp format is supported."); } _transformer.SetBitmap(bitmap); _writer.StartObject(destination == Destination.Disk ? ObjectType.Chip: ObjectType.Bitmap, name); var byteWidth = _transformer.GetByteWidth(); var height = _transformer.GetHeight(); _writer.WriteCode(Code.Normal, $"{name}_BPL\t\tequ\t{planeCount}"); _writer.WriteCode(Code.Normal, $"{name}_BWIDTH\t\tequ\t{byteWidth}"); _writer.WriteCode(Code.Normal, $"{name}_HEIGHT\t\tequ\t{height}"); var interleaved = _transformer.GetInterleaved(planeCount); RunLengthEncoder.ProjectCompression(interleaved); _writer.WriteBlob(interleaved); _writer.EndObject(); }
private void ConvertSprite(string name) { var palette = _definition.Palette.FromInputFolder().LoadIndexedBitmap(); var bitmap = _definition.File.FromInputFolder().LoadBitmap(); var spriteX = _definition.StartX; var spriteY = _definition.StartY; var numTiles = _definition.Count; var width = 16; var height = _definition.Height; var maxX = bitmap.Width / width; var maxY = bitmap.Height / height; int i = 0; while (i < numTiles) { var bobBitmap = bitmap.Clone(new Rectangle(spriteX * width, spriteY * height, width, height), bitmap.PixelFormat); bobBitmap = MapColors(palette, bobBitmap); _transformer.SetBitmap(bobBitmap); var sprite = TrimSprite(_transformer.GetInterleaved(_attached ? PlaneCount * 2 : PlaneCount)); if (sprite.Any(v => v != 0)) { if (_attached) { // Given the content (in words) w0,w1,w2,w3,w4,w5,w6,w7 // sprite0 will take w0,w1,w4,w5 // sprite1 will take w2,w3,w6,w7 var sprite0 = new List <byte>(); var sprite1 = new List <byte>(); var t = 0; while (t < sprite.Length) { for (var n = 0; n < 4; n++) { sprite0.Add(sprite[t++]); } for (var n = 0; n < 4; n++) { sprite1.Add(sprite[t++]); } } AddSprite(_converted0, sprite0.ToArray()); AddSprite(_converted1, sprite1.ToArray()); } else { AddSprite(_converted0, sprite); } i++; } spriteX++; if (spriteX >= maxX) { spriteY++; if (spriteY >= maxY) { throw new ConversionException( $"Converting {_definition.File} reached the end of the image trying to get {numTiles} tiles."); } spriteX = 0; } } WriteSpriteData(name, _converted0); if (_attached) { WriteSpriteData(name + "A", _converted1); } }
/// <summary> /// Renders tiles so each tile's bitplanes are next to each other. /// </summary> /// <param name="name"></param> /// <param name="bitmap"></param> /// <param name="tileWidth"></param> /// <param name="tileHeight"></param> public void Render(string name, Bitmap bitmap, int tileWidth, int tileHeight, int planeCount) { if (tileWidth % 8 != 0) { throw new ConversionException($"Tile rendering {name}. Tile width must be a multiple of 8."); } if (bitmap.Width % tileWidth != 0) { throw new ConversionException($"Bitmap must be a width that is a multiple of the tile width."); } if (bitmap.Height % tileHeight != 0) { throw new ConversionException($"Bitmap must be a height that is a multiple of the tile height."); } _transformer.SetBitmap(bitmap); var byteWidth = _transformer.GetByteWidth(); var height = _transformer.GetHeight(); var tileByteWidth = tileWidth / 8; var tileSize = tileByteWidth * tileHeight * planeCount; var data = _transformer.GetBitplanes(planeCount); var destination = new byte[data.Length + tileSize]; // For one blank tile at the beginning var bplSize = byteWidth * height; var tileCounter = 0; for (int tileY = 0; tileY < bitmap.Height / tileHeight; tileY++) { for (int tileX = 0; tileX < bitmap.Width / tileWidth; tileX++) { for (int tileRow = 0; tileRow < tileHeight; tileRow++) { for (int bpl = 0; bpl < planeCount; bpl++) { var src = tileX * tileByteWidth + tileY * tileHeight * byteWidth + bpl * bplSize + tileRow * byteWidth; var dst = tileByteWidth * tileHeight * planeCount * tileCounter + bpl * tileByteWidth + tileRow * tileByteWidth * planeCount + tileSize // One blank tile at the beginning ; for (int b = 0; b < tileByteWidth; b++) { var s = data[src++]; destination[dst++] = s; } } } tileCounter++; } } _writer.WriteCode(Code.Data, "; Tiles are in interlaced format one after another."); _writer.WriteCode(Code.Data, "; The first tile is all zeros and is to be used when Tiled does not have a tile assigned."); _writer.WriteCode(Code.Data, $"; Tiles are {tileByteWidth} byte wide, {tileHeight} pixel tall and have {planeCount} biplanes"); _writer.WriteCode(Code.Normal, $"; Tile definitions for {name}"); _writer.WriteCode(Code.Normal, $"TILE_BWIDTH_{name.ToUpperInvariant()}\t\t\tequ\t{tileByteWidth}"); _writer.WriteCode(Code.Normal, $"TILE_HEIGHT_{name.ToUpperInvariant()}\t\t\tequ\t{tileHeight}"); _writer.WriteCode(Code.Normal, $"TILE_PLANE_COUNT_{name.ToUpperInvariant()}\tequ\t{planeCount}"); _writer.StartObject(ObjectType.Tile, name); _writer.WriteBlob(destination); _writer.EndObject(); }
private void SaveBobsWithMasks(Bitmap bitmap, int initialOffset) { var width = _definition.Width; var height = _definition.Height.GetValueOrDefault(bitmap.Height); var numTiles = _definition.Count.GetValueOrDefault(bitmap.Width / _definition.Width); var bobX = _definition.StartX; var bobY = _definition.StartY; var info = new BobData[numTiles]; _writer.WriteWord((ushort)(_bobWordWidth)); initialOffset += 2; _writer.WriteWord((ushort)numTiles); initialOffset += 2; for (var i = 0; i < numTiles;) { var currentBob = new BobData(); info[i] = currentBob; if (bobX + width > bitmap.Width) { throw new ConversionException("Bob out of bitmap bounds"); } if (bobY + height > bitmap.Height) { throw new ConversionException("Bob out of bitmap bounds"); } var bobBitmap = bitmap.Clone(new Rectangle(bobX, bobY, width, height), bitmap.PixelFormat); _transformer.SetBitmap(bobBitmap); byte transparent = 0; if (_colorFlip) { transparent = (byte)((1 << _planeCount) - 1); _transformer.FlipColors(0, transparent); } var planes = _transformer.GetInterleaved(_planeCount); // This will bump up to word size... if (planes.Any(_ => _ != 0)) { for (var y = 0; y < height; y++) { var rowData = new byte[_bobWordWidth * 2 * _planeCount]; var rowMask = new byte[_bobWordWidth * 2 * _planeCount]; if (_colorFlip) { ArrayFill(rowData, transparent); } for (var x = 0; x < width / 8; x++) { byte mask = _colorFlip ? (byte)0xff : (byte)0x00; for (var bpl = 0; bpl < _planeCount; bpl++) { var value = planes[y * _planeCount * _bobWordWidth * 2 + bpl * _bobWordWidth * 2 + x]; rowData[bpl * _bobWordWidth * 2 + x] = value; if (_colorFlip) { mask &= value; } else { mask |= value; } } for (var bpl = 0; bpl < _planeCount; bpl++) { rowMask[bpl * _bobWordWidth * 2 + x] = _colorFlip ? (byte)~mask : (byte)mask; } } currentBob.PlaneRows.Add(rowData); currentBob.MaskRows.Add(rowMask); } i++; } if (i < numTiles) { bobX += width; if (bobX >= bitmap.Width) { bobY += height; if (bobY >= bitmap.Height) { throw new ConversionException( $"Converting {_definition.ImageFile} reached the end of the image trying to get {numTiles} tiles."); } bobX = _definition.StartX; } } } // All Bob info added to the initial offset initialOffset += numTiles * 16; // 8 bytes per tile of information in the header AdjustBobs(info, initialOffset); WriteBobs(info); }