Skip to content

Instantly share code, notes, and snippets.

@freyacodes
Created November 25, 2018 19:05
Show Gist options
  • Save freyacodes/115a15450bec82720d3bb5a70b5ceefd to your computer and use it in GitHub Desktop.
Save freyacodes/115a15450bec82720d3bb5a70b5ceefd to your computer and use it in GitHub Desktop.
import java.awt.Color
import java.io.File
import javax.imageio.ImageIO
import kotlin.math.roundToInt
const val N = 1.0
fun main(args: Array<String>) {
val img = ImageIO.read(File(args[0]))
val map = Array(img.width) { arrayOfNulls<Vector>(img.height) }
for (x in 0 until img.width) {
for (y in 0 until img.height) {
map[x][y] = Vector(img.getRGB(x, y))
}
}
fun tryAdd(x: Int, y: Int, quantError: Vector, sixteenths: Int) {
if (x >= 0 && y >= 0 && x < img.width && y < img.height) {
map[x][y] = map[x][y]!! + quantError * (sixteenths / 16.0)
}
}
for (x in 0 until img.width) {
for (y in 0 until img.height) {
val oldPixel = map[x][y]!!
val newPixel = oldPixel.reduceColors()
//map[x][y] = newPixel
val quantError = oldPixel - newPixel
// @formatter:off
tryAdd(x + 1, y , quantError, 7)
tryAdd(x - 1, y + 1, quantError, 3)
tryAdd(x , y + 1, quantError, 5)
tryAdd(x + 1, y + 1, quantError, 1)
// @formatter:on
img.setRGB(x, y, newPixel.toColor().rgb)
}
}
File("gen").mkdir()
val file = File.createTempFile("dithered", ".png", File("gen"))
ImageIO.write(img, "PNG", file)
Runtime.getRuntime().exec("feh ${file.canonicalPath}")
}
data class Vector(val r: Double, val g: Double, val b: Double) {
constructor(rgb: Int) : this(
(rgb shr 16 and 0xFF).toDouble() / 255,
(rgb shr 8 and 0xFF).toDouble() / 255,
(rgb shr 0 and 0xFF).toDouble() / 255
)
operator fun plus(o: Vector): Vector {
return Vector(r + o.r, g + o.g, b + o.b)
}
operator fun minus(o: Vector): Vector {
return Vector(r - o.r, g - o.g, b - o.b)
}
operator fun div(op: Double): Vector {
return Vector(r / op, g / op, b / op)
}
operator fun times(op: Double): Vector {
return Vector(r * op, g * op, b * op)
}
fun reduceColors(): Vector {
return Vector(
(r * N).roundToInt() / N,
(g * N).roundToInt() / N,
(b * N).roundToInt() / N
)
}
fun toColor(): Color {
return Color(
(r * 255).roundToInt(),
(g * 255).roundToInt(),
(b * 255).roundToInt()
)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment