fastimage 2.1.7 → 2.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (4) hide show
  1. checksums.yaml +4 -4
  2. data/README.textile +1 -1
  3. data/lib/fastimage.rb +115 -7
  4. metadata +4 -4
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 2aaa7bc9e7b596326f39fc933d836e8d94a0c19601670c0b55c839ba8d0e9ed5
4
- data.tar.gz: b807e4cb3ac6ac16b10c026d15ac6a6440a65a75036482518b1a337475bd723b
3
+ metadata.gz: 53c0966ef5216c189e2950b1ad36c106777175f0d4dca9851abd34472fd9cb61
4
+ data.tar.gz: 29f5a6bc03623e184166e7f9c5e8c4379011b301904d4c690037d5b7b0ba0b33
5
5
  SHA512:
6
- metadata.gz: 8a87fd1e5eb5a209da0c2a2af1d7c0d6cead3f14af8cc591810e0e0d7b853cd519e236f9ec0ed70fdea0c39569631f5b41f88f5fea8942aa55fbe018390102ef
7
- data.tar.gz: 002d20c88557352e4b3ebb80975d2f26cffa221cc3c510a0865ffed55fe251a63f53dfeff53843f351574cff1aa9c9864d5df1a2e5fc9a4550b5e03fd798880a
6
+ metadata.gz: 28e8ec4debe6c2c477da19cafb1ad41e5de4d809136bd86621ae128372c32c1259abea833856f73dfcfe8ef3444bc5e1a148f91b52ee02d3292235c4d95fc542
7
+ data.tar.gz: ba8b4c6bb42146387b1a8af718fbbaf74a9a94532ee5adce082ff676095dad5d5e0eb613f1ec41d7729709847195fa81c4614f2d9d510d6c7def67f8970f168e
@@ -1,5 +1,5 @@
1
1
  !https://img.shields.io/gem/dt/fastimage.svg!:https://rubygems.org/gems/fastimage
2
- !https://travis-ci.org/sdsykes/fastimage.png?branch=master!:https://travis-ci.org/sdsykes/fastimage
2
+ !https://travis-ci.org/sdsykes/fastimage.svg?branch=master!:https://travis-ci.org/sdsykes/fastimage
3
3
 
4
4
  h1. FastImage
5
5
 
@@ -70,7 +70,7 @@ if RUBY_VERSION < "2.2"
70
70
  end
71
71
 
72
72
  class FastImage
73
- attr_reader :size, :type, :content_length, :orientation
73
+ attr_reader :size, :type, :content_length, :orientation, :animated
74
74
 
75
75
  attr_reader :bytes_read
76
76
 
@@ -179,6 +179,34 @@ class FastImage
179
179
  new(uri, options.merge(:type_only=>true)).type
180
180
  end
181
181
 
182
+ # Returns a boolean value indicating the image is animated.
183
+ # It will return nil if the image could not be fetched, or if the image type was not recognised.
184
+ #
185
+ # By default there is a timeout of 2 seconds for opening and reading from a remote server.
186
+ # This can be changed by passing a :timeout => number_of_seconds in the options.
187
+ #
188
+ # If you wish FastImage to raise if it cannot find the type of the image for any reason, then pass
189
+ # :raise_on_failure => true in the options.
190
+ #
191
+ # === Example
192
+ #
193
+ # require 'fastimage'
194
+ #
195
+ # FastImage.animated?("test/fixtures/test.gif")
196
+ # => false
197
+ # FastImage.animated?("test/fixtures/animated.gif")
198
+ # => true
199
+ #
200
+ # === Supported options
201
+ # [:timeout]
202
+ # Overrides the default timeout of 2 seconds. Applies both to reading from and opening the http connection.
203
+ # [:raise_on_failure]
204
+ # If set to true causes an exception to be raised if the image type cannot be found for any reason.
205
+ #
206
+ def self.animated?(uri, options={})
207
+ new(uri, options.merge(:animated_only=>true)).animated
208
+ end
209
+
182
210
  def initialize(uri, options={})
183
211
  @uri = uri
184
212
  @options = {
@@ -189,7 +217,13 @@ class FastImage
189
217
  :http_header => {}
190
218
  }.merge(options)
191
219
 
192
- @property = @options[:type_only] ? :type : :size
220
+ @property = if @options[:animated_only]
221
+ :animated
222
+ elsif @options[:type_only]
223
+ :type
224
+ else
225
+ :size
226
+ end
193
227
 
194
228
  @type, @state = nil
195
229
 
@@ -248,7 +282,7 @@ class FastImage
248
282
  begin
249
283
  URI(location)
250
284
  rescue URI::InvalidURIError
251
- URI.escape(location)
285
+ ::URI::DEFAULT_PARSER.escape(location)
252
286
  else
253
287
  location
254
288
  end
@@ -262,7 +296,10 @@ class FastImage
262
296
  if res.is_a?(Net::HTTPRedirection) && @redirect_count < 4
263
297
  @redirect_count += 1
264
298
  begin
265
- @parsed_uri = URI.join(@parsed_uri, escaped_location(res['Location']))
299
+ location = res['Location']
300
+ raise ImageFetchFailure if location.nil? || location.empty?
301
+
302
+ @parsed_uri = URI.join(@parsed_uri, escaped_location(location))
266
303
  rescue URI::InvalidURIError
267
304
  else
268
305
  fetch_using_http_from_parsed_uri
@@ -369,7 +406,7 @@ class FastImage
369
406
 
370
407
  begin
371
408
  result = send("parse_#{@property}")
372
- if result
409
+ if result != nil
373
410
  # extract exif orientation if it was found
374
411
  if @property == :size && result.size == 3
375
412
  @orientation = result.pop
@@ -391,6 +428,11 @@ class FastImage
391
428
  send("parse_size_for_#{@type}")
392
429
  end
393
430
 
431
+ def parse_animated
432
+ @type = parse_type unless @type
433
+ @type == :gif ? send("parse_animated_for_#{@type}") : nil
434
+ end
435
+
394
436
  def fetch_using_base64(uri)
395
437
  data = uri.split(',')[1]
396
438
  decoded = Base64.decode64(data)
@@ -502,7 +544,7 @@ class FastImage
502
544
  when "RI"
503
545
  :webp if @stream.peek(12)[8..11] == "WEBP"
504
546
  when "<s"
505
- :svg
547
+ :svg if @stream.peek(4) == "<svg"
506
548
  when /<[?!]/
507
549
  # Peek 10 more chars each time, and if end of file is reached just raise
508
550
  # unknown. We assume the <svg tag cannot be within 10 chars of the end of
@@ -524,8 +566,69 @@ class FastImage
524
566
  end
525
567
  alias_method :parse_size_for_cur, :parse_size_for_ico
526
568
 
569
+ class Gif # :nodoc:
570
+ def initialize(stream)
571
+ @stream = stream
572
+ end
573
+
574
+ def width_and_height
575
+ @stream.read(11)[6..10].unpack('SS')
576
+ end
577
+
578
+ # Checks if a delay between frames exists and if it does, then the GIFs is
579
+ # animated
580
+ def animated?
581
+ delay = 0
582
+
583
+ @stream.read(10) # "GIF" + version (3) + width (2) + height (2)
584
+
585
+ fields = @stream.read(3).unpack("C")[0] # fields (1) + bg color (1) + pixel ratio (1)
586
+
587
+ # Skip Global Color Table if it exists
588
+ if fields & 0x80
589
+ # 2 * (depth + 1) colors, each occupying 3 bytes (RGB)
590
+ @stream.skip(3 * 2 ** ((fields & 0x7) + 1))
591
+ end
592
+
593
+ loop do
594
+ block_type = @stream.read(1).unpack("C")[0]
595
+ if block_type == 0x21
596
+ extension_type = @stream.read(1).unpack("C")[0]
597
+ size = @stream.read(1).unpack("C")[0]
598
+ if extension_type == 0xF9
599
+ delay = @stream.read(4).unpack("CSC")[1] # fields (1) + delay (2) + transparent index (1)
600
+ break
601
+ elsif extension_type == 0xFF
602
+ @stream.skip(size) # application ID (8) + version (3)
603
+ else
604
+ return # unrecognized extension
605
+ end
606
+ skip_sub_blocks
607
+ else
608
+ return # unrecognized block
609
+ end
610
+ end
611
+
612
+ delay > 0
613
+ end
614
+
615
+ private
616
+
617
+ def skip_sub_blocks
618
+ loop do
619
+ size = @stream.read(1).unpack("C")[0]
620
+ if size == 0
621
+ break
622
+ else
623
+ @stream.skip(size)
624
+ end
625
+ end
626
+ end
627
+ end
628
+
527
629
  def parse_size_for_gif
528
- @stream.read(11)[6..10].unpack('SS')
630
+ gif = Gif.new(@stream)
631
+ gif.width_and_height
529
632
  end
530
633
 
531
634
  def parse_size_for_png
@@ -785,4 +888,9 @@ class FastImage
785
888
  svg = Svg.new(@stream)
786
889
  svg.width_and_height
787
890
  end
891
+
892
+ def parse_animated_for_gif
893
+ gif = Gif.new(@stream)
894
+ gif.animated?
895
+ end
788
896
  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: 2.1.7
4
+ version: 2.2.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: 2019-09-05 00:00:00.000000000 Z
11
+ date: 2020-07-23 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: fakeweb-fi
@@ -28,14 +28,14 @@ dependencies:
28
28
  name: rake
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
- - - "~>"
31
+ - - ">="
32
32
  - !ruby/object:Gem::Version
33
33
  version: '10.5'
34
34
  type: :development
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
- - - "~>"
38
+ - - ">="
39
39
  - !ruby/object:Gem::Version
40
40
  version: '10.5'
41
41
  - !ruby/object:Gem::Dependency