fastimage 2.3.0 → 2.4.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,69 @@
1
+ module FastImageParsing
2
+ class TypeParser
3
+ def initialize(stream)
4
+ @stream = stream
5
+ end
6
+
7
+ # type will use peek to get enough bytes to determing the type of the image
8
+ def type
9
+ parsed_type = case @stream.peek(2)
10
+ when "BM"
11
+ :bmp
12
+ when "GI"
13
+ :gif
14
+ when 0xff.chr + 0xd8.chr
15
+ :jpeg
16
+ when 0x89.chr + "P"
17
+ :png
18
+ when "II", "MM"
19
+ case @stream.peek(11)[8..10]
20
+ when "APC", "CR\002"
21
+ nil # do not recognise CRW or CR2 as tiff
22
+ else
23
+ :tiff
24
+ end
25
+ when '8B'
26
+ :psd
27
+ when "\xFF\x0A".b
28
+ :jxl
29
+ when "\0\0"
30
+ case @stream.peek(3).bytes.to_a.last
31
+ when 0
32
+ # http://www.ftyps.com/what.html
33
+ case @stream.peek(12)[4..-1]
34
+ when "ftypavif"
35
+ :avif
36
+ when "ftypavis"
37
+ :avif
38
+ when "ftypheic"
39
+ :heic
40
+ when "ftypmif1"
41
+ :heif
42
+ else
43
+ if @stream.peek(7)[4..-1] == 'JXL'
44
+ :jxl
45
+ end
46
+ end
47
+ # ico has either a 1 (for ico format) or 2 (for cursor) at offset 3
48
+ when 1 then :ico
49
+ when 2 then :cur
50
+ end
51
+ when "RI"
52
+ :webp if @stream.peek(12)[8..11] == "WEBP"
53
+ when "<s"
54
+ :svg if @stream.peek(4) == "<svg"
55
+ when /\s\s|\s<|<[?!]/, 0xef.chr + 0xbb.chr
56
+ # Peek 10 more chars each time, and if end of file is reached just raise
57
+ # unknown. We assume the <svg tag cannot be within 10 chars of the end of
58
+ # the file, and is within the first 1000 chars.
59
+ begin
60
+ :svg if (1..100).detect {|n| @stream.peek(10 * n).include?("<svg")}
61
+ rescue FiberError, FastImage::CannotParseImage
62
+ nil
63
+ end
64
+ end
65
+
66
+ parsed_type or raise FastImage::UnknownImageType
67
+ end
68
+ end
69
+ end
@@ -0,0 +1,60 @@
1
+ module FastImageParsing
2
+ class Webp < ImageBase # :nodoc:
3
+ def dimensions
4
+ vp8 = @stream.read(16)[12..15]
5
+ _len = @stream.read(4).unpack("V")
6
+ case vp8
7
+ when "VP8 "
8
+ parse_size_vp8
9
+ when "VP8L"
10
+ parse_size_vp8l
11
+ when "VP8X"
12
+ parse_size_vp8x
13
+ else
14
+ nil
15
+ end
16
+ end
17
+
18
+ def animated?
19
+ vp8 = @stream.read(16)[12..15]
20
+ _len = @stream.read(4).unpack("V")
21
+ case vp8
22
+ when "VP8 "
23
+ false
24
+ when "VP8L"
25
+ false
26
+ when "VP8X"
27
+ flags = @stream.read(4).unpack("C")[0]
28
+ flags & 2 > 0
29
+ else
30
+ nil
31
+ end
32
+ end
33
+
34
+ private
35
+
36
+ def parse_size_vp8
37
+ w, h = @stream.read(10).unpack("@6vv")
38
+ [w & 0x3fff, h & 0x3fff]
39
+ end
40
+
41
+ def parse_size_vp8l
42
+ @stream.skip(1) # 0x2f
43
+ b1, b2, b3, b4 = @stream.read(4).bytes.to_a
44
+ [1 + (((b2 & 0x3f) << 8) | b1), 1 + (((b4 & 0xF) << 10) | (b3 << 2) | ((b2 & 0xC0) >> 6))]
45
+ end
46
+
47
+ def parse_size_vp8x
48
+ flags = @stream.read(4).unpack("C")[0]
49
+ b1, b2, b3, b4, b5, b6 = @stream.read(6).unpack("CCCCCC")
50
+ width, height = 1 + b1 + (b2 << 8) + (b3 << 16), 1 + b4 + (b5 << 8) + (b6 << 16)
51
+
52
+ if flags & 8 > 0 # exif
53
+ # parse exif for orientation
54
+ # TODO: find or create test images for this
55
+ end
56
+
57
+ [width, height]
58
+ end
59
+ end
60
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  class FastImage
4
- VERSION = '2.3.0'
4
+ VERSION = '2.4.0'
5
5
  end