diff --git a/pixie.nimble b/pixie.nimble index 3941636..bf4e915 100644 --- a/pixie.nimble +++ b/pixie.nimble @@ -1,4 +1,4 @@ -version = "3.0.0" +version = "3.0.1" author = "Andre von Houck and Ryan Oldenburg" description = "Full-featured 2d graphics library for Nim." license = "MIT" @@ -6,7 +6,7 @@ license = "MIT" srcDir = "src" requires "nim >= 1.4.0" -requires "vmath >= 1.0.11" +requires "vmath >= 1.1.0" requires "chroma >= 0.2.5" requires "zippy >= 0.6.2" requires "flatty >= 0.2.2" diff --git a/src/pixie/images.nim b/src/pixie/images.nim index d9c5a86..81935d5 100644 --- a/src/pixie/images.nim +++ b/src/pixie/images.nim @@ -256,14 +256,24 @@ proc minifyBy2*(image: Image, power = 1): Image {.raises: [PixieError].} = var src = image for _ in 1 .. power: - result = newImage(src.width div 2, src.height div 2) - for y in 0 ..< result.height: + # When minifying an image of odd size, round the result image size up + # so a 99 x 99 src image returns a 50 x 50 image. + let + srcWidthIsOdd = (src.width mod 2) != 0 + srcHeightIsOdd = (src.height mod 2) != 0 + resultEvenWidth = src.width div 2 + resultEvenHeight = src.height div 2 + result = newImage( + if srcWidthIsOdd: resultEvenWidth + 1 else: resultEvenWidth, + if srcHeightIsOdd: resultEvenHeight + 1 else: resultEvenHeight + ) + for y in 0 ..< resultEvenHeight: var x: int when defined(amd64) and not defined(pixieNoSimd): let oddMask = mm_set1_epi16(cast[int16](0xff00)) first32 = cast[M128i]([uint32.high, 0, 0, 0]) - for _ in countup(0, result.width - 4, 2): + for _ in countup(0, resultEvenWidth - 4, 2): let top = mm_loadu_si128(src.data[src.dataIndex(x * 2, y * 2 + 0)].addr) btm = mm_loadu_si128(src.data[src.dataIndex(x * 2, y * 2 + 1)].addr) @@ -303,7 +313,7 @@ proc minifyBy2*(image: Image, power = 1): Image {.raises: [PixieError].} = mm_storeu_si128(result.data[result.dataIndex(x, y)].addr, zeroTwo) x += 2 - for x in x ..< result.width: + for x in x ..< resultEvenWidth: let a = src.getRgbaUnsafe(x * 2 + 0, y * 2 + 0) b = src.getRgbaUnsafe(x * 2 + 1, y * 2 + 0) @@ -318,6 +328,32 @@ proc minifyBy2*(image: Image, power = 1): Image {.raises: [PixieError].} = result.setRgbaUnsafe(x, y, rgba) + if srcWidthIsOdd: + let rgbx = mix( + src.getRgbaUnsafe(src.width - 1, y * 2 + 0), + src.getRgbaUnsafe(src.width - 1, y * 2 + 1), + 0.5 + ) * 0.5 + result.setRgbaUnsafe(result.width - 1, y, rgbx) + + if srcHeightIsOdd: + let y = result.height - 1 + + for x in 0 ..< resultEvenWidth: + let rgbx = mix( + src.getRgbaUnsafe(x * 2 + 0, y), + src.getRgbaUnsafe(x * 2 + 1, y), + 0.5 + ) * 0.5 + result.setRgbaUnsafe(x, y, rgbx) + + if srcWidthIsOdd: + result.setRgbaUnsafe( + result.width - 1, + result.height - 1, + src.getRgbaUnsafe(src.width - 1, src.height - 1) * 0.25 + ) + # Set src as this result for if we do another power src = result diff --git a/src/pixie/internal.nim b/src/pixie/internal.nim index 411cffd..fa53219 100644 --- a/src/pixie/internal.nim +++ b/src/pixie/internal.nim @@ -22,7 +22,7 @@ proc gaussianKernel*(radius: int): seq[uint16] {.raises: [].} = for i, f in floats: result[i] = round(f * 255 * 256).uint16 -proc applyOpacity*(color: ColorRGBX, opacity: float32): ColorRGBX {.raises: [].} = +proc `*`*(color: ColorRGBX, opacity: float32): ColorRGBX {.raises: [].} = if opacity == 0: rgbx(0, 0, 0, 0) else: diff --git a/tests/images/diffs/minify_odd.png b/tests/images/diffs/minify_odd.png new file mode 100644 index 0000000..a37198b Binary files /dev/null and b/tests/images/diffs/minify_odd.png differ diff --git a/tests/images/magnifiedBy2.png b/tests/images/magnifiedBy2.png index 24655dc..da429be 100644 Binary files a/tests/images/magnifiedBy2.png and b/tests/images/magnifiedBy2.png differ diff --git a/tests/images/magnifiedBy4.png b/tests/images/magnifiedBy4.png index cefd926..3f18f7c 100644 Binary files a/tests/images/magnifiedBy4.png and b/tests/images/magnifiedBy4.png differ diff --git a/tests/images/masters/minify_odd.png b/tests/images/masters/minify_odd.png new file mode 100644 index 0000000..4d3ac69 Binary files /dev/null and b/tests/images/masters/minify_odd.png differ diff --git a/tests/images/minifiedBy2.png b/tests/images/minifiedBy2.png index 854cdfc..cc72a7e 100644 Binary files a/tests/images/minifiedBy2.png and b/tests/images/minifiedBy2.png differ diff --git a/tests/images/minifiedBy4.png b/tests/images/minifiedBy4.png index 6e5769b..532c931 100644 Binary files a/tests/images/minifiedBy4.png and b/tests/images/minifiedBy4.png differ diff --git a/tests/images/rendered/minify_odd.png b/tests/images/rendered/minify_odd.png new file mode 100644 index 0000000..87f83e3 Binary files /dev/null and b/tests/images/rendered/minify_odd.png differ diff --git a/tests/test_images_draw.nim b/tests/test_images_draw.nim index ba89f6b..b035137 100644 --- a/tests/test_images_draw.nim +++ b/tests/test_images_draw.nim @@ -1,5 +1,13 @@ import pixie, strformat +proc doDiff(rendered: Image, name: string) = + rendered.writeFile(&"tests/images/rendered/{name}.png") + let + master = readImage(&"tests/images/masters/{name}.png") + (diffScore, diffImage) = diff(master, rendered) + echo &"{name} score: {diffScore}" + diffImage.writeFile(&"tests/images/diffs/{name}.png") + block: let a = newImage(1000, 1000) @@ -128,14 +136,6 @@ block: a.draw(b, translate(vec2(250, 250)) * scale(vec2(0.5, 0.5))) a.writeFile("tests/images/scaleHalf.png") -proc doDiff(rendered: Image, name: string) = - rendered.writeFile(&"tests/images/rendered/{name}.png") - let - master = readImage(&"tests/images/masters/{name}.png") - (diffScore, diffImage) = diff(master, rendered) - echo &"{name} score: {diffScore}" - diffImage.writeFile(&"tests/images/diffs/{name}.png") - block: let a = newImage(100, 100) @@ -249,3 +249,12 @@ block: a.draw(b, m * translate(vec2(-40,-40))) a.draw(b, m * translate(vec2(0,-40))) doDiff(a, "smooth12") + +block: + let + a = newImage(100, 100) + b = newImage(99, 99) + a.fill(rgba(255, 255, 255, 255)) + b.fill(rgba(0, 0, 0, 255)) + a.draw(b, scale(vec2(0.5, 0.5))) + doDiff(a, "minify_odd")