🌇

Ruby用2D描画&画像生成ライブラリまとめ

2023/08/24に公開

比較

ライブラリ 座標基点 SVG PS PDF PNG JPG BMP GIF
RMagick 左上
rcairo 左上
gosu 左上
  • 亀 = 内部にカーソルを持っているタイプ
  • SVGの扱いは ImageMagick の時点で動作が怪しい
  • rmagick はアニメーション GIF にも対応している

RMagick

require "rmagick"

width = 800
height = 600

layer = Magick::Image.new(width, height) do |e|
  e.background_color = "black"
end
layer.columns  # => 800
layer.rows     # => 600

gc = Magick::Draw.new
gc.fill("blue")
gc.rectangle(width * 0.25, height * 0.25, width * 0.75 - 1, height * 0.75 - 1)
gc.draw(layer)

gc = Magick::Draw.new
gc.stroke("white")
gc.line(0, 0, width - 1, height - 1)
gc.draw(layer)

layer.write("images/rmagick.png")

  • 拡張子に合わせた画像形式になる
    • ただ SVG にしたら中身がちょっと変で正しく表示されなかった
  • Photoshop のような使い方ができる
    • 複雑なパーツで構成される図形を描く場合は Image クラスで生成するオブジェクトを一つのレイヤーと扱い、最後にZ軸を考慮してすべて重ね合わせるなど
    • 特殊効果もたくさんある
  • ImageList にレイヤーを溜めるとアニメーション gif がすぐ作れたりする

rcairo

require "cairo"

width = 800
height = 600

surface = Cairo::ImageSurface.new(width, height)
surface.width   # => 800
surface.height  # => 600

context = Cairo::Context.new(surface)

context.set_source_color(:black)
context.rectangle(0, 0, width, height)
context.fill

context.set_source_color(:blue)
context.rectangle(width * 0.25, height * 0.25, width / 2, height / 2) # x, y, w, h
context.fill

context.set_source_color(:white)
context.move_to(0, 0)
context.line_to(width - 1, height - 1)
context.stroke

surface.write_to_png("images/rcairo.png")

  • SVG出力するには?
    • surface = Cairo::SVGSurface.new("foo.svg", width, height) に変更する
    • Cairo::ImageSurface.new と引数が違うので注意する
    • write_to_svg メソッドが用意されているわけではなく、いつのまにか生成されている
  • 拡張子に合わせて画像形式が変更されたりしないため他のライブラリに慣れていると使いやすいとは言えない
  • context.scale(width, height) としておくと (width, height) が (1.0, 1.0) 換算になる
    • 抽象化されて便利な面もあればピクセルの境界が曖昧になって不便な面もある
  • 上のサンプルだと特に違いがわからないが文字などを描画する場合は綺麗に表示されるらしい

gosu

require "gosu"

w, h = 800, 600
image = Gosu.render(w, h) do
  Gosu.draw_rect(0, 0, w, h, Gosu::Color::BLACK)
  Gosu.draw_rect(w * 0.25, h * 0.25, w * 0.5, h * 0.5, Gosu::Color::BLUE)
  Gosu.draw_line(0, 0, Gosu::Color::WHITE, w, h, Gosu::Color::RED)
end
image.save("images/gosu.png")

  • GUI アプリケーションとして起動しなくても画像を生成できる
  • 拡張子に合わせた画像形式で保存する
  • png, jpg, bmp に対応している

GUI 版

GUIアプリケーションとして起動し任意のタイミングでスクリーンショットを撮る場合

require "gosu"

class App < Gosu::Window
  def draw
    Gosu.draw_rect(0, 0, width, height, Gosu::Color::BLACK)
    Gosu.draw_rect(width * 0.25, height * 0.25, width * 0.5, height * 0.5, Gosu::Color::BLUE)
    Gosu.draw_line(0, 0, Gosu::Color::WHITE, width, height, Gosu::Color::RED)
  end

  def button_down(id)
    if id == Gosu::KB_SPACE
      Gosu.render(width, height) { draw }.save("images/gosu_app.png")
    end
  end

  new(800, 600).show
end

Discussion