exifr 1.0.0 → 1.0.1

Sign up to get free protection for your applications and to get access to all the features.
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.