Class: Gifenc::Extension::GraphicControl

Inherits:
Gifenc::Extension show all
Defined in:
lib/extensions.rb

Overview

This extension precedes a single image and controls several of its rendering charactestics, such as its duration and the transparent color index. A complete description, mostly adapted from the specification, follows:

  • Disposal method (3 bits): Indicates in which way should be image be disposed of before displaying the next one.
    • 0 - No disposal specified. This image will be fully replaced by the next one without transparency.
    • 1 - Do not dispose. The image will remain onscreen, and the next one will be drawn on top, with the old one showing through the transparent pixels of the new one.
    • 2 - Restore to background color. The image will be fully replaced by the background color, over which the next image will be drawn.
    • 3 - Restore to previous. The previous undisposed image will be restored, and the next one will be drawn over it. Useful for animating over a fixed background.
    • 4-7 - Undefined.
  • User input flag (1 bit): Indicates whether or not user input is required before continuing with the next image in the GIF. The nature of the User input is determined by the application (Carriage Return, Mouse Button Click, etc.).
    • 0 - User input is not expected.
    • 1 - User input is expected.
  • Transparency flag (1 bit): Indicates whether or not a color will be specified in the Transparent Index field as the transparent color.
    • 0 - Transparent Index is not given.
    • 1 - Transparent Index is given.
  • Delay Time (2 bytes): If not 0, this field specifies the number of hundredths (1/100) of a second to wait before continuing with the processing of the Data Stream. The clock starts ticking immediately after the graphic is rendered. This field may be used in conjunction with the User Input Flag field.
  • Transparency Index (1 byte): The Transparency Index is such that when encountered, the corresponding pixel of the display device is not modified and processing goes on to the next pixel. This is done if and only if the Transparency Flag is set to 1.

Note that, in reality, most software does not perfectly conform to this standard. Notably, the user input flag is mostly ignored, and very small delays are changed to a higher value (see #delay). Also, disposal methods 2 and 3 are sometimes not supported either.

Constant Summary collapse

LABEL =

Label identifying a Graphic Control Extension block.

"\xF9".freeze

Constants inherited from Gifenc::Extension

EXTENSION_INTRODUCER

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods inherited from Gifenc::Extension

#encode

Constructor Details

#initialize(delay: DEFAULT_DELAY, disposal: DEFAULT_DISPOSAL, trans_color: nil, user_input: DEFAULT_USER_INPUT) ⇒ GraphicControl

Create a new Graphic Control Extension associated to a particular image.

Parameters:

  • delay (Integer) (defaults to: DEFAULT_DELAY)

    Number of 1/100ths of a second (0-65535) to wait before rendering next image in the GIF file. Beware that most software does not support ultra fast GIFs (see #delay).

  • disposal (Integer) (defaults to: DEFAULT_DISPOSAL)

    The disposal method (0-7) indicates how to dispose of this image before displaying the next one (see #disposal).

  • trans_color (Integer) (defaults to: nil)

    Color table index (0-255) of the color that should be used as the transparent color. The transparent color maintains whatever color was present in that pixel before rendering this image (see #trans_color).

  • user_input (Boolean) (defaults to: DEFAULT_USER_INPUT)

    Whether or not user input is expected to continue rendering the subsequent GIF images (mostly deprecated flag).



129
130
131
132
133
134
135
136
137
138
139
140
141
# File 'lib/extensions.rb', line 129

def initialize(
    delay:        DEFAULT_DELAY,
    disposal:     DEFAULT_DISPOSAL,
    trans_color:  nil,
    user_input:   DEFAULT_USER_INPUT
  )
  super(LABEL)

  @disposal     = (0..7).include?(disposal) ? disposal : DEFAULT_DISPOSAL
  @user_input   = user_input
  @delay        = (0..0xFFFF).include?(delay) ? delay : DEFAULT_DELAY
  @trans_color  = (0..0xFF).include?(trans_color) ? trans_color : nil
end

Instance Attribute Details

#delayInteger

Specifies the time, in 1/100ths of a second, to leave this image onscreen before moving on to rendering the next one in the GIF. Must be between 0 and 65535. If 0, processing of the GIF should continue immediately. In reality, however, programs almost never comply with this standard, and instead normalize very small delays up to a certain, slower value. For instance, in most browsers, values smaller than 2 (i.e. 0 and 1) will be changed to 10, resulting in the fastest possible speed being attained with a delay of 2 (20ms, or 50fps).

Returns:

  • (Integer)

    Time to leave image onscreen.



81
82
83
# File 'lib/extensions.rb', line 81

def delay
  @delay
end

#disposalInteger

The disposal method (0-3) to use for this image before displaying the next one.

  • 0 : No disposal specified. This image will be fully replaced by the next one without transparency.
  • 1 : Do not dispose. The image will remain onscreen, and the next one will be drawn on top, with the old one showing through the transparent pixels of the new one.
  • 2 : Restore to background color. The image will be fully replaced by the background color, over which the next image will be drawn.
  • 3 : Restore to previous. The previous undisposed image will be restored, and the next one will be drawn over it. Useful for animating over a fixed background.

Note that support for all disposal methods might be incomplete in some pieces of software. The most limited programs only support method 1.

Returns:

  • (Integer)

    Disposal method.



99
100
101
# File 'lib/extensions.rb', line 99

def disposal
  @disposal
end

#trans_colorInteger

Index in the color table of the color to render as transparent. If specified, the transparency flag in the GIF will be set by default. Whatever is in the background (e.g. the background color, or a previous frame, see #disposal) will the show through the transparent pixels of the current image. To disable transparency, simply set this to nil.

Returns:

  • (Integer)

    Index of transparent color.



107
108
109
# File 'lib/extensions.rb', line 107

def trans_color
  @trans_color
end

#user_inputBoolean

Note:

This flag is ignored by most decoders nowadays, instead just displaying all images continuously according to the delay.

Whether or not user input is required to continue onto the next image.

Returns:

  • (Boolean)

    User input flag.



113
114
115
# File 'lib/extensions.rb', line 113

def user_input
  @user_input
end

Instance Method Details

#bodyString

Encode the extension block as a 6-byte binary string, as it will appear in the actual GIF file.

Returns:

  • (String)

    The encoded extension block.



146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
# File 'lib/extensions.rb', line 146

def body
  # Packed flags
  flags = [
    (0                               & 0b111) << 5 |
    ((@disposal || DEFAULT_DISPOSAL) & 0b111) << 2 |
    ((@user_input    ? 1 : 0)        & 0b1  ) << 1 |
    ((!!@trans_color ? 1 : 0)        & 0b1  )
  ].pack('C'.freeze)
  trans_color = !@trans_color ? DEFAULT_TRANS_COLOR : @trans_color

  # Main params
  str = "\x04"                          # Block size (always 4 bytes)
  str << flags                          # Packed fields
  str << [@delay].pack('S<'.freeze)     # Delay time
  str << [trans_color].pack('C'.freeze) # Transparent index
  str << BLOCK_TERMINATOR

  str
end

#dupGraphicControl

Create a duplicate copy of this graphic control extension.

Returns:



168
169
170
171
172
173
174
175
# File 'lib/extensions.rb', line 168

def dup
  GraphicControl.new(
    delay:       @delay,
    disposal:    @disposal,
    trans_color: @trans_color,
    user_input:  @user_input
  )
end