{"id":77,"date":"2018-06-16T03:38:03","date_gmt":"2018-06-16T03:38:03","guid":{"rendered":"https:\/\/embers.nicejacket.cc\/blog\/?p=77"},"modified":"2018-06-16T03:57:07","modified_gmt":"2018-06-16T03:57:07","slug":"transparent-layers-for-openseadragon-with-libvips","status":"publish","type":"post","link":"https:\/\/embers.nicejacket.cc\/blog\/2018\/06\/16\/transparent-layers-for-openseadragon-with-libvips\/","title":{"rendered":"Transparent Layers for OpenSeadragon with libvips"},"content":{"rendered":"<p>One major issue in making the <a href=\"http:\/\/embers.nicejacket.cc\/known-eilarun.html\">map<\/a> of the Embers was creating transparent layers. I wanted my map to have borders reminiscent of <a href=\"https:\/\/en.wikipedia.org\/wiki\/John_Speed\">John Speed<\/a>&#8216;s wonderful maps, but the process of <a href=\"http:\/\/openseadragon.github.io\/\">OpenSeadragon<\/a>-ing with transparent pngs can be tricky.<\/p>\n<p><!--more--><\/p>\n<figure id=\"attachment_78\" aria-describedby=\"caption-attachment-78\" style=\"width: 300px\" class=\"wp-caption aligncenter\"><a href=\"http:\/\/embers.nicejacket.cc\/images\/John_Speed_Wales.jpg\"><img loading=\"lazy\" decoding=\"async\" class=\"size-medium wp-image-78\" src=\"https:\/\/embers.nicejacket.cc\/blog\/wp-content\/uploads\/2018\/06\/John_Speed_Wales-300x230.jpg\" alt=\"John Speed map of Wales\" width=\"300\" height=\"230\" \/><\/a><figcaption id=\"caption-attachment-78\" class=\"wp-caption-text\">Map of Wales, John Speed (<a href=\"https:\/\/en.wikipedia.org\/wiki\/John_Speed\">Wikipedia<\/a>)<\/figcaption><\/figure>\n<p>Look at the map above. The borders are essentially at 50% opacity. You don&#8217;t lose detail beneath them and I feel they blend well into the map, especially for my mood setting-first approach.<\/p>\n<p>At the time of writing, there&#8217;s a bug in OpenSeadragon which causes a slight overlap apparent in layers made from transparent images, even when overlay=0 in your dzi file. Thankfully <a href=\"https:\/\/github.com\/openseadragon\/openseadragon\/pull\/1470\">this bug has been fixed<\/a> in the master branch, but it isn&#8217;t released quite yet.<\/p>\n<figure id=\"attachment_79\" aria-describedby=\"caption-attachment-79\" style=\"width: 300px\" class=\"wp-caption aligncenter\"><img loading=\"lazy\" decoding=\"async\" class=\"size-medium wp-image-79\" src=\"https:\/\/embers.nicejacket.cc\/blog\/wp-content\/uploads\/2018\/06\/transparent-overlap-mockup-300x300.jpg\" alt=\"transparent layer issue\" width=\"300\" height=\"300\" srcset=\"https:\/\/embers.nicejacket.cc\/blog\/wp-content\/uploads\/2018\/06\/transparent-overlap-mockup-300x300.jpg 300w, https:\/\/embers.nicejacket.cc\/blog\/wp-content\/uploads\/2018\/06\/transparent-overlap-mockup-150x150.jpg 150w, https:\/\/embers.nicejacket.cc\/blog\/wp-content\/uploads\/2018\/06\/transparent-overlap-mockup.jpg 400w\" sizes=\"auto, (max-width: 300px) 85vw, 300px\" \/><figcaption id=\"caption-attachment-79\" class=\"wp-caption-text\">This is a mockup, but essentially what you&#8217;d see if one of your dzi layers was based off a transparent image.<\/figcaption><\/figure>\n<p>Regardless, I believe best practice when you need transparent layers is to make your shapes\/images at 100% opacity with transparent backgrounds, and manage opacity in your OpenSeadragon tileSource settings:<\/p>\n<figure id=\"attachment_83\" aria-describedby=\"caption-attachment-83\" style=\"width: 300px\" class=\"wp-caption aligncenter\"><img loading=\"lazy\" decoding=\"async\" class=\"size-medium wp-image-83\" src=\"https:\/\/embers.nicejacket.cc\/blog\/wp-content\/uploads\/2018\/06\/transparent-better-method-300x300.jpg\" alt=\"better transparent layer method\" width=\"300\" height=\"300\" srcset=\"https:\/\/embers.nicejacket.cc\/blog\/wp-content\/uploads\/2018\/06\/transparent-better-method-300x300.jpg 300w, https:\/\/embers.nicejacket.cc\/blog\/wp-content\/uploads\/2018\/06\/transparent-better-method-150x150.jpg 150w, https:\/\/embers.nicejacket.cc\/blog\/wp-content\/uploads\/2018\/06\/transparent-better-method.jpg 400w\" sizes=\"auto, (max-width: 300px) 85vw, 300px\" \/><figcaption id=\"caption-attachment-83\" class=\"wp-caption-text\">Solid images + transparent background = happy worldbuilder.<\/figcaption><\/figure>\n<p>So, how to do that.<\/p>\n<h5>Borders with libvips: Labor of Love, Emphasis on Labor.<\/h5>\n<p>In my <a href=\"https:\/\/embers.nicejacket.cc\/blog\/2018\/06\/14\/making-large-maps-with-openseadragon\/\">previous post<\/a>, I showed an easy way to compose large images from smaller tiles using ImageMagick, but here the mogrify process will convert transparency to white. <a href=\"http:\/\/www.imagemagick.org\/script\/command-line-options.php#transparent\">You can reverse this<\/a>, but you&#8217;re left with pixel residue. There are <a href=\"https:\/\/stackoverflow.com\/questions\/9155377\/set-transparent-background-using-imagemagick-and-commandline-prompt\">ways to work around that<\/a>, but if I wanted fuzzy borders, I would have drawn them that way.<\/p>\n<p>libvips is the superior tool here. On my todo list is writing a script to automate this process in libvips, but at the time I was dumb and just wanted to finish my map. The process below is for those who might have trouble scripting this process but still want a map. More time for you to learn about brilliant worldbuilding minutia like <a href=\"https:\/\/www.youtube.com\/watch?v=y3Kb_ik5f-I\">albedo<\/a>.<\/p>\n<p>In your Illustrator\/Photoshop\/GIMP file, hide all non-border layers. Unlike my <a href=\"https:\/\/embers.nicejacket.cc\/blog\/2018\/06\/14\/making-large-maps-with-openseadragon\/\">previous post<\/a>, we can&#8217;t use ImageMagick, so you can&#8217;t svg &gt; png. You have to save your border tile artboards as png manually. I found naming them <span class=\"st\">cartesianally (see below) helps keeping your mind straight, and I&#8217;ll use this methodology below.<\/span><\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-medium wp-image-90\" src=\"https:\/\/embers.nicejacket.cc\/blog\/wp-content\/uploads\/2018\/06\/transparency-example-3-3-300x300.png\" alt=\"cartesian map tile example\" width=\"300\" height=\"300\" srcset=\"https:\/\/embers.nicejacket.cc\/blog\/wp-content\/uploads\/2018\/06\/transparency-example-3-3-300x300.png 300w, https:\/\/embers.nicejacket.cc\/blog\/wp-content\/uploads\/2018\/06\/transparency-example-3-3-150x150.png 150w, https:\/\/embers.nicejacket.cc\/blog\/wp-content\/uploads\/2018\/06\/transparency-example-3-3.png 400w\" sizes=\"auto, (max-width: 300px) 85vw, 300px\" \/><\/p>\n<p>Documentation on merge is <a href=\"https:\/\/jcupitt.github.io\/libvips\/API\/current\/libvips-mosaicing.html#vips-merge\">here<\/a>. In terminal, navigate to where vips.exe lives, and run the following:<\/p>\n<pre>$ vips merge c:\\1-2.png c:\\1-1.png c:\\row1output1.png horizontal 3000 0<\/pre>\n<p>The order might seem counterintuitive; vips is saying, &#8220;give me the image you want to add (1-2.png), and then the <em>source<\/em> you want me to add it to (1-1.png)&#8221;. Merge horizontally, and the position you want the &#8220;added&#8221; image offset. In my case, tiles are 3000&#215;3000, so I want 1-2.png offset 3000 pixels from (0,0) of my <em>source<\/em> 1-1.png.<\/p>\n<p>Thus, to get the 1-3.png added:<\/p>\n<pre>$ vips merge c:\\1-3.png c:\\row1output1.png c:\\row1output2.png horizontal 6000 0<\/pre>\n<p>Once you&#8217;ve reached the end of your row, I recommend starting a new row from scratch with the above method. That way if you enter the wrong coordinates you only have to fix or redo that row.<\/p>\n<p>Once you have all your complete row images, merge them vertically:<\/p>\n<pre>$ vips merge c:\\row2.png c:\\row1.png c:\\outputrows12.png vertical 0 3000<\/pre>\n<p>Repeat as necessary.<\/p>\n<p>You can save some time by skipping empty spaces, as merge will fill this in. My map&#8217;s artboards aren&#8217;t a perfect grid:<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-medium wp-image-64\" src=\"https:\/\/embers.nicejacket.cc\/blog\/wp-content\/uploads\/2018\/06\/artboard-grid-300x297.jpg\" alt=\"artboard grid\" width=\"300\" height=\"297\" srcset=\"https:\/\/embers.nicejacket.cc\/blog\/wp-content\/uploads\/2018\/06\/artboard-grid-300x297.jpg 300w, https:\/\/embers.nicejacket.cc\/blog\/wp-content\/uploads\/2018\/06\/artboard-grid-150x150.jpg 150w, https:\/\/embers.nicejacket.cc\/blog\/wp-content\/uploads\/2018\/06\/artboard-grid.jpg 400w\" sizes=\"auto, (max-width: 300px) 85vw, 300px\" \/><\/p>\n<p>So when I got to my third row, I offset the third row 6000 down and 3000 over:<\/p>\n<pre>$ vips merge c:\\row3.png c:\\rows1and2.png c:\\rows123.png vertical 3000 6000<\/pre>\n<p>Once you have your transparent border layer, run dzsave <a href=\"https:\/\/embers.nicejacket.cc\/blog\/2018\/06\/14\/making-large-maps-with-openseadragon\/\">normally<\/a> (using &#8211;suffix .png to maintain file format), and you&#8217;ll have a transparent dzi.<\/p>\n<p>If you now want the opaque elements of your transparency layer to appear somewhat transparent in OpenSeadragon, include the opacity option in tileSources:<\/p>\n<pre>...\r\ntileSources: [\r\n{\r\n  tileSource: 'dzi\/basemap.dzi',\r\n  opacity: 1\r\n},\r\n{\r\n  tileSource: 'dzi\/borders.dzi',\r\n  opacity: 0.5\r\n}\r\n...<\/pre>\n<p>Lastly, as this process is laborious and less than ideal, if your transparency layer is smaller than your base maps, you can position it with x and y, though if the layer doesn&#8217;t match the width of the base dzi, you&#8217;ll need to position it using width and height or it will stretch to match. You can read more about this <a href=\"https:\/\/openseadragon.github.io\/examples\/ui-overlays\/\">here<\/a>. For example:<\/p>\n<pre>...\r\n{\r\n  tileSource: 'dzi\/borders.dzi.',\r\n  opacity: 0.5,\r\n  x: 0.33,\r\n  y: 0.75,\r\n  width: 0.2,\r\n  height: 0.25\r\n}\r\n...<\/pre>\n","protected":false},"excerpt":{"rendered":"<p>One major issue in making the map of the Embers was creating transparent layers. I wanted my map to have borders reminiscent of John Speed&#8216;s wonderful maps, but the process of OpenSeadragon-ing with transparent pngs can be tricky.<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[],"class_list":["post-77","post","type-post","status-publish","format-standard","hentry","category-uncategorized"],"_links":{"self":[{"href":"https:\/\/embers.nicejacket.cc\/blog\/wp-json\/wp\/v2\/posts\/77","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/embers.nicejacket.cc\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/embers.nicejacket.cc\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/embers.nicejacket.cc\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/embers.nicejacket.cc\/blog\/wp-json\/wp\/v2\/comments?post=77"}],"version-history":[{"count":6,"href":"https:\/\/embers.nicejacket.cc\/blog\/wp-json\/wp\/v2\/posts\/77\/revisions"}],"predecessor-version":[{"id":92,"href":"https:\/\/embers.nicejacket.cc\/blog\/wp-json\/wp\/v2\/posts\/77\/revisions\/92"}],"wp:attachment":[{"href":"https:\/\/embers.nicejacket.cc\/blog\/wp-json\/wp\/v2\/media?parent=77"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/embers.nicejacket.cc\/blog\/wp-json\/wp\/v2\/categories?post=77"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/embers.nicejacket.cc\/blog\/wp-json\/wp\/v2\/tags?post=77"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}