Praggerとnetpbmで作る画像→AA変換ツール

Rubyを使って何か面白いものを作ってみよう!


高倉 利明
株式会社ケイビーエムジェイ

2008/9/24

プラグインの作成

 今回作成したPraggerプラグインは以下の3つです。

  • 画像→AA変換
  • 電子メール出力
  • IRC出力

 それでは、これからそれぞれのPraggerプラグインの仕様とソースコードを見ていきましょう。

 

 

 

 

 

画像→AA変換プラグイン

 image_to_aa.rbは、本ツールの要となる画像→AA変換プラグインです。

  • 処理概要:指定した画像ファイルをAAデータに変換する
  • Pragger入力:使用しない(configで変換対象ファイルなどを指定)
  • Pragger出力:AA変換したテキストデータ
  • 変換可能な画像ファイルフォーマット:icon、jpeg、png、gif、bmp

 AA変換はRuby上から各netpbmコマンドを利用して行います。入力画像フォーマットにより変換メソッドを変更する必要があるため、get_cmd_nameメソッド内で拡張子からフォーマットを判別しコマンドを決定します。

## image_to_aa - from image file to ascii art text
##
## - module: image_to_aa
##   config:
##     file: convert file path
##     size_mode: convert ascii art size (1:normal size, 2:half size)
##

def image_to_aa(config, data)
  file = config["file"]
  size_mode = config["size_mode"]
  generate_aa(file, size_mode)
end

# アスキーアートを生成
def generate_aa(file, size_mode)
  cmd_name = get_cmd_name(file)
  mode = get_size_mode(size_mode)
  cmd = "#{cmd_name} #{file} | ppmtopgm | pgmtopbm | pbmtoascii #{mode}"
  `#{cmd}`
end

# 拡張子から変換コマンドを選択
def get_cmd_name(file)
  ext = File.extname(file)
  if /.*\.(jpg|jpeg|JPG|JPEG)\z/ =~ ext
    return "jpegtopnm"
  elsif /.*\.(png|PNG)\z/ =~ ext
    return "pngtopnm"
  elsif /.*\.(gif|GIF)\z/ =~ ext
    return "giftopnm"
  elsif /.*\.(bmp|BMP)\z/ =~ ext
    return "bmptopnm"
  elsif /.*\.(ico|ICO)\z/ =~ ext
    return "winicontoppm"
  else
    raise ArgumentError, "file format invalid!!"
  end
end

# AAサイズ選択
def get_size_mode(size_mode)
  if size_mode == 1
    return "-1x2"
  elsif size_mode== 2
    return "-2x4"
  else
    return "" # default(=-1x2)
  end
end
image_to_aa.rb

 本記事では画像ファイルサイズの変換を基本的に行っていないため、AAの大きさは基本的に画像に依存します(size_modeで通常サイズか半分サイズにするかを指定できます)。

 筆者がいろいろと試した結果、ファイルサイズは100×100ピクセルぐらいまでがちょうどよい大きさに変換されます。それ以上大きいファイルを使用すると、生成するAAが非常に大きくなってしまいますので気を付けてください。

電子メール出力プラグイン

 Praggerには標準で電子メール送信を行うプラグインが存在しないため、出力するためのプラグインsend_mail.rbを作成しました。

  • 処理概要:Pragger入力のテキストデータをメールで送信する
  • Pragger入力:テキストデータ
  • Pragger出力:なし

 なお、電子メール送信はtmailに任せているため、あらかじめgemでtmailをインストールしておく必要があります。

takakura@ubuntu-vm:~$ sudo gem install tmail

## send_mail - simple mail send with tmail
##
## ※mail body is input data
##
## - module: send_mail
##   config:
##     subject: mail subject
##     host: mail server host
##     port: mail server port
##     from: from address
##     to: to address
##
require 'rubygems'
require 'tmail'
require 'net/smtp'
require 'nkf'

def send_mail(config, data)
  params = {
    "subject" => config["subject"],
    "body" => data.to_s,
    "host" => config["host"],
    "port" => config["port"],
    "from" => config["from"],
    "to" => config["to"]
  }
  sendmail(params)
end

# メール送信
def sendmail(params)
  mail = TMail::Mail.new
  mail.to = params["to"]
  mail.from = params["from"]
  mail.date = Time.now
  mail.mime_version = '1.0'
  mail.set_content_type 'text', 'plain', {'charset'=>'iso-2022-jp'}
  mail.subject = NKF.nkf('-j -m0', params["subject"])
  mail.body = NKF.nkf('-j -m0', params["body"])

  Net::SMTP.start(params["host"], params["port"]) do |smtp|
    str = mail.encoded
    smtp.send_mail(str, mail.from, mail.destinations)
  end
end
send_mail.rb

IRC出力プラグイン

 電子メール送信と同じく、IRC出力するプラグインsend_irc.rbを作成しました。

  • 処理概要:Pragger入力のテキストデータを指定したIRCチャンネルに投稿する
  • Pragger入力:テキストデータ
  • Pragger出力:なし

 IRCに出力する際に「IRCサーバ、チャンネルに接続→AAを1行単位で投稿→チャンネル、サーバ切断」という一通りの処理を行うため、処理終了までに非常に時間がかかります。

## send_irc - simple irc send
##
## ※send msg is input data
##
## - module: send_irc
##   config:
##     host: irc server host
##     port: irc server port
##     channel: irc server channel
##     nick: nick name
##     user: user name
##     realname: real name
##     send_sleep: sleep time it doesn't do the Excess Flood (optional)
##     quit_sleep: sleep time for server part and quit process (optional)
##
require 'socket'
require 'kconv'

$KCODE = 'UTF8'
@eol = "\r\n"

@send_sleep = 1
@quit_sleep = 30

def send_irc(config, data)

  @host = config["host"]
  @port = config["port"]
  @channel = config["channel"]
  @nick = config["nick"]
  @user = config["user"]
  @realname = config["realname"]

  # Excess Flood対策のスリープ時間
  @send_sleep = config["send_sleep"] if config["send_sleep"]
  # 全ての送信メッセージが処理されて、までのスリープ時間
  @quit_sleep = config["quit_sleep"] if config["quit_sleep"]

  irc_thread_start(data)
end

def irc_thread_start(data)
  @irc = TCPSocket.new(@host, @port)
  login_and_join

  t = Thread.new do
    while host_msg = Kconv.toutf8(@irc.gets)
      puts host_msg
      msg = host_msg.split
      if msg[1] == '366' # 366(End of NAMES list)を接続完了合図とする
        data.each { |msg|
          send_msg(msg)
          sleep @send_sleep
        }
        sleep @quit_sleep
        part_and_quit("byebye!")
        break
      end
    end
  end

  t.join

end

def send_cmd(cmd)
  p "send command :#{cmd}"
  @irc.write(cmd + @eol)
end

def send_msg(msg)
  str = Kconv.tojis(msg).chomp
  send_cmd("PRIVMSG #{@channel} :#{str}")
end

def login_and_join
  send_cmd("USER #{@user}, #{@host}, ignore, #{@realname}")
  send_cmd("NICK #{@nick}")
  send_cmd("JOIN #{@channel}")
end

def part_and_quit(bye)
  send_cmd("PART #{@channel} #{bye}")
  send_cmd("QUIT #{bye}")
end
send_irc.rb

2/3

Index
Praggerとnetpbmで作る画像→AA変換ツール
  Page1
Praggerって何?
netpbmライブラリ群によるAA変換
Page2
プラグインの作成
画像→AA変換
電子メール出力プラグイン
IRC出力プラグイン
  Page3
複数先への出力を平然とやってのけるッ!!
これからの発展形を目指して

Coding Edgeフォーラム トップページ

 Ruby/Rails関連記事
プログラミングは人生だ
まつもと ゆきひろのコーディング天国
 ときにプログラミングはスポーツであり、ときにプログラミングは創造である。楽しいプログラミングは人生をより実りあるものにしてくれる
生産性を向上させるRuby向け統合開発環境カタログ
Ruby on Rails 2.0も強力サポート
 生産性が高いと評判のプログラミング言語「Ruby」。統合開発環境を整えることで、さらに効率的なプログラミングが可能になる
かんたんAjax開発をするためのRailsの基礎知識
Ruby on RailsのRJSでかんたんAjax開発(前編)
 実はAjaxアプリケーション開発はあなたが思うよりも簡単です。まずはRuby on Railsの基礎知識から学びましょう
Praggerとnetpbmで作る画像→AA変換ツール
Rubyを使って何か面白いものを作ってみよう!
 一般的な画像をアスキーアートに変換するツールを作ってみる。さらに出力にバリエーションを持たせてみよう
コードリーディングを始めよう
Railsコードリーディング〜scaffoldのその先へ〜(1)
 優れたプログラマはコードを書くのと同じくらい、読みこなす。優れたコードを読むことで自身のスキルも上達するのだ
  Coding Edgeフォーラムフィード  2.01.00.91


Coding Edge フォーラム 新着記事
@ITメールマガジン 新着情報やスタッフのコラムがメールで届きます(無料)

注目のテーマ

>

Coding Edge 記事ランキング

本日 月間