exifr 1.0.0 → 1.0.1

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.
data/CHANGELOG CHANGED
@@ -1,3 +1,6 @@
1
+ EXIF Reader 1.0.1
2
+ * bug fix; "[GH#7] Unable to properly display exposure_bias_value"; thanks to John Krueger
3
+
1
4
  EXIF Reader 1.0.0
2
5
  * bug fix; "ArgumentError: invalid byte sequence in UTF-8" when reading messy field using Ruby 1.9+
3
6
  * enhancement; "[GH#4] more informative inspect for EXIFR::TIFF::Orientation instance"
data/bin/exifr CHANGED
@@ -38,6 +38,14 @@ end
38
38
 
39
39
  if ARGV.size == 0
40
40
  STDERR.puts "Usage: #{$0} FILE .."
41
+ elsif ARGV[0] == "--dump-exif"
42
+ ARGV[1..-1].each do |fname|
43
+ STDOUT.write JPEG.new(fname).exif_data
44
+ end
45
+ elsif ARGV[0] == "--dump-thumbnail"
46
+ ARGV[1..-1].each do |fname|
47
+ STDOUT.write JPEG.new(fname).thumbnail
48
+ end
41
49
  else
42
50
  ARGV.each do |fname|
43
51
  case fname
@@ -20,6 +20,8 @@ module EXIFR
20
20
  attr_reader :comment
21
21
  # EXIF data if available
22
22
  attr_reader :exif
23
+ # raw EXIF data
24
+ attr_reader :exif_data # :nodoc:
23
25
 
24
26
  # +file+ is a filename or an IO object. Hint: use StringIO when working with slurped data like blobs.
25
27
  def initialize(file)
@@ -102,7 +104,8 @@ module EXIFR
102
104
  @comment = @comment.first if @comment && @comment.size == 1
103
105
 
104
106
  if app1 = app1s.find { |d| d[0..5] == "Exif\0\0" }
105
- @exif = TIFF.new(StringIO.new(app1[6..-1]))
107
+ @exif_data = app1[6..-1]
108
+ @exif = TIFF.new(StringIO.new(@exif_data))
106
109
  end
107
110
  end
108
111
  end
@@ -459,17 +459,20 @@ module EXIFR
459
459
  @type = data.readshort(pos + 2)
460
460
 
461
461
  case @type
462
- when 1, 6 # byte, signed byte
463
- # TODO handle signed bytes
462
+ when 1 # byte
464
463
  len, pack = count, proc { |d| d }
464
+ when 6 # signed byte
465
+ len, pack = count, proc { |d| sign_byte(d) }
465
466
  when 2 # ascii
466
467
  len, pack = count, proc { |d| d.unpack("A*") }
467
- when 3, 8 # short, signed short
468
- # TODO handle signed
468
+ when 3 # short
469
469
  len, pack = count * 2, proc { |d| d.unpack(data.short + '*') }
470
- when 4, 9 # long, signed long
471
- # TODO handle signed
470
+ when 8 # signed short
471
+ len, pack = count * 2, proc { |d| d.unpack(data.short + '*').map{|n| sign_short(n)} }
472
+ when 4 # long
472
473
  len, pack = count * 4, proc { |d| d.unpack(data.long + '*') }
474
+ when 9 # signed long
475
+ len, pack = count * 4, proc { |d| d.unpack(data.long + '*').map{|n| sign_long(n)} }
473
476
  when 7 # undefined
474
477
  # UserComment
475
478
  if @tag == 0x9286
@@ -478,18 +481,16 @@ module EXIFR
478
481
  start = len > 4 ? @offset + 8 : (pos + 8) # UserComment first 8-bytes is char code
479
482
  @value = [pack[data[start..(start + len - 1)]]].flatten
480
483
  end
481
- when 5, 10
484
+ when 5 # unsigned rational
482
485
  len, pack = count * 8, proc do |d|
483
- r = []
484
- d.unpack(data.long + '*').each_with_index do |v,i|
485
- i % 2 == 0 ? r << [v] : r.last << v
486
+ d.unpack(data.long + '*').each_slice(2).map do |f|
487
+ rational(*f)
486
488
  end
487
- r.map do |f|
488
- if f[1] == 0 # allow NaN and Infinity
489
- f[0].to_f.quo(f[1])
490
- else
491
- Rational.respond_to?(:reduce) ? Rational.reduce(*f) : f[0].quo(f[1])
492
- end
489
+ end
490
+ when 10 # signed rational
491
+ len, pack = count * 8, proc do |d|
492
+ d.unpack(data.long + '*').map{|n| sign_long(n)}.each_slice(2).map do |f|
493
+ rational(*f)
493
494
  end
494
495
  end
495
496
  end
@@ -500,6 +501,27 @@ module EXIFR
500
501
  @value = d && [pack[d]].flatten
501
502
  end
502
503
  end
504
+
505
+ private
506
+ def sign_byte(n)
507
+ (n & 0x80) != 0 ? n - 0x100 : n
508
+ end
509
+
510
+ def sign_short(n)
511
+ (n & 0x8000) != 0 ? n - 0x10000 : n
512
+ end
513
+
514
+ def sign_long(n)
515
+ (n & 0x80000000) != 0 ? n - 0x100000000 : n
516
+ end
517
+
518
+ def rational(n, d)
519
+ if d == 0 # allow NaN and Infinity
520
+ n.to_f.quo(d)
521
+ else
522
+ Rational.respond_to?(:reduce) ? Rational.reduce(n, d) : n.quo(d)
523
+ end
524
+ end
503
525
  end
504
526
 
505
527
  class Data #:nodoc:
@@ -91,7 +91,7 @@ class TIFFTest < Test::Unit::TestCase
91
91
  assert_equal [678886.quo(100000), 0.quo(1), 0.quo(1)], t.gps_longitude
92
92
  assert_equal 'WGS84', t.gps_map_datum
93
93
 
94
- (all_test_exifs - %w(gps user-comment out-of-range).map{|v| f("#{v}.exif")}).each do |fname|
94
+ (all_test_exifs - %w(gps user-comment out-of-range negative-exposure-bias-value).map{|v| f("#{v}.exif")}).each do |fname|
95
95
  assert_nil TIFF.new(fname).gps_version_id
96
96
  end
97
97
  end
@@ -172,4 +172,8 @@ class TIFFTest < Test::Unit::TestCase
172
172
  assert 'NIKON', TIFF.new(f('out-of-range.exif')).make
173
173
  end
174
174
  end
175
+
176
+ def test_negative_exposure_bias_value
177
+ assert_equal -1.quo(3), TIFF.new(f('negative-exposure-bias-value.exif')).exposure_bias_value
178
+ end
175
179
  end
metadata CHANGED
@@ -1,7 +1,12 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: exifr
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0
4
+ prerelease: false
5
+ segments:
6
+ - 1
7
+ - 0
8
+ - 1
9
+ version: 1.0.1
5
10
  platform: ruby
6
11
  authors:
7
12
  - R.W. van 't Veer
@@ -9,7 +14,7 @@ autorequire:
9
14
  bindir: bin
10
15
  cert_chain: []
11
16
 
12
- date: 2010-04-07 00:00:00 +02:00
17
+ date: 2010-04-26 00:00:00 +02:00
13
18
  default_executable:
14
19
  dependencies: []
15
20
 
@@ -29,21 +34,22 @@ files:
29
34
  - lib/jpeg.rb
30
35
  - lib/tiff.rb
31
36
  - tests/data/1x1.jpg
32
- - tests/data/Canon_PowerShot_A85.exif
33
- - tests/data/Casio-EX-S20.exif
34
- - tests/data/FUJIFILM-FinePix_S3000.exif
35
- - tests/data/Panasonic-DMC-LC33.exif
36
- - tests/data/Trust-DC3500_MINI.exif
37
37
  - tests/data/apple-aperture-1.5.exif
38
38
  - tests/data/canon-g3.exif
39
+ - tests/data/Canon_PowerShot_A85.exif
40
+ - tests/data/Casio-EX-S20.exif
39
41
  - tests/data/endless-loop.exif
40
42
  - tests/data/exif.jpg
43
+ - tests/data/FUJIFILM-FinePix_S3000.exif
41
44
  - tests/data/gps.exif
42
45
  - tests/data/image.jpg
43
46
  - tests/data/multiple-app1.jpg
47
+ - tests/data/negative-exposure-bias-value.exif
44
48
  - tests/data/nikon_d1x.tif
45
49
  - tests/data/out-of-range.exif
50
+ - tests/data/Panasonic-DMC-LC33.exif
46
51
  - tests/data/plain.tif
52
+ - tests/data/Trust-DC3500_MINI.exif
47
53
  - tests/data/user-comment.exif
48
54
  - tests/data/weird_date.exif
49
55
  - tests/jpeg_test.rb
@@ -67,18 +73,20 @@ required_ruby_version: !ruby/object:Gem::Requirement
67
73
  requirements:
68
74
  - - ">="
69
75
  - !ruby/object:Gem::Version
76
+ segments:
77
+ - 0
70
78
  version: "0"
71
- version:
72
79
  required_rubygems_version: !ruby/object:Gem::Requirement
73
80
  requirements:
74
81
  - - ">="
75
82
  - !ruby/object:Gem::Version
83
+ segments:
84
+ - 0
76
85
  version: "0"
77
- version:
78
86
  requirements: []
79
87
 
80
88
  rubyforge_project:
81
- rubygems_version: 1.3.5
89
+ rubygems_version: 1.3.6
82
90
  signing_key:
83
91
  specification_version: 3
84
92
  summary: EXIF Reader is a module to read EXIF from JPEG images.