exif 0.10.0 → 0.11.0

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 5e2d459e26e4c1bc0cc6c02e6c1e87c8a7168796
4
- data.tar.gz: e430895590e8ceaa7595f19c38aa0b062780c527
3
+ metadata.gz: b333d92e91da900e3092613d33281d08b2b83de8
4
+ data.tar.gz: 09eb52bf0bad1c86ff330ebfa8da62543cc76fa3
5
5
  SHA512:
6
- metadata.gz: 5e5b91c5f772dbdc7c8bef203b2101b8f57122c081a30ef841da082de6ba42cd8c942698024678136930ae895a95f59931b28ea4dc7e988d2f4445ae5d38bf48
7
- data.tar.gz: 9dd8285f7a418fed4bf545be7039feb702bd246aa524754090a88196a573adbd491c9a005736c3eaff8458338bdeaabb182d6e02cf83756eed229f2daf1d4395
6
+ metadata.gz: 27d623c15fb6ad2a9ac9e65ff960220bd5afa5ae1899e8eb0a0f5e009b79746a9aced6b1285b2a699507a1e84ad52957950737539a9b787d7c37a581ee30df9e
7
+ data.tar.gz: 1a3d1eaf3eb5f7be85f5badca07a174df54a6df99664a092854c8cbfff22799adab34592729c354261403a518e6221abee7c1b9885bfed15183cd7f2b69dabaa
data/README.md CHANGED
@@ -1,27 +1,61 @@
1
- # Exif
2
-
3
- Ruby wrapper for libexif
1
+ Ruby EXIF reader written in C extension.
4
2
 
5
3
  # Installation
6
4
 
7
5
  $ gem install exif
8
6
 
7
+ Please make sure you have installed `libexif` first.
8
+
9
9
  # Usage
10
10
 
11
11
  ```ruby
12
12
  data = Exif::Data.new('sample.jpg')
13
+ data.model # => "NIKON D600"
13
14
  data.image_width # => 4000
14
- data.gps_latitude # => '24, 10.6817, 0'
15
+ data.gps_longitude # => 121.51246
16
+ data.date_time # => 2013-12-08 21:14:11 0800
15
17
 
16
18
  # get all entries in an IFD
17
19
  data[0] # => {image_width: 4000, image_length: 2670, ...}
18
- data[1] # => {x_resolution: "72"}, y_resolution: "72", ...}
20
+ data[1] # => {x_resolution: "72", y_resolution: "72", ...}
19
21
  data[:exif] # => exposure_time: "1/125 sec.", f_number: "f/8.0"}
20
22
  data[:gps] # => {gps_version_id: "2.2.0.0", gps_latitude_ref: "N", ...}
21
23
  data[:interoperability] # => {...}
22
24
  data.to_h # => {0 => {...}, 1 => {...}, :exif => {...}}
23
25
  ```
24
26
 
27
+ # How fast?
28
+
29
+ There is another excellent work called [exifr](https://github.com/remvee/exifr) made by [@remvee](https://github.com/remvee). That's pure Ruby while this one is C extension. If you program JRuby, you may want to choose exifr, otherwise you can try this gem for speed purpose, it's about 8 times faster. A small benchmark shows below:
30
+
31
+ ```ruby
32
+ require 'benchmark'
33
+ require 'exif'
34
+ require 'exifr'
35
+ N = 500
36
+ FILE_PATH = 'sample.jpg'
37
+ Benchmark.bmbm do |x|
38
+ x.report '[exifr] init' do
39
+ N.times{ EXIFR::JPEG.new(FILE_PATH).width }
40
+ end
41
+ x.report '[exif] init' do
42
+ N.times{ Exif::Data.new(FILE_PATH).image_width }
43
+ end
44
+ end
45
+ ```
46
+
47
+ ```
48
+ $ ruby benchmark/benchmark.rb
49
+ Rehearsal ------------------------------------------------
50
+ [exifr] init 0.810000 0.020000 0.830000 ( 0.840701)
51
+ [exif] init 0.090000 0.010000 0.100000 ( 0.099700)
52
+ --------------------------------------- total: 0.930000sec
53
+
54
+ user system total real
55
+ [exifr] init 0.810000 0.020000 0.830000 ( 0.830644)
56
+ [exif] init 0.090000 0.010000 0.100000 ( 0.095148)
57
+ ```
58
+
25
59
  ## Tag Rreference
26
60
 
27
61
  - aperture_value
@@ -5,8 +5,6 @@ require 'exifr'
5
5
 
6
6
  N = 500
7
7
  FILE_PATH = File.expand_path('../../spec/sample.jpg', __FILE__)
8
- exifr = EXIFR::JPEG.new(FILE_PATH)
9
- exif = Exif::Data.new(FILE_PATH)
10
8
  Benchmark.bmbm do |x|
11
9
  x.report '[exifr] init' do
12
10
  N.times{ EXIFR::JPEG.new(FILE_PATH).width }
@@ -14,10 +12,4 @@ Benchmark.bmbm do |x|
14
12
  x.report '[exif] init' do
15
13
  N.times{ Exif::Data.new(FILE_PATH).image_width }
16
14
  end
17
- x.report '[exifr] get width' do
18
- N.times{ exifr.width }
19
- end
20
- x.report '[exif] get width' do
21
- N.times{ exif.image_width }
22
- end
23
15
  end
data/exif.gemspec CHANGED
@@ -9,8 +9,8 @@ Gem::Specification.new do |spec|
9
9
  spec.authors = ["Jian Weihang"]
10
10
  spec.email = ["tonytonyjan@gmail.com"]
11
11
  spec.extensions = ["ext/exif/extconf.rb"]
12
- spec.summary = %q{Wrapper of libexif}
13
- spec.description = %q{Wrapper of libexif}
12
+ spec.summary = %q{Ruby EXIF reader written in C extension.}
13
+ spec.description = %q{Ruby EXIF reader written in C extension.}
14
14
  spec.homepage = "https://github.com/tonytonyjan/exif"
15
15
  spec.license = "MIT"
16
16
 
data/ext/exif/data.c CHANGED
@@ -1,4 +1,5 @@
1
1
  #include <libexif/exif-data.h>
2
+ #include <time.h>
2
3
  #include "data.h"
3
4
 
4
5
  extern VALUE rb_mExif;
@@ -93,13 +94,59 @@ static void each_entry(ExifEntry *ee, void *self_ptr){
93
94
  value = rb_float_new(atof(buf));
94
95
  break;
95
96
  default:
96
- value = rb_str_new_cstr(buf);
97
+ value = process_value(self, ee->tag, buf);
97
98
  }
98
99
  rb_hash_aset(rb_hash_aref(rb_contents, IFD2SYM[ifd]), tag_name, value);
99
100
  rb_hash_aset(rb_contents, tag_name, value);
100
101
  rb_iv_set(*self, attr_name, value);
101
102
  }
102
103
 
104
+ static VALUE process_value(VALUE *self_ptr, ExifTag tag, char *buf){
105
+ ExifData *ed;
106
+ Data_Get_Struct(*self_ptr, ExifData, ed);
107
+ switch((int)tag){
108
+ case EXIF_TAG_DATE_TIME:
109
+ case EXIF_TAG_DATE_TIME_ORIGINAL:
110
+ case EXIF_TAG_DATE_TIME_DIGITIZED:
111
+ {
112
+ int i;
113
+ struct tm timer;
114
+ // "2013:09:10 16:31:21"
115
+ buf[4] = buf[7] = buf[10] = buf[13] = buf[16] = '\0';
116
+ timer.tm_year = atoi(buf) - 1900;
117
+ timer.tm_mon = atoi(buf + 5) - 1;
118
+ timer.tm_mday = atoi(buf + 8);
119
+ timer.tm_hour = atoi(buf + 11);
120
+ timer.tm_min = atoi(buf + 14);
121
+ timer.tm_sec = atoi(buf + 17);
122
+ return rb_time_new(mktime(&timer), 0);
123
+ break;
124
+ }
125
+ case EXIF_TAG_GPS_LATITUDE:
126
+ case EXIF_TAG_GPS_LONGITUDE:
127
+ {
128
+ char *l = buf, *r = buf + 1;
129
+ double degrees, minutes, seconds;
130
+ // "121, 30.7476, 0"
131
+ while(*r != ',') r++;
132
+ *r = '\0'; r++;
133
+ degrees = atof(l); l = r;
134
+ while(*r != ',') r++;
135
+ *r = '\0';
136
+ minutes = atof(l); l = r + 1;
137
+ seconds = atof(l);
138
+ ExifTag ref_tag = tag == EXIF_TAG_GPS_LATITUDE ? EXIF_TAG_GPS_LATITUDE_REF : EXIF_TAG_GPS_LONGITUDE_REF;
139
+ ExifEntry *entry = exif_content_get_entry(ed->ifd[EXIF_IFD_GPS], ref_tag);
140
+ char ref_value; exif_entry_get_value(entry, &ref_value, 1);
141
+ double degree = (degrees * 3600 + minutes * 60 + seconds) / 3600;
142
+ if(ref_value == 'S' || ref_value == 'W') degree *= -1;
143
+ return rb_float_new(degree);
144
+ }
145
+ default:
146
+ return rb_str_new_cstr(buf);
147
+ }
148
+ }
149
+
103
150
  static char* attr_string(ExifIfd ifd, ExifTag tag){
104
151
  switch((int)tag){
105
152
  case EXIF_TAG_INTEROPERABILITY_INDEX: /* EXIF_TAG_GPS_LATITUDE_REF */
data/ext/exif/data.h CHANGED
@@ -14,6 +14,7 @@ static VALUE rb_value(VALUE self, VALUE key);
14
14
 
15
15
  static void each_content(ExifContent *ec, void *user_data);
16
16
  static void each_entry(ExifEntry *, void *user_data);
17
+ static VALUE process_value(VALUE *self_ptr, ExifTag tag, char *buf);
17
18
  static char* attr_string(ExifIfd ifd, ExifTag tag);
18
19
 
19
20
  #endif /* DATA_H */
data/lib/exif/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Exif
2
- VERSION = "0.10.0"
2
+ VERSION = "0.11.0"
3
3
  end
data/spec/exif_spec.rb CHANGED
@@ -10,15 +10,9 @@ describe Exif do
10
10
  # end
11
11
 
12
12
  it 'works' do
13
- expect(@data.to_h[0][:image_width]).to eq 4000
14
- expect(@data.to_h[:image_width]).to eq 4000
15
- expect(@data[0][:image_width]).to eq 4000
16
- expect(@data[:image_width]).to eq 4000
13
+ expect(@data.model).to eq 'NIKON D600'
17
14
  expect(@data.image_width).to eq 4000
18
- expect(@data.to_h[:gps][:gps_latitude]).to eq '24, 10.6817, 0'
19
- expect(@data.to_h[:gps_latitude]).to eq '24, 10.6817, 0'
20
- expect(@data[:gps][:gps_latitude]).to eq '24, 10.6817, 0'
21
- expect(@data[:gps_latitude]).to eq '24, 10.6817, 0'
22
- expect(@data.gps_latitude).to eq '24, 10.6817, 0'
15
+ expect(@data.gps_latitude).to be_within(0.0001).of(24.178028333333334)
16
+ expect(@data.date_time).to eq Time.new(2013,12,8,21,14,11)
23
17
  end
24
18
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: exif
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.10.0
4
+ version: 0.11.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jian Weihang
@@ -52,7 +52,7 @@ dependencies:
52
52
  - - ">="
53
53
  - !ruby/object:Gem::Version
54
54
  version: '0'
55
- description: Wrapper of libexif
55
+ description: Ruby EXIF reader written in C extension.
56
56
  email:
57
57
  - tonytonyjan@gmail.com
58
58
  executables: []
@@ -101,7 +101,7 @@ rubyforge_project:
101
101
  rubygems_version: 2.4.2
102
102
  signing_key:
103
103
  specification_version: 4
104
- summary: Wrapper of libexif
104
+ summary: Ruby EXIF reader written in C extension.
105
105
  test_files:
106
106
  - spec/exif_spec.rb
107
107
  - spec/sample.jpg