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 +4 -4
- data/lib/fastimage/version.rb +5 -0
- data/lib/fastimage.rb +188 -2
- metadata +7 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d7667683a4bbc8ac16d583fb3ed7c93e6a58a25c19bf8df909ab7dae8d4ef782
|
4
|
+
data.tar.gz: 0baf5dcf6af104d0edd38baf65b7b35c972e6fc4271363d52855071e22b97a82
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9261157ade925ba5be4761028b4d70a698f1cc4d54e4ef0fcb7f4b23b6120ae6f9c42516b0dc17f915c423d168a4ef66c805a686ea20e3ca311556ce3e930593
|
7
|
+
data.tar.gz: 2d319a0aa6c4e7c7a3d951b3025d6215ac999bc2efe5d054720dac9c063cb3e2939e35e30660cf360bfae5f88285b91bb8029ec594c64ca1eb9e3e4144fa6b4c
|
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.
|
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-
|
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.
|
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: []
|