{"id":225,"date":"2005-11-24T02:52:33","date_gmt":"2005-11-24T07:52:33","guid":{"rendered":"http:\/\/esr.ibiblio.org\/?p=225"},"modified":"2005-11-25T05:15:16","modified_gmt":"2005-11-25T10:15:16","slug":"my-first-gimp-hack","status":"publish","type":"post","link":"http:\/\/esr.ibiblio.org\/?p=225","title":{"rendered":"LISP &#8212; The Language That Will Not Die"},"content":{"rendered":"<p>I&#8217;ve spent large parts of the last week editing maps for a game<br \/>\nsystem I&#8217;m working on.  I&#8217;ve been using the <a href='http:\/\/www.gimp.org'>GIMP<\/a> graphics editor, and I&#8217;m pretty<br \/>\nimpressed with it.  I haven&#8217;t found anything I can&#8217;t easily make it do<br \/>\n&mdash; except, oddly enough, draw straight lines between defined<br \/>\nendpoints.  (I suspect there&#8217;s actually a way to do this using the<br \/>\npath facility.)<\/p>\n<p>I have a requirement to prepare about six different variants of a<br \/>\nbase map, using the same topographic map but with different<br \/>\narrangements of national borders.  I&#8217;ve handled this by creating a<br \/>\nmulti-layered XCF file with the topo map as the background and the<br \/>\ndifferent borders as optional overlays.<\/p>\n<p>OK, so I save the variants to flat PNGs by hand whenever I change the<br \/>\nimage, but that&#8217;s a pain.  What I wanted was a way to put in my makefile<br \/>\ninstructions that say, for each variant map, that it depends on the XCF<br \/>\nand the way to make it is to composite a particular selected subset of layers<br \/>\nby running GIMP in batch mode.<\/p>\n<p>Fortunately, GIMP has an embedded Scheme interpreter that&#8217;s good<br \/>\nfor exactly this kind of thing.  Looking at some Python-Fu code by<br \/>\nCarol Spears taught me enough about the API to get started; the fact<br \/>\nthat I&#8217;m an old LISP head got me the rest of the way.<\/p>\n<p>Here it is.<\/p>\n<pre>\r\n;; Batch-mode select and save of a layer set as a PNG.\r\n;; Has to be copied into  ~\/.gimp-2.2\/scripts to work\r\n;;\r\n;; Note: This assumes that gimp-drawable-get-name returns a list with\r\n;; the actual string name as its car.  This is what gimp-2.2 does, but\r\n;; not what the documentation says it should do!\r\n\r\n(define (layer-set-saver infile select outfile)\r\n   (let* ((image (car (gimp-file-load RUN-NONINTERACTIVE infile infile)))\r\n\t  (layers (cadr (gimp-image-get-layers image)))\r\n\t  (ind 0))\r\n     (while (< ind (length layers))\r\n\t    (let* ((layer (aref layers ind))\r\n\t\t   (layer-name (car (gimp-drawable-get-name layer))))\r\n\t      (gimp-drawable-set-visible layer (if (member layer-name select) 1 0)))\r\n\t    (set! ind (+ ind 1)))\r\n     (file-png-save-defaults RUN-NONINTERACTIVE \r\n\t\t     image \r\n\t\t     (car (gimp-image-flatten image)) \r\n\t\t     outfile outfile)\r\n     )\r\n   (gimp-quit 0)\r\n   )\r\n<\/pre>\n<p>Here's one of my makefile productions. The second arg is a list of layer names.<\/p>\n<pre>\r\nbasic.png: basic.xcf\r\n\tgimp -i -b '(layer-set-saver \"basic.xcf\" (quote (\"topographic\" \"skinny-borders\" \"grey-switzerland\")) \"basic.png\")'\r\n<\/pre>\n<p>Apologies for the long line.<\/p>\n<p>LISP truly is The Language That Will Not Die. And that&#8217;s a good thing.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>I&#8217;ve spent large parts of the last week editing maps for a game system I&#8217;m working on. I&#8217;ve been using the GIMP graphics editor, and I&#8217;m pretty impressed with it. I haven&#8217;t found anything I can&#8217;t easily make it do &mdash; except, oddly enough, draw straight lines between defined endpoints. (I suspect there&#8217;s actually a&hellip; <a class=\"more-link\" href=\"http:\/\/esr.ibiblio.org\/?p=225\">Continue reading <span class=\"screen-reader-text\">LISP &#8212; The Language That Will Not Die<\/span><\/a><\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[13],"tags":[],"class_list":["post-225","post","type-post","status-publish","format-standard","hentry","category-software","entry"],"_links":{"self":[{"href":"http:\/\/esr.ibiblio.org\/index.php?rest_route=\/wp\/v2\/posts\/225","targetHints":{"allow":["GET"]}}],"collection":[{"href":"http:\/\/esr.ibiblio.org\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/esr.ibiblio.org\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/esr.ibiblio.org\/index.php?rest_route=\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"http:\/\/esr.ibiblio.org\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=225"}],"version-history":[{"count":0,"href":"http:\/\/esr.ibiblio.org\/index.php?rest_route=\/wp\/v2\/posts\/225\/revisions"}],"wp:attachment":[{"href":"http:\/\/esr.ibiblio.org\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=225"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/esr.ibiblio.org\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=225"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/esr.ibiblio.org\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=225"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}