fastimage 1.6.8 → 1.7.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.textile +8 -2
- data/lib/fastimage.rb +83 -3
- data/test/fixtures/test.svg +43 -0
- data/test/fixtures/test_partial_viewport.svg +9 -0
- data/test/test.rb +17 -1
- metadata +4 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b171e7bf1f4fd89ec28ce3b4f3ddfb3686a71d00
|
4
|
+
data.tar.gz: a851e15026cdd61e9e13923b73c73b0a004a4f13
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6f0891068f233455992127dedeea3e11c69cf17c292c08b8ce18aad3e20582921f1f3d7b109c35ad2b70e64b082157525546f3326c7592d6fef5012d75199a94
|
7
|
+
data.tar.gz: a28dae9ccdd8aa0741e8fb45dc9f8078c10ca3ebecaa872a234e0a7f5c79c2428622e0077d6e9667eb0d39d46b5e79757ee46a230b4c126a61815176ece50cf7
|
data/README.textile
CHANGED
@@ -12,7 +12,7 @@ But the image is not locally stored - it's on another asset server, or in the cl
|
|
12
12
|
|
13
13
|
You don't want to download the entire image to your app server - it could be many tens of kilobytes, or even megabytes just to get this information. For most common image types (GIF, PNG, BMP etc.), the size of the image is simply stored at the start of the file. For JPEG files it's a little bit more complex, but even so you do not need to fetch much of the image to find the size.
|
14
14
|
|
15
|
-
FastImage does this minimal fetch for image types GIF, JPEG, PNG, TIFF, BMP, ICO, CUR, PSD and WEBP. And it doesn't rely on installing external libraries such as RMagick (which relies on ImageMagick or GraphicsMagick) or ImageScience (which relies on FreeImage).
|
15
|
+
FastImage does this minimal fetch for image types GIF, JPEG, PNG, TIFF, BMP, ICO, CUR, PSD, SVG and WEBP. And it doesn't rely on installing external libraries such as RMagick (which relies on ImageMagick or GraphicsMagick) or ImageScience (which relies on FreeImage).
|
16
16
|
|
17
17
|
You only need supply the uri, and FastImage will do the rest.
|
18
18
|
|
@@ -32,6 +32,8 @@ You can add a timeout to the request which will limit the request time by passin
|
|
32
32
|
|
33
33
|
FastImage normally replies will nil if it encounters an error, but you can pass :raise_on_failure => true to get an exception.
|
34
34
|
|
35
|
+
FastImage also provides a reader for the content length header provided in HTTP. This may be useful to assess the file size of an image, but do not rely on it exclusively - it will not be present in chunked responses for instance.
|
36
|
+
|
35
37
|
h2. Security
|
36
38
|
|
37
39
|
As of v1.6.7 FastImage no longer uses openuri to open files, but directly calls File.open. But take care to sanitise the strings passed to FastImage; it will try to read from whatever is passed.
|
@@ -51,6 +53,8 @@ FastImage.size("http://upload.wikimedia.org/wikipedia/commons/b/b4/Mardin_135066
|
|
51
53
|
=> FastImage::ImageFetchFailure: FastImage::ImageFetchFailure
|
52
54
|
FastImage.size("http://upload.wikimedia.org/wikipedia/commons/b/b4/Mardin_1350660_1350692_33_images.jpg", :raise_on_failure=>true, :timeout=>2.0)
|
53
55
|
=> [9545, 6623]
|
56
|
+
FastImage.new("http://stephensykes.com/images/pngimage").content_length
|
57
|
+
=> 432
|
54
58
|
</code></pre>
|
55
59
|
|
56
60
|
h2. Installation
|
@@ -126,6 +130,7 @@ h2. FastImage in other languages
|
|
126
130
|
* "Python by bmuller":https://github.com/bmuller/fastimage
|
127
131
|
* "Swift by kaishin":https://github.com/kaishin/ImageScout
|
128
132
|
* "Go by rubenfonseca":https://github.com/rubenfonseca/fastimage
|
133
|
+
* "PHP by tommoor":https://github.com/tommoor/fastimage
|
129
134
|
|
130
135
|
h2. Licence
|
131
136
|
|
@@ -143,4 +148,5 @@ Pull requests and suggestions are always welcome. Thanks to all the contributors
|
|
143
148
|
* @marcandre
|
144
149
|
* @apanzerj
|
145
150
|
* @forresty
|
146
|
-
|
151
|
+
* kikihakiem
|
152
|
+
* lulalalalistia
|
data/lib/fastimage.rb
CHANGED
@@ -8,7 +8,7 @@
|
|
8
8
|
# No external libraries such as ImageMagick are used here, this is a very lightweight solution to
|
9
9
|
# finding image information.
|
10
10
|
#
|
11
|
-
# FastImage knows about GIF, JPEG, BMP, TIFF, ICO, CUR, PNG, PSD and WEBP files.
|
11
|
+
# FastImage knows about GIF, JPEG, BMP, TIFF, ICO, CUR, PNG, PSD, SVG and WEBP files.
|
12
12
|
#
|
13
13
|
# FastImage can also read files from the local filesystem by supplying the path instead of a uri.
|
14
14
|
# In this case FastImage reads the file in chunks of 256 bytes until
|
@@ -20,6 +20,10 @@
|
|
20
20
|
#
|
21
21
|
# FastImage will follow up to 4 HTTP redirects to get the image.
|
22
22
|
#
|
23
|
+
# FastImage also provides a reader for the content length header provided in HTTP.
|
24
|
+
# This may be useful to assess the file size of an image, but do not rely on it exclusively -
|
25
|
+
# it will not be present in chunked responses for instance.
|
26
|
+
#
|
23
27
|
# === Examples
|
24
28
|
# require 'fastimage'
|
25
29
|
#
|
@@ -48,7 +52,7 @@ require 'pathname'
|
|
48
52
|
require 'zlib'
|
49
53
|
|
50
54
|
class FastImage
|
51
|
-
attr_reader :size, :type
|
55
|
+
attr_reader :size, :type, :content_length
|
52
56
|
|
53
57
|
attr_reader :bytes_read
|
54
58
|
|
@@ -76,7 +80,7 @@ class FastImage
|
|
76
80
|
# If you wish FastImage to raise if it cannot size the image for any reason, then pass
|
77
81
|
# :raise_on_failure => true in the options.
|
78
82
|
#
|
79
|
-
# FastImage knows about GIF, JPEG, BMP, TIFF, ICO, CUR, PNG, PSD and WEBP files.
|
83
|
+
# FastImage knows about GIF, JPEG, BMP, TIFF, ICO, CUR, PNG, PSD, SVG and WEBP files.
|
80
84
|
#
|
81
85
|
# === Example
|
82
86
|
#
|
@@ -231,6 +235,8 @@ class FastImage
|
|
231
235
|
|
232
236
|
raise ImageFetchFailure unless res.is_a?(Net::HTTPSuccess)
|
233
237
|
|
238
|
+
@content_length = res.content_length
|
239
|
+
|
234
240
|
read_fiber = Fiber.new do
|
235
241
|
res.read_body do |str|
|
236
242
|
Fiber.yield str
|
@@ -343,6 +349,14 @@ class FastImage
|
|
343
349
|
def read_int
|
344
350
|
read(2).unpack('n')[0]
|
345
351
|
end
|
352
|
+
|
353
|
+
def read_string_int
|
354
|
+
value = []
|
355
|
+
while read(1) =~ /(\d)/
|
356
|
+
value << $1
|
357
|
+
end
|
358
|
+
value.join.to_i
|
359
|
+
end
|
346
360
|
end
|
347
361
|
|
348
362
|
class FiberStream # :nodoc:
|
@@ -410,6 +424,8 @@ class FastImage
|
|
410
424
|
else
|
411
425
|
raise UnknownImageType
|
412
426
|
end
|
427
|
+
when "<?", "<s"
|
428
|
+
:svg
|
413
429
|
else
|
414
430
|
raise UnknownImageType
|
415
431
|
end
|
@@ -596,4 +612,68 @@ class FastImage
|
|
596
612
|
def parse_size_for_psd
|
597
613
|
@stream.read(26).unpack("x14NN").reverse
|
598
614
|
end
|
615
|
+
|
616
|
+
class Svg # :nodoc:
|
617
|
+
def initialize(stream)
|
618
|
+
@stream = stream
|
619
|
+
parse_svg
|
620
|
+
end
|
621
|
+
|
622
|
+
def width_and_height
|
623
|
+
if @width && @height
|
624
|
+
[@width, @height]
|
625
|
+
elsif @width && @ratio
|
626
|
+
[@width, @width / @ratio]
|
627
|
+
elsif @height && @ratio
|
628
|
+
[@height * @ratio, @height]
|
629
|
+
end
|
630
|
+
end
|
631
|
+
|
632
|
+
private
|
633
|
+
|
634
|
+
def parse_svg
|
635
|
+
attr_name = []
|
636
|
+
state = nil
|
637
|
+
|
638
|
+
while (char = @stream.read(1)) && state != :stop do
|
639
|
+
case char
|
640
|
+
when "="
|
641
|
+
if attr_name.join =~ /width/i
|
642
|
+
@stream.read(1)
|
643
|
+
@width = @stream.read_string_int
|
644
|
+
return if @height
|
645
|
+
elsif attr_name.join =~ /height/i
|
646
|
+
@stream.read(1)
|
647
|
+
@height = @stream.read_string_int
|
648
|
+
return if @width
|
649
|
+
elsif attr_name.join =~ /viewbox/i
|
650
|
+
values = attr_value.split(/\s/)
|
651
|
+
@ratio = values[2].to_f / values[3].to_f
|
652
|
+
end
|
653
|
+
when /\w/
|
654
|
+
attr_name << char
|
655
|
+
when ">"
|
656
|
+
state = :stop if state == :started
|
657
|
+
else
|
658
|
+
state = :started if attr_name.join == "svg"
|
659
|
+
attr_name.clear
|
660
|
+
end
|
661
|
+
end
|
662
|
+
end
|
663
|
+
|
664
|
+
def attr_value
|
665
|
+
@stream.read(1)
|
666
|
+
|
667
|
+
value = []
|
668
|
+
while @stream.read(1) =~ /([^"])/
|
669
|
+
value << $1
|
670
|
+
end
|
671
|
+
value.join
|
672
|
+
end
|
673
|
+
end
|
674
|
+
|
675
|
+
def parse_size_for_svg
|
676
|
+
svg = Svg.new(@stream)
|
677
|
+
svg.width_and_height
|
678
|
+
end
|
599
679
|
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
<?xml version="1.0"?>
|
2
|
+
|
3
|
+
<svg version="1.1"
|
4
|
+
xmlns="http://www.w3.org/2000/svg"
|
5
|
+
xmlns:xlink="http://www.w3.org/1999/xlink"
|
6
|
+
width="200" height="300"
|
7
|
+
style="background-color: #D2B48C;"
|
8
|
+
onload="loaded()">
|
9
|
+
<script type="text/javascript"><![CDATA[
|
10
|
+
function loaded() {
|
11
|
+
// change onloadFunc to point to your real onload function that you
|
12
|
+
// want called when the page is truly ready
|
13
|
+
var onloadFunc = doload;
|
14
|
+
|
15
|
+
if (top.svgweb) {
|
16
|
+
top.svgweb.addOnLoad(onloadFunc, true, window);
|
17
|
+
} else {
|
18
|
+
onloadFunc();
|
19
|
+
}
|
20
|
+
}
|
21
|
+
|
22
|
+
function doload() {
|
23
|
+
// developers original onload handler
|
24
|
+
|
25
|
+
// add an event listener to our circle; on* style events added right
|
26
|
+
// to the markup are not yet supported
|
27
|
+
var circle = document.getElementById('myCircle');
|
28
|
+
circle.addEventListener('mousedown', function(evt) {
|
29
|
+
alert('You pressed the mouse button on our circle: ' + evt.target.id);
|
30
|
+
}, false);
|
31
|
+
}
|
32
|
+
]]></script>
|
33
|
+
<g id="myGroup"
|
34
|
+
fill="blue"
|
35
|
+
style="font-size: 18px; text-anchor: middle; font-family: serif;">
|
36
|
+
<circle id="myCircle"
|
37
|
+
cx="100" cy="75" r="50"
|
38
|
+
stroke="firebrick"
|
39
|
+
stroke-width="3" />
|
40
|
+
<text x="100" y="155">Hello World</text>
|
41
|
+
<text x="100" y="175">From An SVG File!</text>
|
42
|
+
</g>
|
43
|
+
</svg>
|
@@ -0,0 +1,9 @@
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" version="1.0" width="860" viewBox="0 0 215 100">
|
2
|
+
<path d="M4.8 72.6C8.4 77.2 40.3 78.8 48 73.8 64.9 77.7 98.6 75.9 97.7 69.2 97 63.2 -16.4 46.1 4.8 72.6zM114.8 69.3C130.6 78.8 162 75.7 167.9 73.8 173.6 80.6 209.4 79.6 211.3 74.3 213.2 68.8 90.7 18.1 114.8 69.3z" style="fill:#cfcfcf"/>
|
3
|
+
<path d="M67.9 31.1C42.1 30.4 27.6 58.1 34.8 66.4 44.4 77.6 89.3 73.7 95.7 67.1 105.3 57.4 93.5 31.7 67.9 31.1z" style="fill:#cca776;stroke:#715835"/>
|
4
|
+
<path d="M25.7 43.9C2.8 43.8 -0.2 64.2 4.5 71.6 7.4 76.3 42.2 76.8 47.1 70.9 52.5 64.4 49 44 25.7 43.9z" style="fill:#ffe2af;stroke:#daa240"/>
|
5
|
+
<path d="M141.8 33.1C108.7 32.1 105.2 59.2 112.9 67.3 121.1 76 163.9 75.9 170.9 67.9 177.5 60.2 175.1 34.2 141.8 33.1z" style="fill:#a7dcc1;stroke:#5ba67e"/>
|
6
|
+
<path d="M188.8 43.6C166.1 43.1 160 64.7 165.9 71.8 171.6 78.6 203.4 78 209.3 72.3 215.6 66.1 211 44.1 188.8 43.6z" style="fill:#ffd1ba;stroke:#cc7f58"/>
|
7
|
+
<path d="M141.6 2.5C118.4 2 105.7 25 115 34.5 120.9 40.5 160.2 41.3 166.4 34.3 174.1 25.6 164.6 3 141.6 2.5z" style="fill:#fbf499;stroke:#cbc238"/>
|
8
|
+
<path d="M31.3 54.6C32.6 56.7 32.6 58.1 33 60.9M37.4 60.2C37.5 57.4 37 56.4 36 54.5M84.1 56.3C83.8 53.4 83.3 50.4 81.7 47.5M90.5 56.3C90.3 53.3 89.9 50.2 88.4 47.2M121.5 53C121.1 50.2 121.7 47.3 123 44.4M127.3 53.5C126.8 50.7 127.7 47.8 129.3 44.9M125.1 15.9C125.1 13.3 125.9 11.4 126.9 8.8M132.8 8.6C131.9 11 131 13.5 131.1 15.9M174.8 53.3C173.5 55.9 172.5 58.6 172.6 61.6M181.4 53.5C180 55.4 178.6 60.4 179.7 62.1" style="fill:none;stroke:#000000;stroke-width:1.25;stroke-linecap:round"/>
|
9
|
+
</svg>
|
data/test/test.rb
CHANGED
@@ -30,7 +30,9 @@ GoodFixtures = {
|
|
30
30
|
"test.cur" => [:cur, [32, 32]],
|
31
31
|
"webp_vp8x.webp" => [:webp, [386, 395]],
|
32
32
|
"webp_vp8l.webp" => [:webp, [386, 395]],
|
33
|
-
"webp_vp8.webp" => [:webp, [550, 368]]
|
33
|
+
"webp_vp8.webp" => [:webp, [550, 368]],
|
34
|
+
"test.svg" => [:svg, [200, 300]],
|
35
|
+
"test_partial_viewport.svg" => [:svg, [860, 400]]
|
34
36
|
}
|
35
37
|
|
36
38
|
BadFixtures = [
|
@@ -297,4 +299,18 @@ class FastImageTest < Test::Unit::TestCase
|
|
297
299
|
ensure
|
298
300
|
%x{rm -f shell_test}
|
299
301
|
end
|
302
|
+
|
303
|
+
def test_content_length
|
304
|
+
url = "#{TestUrl}with_content_length.gif"
|
305
|
+
FakeWeb.register_uri(:get, url, :body => File.join(FixturePath, "test.jpg"), :content_length => 52)
|
306
|
+
|
307
|
+
assert_equal 52, FastImage.new(url).content_length
|
308
|
+
end
|
309
|
+
|
310
|
+
def test_content_length_not_provided
|
311
|
+
url = "#{TestUrl}without_content_length.gif"
|
312
|
+
FakeWeb.register_uri(:get, url, :body => File.join(FixturePath, "test.jpg"))
|
313
|
+
|
314
|
+
assert_equal nil, FastImage.new(url).content_length
|
315
|
+
end
|
300
316
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: fastimage
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.7.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Stephen Sykes
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-
|
11
|
+
date: 2015-05-12 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: addressable
|
@@ -112,12 +112,14 @@ files:
|
|
112
112
|
- test/fixtures/test.jpg
|
113
113
|
- test/fixtures/test.png
|
114
114
|
- test/fixtures/test.psd
|
115
|
+
- test/fixtures/test.svg
|
115
116
|
- test/fixtures/test.tiff
|
116
117
|
- test/fixtures/test2.bmp
|
117
118
|
- test/fixtures/test2.jpg
|
118
119
|
- test/fixtures/test2.tiff
|
119
120
|
- test/fixtures/test3.jpg
|
120
121
|
- test/fixtures/test4.jpg
|
122
|
+
- test/fixtures/test_partial_viewport.svg
|
121
123
|
- test/fixtures/truncated_gzipped.jpg
|
122
124
|
- test/fixtures/webp_vp8.webp
|
123
125
|
- test/fixtures/webp_vp8l.webp
|