cul_image_props 0.3.3 → 0.3.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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