# File lib/png/reader.rb, line 66
  def self.read_IDAT data, bit_depth, color_type, canvas
    data = Zlib::Inflate.inflate(data).unpack 'C*'

    pixel_size = color_type == RGBA ? 4 : 3

    height = canvas.height
    scanline_length = pixel_size * canvas.width + 1 # for filter

    row = canvas.height - 1
    until data.empty? do
      row_data = data.slice! 0, scanline_length

      filter = row_data.shift
      case filter
      when NONE then
      when SUB then
        row_data.each_with_index do |byte, index|
          left = index < pixel_size ? 0 : row_data[index - pixel_size]
          row_data[index] = (byte + left) % 256
        end
      when UP then
        row_data.each_with_index do |byte, index|
          col = index / pixel_size
          upper = row == 0 ? 0 : canvas[col, row + 1].values[index % pixel_size]
          row_data[index] = (upper + byte) % 256
        end
      when AVG then
        row_data.each_with_index do |byte, index|
          col = index / pixel_size
          upper = row == 0 ? 0 : canvas[col, row + 1].values[index % pixel_size]
          left = index < pixel_size ? 0 : row_data[index - pixel_size]

          row_data[index] = (byte + ((left + upper)/2).floor) % 256
        end
      when PAETH then
        left = upper = upper_left = nil
        row_data.each_with_index do |byte, index|
          col = index / pixel_size

          left = index < pixel_size ? 0 : row_data[index - pixel_size]
          if row == height then
            upper = upper_left = 0
          else
            upper = canvas[col, row + 1].values[index % pixel_size]
            upper_left = col == 0 ? 0 :
              canvas[col - 1, row + 1].values[index % pixel_size]
          end

          paeth = paeth left, upper, upper_left
          row_data[index] = (byte + paeth) % 256
        end
      else
        raise ArgumentError, "invalid filter algorithm #{filter}"
      end

      col = 0
      row_data.each_slice pixel_size do |slice|
        slice << 0xFF if pixel_size == 3
        canvas[col, row] = PNG::Color.new(*slice)
        col += 1
      end

      row -= 1
    end
  end