Class: FormatParser::GIFParser
- Inherits:
-
Object
- Object
- FormatParser::GIFParser
- Includes:
- IOUtils
- Defined in:
- lib/parsers/gif_parser.rb
Constant Summary collapse
- HEADERS =
['GIF87a', 'GIF89a'].map(&:b)
- NETSCAPE_AND_AUTHENTICATION_CODE =
'NETSCAPE2.0'
Instance Method Summary collapse
Methods included from IOUtils
Instance Method Details
#call(io) ⇒ Object
7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 |
# File 'lib/parsers/gif_parser.rb', line 7 def call(io) io = FormatParser::IOConstraint.new(io) header = safe_read(io, 6) return unless HEADERS.include?(header) w, h = safe_read(io, 4).unpack('vv') gct_byte, _bgcolor_index, _pixel_aspect_ratio = safe_read(io, 5).unpack('Cvv') # and actually onwards for this: # http://www.matthewflickinger.com/lab/whatsinagif/bits_and_bytes.asp # Determine how big our color table is has_gct = gct_byte[0] == 1 bytes_per_color = gct_byte >> 6 unpacked_radix = gct_byte & 0b00000111 num_colors = 2**(unpacked_radix + 1) gct_table_size = num_colors * bytes_per_color # If we have the global color table - skip over it safe_read(io, gct_table_size) if has_gct # Now it gets interesting - we are at the place where an # application extension for the NETSCAPE2.0 block will occur. # If it does, it most likely means the application that wrote the # GIF needed looping, and if it did, it means that the GIF is # very, very likely to be animated. To read the actual animation # we need to skip over actual image data frames, which, in case # of our paged reads, will incur potentially_netscape_app_header = safe_read(io, 64) is_animated = potentially_netscape_app_header.include?(NETSCAPE_AND_AUTHENTICATION_CODE) FormatParser::Image.new( format: :gif, width_px: w, height_px: h, has_multiple_frames: is_animated, color_mode: :indexed, ) end |