SVX日記
2023-09-05(Tue) Rubyで端末画面に画像を表示する
一応、CUIコンソール画面に画像を出力できたんだが、Maveに実装することを考えれば、縮小(ついでに拡大)機能と、右側のトリミング機能が必要だ。ついでに透過処理もできるとカッコいい。
さて、透過処理はどうすれば……と考え込んだところで「▀」という「上半分塗りつぶし」文字と「▄」という「下半分塗りつぶし」文字を使い分ける必要があることに気づく。そういや、参考に読んだcatimgのコードで両方を使い分けていたのはそういうことだっとのか。
# ./grouping.rb
["A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R"]
1: A,B,C,D,E
2: F,G,H,I,J
3: K,L,M,N,O
4: P,Q,R
#!/usr/bin/env ruby
x = '@'; xs = []; 18.times {
xs << x.succ!.dup
}
puts(xs.inspect)
n = 0; xp = []; xs.each {|x|
xp << x
if(xp.size == 5)
puts('%d: %s' % [n += 1, xp.join(',')]) # same!
xp.clear
end
}
puts('%d: %s' % [n += 1, xp.join(',')]) # same!
__END__
ここで「same!」とある行を2度書くのがすごくイヤなんだよな。こういうのに対応する構文を持つ言語ってあるのかしらん……とか考えつつ、その部分はさておき、他はどうにかこうにか納得できるコードが書けた。
#!/usr/bin/env ruby
require 'rmagick'
if(ARGV.size == 0)
abort(<<USAGE)
Usage: rcatimg image_file [width] [trim]
USAGE
end
image = Magick::Image.read(ARGV[0])
w = image[0].columns
h = image[0].rows
tgt_w = `tput cols`.to_i
tgt_w > w and tgt_w = w
(it = ARGV[1]) and tgt_w = it.to_i
trm_x = false
(it = ARGV[2]) and trm_x = it.to_i
tgt_h = h * tgt_w / w
sstep = (h << 8) / tgt_h
# +---------+ tdms = [ [ 0b00, 'Ar;Ag;Ab', 'Wr;Wg;Wb' ],
# | A C D | [ 0b10, nil, 'Xr;Xg;Xb' ],
# | W X Z | [ 0b01, 'Cr;Cg;Cb', nil ],
# +---------+ [ 0b00, 'Dr;Dg;Db', 'Zr;Zg;Zb' ] ]
ess = [ "\e[38;2;%2$sm\e[48;2;%3$sm\u2580\e[m", # 0b00: f_col, b_col, [▀]
"\e[38;2;%2$sm\u2580\e[m", # 0b01: f_col, [▀]
"\e[38;2;%3$sm\u2584\e[m", # 0b10: f_col, [▄]
' ' ] # 0b11: [ ]
y8 = 0; tdms = []; tgt_h.times {
x8 = 0; tgt_w.times {|cx|
trm_x and (cx < trm_x or break)
c = image[0].pixel_color(x8 >> 8, y8 >> 8)
tdms[cx] ||= [0]
tdms[cx][0] <<= 1
if(c.opacity < 64)
tdms[cx] << '%d;%d;%d' % [c.red >> 8, c.green >> 8, c.blue >> 8]
else
tdms[cx][0] += 1 # 透明
tdms[cx] << nil
end
x8 += sstep
}
if(tdms[0].size == 3)
tdms.each {|tdm|
print(ess[tdm[0]] % tdm)
}
puts; tdms.clear
end
y8 += sstep
}
if(tdms.size != 0)
tdms.each {|tdm|
print(ess[(tdm[0] << 1) + 1] % tdm)
}
puts
end
if(ENV['INFO'])
puts('#' * trm_x) if(trm_x)
puts('#' * tgt_w)
puts('[%d, %d] -> x%d/%d -> [%d, %d]' % [w, h, 256, sstep, tgt_w, tgt_h])
end
__END__