fastimage 2.2.2 → 2.2.6

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: 6e4c8a8fb1f0bf8db7dff5aef7fd640d56e0938bd0c0e8bd2f5f0a659009429d
4
- data.tar.gz: f827ef53ce46af99612e2628f72ed5bfa2c82b4729ea3a5dccd76dc67079b6c3
3
+ metadata.gz: d7667683a4bbc8ac16d583fb3ed7c93e6a58a25c19bf8df909ab7dae8d4ef782
4
+ data.tar.gz: 0baf5dcf6af104d0edd38baf65b7b35c972e6fc4271363d52855071e22b97a82
5
5
  SHA512:
6
- metadata.gz: 599ffa78f1020ece118a5f1bc47533ad98085ac6f71ede9ad4b2b0c1d8748c81e4fb060f6a1b9f5001f7df2661d70d9a16972bd118863461d39d491d0e3b2988
7
- data.tar.gz: d761639e39eae059e2f810c7d6a124515d3c6db1470236044db376b424e78effaf48c51f4197c3a565c1aae3d1f742e1899e221f566a828c4f1f209d4e91d588
6
+ metadata.gz: 9261157ade925ba5be4761028b4d70a698f1cc4d54e4ef0fcb7f4b23b6120ae6f9c42516b0dc17f915c423d168a4ef66c805a686ea20e3ca311556ce3e930593
7
+ data.tar.gz: 2d319a0aa6c4e7c7a3d951b3025d6215ac999bc2efe5d054720dac9c063cb3e2939e35e30660cf360bfae5f88285b91bb8029ec594c64ca1eb9e3e4144fa6b4c
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ class FastImage
4
+ VERSION = '2.2.6'
5
+ end
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
  #
@@ -538,8 +541,18 @@ class FastImage
538
541
  when '8B'
539
542
  :psd
540
543
  when "\0\0"
541
- # ico has either a 1 (for ico format) or 2 (for cursor) at offset 3
542
544
  case @stream.peek(3).bytes.to_a.last
545
+ when 0
546
+ # http://www.ftyps.com/what.html
547
+ case @stream.peek(12)[4..-1]
548
+ when "ftypavif"
549
+ :avif
550
+ when "ftypheic"
551
+ :heic
552
+ when "ftypmif1"
553
+ :heif
554
+ end
555
+ # ico has either a 1 (for ico format) or 2 (for cursor) at offset 3
543
556
  when 1 then :ico
544
557
  when 2 then :cur
545
558
  end
@@ -547,7 +560,7 @@ class FastImage
547
560
  :webp if @stream.peek(12)[8..11] == "WEBP"
548
561
  when "<s"
549
562
  :svg if @stream.peek(4) == "<svg"
550
- when /<[?!]/
563
+ when /\s\s|\s<|<[?!]/, 0xef.chr + 0xbb.chr
551
564
  # Peek 10 more chars each time, and if end of file is reached just raise
552
565
  # unknown. We assume the <svg tag cannot be within 10 chars of the end of
553
566
  # the file, and is within the first 250 chars.
@@ -568,6 +581,179 @@ class FastImage
568
581
  end
569
582
  alias_method :parse_size_for_cur, :parse_size_for_ico
570
583
 
584
+ # HEIC/AVIF are a special case of the general ISO_BMFF format, in which all data is encapsulated in typed boxes,
585
+ # with a mandatory ftyp box that is used to indicate particular file types. Is composed of nested "boxes". Each
586
+ # box has a header composed of
587
+ # - Size (32 bit integer)
588
+ # - Box type (4 chars)
589
+ # - Extended size: only if size === 1, the type field is followed by 64 bit integer of extended size
590
+ # - Payload: Type-dependent
591
+ class IsoBmff # :nodoc:
592
+ def initialize(stream)
593
+ @stream = stream
594
+ end
595
+
596
+ def width_and_height
597
+ @rotation = 0
598
+ @max_size = nil
599
+ @primary_box = nil
600
+ @ipma_boxes = []
601
+ @ispe_boxes = []
602
+ @final_size = nil
603
+
604
+ catch :finish do
605
+ read_boxes!
606
+ end
607
+
608
+ if [90, 270].include?(@rotation)
609
+ @final_size.reverse
610
+ else
611
+ @final_size
612
+ end
613
+ end
614
+
615
+ private
616
+
617
+ # Format specs: https://www.loc.gov/preservation/digital/formats/fdd/fdd000525.shtml
618
+
619
+ # If you need to inspect a heic/heif file, use
620
+ # https://gpac.github.io/mp4box.js/test/filereader.html
621
+ def read_boxes!(max_read_bytes = nil)
622
+ end_pos = max_read_bytes.nil? ? nil : @stream.pos + max_read_bytes
623
+ index = 0
624
+
625
+ loop do
626
+ return if end_pos && @stream.pos >= end_pos
627
+
628
+ box_type, box_size = read_box_header!
629
+
630
+ case box_type
631
+ when "meta"
632
+ handle_meta_box(box_size)
633
+ when "pitm"
634
+ handle_pitm_box(box_size)
635
+ when "ipma"
636
+ handle_ipma_box(box_size)
637
+ when "hdlr"
638
+ handle_hdlr_box(box_size)
639
+ when "iprp", "ipco"
640
+ read_boxes!(box_size)
641
+ when "irot"
642
+ handle_irot_box
643
+ when "ispe"
644
+ handle_ispe_box(box_size, index)
645
+ when "mdat"
646
+ throw :finish
647
+ else
648
+ @stream.read(box_size)
649
+ end
650
+
651
+ index += 1
652
+ end
653
+ end
654
+
655
+ def handle_irot_box
656
+ @rotation = (read_uint8! & 0x3) * 90
657
+ end
658
+
659
+ def handle_ispe_box(box_size, index)
660
+ throw :finish if box_size < 12
661
+
662
+ data = @stream.read(box_size)
663
+ width, height = data[4...12].unpack("N2")
664
+ @ispe_boxes << { index: index, size: [width, height] }
665
+ end
666
+
667
+ def handle_hdlr_box(box_size)
668
+ throw :finish if box_size < 12
669
+
670
+ data = @stream.read(box_size)
671
+ throw :finish if data[8...12] != "pict"
672
+ end
673
+
674
+ def handle_ipma_box(box_size)
675
+ @stream.read(3)
676
+ flags3 = read_uint8!
677
+ entries_count = read_uint32!
678
+
679
+ entries_count.times do
680
+ id = read_uint16!
681
+ essen_count = read_uint8!
682
+
683
+ essen_count.times do
684
+ property_index = read_uint8! & 0x7F
685
+
686
+ if flags3 & 1 == 1
687
+ property_index = (property_index << 7) + read_uint8!
688
+ end
689
+
690
+ @ipma_boxes << { id: id, property_index: property_index - 1 }
691
+ end
692
+ end
693
+ end
694
+
695
+ def handle_pitm_box(box_size)
696
+ data = @stream.read(box_size)
697
+ @primary_box = data[4...6].unpack("S>")[0]
698
+ end
699
+
700
+ def handle_meta_box(box_size)
701
+ throw :finish if box_size < 4
702
+
703
+ @stream.read(4)
704
+ read_boxes!(box_size - 4)
705
+
706
+ throw :finish if !@primary_box
707
+
708
+ primary_indices = @ipma_boxes
709
+ .select { |box| box[:id] == @primary_box }
710
+ .map { |box| box[:property_index] }
711
+
712
+ ispe_box = @ispe_boxes.find do |box|
713
+ primary_indices.include?(box[:index])
714
+ end
715
+
716
+ if ispe_box
717
+ @final_size = ispe_box[:size]
718
+ end
719
+
720
+ throw :finish
721
+ end
722
+
723
+ def read_box_header!
724
+ size = read_uint32!
725
+ type = @stream.read(4)
726
+ [type, size - 8]
727
+ end
728
+
729
+ def read_uint8!
730
+ @stream.read(1).unpack("C")[0]
731
+ end
732
+
733
+ def read_uint16!
734
+ @stream.read(2).unpack("S>")[0]
735
+ end
736
+
737
+ def read_uint32!
738
+ @stream.read(4).unpack("N")[0]
739
+ end
740
+ end
741
+
742
+ def parse_size_for_avif
743
+ bmff = IsoBmff.new(@stream)
744
+ bmff.width_and_height
745
+ end
746
+
747
+ def parse_size_for_heic
748
+ bmff = IsoBmff.new(@stream)
749
+ bmff.width_and_height
750
+ end
751
+
752
+ def parse_size_for_heif
753
+ bmff = IsoBmff.new(@stream)
754
+ bmff.width_and_height
755
+ end
756
+
571
757
  class Gif # :nodoc:
572
758
  def initialize(stream)
573
759
  @stream = stream
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.2
4
+ version: 2.2.6
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: 2021-01-30 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.2.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: []