diff --git a/src/pixie/images.nim b/src/pixie/images.nim index 973dd66..b952492 100644 --- a/src/pixie/images.nim +++ b/src/pixie/images.nim @@ -16,6 +16,9 @@ when defined(release): proc newImage*(width, height: int): Image = ## Creates a new image with the parameter dimensions. + if width < 0 or height < 0: + raise newException(PixieError, "Image width and height must be positive") + result = Image() result.width = width result.height = height @@ -143,11 +146,28 @@ proc subImage*(image: Image, x, y, w, h: int): Image = ) proc superImage*(image: Image, x, y, w, h: int): Image = - ## Cuts either a sub image or super image with padded transparency. - result = newImage(w, h) - for y2 in 0 ..< h: - for x2 in 0 ..< w: - result.setRgbaUnsafe(x2, y2, image[x2 + x, y2 + y]) + ## Either cuts a sub image or returns a super image with padded transparency. + if x >= 0 and x + w <= image.width and y >= 0 and y + h <= image.height: + result = image.subImage(x, y, w, h) + elif abs(x) >= image.width or abs(y) >= image.height: + # Nothing to copy, just an empty new image + result = newImage(w, h) + else: + let + readOffsetX = max(x, 0) + readOffsetY = max(y, 0) + writeOffsetX = max(0 - x, 0) + writeOffsetY = max(0 - y, 0) + copyWidth = max(min(image.width, w) - abs(x), 0) + copyHeight = max(min(image.height, h) - abs(y), 0) + + result = newImage(w, h) + for y2 in 0 ..< copyHeight: + copyMem( + result.data[result.dataIndex(writeOffsetX, writeOffsetY + y2)].addr, + image.data[image.dataIndex(readOffsetX, readOffsetY + y2)].addr, + copyWidth * 4 + ) proc minifyBy2*(image: Image, power = 1): Image = ## Scales the image down by an integer scale. diff --git a/tests/images/superimage1.png b/tests/images/superimage1.png new file mode 100644 index 0000000..56eff27 Binary files /dev/null and b/tests/images/superimage1.png differ diff --git a/tests/images/superimage2.png b/tests/images/superimage2.png new file mode 100644 index 0000000..2e903a2 Binary files /dev/null and b/tests/images/superimage2.png differ diff --git a/tests/images/superimage3.png b/tests/images/superimage3.png new file mode 100644 index 0000000..1e7232f Binary files /dev/null and b/tests/images/superimage3.png differ diff --git a/tests/images/superimage4.png b/tests/images/superimage4.png new file mode 100644 index 0000000..1b58d46 Binary files /dev/null and b/tests/images/superimage4.png differ diff --git a/tests/images/superimage5.png b/tests/images/superimage5.png new file mode 100644 index 0000000..4ed0c8e Binary files /dev/null and b/tests/images/superimage5.png differ diff --git a/tests/images/superimage6.png b/tests/images/superimage6.png new file mode 100644 index 0000000..3343ca4 Binary files /dev/null and b/tests/images/superimage6.png differ diff --git a/tests/test_images.nim b/tests/test_images.nim index 79822bf..326de43 100644 --- a/tests/test_images.nim +++ b/tests/test_images.nim @@ -43,3 +43,39 @@ block: a.writeFile("tests/images/flipped2.png") a.flipHorizontal() a.writeFile("tests/images/flipped3.png") + +block: + let + a = readImage("tests/images/flipped1.png") + b = a.superImage(-10, 0, 20, 20) + b.writeFile("tests/images/superimage1.png") + +block: + let + a = readImage("tests/images/flipped1.png") + b = a.superImage(-10, -10, 20, 20) + b.writeFile("tests/images/superimage2.png") + +block: + let + a = readImage("tests/images/flipped1.png") + b = a.superImage(90, 0, 120, 120) + b.writeFile("tests/images/superimage3.png") + +block: + let + a = readImage("tests/images/flipped1.png") + b = a.superImage(90, 90, 120, 120) + b.writeFile("tests/images/superimage4.png") + +block: + let + a = readImage("tests/images/flipped1.png") + b = a.superImage(-10, -10, 120, 120) + b.writeFile("tests/images/superimage5.png") + +block: + let + a = readImage("tests/images/flipped1.png") + b = a.superImage(45, 45, 20, 20) + b.writeFile("tests/images/superimage6.png")