Bigarray to image (data uri compatible)

Hi,
I’m working on a project where I have to produce an image from a bigarray of pixels. Then, this image is used in a src html field as data. See the following example:

<img src="data:image/<type>;base64,<data_content> />

The type must be compatible with MIME type.

I tried to find a library that allows me to produce such data but I can’t find one to do what I want. The only one that suits is imagelib but there isn’t a release with the function I need. I use js_of_ocaml so I can’t use bindings…

Does someone have already encounter the problem and may have another solution ?

I suspect you are going to tell me I can’t use canvas ;–) but: take your bigarray draw it on a 2D canvas element and use the toDataURL function.

Now if you can’t use canvas because you are in a webworker but can choose the <type> and you are willing to let that be image/png then it’s quite easy to devise your own wasteful (doesn’t compress) encoder, see this old caml-list discussion. You can find the code mentioned in this message on archive.org.

Use that to produce bytes and then use the browser btoa and you are done.

1 Like

JavaScript supports this natively by calling toDataURL on a canvas element. The canvas can be filled by using putImageData. js_of_ocaml provides bindings for most of these APIs, including conversion of Bigarray to JavaScript’s typed arrays (without copying, by the way!).

Something like this should do the trick:

open Js_of_ocaml

let base64_of_bigarray b width height =
  let canvas = Dom_html.createCanvas Dom_html.document in
  canvas##.width := width;
  canvas##.height := height;
  let context = canvas##getContext Dom_html._2d_ in
  let image_data = context##createImageData width height in
  let data = image_data##.data in
  let buffer: Typed_array.arrayBuffer Js.t = Js_of_ocaml.Js.Unsafe.get data "buffer" in
  let dst = new%js Typed_array.uint8Array_fromBuffer buffer in
  let src = Typed_array.Bigstring.to_uint8Array b in
  dst##set_fromTypedArray src 0;
  context##putImageData image_data 0. 0.;
  canvas##toDataURL_type (Js.string "image/png")
3 Likes

Thanks for your replies.
Indeed, @dbuenzli, I can’t use canvas :slight_smile: Thanks for the link, I will take a look at this method: it can support both Javascript and native code.

@copy I see that my question wasn’t complete. I apologize for this. I forgot to mention that I can’t use js_of_ocaml code only. My code will be compile to naive and js code so it must be functionalities usable both.

Why don’t you use the pure ocaml implementation of the PNG format that is available in imagelib? (this is not a binding). You say that there is not “the function you need”, what is this function that you need? If you have problems with PNG, have you tryed the BMP? What kind of images is it? logo, charts, pictures? If it’s logo or charts, you can probably use SVG instead.

The PNG ocaml module doesn’t allow me to export the array of pixels as a byte sequence.
The function I was talking about is png_to_bytes. It’s always the same problem, I do not have a library to produce a data uri from an array of pixels.

The solution I have made, use virtual libraries and build two distinct things: one in the navigator and the other in the cli app.

Why don’t you add this missing function png_to_bytes to the lib? imglib is open source, you can modify it to adapt it to your needs. Is there a technical difficulty? Maybe we can help you to resolve it?

This function already exists in the library but in the master branch (code) and not in the opam repository. The maintainer can’t do a release (issue). Furthermore, I have a compatibility problem with the decompress version used by imagelib and the version needed by my project…

Using virtual libraries solved my problem. So, it’s not a problem anymore in my case. Nevertheless, thanks for your help proposition @ffcm :slight_smile:

Documentation for the new version is now live at: https://rlepigre.github.io/ocaml-imagelib/imagelib/index.html

The release PR is pending approval in the opam-repository and should be available soon for fruition

2 Likes