mirror of
https://github.com/sdsykes/fastimage.git
synced 2025-07-19 00:00:38 -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
|
||||
matrix:
|
||||
ruby:
|
||||
- '2.0'
|
||||
- '2.1'
|
||||
- '2.2'
|
||||
- '2.3'
|
||||
- '2.4'
|
||||
- '2.5'
|
||||
@ -27,3 +24,20 @@ jobs:
|
||||
ruby-version: ${{ matrix.ruby }}
|
||||
bundler-cache: true
|
||||
- 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
|
||||
# require 'fastimage'
|
||||
#
|
||||
# FastImage.size("http://stephensykes.com/images/ss.com_x.gif")
|
||||
# => [266, 56]
|
||||
# FastImage.type("http://stephensykes.com/images/pngimage")
|
||||
# FastImage.size("https://switchstep.com/images/ios.gif")
|
||||
# => [196, 283]
|
||||
# FastImage.type("http://switchstep.com/images/ss_logo.png")
|
||||
# => :png
|
||||
# FastImage.type("/some/local/file.gif")
|
||||
# => :gif
|
||||
# File.open("/some/local/file.gif", "r") {|io| FastImage.type(io)}
|
||||
# => :gif
|
||||
# FastImage.new("http://stephensykes.com/images/pngimage").content_length
|
||||
# => 432
|
||||
# FastImage.new("http://stephensykes.com/images/ExifOrientation3.jpg").orientation
|
||||
# FastImage.new("http://switchstep.com/images/ss_logo.png").content_length
|
||||
# => 4679
|
||||
# FastImage.new("http://switchstep.com/images/ExifOrientation3.jpg").orientation
|
||||
# => 3
|
||||
#
|
||||
# === References
|
||||
@ -61,6 +61,7 @@ require 'pathname'
|
||||
require 'zlib'
|
||||
require 'base64'
|
||||
require 'uri'
|
||||
require 'stringio'
|
||||
require_relative 'fastimage/version'
|
||||
|
||||
# see http://stackoverflow.com/questions/5208851/i/41048816#41048816
|
||||
@ -109,27 +110,27 @@ class FastImage
|
||||
#
|
||||
# require 'fastimage'
|
||||
#
|
||||
# FastImage.size("http://stephensykes.com/images/ss.com_x.gif")
|
||||
# => [266, 56]
|
||||
# FastImage.size("http://stephensykes.com/images/pngimage")
|
||||
# => [16, 16]
|
||||
# FastImage.size("http://farm4.static.flickr.com/3023/3047236863_9dce98b836.jpg")
|
||||
# => [500, 375]
|
||||
# FastImage.size("http://www-ece.rice.edu/~wakin/images/lena512.bmp")
|
||||
# FastImage.size("https://switchstep.com/images/ios.gif")
|
||||
# => [196, 283]
|
||||
# FastImage.size("http://switchstep.com/images/ss_logo.png")
|
||||
# => [300, 300]
|
||||
# FastImage.size("https://upload.wikimedia.org/wikipedia/commons/0/09/Jpeg_thumb_artifacts_test.jpg")
|
||||
# => [1280, 800]
|
||||
# FastImage.size("https://eeweb.engineering.nyu.edu/~yao/EL5123/image/lena_gray.bmp")
|
||||
# => [512, 512]
|
||||
# FastImage.size("test/fixtures/test.jpg")
|
||||
# => [882, 470]
|
||||
# FastImage.size("http://pennysmalls.com/does_not_exist")
|
||||
# FastImage.size("http://switchstep.com/does_not_exist")
|
||||
# => 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
|
||||
# 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]
|
||||
# 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
|
||||
# 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
|
||||
# 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
|
||||
#
|
||||
# === Supported options
|
||||
@ -155,17 +156,17 @@ class FastImage
|
||||
#
|
||||
# require 'fastimage'
|
||||
#
|
||||
# FastImage.type("http://stephensykes.com/images/ss.com_x.gif")
|
||||
# FastImage.type("https://switchstep.com/images/ios.gif")
|
||||
# => :gif
|
||||
# FastImage.type("http://stephensykes.com/images/pngimage")
|
||||
# FastImage.type("http://switchstep.com/images/ss_logo.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
|
||||
# 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
|
||||
# FastImage.type("test/fixtures/test.jpg")
|
||||
# => :jpeg
|
||||
# FastImage.type("http://stephensykes.com/does_not_exist")
|
||||
# FastImage.type("http://switchstep.com/does_not_exist")
|
||||
# => nil
|
||||
# File.open("/some/local/file.gif", "r") {|io| FastImage.type(io)}
|
||||
# => :gif
|
||||
@ -435,7 +436,7 @@ class FastImage
|
||||
|
||||
def parse_animated
|
||||
@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
|
||||
|
||||
def fetch_using_base64(uri)
|
||||
@ -569,9 +570,9 @@ class FastImage
|
||||
when /\s\s|\s<|<[?!]/, 0xef.chr + 0xbb.chr
|
||||
# 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
|
||||
# the file, and is within the first 250 chars.
|
||||
# the file, and is within the first 1000 chars.
|
||||
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
|
||||
nil
|
||||
end
|
||||
@ -649,9 +650,9 @@ class FastImage
|
||||
when "ispe"
|
||||
handle_ispe_box(box_size, index)
|
||||
when "mdat"
|
||||
throw :finish
|
||||
@stream.skip(box_size)
|
||||
else
|
||||
@stream.read(box_size)
|
||||
@stream.skip(box_size)
|
||||
end
|
||||
|
||||
index += 1
|
||||
@ -729,6 +730,7 @@ class FastImage
|
||||
def read_box_header!
|
||||
size = read_uint32!
|
||||
type = @stream.read(4)
|
||||
size = read_uint64! - 8 if size == 1
|
||||
[type, size - 8]
|
||||
end
|
||||
|
||||
@ -743,6 +745,10 @@ class FastImage
|
||||
def read_uint32!
|
||||
@stream.read(4).unpack("N")[0]
|
||||
end
|
||||
|
||||
def read_uint64!
|
||||
@stream.read(8).unpack("Q>")[0]
|
||||
end
|
||||
end
|
||||
|
||||
def parse_size_for_avif
|
||||
@ -1095,6 +1101,25 @@ class FastImage
|
||||
gif.animated?
|
||||
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
|
||||
vp8 = @stream.read(16)[12..15]
|
||||
_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.gif"=>[:gif, [17, 32]],
|
||||
"animated.gif"=>[:gif, [400, 400]],
|
||||
"animated.png"=>[:png, [100, 100]],
|
||||
"animated_without_gct.gif"=>[:gif, [859, 478]],
|
||||
"test.jpg"=>[:jpeg, [882, 470]],
|
||||
"test.png"=>[:png, [30, 20]],
|
||||
@ -41,6 +42,7 @@ GoodFixtures = {
|
||||
"test3.svg" => [:svg, [255, 48]],
|
||||
"test4.svg" => [:svg, [271, 271]],
|
||||
"test5.svg" => [:svg, [255, 48]],
|
||||
"test7.svg" => [:svg, [100, 100]],
|
||||
"orient_6.jpg"=>[:jpeg, [1250,2500]],
|
||||
"heic/test.heic"=>[:heic, [700,476]],
|
||||
"heic/heic-empty.heic"=>[:heic, [3992,2992]],
|
||||
@ -50,6 +52,7 @@ GoodFixtures = {
|
||||
"heic/heic-single.heic"=>[:heif,[1440,960]],
|
||||
"heic/heic-collection.heic"=>[:heif,[1440,960]],
|
||||
"heic/inverted.heic"=>[:heic,[3024, 4032]],
|
||||
"heic/test-meta-after-mdat.heic"=>[:heic,[4000, 3000]],
|
||||
"test6.svg" => [:svg, [450, 450]],
|
||||
"avif/hato.avif" => [:avif, [3082, 2048]],
|
||||
"avif/fox.avif" => [:avif, [1204, 799]],
|
||||
@ -122,9 +125,11 @@ class FastImageTest < Test::Unit::TestCase
|
||||
end
|
||||
|
||||
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 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 false, FastImage.animated?(TestUrl + "webp_vp8x.webp")
|
||||
assert_equal true, FastImage.animated?(TestUrl + "webp_animated.webp")
|
||||
|
Loading…
x
Reference in New Issue
Block a user