2

I have a program which is trying to set values in ImageData represented as a Uint8ClampedArray in a Kotlin program. According to the specification for the set method, I need to pass a Kotlin byte into the array, but Kotlin bytes are signed:

    ...create context...
    //setup pix as a js Uint8ClampedArray
    val imgd = context.createImageData(100.0, 100.0)
    val pix = imgd.data   //pix is now a Uint8ClampedArray

    //sets pix[40] to 127
    pix[40] = 127
    //gives an error - Kotlin bytes are signed, so it cannot be passed as a literal
    pix[40] = 200
    //also doesn't work, still converts to a signed byte
    pix[40] = 200.toByte()

My problem with this is that Javascript will read this as only 127, not 255. How can I set values of this array to be greater than 127? I can't even find a hack-y way to make the JS result read what I want, because ultimately the assignment needs a signed byte which doesn't allow for values greater than 127.

2 Answers2

4

I figured it out! You can do an unsafe cast of the UInt8 array to a UInt16 array, then use that instead, and javascript seems to figure out what you mean:

    //instead of val pix = imgd.data
    val pix = imgd.data.unsafeCast<Uint16Array>()
    // now you can assign values outside the -127..127 range
2

There is an issue in the Kotlin tracker — https://youtrack.jetbrains.com/issue/KT-24583

org.khronos.webgl.Uint8ClampedArray getter and setter declarations use Byte. Which means assigning values over 127 to it is not trivial. Also the values obtained from it violate the Byte contract

Besides one could argue that it is not a "real" array. Assigning values outside of 0..255 range is completely normal for it.

This case is important, because it is used for the canvas manipulation: https://developer.mozilla.org/en-US/docs/Web/API/ImageData/data

vanyochek
  • 815
  • 4
  • 10