fastimage 2.2.1 → 2.2.5

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 72e83c6f6d442c29071e060cca8a8b0a0a17024a7871cd19a64b83f77e0c0ced
4
- data.tar.gz: 56d0f5f86e11f1a8922cdf5bbe292fef2753f5637df402fd7532ef21d8393537
3
+ metadata.gz: cfa3d72608b0c236038f0d4917930580df5474e5b46b61bcbb5758190e0050e3
4
+ data.tar.gz: 759948e3de376e61a038c6a710b1d15a39d0459c2c20efa7fefbf3692bcc26b7
5
5
  SHA512:
6
- metadata.gz: 002eb40a04b2ce79f8cdc34ee2fdc0d70fe35ff964d380096302682756a17e4b22f8275e335822f5229080aada2ca8d5d17603607cb0cf6479b61ac6d4dd64ef
7
- data.tar.gz: 17c8efefdc90fae00178d045bb0670e2914f9f19eabdb0be983c49ffb573b752672f02678e38b1395129d7f55ffc42905fa1cbeb9017445ffa295db6cc4fe119
6
+ metadata.gz: 49a8af8f7dbed9c9c2de250a67cd9ff2810c7b0a5a41d79c5069b777331573de9633163cbc3a95b7a5710e695065a6266e37a255cfeb3ed380ddd29076ce34d9
7
+ data.tar.gz: 4c9136b413828a5ef790befb5b16144fdc277979c5e28b855886888ea513aa7343900269c302feb495639cd5647f0e58dcdb1a67dd812f4d1357c42adaf1ebe5
data/README.textile CHANGED
@@ -132,7 +132,7 @@ h2. Tests
132
132
 
133
133
  You'll need to @gem install fakeweb@ and possibly also @gem install test-unit@ to be able to run the tests.
134
134
 
135
- bc.. $ ruby test.rb
135
+ bc.. $ ruby test/test.rb
136
136
  Run options:
137
137
 
138
138
  # Running tests:
data/lib/fastimage.rb CHANGED
@@ -61,6 +61,7 @@ require 'pathname'
61
61
  require 'zlib'
62
62
  require 'base64'
63
63
  require 'uri'
64
+ require_relative 'fastimage/version'
64
65
 
65
66
  # see http://stackoverflow.com/questions/5208851/i/41048816#41048816
66
67
  if RUBY_VERSION < "2.2"
@@ -89,6 +90,8 @@ class FastImage
89
90
 
90
91
  LocalFileChunkSize = 256 unless const_defined?(:LocalFileChunkSize)
91
92
 
93
+ SUPPORTED_IMAGE_TYPES = [:bmp, :gif, :jpeg, :png, :tiff, :psd, :heic, :heif, :webp, :svg, :ico, :cur].freeze
94
+
92
95
  # Returns an array containing the width and height of the image.
93
96
  # It will return nil if the image could not be fetched, or if the image type was not recognised.
94
97
  #
@@ -251,10 +254,8 @@ class FastImage
251
254
  Errno::ENETUNREACH, ImageFetchFailure, Net::HTTPBadResponse, EOFError, Errno::ENOENT,
252
255
  OpenSSL::SSL::SSLError
253
256
  raise ImageFetchFailure if @options[:raise_on_failure]
254
- rescue NoMethodError # 1.8.7p248 can raise this due to a net/http bug
255
- raise ImageFetchFailure if @options[:raise_on_failure]
256
257
  rescue UnknownImageType
257
- raise UnknownImageType if @options[:raise_on_failure]
258
+ raise if @options[:raise_on_failure]
258
259
  rescue CannotParseImage
259
260
  if @options[:raise_on_failure]
260
261
  if @property == :size
@@ -434,8 +435,11 @@ class FastImage
434
435
  end
435
436
 
436
437
  def fetch_using_base64(uri)
437
- data = uri.split(',')[1]
438
- decoded = Base64.decode64(data)
438
+ decoded = begin
439
+ Base64.decode64(uri.split(',')[1])
440
+ rescue
441
+ raise CannotParseImage
442
+ end
439
443
  @content_length = decoded.size
440
444
  fetch_using_read StringIO.new(decoded)
441
445
  end
@@ -471,19 +475,20 @@ class FastImage
471
475
 
472
476
  # Peeking beyond the end of the input will raise
473
477
  def peek(n)
474
- while @strpos + n - 1 >= @str.size
478
+ while @strpos + n > @str.size
475
479
  unused_str = @str[@strpos..-1]
480
+
476
481
  new_string = @read_fiber.resume
482
+ new_string = @read_fiber.resume if new_string.is_a? Net::ReadAdapter
477
483
  raise CannotParseImage if !new_string
478
-
479
484
  # we are dealing with bytes here, so force the encoding
480
- new_string.force_encoding("ASCII-8BIT") if String.method_defined? :force_encoding
485
+ new_string.force_encoding("ASCII-8BIT") if new_string.respond_to? :force_encoding
481
486
 
482
487
  @str = unused_str + new_string
483
488
  @strpos = 0
484
489
  end
485
490
 
486
- @str[@strpos..(@strpos + n - 1)]
491
+ @str[@strpos, n]
487
492
  end
488
493
 
489
494
  def read(n)
@@ -501,7 +506,7 @@ class FastImage
501
506
  new_string = @read_fiber.resume
502
507
  raise CannotParseImage if !new_string
503
508
 
504
- new_string.force_encoding("ASCII-8BIT") if String.method_defined? :force_encoding
509
+ new_string.force_encoding("ASCII-8BIT") if new_string.respond_to? :force_encoding
505
510
 
506
511
  fetched += new_string.size
507
512
  @str = new_string
@@ -536,8 +541,21 @@ class FastImage
536
541
  when '8B'
537
542
  :psd
538
543
  when "\0\0"
539
- # ico has either a 1 (for ico format) or 2 (for cursor) at offset 3
540
544
  case @stream.peek(3).bytes.to_a.last
545
+ when 0
546
+ # http://www.ftyps.com/what.html
547
+ # HEIC is composed of nested "boxes". Each box has a header composed of
548
+ # - Size (32 bit integer)
549
+ # - Box type (4 chars)
550
+ # - Extended size: only if size === 1, the type field is followed by 64 bit integer of extended size
551
+ # - Payload: Type-dependent
552
+ case @stream.peek(12)[4..-1]
553
+ when "ftypheic"
554
+ :heic
555
+ when "ftypmif1"
556
+ :heif
557
+ end
558
+ # ico has either a 1 (for ico format) or 2 (for cursor) at offset 3
541
559
  when 1 then :ico
542
560
  when 2 then :cur
543
561
  end
@@ -545,7 +563,7 @@ class FastImage
545
563
  :webp if @stream.peek(12)[8..11] == "WEBP"
546
564
  when "<s"
547
565
  :svg if @stream.peek(4) == "<svg"
548
- when /<[?!]/
566
+ when /\s\s|\s<|<[?!]/, 0xef.chr + 0xbb.chr
549
567
  # Peek 10 more chars each time, and if end of file is reached just raise
550
568
  # unknown. We assume the <svg tag cannot be within 10 chars of the end of
551
569
  # the file, and is within the first 250 chars.
@@ -566,6 +584,167 @@ class FastImage
566
584
  end
567
585
  alias_method :parse_size_for_cur, :parse_size_for_ico
568
586
 
587
+ class Heic # :nodoc:
588
+ def initialize(stream)
589
+ @stream = stream
590
+ end
591
+
592
+ def width_and_height
593
+ @rotation = 0
594
+ @max_size = nil
595
+ @primary_box = nil
596
+ @ipma_boxes = []
597
+ @ispe_boxes = []
598
+ @final_size = nil
599
+
600
+ catch :finish do
601
+ read_boxes!
602
+ end
603
+
604
+ if [90, 270].include?(@rotation)
605
+ @final_size.reverse
606
+ else
607
+ @final_size
608
+ end
609
+ end
610
+
611
+ private
612
+
613
+ # Format specs: https://www.loc.gov/preservation/digital/formats/fdd/fdd000525.shtml
614
+
615
+ # If you need to inspect a heic/heif file, use
616
+ # https://gpac.github.io/mp4box.js/test/filereader.html
617
+ def read_boxes!(max_read_bytes = nil)
618
+ end_pos = max_read_bytes.nil? ? nil : @stream.pos + max_read_bytes
619
+ index = 0
620
+
621
+ loop do
622
+ return if end_pos && @stream.pos >= end_pos
623
+
624
+ box_type, box_size = read_box_header!
625
+
626
+ case box_type
627
+ when "meta"
628
+ handle_meta_box(box_size)
629
+ when "pitm"
630
+ handle_pitm_box(box_size)
631
+ when "ipma"
632
+ handle_ipma_box(box_size)
633
+ when "hdlr"
634
+ handle_hdlr_box(box_size)
635
+ when "iprp", "ipco"
636
+ read_boxes!(box_size)
637
+ when "irot"
638
+ handle_irot_box
639
+ when "ispe"
640
+ handle_ispe_box(box_size, index)
641
+ when "mdat"
642
+ throw :finish
643
+ else
644
+ @stream.read(box_size)
645
+ end
646
+
647
+ index += 1
648
+ end
649
+ end
650
+
651
+ def handle_irot_box
652
+ @rotation = (read_uint8! & 0x3) * 90
653
+ end
654
+
655
+ def handle_ispe_box(box_size, index)
656
+ throw :finish if box_size < 12
657
+
658
+ data = @stream.read(box_size)
659
+ width, height = data[4...12].unpack("N2")
660
+ @ispe_boxes << { index: index, size: [width, height] }
661
+ end
662
+
663
+ def handle_hdlr_box(box_size)
664
+ throw :finish if box_size < 12
665
+
666
+ data = @stream.read(box_size)
667
+ throw :finish if data[8...12] != "pict"
668
+ end
669
+
670
+ def handle_ipma_box(box_size)
671
+ @stream.read(3)
672
+ flags3 = read_uint8!
673
+ entries_count = read_uint32!
674
+
675
+ entries_count.times do
676
+ id = read_uint16!
677
+ essen_count = read_uint8!
678
+
679
+ essen_count.times do
680
+ property_index = read_uint8! & 0x7F
681
+
682
+ if flags3 & 1 == 1
683
+ property_index = (property_index << 7) + read_uint8!
684
+ end
685
+
686
+ @ipma_boxes << { id: id, property_index: property_index - 1 }
687
+ end
688
+ end
689
+ end
690
+
691
+ def handle_pitm_box(box_size)
692
+ data = @stream.read(box_size)
693
+ @primary_box = data[4...6].unpack("S>")[0]
694
+ end
695
+
696
+ def handle_meta_box(box_size)
697
+ throw :finish if box_size < 4
698
+
699
+ @stream.read(4)
700
+ read_boxes!(box_size - 4)
701
+
702
+ throw :finish if !@primary_box
703
+
704
+ primary_indices = @ipma_boxes
705
+ .select { |box| box[:id] == @primary_box }
706
+ .map { |box| box[:property_index] }
707
+
708
+ ispe_box = @ispe_boxes.find do |box|
709
+ primary_indices.include?(box[:index])
710
+ end
711
+
712
+ if ispe_box
713
+ @final_size = ispe_box[:size]
714
+ end
715
+
716
+ throw :finish
717
+ end
718
+
719
+ def read_box_header!
720
+ size = read_uint32!
721
+ type = @stream.read(4)
722
+ [type, size - 8]
723
+ end
724
+
725
+ def read_uint8!
726
+ @stream.read(1).unpack("C")[0]
727
+ end
728
+
729
+ def read_uint16!
730
+ @stream.read(2).unpack("S>")[0]
731
+ end
732
+
733
+ def read_uint32!
734
+ @stream.read(4).unpack("N")[0]
735
+ end
736
+ end
737
+
738
+ def parse_size_for_heic
739
+ heic = Heic.new(@stream)
740
+ heic.width_and_height
741
+ end
742
+
743
+ def parse_size_for_heif
744
+ heic = Heic.new(@stream)
745
+ heic.width_and_height
746
+ end
747
+
569
748
  class Gif # :nodoc:
570
749
  def initialize(stream)
571
750
  @stream = stream
@@ -585,7 +764,7 @@ class FastImage
585
764
 
586
765
  # fields (1) + bg color (1) + pixel ratio (1)
587
766
  fields = @stream.read(3).unpack("CCC")[0]
588
- if fields & 0x80 # Global Color Table
767
+ if fields & 0x80 != 0 # Global Color Table
589
768
  # 2 * (depth + 1) colors, each occupying 3 bytes (RGB)
590
769
  @stream.skip(3 * 2 ** ((fields & 0x7) + 1))
591
770
  end
@@ -0,0 +1,3 @@
1
+ class FastImage
2
+ VERSION = "2.2.5"
3
+ 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.2.1
4
+ version: 2.2.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Stephen Sykes
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-07-23 00:00:00.000000000 Z
11
+ date: 2021-02-28 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: fakeweb-fi
@@ -77,11 +77,12 @@ files:
77
77
  - MIT-LICENSE
78
78
  - README.textile
79
79
  - lib/fastimage.rb
80
+ - lib/fastimage/version.rb
80
81
  homepage: http://github.com/sdsykes/fastimage
81
82
  licenses:
82
83
  - MIT
83
84
  metadata: {}
84
- post_install_message:
85
+ post_install_message:
85
86
  rdoc_options:
86
87
  - "--charset=UTF-8"
87
88
  require_paths:
@@ -97,8 +98,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
97
98
  - !ruby/object:Gem::Version
98
99
  version: '0'
99
100
  requirements: []
100
- rubygems_version: 3.0.3
101
- signing_key:
101
+ rubygems_version: 3.1.6
102
+ signing_key:
102
103
  specification_version: 4
103
104
  summary: FastImage - Image info fast
104
105
  test_files: []