From fc346c3ec29b36da3eaa54f87267db7221b739e7 Mon Sep 17 00:00:00 2001 From: Elias Batek Date: Mon, 7 Oct 2024 01:48:04 +0200 Subject: [PATCH] Fix cropInPlace() --- pixmappaint.d | 50 +++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 43 insertions(+), 7 deletions(-) diff --git a/pixmappaint.d b/pixmappaint.d index 20314f3..fbdcd9a 100644 --- a/pixmappaint.d +++ b/pixmappaint.d @@ -375,13 +375,16 @@ struct SubPixmap { Copies the pixel data – cropped to the subimage region – into the target Pixmap. - Returns: - A size-adjusted shallow copy of the input Pixmap overwritten - with the image data of the SubPixmap. + $(PITFALL + Do not attempt to extract a subimage back into the source pixmap. + This will fail in cases where source and target regions overlap + and potentially crash the program. + ) $(PITFALL While the returned Pixmap utilizes the buffer provided by the input, the returned Pixmap might not exactly match the input. + The dimensions (width and height) and the length might have changed. Always use the returned Pixmap structure. @@ -393,6 +396,10 @@ struct SubPixmap { pixmap = subPixmap.extractToPixmap(pixmap); --- ) + + Returns: + A size-adjusted shallow copy of the input Pixmap overwritten + with the image data of the SubPixmap. +/ Pixmap extractToPixmap(Pixmap target) @nogc const { // Length adjustment @@ -418,6 +425,19 @@ struct SubPixmap { src.popFront(); } } + + private void extractToPixmapCopyPixelByPixelImpl(Pixmap target) @nogc const { + auto src = SubPixmapScanner(this); + auto dst = PixmapScannerRW(target); + + foreach (dstLine; dst) { + const srcLine = src.front; + foreach (idx, ref px; dstLine) { + px = srcLine[idx]; + } + src.popFront(); + } + } } @safe pure nothrow @nogc: @@ -1640,12 +1660,18 @@ Pixmap cropNew(const Pixmap source, Size targetSize, Point offset = Point(0, 0)) /++ Crops an image and stores the result in the source buffer. - The source pixmap structure is passed by ref and gets with a size-adjusted - structure using a slice of the same underlying memory. + The source pixmap structure is passed by value. + A size-adjusted structure using a slice of the same underlying memory is + returned. +/ -void cropInplace(ref Pixmap source, Size targetSize, Point offset = Point(0, 0)) @nogc { +Pixmap cropInPlace(Pixmap source, Size targetSize, Point offset = Point(0, 0)) @nogc { + Pixmap target = source; + target.width = targetSize.width; + target.data = target.data[0 .. targetSize.area]; + auto src = const(SubPixmap)(source, targetSize, offset); - source = src.extractToPixmap(source); + src.extractToPixmapCopyPixelByPixelImpl(target); + return target; } /++ @@ -1674,6 +1700,16 @@ void rotateClockwise(const Pixmap source, Pixmap target) @nogc { } } +/++ + Rotates an image by 90° clockwise. + Stores the result in a newly allocated Pixmap. + +/ +Pixmap rotateClockwiseNew(const Pixmap source) { + auto target = Pixmap(Size(source.height, source.width)); + source.rotateClockwise(target); + return target; +} + @safe pure nothrow @nogc: // ==== Blending functions ====