class FB2Image::BitMap

Attributes

buf[W]
height[R]
width[R]

Public Class Methods

new(width, height, dpi = 96) click to toggle source
# File lib/fb2image/bmp.rb, line 4
def initialize(width, height, dpi = 96)
  @width = width
  @height = height
  @line_size = width * 3 + (4 - (width * 3) % 4) % 4
  @buf_size = @line_size * height
  @buf = "\000" * @buf_size
  @bit_count = 24
  @compression = 0  # 圧縮無し
  @size_image = 0
  @x_pix_per_meter = (39.375 * dpi).round
  @y_pix_per_meter = (39.375 * dpi).round
  @clr_used = 0
  @cir_important = 0
end
read(filename) click to toggle source

BMPファイルを読み込む

# File lib/fb2image/bmp.rb, line 51
def BitMap.read(filename)
  buf = nil
  open(filename, "rb") do |f|
    buf = f.read
  end

  if buf[0] != ?B or buf[1] != ?M
    raise('[Error] read: Invalid Header')
  end
  real_buf_size = buf.size
  buf_size = (buf[2, 4].unpack("l*"))[0]
  if buf_size > real_buf_size
    raise('[Error] read: Invalid Buffer Size')
  end
  data_offset = (buf[10, 4].unpack("l*"))[0]
  if data_offset != 54
    raise('[Error] read: Invalid Data Offset')
  end

  width = (buf[18, 4].unpack("l*"))[0]
  height = (buf[22, 4].unpack("l*"))[0]

  bit_count = (buf[28, 2].unpack("s*"))[0]
  if bit_count != 24
    raise('[Error] read: Unsupported Color Depth')
  end

  compression = (buf[30, 4].unpack("l*"))[0]
  if compression != 0
    raise('[Error] read: Compression Not Supported')
  end

  pix_per_meter = (buf[38, 4].unpack("l*"))[0]
  dpi = pix_per_meter / 39.375

  image_buf = buf[54, buf_size]

  image = BitMap.new(width, height, dpi)
  image.buf = image_buf

  return image
end

Public Instance Methods

clear(r = 255, g = 255, b = 255) click to toggle source
# File lib/fb2image/bmp.rb, line 19
def clear(r = 255, g = 255, b = 255)
  line = b.chr * @line_size
  @width.times do |x|
    line[x * 3 + 1] = g
    line[x * 3 + 2] = r
  end

  @buf = line * @height
end
clip(x1, y1, x2, y2) click to toggle source

(x1, y1) - (x2, y2)の部分画像を取り出す

# File lib/fb2image/bmp.rb, line 96
def clip(x1, y1, x2, y2)
  return if x1 > x2
  return if y1 > y2
  return if x2 < 0
  return if y2 < 0
  return if x1 >= @width
  return if y1 >= @height
  x1 = 0 if x1 < 0
  y1 = 0 if y1 < 0
  x2 = @width - 1  if x2 >= @width
  y2 = @height - 1 if y2 >= @height

  clip_width  = x2 - x1 + 1
  clip_height = y2 - y1 + 1

  clip_image = BitMap.new(clip_width, clip_height, self.get_dpi)

  for y in 0 .. (clip_height - 1)
    for x in 0 .. (clip_width - 1)
      color = self.pget(x1 + x, y1 + y)
      clip_image.pset(x, y, color[0], color[1], color[2])
    end
  end

  return clip_image
end
get_dpi() click to toggle source
# File lib/fb2image/bmp.rb, line 156
def get_dpi()
  return (@x_pix_per_meter / 39.375).round
end
paste(image, x0 = 0, y0 = 0) click to toggle source

x0, y0 は、貼り付ける始点(左上)の座標

# File lib/fb2image/bmp.rb, line 166
def paste(image, x0 = 0, y0 = 0)
  return if image == nil
  image.height.times do |from_y|
    y = y0 + from_y
    next if y < 0 or @height <= y

    image.width.times do |from_x|
      x = x0 + from_x
      next if x < 0 or @width <= x
      color = image.pget(from_x, from_y)
      self.pset(x, y, color[0], color[1], color[2])
    end
  end
end
pget(x, y) click to toggle source

x, yは整数であることを期待している 戻り値は[r, g, b]な配列

# File lib/fb2image/bmp.rb, line 142
def pget(x, y)
  x = 0 if x < 0
  x = @width - 1 if x >= @width
  y = 0 if y < 0
  y = @height - 1 if y >= @height

  addr = (@height - 1 - y) * @line_size + x * 3
  b = @buf[addr    ]
  g = @buf[addr + 1]
  r = @buf[addr + 2]

  return [r, g, b]
end
pset(x, y, r, g, b) click to toggle source

x, y, r, g, b は整数であることを期待している

# File lib/fb2image/bmp.rb, line 125
def pset(x, y, r, g, b)
  return if x < 0 or @width <= x
  return if y < 0 or @height <= y
  r = 0 if r < 0
  g = 0 if g < 0
  b = 0 if b < 0
  r = 255 if r > 255
  g = 255 if g > 255
  b = 255 if b > 255

  @buf[(@height - 1 - y) * @line_size + x * 3    ] = b.chr
  @buf[(@height - 1 - y) * @line_size + x * 3 + 1] = g.chr
  @buf[(@height - 1 - y) * @line_size + x * 3 + 2] = r.chr
end
set_dpi(dpi) click to toggle source
# File lib/fb2image/bmp.rb, line 160
def set_dpi(dpi)
  @x_pix_per_meter = (39.375 * dpi).round
  @y_pix_per_meter = @x_pix_per_meter
end
write(filename) click to toggle source

BMPファイルを出力する

# File lib/fb2image/bmp.rb, line 33
def write(filename)
  file_size = 14 + 40 + @buf_size
  data_offset = 14 + 40

  open(filename, "wb") do |f|
    f.print 'BM'
    f.print [file_size, 0, data_offset].pack("l*")
    f.print [40, @width, @height].pack("l*")
    f.print [1, @bit_count].pack("S*")
    f.print [@compression, @size_image,
             @x_pix_per_meter, @y_pix_per_meter,
             @clr_used, @cir_important].pack("l*")
    f.print @buf
  end
end