Created
April 3, 2011 19:47
-
-
Save digal/900709 to your computer and use it in GitHub Desktop.
Scala DSL for simple imagemagick-styles geometry strings
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* DSL for imagemagick-style geometry strings | |
* See http://www.imagemagick.org/Magick++/Geometry.html for description | |
* Note: offesets are not supported | |
* | |
* Implements following constructs | |
* | |
* <width> x <height> - Rect | |
* <Rect> <Qualifier> (where qualifier is !/%/>/<) - Geometry | |
* | |
* e.g. | |
* 100 x 200 | |
* 100 x 200 > | |
*/ | |
object Dimensions{ | |
implicit def int2Side(i: Int) = Side(i) | |
implicit def rect2Pair(r: Rect) = (r.w, r.h) | |
def original = 100 x 100 % | |
} | |
case class Geometry(rect: Rect, qualifier: GeoQualifier) { | |
def resize(img: Rect) = | |
qualifier.resize(img, rect) | |
} | |
case class Side(w: Int) { | |
def x (h: Int) = | |
Rect(w, h) | |
} | |
case class Rect(w: Int, h: Int) { | |
def turn = Rect(h, w) | |
def ratio = w.toDouble / h // w = r * h h = w / r | |
def isSquare = w == h | |
def tallerThan(other: Rect) = this.ratio < other.ratio | |
def widerThan(other: Rect) = this.ratio > other.ratio | |
def contains(other: Rect) = (this.w >= other.w) && (this.h >= other.h) | |
def notContains(other: Rect) = !(this contains other) | |
def * (mul: Int) = Rect(w * mul, h * mul) | |
def * (r: Rect) = Rect(w * r.w, h * r.h) | |
def / (div: Int) = Rect(w / div, h / div) | |
def / (r: Rect) = Rect(w / r.w, h / r.h) | |
def % = Geometry(this, Percentage) | |
def ! = Geometry(this, Exact) | |
def < = Geometry(this, ResizeIfSmaller) | |
def > = Geometry(this, ResizeIfGreater) | |
override def toString = "(%d x %d, r = %f) " format (w, h, ratio) | |
} | |
abstract sealed class GeoQualifier { | |
def resize(imgRect: Rect, geoRect: Rect): Rect | |
} | |
object Percentage extends GeoQualifier { | |
def resize(imgRect: Rect, geoRect: Rect) = | |
imgRect * geoRect / 100 | |
} | |
object Exact extends GeoQualifier { | |
def resize(imgRect: Rect, geoRect: Rect) = | |
geoRect | |
} | |
object ResizeIfSmaller extends GeoQualifier { | |
def resize(imgRect: Rect, geoRect: Rect) = | |
if (geoRect contains imgRect) { | |
if (imgRect tallerThan geoRect) //scale by height | |
Rect((geoRect.h * imgRect.ratio).toInt , geoRect.h ) | |
else //scale by width | |
Rect(geoRect.w , (geoRect.w / imgRect.ratio).toInt ) | |
} else { | |
imgRect | |
} | |
} | |
object ResizeIfGreater extends GeoQualifier { | |
def resize(imgRect: Rect, geoRect: Rect) = | |
if (geoRect notContains imgRect) { | |
if (imgRect tallerThan geoRect) //scale by height | |
Rect((geoRect.h * imgRect.ratio).toInt , geoRect.h ) | |
else //scale by width | |
Rect(geoRect.w , (geoRect.w / imgRect.ratio).toInt ) | |
} else { | |
imgRect | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import org.scalatest._ | |
import org.scalatest.junit.AssertionsForJUnit | |
import org.junit._ | |
import org.junit.Assert._ | |
import Dimensions._ | |
class DimensionsTest extends AssertionsForJUnit { | |
@Test def testRect = { | |
val rect = 100 x 200 | |
assertEquals(rect.w, 100) | |
assertEquals(rect.h, 200) | |
val pair: Pair[Int, Int] = rect | |
val (w, h) = pair | |
assertEquals(w, 100) | |
assertEquals(h, 200) | |
assertEquals(Rect(200,400), rect * 2) | |
assertEquals(Rect(10000,40000), rect * rect) | |
assertEquals(Rect(50,100), rect / 2) | |
assertEquals(Rect(1,1), rect / rect) | |
} | |
@Test def dimensionTest = { | |
val testRect = 200 x 200 | |
val tallRect = 100 x 200 | |
val wideRect = 200 x 100 | |
val exact100x200: Geometry = 100 x 200 ! | |
assertEquals(Geometry(Rect(100,200), Exact), exact100x200) | |
val percent100x200: Geometry = 100 x 200 % | |
assertEquals(Geometry(Rect(100,200), Percentage), percent100x200) | |
val smaller100x200: Geometry = (100 x 200) < | |
assertEquals(Geometry(Rect(100,200), ResizeIfSmaller), smaller100x200) | |
val greater100x200: Geometry = 100 x 200 > | |
assertEquals(Geometry(Rect(100,200), ResizeIfGreater), greater100x200) | |
assertEquals(100 x 200, exact100x200 resize testRect) | |
assertEquals(200 x 400, percent100x200 resize testRect) | |
assertEquals(200 x 200, smaller100x200 resize testRect) | |
assertEquals(100 x 100, greater100x200 resize testRect) | |
assertTrue(tallRect tallerThan wideRect) | |
assertFalse(wideRect tallerThan tallRect) | |
assertFalse(tallRect widerThan wideRect) | |
assertTrue(wideRect widerThan tallRect) | |
assertTrue(200 x 200 contains (100 x 200)) | |
assertFalse(100 x 200 contains (200 x 200)) | |
assertTrue(100 x 200 notContains (200 x 200)) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment