From 7e56800de7ed6d35d2b619bfc324e61ca88679e9 Mon Sep 17 00:00:00 2001 From: Ryan Oldenburg <ryan@guzba.com> Date: Tue, 17 Aug 2021 16:14:31 -0500 Subject: [PATCH] image isTransparent isOneColor --- src/pixie/images.nim | 35 +++++++++++++++++++++++++++++++++++ tests/benchmark_images.nim | 8 ++++++++ tests/test_images.nim | 33 +++++++++++++++++++++++++++++++++ 3 files changed, 76 insertions(+) diff --git a/src/pixie/images.nim b/src/pixie/images.nim index 0eb4a69..07cfdb5 100644 --- a/src/pixie/images.nim +++ b/src/pixie/images.nim @@ -126,6 +126,41 @@ proc fill*(image: Image, color: SomeColor) {.inline.} = ## Fills the image with the parameter color. fillUnsafe(image.data, color, 0, image.data.len) +proc isOneColor(image: Image, color: ColorRGBX): bool = + ## Checks if the entire image is color. + result = true + + let color = image.getRgbaUnsafe(0, 0) + + var i: int + when defined(amd64) and not defined(pixieNoSimd): + let colorVec = mm_set1_epi32(cast[int32](color)) + for j in countup(0, image.data.len - 16, 16): + let + values0 = mm_loadu_si128(image.data[j].addr) + values1 = mm_loadu_si128(image.data[j + 4].addr) + values2 = mm_loadu_si128(image.data[j + 8].addr) + values3 = mm_loadu_si128(image.data[j + 12].addr) + values01 = mm_or_si128(values0, values1) + values23 = mm_or_si128(values2, values3) + values = mm_or_si128(values01, values23) + mask = mm_movemask_epi8(mm_cmpeq_epi8(values, colorVec)) + if mask != uint16.high.int: + return false + i += 16 + + for j in i ..< image.data.len: + if image.data[j] != color: + return false + +proc isOneColor*(image: Image): bool = + ## Checks if the entire image is the same color. + image.isOneColor(image.getRgbaUnsafe(0, 0)) + +proc isTransparent*(image: Image): bool = + ## Checks if this image is fully transparent or not. + image.isOneColor(rgbx(0, 0, 0, 0)) + proc flipHorizontal*(image: Image) = ## Flips the image around the Y axis. let w = image.width div 2 diff --git a/tests/benchmark_images.nim b/tests/benchmark_images.nim index 6f761d7..428fbd0 100644 --- a/tests/benchmark_images.nim +++ b/tests/benchmark_images.nim @@ -17,6 +17,14 @@ timeIt "fill_rgba": image.fill(rgba(63, 127, 191, 191)) doAssert image[0, 0] == rgba(63, 127, 191, 191) +image.fill(rgba(100, 0, 100, 100)) +timeIt "isOneColor": + doAssert image.isOneColor() + +image.fill(rgba(0, 0, 0, 0)) +timeIt "isTransparent": + doAssert image.isTransparent() + reset() timeIt "subImage": diff --git a/tests/test_images.nim b/tests/test_images.nim index 13b3da0..1b052a0 100644 --- a/tests/test_images.nim +++ b/tests/test_images.nim @@ -164,3 +164,36 @@ block: image.fillPath(p, rgba(255, 0, 0, 255)) newImage(newMask(image)).writeFile("tests/images/mask2image.png") + +block: + let image = newImage(100, 100) + doAssert image.isOneColor() + +block: + let image = newImage(100, 100) + image.fill(rgba(255, 255, 255, 255)) + doAssert image.isOneColor() + +block: + let image = newImage(100, 100) + image.fill(rgba(1, 2, 3, 4)) + doAssert image.isOneColor() + +block: + let image = newImage(100, 100) + image[99, 99] = rgba(255, 255, 255, 255) + doAssert not image.isOneColor() + +block: + let image = newImage(100, 100) + doAssert image.isTransparent() + +block: + let image = newImage(100, 100) + image.fill(rgba(255, 255, 255, 0)) + doAssert image.isTransparent() + +block: + let image = newImage(100, 100) + image[99, 99] = rgba(255, 255, 255, 255) + doAssert not image.isTransparent()