File: jxlc.rb

package info (click to toggle)
ruby-fastimage 2.4.0-3
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 29,008 kB
  • sloc: ruby: 1,442; xml: 7; makefile: 2; sh: 1
file content (75 lines) | stat: -rw-r--r-- 1,680 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
module FastImageParsing
  class Jxlc # :nodoc:
    attr_reader :width, :height

    LENGTHS = [9, 13, 18, 30]
    MULTIPLIERS = [1, 1.2, Rational(4, 3), 1.5, Rational(16, 9), 1.25, 2]
  
    def initialize(stream)
      @stream = stream
      @width, @height´ = nil
      @bit_counter = 0
      parse_jxlc
    end
    
    def parse_jxlc
      @words = @stream.read(6)[2..5].unpack('vv')

      # small mode allows for values <= 256 that are divisible by 8
      small = get_bits(1)
      if small == 1
        y = (get_bits(5) + 1) * 8
        x = x_from_ratio(y)
        if !x
          x = (get_bits(5) + 1) * 8
        end
        @width, @height = x, y
        return
      end

      len = LENGTHS[get_bits(2)]
      y = get_bits(len) + 1
      x = x_from_ratio(y)
      if !x
        len = LENGTHS[get_bits(2)]
        x = get_bits(len) + 1
      end
      @width, @height = x, y
    end

    def get_bits(size)
      if @words.size < (@bit_counter + size) / 16 + 1
        @words += @stream.read(4).unpack('vv')
      end

      dest_pos = 0
      dest = 0
      size.times do
        word = @bit_counter / 16
        source_pos = @bit_counter % 16
        dest |= ((@words[word] & (1 << source_pos)) > 0 ? 1 : 0) << dest_pos
        dest_pos += 1
        @bit_counter += 1
      end
      dest
    end

    def x_from_ratio(y)
      ratio = get_bits(3)
      if ratio == 0
        return nil
      else
        return (y * MULTIPLIERS[ratio - 1]).to_i
      end
    end
  end

  def parse_size_for_jxl
    if @stream.peek(2) == "\xFF\x0A".b
      JXL.new(@stream).read_size_header
    else
      bmff = IsoBmff.new(@stream)
      bmff.width_and_height
    end
  end
end