Class: MiniMagick::Image::Info

Inherits:
Object
  • Object
show all
Defined in:
lib/mini_magick/image/info.rb

Constant Summary collapse

ASCII_ENCODED_EXIF_KEYS =
%w[ExifVersion FlashPixVersion]

Instance Method Summary collapse

Constructor Details

#initialize(path) ⇒ Info

Returns a new instance of Info.



7
8
9
10
# File 'lib/mini_magick/image/info.rb', line 7

def initialize(path)
  @path = path
  @info = {}
end

Instance Method Details

#[](value, *args) ⇒ Object



12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
# File 'lib/mini_magick/image/info.rb', line 12

def [](value, *args)
  case value
  when "format", "width", "height", "dimensions", "size", "human_size"
    cheap_info(value)
  when "colorspace"
    colorspace
  when "mime_type"
    mime_type
  when "resolution"
    resolution(*args)
  when "signature"
    signature
  when /^EXIF\:/i
    raw_exif(value)
  when "exif"
    exif
  when "details"
    details
  else
    raw(value)
  end
end

#cheap_info(value) ⇒ Object



39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
# File 'lib/mini_magick/image/info.rb', line 39

def cheap_info(value)
  @info.fetch(value) do
    format, width, height, size = self["%m %w %h %b"].split(" ")

    path = @path
    path = path.match(/\[\d+\]$/).pre_match if path =~ /\[\d+\]$/

    @info.update(
      "format"     => format,
      "width"      => Integer(width),
      "height"     => Integer(height),
      "dimensions" => [Integer(width), Integer(height)],
      "size"       => File.size(path),
      "human_size" => size,
    )

    @info.fetch(value)
  end
rescue ArgumentError, TypeError
  raise MiniMagick::Invalid, "image data can't be read"
end

#clearObject



35
36
37
# File 'lib/mini_magick/image/info.rb', line 35

def clear
  @info.clear
end

#colorspaceObject



61
62
63
# File 'lib/mini_magick/image/info.rb', line 61

def colorspace
  @info["colorspace"] ||= self["%r"]
end

#decode_comma_separated_ascii_characters(encoded_value) ⇒ Object



145
146
147
148
# File 'lib/mini_magick/image/info.rb', line 145

def decode_comma_separated_ascii_characters(encoded_value)
  return encoded_value unless encoded_value.include?(',')
  encoded_value.scan(/\d+/).map(&:to_i).map(&:chr).join
end

#detailsObject



104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
# File 'lib/mini_magick/image/info.rb', line 104

def details
  @info["details"] ||= (
    details_string = identify(&:verbose)
    key_stack = []
    details_string.lines.to_a[1..-1].each_with_object({}) do |line, details_hash|
      next if !line.valid_encoding? || line.strip.length.zero?

      level = line[/^\s*/].length / 2 - 1
      if level >= 0
        key_stack.pop until key_stack.size <= level
      else
        # Some metadata, such as SVG clipping paths, will be saved without
        # indentation, resulting in a level of -1
        last_key = details_hash.keys.last
        details_hash[last_key] = '' if details_hash[last_key].empty?
        details_hash[last_key] << line
        next
      end

      key, _, value = line.partition(/:[\s\n]/).map(&:strip)
      hash = key_stack.inject(details_hash) { |hash, key| hash.fetch(key) }
      if value.empty?
        hash[key] = {}
        key_stack.push key
      else
        hash[key] = value
      end
    end
  )
end

#exifObject



81
82
83
84
85
86
87
88
89
90
91
92
93
94
# File 'lib/mini_magick/image/info.rb', line 81

def exif
  @info["exif"] ||= (
    output = self["%[EXIF:*]"]
    pairs = output.gsub(/^exif:/, "").split("\n").map { |line| line.split("=") }
    Hash[pairs].tap do |hash|
      ASCII_ENCODED_EXIF_KEYS.each do |key|
        next unless hash.has_key?(key)

        value = hash[key]
        hash[key] = decode_comma_separated_ascii_characters(value)
      end
    end
  )
end

#identifyObject



135
136
137
138
139
140
141
142
143
# File 'lib/mini_magick/image/info.rb', line 135

def identify
  path = @path
  path += "[0]" unless path =~ /\[\d+\]$/

  MiniMagick::Tool::Identify.new do |builder|
    yield builder if block_given?
    builder << path
  end
end

#mime_typeObject



65
66
67
# File 'lib/mini_magick/image/info.rb', line 65

def mime_type
  "image/#{self["format"].downcase}"
end

#raw(value) ⇒ Object



96
97
98
# File 'lib/mini_magick/image/info.rb', line 96

def raw(value)
  @info["raw:#{value}"] ||= identify { |b| b.format(value) }
end

#raw_exif(value) ⇒ Object



77
78
79
# File 'lib/mini_magick/image/info.rb', line 77

def raw_exif(value)
  self["%[#{value}]"]
end

#resolution(unit = nil) ⇒ Object



69
70
71
72
73
74
75
# File 'lib/mini_magick/image/info.rb', line 69

def resolution(unit = nil)
  output = identify do |b|
    b.units unit if unit
    b.format "%x %y"
  end
  output.split(" ").map(&:to_i)
end

#signatureObject



100
101
102
# File 'lib/mini_magick/image/info.rb', line 100

def signature
  @info["signature"] ||= self["%#"]
end