Nick Sieger: ImageVoodoo 0.1 Releaseddo what you lovetag:blog.nicksieger.com,2005:TypoTypo2008-04-09T13:10:43+00:00Miami Web Designurn:uuid:c1da65d0-148c-4504-887a-01196dec0fac2008-04-09T13:10:43+00:002008-04-09T13:10:43+00:00Comment on ImageVoodoo 0.1 Released by Miami Web Design<p>Thanks a lot, I have been searching for an alternative to ImageScience for quite some time (don’t ask :P) and this is exactly what I wanted :)</p>Christian Seilerurn:uuid:4a9825c3-35ba-4029-8f40-361050c20a5a2008-04-01T09:38:03+00:002008-04-01T09:38:03+00:00Comment on ImageVoodoo 0.1 Released by Christian Seiler<p>Thanks so much for this. I always avoided installing those C-based image processing libraries on my development machine (Windows), because it’s such a pain in the ass. Now ImageVoodoo simply works. gem install, and that’s it. This is where Java really shines.</p>Matthew Kanwisherurn:uuid:996dcafd-d676-410c-8268-2663c3a036732008-03-28T17:09:53+00:002008-03-28T17:09:53+00:00Comment on ImageVoodoo 0.1 Released by Matthew Kanwisher<p>Heh I bumped into your git project looking for a way to use attachment_fu in jruby. Good to hear you have a 0.1 version ;)</p>Nick Siegerurn:uuid:3b535c66-18f9-4ae5-9e37-79757d8b7a322008-03-27T21:39:23+00:002008-03-27T21:39:23+00:00ImageVoodoo 0.1 Released<h2>Introducing ImageVoodoo</h2>
<p>I just pushed out the first release of ImageVoodoo, a nifty little image manipulation library conceived as a quick hack by <a href="http://www.bloglines.com/blog/ThomasEEnebo" title="Tom's Ruminations - Powered By Bloglines">Tom</a>. It’s a play-on-words of <a href="http://seattlerb.rubyforge.org/ImageScience.html" title="ImageScience">ImageScience</a>, of course, the quick, lightweight imaging library for Ruby. To get it,</p>
<pre><code>jruby -S gem install image_voodoo
</code></pre>
<p>What’s cool about ImageVoodoo (other than the name) is that we were able to make it API-compatible with ImageScience. In fact, ImageVoodoo’s <code>image_science.rb</code> simply looks like this:</p>
<div class="typocode"><pre><code class="typocode_ruby "><span class="ident">require</span> <span class="punct">'</span><span class="string">image_voodoo</span><span class="punct">'</span>
<span class="comment"># HA HA...let the pin-pricking begin</span>
<span class="constant">ImageScience</span> <span class="punct">=</span> <span class="constant">ImageVoodoo</span></code></pre></div>
<p>So, you can use it pretty much anywhere you might use ImageScience, and it should <em>just work</em>. At work, we’re using it with <a href="http://github.com/technoweenie/attachment_fu/tree/master">attachment_fu</a>, and it works great. ImageVoodoo even steals and uses ImageScience’s unit tests (which all run successfully, too). Speed-wise, it’s about twice as slow as ImageScience running on MatzRuby, but still plenty fast enough for most cases.</p>
<p>But we wouldn’t be having fun unless we embraced and extended a little bit, right? So I added a couple of extra features you might find useful.</p>
<h2>Preview</h2>
<p>Since ImageVoodoo is just leveraging the Java Platform’s imaging libraries, image rendering can be easily tied into a simple preview frame. This code:</p>
<div class="typocode"><pre><code class="typocode_ruby "><span class="constant">ImageVoodoo</span><span class="punct">.</span><span class="ident">with_image</span><span class="punct">("</span><span class="string">samples/checkerboard.jpg</span><span class="punct">")</span> <span class="keyword">do</span> <span class="punct">|</span><span class="ident">img</span><span class="punct">|</span>
<span class="ident">img</span><span class="punct">.</span><span class="ident">preview</span>
<span class="keyword">end</span></code></pre></div>
<p>Will pop up a little frame like this:</p>
<p><img src="/files/image_voodoo_preview.png" alt="preview" title="preview"/></p>
<p>The code that displays the preview frame is nice and compact, and shows off how nicely you can write clean swing GUI code using JRuby’s java integration features.</p>
<div class="typocode"><pre><code class="typocode_ruby "><span class="keyword">class </span><span class="class">ImageVoodoo</span>
<span class="keyword">class </span><span class="class">JImagePanel</span> <span class="punct"><</span> <span class="ident">javax</span><span class="punct">.</span><span class="ident">swing</span><span class="punct">.</span><span class="ident">JPanel</span>
<span class="keyword">def </span><span class="method">initialize</span><span class="punct">(</span><span class="ident">image</span><span class="punct">,</span> <span class="ident">x</span><span class="punct">,</span> <span class="ident">y</span><span class="punct">)</span>
<span class="keyword">super</span><span class="punct">()</span>
<span class="attribute">@image</span><span class="punct">,</span> <span class="attribute">@x</span><span class="punct">,</span> <span class="attribute">@y</span> <span class="punct">=</span> <span class="ident">image</span><span class="punct">,</span> <span class="ident">x</span><span class="punct">,</span> <span class="ident">y</span>
<span class="keyword">end</span>
<span class="keyword">def </span><span class="method">paintComponent</span><span class="punct">(</span><span class="ident">graphics</span><span class="punct">)</span>
<span class="ident">graphics</span><span class="punct">.</span><span class="ident">drawImage</span><span class="punct">(</span><span class="attribute">@image</span><span class="punct">,</span> <span class="attribute">@x</span><span class="punct">,</span> <span class="attribute">@y</span><span class="punct">,</span> <span class="constant">nil</span><span class="punct">)</span>
<span class="keyword">end</span>
<span class="keyword">end</span>
<span class="keyword">class </span><span class="class">WindowClosed</span>
<span class="keyword">def </span><span class="method">initialize</span><span class="punct">(</span><span class="ident">block</span> <span class="punct">=</span> <span class="constant">nil</span><span class="punct">)</span>
<span class="attribute">@block</span> <span class="punct">=</span> <span class="ident">block</span> <span class="punct">||</span> <span class="ident">proc</span> <span class="punct">{</span> <span class="ident">java</span><span class="punct">.</span><span class="ident">lang</span><span class="punct">.</span><span class="ident">System</span><span class="punct">.</span><span class="ident">exit</span><span class="punct">(</span><span class="number">0</span><span class="punct">)</span> <span class="punct">}</span>
<span class="keyword">end</span>
<span class="keyword">def </span><span class="method">method_missing</span><span class="punct">(</span><span class="ident">meth</span><span class="punct">,*</span><span class="ident">args</span><span class="punct">);</span> <span class="keyword">end</span>
<span class="keyword">def </span><span class="method">windowClosing</span><span class="punct">(</span><span class="ident">event</span><span class="punct">);</span> <span class="attribute">@block</span><span class="punct">.</span><span class="ident">call</span><span class="punct">;</span> <span class="keyword">end</span>
<span class="keyword">end</span>
<span class="keyword">def </span><span class="method">preview</span><span class="punct">(&</span><span class="ident">block</span><span class="punct">)</span>
<span class="ident">frame</span> <span class="punct">=</span> <span class="ident">javax</span><span class="punct">.</span><span class="ident">swing</span><span class="punct">.</span><span class="ident">JFrame</span><span class="punct">.</span><span class="ident">new</span><span class="punct">("</span><span class="string">Preview</span><span class="punct">")</span>
<span class="ident">frame</span><span class="punct">.</span><span class="ident">add_window_listener</span> <span class="constant">WindowClosed</span><span class="punct">.</span><span class="ident">new</span><span class="punct">(</span><span class="ident">block</span><span class="punct">)</span>
<span class="ident">frame</span><span class="punct">.</span><span class="ident">set_bounds</span> <span class="number">0</span><span class="punct">,</span> <span class="number">0</span><span class="punct">,</span> <span class="ident">width</span> <span class="punct">+</span> <span class="number">20</span><span class="punct">,</span> <span class="ident">height</span> <span class="punct">+</span> <span class="number">40</span>
<span class="ident">frame</span><span class="punct">.</span><span class="ident">add</span> <span class="constant">JImagePanel</span><span class="punct">.</span><span class="ident">new</span><span class="punct">(</span><span class="attribute">@src</span><span class="punct">,</span> <span class="number">10</span><span class="punct">,</span> <span class="number">10</span><span class="punct">)</span>
<span class="ident">frame</span><span class="punct">.</span><span class="ident">visible</span> <span class="punct">=</span> <span class="constant">true</span>
<span class="keyword">end</span>
<span class="keyword">end</span></code></pre></div>
<h2>Command-line</h2>
<p>As I was <a href="http://twitter.com/nicksieger/statuses/778203542">fixing a bug in ImageVoodoo’s file saving</a> I whipped up a little command-line utility to aid debugging. It allows you to string along several image manipulation actions on a single command-line. For example,</p>
<pre><code>jruby -S image_voodoo --push --resize 50x50 --preview --save t1.jpg \
--pop --resize 40x40 --preview --save t2.jpg \
--pop --resize 30x30 --preview --save t3.jpg image.jpg
</code></pre>
<p>This will resize <code>image.jpg</code> into three smaller images, <code>t[1-3].jpg</code>, but will pop up a preview frame at each step of the way. Simply close the preview frame to continue to the next action, or quit out of the application to abort.</p>
<h2>Summary</h2>
<p>And so, another functional area, image manipulation, becomes as easy on JRuby as it is on MatzRuby. Now that fancy social networking application you’ve been working on should have one less reason to be able to run unmodified on JRuby!</p>