package imagefilters import java.awt.Color /** * This class implements the various image filters */ object ImageFilters { def filter(src: Array[Array[Int]], func: (Int, Int, Int, Int, Int) => Int): Array[Array[Int]] = { val width: Int = src.length val height: Int = if (width == 0) 0 else src(0).length val dst: Array[Array[Int]] = Array.ofDim(width, height) for (x: Int <- 0 until width) { for (y: Int <- 0 until height) { dst(x)(y) = func(src(x)(y), x, y, width, height) } } return dst } def filter(src: Array[Array[Int]], func: (Int) => Int): Array[Array[Int]] = filter(src, (value, x, y, width, height) => func(value)) def colorFilter(src: Array[Array[Color]], func: (Color, Int, Int, Int, Int) => Color): Array[Array[Color]] = { val width: Int = src.length val height: Int = if (width == 0) 0 else src(0).length val dst: Array[Array[Color]] = Array.ofDim(width, height) for (x: Int <- 0 until width) { for (y: Int <- 0 until height) { dst(x)(y) = func(src(x)(y), x, y, width, height) } } return dst } def colorFilter(src: Array[Array[Color]], func: (Color) => Color): Array[Array[Color]] = colorFilter(src, (value, x, y, width, height) => func(value)) def duplicate(a: Array[Array[Int]]): Array[Array[Int]] = filter(a, (value) => value) def threshold(a: Array[Array[Int]], thresh: Int): Array[Array[Int]] = filter(a, (value) => if (value > thresh) 255 else 0) def mean(a: Array[Array[Int]]): Array[Array[Int]] = filter(a, (value, x, y, width, height) => { if (x == 0 || x == width - 1 || y == 0 || y == height - 1) value else { var avg: Double = 0 for (dx: Int <- -1 to 1) { for (dy: Int <- -1 to 1) { avg += a(x+dx)(y+dy) } } (avg/9.0).toInt } }) def mean(a: Array[Array[Int]], radius: Int): Array[Array[Int]] = { if (radius < 0) throw new IllegalArgumentException("radius must be >= 0") val diameter: Int = 2 * radius + 1 filter(a, (value, x, y, width, height) => { if (x <= radius - 1 || x >= width - radius || y <= radius - 1 || y >= height - radius) value else { var avg: Double = 0 for (dx: Int <- -radius to radius) { for (dy: Int <- -radius to radius) { avg += a(x+dx)(y+dy) } } (avg/(diameter * diameter)).toInt } }) } def edges(a: Array[Array[Int]]): Array[Array[Int]] = filter(a, (value, x, y, width, height) => { if (x == 0 || x == width - 1 || y == 0 || y == height - 1) value else { val dx: Int = a(x+1)(y) - a(x-1)(y) val dy: Int = a(x)(y+1) - a(x)(y-1) Math.sqrt(dx*dx + dy*dy).toInt } }) def sobel(a: Array[Array[Int]], intensityFactor: Double): Array[Array[Int]] = filter(a, (value, x, y, width, height) => { if (x == 0 || x == width - 1 || y == 0 || y == height - 1) value else { val dx: Int = a(x+1)(y-1) + 2*a(x+1)(y) + a(x+1)(y+1) - a(x-1)(y-1) - 2*a(x-1)(y) - a(x-1)(y+1) val dy: Int = a(x-1)(y+1) + 2*a(x)(y+1) + a(x+1)(y+1) - a(x-1)(y-1) - 2*a(x)(y-1) - a(x+1)(y-1) (Math.sqrt(dx*dx + dy*dy)*intensityFactor).toInt } }) def noise(a: Array[Array[Int]], intensity: Double): Array[Array[Int]] = filter(a, (value) => { Math.max(0, Math.min(255, value + (Math.random()*2-1)*intensity)).toInt }) def mask(a: Array[Array[Color]], maskImg: Array[Array[Int]]): Array[Array[Color]] = { val maskWidth: Int = maskImg.length val maskHeight: Int = if (maskWidth == 0) 0 else maskImg(0).length colorFilter(a, (col, x, y, width, height) => { if (x >= maskWidth || y >= maskHeight) col else { val factor: Double = maskImg(x)(y)/255.0 new Color( (col.getRed * factor).toInt, (col.getGreen * factor).toInt, (col.getBlue * factor).toInt ) } }) } def getAvgInPixel(a: Array[Array[Color]], pixelSize: Int, px: Int, py: Int): Color = { val width: Int = a.length val height: Int = if (width == 0) 0 else a(0).length var r: Double = 0 var g: Double = 0 var b: Double = 0 var cnt: Int = 0 for (x: Int <- px*pixelSize until (px+1)*pixelSize) { for (y: Int <- py*pixelSize until (py+1)*pixelSize) { if (x < width && y < height) { cnt += 1 r += a(x)(y).getRed g += a(x)(y).getGreen b += a(x)(y).getBlue } } } return new Color((r/cnt).toInt, (g/cnt).toInt, (b/cnt).toInt) } def pixelize(a: Array[Array[Color]], pixelSize: Int): Array[Array[Color]] = { val width: Int = a.length val height: Int = if (width == 0) 0 else a(0).length val hPixels: Int = Math.ceil(width.toDouble/pixelSize).toInt val vPixels: Int = Math.ceil(height.toDouble/pixelSize).toInt val pixels: Array[Array[Color]] = Array.ofDim[Color](hPixels, vPixels) for (x: Int <- 0 until hPixels) { for (y: Int <- 0 until vPixels) { pixels(x)(y) = getAvgInPixel(a, pixelSize, x, y) } } colorFilter(a, (col, x, y, w, h) => pixels(x/pixelSize)(y/pixelSize)) } def pixelize(a: Array[Array[Color]], pixelSize: Int, x1: Int, y1: Int, x2: Int, y2: Int): Array[Array[Color]] = { val pixelated: Array[Array[Color]] = pixelize(a, pixelSize) colorFilter(a, (col, x, y, w, h) => { if (x1 <= x && x <= x2 && y1 <= y && y <= y2) { pixelated(x)(y) } else col }) } }