jima's Journal http://use.perl.org/~jima/journal/ jima's use Perl Journal en-us use Perl; is Copyright 1998-2006, Chris Nandor. Stories, comments, journals, and other submissions posted on use Perl; are Copyright their respective owners. 2012-01-25T02:39:18+00:00 pudge pudge@perl.org Technology hourly 1 1970-01-01T00:00+00:00 jima's Journal http://use.perl.org/images/topics/useperl.gif http://use.perl.org/~jima/journal/ Removing EXIF data from JPEG images using PerlMagick http://use.perl.org/~jima/journal/30908?from=rss <p> One issue that came up when we were testing the original version of this software was that metadata was being kept in images that were created by the system. Small "slices" of the original images uploaded by players were passed along to subsequent players, for them to use in their own creations, and any existing EXIF thumbnail images in the original image file were accidentally also being passed along. </p><p> After some futzing around with ImageMagick <a href="http://www.imagemagick.org/">http://www.imagemagick.org/</a> I eventually settled on using the jpegtran tools that come installed on just about every flavor of Linux. But I never gave up on a possible PerlMagick solution, and now I've finally stumbled upon the correct combination of incantations that allow you to create an image with no EXIF data. Since the documentation for ImageMagick is quite sparse, I thought I would record my discovery here. </p><p> I suspected that copying an image from one Image::Magick object to another would probably not copy the EXIF data, and it took me a while to stumble on the Composite() method which in fact works exactly as I suspected it would. Here's my code:</p><blockquote><div><p> <tt>use Image::Magick;<br> <br>my($i) = Image::Magick-&gt;new();<br>my($j) = Image::Magick-&gt;new();<br> <br>$i-&gt;Read('image-with-exif.jpg');<br>$j-&gt;Set('size', $i-&gt;Get('width').'x'.$i-&gt;Get('height'));<br>$j-&gt;Read('NULL:white');<br> <br>$resp = $j-&gt;Composite( image =&gt; $i, compose =&gt; Copy );&nbsp; # you can check $resp for errors<br> <br>$j-&gt;Write('image-without-exif.jpg');</tt></p></div> </blockquote><p>A couple of things that might not be obvious to the ImageMagick novice: </p><ul> <li> The <code>$j-&gt;Read()</code> function call is needed to create an image in the <code>$j</code> variable. Apparently you need to have some image in your destination variable to copy stuff onto. </li><li> The <code>NULL:white</code> string is what's known in ImageMagick as a pseudo-image format. Other formats, useful for creating gradients, steganographic images, plasma backgrounds, etc. can be found in this page in the ImageMagick documentation: <a href="http://www.imagemagick.org/script/formats.php#pseudo">http://www.imagemagick.org/script/formats.php#pseudo</a> </li></ul><p> Some investigation with the resulting images using the Image::ExifTool module indicates that there is no resulting EXIF data in the new JPEG image. Mission accomplished! </p> jima 2006-09-06T15:58:38+00:00 journal Notes on posting via Perl to Blogger http://use.perl.org/~jima/journal/30881?from=rss <p> One of the features that the new code will have is the ability to automatically create a new posting for a specified blog, in order to publicly display the finished collaborative art. Some blogs, such as Movable Type, have pretty straightforward API documentation: <a href="http://www.movabletype.org/mt-static/docs/mtmanual_programmatic.html">http://www.movabletype.org/mt-static/docs/mtmanual_programmatic.html</a> Others, like Blogger, take a bit of trial and error to get working. Here's the code that I just got working for my module that posts to an existing Blogger weblog (you'll have to put in the user name, password and numeric blog ID string into the code yourself, of course):</p><blockquote><div><p> <tt>my($ua) = LWP::UserAgent-&gt;new;<br> <br>my($entry) = &lt;&lt;FOO;<br>&lt;?xml version="1.0" encoding="UTF-8" standalone="yes"?&gt;<br>&lt;entry xmlns="http://purl.org/atom/ns#"&gt;<br>&nbsp; &lt;title mode="escaped" type="text/plain"&gt;atom test&lt;/title&gt;<br>&nbsp; &lt;issued&gt;2006-09-04T00:00:00Z&lt;/issued&gt;<br>&nbsp; &lt;generator url="http://anexquisitecorpse.net"&gt;An Exquisite Corpse backend code&lt;/generator&gt;<br>&nbsp; &lt;content type="application/xhtml+xml"&gt;<br>&nbsp; &nbsp; &lt;div xmlns="http://www.w3.org/1999/xhtml"&gt;Testing the Atom API&lt;/div&gt;<br>&nbsp; &lt;/content&gt;<br>&lt;/entry&gt;<br>&nbsp; &nbsp; FOO<br> <br>my($h) = HTTP::Headers-&gt;new;<br>$h-&gt;header('Content-type', 'application/xml');<br>$h-&gt;header('Host', 'www.blogger.com');<br>$h-&gt;authorization_basic('username','password');&nbsp; # &lt;&lt; replace with your own details, obv<br> <br>my($req) = HTTP::Request-&gt;new(<br> <br>&nbsp; &nbsp; &nbsp; &nbsp; POST =&gt; 'https://www.blogger.com/atom/12345678',&nbsp; # &lt;&lt; replace with your own blogger ID, found in the header of your blogspot homepage<br>&nbsp; &nbsp; &nbsp; &nbsp; $h,<br>&nbsp; &nbsp; &nbsp; &nbsp; $entry<br>);<br> <br>my($resp) = $ua-&gt;request($req);<br> <br>print $resp-&gt;as_string;</tt></p></div> </blockquote><p> You should get back a big meaty chunk of XML that will include, among other things, the formatted entry returned from the blog and a link tag that contains the URL for the new entry. Here's what that looks like:</p><blockquote><div><p> <tt>&lt;?xml version="1.0" encoding="utf-8" standalone="yes"?&gt;<br>&lt;entry xmlns="http://purl.org/atom/ns#"&gt;<br>&nbsp; &nbsp; &lt;link href="https://www.blogger.com/atom/12345678/1234567890" rel="service.edit" title="atom test" type="application/atom+xml"/&gt;<br>&nbsp; &nbsp; &lt;author&gt;<br>&nbsp; &nbsp; &nbsp; &nbsp; &lt;name&gt;your name here&lt;/name&gt;<br>&nbsp; &nbsp; &lt;/author&gt;<br>&nbsp; &nbsp; &lt;issued&gt;2006-09-03T17:00:00-07:00&lt;/issued&gt;<br>&nbsp; &nbsp; &lt;modified&gt;2006-09-04T16:12:56Z&lt;/modified&gt;<br>&nbsp; &nbsp; &lt;created&gt;2006-09-04T16:12:56Z&lt;/created&gt;<br>&nbsp; &nbsp; &lt;link href="http://whatever.blogspot.com/whatever" rel="alternate" title="atom test" type="text/html"/&gt;<br>&nbsp; &nbsp; &lt;id&gt;tag:blogger.com,1999:blog-12345678.post-1234567890&lt;/id&gt;<br>&nbsp; &nbsp; &lt;title mode="escaped" type="text/html"&gt;atom test&lt;/title&gt;<br>&nbsp; &nbsp; &lt;content type="application/xhtml+xml" xml:base="http://whatever.blogspot.com" xml:space="preserve"&gt;<br>&nbsp; &nbsp; &nbsp; &nbsp; &lt;div xmlns="http://www.w3.org/1999/xhtml"&gt;<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;div xmlns="http://www.w3.org/1999/xhtml"&gt;Testing the Atom API&lt;/div&gt;<br>&nbsp; &nbsp; &nbsp; &nbsp; &lt;/div&gt;<br>&nbsp; &nbsp; &lt;/content&gt;<br>&nbsp; &nbsp; &lt;draft xmlns="http://purl.org/atom-blog/ns#"&gt;false&lt;/draft&gt;<br>&lt;/entry&gt;</tt></p></div> </blockquote><p>Still to be figured out: what standard-issue XML and HTTP modules I can use to parse these requests and responses, and how much of the XML I might need to hard-code into the modules. </p><p> And while we're on the subject of Blogger, can I just say that it's a big pain having to code for a standard that's currently in production (the Atom API), while at the same time being told to plan for an upgraded publishing spec (the GData API: <a href="http://code.google.com/apis/gdata/blogger.html">http://code.google.com/apis/gdata/blogger.html</a>) that I can't even test yet because it's still in beta. Well, maybe someday I'll get to test it, but for now I'll just stick with the Atom API, because that's what I've got to work with right now. </p> jima 2006-09-04T17:08:58+00:00 journal Notes on CAMS http://use.perl.org/~jima/journal/30825?from=rss <p>Hello. I've been working on a large open source Perl project for a few months now, and I've been wanting a place to post my thoughts and code ideas, just to get them out of my head and onto paper.</p><p>The project is growing out of my work on the site An Exquisite Corpse <a href="http://www.anexquisitecorpse.net/">http://www.anexquisitecorpse.net/</a>, which is a Website devoted to playing the Exquisite Corpse game online (if you don't know what an Exquisite Corpse is, look it up in Wikipedia: <a href="http://en.wikipedia.org/wiki/Exquisite_corpse">http://en.wikipedia.org/wiki/Exquisite_corpse</a>). The current system was cobbled together as quickly as possible, which of course means it's not that great or easy to use. I'm working on the next version of the code and trying to make it a lot more general-purpose (i.e., to provide the capability of implementing other online collaborative art games, not just Exquisite Corpse) and more user-friendly, with the ultimate goal of making it open source and available for other people to use and extend. </p><p> The new system, which I am currently referring to as the Collaborative Art Management System, or CAMS, will be a user-management system with a series of Perl modules that implement a series of collaboartive art "games". The first one I'm implementing is Exquisite Corpse, but ultimately I hope to have a number of games written. Other possible games include Photoshop Tennis <a href="http://www.coudal.com/tennis.php">http://www.coudal.com/tennis.php</a>, Corpse Tennis <a href="http://www.deadhorse.org/corpsetennis/">http://www.deadhorse.org/corpsetennis/</a>, and a text version of Exquisite Corpse. </p><p> I'm still in the development stage right now, and hope to have some code up and running by sometime next year. (It's not a high priority project; I do have a real job, as well as a fairly active social life.) A tentative goal is to attend either the 2007 or 2008 SXSW Interactive festival <a href="http://www.sxsw.com/">http://www.sxsw.com/</a> and promote the site, or the new project, or both. From the reports I've been getting about the festival it sounds like a good place to spread the gospel of the Corpse. I've also thought of attending Perl conferences to discuss the project, but right now I think we want to focus more on getting artists interested in the project, to improve the content that we're getting on the site. </p><p> So this site will be infrequently updated, as I work on the project and want to share my findings. Catch you later.... </p> jima 2006-08-31T14:47:27+00:00 journal