cul_image_props 0.3.3 → 0.3.4

Sign up to get free protection for your applications and to get access to all the features.
@@ -26,19 +26,39 @@ end
26
26
 
27
27
  # first element of tuple is tag name, optional second element is
28
28
  # another dictionary giving names to values
29
- class TagName
29
+ class TagEntry
30
30
  attr_accessor :name, :value
31
31
  def initialize(name, value=false)
32
32
  @name = name
33
33
  @value = value
34
34
  end
35
+
36
+ def translates?
37
+ return (not ( @value.nil? or @value == false ))
38
+ end
39
+
40
+ def translate(values)
41
+ if @value
42
+ if @value.respond_to? :call
43
+ # value was a proc
44
+ @value.call(values)
45
+ else
46
+ # value was a dictionary
47
+ trans = ''
48
+ values.each {|i| trans += (@value.include? i) ? @value[i] : i.inspect }
49
+ trans
50
+ end
51
+ else
52
+ values.inspect
53
+ end
54
+ end
35
55
  end
36
56
 
37
57
  class Ratio
38
58
  # ratio object that eventually will be able to reduce itself to lowest
39
59
  # common denominator for printing
40
60
  attr_accessor :num, :den
41
- def gcd(a, b)
61
+ def self.gcd(a, b)
42
62
  if b == 1 or a == 1
43
63
  return 1
44
64
  elsif b == 0
@@ -62,7 +82,7 @@ class Ratio
62
82
  end
63
83
 
64
84
  def reduce
65
- div = gcd(@num, @den)
85
+ div = Ratio.gcd(@num, @den)
66
86
  if div > 1
67
87
  @num = @num / div
68
88
  @den = @den / div
@@ -72,36 +92,52 @@ end
72
92
 
73
93
  # for ease of dealing with tags
74
94
  class IFD_Tag
75
- attr_accessor :printable, :tag, :field_type, :values, :field_offset, :field_length
76
- def initialize( printable, tag, field_type, values, field_offset, field_length)
77
- # printable version of data
78
- @printable = printable
95
+ attr_accessor :tag, :field_type, :values, :field_offset, :field_length
96
+ def initialize( tag_id, field_type, tag_entry, values, field_offset, count)
79
97
  # tag ID number
80
- @tag = tag
98
+ @tag = tag_id
81
99
  # field type as index into FIELD_TYPES
82
100
  @field_type = field_type
101
+ # the TagEntry looked up for this tag_id
102
+ @tag_entry = tag_entry
83
103
  # offset of start of field in bytes from beginning of IFD
84
104
  @field_offset = field_offset
85
105
  # length of data field in bytes
86
- @field_length = field_length
106
+ @count = count
107
+ typelen = FIELD_TYPES[@field_type].length
108
+ @field_length = count * typelen
87
109
  # either a string or array of data items
88
110
  @values = values
89
111
  end
90
112
 
113
+ def printable
114
+ @printable ||= begin
115
+ if @tag_entry.translates?
116
+ @tag_entry.translate @values
117
+ elsif @count == 1 and @field_type != 2
118
+ @values[0].to_s
119
+ elsif @count > 50 and @values.length > 20
120
+ (field_type == 2) ? (@values[0...20] + '...') : ("[" + @values[0...20].join(',') + ", ... ]")
121
+ else
122
+ @values.inspect
123
+ end
124
+ end
125
+ end
126
+
91
127
  def to_s
92
- return @printable
128
+ printable
93
129
  end
94
130
 
95
131
  def inspect
96
132
  begin
97
133
  s= format("(0x%04X) %s=%s @ %d", @tag,
98
- FIELD_TYPES[@field_type][2],
99
- @printable,
134
+ FIELD_TYPES[@field_type].name,
135
+ printable,
100
136
  @field_offset)
101
137
  rescue
102
138
  s= format("(%s) %s=%s @ %s", @tag.to_s,
103
- FIELD_TYPES[@field_type][2],
104
- @printable,
139
+ FIELD_TYPES[@field_type].name,
140
+ printable,
105
141
  @field_offset.to_s)
106
142
  end
107
143
  return s
@@ -123,39 +159,39 @@ class EXIF_header
123
159
  end
124
160
 
125
161
  # extract multibyte integer in Motorola format (big/network endian)
126
- def s2n_motorola(src)
127
- x = 0
128
- l = src.length
129
- if l == 1
130
- return src.unpack('C')[0]
131
- elsif l == 2
132
- return src.unpack('n')[0]
133
- elsif l == 4
134
- return src.unpack('N')[0]
135
- else
136
- raise "Unexpected packed Fixnum length: " + l.to_s
137
- end
162
+ def self.s2n_motorola(src)
163
+ x = 0
164
+ l = src.bytesize
165
+ if l == 1
166
+ return src.unpack('C')[0]
167
+ elsif l == 2
168
+ return src.unpack('n')[0]
169
+ elsif l == 4
170
+ return src.unpack('N')[0]
171
+ else
172
+ raise "Unexpected packed Fixnum length: " + l.to_s
173
+ end
138
174
  end
139
175
  # extract multibyte integer in Intel format (little endian)
140
- def s2n_intel(src)
141
- x = 0
142
- l = src.length
143
- if l == 1
144
- return src.unpack('C')[0]
145
- elsif l == 2
146
- return src.unpack('v')[0]
147
- elsif l == 4
148
- return src.unpack('V')[0]
149
- else
150
- raise "Unexpected packed Fixnum length: " + l.to_s
151
- end
176
+ def self.s2n_intel(src)
177
+ x = 0
178
+ l = src.bytesize
179
+ if l == 1
180
+ return src.unpack('C')[0]
181
+ elsif l == 2
182
+ return src.unpack('v')[0]
183
+ elsif l == 4
184
+ return src.unpack('V')[0]
185
+ else
186
+ raise "Unexpected packed Fixnum length: " + l.to_s
152
187
  end
188
+ end
153
189
 
154
190
  def unpack_number(src, signed=false)
155
191
  if @endian == 'I'
156
- val=s2n_intel(src)
192
+ val = EXIF_header.s2n_intel(src)
157
193
  else
158
- val=s2n_motorola(src)
194
+ val = EXIF_header.s2n_motorola(src)
159
195
  end
160
196
  # Sign extension ?
161
197
  if signed
@@ -239,12 +275,7 @@ class EXIF_header
239
275
  tag_id = unpack_number(@file.read(2))
240
276
 
241
277
  # get tag name early to avoid errors, help debug
242
- tag_entry = dict[tag_id]
243
- if tag_entry
244
- tag_name = tag_entry.name
245
- else
246
- tag_name = 'Tag 0x%04X' % tag_id
247
- end
278
+ tag_entry = dict[tag_id] || TagEntry.new('Tag 0x%04X' % tag_id)
248
279
 
249
280
  # ignore certain tags for faster processing
250
281
  if not (not @detail and IGNORE_TAGS.include? tag_id)
@@ -261,7 +292,7 @@ class EXIF_header
261
292
  raise format("unknown type %d in tag 0x%04X", field_type, tag)
262
293
  end
263
294
  end
264
- typelen = FIELD_TYPES[field_type][0]
295
+ typelen = FIELD_TYPES[field_type].length
265
296
  count = unpack_number(@file.read(4))
266
297
 
267
298
  # If the value exceeds 4 bytes, it is a pointer to values.
@@ -297,7 +328,7 @@ class EXIF_header
297
328
 
298
329
  # @todo investigate
299
330
  # some entries get too big to handle could be malformed file
300
- if count < 1000 or tag_name == 'MakerNote'
331
+ if count < 1000 or tag_entry.name == 'MakerNote'
301
332
  @file.seek(@offset + field_offset)
302
333
  count.times {
303
334
  if field_type == 5 or field_type == 10
@@ -312,39 +343,12 @@ class EXIF_header
312
343
  end
313
344
  end
314
345
 
315
- # now 'values' is either a string or an array
316
- # compute printable version of values
317
- if tag_entry
318
- if tag_entry.value
319
- # optional 2nd tag element is present
320
- if tag_entry.value.respond_to? :call
321
- # call mapping function
322
- puts "tag_name: #{tag_name}"
323
- puts "field_type: #{field_type}"
324
- puts "count: #{count}"
325
- printable = tag_entry.value.call(values)
326
- puts "printable: #{printable}"
327
- else
328
- printable = ''
329
- values.each { |i|
330
- # use lookup table for this tag
331
- printable += (tag_entry.value.include? i) ? tag_entry.value[i] : i.inspect
332
- }
333
- end
334
- end
335
- elsif count == 1 and field_type != 2
336
- printable=values[0].to_s
337
- elsif count > 50 and values.length > 20
338
- printable= (field_type == 2) ? (values[0...20] + '...') : ("[" + values[0...20].join(',') + ", ... ]")
339
- else
340
- printable=values.inspect
341
- end
342
- self.tags[ifd_name + ' ' + tag_name] = IFD_Tag.new(printable, tag_id,
343
- field_type,
346
+ self.tags[ifd_name + ' ' + tag_entry.name] = IFD_Tag.new(tag_id,
347
+ field_type, tag_entry,
344
348
  values, field_offset,
345
- count * typelen)
349
+ count)
346
350
  end
347
- if tag_name == stop_tag
351
+ if tag_entry.name == stop_tag
348
352
  break
349
353
  end
350
354
  }
@@ -370,7 +374,7 @@ class EXIF_header
370
374
  entry = thumb_ifd + 2 + 12 * i
371
375
  tag = self.s2n(entry, 2)
372
376
  field_type = self.s2n(entry+2, 2)
373
- typelen = FIELD_TYPES[field_type][0]
377
+ typelen = FIELD_TYPES[field_type].length
374
378
  count = self.s2n(entry+4, 4)
375
379
  oldoff = self.s2n(entry+8, 4)
376
380
  # start of the 4-byte pointer area in entry
@@ -1,7 +1,7 @@
1
1
  module Cul
2
2
  module Image
3
3
  module Properties
4
- VERSION = "0.3.3"
4
+ VERSION = "0.3.4"
5
5
  end
6
6
  end
7
7
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cul_image_props
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.3
4
+ version: 0.3.4
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-01-25 00:00:00.000000000 Z
12
+ date: 2013-01-28 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: nokogiri