image_size 2.1.2 → 3.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/workflows/check.yml +30 -1
- data/.rubocop.yml +6 -0
- data/CHANGELOG.markdown +6 -0
- data/Gemfile +2 -0
- data/README.markdown +18 -12
- data/image_size.gemspec +2 -1
- data/lib/image_size/chunky_reader.rb +44 -0
- data/lib/image_size/reader.rb +64 -0
- data/lib/image_size/seekable_io_reader.rb +28 -0
- data/lib/image_size/stream_io_reader.rb +22 -0
- data/lib/image_size/string_reader.rb +21 -0
- data/lib/image_size/uri_reader.rb +88 -0
- data/lib/image_size.rb +52 -65
- data/spec/image_size/chunky_reader_spec.rb +69 -0
- data/spec/image_size_spec.rb +40 -2
- data/spec/images/.gitattributes +1 -0
- data/spec/images/svg/crlf.72x100.svg +3 -0
- data/spec/images/svg/long.72x100.svg +20 -0
- data/spec/images/svg/long.crlf.72x100.svg +20 -0
- data/spec/images/xbm/crlf.16x32.xbm +11 -0
- data/spec/images/xpm/crlf.24x32.xpm +40 -0
- metadata +38 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 44be96b790fd826a8e6471928ce381cda6a0269bb9a24d7111142b54ff1556bb
|
4
|
+
data.tar.gz: 494d270c18e0e9583ce226e53a478bf5829ce3823cc212c392dc933445962a89
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e33c991f5c78de857a38591d62b6b71f9c95693b0222bdfa7141b94a0359cf76f3e94e3cdf1c424e2935a8f1f397072473c00ac53d0656aeece5ff5e077466dc
|
7
|
+
data.tar.gz: aec5519f54c0dafcc0ae424703567276161ca1c5f53306134c3c3995642a67533d7196b1671e1c74158ffed604a90d2ef61f3e7f5d175246b935954b697afe5d
|
data/.github/workflows/check.yml
CHANGED
@@ -28,7 +28,36 @@ jobs:
|
|
28
28
|
with:
|
29
29
|
ruby-version: "${{ matrix.ruby }}"
|
30
30
|
bundler-cache: true
|
31
|
-
- run: bundle exec rspec
|
31
|
+
- run: bundle exec rspec --format documentation
|
32
|
+
legacy:
|
33
|
+
runs-on: ubuntu-latest
|
34
|
+
container: ${{ matrix.container }}
|
35
|
+
strategy:
|
36
|
+
matrix:
|
37
|
+
container:
|
38
|
+
- rspec/ci:1.8.7
|
39
|
+
- rspec/ci:1.9.3
|
40
|
+
fail-fast: false
|
41
|
+
steps:
|
42
|
+
- uses: actions/checkout@v2
|
43
|
+
- run: bundle install
|
44
|
+
- run: bundle exec rspec --format documentation
|
45
|
+
windows:
|
46
|
+
runs-on: windows-latest
|
47
|
+
strategy:
|
48
|
+
matrix:
|
49
|
+
ruby:
|
50
|
+
- '2.6'
|
51
|
+
- '2.7'
|
52
|
+
- '3.0'
|
53
|
+
fail-fast: false
|
54
|
+
steps:
|
55
|
+
- uses: actions/checkout@v2
|
56
|
+
- uses: ruby/setup-ruby@v1
|
57
|
+
with:
|
58
|
+
ruby-version: "${{ matrix.ruby }}"
|
59
|
+
bundler-cache: true
|
60
|
+
- run: bundle exec rspec --format documentation
|
32
61
|
rubocop:
|
33
62
|
runs-on: ubuntu-latest
|
34
63
|
steps:
|
data/.rubocop.yml
CHANGED
@@ -15,6 +15,9 @@ Layout/CaseIndentation:
|
|
15
15
|
Layout/EndAlignment:
|
16
16
|
EnforcedStyleAlignWith: variable
|
17
17
|
|
18
|
+
Layout/FirstHashElementIndentation:
|
19
|
+
EnforcedStyle: consistent
|
20
|
+
|
18
21
|
Layout/LineLength:
|
19
22
|
Max: 120
|
20
23
|
|
@@ -65,6 +68,9 @@ Style/HashTransformValues:
|
|
65
68
|
Style/IfUnlessModifier:
|
66
69
|
Enabled: false
|
67
70
|
|
71
|
+
Style/NumericPredicate:
|
72
|
+
Enabled: false
|
73
|
+
|
68
74
|
Style/ParallelAssignment:
|
69
75
|
Enabled: false
|
70
76
|
|
data/CHANGELOG.markdown
CHANGED
@@ -2,6 +2,12 @@
|
|
2
2
|
|
3
3
|
## unreleased
|
4
4
|
|
5
|
+
## v3.0.0 (2021-10-17)
|
6
|
+
|
7
|
+
* Read only required chunks of data for files and seekable IOs [@toy](https://github.com/toy)
|
8
|
+
* Raise `FormatError` whenever reading data returns less data than expected [#12](https://github.com/toy/image_size/issues/12) [@toy](https://github.com/toy)
|
9
|
+
* Add `w`/`width` and `h`/`height` accessors to `Size` [@toy](https://github.com/toy)
|
10
|
+
|
5
11
|
## v2.1.2 (2021-08-21)
|
6
12
|
|
7
13
|
* Fix for pcx on big endian systems by forcing reading dimensions in little endian byte order [#15](https://github.com/toy/image_size/issues/15) [#16](https://github.com/toy/image_size/pull/16) [@mtasaka](https://github.com/mtasaka)
|
data/Gemfile
CHANGED
data/README.markdown
CHANGED
@@ -3,8 +3,8 @@
|
|
3
3
|
|
4
4
|
# image_size
|
5
5
|
|
6
|
-
|
7
|
-
|
6
|
+
Measure image size using pure Ruby.
|
7
|
+
Formats: `apng`, `bmp`, `cur`, `gif`, `ico`, `j2c`, `jp2`, `jpeg`, `jpx`, `mng`, `pam`, `pbm`, `pcx`, `pgm`, `png`, `ppm`, `psd`, `svg`, `swf`, `tiff`, `webp`, `xbm`, `xpm`.
|
8
8
|
|
9
9
|
## Installation
|
10
10
|
|
@@ -23,20 +23,26 @@ gem 'image_size', '~> 2.0'
|
|
23
23
|
## Usage
|
24
24
|
|
25
25
|
```ruby
|
26
|
-
image_size = ImageSize.path('spec/
|
26
|
+
image_size = ImageSize.path('spec/images/jpeg/436x429.jpeg')
|
27
27
|
|
28
28
|
image_size.format #=> :jpec
|
29
|
-
image_size.width #=>
|
30
|
-
image_size.height #=>
|
31
|
-
image_size.w #=>
|
32
|
-
image_size.h #=>
|
33
|
-
image_size.size #=> [
|
29
|
+
image_size.width #=> 436
|
30
|
+
image_size.height #=> 429
|
31
|
+
image_size.w #=> 436
|
32
|
+
image_size.h #=> 429
|
33
|
+
image_size.size #=> [436, 429]
|
34
|
+
image_size.size.to_s #=> "436x429"
|
35
|
+
"#{image_size.size}" #=> "436x429"
|
36
|
+
image_size.size.width #=> 436
|
37
|
+
image_size.size.height #=> 429
|
38
|
+
image_size.size.w #=> 436
|
39
|
+
image_size.size.h #=> 429
|
34
40
|
```
|
35
41
|
|
36
42
|
Or using `IO` object:
|
37
43
|
|
38
44
|
```ruby
|
39
|
-
image_size = File.open('spec/
|
45
|
+
image_size = File.open('spec/images/jpeg/436x429.jpeg', 'rb'){ |fh| ImageSize.new(fh) }
|
40
46
|
```
|
41
47
|
|
42
48
|
Any object responding to `read` and `eof?`:
|
@@ -68,14 +74,14 @@ So rewind if needed before passing to `ImageSize` and/or rewind after passing to
|
|
68
74
|
```ruby
|
69
75
|
require 'image_size'
|
70
76
|
|
71
|
-
File.open('spec/
|
77
|
+
File.open('spec/images/jpeg/436x429.jpeg', 'rb') do |fh|
|
72
78
|
image_size = ImageSize.new(fh)
|
73
79
|
|
74
80
|
fh.rewind
|
75
81
|
data = fh.read
|
76
82
|
end
|
77
83
|
|
78
|
-
File.open('spec/
|
84
|
+
File.open('spec/images/jpeg/436x429.jpeg', 'rb') do |fh|
|
79
85
|
data = fh.read
|
80
86
|
fh.rewind
|
81
87
|
|
@@ -88,4 +94,4 @@ end
|
|
88
94
|
This code is free to use under the terms of the [Ruby's licence](LICENSE.txt).
|
89
95
|
|
90
96
|
Original author: Keisuke Minami <keisuke@rccn.com>.\
|
91
|
-
Further development 2010-
|
97
|
+
Further development 2010-2021 Ivan Kuchin https://github.com/toy/image_size
|
data/image_size.gemspec
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
|
3
3
|
Gem::Specification.new do |s|
|
4
4
|
s.name = 'image_size'
|
5
|
-
s.version = '
|
5
|
+
s.version = '3.0.0'
|
6
6
|
s.summary = %q{Measure image size using pure Ruby}
|
7
7
|
s.description = %q{Measure following file dimensions: apng, bmp, cur, gif, ico, j2c, jp2, jpeg, jpx, mng, pam, pbm, pcx, pgm, png, ppm, psd, svg, swf, tiff, webp, xbm, xpm}
|
8
8
|
s.homepage = "https://github.com/toy/#{s.name}"
|
@@ -24,5 +24,6 @@ Gem::Specification.new do |s|
|
|
24
24
|
s.add_development_dependency 'rspec', '~> 3.0'
|
25
25
|
if RUBY_VERSION >= '2.4'
|
26
26
|
s.add_development_dependency 'rubocop', '~> 1.0'
|
27
|
+
s.add_development_dependency 'rubocop-rspec', '~> 2.0'
|
27
28
|
end
|
28
29
|
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'image_size/reader'
|
4
|
+
|
5
|
+
class ImageSize
|
6
|
+
module ChunkyReader # :nodoc:
|
7
|
+
include Reader
|
8
|
+
|
9
|
+
# Size of a chunk in which to read
|
10
|
+
def chunk_size
|
11
|
+
4096
|
12
|
+
end
|
13
|
+
|
14
|
+
# Including class should define method chunk that accepts the chunk number
|
15
|
+
# and returns a string of chunk_size length or shorter for last chunk, or
|
16
|
+
# nil for further chunks.
|
17
|
+
# Determines required chunks, takes parts of them to construct desired
|
18
|
+
# substring, behaves same as str[start, length] except start can't be
|
19
|
+
# negative.
|
20
|
+
def [](offset, length)
|
21
|
+
raise ArgumentError, "expected offset not to be negative, got #{offset}" if offset < 0
|
22
|
+
return if length < 0
|
23
|
+
|
24
|
+
first = offset / chunk_size
|
25
|
+
return unless (first_chunk = chunk(first))
|
26
|
+
|
27
|
+
last = (offset + length - 1) / chunk_size
|
28
|
+
|
29
|
+
if first >= last
|
30
|
+
first_chunk[offset - (first * chunk_size), length]
|
31
|
+
else
|
32
|
+
return unless (first_piece = first_chunk[offset - (first * chunk_size), chunk_size])
|
33
|
+
|
34
|
+
chunks = (first.succ...last).map{ |i| chunk(i) }.unshift(first_piece)
|
35
|
+
|
36
|
+
if (last_chunk = chunk(last))
|
37
|
+
chunks.push(last_chunk[0, offset + length - (last * chunk_size)])
|
38
|
+
end
|
39
|
+
|
40
|
+
chunks.join
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'pathname'
|
4
|
+
require 'stringio'
|
5
|
+
|
6
|
+
class ImageSize
|
7
|
+
module Reader # :nodoc:
|
8
|
+
class << self
|
9
|
+
def open(input)
|
10
|
+
case
|
11
|
+
when input.is_a?(String)
|
12
|
+
yield StringReader.new(input)
|
13
|
+
when input.is_a?(StringIO)
|
14
|
+
yield StringReader.new(input.string)
|
15
|
+
when input.respond_to?(:read) && input.respond_to?(:eof?)
|
16
|
+
yield for_io(input)
|
17
|
+
when input.is_a?(Pathname)
|
18
|
+
input.open('rb'){ |f| yield for_io(f) }
|
19
|
+
else
|
20
|
+
raise ArgumentError, "expected data as String or an object responding to read and eof?, got #{input.class}"
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
private
|
25
|
+
|
26
|
+
def for_io(io)
|
27
|
+
if io.respond_to?(:stat) && !io.stat.file?
|
28
|
+
StreamIOReader.new(io)
|
29
|
+
else
|
30
|
+
begin
|
31
|
+
io.seek(0, IO::SEEK_CUR)
|
32
|
+
SeekableIOReader.new(io)
|
33
|
+
rescue Errno::ESPIPE, Errno::EINVAL
|
34
|
+
StreamIOReader.new(io)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def fetch(offset, length)
|
41
|
+
chunk = self[offset, length]
|
42
|
+
|
43
|
+
unless chunk && chunk.length == length
|
44
|
+
raise FormatError, "Expected #{length} bytes at offset #{offset}, got #{chunk.inspect}"
|
45
|
+
end
|
46
|
+
|
47
|
+
chunk
|
48
|
+
end
|
49
|
+
|
50
|
+
def unpack(offset, length, format)
|
51
|
+
fetch(offset, length).unpack(format)
|
52
|
+
end
|
53
|
+
|
54
|
+
if ''.respond_to?(:unpack1)
|
55
|
+
def unpack1(offset, length, format)
|
56
|
+
fetch(offset, length).unpack1(format)
|
57
|
+
end
|
58
|
+
else
|
59
|
+
def unpack1(offset, length, format)
|
60
|
+
fetch(offset, length).unpack(format)[0]
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'image_size/chunky_reader'
|
4
|
+
|
5
|
+
class ImageSize
|
6
|
+
class SeekableIOReader # :nodoc:
|
7
|
+
include ChunkyReader
|
8
|
+
|
9
|
+
def initialize(io)
|
10
|
+
@io = io
|
11
|
+
@pos = 0
|
12
|
+
@chunks = {}
|
13
|
+
end
|
14
|
+
|
15
|
+
private
|
16
|
+
|
17
|
+
def chunk(i)
|
18
|
+
unless @chunks.key?(i)
|
19
|
+
@io.seek((chunk_size * i) - @pos, IO::SEEK_CUR)
|
20
|
+
data = @io.read(chunk_size)
|
21
|
+
@pos += data.length
|
22
|
+
@chunks[i] = data
|
23
|
+
end
|
24
|
+
|
25
|
+
@chunks[i]
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'image_size/chunky_reader'
|
4
|
+
|
5
|
+
class ImageSize
|
6
|
+
class StreamIOReader # :nodoc:
|
7
|
+
include ChunkyReader
|
8
|
+
|
9
|
+
def initialize(io)
|
10
|
+
@io = io
|
11
|
+
@chunks = []
|
12
|
+
end
|
13
|
+
|
14
|
+
private
|
15
|
+
|
16
|
+
def chunk(i)
|
17
|
+
@chunks << @io.read(chunk_size) while i >= @chunks.length && !@io.eof?
|
18
|
+
|
19
|
+
@chunks[i]
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'image_size/reader'
|
4
|
+
|
5
|
+
class ImageSize
|
6
|
+
class StringReader # :nodoc:
|
7
|
+
include Reader
|
8
|
+
|
9
|
+
def initialize(string)
|
10
|
+
@string = if string.respond_to?(:encoding) && string.encoding.name != 'ASCII-8BIT'
|
11
|
+
string.dup.force_encoding('ASCII-8BIT')
|
12
|
+
else
|
13
|
+
string
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def [](offset, length)
|
18
|
+
@string[offset, length]
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,88 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'image_size/reader'
|
4
|
+
require 'image_size/chunky_reader'
|
5
|
+
|
6
|
+
require 'net/https'
|
7
|
+
require 'uri'
|
8
|
+
|
9
|
+
# This is a hacky experiment and not part of public API
|
10
|
+
#
|
11
|
+
# It adds ability to fetch size of image from http server while downloading only
|
12
|
+
# needed chunks if the server recognises Range header
|
13
|
+
class ImageSize
|
14
|
+
class URIReader # :nodoc:
|
15
|
+
include ChunkyReader
|
16
|
+
|
17
|
+
def initialize(uri, redirects = 5)
|
18
|
+
if !@http || @http.address != uri.host || @http.port != uri.port
|
19
|
+
@http.finish if @http
|
20
|
+
@http = Net::HTTP.new(uri.host, uri.port)
|
21
|
+
@http.use_ssl = true if uri.scheme == 'https'
|
22
|
+
@http.start
|
23
|
+
end
|
24
|
+
|
25
|
+
@request_uri = uri.request_uri
|
26
|
+
response = request_chunk(0)
|
27
|
+
|
28
|
+
case response
|
29
|
+
when Net::HTTPRedirection
|
30
|
+
raise "Too many redirects: #{response['location']}" unless redirects > 0
|
31
|
+
|
32
|
+
initialize(uri + response['location'], redirects - 1)
|
33
|
+
when Net::HTTPOK
|
34
|
+
@body = response.body
|
35
|
+
when Net::HTTPPartialContent
|
36
|
+
@chunks = { 0 => response.body }
|
37
|
+
else
|
38
|
+
raise "Unexpected response: #{response}"
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def [](offset, length)
|
43
|
+
if @body
|
44
|
+
@body[offset, length]
|
45
|
+
else
|
46
|
+
super
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def chunk(i)
|
51
|
+
unless @chunks.key?(i)
|
52
|
+
response = request_chunk(i)
|
53
|
+
case response
|
54
|
+
when Net::HTTPPartialContent
|
55
|
+
@chunks[i] = response.body
|
56
|
+
else
|
57
|
+
raise "Unexpected response: #{response}"
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
@chunks[i]
|
62
|
+
end
|
63
|
+
|
64
|
+
private
|
65
|
+
|
66
|
+
def request_chunk(i)
|
67
|
+
@http.get(@request_uri, 'Range' => "bytes=#{chunk_size * i}-#{(chunk_size * (i + 1)) - 1}")
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
module Reader # :nodoc:
|
72
|
+
class << self
|
73
|
+
def open_with_uri(input, &block)
|
74
|
+
if input.is_a?(URI)
|
75
|
+
yield URIReader.new(input)
|
76
|
+
else
|
77
|
+
open_without_uri(input, &block)
|
78
|
+
end
|
79
|
+
end
|
80
|
+
alias_method :open_without_uri, :open
|
81
|
+
alias_method :open, :open_with_uri
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
def self.url(url)
|
86
|
+
new(url.is_a?(URI) ? url : URI(url))
|
87
|
+
end
|
88
|
+
end
|
data/lib/image_size.rb
CHANGED
@@ -1,7 +1,10 @@
|
|
1
1
|
# encoding: BINARY
|
2
2
|
# frozen_string_literal: true
|
3
3
|
|
4
|
-
require '
|
4
|
+
require 'image_size/reader'
|
5
|
+
require 'image_size/seekable_io_reader'
|
6
|
+
require 'image_size/stream_io_reader'
|
7
|
+
require 'image_size/string_reader'
|
5
8
|
|
6
9
|
# Determine image format and size
|
7
10
|
class ImageSize
|
@@ -13,38 +16,23 @@ class ImageSize
|
|
13
16
|
def to_s
|
14
17
|
join('x')
|
15
18
|
end
|
16
|
-
end
|
17
|
-
|
18
|
-
class ImageReader # :nodoc:
|
19
|
-
attr_reader :data
|
20
19
|
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
elsif data_or_io.respond_to?(:read) && data_or_io.respond_to?(:eof?)
|
25
|
-
data_or_io
|
26
|
-
else
|
27
|
-
raise ArgumentError, "expected data as String or an object responding to read and eof?, got #{data_or_io.class}"
|
28
|
-
end
|
29
|
-
@data = String.new # not frozen
|
20
|
+
# get first element
|
21
|
+
def width
|
22
|
+
self[0]
|
30
23
|
end
|
24
|
+
alias_method :w, :width
|
31
25
|
|
32
|
-
|
33
|
-
def
|
34
|
-
|
35
|
-
data = @io.read(CHUNK)
|
36
|
-
break unless data
|
37
|
-
|
38
|
-
data.force_encoding(@data.encoding) if data.respond_to?(:encoding)
|
39
|
-
@data << data
|
40
|
-
end
|
41
|
-
@data[offset, length]
|
26
|
+
# get second element
|
27
|
+
def height
|
28
|
+
self[1]
|
42
29
|
end
|
30
|
+
alias_method :h, :height
|
43
31
|
end
|
44
32
|
|
45
33
|
# Given path to image finds its format, width and height
|
46
34
|
def self.path(path)
|
47
|
-
|
35
|
+
new(Pathname.new(path))
|
48
36
|
end
|
49
37
|
|
50
38
|
# Used for svg
|
@@ -59,11 +47,10 @@ class ImageSize
|
|
59
47
|
|
60
48
|
# Given image as any class responding to read and eof? or data as String, finds its format and dimensions
|
61
49
|
def initialize(data)
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
@width, @height = send("size_of_#{@format}", ir)
|
50
|
+
Reader.open(data) do |ir|
|
51
|
+
@format = detect_format(ir)
|
52
|
+
@width, @height = send("size_of_#{@format}", ir) if @format
|
53
|
+
end
|
67
54
|
end
|
68
55
|
|
69
56
|
# Image format
|
@@ -100,7 +87,7 @@ private
|
|
100
87
|
when head =~ %r{/\* XPM \*/} then :xpm
|
101
88
|
when head[0, 4] == '8BPS' then :psd
|
102
89
|
when head[0, 3] =~ /[FC]WS/ then :swf
|
103
|
-
when head =~ SVG_R || (head =~ XML_R && ir[0, 4096]
|
90
|
+
when head =~ SVG_R || (head =~ XML_R && ir[0, 4096] =~ SVG_R) then :svg
|
104
91
|
when head[0, 2] =~ /\n[\0-\5]/ then :pcx
|
105
92
|
when head[0, 12] =~ /RIFF(?m:....)WEBP/ then :webp
|
106
93
|
when head[0, 4] == "\0\0\1\0" then :ico
|
@@ -117,7 +104,7 @@ private
|
|
117
104
|
break if ['IDAT', 'IEND', nil].include?(type)
|
118
105
|
return :apng if type == 'acTL'
|
119
106
|
|
120
|
-
length = ir
|
107
|
+
length = ir.unpack1(offset, 4, 'N')
|
121
108
|
offset += 8 + length + 4
|
122
109
|
end
|
123
110
|
:png
|
@@ -144,7 +131,7 @@ private
|
|
144
131
|
end
|
145
132
|
|
146
133
|
def size_of_gif(ir)
|
147
|
-
ir
|
134
|
+
ir.unpack(6, 4, 'vv')
|
148
135
|
end
|
149
136
|
|
150
137
|
def size_of_mng(ir)
|
@@ -152,7 +139,7 @@ private
|
|
152
139
|
raise FormatError, 'MHDR not in place for MNG'
|
153
140
|
end
|
154
141
|
|
155
|
-
ir
|
142
|
+
ir.unpack(16, 8, 'NN')
|
156
143
|
end
|
157
144
|
|
158
145
|
def size_of_png(ir)
|
@@ -160,7 +147,7 @@ private
|
|
160
147
|
raise FormatError, 'IHDR not in place for PNG'
|
161
148
|
end
|
162
149
|
|
163
|
-
ir
|
150
|
+
ir.unpack(16, 8, 'NN')
|
164
151
|
end
|
165
152
|
alias_method :size_of_apng, :size_of_png
|
166
153
|
|
@@ -178,11 +165,11 @@ private
|
|
178
165
|
offset += 1 until section_marker != ir[offset + 1, 1]
|
179
166
|
raise FormatError, 'EOF in JPEG' if ir[offset, 1].nil?
|
180
167
|
|
181
|
-
|
168
|
+
code, length = ir.unpack(offset, 4, 'xCn')
|
182
169
|
offset += 4
|
183
170
|
|
184
171
|
if JPEG_CODE_CHECK.include?(code)
|
185
|
-
return ir
|
172
|
+
return ir.unpack(offset + 1, 4, 'nn').reverse
|
186
173
|
end
|
187
174
|
|
188
175
|
offset += length - 2
|
@@ -190,11 +177,11 @@ private
|
|
190
177
|
end
|
191
178
|
|
192
179
|
def size_of_bmp(ir)
|
193
|
-
header_size = ir
|
180
|
+
header_size = ir.unpack1(14, 4, 'V')
|
194
181
|
if header_size == 12
|
195
|
-
ir
|
182
|
+
ir.unpack(18, 4, 'vv')
|
196
183
|
else
|
197
|
-
ir
|
184
|
+
ir.unpack(18, 8, 'VV').map do |n|
|
198
185
|
if n > 0x7fff_ffff
|
199
186
|
0x1_0000_0000 - n # absolute value of converted to signed
|
200
187
|
else
|
@@ -216,7 +203,7 @@ private
|
|
216
203
|
def size_of_pam(ir)
|
217
204
|
width = height = nil
|
218
205
|
offset = 3
|
219
|
-
|
206
|
+
until width && height
|
220
207
|
if ir[offset, 1] == '#'
|
221
208
|
offset += 1 until ["\n", '', nil].include?(ir[offset, 1])
|
222
209
|
offset += 1
|
@@ -235,7 +222,6 @@ private
|
|
235
222
|
raise FormatError, "Unexpected data in PAM header: #{chunk.inspect}"
|
236
223
|
end
|
237
224
|
offset += $&.length
|
238
|
-
break if width && height
|
239
225
|
end
|
240
226
|
end
|
241
227
|
[width, height]
|
@@ -259,23 +245,23 @@ private
|
|
259
245
|
end
|
260
246
|
|
261
247
|
def size_of_psd(ir)
|
262
|
-
ir
|
248
|
+
ir.unpack(14, 8, 'NN').reverse
|
263
249
|
end
|
264
250
|
|
265
251
|
def size_of_tiff(ir)
|
266
|
-
endian2b = ir
|
252
|
+
endian2b = ir.fetch(0, 4) == "II*\000" ? 'v' : 'n'
|
267
253
|
endian4b = endian2b.upcase
|
268
254
|
packspec = [nil, 'C', nil, endian2b, endian4b, nil, 'c', nil, endian2b, endian4b]
|
269
255
|
|
270
|
-
offset = ir
|
271
|
-
num_dirent = ir
|
256
|
+
offset = ir.unpack1(4, 4, endian4b)
|
257
|
+
num_dirent = ir.unpack1(offset, 2, endian2b)
|
272
258
|
offset += 2
|
273
259
|
num_dirent = offset + (num_dirent * 12)
|
274
260
|
|
275
261
|
width = height = nil
|
276
262
|
until width && height
|
277
|
-
ifd = ir
|
278
|
-
raise FormatError, 'Reached end of directory entries in TIFF' if
|
263
|
+
ifd = ir.fetch(offset, 12)
|
264
|
+
raise FormatError, 'Reached end of directory entries in TIFF' if offset > num_dirent
|
279
265
|
|
280
266
|
tag, type = ifd.unpack(endian2b * 2)
|
281
267
|
offset += 12
|
@@ -294,14 +280,14 @@ private
|
|
294
280
|
end
|
295
281
|
|
296
282
|
def size_of_pcx(ir)
|
297
|
-
parts = ir
|
283
|
+
parts = ir.unpack(4, 8, 'v4')
|
298
284
|
[parts[2] - parts[0] + 1, parts[3] - parts[1] + 1]
|
299
285
|
end
|
300
286
|
|
301
287
|
def size_of_swf(ir)
|
302
|
-
value_bit_length = ir
|
303
|
-
bit_length = 5 + value_bit_length * 4
|
304
|
-
rect_bits = ir
|
288
|
+
value_bit_length = ir.unpack1(8, 1, 'B5').to_i(2)
|
289
|
+
bit_length = 5 + (value_bit_length * 4)
|
290
|
+
rect_bits = ir.unpack1(8, (bit_length / 8) + 1, "B#{bit_length}")
|
305
291
|
values = rect_bits[5..-1].unpack("a#{value_bit_length}" * 4).map{ |bits| bits.to_i(2) }
|
306
292
|
x_min, x_max, y_min, y_max = values
|
307
293
|
[(x_max - x_min) / 20, (y_max - y_min) / 20]
|
@@ -309,7 +295,8 @@ private
|
|
309
295
|
|
310
296
|
def size_of_svg(ir)
|
311
297
|
attributes = {}
|
312
|
-
ir
|
298
|
+
svg_tag = ir[0, 1024][SVG_R, 1] || ir[0, 4096][SVG_R, 1]
|
299
|
+
svg_tag.scan(/(\S+)=(?:'([^']*)'|"([^"]*)"|([^'"\s]*))/) do |name, v0, v1, v2|
|
313
300
|
attributes[name] = v0 || v1 || v2
|
314
301
|
end
|
315
302
|
dpi = self.class.dpi
|
@@ -330,20 +317,20 @@ private
|
|
330
317
|
end
|
331
318
|
|
332
319
|
def size_of_ico(ir)
|
333
|
-
ir
|
320
|
+
ir.unpack(6, 2, 'CC').map{ |v| v.zero? ? 256 : v }
|
334
321
|
end
|
335
322
|
alias_method :size_of_cur, :size_of_ico
|
336
323
|
|
337
324
|
def size_of_webp(ir)
|
338
|
-
case ir
|
325
|
+
case ir.fetch(12, 4)
|
339
326
|
when 'VP8 '
|
340
|
-
ir
|
327
|
+
ir.unpack(26, 4, 'vv').map{ |v| v & 0x3fff }
|
341
328
|
when 'VP8L'
|
342
|
-
n = ir
|
343
|
-
[(n & 0x3fff) + 1, (n >> 14 & 0x3fff) + 1]
|
329
|
+
n = ir.unpack1(21, 4, 'V')
|
330
|
+
[(n & 0x3fff) + 1, ((n >> 14) & 0x3fff) + 1]
|
344
331
|
when 'VP8X'
|
345
|
-
w16, w8, h16, h8 = ir
|
346
|
-
[(w16 | w8 << 16) + 1, (h16 | h8 << 16) + 1]
|
332
|
+
w16, w8, h16, h8 = ir.unpack(24, 6, 'vCvC')
|
333
|
+
[(w16 | (w8 << 16)) + 1, (h16 | (h8 << 16)) + 1]
|
347
334
|
end
|
348
335
|
end
|
349
336
|
|
@@ -355,13 +342,13 @@ private
|
|
355
342
|
break if stop && offset >= stop
|
356
343
|
break if ir[offset, 4] == '' || ir[offset, 4].nil?
|
357
344
|
|
358
|
-
size = ir
|
359
|
-
type = ir
|
345
|
+
size = ir.unpack1(offset, 4, 'N')
|
346
|
+
type = ir.fetch(offset + 4, 4)
|
360
347
|
|
361
348
|
data_offset = 8
|
362
349
|
case size
|
363
350
|
when 1
|
364
|
-
size = ir
|
351
|
+
size = ir.unpack1(offset, 8, 'Q>')
|
365
352
|
data_offset = 16
|
366
353
|
raise FormatError, "Unexpected xl-box size #{size}" if (1..15).include?(size)
|
367
354
|
when 2..7
|
@@ -373,7 +360,7 @@ private
|
|
373
360
|
offset += data_offset
|
374
361
|
in_header = true
|
375
362
|
elsif in_header && type == 'ihdr'
|
376
|
-
return ir
|
363
|
+
return ir.unpack(offset + data_offset, 8, 'NN').reverse
|
377
364
|
else
|
378
365
|
break if size.zero? # box to the end of file
|
379
366
|
|
@@ -384,6 +371,6 @@ private
|
|
384
371
|
alias_method :size_of_jpx, :size_of_jp2
|
385
372
|
|
386
373
|
def size_of_j2c(ir)
|
387
|
-
ir
|
374
|
+
ir.unpack(8, 8, 'NN')
|
388
375
|
end
|
389
376
|
end
|
@@ -0,0 +1,69 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'rspec'
|
4
|
+
|
5
|
+
require 'image_size/chunky_reader'
|
6
|
+
|
7
|
+
describe ImageSize::ChunkyReader do
|
8
|
+
context :[] do
|
9
|
+
test_reader = Class.new do
|
10
|
+
include ImageSize::ChunkyReader
|
11
|
+
|
12
|
+
def initialize(string)
|
13
|
+
@string = string
|
14
|
+
end
|
15
|
+
|
16
|
+
private
|
17
|
+
|
18
|
+
def chunk(i)
|
19
|
+
@string[i * chunk_size, chunk_size]
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
custom_chunk_size_reader = Class.new(test_reader) do
|
24
|
+
def chunk_size
|
25
|
+
100
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
{
|
30
|
+
'empty string' => '',
|
31
|
+
'a bit of data' => 'foo bar baz',
|
32
|
+
'a lot of data' => File.open('GPL', 'rb', &:read),
|
33
|
+
}.each do |data_description, data|
|
34
|
+
{
|
35
|
+
'default' => test_reader.new(data),
|
36
|
+
'custom' => custom_chunk_size_reader.new(data),
|
37
|
+
}.each do |chunk_size_description, reader|
|
38
|
+
context "for #{data_description} using reader with #{chunk_size_description} chunk size" do
|
39
|
+
it 'raises ArgumentError for negative offset' do
|
40
|
+
[-1, 0, 1, 100].each do |length|
|
41
|
+
expect{ reader[-1, length] }.to raise_exception(ArgumentError)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
it 'behaves same as fetching a string for any offset and length' do
|
46
|
+
full_chunks = data.length / reader.chunk_size
|
47
|
+
offsets = [0, 1, full_chunks - 1, full_chunks, full_chunks + 1].map do |i|
|
48
|
+
[-1, 0, 1].map do |add|
|
49
|
+
(i * reader.chunk_size) + add
|
50
|
+
end
|
51
|
+
end.flatten
|
52
|
+
|
53
|
+
offsets.each do |offset|
|
54
|
+
next if offset < 0
|
55
|
+
|
56
|
+
offsets.each do |offset_b|
|
57
|
+
length = offset_b - offset
|
58
|
+
expect(reader[offset, length]).to eq(data[offset, length]),
|
59
|
+
"for offset #{offset} and length #{length}\n"\
|
60
|
+
"expected: #{data[offset, length].inspect}\n"\
|
61
|
+
" got: #{reader[offset, length].inspect}"
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
data/spec/image_size_spec.rb
CHANGED
@@ -1,13 +1,35 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require 'rspec'
|
4
|
+
|
4
5
|
require 'image_size'
|
6
|
+
require 'image_size/uri_reader'
|
7
|
+
|
5
8
|
require 'tempfile'
|
9
|
+
require 'shellwords'
|
10
|
+
require 'webrick'
|
6
11
|
|
7
12
|
describe ImageSize do
|
13
|
+
before :all do
|
14
|
+
@server = WEBrick::HTTPServer.new({
|
15
|
+
:Logger => WEBrick::Log.new(StringIO.new),
|
16
|
+
:AccessLog => [],
|
17
|
+
:BindAddress => '127.0.0.1',
|
18
|
+
:Port => 0, # get the next available port
|
19
|
+
:DocumentRoot => '.',
|
20
|
+
})
|
21
|
+
@server_thread = Thread.new{ @server.start }
|
22
|
+
@server_base_url = URI("http://localhost:#{@server.config[:Port]}/")
|
23
|
+
end
|
24
|
+
|
25
|
+
after :all do
|
26
|
+
@server.shutdown
|
27
|
+
@server_thread.join
|
28
|
+
end
|
29
|
+
|
8
30
|
max_filesize = 16_384
|
9
31
|
|
10
|
-
(Dir['spec/images/*/*.*'] + [__FILE__]).each do |path|
|
32
|
+
(Dir['spec/images/*/*.*'] + [__FILE__[%r{spec/.+?\z}]]).each do |path|
|
11
33
|
filesize = File.size(path)
|
12
34
|
warn "#{path} is too big #{filesize} (max #{max_filesize})" if filesize > max_filesize
|
13
35
|
|
@@ -50,13 +72,22 @@ describe ImageSize do
|
|
50
72
|
end
|
51
73
|
end
|
52
74
|
|
75
|
+
context 'given as unseekable IO' do
|
76
|
+
it 'gets format and dimensions' do
|
77
|
+
IO.popen(%W[cat #{path}].shelljoin, 'rb') do |io|
|
78
|
+
image_size = ImageSize.new(io)
|
79
|
+
expect(image_size).to have_attributes(attributes)
|
80
|
+
expect(io).not_to be_closed
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
53
85
|
context 'given as StringIO' do
|
54
86
|
it 'gets format and dimensions' do
|
55
87
|
io = StringIO.new(file_data)
|
56
88
|
image_size = ImageSize.new(io)
|
57
89
|
expect(image_size).to have_attributes(attributes)
|
58
90
|
expect(io).not_to be_closed
|
59
|
-
expect(io.pos).to_not be_zero
|
60
91
|
io.rewind
|
61
92
|
expect(io.read).to eq(file_data)
|
62
93
|
end
|
@@ -84,6 +115,13 @@ describe ImageSize do
|
|
84
115
|
expect(image_size).to have_attributes(attributes)
|
85
116
|
end
|
86
117
|
end
|
118
|
+
|
119
|
+
context 'fetching from webserver' do
|
120
|
+
it 'gets format and dimensions' do
|
121
|
+
image_size = ImageSize.url(@server_base_url + path)
|
122
|
+
expect(image_size).to have_attributes(attributes)
|
123
|
+
end
|
124
|
+
end
|
87
125
|
end
|
88
126
|
end
|
89
127
|
|
@@ -0,0 +1 @@
|
|
1
|
+
* -text
|
@@ -0,0 +1,20 @@
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
2
|
+
<!--[[[[[[[[[[[[[[[[[[[[[[[[[[[[]]]]]]]]]]]]]]]]]]]]]]]]]]]]-->
|
3
|
+
<!--[ [[[[[[[[[[[[[[[[[[[[[[[[]]]]]]]]]]]]]]]]]]]]]]]] ]-->
|
4
|
+
<!--[ [ [[[[[[[[[[[[[[[[[[[[]]]]]]]]]]]]]]]]]]]] ] ]-->
|
5
|
+
<!--[ [ [ [[[[[[[[[[[[[[[[]]]]]]]]]]]]]]]] ] ] ]-->
|
6
|
+
<!--[ [ [ [ [[[[[[[[[[[[]]]]]]]]]]]] ] ] ] ]-->
|
7
|
+
<!--[ [ [ [ [ [[[[[[[[]]]]]]]] ] ] ] ] ]-->
|
8
|
+
<!--[ [ [ [ [ [ [[[[]]]] ] ] ] ] ] ]-->
|
9
|
+
<!--[ [ [ [ [ [ [ ] ] ] ] ] ] ]-->
|
10
|
+
<!--[ [ [ [ [ [ [ ] ] ] ] ] ] ]-->
|
11
|
+
<!--[ [ [ [ [ [ [[[[]]]] ] ] ] ] ] ]-->
|
12
|
+
<!--[ [ [ [ [ [[[[[[[[]]]]]]]] ] ] ] ] ]-->
|
13
|
+
<!--[ [ [ [ [[[[[[[[[[[[]]]]]]]]]]]] ] ] ] ]-->
|
14
|
+
<!--[ [ [ [[[[[[[[[[[[[[[[]]]]]]]]]]]]]]]] ] ] ]-->
|
15
|
+
<!--[ [ [[[[[[[[[[[[[[[[[[[[]]]]]]]]]]]]]]]]]]]] ] ]-->
|
16
|
+
<!--[ [[[[[[[[[[[[[[[[[[[[[[[[]]]]]]]]]]]]]]]]]]]]]]]] ]-->
|
17
|
+
<!--[[[[[[[[[[[[[[[[[[[[[[[[[[[[]]]]]]]]]]]]]]]]]]]]]]]]]]]]-->
|
18
|
+
<svg width="1in" height="100" xmlns="http://www.w3.org/2000/svg">
|
19
|
+
<circle cx="36" cy="50" r="30" stroke="black" stroke-width="10" fill="red" />
|
20
|
+
</svg>
|
@@ -0,0 +1,20 @@
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
2
|
+
<!--[[[[[[[[[[[[[[[[[[[[[[[[[[[[]]]]]]]]]]]]]]]]]]]]]]]]]]]]-->
|
3
|
+
<!--[ [[[[[[[[[[[[[[[[[[[[[[[[]]]]]]]]]]]]]]]]]]]]]]]] ]-->
|
4
|
+
<!--[ [ [[[[[[[[[[[[[[[[[[[[]]]]]]]]]]]]]]]]]]]] ] ]-->
|
5
|
+
<!--[ [ [ [[[[[[[[[[[[[[[[]]]]]]]]]]]]]]]] ] ] ]-->
|
6
|
+
<!--[ [ [ [ [[[[[[[[[[[[]]]]]]]]]]]] ] ] ] ]-->
|
7
|
+
<!--[ [ [ [ [ [[[[[[[[]]]]]]]] ] ] ] ] ]-->
|
8
|
+
<!--[ [ [ [ [ [ [[[[]]]] ] ] ] ] ] ]-->
|
9
|
+
<!--[ [ [ [ [ [ [ ] ] ] ] ] ] ]-->
|
10
|
+
<!--[ [ [ [ [ [ [ ] ] ] ] ] ] ]-->
|
11
|
+
<!--[ [ [ [ [ [ [[[[]]]] ] ] ] ] ] ]-->
|
12
|
+
<!--[ [ [ [ [ [[[[[[[[]]]]]]]] ] ] ] ] ]-->
|
13
|
+
<!--[ [ [ [ [[[[[[[[[[[[]]]]]]]]]]]] ] ] ] ]-->
|
14
|
+
<!--[ [ [ [[[[[[[[[[[[[[[[]]]]]]]]]]]]]]]] ] ] ]-->
|
15
|
+
<!--[ [ [[[[[[[[[[[[[[[[[[[[]]]]]]]]]]]]]]]]]]]] ] ]-->
|
16
|
+
<!--[ [[[[[[[[[[[[[[[[[[[[[[[[]]]]]]]]]]]]]]]]]]]]]]]] ]-->
|
17
|
+
<!--[[[[[[[[[[[[[[[[[[[[[[[[[[[[]]]]]]]]]]]]]]]]]]]]]]]]]]]]-->
|
18
|
+
<svg width="1in" height="100" xmlns="http://www.w3.org/2000/svg">
|
19
|
+
<circle cx="36" cy="50" r="30" stroke="black" stroke-width="10" fill="red" />
|
20
|
+
</svg>
|
@@ -0,0 +1,11 @@
|
|
1
|
+
#define cursor_width 16
|
2
|
+
#define cursor_height 32
|
3
|
+
static unsigned char cursor_bits[] = {
|
4
|
+
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
5
|
+
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
6
|
+
0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x84, 0x10,
|
7
|
+
0xe8, 0x0b, 0x90, 0x04, 0xa8, 0x0a, 0x88, 0x08,
|
8
|
+
0xfe, 0x3f, 0x88, 0x08, 0xa8, 0x0a, 0x90, 0x04,
|
9
|
+
0xe8, 0x0b, 0x84, 0x10, 0x80, 0x00, 0x00, 0x00,
|
10
|
+
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
11
|
+
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
|
@@ -0,0 +1,40 @@
|
|
1
|
+
/* XPM */
|
2
|
+
static char *test2[] = {
|
3
|
+
/* columns rows colors chars-per-pixel */
|
4
|
+
"24 32 2 1 ",
|
5
|
+
" c red",
|
6
|
+
". c white",
|
7
|
+
/* pixels */
|
8
|
+
"........................",
|
9
|
+
"........................",
|
10
|
+
"........................",
|
11
|
+
"........................",
|
12
|
+
"........................",
|
13
|
+
"........................",
|
14
|
+
".. .................. ",
|
15
|
+
".. ................ ",
|
16
|
+
"... .............. .",
|
17
|
+
".... ............ ..",
|
18
|
+
"..... .......... ...",
|
19
|
+
"...... ........ ....",
|
20
|
+
"....... ...... .....",
|
21
|
+
"........ .... ......",
|
22
|
+
"......... .. .......",
|
23
|
+
".......... ........",
|
24
|
+
"........... .........",
|
25
|
+
"............ .........",
|
26
|
+
"........... ........",
|
27
|
+
".......... . .......",
|
28
|
+
"......... ... ......",
|
29
|
+
"........ ..... .....",
|
30
|
+
"....... ....... ....",
|
31
|
+
"...... ......... ...",
|
32
|
+
"..... ........... ..",
|
33
|
+
".... ............. .",
|
34
|
+
"... ............... ",
|
35
|
+
".. ................. ",
|
36
|
+
".. ................... ",
|
37
|
+
"........................",
|
38
|
+
"........................",
|
39
|
+
"........................"
|
40
|
+
};
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: image_size
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 3.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Keisuke Minami
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2021-
|
12
|
+
date: 2021-10-17 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rspec
|
@@ -39,6 +39,20 @@ dependencies:
|
|
39
39
|
- - "~>"
|
40
40
|
- !ruby/object:Gem::Version
|
41
41
|
version: '1.0'
|
42
|
+
- !ruby/object:Gem::Dependency
|
43
|
+
name: rubocop-rspec
|
44
|
+
requirement: !ruby/object:Gem::Requirement
|
45
|
+
requirements:
|
46
|
+
- - "~>"
|
47
|
+
- !ruby/object:Gem::Version
|
48
|
+
version: '2.0'
|
49
|
+
type: :development
|
50
|
+
prerelease: false
|
51
|
+
version_requirements: !ruby/object:Gem::Requirement
|
52
|
+
requirements:
|
53
|
+
- - "~>"
|
54
|
+
- !ruby/object:Gem::Version
|
55
|
+
version: '2.0'
|
42
56
|
description: 'Measure following file dimensions: apng, bmp, cur, gif, ico, j2c, jp2,
|
43
57
|
jpeg, jpx, mng, pam, pbm, pcx, pgm, png, ppm, psd, svg, swf, tiff, webp, xbm, xpm'
|
44
58
|
email:
|
@@ -57,7 +71,15 @@ files:
|
|
57
71
|
- README.markdown
|
58
72
|
- image_size.gemspec
|
59
73
|
- lib/image_size.rb
|
74
|
+
- lib/image_size/chunky_reader.rb
|
75
|
+
- lib/image_size/reader.rb
|
76
|
+
- lib/image_size/seekable_io_reader.rb
|
77
|
+
- lib/image_size/stream_io_reader.rb
|
78
|
+
- lib/image_size/string_reader.rb
|
79
|
+
- lib/image_size/uri_reader.rb
|
80
|
+
- spec/image_size/chunky_reader_spec.rb
|
60
81
|
- spec/image_size_spec.rb
|
82
|
+
- spec/images/.gitattributes
|
61
83
|
- spec/images/bmp/v2.42x50.bmp
|
62
84
|
- spec/images/bmp/v3-bottom2top.42x50.bmp
|
63
85
|
- spec/images/bmp/v3-top2bottom.42x50.bmp
|
@@ -82,6 +104,9 @@ files:
|
|
82
104
|
- spec/images/pnm/ascii.22x25.ppm
|
83
105
|
- spec/images/psd/16x20.psd
|
84
106
|
- spec/images/svg/72x100.svg
|
107
|
+
- spec/images/svg/crlf.72x100.svg
|
108
|
+
- spec/images/svg/long.72x100.svg
|
109
|
+
- spec/images/svg/long.crlf.72x100.svg
|
85
110
|
- spec/images/swf/450x200.swf
|
86
111
|
- spec/images/tiff/big-endian.68x49.tiff
|
87
112
|
- spec/images/tiff/little-endian.40x68.tiff
|
@@ -89,14 +114,16 @@ files:
|
|
89
114
|
- spec/images/webp/lossless.16x32.webp
|
90
115
|
- spec/images/webp/lossy.16x32.webp
|
91
116
|
- spec/images/xbm/16x32.xbm
|
117
|
+
- spec/images/xbm/crlf.16x32.xbm
|
92
118
|
- spec/images/xpm/24x32.xpm
|
119
|
+
- spec/images/xpm/crlf.24x32.xpm
|
93
120
|
homepage: https://github.com/toy/image_size
|
94
121
|
licenses:
|
95
122
|
- Ruby
|
96
123
|
metadata:
|
97
124
|
bug_tracker_uri: https://github.com/toy/image_size/issues
|
98
125
|
changelog_uri: https://github.com/toy/image_size/blob/master/CHANGELOG.markdown
|
99
|
-
documentation_uri: https://www.rubydoc.info/gems/image_size/
|
126
|
+
documentation_uri: https://www.rubydoc.info/gems/image_size/3.0.0
|
100
127
|
source_code_uri: https://github.com/toy/image_size
|
101
128
|
post_install_message:
|
102
129
|
rdoc_options: []
|
@@ -113,12 +140,14 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
113
140
|
- !ruby/object:Gem::Version
|
114
141
|
version: '0'
|
115
142
|
requirements: []
|
116
|
-
rubygems_version: 3.2.
|
143
|
+
rubygems_version: 3.2.29
|
117
144
|
signing_key:
|
118
145
|
specification_version: 4
|
119
146
|
summary: Measure image size using pure Ruby
|
120
147
|
test_files:
|
148
|
+
- spec/image_size/chunky_reader_spec.rb
|
121
149
|
- spec/image_size_spec.rb
|
150
|
+
- spec/images/.gitattributes
|
122
151
|
- spec/images/bmp/v2.42x50.bmp
|
123
152
|
- spec/images/bmp/v3-bottom2top.42x50.bmp
|
124
153
|
- spec/images/bmp/v3-top2bottom.42x50.bmp
|
@@ -143,6 +172,9 @@ test_files:
|
|
143
172
|
- spec/images/pnm/ascii.22x25.ppm
|
144
173
|
- spec/images/psd/16x20.psd
|
145
174
|
- spec/images/svg/72x100.svg
|
175
|
+
- spec/images/svg/crlf.72x100.svg
|
176
|
+
- spec/images/svg/long.72x100.svg
|
177
|
+
- spec/images/svg/long.crlf.72x100.svg
|
146
178
|
- spec/images/swf/450x200.swf
|
147
179
|
- spec/images/tiff/big-endian.68x49.tiff
|
148
180
|
- spec/images/tiff/little-endian.40x68.tiff
|
@@ -150,4 +182,6 @@ test_files:
|
|
150
182
|
- spec/images/webp/lossless.16x32.webp
|
151
183
|
- spec/images/webp/lossy.16x32.webp
|
152
184
|
- spec/images/xbm/16x32.xbm
|
185
|
+
- spec/images/xbm/crlf.16x32.xbm
|
153
186
|
- spec/images/xpm/24x32.xpm
|
187
|
+
- spec/images/xpm/crlf.24x32.xpm
|