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 +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
|