Reputation: 1
so I have to convert a bitmap that is 400x300 into a byte array with exactly 15000 size. It has to be displayed on an e-paper screen so it can only be black/white/gray.
This is my attempt so far:
fun convertPictureToByteArray(bitmap: Bitmap): ByteArray {
val byteArray = ByteArray(15000)
var index = 0
var temp = 0
val pixels = IntArray(bitmap.width * bitmap.height)
bitmap.getPixels(pixels, 0, bitmap.width, 0, 0, bitmap.width, bitmap.height)
for(x in (bitmap.height - 1) downTo 0) {
for(y in 0 until bitmap.width / 8) {
var tempPixels = IntArray(8)
for(z in 0 until 8) {
tempPixels[z] = pixels[temp]
temp++
}
var totalLuminance = 0.0
for(pixel in tempPixels) {
val red = Color.red(pixel)
val green = Color.green(pixel)
val blue = Color.blue(pixel)
val luminance = 0.299 * red + 0.587 * green + 0.114 * blue
totalLuminance += luminance
}
val averageLuminance = totalLuminance / tempPixels.size
byteArray[index] = grayShadesArray[averageLuminance.toInt()]
index++
}
}
return byteArray
}
Basically what it should do is go through the bitmap pixel by pixel and get average luminance from 8 pixels that are next to each other. Based on the average luminance I get byte value from greyShadesArray with that index and save it to a byte array I return. It kinda works but not well enough. There are white lines and text is not readable: Converted image
Any suggestions on fixing it or other approaches are much appreciated!
Upvotes: 0
Views: 437
Reputation: 93834
Just a suggestion to use bit manipulation instead of concatenating and parsing Strings. It should be significantly faster, considering you're running this for every pixel in an image. You can use the repeat
function for more simply iterating a range where you don't need the iteration index variable. Also, there's a Color.luminance
utility function.
fun convertPictureToByteArray(bitmap: Bitmap): ByteArray {
val byteArray = ByteArray(15000)
var index = 0
var temp = 0
val pixels = IntArray(bitmap.width * bitmap.height)
bitmap.getPixels(pixels, 0, bitmap.width, 0, 0, bitmap.width, bitmap.height)
repeat(pixels.size / 8) {
var tempBinary = 0
repeat(8) {
tempBinary = (tempBinary shl 1) or Color.luminance(pixels[temp++]).roundToInt()
}
byteArray[index++] = tempBinary.toByte()
}
return byteArray
}
Upvotes: 0
Reputation: 1
As @Selvin suggested I should have checked each pixel by the treshold and converted the binary to hex/byte. Here is the working version:
fun convertPictureToByteArray(bitmap: Bitmap): ByteArray {
val byteArray = ByteArray(15000)
var index = 0
var temp = 0
val pixels = IntArray(bitmap.width * bitmap.height)
bitmap.getPixels(pixels, 0, bitmap.width, 0, 0, bitmap.width, bitmap.height)
for(x in (bitmap.height - 1) downTo 0) {
for(y in 0 until bitmap.width / 8) {
var tempBinary = ""
for(z in 0 until 8) {
val red = Color.red(pixels[temp])
val green = Color.green(pixels[temp])
val blue = Color.blue(pixels[temp])
val luminance = 0.299 * red + 0.587 * green + 0.114 * blue
if(luminance < 128)
tempBinary += "0"
else
tempBinary += "1"
temp++
}
val decimalValue = Integer.parseInt(tempBinary, 2)
val hexValue = decimalValue.toString(16).toUpperCase()
byteArray[index] = hexValue.toInt(16).toByte()
index++
}
}
return byteArray
}
Upvotes: 0