<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet href="/stylesheets/rss.css" type="text/css"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/">
  <channel>
    <title>Drinkingbird: Disk free custom images on rails.</title>
    <link>http://www.drinkingbird.net/blog/articles/2007/09/05/disk-free-custom-images-on-rails</link>
    <language>en-us</language>
    <ttl>40</ttl>
    <description>Random keyboard peckings</description>
    <item>
      <title>Disk free custom images on rails.</title>
      <description>&lt;p&gt;So, I hit an odd problem in one of the apps I&amp;#8217;m working on that I needed to render custom text onto images.&lt;/p&gt;

&lt;p&gt;RMagick made that job pretty easy, but I didn&amp;#8217;t want to clog up space on the server with a whole bunch of images that were only being viewed once.&lt;/p&gt;

&lt;p&gt;The solution turned out to be fairly simple in the end, using send_data in the controller.&lt;/p&gt;

&lt;p&gt;I&amp;#8217;ll let the code speak for itself:&lt;/p&gt;

&lt;p&gt;Controller (in StoreController):&lt;/p&gt;

&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;&lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;gift_preview&lt;/span&gt;
  &lt;span class="ident"&gt;require&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;RMagick&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt;

  &lt;span class="ident"&gt;text_params&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="punct"&gt;{&lt;/span&gt;
    &lt;span class="symbol"&gt;:width&lt;/span&gt; &lt;span class="punct"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="number"&gt;200&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt;
    &lt;span class="symbol"&gt;:height&lt;/span&gt; &lt;span class="punct"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="number"&gt;120&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt;
    &lt;span class="symbol"&gt;:xpos&lt;/span&gt; &lt;span class="punct"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="number"&gt;240&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt;
    &lt;span class="symbol"&gt;:ypos&lt;/span&gt; &lt;span class="punct"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="number"&gt;340&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt;
    &lt;span class="symbol"&gt;:colour&lt;/span&gt; &lt;span class="punct"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;black&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt;
  &lt;span class="punct"&gt;}&lt;/span&gt;

  &lt;span class="comment"&gt;# Get base image&lt;/span&gt;
  &lt;span class="ident"&gt;image&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="constant"&gt;Magick&lt;/span&gt;&lt;span class="punct"&gt;::&lt;/span&gt;&lt;span class="constant"&gt;ImageList&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;new&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt; &lt;span class="constant"&gt;File&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;join&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;&lt;span class="expr"&gt;#{RAILS_ROOT}&lt;/span&gt;/public/images&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;,&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;gift_box.jpg&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt; &lt;span class="punct"&gt;)&lt;/span&gt; &lt;span class="punct"&gt;)&lt;/span&gt;

  &lt;span class="comment"&gt;# Set up text&lt;/span&gt;
  &lt;span class="ident"&gt;text&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="constant"&gt;Magick&lt;/span&gt;&lt;span class="punct"&gt;::&lt;/span&gt;&lt;span class="constant"&gt;Draw&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;new&lt;/span&gt;
  &lt;span class="ident"&gt;text&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;font_family&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;times&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt;
  &lt;span class="ident"&gt;text&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;pointsize&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="number"&gt;15&lt;/span&gt;
  &lt;span class="ident"&gt;text&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;font_style&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="constant"&gt;Magick&lt;/span&gt;&lt;span class="punct"&gt;::&lt;/span&gt;&lt;span class="constant"&gt;ItalicStyle&lt;/span&gt;

  &lt;span class="comment"&gt;# Add text to image&lt;/span&gt;
  &lt;span class="ident"&gt;text&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;annotate&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;
    &lt;span class="ident"&gt;image&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt;
    &lt;span class="ident"&gt;text_params&lt;/span&gt;&lt;span class="punct"&gt;[&lt;/span&gt;&lt;span class="symbol"&gt;:width&lt;/span&gt;&lt;span class="punct"&gt;],&lt;/span&gt;
    &lt;span class="ident"&gt;text_params&lt;/span&gt;&lt;span class="punct"&gt;[&lt;/span&gt;&lt;span class="symbol"&gt;:height&lt;/span&gt;&lt;span class="punct"&gt;],&lt;/span&gt;
    &lt;span class="ident"&gt;text_params&lt;/span&gt;&lt;span class="punct"&gt;[&lt;/span&gt;&lt;span class="symbol"&gt;:xpos&lt;/span&gt;&lt;span class="punct"&gt;],&lt;/span&gt;
    &lt;span class="ident"&gt;text_params&lt;/span&gt;&lt;span class="punct"&gt;[&lt;/span&gt;&lt;span class="symbol"&gt;:ypos&lt;/span&gt;&lt;span class="punct"&gt;],&lt;/span&gt;
    &lt;span class="ident"&gt;params&lt;/span&gt;&lt;span class="punct"&gt;[&lt;/span&gt;&lt;span class="symbol"&gt;:message&lt;/span&gt;&lt;span class="punct"&gt;]&lt;/span&gt; &lt;span class="punct"&gt;)&lt;/span&gt; &lt;span class="punct"&gt;{&lt;/span&gt;
    &lt;span class="constant"&gt;self&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;fill&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="ident"&gt;text_params&lt;/span&gt;&lt;span class="punct"&gt;[&lt;/span&gt;&lt;span class="symbol"&gt;:colour&lt;/span&gt;&lt;span class="punct"&gt;]&lt;/span&gt;
  &lt;span class="punct"&gt;}&lt;/span&gt;
  &lt;span class="comment"&gt;# send the image data back&lt;/span&gt;
  &lt;span class="ident"&gt;send_data&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt; &lt;span class="ident"&gt;image&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;to_blob&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="symbol"&gt;:type&lt;/span&gt; &lt;span class="punct"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;image/jpeg&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt; &lt;span class="punct"&gt;)&lt;/span&gt;
&lt;span class="keyword"&gt;end&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The important part of this is the last line that sends the image back as a binary blob with an appropriate content type (adjust for your image format).&lt;/p&gt;

&lt;p&gt;In the template I have:&lt;/p&gt;

&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_default "&gt;&amp;lt;%= link_to_function &amp;quot;Gift Preview&amp;quot;,
  &amp;quot;$('gift_image').src='#{url_for( :action =&amp;gt; 'gift_preview' )}?message=' + $F('order_message')&amp;quot; %&amp;gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&amp;#8220;order_message&amp;#8221; is a text area, and $F is a very handy prototype function that grabs it&amp;#8217;s current contents, and &amp;#8220;gift_image&amp;#8221; is an image tag for displaying the custom image.&lt;/p&gt;

&lt;p&gt;Clicking on this link sets the image source to the gift_preview action, passing the current message, then the controller returns the new custom image, never writing it to disk.&lt;/p&gt;

&lt;p&gt;The code can do with some tidying, but for now, this is working for me (and it&amp;#8217;s a prototype, so :P).&lt;/p&gt;

&lt;p&gt;Enjoy! And for more RMagick detail, head &lt;a href="http://rmagick.rubyforge.org"&gt;here&lt;/a&gt;.&lt;/p&gt;</description>
      <pubDate>Wed, 05 Sep 2007 20:38:00 -0500</pubDate>
      <guid isPermaLink="false">urn:uuid:deb1fa78-4d2b-4786-b612-85710e71ced9</guid>
      <author>Chris</author>
      <link>http://www.drinkingbird.net/blog/articles/2007/09/05/disk-free-custom-images-on-rails</link>
      <category>Ruby on Rails</category>
    </item>
  </channel>
</rss>
