Skip to content

Commit ce068c1

Browse files
authored
Optimize the drawing of the bookmark map (#3034)
2 parents 0108535 + 25b9c88 commit ce068c1

1 file changed

Lines changed: 30 additions & 50 deletions

File tree

ImperatorToCK3/Outputter/BookmarkOutputter.cs

Lines changed: 30 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -202,7 +202,6 @@ private static async Task DrawBookmarkMap(Configuration config, List<Title> play
202202
if (flatmapPath is null) {
203203
throw new FileNotFoundException("flatmap.dds not found!");
204204
}
205-
const string tmpFlatmapPath = "temp/flatmap.png";
206205

207206
SixLabors.ImageSharp.Configuration.Default.ImageFormatsManager.SetEncoder(PngFormat.Instance, new PngEncoder {
208207
TransparentColorMode = PngTransparentColorMode.Clear,
@@ -218,21 +217,21 @@ private static async Task DrawBookmarkMap(Configuration config, List<Title> play
218217
using (var flatmapMagickImage = new MagickImage(flatmapPath)) {
219218
flatmapMagickImage.Scale(2160, 1080);
220219
flatmapMagickImage.Crop(1920, 1080);
221-
await flatmapMagickImage.WriteAsync(tmpFlatmapPath);
222-
}
220+
byte[] flatmapPngBytes = flatmapMagickImage.ToByteArray(MagickFormat.Png);
221+
await using var flatmapStream = new MemoryStream(flatmapPngBytes);
222+
using var bookmarkMapImage = await Image.LoadAsync(flatmapStream);
223223

224-
using var bookmarkMapImage = await Image.LoadAsync(tmpFlatmapPath);
224+
var mapData = ck3World.MapData;
225+
var provDefs = mapData.ProvinceDefinitions;
225226

226-
var mapData = ck3World.MapData;
227-
var provDefs = mapData.ProvinceDefinitions;
227+
foreach (var playerTitle in playerTitles) {
228+
await DrawPlayerTitleOnMap(config, ck3World, playerTitle, mapData, provincesImage, provDefs, bookmarkMapImage);
229+
}
228230

229-
foreach (var playerTitle in playerTitles) {
230-
await DrawPlayerTitleOnMap(config, ck3World, playerTitle, mapData, provincesImage, provDefs, bookmarkMapImage);
231+
var outputPath = Path.Combine("output", config.OutputModName, "gfx/interface/bookmarks/bm_converted.png");
232+
await bookmarkMapImage.SaveAsPngAsync(outputPath);
233+
await ResaveImageAsDDS(outputPath);
231234
}
232-
233-
var outputPath = Path.Combine("output", config.OutputModName, "gfx/interface/bookmarks/bm_converted.png");
234-
await bookmarkMapImage.SaveAsPngAsync(outputPath);
235-
await ResaveImageAsDDS(outputPath);
236235
}
237236

238237
private static async Task DrawPlayerTitleOnMap(
@@ -244,8 +243,6 @@ private static async Task DrawPlayerTitleOnMap(
244243
ProvinceDefinitions provDefs,
245244
Image bookmarkMapImage
246245
) {
247-
Rgba32 black = Color.Black;
248-
249246
var colorOnMap = playerTitle.Color1 ?? new commonItems.Colors.Color(0, 0, 0);
250247
var rgba32ColorOnMap = new Rgba32((byte)colorOnMap.R, (byte)colorOnMap.G, (byte)colorOnMap.B);
251248
HashSet<ulong> heldProvinces = playerTitle.GetProvincesInCountry(config.CK3BookmarkDate);
@@ -256,19 +253,16 @@ Image bookmarkMapImage
256253
Logger.Debug($"Coloring {diff} impassable provinces with color of {playerTitle}...");
257254

258255
using var realmHighlightImage = provincesImage.CloneAs<Rgba32>();
259-
IEnumerable<Rgb24> provinceColors = provincesToColor.Select(provId => provDefs.ProvinceToColorDict[provId]);
260-
foreach (var provinceColor in provinceColors) {
261-
// Make pixels of the province black.
256+
var provinceColorSet = new HashSet<Rgba32>(provincesToColor.Count);
257+
foreach (var provinceId in provincesToColor) {
258+
if (!provDefs.ProvinceToColorDict.TryGetValue(provinceId, out Rgb24 provinceColor)) {
259+
continue;
260+
}
262261
var rgbaProvinceColor = new Rgba32();
263262
provinceColor.ToRgba32(ref rgbaProvinceColor);
264-
ReplaceColorOnImage(realmHighlightImage, rgbaProvinceColor, black);
263+
provinceColorSet.Add(rgbaProvinceColor);
265264
}
266-
267-
// Make all non-black pixels transparent.
268-
InverseTransparent(realmHighlightImage, black);
269-
270-
// Replace black with title color.
271-
ReplaceColorOnImage(realmHighlightImage, black, rgba32ColorOnMap);
265+
ApplyRealmColorMaskInSinglePass(realmHighlightImage, provinceColorSet, rgba32ColorOnMap);
272266

273267
// Create realm highlight file.
274268
var holder = ck3World.Characters[playerTitle.GetHolderId(config.CK3BookmarkDate)];
@@ -285,6 +279,18 @@ Image bookmarkMapImage
285279
bookmarkMapImage.Mutate(x => x.DrawImage(realmHighlightImage, 0.5f));
286280
}
287281

282+
private static void ApplyRealmColorMaskInSinglePass(Image<Rgba32> image, HashSet<Rgba32> provinceColorSet, Rgba32 realmColor) {
283+
Rgba32 transparent = Color.Transparent;
284+
image.ProcessPixelRows(accessor => {
285+
for (int y = 0; y < image.Height; ++y) {
286+
var row = accessor.GetRowSpan(y);
287+
for (int x = 0; x < row.Length; ++x) {
288+
row[x] = provinceColorSet.Contains(row[x]) ? realmColor : transparent;
289+
}
290+
}
291+
});
292+
}
293+
288294
private static FrozenSet<ulong> GetColorableImpassablesExceptMapEdgeProvinces(MapData mapData) {
289295
return mapData.ColorableImpassableProvinceIds.Except(mapData.MapEdgeProvinceIds).ToFrozenSet();
290296
}
@@ -315,32 +321,6 @@ private static HashSet<ulong> GetImpassableProvincesToColor(MapData mapData, Has
315321
return provinceIdsToColor;
316322
}
317323

318-
private static void ReplaceColorOnImage(Image<Rgba32> image, Rgba32 sourceColor, Rgba32 targetColor) {
319-
image.ProcessPixelRows(accessor => {
320-
for (int y = 0; y < image.Height; ++y) {
321-
foreach (ref Rgba32 pixel in accessor.GetRowSpan(y)) {
322-
if (pixel.Equals(sourceColor)) {
323-
pixel = targetColor;
324-
}
325-
}
326-
}
327-
});
328-
}
329-
330-
private static void InverseTransparent(Image<Rgba32> image, Rgba32 color) {
331-
Rgba32 transparent = Color.Transparent;
332-
image.ProcessPixelRows(accessor => {
333-
for (int y = 0; y < image.Height; ++y) {
334-
foreach (ref Rgba32 pixel in accessor.GetRowSpan(y)) {
335-
if (pixel.Equals(color)) {
336-
continue;
337-
}
338-
pixel = transparent;
339-
}
340-
}
341-
});
342-
}
343-
344324
private static async Task ResaveImageAsDDS(string imagePath) {
345325
using (var magickImage = new MagickImage(imagePath)) {
346326
await magickImage.WriteAsync(Path.ChangeExtension(imagePath, ".dds"));

0 commit comments

Comments
 (0)