Class: ZPNG::Adam7Decoder

Inherits:
Object
  • Object
show all
Defined in:
lib/zpng/adam7_decoder.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(width, height, bpp) ⇒ Adam7Decoder



7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# File 'lib/zpng/adam7_decoder.rb', line 7

def initialize width, height, bpp
  @bpp = bpp
  raise "Invalid BPP #{@bpp.inspect}" if @bpp.to_i == 0
  @widths = [
    [(width/8.0).ceil]     * (height/8.0).ceil,     # pass1
    [((width-4)/8.0).ceil] * (height/8.0).ceil,     # pass2
    [(width/4.0).ceil]     * ((height-4)/8.0).ceil, # pass3
    [((width-2)/4.0).ceil] * (height/4.0).ceil,     # pass4
    [(width/2.0).ceil]     * ((height-2)/4.0).ceil, # pass5
    [((width-1)/2.0).ceil] * (height/2.0).ceil,     # pass6
    [width]                * ((height-1)/2.0).ceil  # pass7
  ].map{ |x| x == [0] ? [] : x }
  @scanlines_count = 0
  # two leading zeroes added specially for convert_coords() code readability
  @pass_starts = [0,0] + @widths.map(&:size).map{ |x| @scanlines_count+=x }
  @widths.flatten! # yahoo! :))
end

Instance Attribute Details

#bppObject

Returns the value of attribute bpp.



3
4
5
# File 'lib/zpng/adam7_decoder.rb', line 3

def bpp
  @bpp
end

#scanlines_countObject (readonly)

Returns the value of attribute scanlines_count.



4
5
6
# File 'lib/zpng/adam7_decoder.rb', line 4

def scanlines_count
  @scanlines_count
end

Instance Method Details

#convert_coords(x, y) ⇒ Object

convert “flat” coords in scanline number & pos in scanline



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
# File 'lib/zpng/adam7_decoder.rb', line 42

def convert_coords x,y
  # optimizing this into one switch/case statement gives
  # about 1-2% speed increase (ruby 1.9.3p286)

  if y%2 == 1
    # 7th pass: last height/2 full scanlines
    [x, y/2 + @pass_starts[7]]
  elsif x%2 == 1 && y%2 == 0
    # 6th pass
    [x/2, y/2 + @pass_starts[6]]
  elsif x%8 == 0 && y%8 == 0
    # 1st pass, starts at 0
    [x/8, y/8]
  elsif x%8 == 4 && y%8 == 0
    # 2nd pass
    [x/8, y/8 + @pass_starts[2]]
  elsif x%4 == 0 && y%8 == 4
    # 3rd pass
    [x/4, y/8 + @pass_starts[3]]
  elsif x%4 == 2 && y%4 == 0
    # 4th pass
    [x/4, y/4 + @pass_starts[4]]
  elsif x%2 == 0 && y%4 == 2
    # 5th pass
    [x/2, y/4 + @pass_starts[5]]
  else
    raise "invalid coords"
  end
end

#pass_start?(idx) ⇒ Boolean

is the specified scanline is a first scanline in the pass? When the image is interlaced, each pass of the interlace pattern is treated as an independent image for filtering purposes

Returns:

  • (Boolean)


75
76
77
# File 'lib/zpng/adam7_decoder.rb', line 75

def pass_start? idx
  @pass_starts.include?(idx)
end

#scanline_offset(idx) ⇒ Object

scanline offset in imagedata



36
37
38
39
# File 'lib/zpng/adam7_decoder.rb', line 36

def scanline_offset idx
  #TODO: optimize
  (0...idx).map{ |x| scanline_size(x) }.inject(&:+) || 0
end

#scanline_size(idx) ⇒ Object

scanline size in bytes, INCLUDING leading filter byte



31
32
33
# File 'lib/zpng/adam7_decoder.rb', line 31

def scanline_size idx
  (scanline_width(idx) * bpp / 8.0).ceil + 1
end

#scanline_width(idx) ⇒ Object

scanline width in pixels



26
27
28
# File 'lib/zpng/adam7_decoder.rb', line 26

def scanline_width idx
  @widths[idx]
end