I'm developping a proprietary printer service and after Android's PrinterManager created the pdf file, I render the bitmap and I have to convert a 24 BPP image in a 1 BPP image to send it to the printer. I noted that first print is systematically very very long compared to subsequent ones, so I analysed the code and discovered that the time is mainly spent in the the following loop:
val startWhile = System.nanoTime()
while (row < height) {
var imgByte: Byte = 0
var bit = 7
for (i in start..end step 1) {
// Not strictly exact as I assume that every color has the same 'weight' which is not the reality but after all, it depends on the usage
// For example, according to CIE709 recommandation, the test should be:
// if ((pixels[i] * 0.2125 + pixels[i] * 0.7154 + pixels[i] * 0.0721) < 128) {
if (((pixels[i] and 0xFF) + ((pixels[i] shr 8) and 0xFF) + ((pixels[i] shr 16) and 0xFF)) / 3 < 128) { // 0xAA000000 black to 0xAAFFFFFF white AA is transparency value.
imgByte = imgByte or (1 shl bit).toByte()
}
if (bit <= 0) {
bytes[b++] = imgByte
bit = 7
imgByte = 0
} else {
bit--
}
}
if (bit != 7) { // loop interrupted before end of byte
bytes[b++] = imgByte
}
row++
end += width
start += width
}
Log.d(TAG, "+++++ Conversion time 24 BPP to 1 BPP: ${(System.nanoTime() - startWhile) / 1000000L} ms")
According to the log, first execution of the complete while loops (so first complete conversion to 24BPP to 1BPP) is executed in about 11.000 ms, and subsequents one are executed in 11 ms. I suspect some kind of precompilation of code.
Why?