From 7774695e352ea86e00ca4ecceb0bac03da25111b Mon Sep 17 00:00:00 2001 From: Ryan Oldenburg Date: Tue, 19 Oct 2021 17:32:34 -0500 Subject: [PATCH] 3.0.1, minifyBy2 fix for non-even src dimens --- pixie.nimble | 4 +-- src/pixie/images.nim | 44 ++++++++++++++++++++++++--- src/pixie/internal.nim | 2 +- tests/images/diffs/minify_odd.png | Bin 0 -> 326 bytes tests/images/magnifiedBy2.png | Bin 353 -> 411 bytes tests/images/magnifiedBy4.png | Bin 408 -> 479 bytes tests/images/masters/minify_odd.png | Bin 0 -> 381 bytes tests/images/minifiedBy2.png | Bin 194 -> 211 bytes tests/images/minifiedBy4.png | Bin 161 -> 179 bytes tests/images/rendered/minify_odd.png | Bin 0 -> 378 bytes tests/test_images_draw.nim | 25 ++++++++++----- 11 files changed, 60 insertions(+), 15 deletions(-) create mode 100644 tests/images/diffs/minify_odd.png create mode 100644 tests/images/masters/minify_odd.png create mode 100644 tests/images/rendered/minify_odd.png 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 0000000000000000000000000000000000000000..a37198b678ff2c7d960c2e9a519d30ece1e927b9 GIT binary patch literal 326 zcmeAS@N?(olHy`uVBq!ia0vp^DImI3^7phTYrpU`+CKaSW+oe0%30Z?k~_>&5;% z5>o{)M_%Hbnxb61puuAzTe{pP9`%&A&)Y(@{{9Pp`_lG%eDo%pNn7W7s$KZb$v1Jy zr0X|$nUf_n4m(J)oiYe$Yc%4SlDL3}IhB?|>kOW!?6G~Wu+94Y<{gK63R^eJWU*0h z_1D}PFSct{_L^^*_oYyojd(A;;@Yfwx}t#fBk#SFnW@#* Ul>A)x6d33Xp00i_>zopr0B1Fop8x;= literal 353 zcmeAS@N?(olHy`uVBq!ia0vp^DImb;BUjO+ocAbd*hCF+Tq%@XJK^36|v;O}nUE(~!7qC!wPUrVe RuYp0w;OXk;vd$@?2>@9saLxb# diff --git a/tests/images/magnifiedBy4.png b/tests/images/magnifiedBy4.png index cefd926169c9ec567bb5c4788b2ffd6bf5978c03..3f18f7c4dc7e29ceee676e8f2e634a0dad8845b4 100644 GIT binary patch literal 479 zcmeAS@N?(olHy`uVBq!ia0vp^86eET1|(%=wk~8~U|iF4_swiLQm|a-K)?_Gf=P-L#cFnd_6?fUU zldtt(%>Cz>%XsZ#{;P=+WV=oyXZe#G=L=SOzV&~RPogL9s9mtDjGBD(U!`-oGx8Ic>CU_p<0N z-r4-;`R(QBe~(u7=ut3iI>I4DW5(s&dsh``W z$lZxy-8q?;Kn_c~qpu?a!^VE@KZ&eBIU!FM$B+ufw|5S59uDAPbyQul;r>jo@&fT} zW9C%}j>pZ7i*5gweXr_%KS9Z(N5Qb^2#1g|tr>sH%ICeCW1RnSXZV>m9(`@M2@;M; hES-WXbYMK=clypaS&u>b4luMBJYD@<);T3K0RWwUZbkqA literal 0 HcmV?d00001 diff --git a/tests/images/minifiedBy2.png b/tests/images/minifiedBy2.png index 854cdfc0e34c6772b3c5cfa768a9c8ebafb4f3e3..cc72a7e55b1dd99097e0e67da920ec1c02798730 100644 GIT binary patch literal 211 zcmeAS@N?(olHy`uVBq!ia0vp^#vshW1|+Q(8fXEjS)MMAAr*{oZ#ietF;&NZ*-NIoPF!GC(JqrWudKA1-yb2YNdN?V+U zkFXBgTwL?5k5o~}kKJ=8=`LIhuJO1URq fGU*xX^WV%K#~x+fSnG8b=t>4pS3j3^P6+d(K*|v-?)BH(2xS1LLF}9nG#hOP(s|GG|(PoOX!f zyJR$BTJsiUp+4=*ujec-X-5z9)I0<_iow&>&t;ucLK6Vk)Jl>7 diff --git a/tests/images/minifiedBy4.png b/tests/images/minifiedBy4.png index 6e5769b2b757cf262dec690bed767f63c79ed920..532c9319448d3bf58d04b15289d74806ddd675e6 100644 GIT binary patch literal 179 zcmeAS@N?(olHy`uVBq!ia0vp^QXtI11|(N{`J4k%Rh}-6Ar*{or(NVcpupp@K4oIx zqqJRKW-mCbywo?&Sz33z;qR%*%=KR$aJaL`${wvV3dnNS+@Q_u+jf*`CDTe>n~IAD zT`%mCB$6c5wBD=>)LtXD_*`{ef@>@5$#=zQNuH9GxxL%;MrH={ ct#fzDiOg(gRaG&%4Ri&Ar>mdKI;Vst0C~(mb^rhX literal 161 zcmeAS@N?(olHy`uVBq!ia0vp^k|4~%1|*NXY)uAI8J;eVAr*{or)=bHFc4t&|K%#t zdiKY~Nr5v|PRx7|JK>f7rYUS|cI-&lc;Z*3!f}Ubp}JV~b~^YZSDPt-PDJ{d!EJ zf??AU4k2Za9$GUtuYDT-zBV}B?t5+j-&^-{vW0KYbY8PPUiH|fwOcD*H?uh=v2+Tm uxJ{5CoAER2&t0?UbL#g`?I+HtN+$lSiKa*9mj4EZDTAl0pUXO@geCx-YJp_{ literal 0 HcmV?d00001 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")