cul_image_props 0.3.2 → 0.3.3

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.
@@ -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: