mirror of
https://github.com/sdsykes/fastimage.git
synced 2025-07-20 00:00:23 -04:00
Compare commits
13 Commits
81b5b7d3df
...
6266b26b87
Author | SHA1 | Date | |
---|---|---|---|
|
6266b26b87 | ||
|
02d70df8c1 | ||
|
1fcc6c89ea | ||
|
71469cb64f | ||
|
edf9558114 | ||
|
c69d230098 | ||
|
d515546a1d | ||
|
23989af8f9 | ||
|
2d546f4520 | ||
|
7c49d67439 | ||
|
fb319cda6e | ||
|
3fdd1767f5 | ||
|
7056a4b6c9 |
20
.github/workflows/test.yml
vendored
20
.github/workflows/test.yml
vendored
@ -9,9 +9,6 @@ jobs:
|
|||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
ruby:
|
ruby:
|
||||||
- '2.0'
|
|
||||||
- '2.1'
|
|
||||||
- '2.2'
|
|
||||||
- '2.3'
|
- '2.3'
|
||||||
- '2.4'
|
- '2.4'
|
||||||
- '2.5'
|
- '2.5'
|
||||||
@ -27,3 +24,20 @@ jobs:
|
|||||||
ruby-version: ${{ matrix.ruby }}
|
ruby-version: ${{ matrix.ruby }}
|
||||||
bundler-cache: true
|
bundler-cache: true
|
||||||
- run: bundle exec rake
|
- run: bundle exec rake
|
||||||
|
test_old_ruby:
|
||||||
|
name: Test (Ruby ${{ matrix.ruby }})
|
||||||
|
runs-on: ubuntu-20.04
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
ruby:
|
||||||
|
- '2.0'
|
||||||
|
- '2.1'
|
||||||
|
- '2.2'
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
- uses: ruby/setup-ruby@v1
|
||||||
|
with:
|
||||||
|
ruby-version: ${{ matrix.ruby }}
|
||||||
|
bundler-cache: true
|
||||||
|
- run: bundle exec rake
|
||||||
|
@ -35,17 +35,17 @@
|
|||||||
# === Examples
|
# === Examples
|
||||||
# require 'fastimage'
|
# require 'fastimage'
|
||||||
#
|
#
|
||||||
# FastImage.size("http://stephensykes.com/images/ss.com_x.gif")
|
# FastImage.size("https://switchstep.com/images/ios.gif")
|
||||||
# => [266, 56]
|
# => [196, 283]
|
||||||
# FastImage.type("http://stephensykes.com/images/pngimage")
|
# FastImage.type("http://switchstep.com/images/ss_logo.png")
|
||||||
# => :png
|
# => :png
|
||||||
# FastImage.type("/some/local/file.gif")
|
# FastImage.type("/some/local/file.gif")
|
||||||
# => :gif
|
# => :gif
|
||||||
# File.open("/some/local/file.gif", "r") {|io| FastImage.type(io)}
|
# File.open("/some/local/file.gif", "r") {|io| FastImage.type(io)}
|
||||||
# => :gif
|
# => :gif
|
||||||
# FastImage.new("http://stephensykes.com/images/pngimage").content_length
|
# FastImage.new("http://switchstep.com/images/ss_logo.png").content_length
|
||||||
# => 432
|
# => 4679
|
||||||
# FastImage.new("http://stephensykes.com/images/ExifOrientation3.jpg").orientation
|
# FastImage.new("http://switchstep.com/images/ExifOrientation3.jpg").orientation
|
||||||
# => 3
|
# => 3
|
||||||
#
|
#
|
||||||
# === References
|
# === References
|
||||||
@ -61,6 +61,7 @@ require 'pathname'
|
|||||||
require 'zlib'
|
require 'zlib'
|
||||||
require 'base64'
|
require 'base64'
|
||||||
require 'uri'
|
require 'uri'
|
||||||
|
require 'stringio'
|
||||||
require_relative 'fastimage/version'
|
require_relative 'fastimage/version'
|
||||||
|
|
||||||
# see http://stackoverflow.com/questions/5208851/i/41048816#41048816
|
# see http://stackoverflow.com/questions/5208851/i/41048816#41048816
|
||||||
@ -109,27 +110,27 @@ class FastImage
|
|||||||
#
|
#
|
||||||
# require 'fastimage'
|
# require 'fastimage'
|
||||||
#
|
#
|
||||||
# FastImage.size("http://stephensykes.com/images/ss.com_x.gif")
|
# FastImage.size("https://switchstep.com/images/ios.gif")
|
||||||
# => [266, 56]
|
# => [196, 283]
|
||||||
# FastImage.size("http://stephensykes.com/images/pngimage")
|
# FastImage.size("http://switchstep.com/images/ss_logo.png")
|
||||||
# => [16, 16]
|
# => [300, 300]
|
||||||
# FastImage.size("http://farm4.static.flickr.com/3023/3047236863_9dce98b836.jpg")
|
# FastImage.size("https://upload.wikimedia.org/wikipedia/commons/0/09/Jpeg_thumb_artifacts_test.jpg")
|
||||||
# => [500, 375]
|
# => [1280, 800]
|
||||||
# FastImage.size("http://www-ece.rice.edu/~wakin/images/lena512.bmp")
|
# FastImage.size("https://eeweb.engineering.nyu.edu/~yao/EL5123/image/lena_gray.bmp")
|
||||||
# => [512, 512]
|
# => [512, 512]
|
||||||
# FastImage.size("test/fixtures/test.jpg")
|
# FastImage.size("test/fixtures/test.jpg")
|
||||||
# => [882, 470]
|
# => [882, 470]
|
||||||
# FastImage.size("http://pennysmalls.com/does_not_exist")
|
# FastImage.size("http://switchstep.com/does_not_exist")
|
||||||
# => nil
|
# => nil
|
||||||
# FastImage.size("http://pennysmalls.com/does_not_exist", :raise_on_failure=>true)
|
# FastImage.size("http://switchstep.com/does_not_exist", :raise_on_failure=>true)
|
||||||
# => raises FastImage::ImageFetchFailure
|
# => raises FastImage::ImageFetchFailure
|
||||||
# FastImage.size("http://stephensykes.com/favicon.ico", :raise_on_failure=>true)
|
# FastImage.size("http://switchstep.com/images/favicon.ico", :raise_on_failure=>true)
|
||||||
# => [16, 16]
|
# => [16, 16]
|
||||||
# FastImage.size("http://stephensykes.com/images/squareBlue.icns", :raise_on_failure=>true)
|
# FastImage.size("http://switchstep.com/foo.ics", :raise_on_failure=>true)
|
||||||
# => raises FastImage::UnknownImageType
|
# => raises FastImage::UnknownImageType
|
||||||
# FastImage.size("http://stephensykes.com/favicon.ico", :raise_on_failure=>true, :timeout=>0.01)
|
# FastImage.size("http://switchstep.com/images/favicon.ico", :raise_on_failure=>true, :timeout=>0.01)
|
||||||
# => raises FastImage::ImageFetchFailure
|
# => raises FastImage::ImageFetchFailure
|
||||||
# FastImage.size("http://stephensykes.com/images/faulty.jpg", :raise_on_failure=>true)
|
# FastImage.size("http://switchstep.com/images/faulty.jpg", :raise_on_failure=>true)
|
||||||
# => raises FastImage::SizeNotFound
|
# => raises FastImage::SizeNotFound
|
||||||
#
|
#
|
||||||
# === Supported options
|
# === Supported options
|
||||||
@ -155,17 +156,17 @@ class FastImage
|
|||||||
#
|
#
|
||||||
# require 'fastimage'
|
# require 'fastimage'
|
||||||
#
|
#
|
||||||
# FastImage.type("http://stephensykes.com/images/ss.com_x.gif")
|
# FastImage.type("https://switchstep.com/images/ios.gif")
|
||||||
# => :gif
|
# => :gif
|
||||||
# FastImage.type("http://stephensykes.com/images/pngimage")
|
# FastImage.type("http://switchstep.com/images/ss_logo.png")
|
||||||
# => :png
|
# => :png
|
||||||
# FastImage.type("http://farm4.static.flickr.com/3023/3047236863_9dce98b836.jpg")
|
# FastImage.type("https://upload.wikimedia.org/wikipedia/commons/0/09/Jpeg_thumb_artifacts_test.jpg")
|
||||||
# => :jpeg
|
# => :jpeg
|
||||||
# FastImage.type("http://www-ece.rice.edu/~wakin/images/lena512.bmp")
|
# FastImage.type("https://eeweb.engineering.nyu.edu/~yao/EL5123/image/lena_gray.bmp")
|
||||||
# => :bmp
|
# => :bmp
|
||||||
# FastImage.type("test/fixtures/test.jpg")
|
# FastImage.type("test/fixtures/test.jpg")
|
||||||
# => :jpeg
|
# => :jpeg
|
||||||
# FastImage.type("http://stephensykes.com/does_not_exist")
|
# FastImage.type("http://switchstep.com/does_not_exist")
|
||||||
# => nil
|
# => nil
|
||||||
# File.open("/some/local/file.gif", "r") {|io| FastImage.type(io)}
|
# File.open("/some/local/file.gif", "r") {|io| FastImage.type(io)}
|
||||||
# => :gif
|
# => :gif
|
||||||
@ -435,7 +436,7 @@ class FastImage
|
|||||||
|
|
||||||
def parse_animated
|
def parse_animated
|
||||||
@type = parse_type unless @type
|
@type = parse_type unless @type
|
||||||
%i(gif webp avif).include?(@type) ? send("parse_animated_for_#{@type}") : nil
|
%i(gif png webp avif).include?(@type) ? send("parse_animated_for_#{@type}") : nil
|
||||||
end
|
end
|
||||||
|
|
||||||
def fetch_using_base64(uri)
|
def fetch_using_base64(uri)
|
||||||
@ -569,9 +570,9 @@ class FastImage
|
|||||||
when /\s\s|\s<|<[?!]/, 0xef.chr + 0xbb.chr
|
when /\s\s|\s<|<[?!]/, 0xef.chr + 0xbb.chr
|
||||||
# Peek 10 more chars each time, and if end of file is reached just raise
|
# Peek 10 more chars each time, and if end of file is reached just raise
|
||||||
# unknown. We assume the <svg tag cannot be within 10 chars of the end of
|
# unknown. We assume the <svg tag cannot be within 10 chars of the end of
|
||||||
# the file, and is within the first 250 chars.
|
# the file, and is within the first 1000 chars.
|
||||||
begin
|
begin
|
||||||
:svg if (1..25).detect {|n| @stream.peek(10 * n).include?("<svg")}
|
:svg if (1..100).detect {|n| @stream.peek(10 * n).include?("<svg")}
|
||||||
rescue FiberError
|
rescue FiberError
|
||||||
nil
|
nil
|
||||||
end
|
end
|
||||||
@ -649,9 +650,9 @@ class FastImage
|
|||||||
when "ispe"
|
when "ispe"
|
||||||
handle_ispe_box(box_size, index)
|
handle_ispe_box(box_size, index)
|
||||||
when "mdat"
|
when "mdat"
|
||||||
throw :finish
|
@stream.skip(box_size)
|
||||||
else
|
else
|
||||||
@stream.read(box_size)
|
@stream.skip(box_size)
|
||||||
end
|
end
|
||||||
|
|
||||||
index += 1
|
index += 1
|
||||||
@ -729,6 +730,7 @@ class FastImage
|
|||||||
def read_box_header!
|
def read_box_header!
|
||||||
size = read_uint32!
|
size = read_uint32!
|
||||||
type = @stream.read(4)
|
type = @stream.read(4)
|
||||||
|
size = read_uint64! - 8 if size == 1
|
||||||
[type, size - 8]
|
[type, size - 8]
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -743,6 +745,10 @@ class FastImage
|
|||||||
def read_uint32!
|
def read_uint32!
|
||||||
@stream.read(4).unpack("N")[0]
|
@stream.read(4).unpack("N")[0]
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def read_uint64!
|
||||||
|
@stream.read(8).unpack("Q>")[0]
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def parse_size_for_avif
|
def parse_size_for_avif
|
||||||
@ -1095,6 +1101,25 @@ class FastImage
|
|||||||
gif.animated?
|
gif.animated?
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def parse_animated_for_png
|
||||||
|
# Signature (8) + IHDR chunk (4 + 4 + 13 + 4)
|
||||||
|
@stream.read(33)
|
||||||
|
|
||||||
|
loop do
|
||||||
|
length = @stream.read(4).unpack("L>")[0]
|
||||||
|
type = @stream.read(4)
|
||||||
|
|
||||||
|
case type
|
||||||
|
when "acTL"
|
||||||
|
return true
|
||||||
|
when "IDAT"
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
@stream.skip(length + 4)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def parse_animated_for_webp
|
def parse_animated_for_webp
|
||||||
vp8 = @stream.read(16)[12..15]
|
vp8 = @stream.read(16)[12..15]
|
||||||
_len = @stream.read(4).unpack("V")
|
_len = @stream.read(4).unpack("V")
|
||||||
|
BIN
test/fixtures/animated.png
vendored
Normal file
BIN
test/fixtures/animated.png
vendored
Normal file
Binary file not shown.
After Width: | Height: | Size: 62 KiB |
BIN
test/fixtures/heic/test-meta-after-mdat.heic
vendored
Normal file
BIN
test/fixtures/heic/test-meta-after-mdat.heic
vendored
Normal file
Binary file not shown.
BIN
test/fixtures/test2.tiff
vendored
BIN
test/fixtures/test2.tiff
vendored
Binary file not shown.
26
test/fixtures/test7.svg
vendored
Normal file
26
test/fixtures/test7.svg
vendored
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!-- Generator: Adobe Illustrator 26.0.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||||
|
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" [
|
||||||
|
<!ENTITY ns_extend "http://ns.adobe.com/Extensibility/1.0/">
|
||||||
|
<!ENTITY ns_ai "http://ns.adobe.com/AdobeIllustrator/10.0/">
|
||||||
|
<!ENTITY ns_graphs "http://ns.adobe.com/Graphs/1.0/">
|
||||||
|
<!ENTITY ns_vars "http://ns.adobe.com/Variables/1.0/">
|
||||||
|
<!ENTITY ns_imrep "http://ns.adobe.com/ImageReplacement/1.0/">
|
||||||
|
<!ENTITY ns_sfw "http://ns.adobe.com/SaveForWeb/1.0/">
|
||||||
|
<!ENTITY ns_custom "http://ns.adobe.com/GenericCustomNamespace/1.0/">
|
||||||
|
<!ENTITY ns_adobe_xpath "http://ns.adobe.com/XPath/1.0/">
|
||||||
|
]>
|
||||||
|
<svg version="1.1" id="Layer_1" xmlns:x="&ns_extend;" xmlns:i="&ns_ai;" xmlns:graph="&ns_graphs;"
|
||||||
|
xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||||
|
viewBox="0 0 100 100"
|
||||||
|
style="enable-background:new 0 0 113.4 113.4;" xml:space="preserve">
|
||||||
|
<switch>
|
||||||
|
<g i:extraneous="self">
|
||||||
|
<g>
|
||||||
|
<g>
|
||||||
|
<circle cx="50" cy="50" r="20" fill="red" />
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</switch>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 1.1 KiB |
@ -15,6 +15,7 @@ GoodFixtures = {
|
|||||||
"test_v5header.bmp"=>[:bmp, [40, 27]],
|
"test_v5header.bmp"=>[:bmp, [40, 27]],
|
||||||
"test.gif"=>[:gif, [17, 32]],
|
"test.gif"=>[:gif, [17, 32]],
|
||||||
"animated.gif"=>[:gif, [400, 400]],
|
"animated.gif"=>[:gif, [400, 400]],
|
||||||
|
"animated.png"=>[:png, [100, 100]],
|
||||||
"animated_without_gct.gif"=>[:gif, [859, 478]],
|
"animated_without_gct.gif"=>[:gif, [859, 478]],
|
||||||
"test.jpg"=>[:jpeg, [882, 470]],
|
"test.jpg"=>[:jpeg, [882, 470]],
|
||||||
"test.png"=>[:png, [30, 20]],
|
"test.png"=>[:png, [30, 20]],
|
||||||
@ -41,6 +42,7 @@ GoodFixtures = {
|
|||||||
"test3.svg" => [:svg, [255, 48]],
|
"test3.svg" => [:svg, [255, 48]],
|
||||||
"test4.svg" => [:svg, [271, 271]],
|
"test4.svg" => [:svg, [271, 271]],
|
||||||
"test5.svg" => [:svg, [255, 48]],
|
"test5.svg" => [:svg, [255, 48]],
|
||||||
|
"test7.svg" => [:svg, [100, 100]],
|
||||||
"orient_6.jpg"=>[:jpeg, [1250,2500]],
|
"orient_6.jpg"=>[:jpeg, [1250,2500]],
|
||||||
"heic/test.heic"=>[:heic, [700,476]],
|
"heic/test.heic"=>[:heic, [700,476]],
|
||||||
"heic/heic-empty.heic"=>[:heic, [3992,2992]],
|
"heic/heic-empty.heic"=>[:heic, [3992,2992]],
|
||||||
@ -50,6 +52,7 @@ GoodFixtures = {
|
|||||||
"heic/heic-single.heic"=>[:heif,[1440,960]],
|
"heic/heic-single.heic"=>[:heif,[1440,960]],
|
||||||
"heic/heic-collection.heic"=>[:heif,[1440,960]],
|
"heic/heic-collection.heic"=>[:heif,[1440,960]],
|
||||||
"heic/inverted.heic"=>[:heic,[3024, 4032]],
|
"heic/inverted.heic"=>[:heic,[3024, 4032]],
|
||||||
|
"heic/test-meta-after-mdat.heic"=>[:heic,[4000, 3000]],
|
||||||
"test6.svg" => [:svg, [450, 450]],
|
"test6.svg" => [:svg, [450, 450]],
|
||||||
"avif/hato.avif" => [:avif, [3082, 2048]],
|
"avif/hato.avif" => [:avif, [3082, 2048]],
|
||||||
"avif/fox.avif" => [:avif, [1204, 799]],
|
"avif/fox.avif" => [:avif, [1204, 799]],
|
||||||
@ -122,9 +125,11 @@ class FastImageTest < Test::Unit::TestCase
|
|||||||
end
|
end
|
||||||
|
|
||||||
def test_should_report_animated_correctly
|
def test_should_report_animated_correctly
|
||||||
assert_equal nil, FastImage.animated?(TestUrl + "test.png")
|
assert_equal nil, FastImage.animated?(TestUrl + "test.jpg")
|
||||||
|
assert_equal false, FastImage.animated?(TestUrl + "test.png")
|
||||||
assert_equal false, FastImage.animated?(TestUrl + "test.gif")
|
assert_equal false, FastImage.animated?(TestUrl + "test.gif")
|
||||||
assert_equal true, FastImage.animated?(TestUrl + "animated.gif")
|
assert_equal true, FastImage.animated?(TestUrl + "animated.gif")
|
||||||
|
assert_equal true, FastImage.animated?(TestUrl + "animated.png")
|
||||||
assert_equal true, FastImage.animated?(TestUrl + "animated_without_gct.gif")
|
assert_equal true, FastImage.animated?(TestUrl + "animated_without_gct.gif")
|
||||||
assert_equal false, FastImage.animated?(TestUrl + "webp_vp8x.webp")
|
assert_equal false, FastImage.animated?(TestUrl + "webp_vp8x.webp")
|
||||||
assert_equal true, FastImage.animated?(TestUrl + "webp_animated.webp")
|
assert_equal true, FastImage.animated?(TestUrl + "webp_animated.webp")
|
||||||
|
Loading…
x
Reference in New Issue
Block a user