# How to display an array of UInt8 as a color image

**URL:** <https://discourse.julialang.org/t/how-to-display-an-array-of-uint8-as-a-color-image/93990>\
**Category:** Visualization\
**Created:** [February 3, 2023, 2:05pm UTC](https://discourse.julialang.org/t/how-to-display-an-array-of-uint8-as-a-color-image/93990 "2023-02-03T14:05:22Z")\
**Posts on this page:** 9\
**Page:** 1

<div class="post-metadata">

**Author:** ![Tetane](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tetane/32/46516_2.png) [@Tetane](https://discourse.julialang.org/u/Tetane)\
**Post date:** [February 3, 2023, 2:05pm UTC](https://discourse.julialang.org/t/how-to-display-an-array-of-uint8-as-a-color-image/93990/1 "2023-02-03T14:05:22Z")

</div>

I have a color image represented by an array of `UInt8` of size `(58638, 22376, 3)` that I want to display using `imshow` from the `ImageView` package. The `RGB` channels are contained in the third dimension of the array. I understand that for representing color images in Julia there is an `RGB` type and also a `N0f8` type for value between 0 and 255 which seems to be what I’m looking for.  
I tried using `colorview` to change the type of my array to `N0f8` but that didn’t work.

What is the easiest way to display my array as a color image? (Why the `imshow` function can’t just take my array and understand that if it has three dimensions, it is a color image, and display it directly?)

---

<div class="post-metadata">

**Author:** ![stillyslalom](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stillyslalom/32/45687_2.png) [@stillyslalom](https://discourse.julialang.org/u/stillyslalom)\
**Post date:** [February 3, 2023, 2:36pm UTC](https://discourse.julialang.org/t/how-to-display-an-array-of-uint8-as-a-color-image/93990/2 "2023-02-03T14:36:05Z")

</div>

ImageView.jl was largely written by a neuroscientist, so it’s written to work well with 3D magnetic resonance images. Julia’s image array convention puts each color channel into a single structure so each pixel’s values are adjacent in memory, rather than spaced out along the third dimension as in your image. To convert between these conventions, you can use `permutedims` to re-order the image’s axes, or `PermutedDimsArray` if you want to re-order ‘lazily’ (by recalculating indices on the fly rather than copying). There’s a good example in the [docs](https://juliaimages.org/latest/tutorials/conversions_views/#Composing-views-(and-compact-summaries)), but briefly:

```julia
julia> img = rand(N0f8, 58638, 22376, 3);

julia> img_perm = colorview(RGB, normedview(PermutedDimsArray(img, (3,1,2))));

julia> imshow(img_perm)

```

That’s a rather large image, so unless you’re zooming way in, you may want to [shrink](https://juliaimages.org/ImageTransformations.jl/dev/reference/#ImageTransformations.imresize) it before displaying.

---

<div class="post-metadata">

**Author:** ![barucden](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/barucden/32/26154_2.png) [@barucden](https://discourse.julialang.org/u/barucden)\
**Post date:** [February 3, 2023, 2:57pm UTC](https://discourse.julialang.org/t/how-to-display-an-array-of-uint8-as-a-color-image/93990/3 "2023-02-03T14:57:06Z")

</div>

> Why the `imshow` function can’t just take my array and understand that if it has three dimensions, it is a color image, and display it directly?

Try answering these questions:

- What is the value range of an image represented by `Array{Float64, 3}`? (I’ve seen images with values from `0:255`, `0:1`, `-1:-1`, or `0:65536`, all of which would fit in a `Float64`)
- What is the color space of `Array{Float64, 3}`? (RGB is not the only 3-channel color space)
- Does array of shape `(H, W, 3)` represent one 3-channel image of size `H×W` or three 1-channel images of size `H×W`?
- Assuming an array of shape `(3, 3, 3)`, which dimension corresponds to the image channels?

I believe you can spot ambiguities. A way to reduce them is to introduce types, which is what the Julia image ecosystem did.

---

<div class="post-metadata">

**Author:** ![Tetane](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tetane/32/46516_2.png) [@Tetane](https://discourse.julialang.org/u/Tetane)\
**Post date:** [February 3, 2023, 3:20pm UTC](https://discourse.julialang.org/t/how-to-display-an-array-of-uint8-as-a-color-image/93990/4 "2023-02-03T15:20:05Z")

</div>

Ok, thank you, it works !  
Indeed, my image is big and the performance is not good. Is there a package to display very big images with good performance when zooming and panning? (Should I create another post with this question?)

---

<div class="post-metadata">

**Author:** ![Tetane](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tetane/32/46516_2.png) [@Tetane](https://discourse.julialang.org/u/Tetane)\
**Post date:** [February 3, 2023, 3:25pm UTC](https://discourse.julialang.org/t/how-to-display-an-array-of-uint8-as-a-color-image/93990/5 "2023-02-03T15:25:15Z")

</div>

Ok, thank you, I understand the issue here. I guess it is a balance between user-friendliness and robustness of the program. And maybe I’m just too used to using Matlab which is very user-friendly.

---

<div class="post-metadata">

**Author:** ![joa-quim](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/joa-quim/32/227_2.png) [@joa-quim](https://discourse.julialang.org/u/joa-quim)\
**Post date:** [February 3, 2023, 4:37pm UTC](https://discourse.julialang.org/t/how-to-display-an-array-of-uint8-as-a-color-image/93990/6 "2023-02-03T16:37:43Z")

</div>

It’s not unreasonable to expect that a function made to deal with images interprets a MxNx3 uint8 array as an image. For example in GMT this will plot you an image with random colors

```julia
imshow(rand(UInt8,64,64,3))

```

But this makes ofc many assumptions, namely that the image layout is band interleaved.

The problem of the image size is a very different thing. No software will show you all of those pixels, even if it, and the machine were it runs, can hold them all in memory. The solution here is to only load the chunk that is needed when doing a zoom, and to load only a decimated version of the full image when displaying it all. The GeoTIFF format lets us have an image with pyramid layers and it’s up to the software/users to decide what layer to load. I think ArcgGDAL can deal with situations like this (GMT can too but it’s not ironed up in this regard to deal with it smoothly).

---

<div class="post-metadata">

**Author:** ![stillyslalom](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stillyslalom/32/45687_2.png) [@stillyslalom](https://discourse.julialang.org/u/stillyslalom)\
**Post date:** [February 3, 2023, 4:39pm UTC](https://discourse.julialang.org/t/how-to-display-an-array-of-uint8-as-a-color-image/93990/7 "2023-02-03T16:39:49Z")

</div>

You’re pushing up against the limits of a lot of hardware here - your image is ~4 GB, and if those values are converted internally to `Float32` (as is the case for many GPU-based plotting libraries), that’ll take you to ~16 GB, which is larger than the memory of almost all consumer GPUs. GLMakie may be capable of doing this in principle (see [here](https://docs.makie.org/stable/documentation/faq/index.html#dimensions_too_large)), but I don’t know about in practice on your hardware - mine was unable to handle it. @sdanisch ?

---

<div class="post-metadata">

**Author:** ![Tetane](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tetane/32/46516_2.png) [@Tetane](https://discourse.julialang.org/u/Tetane)\
**Post date:** [February 6, 2023, 9:55am UTC](https://discourse.julialang.org/t/how-to-display-an-array-of-uint8-as-a-color-image/93990/8 "2023-02-06T09:55:22Z")

</div>

I was thinking of a solution like what Matlab is doing to plot images. Matlab only takes the pixels needed for the plot at the current zoom, by decimating the image. So there is no interpolation, but it’s very fast and there is nothing more loaded in RAM or on GPU memory.  
Using OpenGL based plotting systems, I was limited by the maximum texture size ~(32000, 32000) on my GPU, so the solution (in your link) of tiling textures seems to be a nice workaround. (On the computer I use to process those big rasters, there is a GPU with 24Go of memory.)

---

<div class="post-metadata">

**Author:** ![stevengj](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stevengj/32/71_2.png) [@stevengj](https://discourse.julialang.org/u/stevengj)\
**Post date:** [February 6, 2023, 1:30pm UTC](https://discourse.julialang.org/t/how-to-display-an-array-of-uint8-as-a-color-image/93990/9 "2023-02-06T13:30:50Z")

</div>

> [@Tetane](#):
>
> I was thinking of a solution like what Matlab is doing to plot images. Matlab only takes the pixels needed for the plot at the current zoom, by decimating the image.

See the discussion here: [Plotting image data in Julia is much slower than MATLAB](https://discourse.julialang.org/t/plotting-image-data-in-julia-is-much-slower-than-matlab/79660)

It’s pretty easy to do a downsampling call yourself, and there are packages like [InteractiveViz.jl](https://github.com/org-arl/InteractiveViz.jl) that will do it for you.
