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 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 JPEG images.
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
@@ -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
- offset = read_long + 6
27
- skip_to(offset)
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
- raise ScanError
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
@@ -2,9 +2,11 @@ require 'dimensions/jpeg_scanner'
2
2
 
3
3
  module Dimensions
4
4
  class Reader
5
- GIF_HEADER = [0x47, 0x49, 0x46, 0x38]
6
- PNG_HEADER = [0x89, 0x50, 0x4E, 0x47]
7
- JPEG_HEADER = [0xFF, 0xD8, 0xFF]
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
@@ -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
- @big = true # endianness
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
- raise ScanError if @pos > @size
40
+ raise_scan_error if @pos > @size
39
41
  end
40
42
 
41
43
  def skip_to(pos)
42
44
  @pos = pos
43
- raise ScanError if @pos > @size
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
@@ -1,3 +1,3 @@
1
1
  module Dimensions
2
- VERSION = "1.1.0"
2
+ VERSION = "1.2.0"
3
3
  end
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.1.0
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-01 00:00:00.000000000 Z
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 JPEG images.
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 JPEG images
56
+ summary: Pure Ruby dimension measurement for GIF, PNG, JPEG and TIFF images
55
57
  test_files: []