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.
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
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
|
-
|
22
|
-
|
23
|
-
return seq
|
18
|
+
if 32 <= c and c < 256
|
19
|
+
str += c.chr
|
24
20
|
end
|
25
|
-
|
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.
|
30
|
-
|
31
|
-
|
32
|
-
#
|
33
|
-
|
34
|
-
|
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(:
|
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(:
|
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(:
|
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(:
|
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(:
|
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(:
|
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(:
|
901
|
-
0x0002 => TagName.new('ISOSetting', self.method(:
|
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,
|
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.
|
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-
|
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:
|
104
|
+
version: 1.9.3
|
105
105
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
106
106
|
none: false
|
107
107
|
requirements:
|