5分で作るソーシャル画像処理サービス(目標)(準備中)
下準備
$ sudo apt-get install imagemagick libmagick++9-dev -y
$ sudo apt-get install graphicsmagick libgraphicsmagick1 libgraphicsmagick1-dev libgraphicsmagick++1-dev libgraphicsmagick++1 -y
$ sudo gem install rmagick cairo
確認
rmagickが入っていること。
中途半端に入っていると、Image#extentがundefinedだったりするので、irb上で確認する。
$ irb -rubygems -r RMagick
irb(main):001:0> Magick::ImageList.new("ruby.jpg").first.methods.grep /ext/
=> ["extend", "texture_floodfill", "extract_info", "extract_info=", "texture_flood_fill", "texture_fill_to_border", "extent", "channel_extrema"]
irb(main):002:0> Magick::ImageList.new("ruby.jpg").first.extent
ArgumentError: wrong number of arguments (expected 2 to 4, got 0)
from (irb):2:in `extent'
from (irb):2
irb(main):003:0> exit
ついでにネットワークの接続確認。
手順(これを追うのに5分目標)
アプリ作成と動作確認
$ rails filtr
$ cd filtr
$ script/plugin install git://github.com/nanki/purl.git
$ script/generate scaffold Image data:binary
$ rake db:migrate
$ script/server
http://localhost:3000/へアクセスして、railsアプリの起動確認。
ソース修正
images/show/[id]にアクセス時、画像を表示する。
# /app/views/images/show.html.erb <p> <b>Data:</b> <img src="<%= url_for :action => :view, :id => @image.id %>" width="120px" height="90px" /></a></td> </p>
images/indexにアクセス時、画像の一覧をプレビュー月で表示する。
# app/views/images/index.html.erb <table> <tr> <th>Data</th> </tr> <% for image in @images %> <tr> <td><a href="<%= url_for :action => :view, :id => image.id %>"> <img src="<%= url_for :action => :view, :id => image.id %>" width="120px" height="90px" /></a></td> <td><%= link_to 'Show', image %></td> <td><%= link_to 'Edit', edit_image_path(image) %></td> <td><%= link_to 'Destroy', image, :confirm => 'Are you sure?', :method => :delete %></td> </tr> <% end %> </table>
images/newのフォームから、画像をアップロードできるようにする。(file_field使用)
# app/views/images/new.html.erb <% form_for(@image, :html => {:multipart => true }) do |f| %> <%= f.error_messages %> <p> <%= f.label :data %><br /> <%= file_field :upload, :data %> </p> <p> <%= f.submit "Upload", :disable_with => "wait" %> </p> <% end %>
- ImagesController#createで、images/newの画像アップロードフォームから受け取った画像のバイナリをDBに入れる。
- ImagesController#viewでリクエストされた画像のバイナリをDBから取り出して送る。(view側では、ImagesController#viewのパスをimageタグのsrcに指定する)
# /app/controllers/images_controller.rb class ImagesController < ApplicationController def view @image = Image.find(params[:id]) send_data(@image.data, :disposition => 'inline') end # ... # POST /images # POST /images.xml def create @image = Image.new(:data => params[:upload][:data].read) respond_to do |format| if @image.save flash[:notice] = 'Image was successfully created.' format.html { redirect_to(@image) } format.xml { render :xml => @image, :status => :created, :location => @image } else format.html { render :action => "new" } format.xml { render :xml => @image.errors, :status => :unprocessable_entity } end end end # ... end
- ここで画像がアップロードできること、アップロードした画像を一覧表示できること、個別に表示できることを確認する。
# config/routes.rb ActionController::Routing::Routes.draw do |map| map.connect 'purl/:commands', :controller => 'purl', :action => 'filter', :commands => /.*/ # ...
PurlController#filterで、purlコマンド(params[:command]で渡される)を実行。
# app/controllers/purl_controller.rb class PurlController < ApplicationController caches_page :filter def filter result = Purl::StackMachine.new( params[:commands], Purl::Purl.new {|p| }).run logger.debug result.inspect send_data(result[-2], :type => result[-1], :disposition => 'inline') end end
フィルターを登録できるようにする。
$ script/genrate scaffold ImageFilter title:string command:string && db:migrate
- ここでフィルターを登録してみる
- 登録した画像とフィルターを選択して、画像を加工できるようにする。
$ script/generate scaffold FilteredImage image_id:integer image_filter_id:integer && db:migrate
- filtered_image/newにおいて、セレクトボックスで画像とフィルターを選択できるようにする。
# app/views/filtered_image/new.html.erb <h1>New filtered_image</h1> <% form_for(@filtered_image) do |f| %> <%= f.error_messages %> <p> <%= f.label :image_id %><br /> <%= f.select(:image_id, Image.find(:all).collect {|p| [p.id, p.id]}, {:prompt => "加工したい画像を選んでね!"}) %> </p> <p> <%= f.label :image_filter_id %><br /> <%= f.select(:image_filter_id, ImageFilter.find(:all).collect {|p| [p.title, p.id]}, {:prompt => "フィルターを選んでね!"}) %> </p> <p> <%= f.submit "Create" %> </p> <% end %> <%= link_to 'Back', filtered_images_path %>
- /showにおいて、加工画像を表示できるようにする。
- まず、画面の裏側で画像をつくって@img_srcに画像のパスを入れる
# app/views/filtered_image/show.html.erb class FilteredImagesController < ApplicationController # ... def show @filtered_image = FilteredImage.find(params[:id]) image_id = @filtered_image.image_id command = ImageFilter.find(@filtered_image.image_filter_id).command @img_src = url_for :controller => 'purl', :action => 'filter', :commands => "#{@filtered_image.image_id}:load:#{command}" # ... end # ... end
- 画面側で、@img_srcの画像を表示する。
# app/views/filtered_image/show.html.erb <p> <b>Image:</b> <%=h @filtered_image.image_id %> </p> <p> <b>Image filter:</b> <%=h @filtered_image.image_filter_id %> </p> <p> <img src="<%= @img_src %>"/a> </p> <%= link_to 'Edit', edit_filtered_image_path(@filtered_image) %> | <%= link_to 'Back', filtered_images_path %>
ユーザが何をできるか
- 画像の共有
- フィルターの共有
- 加工した画像とその作り方(元画像とフィルター)の共有
ツール
http://flickr.nosv.org/ja/?s=filtr
http://blog.netswitch.jp/articles/2008/10/23/purl-image-processing-language-with-rails
thx!
http://www.kanasansoft.com/weblab/2008/10/url_rails_plugin.html
http://d.hatena.ne.jp/mostlyfine/20081012/1223837676
http://blog.s21g.com/articles/161
http://doruby.kbmj.com/katsuo_on_rails/20080225/rails_
ファイルのアップロード - SEのタマゴの殻
PurlからloadするためのImageはこの方法で管理。
Rmagickインストールメモ - cuspos diary
# graphicsmagickが入ってないと、Magick::Image.extentが定義されないのかな・・・?
rubyでundefined method "extent"とか言われて超はまった*1
。
セレクトボックスの要素をDBから取得する - One By One - norizo333's Blog -
VMWareのNATサービスを手軽に再起動する方法 - Hello, world! - s21g
イーモバ接続後、Ubuntuを起動したままスタンバイして再接続する際、VMWare NATの再起動が必要だった。
発展
Rails2.1でhas_manyな関連を設定してscaffold出来たとしたら... - ザリガニが見ていた...。
素材画像、フィルターのリコメンドに使えるかも。
- 素材画像 has many 加工画像
- フィルター has many 加工画像
の関係をつくって、
加工に使われた回数の多い素材画像やフィルターを表示するというイメージ。
*1:extentは、画像のサイズを大きくする?基本的なメソッドらしく、定義されていないというのはおかしい。