class EXIFR::JPEG

JPEG decoder

Examples

EXIFR::JPEG.new('IMG_3422.JPG').width         # -> 2272
EXIFR::JPEG.new('IMG_3422.JPG').exif.model    # -> "Canon PowerShot G3"

Attributes

app1s[R]

raw APP1 frames

comment[R]

comment; a string if one comment found, an array if more, otherwise nil

exif[R]

EXIF data if available

height[R]

image height

width[R]

image width

Public Class Methods

new(file) click to toggle source

file is a filename or an IO object. Hint: use StringIO when working with slurped data like blobs.

# File lib/exifr/jpeg.rb, line 31
def initialize(file)
  if file.kind_of? String
    File.open(file, 'rb') { |io| examine(io) }
  else
    examine(file.dup)
  end
end

Public Instance Methods

exif?() click to toggle source

Returns true when EXIF data is available.

# File lib/exifr/jpeg.rb, line 40
def exif?
  !exif.nil?
end
method_missing(method, *args) click to toggle source

Dispatch to EXIF. When no EXIF data is available but the method does exist for EXIF data nil will be returned.

Calls superclass method
# File lib/exifr/jpeg.rb, line 58
def method_missing(method, *args)
  super unless args.empty?
  super unless methods.include?(method.to_s)
  @exif.send method if defined?(@exif) && @exif
end
thumbnail() click to toggle source

Return thumbnail data when available.

# File lib/exifr/jpeg.rb, line 45
def thumbnail
  defined?(@exif) && @exif && @exif.jpeg_thumbnails && @exif.jpeg_thumbnails.first
end
to_hash() click to toggle source

Get a hash presentation of the image.

# File lib/exifr/jpeg.rb, line 50
def to_hash
  h = {:width => width, :height => height, :bits => bits, :comment => comment}
  h.merge!(exif) if exif?
  h
end

Private Instance Methods

examine(io) click to toggle source
# File lib/exifr/jpeg.rb, line 93
def examine(io)
  io = Reader.new(io)

  unless io.readbyte == 0xFF && io.readbyte == 0xD8 # SOI
    raise MalformedJPEG, "no start of image marker found"
  end

  @app1s = []
  while marker = io.next
    case marker
      when 0xC0..0xC3, 0xC5..0xC7, 0xC9..0xCB, 0xCD..0xCF # SOF markers
        length, @bits, @height, @width, components = io.readsof
        unless length == 8 + components * 3
          raise MalformedJPEG, "frame length does not match number of components"
        end
      when 0xD9, 0xDA;  break # EOI, SOS
      when 0xFE;        (@comment ||= []) << io.readframe # COM
      when 0xE1;        @app1s << io.readframe # APP1, may contain EXIF tag
      else              io.readframe # ignore frame
    end
  end

  @comment = @comment.first if defined?(@comment) && @comment && @comment.size == 1

  if app1 = @app1s.find { |d| d[0..5] == "Exif\0\0" }
    @exif_data = app1[6..-1]
    @exif = TIFF.new(StringIO.new(@exif_data))
  end
end