fastimage 2.2.2 → 2.2.6

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 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: []