Skip to content

Instantly share code, notes, and snippets.

@shahbaz-momi
Created May 10, 2018 21:06
Show Gist options
  • Save shahbaz-momi/f0640844708d183daa5fda9b29e792c6 to your computer and use it in GitHub Desktop.
Save shahbaz-momi/f0640844708d183daa5fda9b29e792c6 to your computer and use it in GitHub Desktop.
Binary to image converter in Kotlin
package com.asdev.bin2img
import java.awt.Color
import java.awt.image.BufferedImage
import java.io.ByteArrayOutputStream
import java.io.File
import java.nio.file.Files
import javax.imageio.ImageIO
/**
* Created by Asdev on 08/26/16. All rights reserved.
* Unauthorized copying via any medium is stricitly
* prohibited.
*
* Authored by Shahbaz Momi as part of BinToImg
* under the package com.asdev.bin2img
*/
fun main(args: Array<String>) {
if(args[0] == "bin-in") {
val img = bin2img(Files.readAllBytes(File(args[1]).toPath())!!.toTypedArray())
ImageIO.write(img, "png", File(args[2]))
} else if(args[0] == "img-in") {
val bytes = img2bin(ImageIO.read(File(args[1])))
Files.write(File(args[2]).toPath()!!, bytes.toByteArray())
}
}
fun bin2img(data: Array<Byte>): BufferedImage {
println("SIZE: " + data.size)
// compute optimal width and height
val sqrt = Math.sqrt(data.size.toDouble() / 3.0)
// add some and call it a day
val width = sqrt.toInt()
var height = sqrt.toInt()
// make sure it fits
while (width * height < data.size / 3.0) {
height ++
}
println("WIDTH $width HEIGHT $height")
// convert the data byte to pixel data
val out = BufferedImage(width, height, BufferedImage.TYPE_3BYTE_BGR)
var index = 0
for(y in 0 until height) {
for(x in 0 until width) {
// value index..index + 2
out.setRGB(x, y, Color(data.getOrElse(index){-128}.toInt() + 128, data.getOrElse(index + 1){-128}.toInt() + 128, data.getOrElse(index + 2){-128}.toInt() + 128).rgb)
index += 3
if(index >= data.size) {
// realign to last three bytes
index -=3
// add marker bit
out.setRGB(x + 1, y, Color( if(index < data.size) 255 else 0, if(index + 1 < data.size) 255 else 0, if(index + 2 < data.size) 255 else 0 ).rgb)
break
}
}
}
// set last 3 bytes to 255
return out
}
fun img2bin(img: BufferedImage): Array<Byte> {
// get size of data
var size = img.width * img.height
// start from end and read all black pixels
for(x in img.width - 1 downTo 0) {
// if black, continue
if(img.getRGB(x, img.height - 1) == Color.BLACK.rgb) {
size --
} else {
// not black no more
// sub this bit from the size
size --
// three bytes per color
size *= 3
// this color tells which bits of last is legit
val lC = Color(img.getRGB(x, img.height - 1))
// see if there is an actual blue component
if(lC.blue == 0)
size --
// see if there is an actual red component
if(lC.green == 0)
size --
break
}
}
println("DECODE SIZE: $size")
val output = ByteArrayOutputStream(size)
var index = 0
for(y in 0 until img.height) {
for(x in 0 until img.width) {
val c = Color(img.getRGB(x, y))
if(index < size) {
output.write(c.red - 128)
}
if(index + 1 < size) {
output.write(c.green - 128)
}
if(index + 2 < size) {
output.write(c.blue - 128)
}
index += 3
if(index >= size) {
break
}
}
}
return output.toByteArray().toTypedArray()
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment