Package limn.graphics

Class GifEncoder

java.lang.Object
limn.graphics.GifEncoder
All Implemented Interfaces:
ImageEncoder

public final class GifEncoder extends Object implements ImageEncoder
The built-in GIF encoder: an animated image with every frame, each with its time, and the turns it asks for; a still image as one picture. Installed when Images loads, after PngEncoder, and here by name for an application that emptied the encoders and wants this one back: Images.installEncoder(GifEncoder.INSTANCE).

A GIF holds 256 colours, one of which stands for a pixel that is not there. A picture of more is written in the ones that stand for it best, chosen once for a whole animation and with no dithering, and a pixel less than half there is written as not there. The quality asked for is not used: there is nothing in the format for it to turn.

  • Field Details

    • INSTANCE

      public static final ImageEncoder INSTANCE
      The one instance; it holds no state.
  • Method Details

    • name

      public String name()
      Description copied from interface: ImageEncoder
      A short, stable, lower-case identifier used in diagnostics. It appears in the failure raised when nothing accepts a request, which is the only way anyone finds out which encoders existed and in what order they were consulted.

      It carries no meaning and nothing may branch on it; the wrong edit this prevents is a comparison against a literal name somewhere on a control-flow path, which would put one encoder's identity into logic that is supposed to be encoder-neutral.

      Deliberately without a default: deriving it from the implementing class produces an unreadable synthetic name for a lambda or an anonymous class, in exactly the message that exists to be readable.

      Specified by:
      name in interface ImageEncoder
      Returns:
      the identifier, never null and never blank
    • supports

      public boolean supports(ImageEncodeOptions options)
      Description copied from interface: ImageEncoder
      Whether this encoder will take options: the whole request, not just the format, so an encoder that supports a format only over part of the quality range can decline the rest instead of silently rounding it.

      Cheap and honest, and it must never throw: it runs on the caller's thread, once per installed encoder, every time anything is encoded, and one encoder that throws here makes the probe unusable for every encoder behind it.

      Declaring support is the whole reason this method exists. An encoder that claims a format it cannot fully represent (alpha into a format without an alpha channel, say) must decline rather than accept and drop the channel: a caller who is refused can choose another format, whereas a caller handed a degraded file finds out when someone looks at it.

      Deliberately without a default, because both possible defaults are wrong: claiming everything destroys the ordering, and claiming nothing makes an encoder that forgot to override it silently unreachable.

      Specified by:
      supports in interface ImageEncoder
    • encode

      public void encode(Image image, ImageEncodeOptions options, OutputStream out) throws IOException
      Description copied from interface: ImageEncoder
      Writes image to out in the requested format. Called only after ImageEncoder.supports(limn.graphics.ImageEncodeOptions) returned true for the same options. Does not close out and does not flush it; the caller owns the stream.

      Orientation is not this method's business: image is top-down (row 0 at the top) by Image's contract and every format this writes is defined against that same order. The wrong edit this prevents is "correcting" the row order here to match a GL framebuffer's bottom-up layout; the flip belongs to whatever read those pixels back (see ReadableSurface), and a second flip here would cancel it for one path and not the other, producing an upside-down file with no other symptom.

      Alpha is straight, never premultiplied, likewise by Image's contract.

      The same image and the same options must produce the same bytes. Determinism is what makes an exported file comparable against a checked-in reference; an encoder that stamps a timestamp, a producer string or a random seed into its output breaks every such test.

      Specified by:
      encode in interface ImageEncoder
      Throws:
      IOException - if out fails