Class: EXIFR::TIFF

Inherits:
Object
  • Object
show all
Includes:
Enumerable
Defined in:
lib/exifr/tiff.rb

Overview

TIFF decoder

Date properties

The properties :date_time, :date_time_original, :date_time_digitized coerced into Time objects.

Orientation

The property :orientation describes the subject rotated and/or mirrored in relation to the camera. It is translated to one of the following instances:

  • TopLeftOrientation

  • TopRightOrientation

  • BottomRightOrientation

  • BottomLeftOrientation

  • LeftTopOrientation

  • RightTopOrientation

  • RightBottomOrientation

  • LeftBottomOrientation

These instances of Orientation have two methods:

  • to_i; return the original integer

  • transform_rmagick(image); transforms the given RMagick::Image to a viewable version

Examples

EXIFR::TIFF.new('DSC_0218.TIF').width           # => 3008
EXIFR::TIFF.new('DSC_0218.TIF')[1].width        # => 160
EXIFR::TIFF.new('DSC_0218.TIF').model           # => "NIKON D1X"
EXIFR::TIFF.new('DSC_0218.TIF').date_time       # => Tue May 23 19:15:32 +0200 2006
EXIFR::TIFF.new('DSC_0218.TIF').exposure_time   # => Rational(1, 100)
EXIFR::TIFF.new('DSC_0218.TIF').orientation     # => EXIFR::TIFF::Orientation

Defined Under Namespace

Classes: Data, Degrees, Field, GPS, IFD, Orientation

Constant Summary collapse

TAG_MAPPING =

:nodoc:

{}
IFD_TAGS =

:nodoc:

[:image, :exif, :gps]
ORIENTATIONS =

:nodoc:

[]
ADAPTERS =

:nodoc:

Hash.new { proc { |v| v } }
TAGS =

Names for all recognized TIFF fields.

[TAG_MAPPING.keys, TAG_MAPPING.values.map{|v|v.values}].flatten.uniq - IFD_TAGS

Class Attribute Summary collapse

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(file, load_thumbnails: true) ⇒ TIFF

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



378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
# File 'lib/exifr/tiff.rb', line 378

def initialize(file, load_thumbnails: true)
  Data.open(file) do |data|
    @ifds = [IFD.new(data)]
    while ifd = @ifds.last.next
      break if @ifds.find{|i| i.offset == ifd.offset}
      @ifds << ifd
    end

    if load_thumbnails
      @jpeg_thumbnails = @ifds.map do |v|
        if v.jpeg_interchange_format && v.jpeg_interchange_format_length
          start, length = v.jpeg_interchange_format, v.jpeg_interchange_format_length
          if Integer === start && Integer === length
            data[start..(start + length)]
          else
            EXIFR.logger.warn("Non numeric JpegInterchangeFormat data")
            nil
          end
        end
      end.compact
    else
      @jpeg_thumbnails = []
    end
  end
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(method, *args) ⇒ Object

Dispatch to first image.



420
421
422
423
424
425
426
427
428
429
430
# File 'lib/exifr/tiff.rb', line 420

def method_missing(method, *args)
  super unless args.empty?

  if @ifds.first.respond_to?(method)
    @ifds.first.send(method)
  elsif TAGS.include?(method)
    @ifds.first.to_hash[method]
  else
    super
  end
end

Class Attribute Details

.mktime_procObject

Callable to create a Time object. Defaults to proc{|*a|Time.local(*a)}.



247
248
249
# File 'lib/exifr/tiff.rb', line 247

def mktime_proc
  @mktime_proc
end

Instance Attribute Details

#jpeg_thumbnailsObject (readonly)

JPEG thumbnails



43
44
45
# File 'lib/exifr/tiff.rb', line 43

def jpeg_thumbnails
  @jpeg_thumbnails
end

Class Method Details

.instance_methods(include_super = true) ⇒ Object

:nodoc:



456
457
458
# File 'lib/exifr/tiff.rb', line 456

def instance_methods(include_super = true) # :nodoc:
  (instance_methods_without_tiff_extras(include_super) + TAGS + IFD.instance_methods(false)).uniq
end

.instance_methods_without_tiff_extrasObject



455
# File 'lib/exifr/tiff.rb', line 455

alias instance_methods_without_tiff_extras instance_methods

.rational(n, d) ⇒ Object



345
346
347
348
349
350
351
352
353
# File 'lib/exifr/tiff.rb', line 345

def self.rational(n, d)
  if d == 0
    n.to_f / d.to_f
  elsif Rational.respond_to?(:reduce)
    Rational.reduce(n, d)
  else
    n.quo(d)
  end
end

.round(f, n) ⇒ Object



355
356
357
358
# File 'lib/exifr/tiff.rb', line 355

def self.round(f, n)
  q = (10 ** n)
  (f * q).round.to_f / q
end

Instance Method Details

#[](index) ⇒ Object

Get index image.



415
416
417
# File 'lib/exifr/tiff.rb', line 415

def [](index)
  index.is_a?(Symbol) ? to_hash[index] : @ifds[index]
end

#eachObject

Yield for each image.



410
411
412
# File 'lib/exifr/tiff.rb', line 410

def each
  @ifds.each { |ifd| yield ifd }
end

#encode_with(coder) ⇒ Object



446
447
448
# File 'lib/exifr/tiff.rb', line 446

def encode_with(coder)
  coder["ifds"] = @ifds
end

#gpsObject

Get GPS location, altitude and image direction return nil when not available.



473
474
475
476
477
478
479
480
481
482
# File 'lib/exifr/tiff.rb', line 473

def gps
  return nil unless gps_latitude && gps_longitude

  altitude = gps_altitude.is_a?(Array) ? gps_altitude.first : gps_altitude

  GPS.new(gps_latitude.to_f * (gps_latitude_ref == 'S' ? -1 : 1),
          gps_longitude.to_f * (gps_longitude_ref == 'W' ? -1 : 1),
          altitude && (altitude.to_f * (gps_altitude_ref == "\1" ? -1 : 1)),
          gps_img_direction && gps_img_direction.to_f)
end

#heightObject

Convenience method to access image height.



465
# File 'lib/exifr/tiff.rb', line 465

def height; @ifds.first.height; end

#inspectObject

:nodoc:



484
485
486
# File 'lib/exifr/tiff.rb', line 484

def inspect # :nodoc:
  @ifds.inspect
end

#methods(regular = true) ⇒ Object

:nodoc:



438
439
440
441
442
443
444
# File 'lib/exifr/tiff.rb', line 438

def methods(regular=true) # :nodoc:
  if regular
    (super + TAGS + IFD.instance_methods(false)).uniq
  else
    super
  end
end

#respond_to?(method, include_all = false) ⇒ Boolean

:nodoc:

Returns:

  • (Boolean)


432
433
434
435
436
# File 'lib/exifr/tiff.rb', line 432

def respond_to?(method, include_all = false) # :nodoc:
  super ||
    (defined?(@ifds) && @ifds && @ifds.first && @ifds.first.respond_to?(method, include_all)) ||
    TAGS.include?(method)
end

#sizeObject

Number of images.



405
406
407
# File 'lib/exifr/tiff.rb', line 405

def size
  @ifds.size
end

#to_hashObject

Get a hash presentation of the (first) image.



468
# File 'lib/exifr/tiff.rb', line 468

def to_hash; @ifds.first.to_hash; end

#to_yaml_propertiesObject



450
451
452
# File 'lib/exifr/tiff.rb', line 450

def to_yaml_properties
  ['@ifds']
end

#widthObject

Convenience method to access image width.



462
# File 'lib/exifr/tiff.rb', line 462

def width; @ifds.first.width; end