{"id":294,"date":"2007-03-08T18:53:11","date_gmt":"2007-03-08T22:53:11","guid":{"rendered":"http:\/\/auroralux.net\/blog\/2007\/03\/08\/scaling-padding-cocoa-and-bindings\/"},"modified":"2007-03-13T13:10:48","modified_gmt":"2007-03-13T17:10:48","slug":"scaling-padding-cocoa-and-bindings","status":"publish","type":"post","link":"https:\/\/fhmiv.net\/blog\/2007\/03\/08\/scaling-padding-cocoa-and-bindings\/","title":{"rendered":"Scaling, padding, Cocoa, and Bindings"},"content":{"rendered":"<p>I <a href=\"\/blog\/2007\/02\/04\/no-photoshop-batch-workflows-no-problem\/\">mentioned<\/a> a while ago needing to implement batched image processing for my mom&#8217;s website that would allow her to easily generate a bunch of images of a certain size, padded with a certain color, for her website.<\/p>\n<p>Besides the problems I mentioned in that post, I soon discovered that wrapping things up for Automator isn&#8217;t as easy as it ought to be, because Cocoa automator components only support a couple of data types, none of them the ones I needed to handily read in image files, pass them through Quartz Composer compositions, and  then write the results back to the file system. I even had a helpful post from an Apple employee on one of the mailing lists, but in the end decided it would be simpler and I&#8217;d get better performance out of the result by just writing a custom application. <\/p>\n<p>I pulled my copy of &#8220;Cocoa Programming for Mac OS X&#8221;, a book by Aaron Hillegas that I recommend for anyone wanting to learn general Cocoa programming. Then I dove right in to Interface Builder to design the interface and help me flesh out the functional spec. It was pretty easy to do that part, and I ended up with a short list of things I needed to do:<\/p>\n<ul>\n<li>Bind user interface elements to user defaults, including non-string things like NSColor<\/li>\n<li>Verify desired image sizes are valid<\/li>\n<li>Choose directories for input files and output files with a file browser<\/li>\n<li>Verify the input files are valid image files that can be read by Quartz<\/li>\n<li>Load the image files<\/li>\n<li>Scale them to a certain size, preserving their aspect ratio<\/li>\n<li>Pad them to be square<\/li>\n<li>Save them back to disk<\/li>\n<li>Display a modal sheet with a progress panel, also using bindings<\/li>\n<\/ul>\n<p>I learned a lot doing this project: I experimented with several of the graphics APIs, including Core Graphics, Core Image, and NSImage; I used bindings for something other than a spiffy but meaninglessly simple IB demo; and I handled the user interface nicities often not handled by example code. Did I mention this app is also fast? I&#8217;ve also accomplished the same task with Graphic Converter that I&#8217;m solving here with my own app, and mine is much faster at generating thumbnails.<\/p>\n<p>If you&#8217;re interested, you can download the <a href=\"http:\/\/auroralux.net\/downloads\/ScaleAndPadImages-100.zip\">pre-built application<\/a> or visit my subversion repository for the <a href=\"\/repos\/ScaleAndPadImages\/\">source code<\/a>, which I&#8217;ve put under a BSD license.<\/p>\n<p>I&#8217;ve really enjoyed the graphics programming, and will probably pick up <a href=\"http:\/\/www.amazon.com\/o\/ASIN\/0321336631\/ref=s9_asin_image_1\/103-5241398-6408647\">Quartz 2D Graphics for Mac OS X(R) Developers<\/a> and <a href=\"http:\/\/www.amazon.com\/Programming-Quartz-Graphics-Kaufmann-Computer\/dp\/0123694736\/ref=pd_sim_b_1\/103-5241398-6408647\">Programming with Quartz<\/a>. <\/p>\n","protected":false},"excerpt":{"rendered":"<p>I mentioned a while ago needing to implement batched image processing for my mom&#8217;s website that would allow her to easily generate a bunch of images of a certain size, padded with a certain color, for her website. Besides the &hellip; <a href=\"https:\/\/fhmiv.net\/blog\/2007\/03\/08\/scaling-padding-cocoa-and-bindings\/\">Continue reading <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[],"tags":[11],"_links":{"self":[{"href":"https:\/\/fhmiv.net\/blog\/wp-json\/wp\/v2\/posts\/294"}],"collection":[{"href":"https:\/\/fhmiv.net\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/fhmiv.net\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/fhmiv.net\/blog\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/fhmiv.net\/blog\/wp-json\/wp\/v2\/comments?post=294"}],"version-history":[{"count":0,"href":"https:\/\/fhmiv.net\/blog\/wp-json\/wp\/v2\/posts\/294\/revisions"}],"wp:attachment":[{"href":"https:\/\/fhmiv.net\/blog\/wp-json\/wp\/v2\/media?parent=294"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/fhmiv.net\/blog\/wp-json\/wp\/v2\/categories?post=294"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/fhmiv.net\/blog\/wp-json\/wp\/v2\/tags?post=294"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}