diff --git a/MergerLogic/ImageProcessing/TileMerger.cs b/MergerLogic/ImageProcessing/TileMerger.cs index 4a9a5a24..e57c2308 100644 --- a/MergerLogic/ImageProcessing/TileMerger.cs +++ b/MergerLogic/ImageProcessing/TileMerger.cs @@ -57,15 +57,15 @@ 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))) - { - 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"); - } + // 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))!; + ImageFormatter.RemoveImageDateAttributes(mergedImage); + + mergedImage.ColorSpace = ColorSpace.sRGB; + mergedImage.ColorType = mergedImage.HasAlpha ? ColorType.TrueColorAlpha : ColorType.TrueColor; + image = mergedImage; + this._logger.LogDebug($"[{MethodBase.GetCurrentMethod()?.Name}] 'imageMagic' merging finished"); } break; } 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 } } }