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.



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

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.



423
424
425
426
427
428
429
430
431
432
433
# File 'lib/exifr/tiff.rb', line 423

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)}.



250
251
252
# File 'lib/exifr/tiff.rb', line 250

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:



459
460
461
# File 'lib/exifr/tiff.rb', line 459

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



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

alias instance_methods_without_tiff_extras instance_methods

.rational(n, d) ⇒ Object



348
349
350
351
352
353
354
355
356
# File 'lib/exifr/tiff.rb', line 348

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



358
359
360
361
# File 'lib/exifr/tiff.rb', line 358

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

Instance Method Details

#[](index) ⇒ Object

Get index image.



418
419
420
# File 'lib/exifr/tiff.rb', line 418

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

#date_timeObject

File changed date time (with UTC offset when available).



488
489
490
# File 'lib/exifr/tiff.rb', line 488

def date_time
  date_time_with_zone(:date_time, :offset_time)
end

#date_time_digitizedObject

Date and time image digitized (with UTC offset when available).



499
500
501
# File 'lib/exifr/tiff.rb', line 499

def date_time_digitized
  date_time_with_zone(:date_time_digitized, :offset_time_digitized)
end

#date_time_originalObject

Date and time original image generated (with UTC offset when available).



494
495
496
# File 'lib/exifr/tiff.rb', line 494

def date_time_original
  date_time_with_zone(:date_time_original, :offset_time_original)
end

#eachObject

Yield for each image.



413
414
415
# File 'lib/exifr/tiff.rb', line 413

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

#encode_with(coder) ⇒ Object



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

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

#gpsObject

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



476
477
478
479
480
481
482
483
484
485
# File 'lib/exifr/tiff.rb', line 476

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.



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

def height; @ifds.first.height; end

#inspectObject

:nodoc:



503
504
505
# File 'lib/exifr/tiff.rb', line 503

def inspect # :nodoc:
  @ifds.inspect
end

#methods(regular = true) ⇒ Object

:nodoc:



441
442
443
444
445
446
447
# File 'lib/exifr/tiff.rb', line 441

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:



435
436
437
438
439
# File 'lib/exifr/tiff.rb', line 435

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.



408
409
410
# File 'lib/exifr/tiff.rb', line 408

def size
  @ifds.size
end

#to_hashObject

Get a hash presentation of the (first) image.



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

def to_hash; @ifds.first.to_hash; end

#to_yaml_propertiesObject



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

def to_yaml_properties
  ['@ifds']
end

#widthObject

Convenience method to access image width.



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

def width; @ifds.first.width; end