Skip to content

Instantly share code, notes, and snippets.

@digal
Created April 3, 2011 19:47
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save digal/900709 to your computer and use it in GitHub Desktop.
Save digal/900709 to your computer and use it in GitHub Desktop.
Scala DSL for simple imagemagick-styles geometry strings
/**
* 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
}
}
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