dimensions 1.1.0 → 1.2.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.
- data/README.md +5 -1
- data/lib/dimensions.rb +2 -0
- data/lib/dimensions/exif_scanner.rb +7 -30
- data/lib/dimensions/jpeg_scanner.rb +2 -2
- data/lib/dimensions/reader.rb +17 -3
- data/lib/dimensions/scanner.rb +17 -3
- data/lib/dimensions/tiff_scanner.rb +33 -0
- data/lib/dimensions/tiff_scanning.rb +47 -0
- data/lib/dimensions/version.rb +1 -1
- metadata +6 -4
data/README.md
CHANGED
@@ -2,7 +2,7 @@ Dimensions
|
|
2
2
|
==========
|
3
3
|
|
4
4
|
Dimensions is a pure Ruby library for reading the width, height and
|
5
|
-
rotation angle of GIF, PNG and
|
5
|
+
rotation angle of GIF, PNG, JPEG and TIFF images.
|
6
6
|
|
7
7
|
Use the `dimensions`, `width` and `height` methods on the `Dimensions`
|
8
8
|
module to measure image files:
|
@@ -65,6 +65,10 @@ end
|
|
65
65
|
|
66
66
|
### Version History
|
67
67
|
|
68
|
+
**1.2.0** (April 25, 2012)
|
69
|
+
|
70
|
+
* Added support for measuring the dimensions of TIFF images.
|
71
|
+
|
68
72
|
**1.1.0** (April 1, 2012)
|
69
73
|
|
70
74
|
* Fixed an issue where images with certain invalid orientation values
|
data/lib/dimensions.rb
CHANGED
@@ -3,6 +3,8 @@ require 'dimensions/io'
|
|
3
3
|
require 'dimensions/jpeg_scanner'
|
4
4
|
require 'dimensions/reader'
|
5
5
|
require 'dimensions/scanner'
|
6
|
+
require 'dimensions/tiff_scanner'
|
7
|
+
require 'dimensions/tiff_scanning'
|
6
8
|
require 'dimensions/version'
|
7
9
|
|
8
10
|
# Extends an IO object with the `Dimensions::IO` module, which adds
|
@@ -1,7 +1,11 @@
|
|
1
1
|
require 'dimensions/scanner'
|
2
|
+
require 'dimensions/tiff_scanning'
|
2
3
|
|
3
4
|
module Dimensions
|
4
5
|
class ExifScanner < Scanner
|
6
|
+
include TiffScanning
|
7
|
+
|
8
|
+
ORIENTATION_TAG = 0x0112
|
5
9
|
ORIENTATIONS = [
|
6
10
|
:top_left,
|
7
11
|
:top_right,
|
@@ -23,21 +27,9 @@ module Dimensions
|
|
23
27
|
def scan
|
24
28
|
scan_header
|
25
29
|
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
# Note: This only checks the first IFD for orientation entries,
|
30
|
-
# which seems to work fine in my (limited) testing but might not
|
31
|
-
# play out in practice.
|
32
|
-
entry_count = read_short
|
33
|
-
entry_count.times do |i|
|
34
|
-
skip_to(offset + 2 + (12 * i))
|
35
|
-
tag = read_short
|
36
|
-
|
37
|
-
if tag == 0x0112 # orientation
|
38
|
-
advance(6)
|
39
|
-
value = read_short
|
40
|
-
|
30
|
+
scan_ifd do |tag|
|
31
|
+
if tag == ORIENTATION_TAG
|
32
|
+
value = read_integer_value
|
41
33
|
if valid_orientation?(value)
|
42
34
|
@orientation = ORIENTATIONS[value - 1]
|
43
35
|
end
|
@@ -50,20 +42,5 @@ module Dimensions
|
|
50
42
|
def valid_orientation?(value)
|
51
43
|
(1..ORIENTATIONS.length).include?(value)
|
52
44
|
end
|
53
|
-
|
54
|
-
def scan_header
|
55
|
-
advance(6)
|
56
|
-
scan_endianness
|
57
|
-
scan_tag_mark
|
58
|
-
end
|
59
|
-
|
60
|
-
def scan_endianness
|
61
|
-
tag = [read_char, read_char]
|
62
|
-
@big = tag == [0x4D, 0x4D]
|
63
|
-
end
|
64
|
-
|
65
|
-
def scan_tag_mark
|
66
|
-
raise ScanError unless read_short == 0x002A
|
67
|
-
end
|
68
45
|
end
|
69
46
|
end
|
@@ -51,14 +51,14 @@ module Dimensions
|
|
51
51
|
if length == (size * 3) + 8
|
52
52
|
@width, @height = width, height
|
53
53
|
else
|
54
|
-
|
54
|
+
raise_scan_error
|
55
55
|
end
|
56
56
|
end
|
57
57
|
|
58
58
|
def scan_app1_frame
|
59
59
|
frame = read_frame
|
60
60
|
if frame[0..5] == "Exif\000\000"
|
61
|
-
scanner = ExifScanner.new(frame)
|
61
|
+
scanner = ExifScanner.new(frame[6..-1])
|
62
62
|
if scanner.scan
|
63
63
|
case scanner.orientation
|
64
64
|
when :bottom_right
|
data/lib/dimensions/reader.rb
CHANGED
@@ -2,9 +2,11 @@ require 'dimensions/jpeg_scanner'
|
|
2
2
|
|
3
3
|
module Dimensions
|
4
4
|
class Reader
|
5
|
-
GIF_HEADER
|
6
|
-
PNG_HEADER
|
7
|
-
JPEG_HEADER
|
5
|
+
GIF_HEADER = [0x47, 0x49, 0x46, 0x38]
|
6
|
+
PNG_HEADER = [0x89, 0x50, 0x4E, 0x47]
|
7
|
+
JPEG_HEADER = [0xFF, 0xD8, 0xFF]
|
8
|
+
TIFF_HEADER_I = [0x49, 0x49, 0x2A, 0x00]
|
9
|
+
TIFF_HEADER_M = [0x4D, 0x4D, 0x00, 0x2A]
|
8
10
|
|
9
11
|
attr_reader :type, :width, :height, :angle
|
10
12
|
|
@@ -41,6 +43,8 @@ module Dimensions
|
|
41
43
|
@type = :png
|
42
44
|
elsif match_header(JPEG_HEADER, bytes)
|
43
45
|
@type = :jpeg
|
46
|
+
elsif match_header(TIFF_HEADER_I, bytes) || match_header(TIFF_HEADER_M, bytes)
|
47
|
+
@type = :tiff
|
44
48
|
end
|
45
49
|
|
46
50
|
process @type ? :"extract_#{type}_dimensions" : nil
|
@@ -77,6 +81,16 @@ module Dimensions
|
|
77
81
|
rescue JpegScanner::ScanError
|
78
82
|
end
|
79
83
|
|
84
|
+
def extract_tiff_dimensions
|
85
|
+
scanner = TiffScanner.new(@data)
|
86
|
+
if scanner.scan
|
87
|
+
@width = scanner.width
|
88
|
+
@height = scanner.height
|
89
|
+
process nil
|
90
|
+
end
|
91
|
+
rescue TiffScanner::ScanError
|
92
|
+
end
|
93
|
+
|
80
94
|
def match_header(header, bytes)
|
81
95
|
bytes[0, header.length] == header
|
82
96
|
end
|
data/lib/dimensions/scanner.rb
CHANGED
@@ -2,12 +2,14 @@ module Dimensions
|
|
2
2
|
class Scanner
|
3
3
|
class ScanError < ::StandardError; end
|
4
4
|
|
5
|
+
attr_reader :pos
|
6
|
+
|
5
7
|
def initialize(data)
|
6
8
|
@data = data.dup
|
7
9
|
@data.force_encoding("BINARY") if @data.respond_to?(:force_encoding)
|
8
10
|
@size = @data.length
|
9
11
|
@pos = 0
|
10
|
-
|
12
|
+
big! # endianness
|
11
13
|
end
|
12
14
|
|
13
15
|
def read_char
|
@@ -35,12 +37,24 @@ module Dimensions
|
|
35
37
|
|
36
38
|
def advance(length)
|
37
39
|
@pos += length
|
38
|
-
|
40
|
+
raise_scan_error if @pos > @size
|
39
41
|
end
|
40
42
|
|
41
43
|
def skip_to(pos)
|
42
44
|
@pos = pos
|
43
|
-
|
45
|
+
raise_scan_error if @pos > @size
|
46
|
+
end
|
47
|
+
|
48
|
+
def big!
|
49
|
+
@big = true
|
50
|
+
end
|
51
|
+
|
52
|
+
def little!
|
53
|
+
@big = false
|
54
|
+
end
|
55
|
+
|
56
|
+
def raise_scan_error
|
57
|
+
raise ScanError
|
44
58
|
end
|
45
59
|
end
|
46
60
|
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
require 'dimensions/scanner'
|
2
|
+
require 'dimensions/tiff_scanning'
|
3
|
+
|
4
|
+
module Dimensions
|
5
|
+
class TiffScanner < Scanner
|
6
|
+
include TiffScanning
|
7
|
+
|
8
|
+
WIDTH_TAG = 0x100
|
9
|
+
HEIGHT_TAG = 0x101
|
10
|
+
|
11
|
+
attr_reader :width, :height
|
12
|
+
|
13
|
+
def initialize(data)
|
14
|
+
@width = nil
|
15
|
+
@height = nil
|
16
|
+
super
|
17
|
+
end
|
18
|
+
|
19
|
+
def scan
|
20
|
+
scan_header
|
21
|
+
|
22
|
+
scan_ifd do |tag|
|
23
|
+
if tag == WIDTH_TAG
|
24
|
+
@width = read_integer_value
|
25
|
+
elsif tag == HEIGHT_TAG
|
26
|
+
@height = read_integer_value
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
@width && @height
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
module Dimensions
|
2
|
+
module TiffScanning
|
3
|
+
def scan_header
|
4
|
+
scan_endianness
|
5
|
+
scan_tag_mark
|
6
|
+
scan_and_skip_to_offset
|
7
|
+
end
|
8
|
+
|
9
|
+
def scan_endianness
|
10
|
+
tag = [read_char, read_char]
|
11
|
+
tag == [0x4D, 0x4D] ? big! : little!
|
12
|
+
end
|
13
|
+
|
14
|
+
def scan_tag_mark
|
15
|
+
raise_scan_error unless read_short == 0x002A
|
16
|
+
end
|
17
|
+
|
18
|
+
def scan_and_skip_to_offset
|
19
|
+
offset = read_long
|
20
|
+
skip_to(offset)
|
21
|
+
end
|
22
|
+
|
23
|
+
def scan_ifd
|
24
|
+
offset = pos
|
25
|
+
entry_count = read_short
|
26
|
+
|
27
|
+
entry_count.times do |i|
|
28
|
+
skip_to(offset + 2 + (12 * i))
|
29
|
+
tag = read_short
|
30
|
+
yield tag
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def read_integer_value
|
35
|
+
type = read_short
|
36
|
+
advance(4)
|
37
|
+
|
38
|
+
if type == 3
|
39
|
+
read_short
|
40
|
+
elsif type == 4
|
41
|
+
read_long
|
42
|
+
else
|
43
|
+
raise_scan_error
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
data/lib/dimensions/version.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: dimensions
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.2.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,10 +9,10 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-04-
|
12
|
+
date: 2012-04-25 00:00:00.000000000 Z
|
13
13
|
dependencies: []
|
14
14
|
description: A pure Ruby library for measuring the dimensions and rotation angles
|
15
|
-
of GIF, PNG and
|
15
|
+
of GIF, PNG, JPEG and TIFF images.
|
16
16
|
email:
|
17
17
|
- sstephenson@gmail.com
|
18
18
|
executables: []
|
@@ -26,6 +26,8 @@ files:
|
|
26
26
|
- lib/dimensions/jpeg_scanner.rb
|
27
27
|
- lib/dimensions/reader.rb
|
28
28
|
- lib/dimensions/scanner.rb
|
29
|
+
- lib/dimensions/tiff_scanner.rb
|
30
|
+
- lib/dimensions/tiff_scanning.rb
|
29
31
|
- lib/dimensions/version.rb
|
30
32
|
- lib/dimensions.rb
|
31
33
|
homepage: https://github.com/sstephenson/dimensions
|
@@ -51,5 +53,5 @@ rubyforge_project:
|
|
51
53
|
rubygems_version: 1.8.11
|
52
54
|
signing_key:
|
53
55
|
specification_version: 3
|
54
|
-
summary: Pure Ruby dimension measurement for GIF, PNG and
|
56
|
+
summary: Pure Ruby dimension measurement for GIF, PNG, JPEG and TIFF images
|
55
57
|
test_files: []
|