View Source Scenic.Assets.Stream.Bitmap (Scenic v0.11.2)

This module helps you to prepare images, in the form of a bitmap, that are to be streamed and displayed through the Scenic.Assets.Stream module.

A bitmap is a rectangular field of pixels. Each pixel can be addressed and assigned a color. When the bitmap is put into Scenic.Assets.Stream it becomes an image that can be displayed in a scene via Scenic.Primitive.Style.Paint.Stream.

committed-vs-mutable

Committed vs. Mutable

Bitmaps are interesting because a typical pattern is to change the color of many pixels in a rapid burst, then send the image up. The bitmaps can become quite large tho, so if we were to make a copy of it every time a single pixel was changed, that could become quite slow.

Unfortunately, writing a NIF that manipulates individual pixels quickly and without making a copy, breaks the immutable, functional model of Erlang/Elixir.

The compromise is that a Bitmap can be either in a "commited" state, which can be put into Scenic.Assets.Stream, but not changed, or in a "mutable" state, which can be manipulated rapidly, but not streamed to scenes.

When a new bitmap is built, it starts in the mutable state, unless the commit: true option is set.

alias Scenic.Assets.Stream.Bitmap

bitmap = Bitmap.build( :rgb, 20, 10, clear: :blue )
  |> Bitmap.put( 2, 3, :red )
  |> Bitmap.put( 9, 10, :yellow )
  |> Bitmap.commit()

Scenic.Assets.Stream.put( "stream_id", bitmap )

In the above example, a new bitmap is created, that can hold an rgb color in every pixel, is 20 pixels wide, 10 pixels high, and starts with the entire image set to the color :blue. The :commit option is not set, so it is mutable.

Then two of the pixels are set to other colors. One :red and the other :yellow.

Finally, the image is committed, making it usable, but no longer mutable. After the image is completed, it is sent to Scenic.Assets.Stream, which makes it available for use in a scene.

color-depth

Color Depth

Bitmaps can be one of four depths. Each consumes a different amount of memory per pixel. If you are running on a constrained memory device, or are worried about bandwidth when remoting the UI, then you should choose the depth that you actually use. If you have lots of memory, then :rgba is usually the fastest format.

DepthBytes per pixelNotes
:g1Simple Greyscale. 256 shades of grey
:ga2Greyscale plus an alhpa channel
:rgb3Red/Green/Blue Millions of colors
:rgba4Red/Green/Blue/Alpha

Link to this section Summary

Functions

Build a new bitmap with a given depth, width and height.

Set the color value of all pixels in a bitmap. This effectively erases the bitmap, replacing it with a solid field of the supplied color.

Change a bitmap from mutable to committed.

Get the color value of a single pixel in a bitmap.

Change a bitmap from committed to mutable.

Set the color value of a single pixel in a bitmap.

Set the color value of a single pixel in a bitmap using an offset from the start.

Link to this section Types

@type depth() :: :g | :ga | :rgb | :rgba
@type m() :: {:mutable_bitmap, meta :: meta(), data :: binary()}
@type meta() :: {width :: pos_integer(), height :: pos_integer(), depth :: depth()}
@type t() :: {Scenic.Assets.Stream.Bitmap, meta :: meta(), data :: binary()}

Link to this section Functions

Link to this function

build(format, width, height, opts \\ [])

View Source
@spec build(
  depth :: depth(),
  width :: pos_integer(),
  height :: pos_integer(),
  opts :: Keyword.t()
) :: t()

Build a new bitmap with a given depth, width and height.

Build creates a new bitmap in memory. It begins in a mutable state and will be set to transparent black unless the :clear option is specified.

The valid depths are :g, :ga, :rgb, :rgba as explained in the following table

DepthBytes per pixelNotes
:g1Simple Greyscale. 256 shades of grey
:ga2Greyscale plus an alhpa channel
:rgb3Red/Green/Blue Millions of colors
:rgba4Red/Green/Blue/Alpha

options

Options

  • :clear Set the new bitmap so that every pixel is the specified color.
  • :commit Set to true to start the bitmap committed. Set to false for mutable. The default if not specified is mutable.
@spec clear(mutable :: m(), color :: Scenic.Color.t()) :: mutable :: m()

Set the color value of all pixels in a bitmap. This effectively erases the bitmap, replacing it with a solid field of the supplied color.

Only works with mutable bitmaps.

The color you provide can be any valid value from the Scenic.Color module.

If the color you provide doesn't match the depth of the bitmap, this will transform the color as appropriate to fit. For example, putting an :rgb color into a :g (greyscale) bit map, will set the level of grey to be the average value of the red, green, and blue channels of the supplied color

@spec commit(mutable :: m()) :: texture :: t()

Change a bitmap from mutable to committed.

Committed bitmaps can be used by Scenic.Assets.Stream. They will not work with the put and clear functions in this module.

@spec get(t_or_m :: t() | m(), x :: pos_integer(), y :: pos_integer()) ::
  Scenic.Color.explicit()

Get the color value of a single pixel in a bitmap.

Works with either committed or mutable bitmaps.

@spec mutable(texture :: t()) :: mutable :: m()

Change a bitmap from committed to mutable.

This makes a copy of the bitmap's memory to preserve the Erlang model.

Mutable bitmaps are not usable by Scenic.Assets.Stream.

Link to this function

put(mutable, x, y, color)

View Source
@spec put(
  mutable :: m(),
  x :: pos_integer(),
  y :: pos_integer(),
  color :: Scenic.Color.t()
) ::
  mutable :: m()

Set the color value of a single pixel in a bitmap.

Only works with mutable bitmaps.

The color you provide can be any valid value from the Scenic.Color module.

If the color you provide doesn't match the depth of the bitmap, this will transform the color as appropriate to fit. For example, putting an :rgb color into a :g (greyscale) bit map, will set the level of grey to be the average value of the red, green, and blue channels of the supplied color

Link to this function

put_offset(mutable, offset, color)

View Source
@spec put_offset(mutable :: m(), offset :: pos_integer(), color :: Scenic.Color.t()) ::
  mutable :: m()

Set the color value of a single pixel in a bitmap using an offset from the start.

Only works with mutable bitmaps.

The color you provide can be any valid value from the Scenic.Color module.

Unlike the put function, which specifies the pixel by x and y position, put_offset takes an offset directly into the data.

The offset would be the same as y * width + x.