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(img) ⇒ Adam7Decoder



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

def initialize img
  @image = img
  @widths = [
    [(img.width/8.0).ceil]     * (img.height/8.0).ceil,     # pass1
    [((img.width-4)/8.0).ceil] * (img.height/8.0).ceil,     # pass2
    [(img.width/4.0).ceil]     * ((img.height-4)/8.0).ceil, # pass3
    [((img.width-2)/4.0).ceil] * (img.height/4.0).ceil,     # pass4
    [(img.width/2.0).ceil]     * ((img.height-2)/4.0).ceil, # pass5
    [((img.width-1)/2.0).ceil] * (img.height/2.0).ceil,     # pass6
    [img.width]                * ((img.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

#imageObject

Returns the value of attribute image.



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

def image
  @image
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



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

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)


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

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

#scanline_offset(idx) ⇒ Object

scanline offset in imagedata



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

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



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

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

#scanline_width(idx) ⇒ Object

scanline width in pixels



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

def scanline_width idx
  @widths[idx]
end