How to use `Dom_html.get_pixel`

Hi all!

I’m trying to do the exercise at the end of the gaffiti tutorial (https://ocsigen.org/tuto/6.4/manual/application), namely be able to pick a color from the drawing instead of the color picker.

It is advised to use the Dom_html.get_pixel function. The doc I’ve found here https://ocsigen.org/js_of_ocaml/3.1.0/api/Dom_html#VALpixel_get did not help me a lot.

  • how do we build a canvasPixelArray Js.t
  • What is the purpose of the int argument in canvasPixelArray Js.t -> int -> int? Select the channel?
1 Like

Hi Sebbes !
Nice if you came through that tutorial until there.
It seems that js canvasPixelArray are monodimentional objects. You can see it with the fact that Class type Dom_html.canvasPixelArray have only one method called length. Get_pixel is a js binding to “low_level” js code that would get the color value (between 0 and 255) of the nth element of a js canvasPixelArray. Value mod 4 gives you the channel:

  • 0 : red
  • 1 : green
  • 2 : blue
  • 3 : alpha

The first answer here describes well how one does pixel manipulation in js, which clarifies what get_pixel is doing in ocaml.
Although there is almost no documentation, I find useful to browse js_of_ocaml api to see if I have to look in the js world to find what is doing some function: here it is in case it can help you too.

[EDIT] It seems you can get a canvasPixelArray with data method of a Dom_html.imageData, but maybe I tell something completely silly there… (second link suggest you would have to create/find a Canvas, get a Context out of it, then get its ImageData, and finally get its canvasPixelArray through data method) If someone has insights on it, her or his answer would be likely to be helpful !

Good luck :wink:

2 Likes

Thanks Ruyblast for your answer, it helps a lot!

I’ve succeeded to get the “data” from the image, but it is not a bare JS array, so the following makes the compiler crying:

    let data =ctx##(getImageData (float_of_int x1) (float_of_int y1) 1. 1.)##.data in
    let r, g, b =
             ( Js_of_ocaml.Js.array_get data 0
             , Js_of_ocaml.Js.array_get data 1
             , Js_of_ocaml.Js.array_get data 2
             )

How can I convert the data to an Array or acces to the fields I want?

You are welcome !
What is your compiler error ? What about

let data =ctx##(getImageData (float_of_int x1) (float_of_int y1) 1. 1.)##.data in
let r, g, b = Js_of_ocaml.Dom_html.(
               pixel_get  data 0
             , pixel_get  data 1
             , pixel_get  data 2
             )
2 Likes

:tada: Victory! Thank you very much Ruyblast! Indeed, I should have read the compiler message more carefully, it was speaking about the canvasPixelArray type!

1 Like

Great ! I found it quite tricky at first to use Js_of_ocaml, because I had to handle weird js world through a huge (and so intimidating) typed api. But to me once you get the logic through practice, you get the nice property that your code does actually something (and likely meaningful) when it compiles.
To me the effort worth it, because ocaml is so much powerful compared to a lot of alternatives. For web dev I find it great.
Keep going and see you next time !

Well, I’m coming from the elm world, and I’ve never encountered such a pain, while having the same moto “when it compiles, it works”…

The philosophy is quite different still: the idea is to define a totally new semantic, abstracting away the js garbage behind a very nice API. It only works on frontend however. Having the same types & functions server side and in the browser is quite exciting, that’s why I give a shot to Ocsigen!

Yes Elm is really good, I tried it too and I love it. I think Ocaml won’t be as easy to use on the front end. If you are familiar with Elm, maybe consider keeping with it and using ocsigen for the back-end (there is an ocsigen tutorial for setting up an api provider). Anyway, both strategies have there advantages and downsides, it is a good idea to explore to make yourself an opinion on this !