fastimage 1.6.8 → 1.7.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/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
         |