image_size 2.1.2 → 3.0.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/.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
|