0

I am trying to read the WebP image header, according to the WebP Container Specification of Extended File Format.

fun get24bit(data: ByteArray, index: Int): Int {
    return ((data[0 + index].toInt()) or (data[1 + index].toInt() shl 8) or (data[2 + index].toInt() shl 16))
}

fun get32bit(data: ByteArray, index: Int): Int {
    return get24bit(data, index) or (data[3 + index].toInt() shl 24)
}

// data -> File(fileName).readBytes() for testing purpose
fun webpExtract(data: ByteArray) {
    println(String(data.copyOfRange(0, 4)))
    println("Size: ${get32bit(data, 4)}")
    println(String(data.copyOfRange(8, 12)))
    println(String(data.copyOfRange(12, 16)))
    // 16, 17, 18, 19 reserved

    val width = 1 + get24bit(data, 20)
    val height = 1 + get24bit(data, 23)

    println("Width: $width, Height: $height")
}

And the outputs are:

RIFF
Size: -52
WEBP
VP8X
Width: 17, Height: 32513

The String outputs are alright, but the Size is getting negative and Width and Heights are wrong i.e. They should be 128 and 128 respectively (for the test image I've used).

Is there something wrong in the code? I am not able to figure out what's the problem.

I've also verified the actual C++ implementation here in github. My code does the same bit shifting, but the results are not correct. As far as I know, left shifting does not has anything to do with unsigned and signed right?

Animesh Sahu
  • 6,497
  • 2
  • 17
  • 41
  • consider this: https://stackoverflow.com/questions/38651192/how-to-correctly-handle-byte-values-greater-than-127-in-kotlin – 9dan Oct 27 '20 at 04:59
  • @9dan thanks, the size comes out to be correct (+ve value and correct), but the Width and Heights are still incorrect :( – Animesh Sahu Oct 27 '20 at 05:09
  • @AdamMillerchip [Spec](https://developers.google.com/speed/webp/docs/riff_container#terminology_basics) says it is in little endian order :^) – Animesh Sahu Oct 27 '20 at 06:01
  • Yeah I deleted the comment after reading that. It doesn't make sense that your width and height are different with the same code, so there must be something strange going on. It would be helpful if you could log out your `data` values (in binary) before you do the shifts. – Adam Millerchip Oct 27 '20 at 06:03
  • @AdamMillerchip I've took byte values and get24bit values till 50 index, I don't see much of a pattern, maybe you can help me https://gist.github.com/Animeshz/affe8c7e54c2949e33444be904e9bffa (this time I used 400x400 image ) . – Animesh Sahu Oct 27 '20 at 06:10
  • @AdamMillerchip Ah, I actually got it, the values of height and widths were at index 24 and 27... Verified using 3 different resolution images. – Animesh Sahu Oct 27 '20 at 06:14
  • yes, looking at ParseVP8X function from webp_dec.c, width is 'VP8X' after 8 offset, that is 24. – 9dan Oct 27 '20 at 06:25

1 Answers1

2

Don't know the Spec was incomplete or something, I logged the byte values and found a pattern somehow. And found that the dimensions are at 24-26 and 27-29 indexes.

val width = 1 + (get24bit(data, 24))
val height = 1 + (get24bit(data, 27))

This does the trick! Hopefully it is helpful to note this point as long as documentation is not updated.

Animesh Sahu
  • 6,497
  • 2
  • 17
  • 41