From 8bee2894351444d5a7ef132fa7e1213c48d41ebf Mon Sep 17 00:00:00 2001 From: treeform Date: Mon, 1 Aug 2022 17:07:48 -0700 Subject: [PATCH 1/4] Add cropAlpha. --- src/pixie/images.nim | 30 ++++++++++++++++++++++++++++ tests/images/cropHeart.png | Bin 0 -> 1067 bytes tests/test_images.nim | 39 +++++++++++++++++++++++++++++++++++++ 3 files changed, 69 insertions(+) create mode 100644 tests/images/cropHeart.png diff --git a/src/pixie/images.nim b/src/pixie/images.nim index eef3c143..3af36cae 100644 --- a/src/pixie/images.nim +++ b/src/pixie/images.nim @@ -751,5 +751,35 @@ proc superImage*(image: Image, x, y, w, h: int): Image {.raises: [PixieError].} result = newImage(w, h) result.draw(image, translate(vec2(-x.float32, -y.float32)), OverwriteBlend) +proc cropAlpha*(image: Image): (Image, Rect) = + ## Crops the alpha off the edges of an image. + ## Returns the new cropped image and the rectangle it used for cropping. + var + xMin = image.width + xMax = 0 + yMin = image.height + yMax = 0 + # Find the crop coordinates. + for y in 0 ..< image.height: + for x in 0 ..< image.width: + if image.unsafe[x, y].a != 0: + xMin = min(xMin, x) + xMax = max(xMax, x + 1) + yMin = min(yMin, y) + yMax = max(yMax, y + 1) + if xMax <= xMin or yMax <= yMin: + raise newException(PixieError, "Cannot cropAlpha fully transparent image") + let + corpImage = newImage(xMax - xMin, yMax - yMin) + cropRect = rect( + xMin.float32, + yMin.float32, + corpImage.width.float32, + corpImage.height.float32 + ) + # Draw the bigger image into the cropped image. + corpImage.draw(image, translate(vec2(-xMin.float32, -yMin.float32))) + return (corpImage, cropRect) + when defined(release): {.pop.} diff --git a/tests/images/cropHeart.png b/tests/images/cropHeart.png new file mode 100644 index 0000000000000000000000000000000000000000..ea21adbf3405d194da0cdcaddccb450bbfb43241 GIT binary patch literal 1067 zcmV+`1l0S9P)NklMh_Cu zo8UpjwrY|^C?Vj*Lv2ZE3@KF0>LHf6y4lQEp4pwHo9yn)?9OaktPhU92jD7DS$7CEuU0i(s&y>-9EM#9`4+%#cUm;;u4=ke>sa*7i;pw= zpg87EiW0>!{^aAl;yg63$t0sLd;QM>wc$4CI4wZNZ^7 zuizcwpte!yK)ANxP@7lqj&M-h021V{ZJWruaIbg}h|RarLOk+ap}?0=-v&@DPS%#5Q_afFkQ2 z=cO@v+4EQnAhQ$CRP~B?qj%96diDI(0uW1+rvW@?-HQnD+;Woq|Gh?C0Lf>ch-$8O zx7Se3(c}MZ)de7CPx71sORRed0hZ`(tEX)NXVXKgIV}T_#L{jC*UDJef26g zm-_;$7rZ@RRDWa-dwtLP&~X5g1sr>R{G=#O@cV4;HKD{a_WbxTdzzdHMI-?{togA^ zmY9@4{_*xaxW{`u?#n=R<`qa7|dhv`QcG9@kM4c>p56j6Yub_s Date: Mon, 1 Aug 2022 20:26:36 -0700 Subject: [PATCH 2/4] opaqueBounds --- src/pixie/images.nim | 30 ++++++++++++++---------------- tests/images/cropHeart.png | Bin 1067 -> 0 bytes tests/images/opaqueBounds.png | Bin 0 -> 1131 bytes tests/test_images.nim | 23 +++++++---------------- 4 files changed, 21 insertions(+), 32 deletions(-) delete mode 100644 tests/images/cropHeart.png create mode 100644 tests/images/opaqueBounds.png diff --git a/src/pixie/images.nim b/src/pixie/images.nim index 3af36cae..e4f447f5 100644 --- a/src/pixie/images.nim +++ b/src/pixie/images.nim @@ -751,15 +751,18 @@ proc superImage*(image: Image, x, y, w, h: int): Image {.raises: [PixieError].} result = newImage(w, h) result.draw(image, translate(vec2(-x.float32, -y.float32)), OverwriteBlend) -proc cropAlpha*(image: Image): (Image, Rect) = - ## Crops the alpha off the edges of an image. - ## Returns the new cropped image and the rectangle it used for cropping. +proc opaqueBounds*(image: Image): Rect = + ## Returns the bounds of opaque pixels. + ## Some images have transparency around them, use this to find just the + ## visible part of the image and then use subImage to cut it out. + ## Returns zero rect if whole image is transparent. + ## Returns just the size of the image if no edge is transparent. var xMin = image.width xMax = 0 yMin = image.height yMax = 0 - # Find the crop coordinates. + # Find the trim coordinates. for y in 0 ..< image.height: for x in 0 ..< image.width: if image.unsafe[x, y].a != 0: @@ -768,18 +771,13 @@ proc cropAlpha*(image: Image): (Image, Rect) = yMin = min(yMin, y) yMax = max(yMax, y + 1) if xMax <= xMin or yMax <= yMin: - raise newException(PixieError, "Cannot cropAlpha fully transparent image") - let - corpImage = newImage(xMax - xMin, yMax - yMin) - cropRect = rect( - xMin.float32, - yMin.float32, - corpImage.width.float32, - corpImage.height.float32 - ) - # Draw the bigger image into the cropped image. - corpImage.draw(image, translate(vec2(-xMin.float32, -yMin.float32))) - return (corpImage, cropRect) + return rect(0, 0, 0, 0) + rect( + xMin.float32, + yMin.float32, + (xMax - xMin).float32, + (yMax - yMin).float32 + ) when defined(release): {.pop.} diff --git a/tests/images/cropHeart.png b/tests/images/cropHeart.png deleted file mode 100644 index ea21adbf3405d194da0cdcaddccb450bbfb43241..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1067 zcmV+`1l0S9P)NklMh_Cu zo8UpjwrY|^C?Vj*Lv2ZE3@KF0>LHf6y4lQEp4pwHo9yn)?9OaktPhU92jD7DS$7CEuU0i(s&y>-9EM#9`4+%#cUm;;u4=ke>sa*7i;pw= zpg87EiW0>!{^aAl;yg63$t0sLd;QM>wc$4CI4wZNZ^7 zuizcwpte!yK)ANxP@7lqj&M-h021V{ZJWruaIbg}h|RarLOk+ap}?0=-v&@DPS%#5Q_afFkQ2 z=cO@v+4EQnAhQ$CRP~B?qj%96diDI(0uW1+rvW@?-HQnD+;Woq|Gh?C0Lf>ch-$8O zx7Se3(c}MZ)de7CPx71sORRed0hZ`(tEX)NXVXKgIV}T_#L{jC*UDJef26g zm-_;$7rZ@RRDWa-dwtLP&~X5g1sr>R{G=#O@cV4;HKD{a_WbxTdzzdHMI-?{togA^ zmY9@4{_*xaxW{`u?#n=R<`qa7|dhv`QcG9@kM4c>p56j6Yub_s_i#7Mknd!qk6Cx1`djtJi?yw*=th1mr3N&xV<3 zi^z8Nmb3XoZSMnv=>yv#dbQT1-w066<=-*}ry(L7))yjT1ZSw#+|Rv%^#Rc)eH%b` zPrnG@B2Zrs2sJOR*EKDE9jm_Y*$zW3C7%G;VW-8zj%{^Ki(kj8?|X*f8v($iofIdE zN&e&?yq4d|I!#347JBC^FNxnzA9)V;N(KR323Si*ekiON zg^q0idN+WKZ2)@bTj=gk9(FR^H6HY4GTOsHZuHD7LNbqK|7{T8qTJNusNXtNP2N*4yxx^4;9sOc6J1j0f?jNDL}8V9u9h? zJ~NuG0!XP)bv8EM18^f+a$s(77H4*&)Kvf?%b#yJruw!5KX9D{)aDG%>Q=w&07R~z zyytqUHwE~W>o}pN)xLi6UN5>m1t9!i#JI>R>=%KtKrL!gyH~-U0}#1(?045o?N-Gt zt_Oh{)S_lTI(-EoQY!r8mMb{`i(L1~A~mShXMg_zh~4wQMuU7DF< zPlq!-5lesoXX)5^M@&W_e*}90+~Yl-3HIV3)&N8nK3z5`?-hkEb4^%pI^|b+kLx&z xJphq!XZ~FI` Date: Mon, 1 Aug 2022 20:36:10 -0700 Subject: [PATCH 3/4] image.subImage(Rect) --- src/pixie/images.nim | 6 ++++++ tests/test_images.nim | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/src/pixie/images.nim b/src/pixie/images.nim index e4f447f5..55db070e 100644 --- a/src/pixie/images.nim +++ b/src/pixie/images.nim @@ -129,6 +129,12 @@ proc subImage*(image: Image, x, y, w, h: int): Image {.raises: [PixieError].} = w * 4 ) +proc subImage*(image: Image, rect: Rect): Image {.raises: [PixieError].} = + ## Gets a sub image from this image via rectangle. + ## Rectangle is snapped/expanded to whole pixels first. + let r = rect.snapToPixels() + image.subImage(r.x.int, r.y.int, r.w.int, r.h.int) + proc diff*(master, image: Image): (float32, Image) {.raises: [PixieError].} = ## Compares the parameters and returns a score and image of the difference. let diff --git a/tests/test_images.nim b/tests/test_images.nim index 5117df10..bb86a6fc 100644 --- a/tests/test_images.nim +++ b/tests/test_images.nim @@ -259,5 +259,5 @@ block: ) let rect = image.opaqueBounds() doAssert rect == rect(6.0, 6.0, 48.0, 48.0) - let trimmedImage = image.subImage(rect.x.int, rect.y.int, rect.w.int, rect.h.int) + let trimmedImage = image.subImage(rect) trimmedImage.xray("tests/images/opaqueBounds.png") From 791eec8eda196819357c0eedcc2db05db25c6579 Mon Sep 17 00:00:00 2001 From: treeform Date: Tue, 2 Aug 2022 10:06:36 -0700 Subject: [PATCH 4/4] fix opaqueBounds test --- tests/images/opaqueBounds.png | Bin 1131 -> 372 bytes tests/test_images.nim | 11 ++++------- 2 files changed, 4 insertions(+), 7 deletions(-) diff --git a/tests/images/opaqueBounds.png b/tests/images/opaqueBounds.png index 6bc151d6290d9db3ca68c7fb32d146c5f4b24fc4..6f70c35bf5902a1c4022b4d5d2183b0d66ee7d7e 100644 GIT binary patch literal 372 zcmV-)0gL{LP)zyAM?-PDcEou+QYrAGuaep|9Q%tDx9*i7hMhxxM*EQT!zXRkudDg||56@t+8 zEVeU0gif!tsRJKEur)psY1U5Yv`Ru9*a?ATUYpnqQRwhWkvbp>L2QE>q|S~C9abq( z2ckld+Qdul%%o8DN|`#46oTAF7BpvNg{oCj)PbxJXg15CJwqi_TuE66R6?NLP{Q)9 zTF70=PzTgPVA*uR`i)7*T*+7mOhRDU*z)dzSx8;UQ3uRIpxIpWj)Y4nTgh1mTtbj4 zkoqr&TPRwopbof&Kq?_Uvrr_ot5jGAii99665e|$7FsJ+r~}19Kp8IXOL+lx0~k&{ SB3sx10000_i#7Mknd!qk6Cx1`djtJi?yw*=th1mr3N&xV<3 zi^z8Nmb3XoZSMnv=>yv#dbQT1-w066<=-*}ry(L7))yjT1ZSw#+|Rv%^#Rc)eH%b` zPrnG@B2Zrs2sJOR*EKDE9jm_Y*$zW3C7%G;VW-8zj%{^Ki(kj8?|X*f8v($iofIdE zN&e&?yq4d|I!#347JBC^FNxnzA9)V;N(KR323Si*ekiON zg^q0idN+WKZ2)@bTj=gk9(FR^H6HY4GTOsHZuHD7LNbqK|7{T8qTJNusNXtNP2N*4yxx^4;9sOc6J1j0f?jNDL}8V9u9h? zJ~NuG0!XP)bv8EM18^f+a$s(77H4*&)Kvf?%b#yJruw!5KX9D{)aDG%>Q=w&07R~z zyytqUHwE~W>o}pN)xLi6UN5>m1t9!i#JI>R>=%KtKrL!gyH~-U0}#1(?045o?N-Gt zt_Oh{)S_lTI(-EoQY!r8mMb{`i(L1~A~mShXMg_zh~4wQMuU7DF< zPlq!-5lesoXX)5^M@&W_e*}90+~Yl-3HIV3)&N8nK3z5`?-hkEb4^%pI^|b+kLx&z xJphq!XZ~FI`