cul_image_props 0.3.2 → 0.3.3

Sign up to get free protection for your applications and to get access to all the features.
@@ -5,33 +5,45 @@ module Properties
5
5
  module Exif
6
6
 
7
7
  # Don't throw an exception when given an out of range character.
8
- def self.make_string(seq)
9
- str = ''
10
- filter = Proc.new { |c|
11
- # Screen out non-printing characters
12
- if 32 <= c and c < 256
13
- str += c.chr
14
- end
15
- }
16
- if seq.is_a? String
17
- seq.each_byte &filter
18
- else # must be a byte array, right?
19
- seq.each &filter
8
+ def self.ascii_bytes_to_filtered_string(seq)
9
+ if seq.is_a? String
10
+ seq = seq.unpack('C*')
11
+ end
12
+ str = ''
13
+ seq.each { |c|
14
+ # Screen out non-printing characters
15
+ unless c.is_a? Fixnum
16
+ raise "Expected an array of ASCII8BIT bytes, got an array value #{c.class}: #{field_type.inspect}"
20
17
  end
21
- # If no printing chars
22
- if not str.length == 0
23
- return seq
18
+ if 32 <= c and c < 256
19
+ str += c.chr
24
20
  end
25
- return str
21
+ }
22
+ return str
26
23
  end
27
24
  # Special version to deal with the code in the first 8 bytes of a user comment.
28
25
  # First 8 bytes gives coding system e.g. ASCII vs. JIS vs Unicode
29
- def self.make_string_uc(seq)
30
- code = seq[0, 8]
31
- seq = seq[8 ... seq.length]
32
- # Of course, this is only correct if ASCII, and the standard explicitly
33
- # allows JIS and Unicode.
34
- return make_string(seq)
26
+ def self.filter_encoded_string(seq)
27
+ if seq.is_a? String
28
+ bytes = seq.unpack('C*')
29
+ else # array of bytes
30
+ bytes = seq
31
+ end
32
+ code = bytes[0, 8]
33
+ seq = bytes[8 ... bytes.length].pack('C*')
34
+ if code == TAG_ENCODING[:ASCII]
35
+ return ascii_bytes_to_filtered_string(bytes[8 ... bytes.length])
36
+ end
37
+ if code == TAG_ENCODING[:UNICODE]
38
+ seq = seq.force_encoding('utf-8') # I see some docs indicating UCS-2 here?
39
+ return seq.gsub(/\p{Cntrl}/,'').gsub(/\P{ASCII}/,'')
40
+ end
41
+ if code == TAG_ENCODING[:JIS]
42
+ # to be implemented
43
+ return "JIS String Value"
44
+ end
45
+ # Fall back to ASCII
46
+ return ascii_bytes_to_filtered_string(bytes[8 ... bytes.length])
35
47
  end
36
48
 
37
49
  # decode Olympus SpecialMode tag in MakerNote
@@ -106,6 +118,12 @@ def self.nikon_ev_bias(seq)
106
118
  return ret_str
107
119
  end
108
120
 
121
+ TAG_ENCODING = {
122
+ :ASCII => [0x41, 0x53, 0x43, 0x49, 0x49, 0x00, 0x00, 0x00],
123
+ :JIS => [0x4A, 0x49, 0x53, 0x00, 0x00, 0x00, 0x00, 0x00],
124
+ :UNICODE => [0x55, 0x4E, 0x49, 0x43, 0x4F, 0x44, 0x45, 0x00],
125
+ :UNDEFINED => [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
126
+ }
109
127
 
110
128
  # field type descriptions as (length, abbreviation, full name) tuples
111
129
  FIELD_TYPES = [
@@ -181,7 +199,7 @@ EXIF_TAGS = {
181
199
  0x011A => TagName.new('XResolution'),
182
200
  0x011B => TagName.new('YResolution'),
183
201
  0x011C => TagName.new('PlanarConfiguration'),
184
- 0x011D => TagName.new('PageName', self.method(:make_string)),
202
+ 0x011D => TagName.new('PageName', self.method(:ascii_bytes_to_filtered_string)),
185
203
  0x0128 => TagName.new('ResolutionUnit',
186
204
  { 1 => 'Not Absolute',
187
205
  2 => 'Pixels/Inch',
@@ -228,7 +246,7 @@ EXIF_TAGS = {
228
246
  0x8825 => TagName.new('GPSInfo'),
229
247
  0x8827 => TagName.new('ISOSpeedRatings'),
230
248
  0x8828 => TagName.new('OECF'),
231
- 0x9000 => TagName.new('ExifVersion', self.method(:make_string)),
249
+ 0x9000 => TagName.new('ExifVersion', self.method(:ascii_bytes_to_filtered_string)),
232
250
  0x9003 => TagName.new('DateTimeOriginal'),
233
251
  0x9004 => TagName.new('DateTimeDigitized'),
234
252
  0x9101 => TagName.new('ComponentsConfiguration',
@@ -289,7 +307,7 @@ EXIF_TAGS = {
289
307
  0x920A => TagName.new('FocalLength'),
290
308
  0x9214 => TagName.new('SubjectArea'),
291
309
  0x927C => TagName.new('MakerNote'),
292
- 0x9286 => TagName.new('UserComment', self.method(:make_string_uc)),
310
+ 0x9286 => TagName.new('UserComment', self.method(:filter_encoded_string)),
293
311
  0x9290 => TagName.new('SubSecTime'),
294
312
  0x9291 => TagName.new('SubSecTimeOriginal'),
295
313
  0x9292 => TagName.new('SubSecTimeDigitized'),
@@ -301,7 +319,7 @@ EXIF_TAGS = {
301
319
  0x9C9E => TagName.new('XPKeywords'),
302
320
  0x9C9F => TagName.new('XPSubject'),
303
321
 
304
- 0xA000 => TagName.new('FlashPixVersion', self.method(:make_string)),
322
+ 0xA000 => TagName.new('FlashPixVersion', self.method(:ascii_bytes_to_filtered_string)),
305
323
  0xA001 => TagName.new('ColorSpace',
306
324
  {1 => 'sRGB',
307
325
  2 => 'Adobe RGB',
@@ -409,7 +427,7 @@ MAKERNOTE_OLYMPUS_TAGS = {
409
427
  0x0206 => TagName.new('LensDistortionParams'),
410
428
  0x0207 => TagName.new('SoftwareRelease'),
411
429
  0x0208 => TagName.new('PictureInfo'),
412
- 0x0209 => TagName.new('CameraID', self.method(:make_string)), # print as string
430
+ 0x0209 => TagName.new('CameraID', self.method(:ascii_bytes_to_filtered_string)), # print as string
413
431
  0x0F00 => TagName.new('DataDump'),
414
432
  0x0300 => TagName.new('PreCaptureFrames'),
415
433
  0x0404 => TagName.new('SerialNumber'),
@@ -683,7 +701,7 @@ MAKERNOTE_CASIO_TAGS={
683
701
  }
684
702
 
685
703
  MAKERNOTE_FUJIFILM_TAGS={
686
- 0x0000 => TagName.new('NoteVersion', self.method(:make_string)),
704
+ 0x0000 => TagName.new('NoteVersion', self.method(:ascii_bytes_to_filtered_string)),
687
705
  0x1000 => TagName.new('Quality'),
688
706
  0x1001 => TagName.new('Sharpness',
689
707
  {1 => 'Soft',
@@ -897,8 +915,8 @@ MAKERNOTE_CANON_TAG_0x004 = {
897
915
 
898
916
  # Nikon E99x MakerNote Tags
899
917
  MAKERNOTE_NIKON_NEWER_TAGS={
900
- 0x0001 => TagName.new('MakernoteVersion', self.method(:make_string)), # Sometimes binary
901
- 0x0002 => TagName.new('ISOSetting', self.method(:make_string)),
918
+ 0x0001 => TagName.new('MakernoteVersion', self.method(:ascii_bytes_to_filtered_string)), # Sometimes binary
919
+ 0x0002 => TagName.new('ISOSetting', self.method(:ascii_bytes_to_filtered_string)),
902
920
  0x0003 => TagName.new('ColorMode'),
903
921
  0x0004 => TagName.new('Quality'),
904
922
  0x0005 => TagName.new('Whitebalance'),
@@ -127,7 +127,7 @@ class EXIF_header
127
127
  x = 0
128
128
  l = src.length
129
129
  if l == 1
130
- return src[0]
130
+ return src.unpack('C')[0]
131
131
  elsif l == 2
132
132
  return src.unpack('n')[0]
133
133
  elsif l == 4
@@ -284,10 +284,10 @@ class EXIF_header
284
284
  # sometimes gets too big to fit in int value
285
285
  if count != 0 and count < (2**31)
286
286
  @file.seek(@offset + field_offset)
287
- values = @file.read(count)
287
+ values = @file.read(count) # ascii string of count bytes
288
288
  #print values
289
289
  # Drop any garbage after a null.
290
- values = values.split(X00, 1)[0]
290
+ values = values.split(X00, 1)[0] # a null-terminated string
291
291
  else
292
292
  values = ''
293
293
  end
@@ -311,29 +311,33 @@ class EXIF_header
311
311
  }
312
312
  end
313
313
  end
314
+
314
315
  # now 'values' is either a string or an array
315
- if count == 1 and field_type != 2
316
- printable=values[0].to_s
317
- elsif count > 50 and values.length > 20
318
- printable= (field_type == 2) ? (values[0...20] + '...') : ("[" + values[0...20].join(',') + ", ... ]")
319
- else
320
- printable=values.inspect
321
- end
322
316
  # compute printable version of values
323
317
  if tag_entry
324
318
  if tag_entry.value
325
319
  # optional 2nd tag element is present
326
320
  if tag_entry.value.respond_to? :call
327
321
  # call mapping function
322
+ puts "tag_name: #{tag_name}"
323
+ puts "field_type: #{field_type}"
324
+ puts "count: #{count}"
328
325
  printable = tag_entry.value.call(values)
326
+ puts "printable: #{printable}"
329
327
  else
330
328
  printable = ''
331
329
  values.each { |i|
332
330
  # use lookup table for this tag
333
- printable += (tag_entry.value.include? i)?tag_entry.value[i] : i.inspect
331
+ printable += (tag_entry.value.include? i) ? tag_entry.value[i] : i.inspect
334
332
  }
335
333
  end
336
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
337
341
  end
338
342
  self.tags[ifd_name + ' ' + tag_name] = IFD_Tag.new(printable, tag_id,
339
343
  field_type,
@@ -1,7 +1,7 @@
1
1
  module Cul
2
2
  module Image
3
3
  module Properties
4
- VERSION = "0.3.2"
4
+ VERSION = "0.3.3"
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.2
4
+ version: 0.3.3
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-24 00:00:00.000000000 Z
12
+ date: 2013-01-25 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: nokogiri
@@ -101,7 +101,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
101
101
  requirements:
102
102
  - - ! '>='
103
103
  - !ruby/object:Gem::Version
104
- version: '0'
104
+ version: 1.9.3
105
105
  required_rubygems_version: !ruby/object:Gem::Requirement
106
106
  none: false
107
107
  requirements: