diff --git a/MergerLogic/ImageProcessing/TileMerger.cs b/MergerLogic/ImageProcessing/TileMerger.cs index 4a9a5a24..ae7b4e4c 100644 --- a/MergerLogic/ImageProcessing/TileMerger.cs +++ b/MergerLogic/ImageProcessing/TileMerger.cs @@ -44,8 +44,16 @@ public TileMerger(ITileScaler tileScaler, ILogger logger) this._logger.LogDebug($"[{MethodBase.GetCurrentMethod()?.Name}] No images where found return null"); return null; case 1: - ImageFormatter.RemoveImageDateAttributes(images[0]); image = images[0]; + try + { + ImageFormatter.RemoveImageDateAttributes(image); + } + catch + { + image.Dispose(); + throw; + } this._logger.LogDebug($"[{MethodBase.GetCurrentMethod()?.Name}] 1 image found"); break; default: @@ -57,21 +65,31 @@ public TileMerger(ITileScaler tileScaler, ILogger logger) } this._logger.LogDebug($"[{MethodBase.GetCurrentMethod()?.Name}] {imageCollection.Count} where found for merge, start 'imageMagic' merging"); - using (var mergedImage = imageCollection.Flatten(MagickColor.FromRgba(0, 0, 0, 0))) + // Flatten returns an image independent of the collection, so it outlives the + // collection's disposal without an extra full-image copy. + IMagickImage mergedImage = imageCollection.Flatten(MagickColor.FromRgba(0, 0, 0, 0))!; + try { ImageFormatter.RemoveImageDateAttributes(mergedImage); - mergedImage.ColorSpace = ColorSpace.sRGB; mergedImage.ColorType = mergedImage.HasAlpha ? ColorType.TrueColorAlpha : ColorType.TrueColor; - image = new MagickImage(mergedImage); - this._logger.LogDebug($"[{MethodBase.GetCurrentMethod()?.Name}] 'imageMagic' merging finished"); } + catch + { + mergedImage.Dispose(); + throw; + } + image = mergedImage; + this._logger.LogDebug($"[{MethodBase.GetCurrentMethod()?.Name}] 'imageMagic' merging finished"); } break; } - Tile tile = new Tile(targetCoords, image); - image.Dispose(); + Tile tile; + using (image) + { + tile = new Tile(targetCoords, image); + } tile.ConvertToFormat(strategy.ApplyStrategy(tile.Format)); return tile; } diff --git a/MergerLogic/ImageProcessing/TileScaler.cs b/MergerLogic/ImageProcessing/TileScaler.cs index 592c18ce..745411c6 100644 --- a/MergerLogic/ImageProcessing/TileScaler.cs +++ b/MergerLogic/ImageProcessing/TileScaler.cs @@ -85,12 +85,16 @@ public TileScaler(IMetricsProvider metricsProvider, ILogger logger) int maxRowOffset = TILE_SIZE * scaledChannels; int pixelRowBytes = TILE_SIZE * channels; + // Read the whole source pixel buffer once instead of allocating a byte[] per source pixel. + var srcValues = srcPixels.GetValues()!; + int srcStride = baseImage.Width * channels; + //loop relevant source pixels for (int i = pixelX; i < maxSrcX; i++) { for (int j = pixelY; j < maxSrcY; j++) { - var srcPixel = srcPixels.GetValue(i, j); + int srcPixelIdx = (j * srcStride) + (i * channels); var targetXStart = (i - pixelX) * scale; var targetYStart = (j - pixelY) * scale; var targetPixelIdxStart = (targetXStart + (TILE_SIZE * targetYStart)) * channels; @@ -99,7 +103,7 @@ public TileScaler(IMetricsProvider metricsProvider, ILogger logger) for (int pixelRowOffset = 0; pixelRowOffset < maxRowOffset; pixelRowOffset += pixelRowBytes) { int pixelIdx = targetPixelIdxStart + pixelColOffset + pixelRowOffset; - srcPixel!.CopyTo(pixels, pixelIdx); //copy all channels + Array.Copy(srcValues, srcPixelIdx, pixels, pixelIdx, channels); //copy all channels } } }