mieki256's diary



2022/08/20() [n年前の日記]

#1 [ruby] Rubyスクリプトに画像ファイルを含める

Ruby/SDL を使ったスクリプト内に、png画像を含めてしまいたい。

exerbを使って Rubyスクリプトをexe化する際、画像ファイルもRubyスクリプト内に含めてしまったほうが都合がいいのかなと思ってしまったので、そういうことができるかどうか試してみた。

まあ、Ruby/SDLを使用しているスクリプトを、exerbでexe化するのは _色々問題があって無理だった のだけど。せっかく実験したので、一応メモしておく。

動作確認環境は以下。
昔、似たようなことをやった記憶がある。日記を検索してみたら、DXRuby を使ってそういうことをしていた。

_Rubyスクリプトの中に画像を仕込むソレ

要するに、png画像を base64文字列に変換してスクリプト内に記述しておけば目的は果たせそう。

_Base64 - Wikipedia

base64への変換スクリプト。 :

png画像等をbase64に変換するスクリプトは以下。

_image2base64.rb
infile = ARGV[0]
bin_data = File.binread(infile)
base64_text = [bin_data].pack("m")
puts base64_text

注意点。Ruby 1.9.3 なら動いたけれど、Ruby 1.8.7 では動かなかった。Ruby 1.8.7 には File.binread() が無かった。

実行は以下。hoge.png を読み込んで、tmp.txt に base64 の形で出力する例。
ruby image2base64.rb hoge.png > tmp.txt

これで得られた base64文字列を、Rubyスクリプトのどこかにコピペしてしまえばいい。

base64を読み出して使うスクリプト。 :

base64文字列を読み出して、Ruby/SDLのウインドウに描画してみる。

_03_imgdisp_rubysdl.rb
require "sdl"
require "stringio"

SCRW, SCRH = 512, 288

# SDL init
SDL.init(SDL::INIT_EVERYTHING)
screen = SDL::Screen.open(SCRW, SCRH, 0, SDL::SWSURFACE)

# read base64 text
base64_text = ""
DATA.each { |l| base64_text += l.chomp }
bin_data_io = StringIO.new(base64_text.unpack("m")[0], "rb")

# load image from StringIO
img = SDL::Surface.loadFromIO(bin_data_io).display_format

# main loop
loop do
  while event = SDL::Event2.poll
    case event
    when SDL::Event2::Quit
      exit
    when SDL::Event2::KeyDown
      exit if event.sym == SDL::Key::ESCAPE
    end
  end

  screen.fill_rect(0, 0, SCRW, SCRH, [0, 100, 200])  # fill bg
  screen.put(img, 32, 32)  # draw sprite
  screen.update_rect(0, 0, 0, 0)  # update screen
  SDL.delay(16.6)  # wait
end

__END__
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

実行すると以下のようなウインドウが開く。画像を描画できている。
ruby 03_imgdisp_rubysdl.rb

03_imgdisp_rubysdl_rb_ss.png


少し解説。

  • このスクリプトは、「__END__」と書かれた行の下に、画像ファイルを変換したbase64文字列を列挙している。
  • Ruby は、「__END__」と書いてある行より下に書かれた行に対して、「DATA」というシンボルでアクセスすることができる。

base64文字列を読み込んで、バイナリデータに変換して、それを StringIO に渡している部分は以下。
base64_text = ""
DATA.each { |l| base64_text += l.chomp }
bin_data_io = StringIO.new(base64_text.unpack("m")[0], "rb")

StringIO というのは、文字列をファイル(IOオブジェクト)のような感覚で利用できるオブジェクトらしい。

_class StringIO (Ruby 1.8.7)


StringIO を渡して、Ruby/SDL で利用できる画像データ(Surface) に変換している部分は以下。
img = SDL::Surface.loadFromIO(bin_data_io).display_format

一般的に、Ruby/SDL で画像ファイルを読み込むなら SDL::Surface.load(filename) を使うけれど、SDL::Surface.loadFromIO(io) を使えば Ruby のIOオブジェクトから画像を読み込める。

_Ruby/SDL Reference Manual (2.x)

別の書き方。 :

「__END__」以下の行を読み込もうとすると1種類のデータしか読み込めなかったりするし、exerb が DATAシンボルに非対応だったりもするので、ちょっと違う書き方をしてみた。

_04_imgdisp_rubysdl_2.rb
require "sdl"
require "stringio"

SCRW, SCRH = 512, 288

BASE64_STRINGS = [
  "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",
]

# SDL init
SDL.init(SDL::INIT_EVERYTHING)
screen = SDL::Screen.open(SCRW, SCRH, 0, SDL::SWSURFACE)

# read base64 text
base64_text = BASE64_STRINGS.join
bin_data_io = StringIO.new(base64_text.unpack("m")[0], "rb")

# load image from StringIO
img = SDL::Surface.loadFromIO(bin_data_io).display_format

# main loop
loop do
  while event = SDL::Event2.poll
    case event
    when SDL::Event2::Quit
      exit
    when SDL::Event2::KeyDown
      exit if event.sym == SDL::Key::ESCAPE
    end
  end

  screen.fill_rect(0, 0, SCRW, SCRH, [0, 100, 200])  # fill bg
  screen.put(img, 32, 32)  # draw sprite
  screen.update_rect(0, 0, 0, 0)  # update screen
  SDL.delay(16.6)  # wait
end

base64 をバイナリ化するあたりは、ちょっとだけ記述が減ってくれた。
base64_text = BASE64_STRINGS.join
bin_data_io = StringIO.new(base64_text.unpack("m")[0], "rb")

以上です。

過去ログ表示

Prev - 2022/08 - Next
1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30 31

カテゴリで表示

検索機能は Namazu for hns で提供されています。(詳細指定/ヘルプ


注意: 現在使用の日記自動生成システムは Version 2.19.6 です。
公開されている日記自動生成システムは Version 2.19.5 です。

Powered by hns-2.19.6, HyperNikkiSystem Project