Package limn.graphics

Class Image

java.lang.Object
limn.graphics.Image

public final class Image extends Object
An immutable, backend-independent bitmap: RGBA8 pixels, straight (non premultiplied) alpha, row-major, row 0 at the top. Decoded once (see Images) and drawn via Canvas.drawImage(limn.graphics.Image, float, float, float, float); the GPU texture is created lazily by each window's renderer, so one Image works across multiple windows (whose GL contexts are not shared).

Object identity is the texture-cache key; reuse the same instance rather than decoding the same asset repeatedly. A window's cache holds on to the instance, and so to its pixels, for as long as it keeps the texture, which Images.setTextureBudget(long) bounds.

An image may be animated: isAnimated(), with frames that are each an image and a time each is shown for. Its own pixels are then those of its first frame, so whatever draws an image and knows nothing of animation draws a still picture. Nothing moves unless something plays it: an ImageView does, and limn.animation.ImageAnimation is what a widget of an application's own does it with.

  • Constructor Details

    • Image

      public Image(int width, int height, byte[] rgba)
      Parameters:
      width - pixels
      height - pixels
      rgba - width*height*4 bytes, straight alpha, top-down
  • Method Details

    • isAnimated

      public boolean isAnimated()
      Returns:
      whether this image has more than one frame, which something may play
    • frameCount

      public int frameCount()
      Returns:
      how many frames; 1 for a still image
    • frame

      public Image frame(int index)
      One frame, as a still image of this image's size: what is shown at that moment, whole, whatever the file built it from. The frame of a still image is the image. For a long animation that is decoded as it plays, a frame that is not in memory is decoded here, on the calling thread, and the frames before it with it: a player asks frameIfReady(int) instead.
      Parameters:
      index - from 0 to frameCount() - 1
      Returns:
      the frame; the same object each time for as long as it is kept in memory
      Throws:
      IndexOutOfBoundsException - if there is no such frame
    • frameIfReady

      public @Nullable Image frameIfReady(int index)
      One frame, if it is in memory now. A long animation is decoded as it plays, a few frames ahead of the one shown, and this is what a player asks instead of frame(int): it answers at once, and says that the frame and the ones after it are wanted. A frame that is not ready is not waited for; the player shows the one before until it is.
      Parameters:
      index - from 0 to frameCount() - 1
      Returns:
      the frame, or null while it is being decoded; never null for a still image, for an animation decoded whole, or for the first frame
      Throws:
      IndexOutOfBoundsException - if there is no such frame
    • frameMillis

      public int frameMillis(int index)
      Parameters:
      index - from 0 to frameCount() - 1
      Returns:
      how long that frame is shown at the animation's own speed, in milliseconds; 0 for a still image
      Throws:
      IndexOutOfBoundsException - if there is no such frame
    • durationMillis

      public long durationMillis()
      Returns:
      how long one turn of the animation takes, in milliseconds; 0 for a still image
    • loopCount

      public int loopCount()
      Returns:
      how many turns the animation asks for: 0 for one that does not end, which is also what a still image answers
    • width

      public int width()
      Returns:
      width in pixels
    • height

      public int height()
      Returns:
      height in pixels
    • pixels

      public byte[] pixels()
      Returns:
      the raw RGBA bytes (do not mutate)