mieki256's diary



2017/04/09() [n年前の日記]

#1 [dxruby][ruby] ドット絵モドキを自動生成するRubyスクリプトを少し手直し

ドット絵モドキを自動生成するソレを Ruby + DXRuby で試しているところ。

_先日の実験 では、乱数でテキトーにドットを打っていくという安易なやり方でも、 てなことをすればちょっとそれっぽいのが生成されると分かったわけだけど。更に、ドット絵専用の拡大アルゴリズムである Scale2x、Scale3x を適用してみたらどうなるか実験してみたり。

結果はこんな感じに。前回は3倍表示してたけど、コレは原寸表示。(16x16 を Scale3x で3倍に拡大して生成。

tinypixelartgen_take3_ss.png

意外とイケそうな…でもないかな…どうなんだ…ちと判断が難しい微妙な結果に。

ちなみに、8倍に拡大するとこんな感じに。

tinypixelartgen_take3_ss2.png

これはこれで味わい深い…のかな…どうなんだ…。

ソースについて。 :

ソースは以下。tinypixelartgen_take3.rb と scalenx.rb の2つが必要。

_tinypixelartgen_take3.rb
_scalenx.rb

Ruby + DXRuby がインストールされてる環境で、ruby tinypixelartgen_take3.rb を実行すると生成される。スペースキーを押せば次々に生成し直し。

ライセンス面での問題。 :

惜しむらくは、Scale2x、Scale3x がGPLなので、Scale2x、Scale3x を利用してるこのドット絵自動生成スクリプトも GPL になるあたりが厳しいなと。いわゆるGPL汚染。

このスクリプトを何かに組み込んで利用したいと思っても、おそらくはそのアプリ全体までGPLで配布しないといけないのだろうと…。MIT License や CC0 / Public Domain に比べると、GPLは不便と言うか不自由だなと。

ん? 待てよ? 自分は _Scale2xのアルゴリズム解説ページ を参考にしてソースを書いたけど、 _Scale2x の exe のソース は一切見ないでソースを書いたわけで…。それでもこのスクリプトはGPLになるんだろうか?

いや、でも…。処理の肝心要の部分を解説ページ中から丸々コピペしてるのだから、コレはやっぱり GPL になるのかしらん。どうなんだろう。

まあ、ニアレストネイバー(Nearest neighbor)で拡大したほうがドットが強調されてドット絵らしさが増すのでは、という気もするので、いざとなれば Scale2x を使ってるあたりをゴッソリ削除してもいいんじゃないか、そうなれば自由に使えるやろ、と思ったりもしますが。

課題というか別の疑問。 :

「5x5ドットぐらいなら横方向3ドット分を作ってミラーするだけでもそれっぽくなるよ」てな方法があるのだけど。

_Space Invader Generator | The 8Bit Pimps Pixel Mine

たしか、GitHubのアイコンも同様の手法で生成されてたと思ったけど。

_Identicons!

それらの各1ドットに、事前に用意した8x8ドットのパターンをランダムに置いていったらどうなるかなと疑問が。例えば以下のようなパターンを使って…。

_mieki256's diary - DXRubyでキャラグラエディタを作ってみた

どうなるんでしょうね。

#2 [ruby] 配列の初期化って時間がかかるのだな

昨日書いた Scale2x の処理を行う Ruby スクリプトを、もうちょっと最適化できないものかと弄っていたのだけど。

ループ内をアレコレ弄って「あまり速くならねえな」とガッカリした直後、ふと、配列の初期化はしなくてもいいんじゃないかと気が付いて。配列の確保だけするようにしてみたら処理時間が二桁減って愕然。 *1

配列の初期化って結構処理時間を食うのだな…。いやまあ、メモリを確保して中身を書き換えていくわけだから当然だろうけど。にしても、まさか条件分岐が山ほど入ってるループ処理部分より配列の初期化で時間を食ってたとは…。

測ってみた。 :

こんな感じで。環境は Windows10 x64 + Ruby 2.2.6-p396 mingw32版。
# Array.new のベンチマーク

require 'benchmark'

w, h = 512, 256

Benchmark.bm(7) do |x|

  # 最初にやってたソレ
  x.report("[][][]") do
    a = Array.new(h).map { Array.new(w).map { Array.new(4, 0) } }
  end

  # 書き方を変えてみた
  x.report("[][][]B") do
    a = Array.new(h) { Array.new(w) { Array.new(4, 0) } }
  end

  # ループを馬鹿みたいに回してみた
  x.report("loop") do
    a = []
    h.times do
      b = []
      w.times do
        b << [0, 0, 0, 0]
      end
      a << b
    end
  end

  # 初期化を省いた
  x.report("[][]") do
    a = Array.new(h).map { Array.new(w) }
  end

  # 一次元配列にしてみた
  x.report("[]") do
    a = Array.new(w * h * 4, 0)
  end

end

結果。
              user     system      total        real
[][][]    0.047000   0.000000   0.047000 (  0.049730)
[][][]B   0.047000   0.000000   0.047000 (  0.041508)
loop      0.031000   0.000000   0.031000 (  0.032914)
[][]      0.000000   0.000000   0.000000 (  0.000188)
[]        0.000000   0.000000   0.000000 (  0.000549)

配列の中身をゼロクリアするとやっぱり遅くなるようで…。多次元配列じゃなく一次元配列にしてゼロクリアしたら速くならないか、と思ったけど甘かった。でもないか。いや、しかし、多次元配列の確保より、一次元配列でゼロクリアするほうが遅いんだよな…。

ちなみに、Ruby 2.2 ではなく Ruby 2.3 でも試してみたけど、さほど違いは無く。ていうかむしろ微妙に遅くなったり。まあ、誤差かもしれないけど。

*1: もっとも、渡された配列の中身をそのまま使う形になった ―― ポインタだけを書き換えてる形になったようなものだから、元の配列の内容を弄られるとおかしなことになるけれど、それは元々そうなってたから今更だし。

#3 [ruby][dxruby] RGBとHLS(HSL)を変換するRubyスクリプトを書いた

グラデ塗りを試す際に必要になりそうだったので、RGBと _HLS(HSL) を変換するRubyスクリプトを書いた。

HLSてのは…。、Hue(色相)、Lightness(輝度)、Saturation(彩度)で色を表す例のヤツ、という説明でいいのだろうか。お絵かきソフトでえてして用意されてたりするアレ。とはちょっと違うか。アレは _HSV か…。

とりあえず、変換処理のソースは以下。

_tinycolorsys.rb

_RGBとHSLの相互変換ツールと変換計算式 - PEKO STEP の解説を参考にして書きました。ありがたや。

使用例。

test_colorsys_ss.png

DXRuby を使って、マウスのx/y座標やカーソルキーの上下でHLSの値を変えて、背景色を変更してる。

require_relative 'tinycolorsys' を呼んで、include TinyColorSys しておくと、hls_to_rgb() と rgb_to_hls() が使えるようになる。

_test_colorsys.rb
# tinycolorsys.rb の動作テスト

require 'dxruby'
require_relative 'tinycolorsys'

include TinyColorSys

fnt = Font.new(28)
v2 = 0.5
set_hls = true

Window.loop do
  break if Input.keyPush?(K_ESCAPE)

  set_hls = !set_hls if Input.mousePush?(M_LBUTTON)

  v0 = Input.mousePosX.to_f / (Window.width - 1)
  v1 = Input.mousePosY.to_f / (Window.height - 1)
  v2 += (Input.keyDown?(K_UP))? (1.0 / 255.0) : 0
  v2 -= (Input.keyDown?(K_DOWN))? (1.0 / 255.0) : 0

  v0 = [[v0, 1.0].min, 0.0].max
  v1 = [[v1, 1.0].min, 0.0].max
  v2 = [[v2, 1.0].min, 0.0].max

  if set_hls
    h = v0
    l = v1
    s = v2
    r, g, b = hls_to_rgb(h, l, s)
    h = (h * 360).to_i
    l = (l * 100).to_i
    s = (s * 100).to_i
  else
    r = (v0 * 255).to_i
    g = (v1 * 255).to_i
    b = (v2 * 255).to_i
    h, l, s = rgb_to_hls(r, g, b)
    h = (360 * h).to_i
    l = (100 * l).to_i
    s = (100 * s).to_i
  end

  Window.bgcolor = [r, g, b]
  col = (l < 50)? C_WHITE : C_BLACK
  msg = (set_hls)? "use HLS" : "use RGB"
  Window.drawFont(4, 4, msg, fnt, :color => col)
  Window.drawFont(4, 40, "RGB=#{r}, #{g}, #{b}", fnt, :color => col)
  Window.drawFont(4, 80, "HLS=#{h}, #{l}, #{s}", fnt, :color => col)
  Window.drawFont(4, 120, "(mouse x/y , Up/Down key)", fnt, :color => col)
end

既にgemがあった。 :

上記のスクリプトを書いた後で、ふと気になってググってみたら、既にそういう gem があった…。自分で書く必要は無かった…。

_color | RubyGems.org | your community gem host
_halostatue/color: Color tools for Ruby.

gem install color でインストールできる。

以下は、前述のソレを color を使って書き直した例。
# gem color の動作テスト

require 'dxruby'
require 'color'

fnt = Font.new(28)
v2 = 0.5
set_hls = true

Window.loop do
  break if Input.keyPush?(K_ESCAPE)

  set_hls = !set_hls if Input.mousePush?(M_LBUTTON)

  v0 = Input.mousePosX.to_f / (Window.width - 1)
  v1 = Input.mousePosY.to_f / (Window.height - 1)
  v2 += (Input.keyDown?(K_UP))? (1.0 / 255.0) : 0
  v2 -= (Input.keyDown?(K_DOWN))? (1.0 / 255.0) : 0

  v0 = [[v0, 1.0].min, 0.0].max
  v1 = [[v1, 1.0].min, 0.0].max
  v2 = [[v2, 1.0].min, 0.0].max

  if set_hls
    h = v0 * 360.0
    l = v1 * 100.0
    s = v2 * 100.0
    rgb = Color::HSL.new(h, s, l).to_rgb
    r = rgb.red
    g = rgb.green
    b = rgb.blue
  else
    r = (v0 * 255).to_i
    g = (v1 * 255).to_i
    b = (v2 * 255).to_i
    hsl = Color::RGB.new(r, g, b).to_hsl
    h = hsl.hue
    l = hsl.luminosity
    s = hsl.saturation
  end
  r = r.to_i
  g = g.to_i
  b = b.to_i
  h = h.to_i
  l = l.to_i
  s = s.to_i

  Window.bgcolor = [r, g, b]
  col = (l < 50)? C_WHITE : C_BLACK
  msg = (set_hls)? "use HLS" : "use RGB"
  Window.drawFont(4, 4, msg, fnt, :color => col)
  Window.drawFont(4, 40, "RGB=#{r}, #{g}, #{b}", fnt, :color => col)
  Window.drawFont(4, 80, "HLS=#{h}, #{l}, #{s}", fnt, :color => col)
  Window.drawFont(4, 120, "(mouse x/y , Up/Down key)", fnt, :color => col)
end

  • Color::HSL.new(hue, saturation, luminosity) で渡す値は、hue が 0〜360、saturation と luminosity が 0〜100。
  • Color::RGB.new(red, green, blue) で渡す値は、0〜255。
  • HSL.to_rgb で RGB になるし、RGB.to_hsl で HSL になる。
  • RGB.red、RGB.green、RGB.blue で取り出した値は、0〜255。
  • HSL.hue、HSL.luminosity、HSL.saturation で取り出し値は、0〜360、0〜100、0〜100。
  • HSL も RGB も、0.0〜1.0を与えて生成するメソッドがあるらしい。hsl = Color:HSL.from_fraction(0.5, 1.0, 0.5) みたいな書き方をすればいいのかな? たぶん。ちと自信無し。

ホント、最初からコレを使えばよかった…。

#4 [gimp] G'MICプラグインがQtベースになるっぽい

G'MICプラグインという、500種類以上のフィルタが使える画像フィルタ集があるのですが。 *1 えてしてGIMPと組わせて使うことが多い、のかな。Kritaにも同梱されてたりしますが。

_G'MIC - GREYC's Magic for Image Computing: A Full-Featured Open-Source Framework for Image Processing
_「G'MIC (GREYC's Magic Image Converter)」

最新版に更新してみようと公式サイトを開いて 2.0.0pre版をDLしようとしたら、gimp_gtk版とgimp_qt版の2つがあることに気が付いて。

_G'MIC - Google+ を眺めると…。どうやら 2.0.0版からはQtベースになるっぽい雰囲気。Qt、なんだか流行ってるなあ…。人気あるなあ…。
*1: 今現在、手元の環境で確認してみたら、526種類のフィルタが有効になってた…。

以上、1 日分です。

過去ログ表示

Prev - 2017/04 - 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

カテゴリで表示

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


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

Powered by hns-2.19.6, HyperNikkiSystem Project