exif 0.10.0 → 0.11.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +39 -5
- data/benchmark/benchmark.rb +0 -8
- data/exif.gemspec +2 -2
- data/ext/exif/data.c +48 -1
- data/ext/exif/data.h +1 -0
- data/lib/exif/version.rb +1 -1
- data/spec/exif_spec.rb +3 -9
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b333d92e91da900e3092613d33281d08b2b83de8
|
4
|
+
data.tar.gz: 09eb52bf0bad1c86ff330ebfa8da62543cc76fa3
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 27d623c15fb6ad2a9ac9e65ff960220bd5afa5ae1899e8eb0a0f5e009b79746a9aced6b1285b2a699507a1e84ad52957950737539a9b787d7c37a581ee30df9e
|
7
|
+
data.tar.gz: 1a3d1eaf3eb5f7be85f5badca07a174df54a6df99664a092854c8cbfff22799adab34592729c354261403a518e6221abee7c1b9885bfed15183cd7f2b69dabaa
|
data/README.md
CHANGED
@@ -1,27 +1,61 @@
|
|
1
|
-
|
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.
|
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"
|
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
|
data/benchmark/benchmark.rb
CHANGED
@@ -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{
|
13
|
-
spec.description = %q{
|
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 =
|
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
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.
|
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.
|
19
|
-
expect(@data.
|
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.
|
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:
|
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:
|
104
|
+
summary: Ruby EXIF reader written in C extension.
|
105
105
|
test_files:
|
106
106
|
- spec/exif_spec.rb
|
107
107
|
- spec/sample.jpg
|