<p><div><div><div><div data-show-faces="false" data-height="21" data-width="100" data-layout="button_count" data-send="true" data-href="https://www.r-bloggers.com/magick-1-6-clipping-geometries-fonts-fuzz-and-a-bit-of-history/"></div></div><div></div></div><div></div></div>
<div>
(This article was first published on <strong><a href="https://ropensci.org/technotes/2017/12/05/magick-16/"> rOpenSci - open tools for open science</a></strong>, and kindly contributed to <a rel="nofollow" href="https://www.r-bloggers.com/">R-bloggers)</a> </div>
<p> <img alt="cover image" src="https://i0.wp.com/i.imgur.com/tTFk7ig.jpg?w=456&ssl=1" data-recalc-dims="1"></p>
<p>This week <a rel="nofollow" href="https://cran.r-project.org/web/packages/magick/vignettes/intro.html" target="_blank">magick</a> 1.6 appeared on CRAN. This release is a big all-round maintenance update with lots of tweaks and improvements across the package.</p>
<p>The <a rel="nofollow" href="https://cran.r-project.org/web/packages/magick/NEWS" target="_blank">NEWS</a> file gives an overview of changes in this version. In this post we highlight some changes.</p>
<pre><code>library(magick)
stopifnot(packageVersion('magick') >= 1.6)
</code></pre>
<p>If you are new to magick, check out the <a rel="nofollow" href="https://cran.r-project.org/web/packages/magick/vignettes/intro.html" target="_blank">vignette</a> for a quick introduction.</p>
<h2>Perfect Graphics Rendering</h2>
<p>I have fixed a few small rendering imperfections in the graphics device. The native magick graphics device <code>image_graph()</code> now renders identical or better quality images as the R-base bitmap devices <code>png</code>, <code>jpeg</code>, etc.</p>
<p>One issue was that sometimes magick graphics would show a 1px black border around the image. It turned out this is caused by rounding of clipping coordinates.</p>
<p>When R calculates clipping area it often ends up at non-whole values. It is then up to the graphics device to decide what to do with the pixel that is partially clipped. Let’s show clipping in action:</p>
<pre><code>testplot &lt;- function(title = &quot;&quot;){
  plot(1, main = title)
  abline(0, 1, col = &quot;blue&quot;, lwd = 2, lty = &quot;solid&quot;)
  abline(0.1, 1, col = &quot;red&quot;, lwd = 3, lty = &quot;dotted&quot;)
  abline(0.2, 1, col = &quot;green&quot;, lwd = 4, lty = &quot;twodash&quot;)
  abline(0.3, 1, col = &quot;black&quot;, lwd = 5, lty = &quot;dotdash&quot;)
  abline(0.4, 1, col = &quot;purple&quot;, lwd = 6, lty = &quot;dashed&quot;)
  abline(0.5, 1, col = &quot;yellow&quot;, lwd = 7, lty = &quot;longdash&quot;)
  abline(-0.1, 1, col = &quot;blue&quot;, lwd = 10, lend = &quot;round&quot;, lty = &quot;dashed&quot;)
  abline(-0.2, 1, col = &quot;blue&quot;, lwd = 10, lend = &quot;butt&quot;, lty = &quot;dashed&quot;)
  abline(-0.3, 1, col = &quot;blue&quot;, lwd = 10, lend = &quot;square&quot;, lty = &quot;dashed&quot;)
}
</code></pre>
<p>Now we run it with and without clipping:</p>
<pre><code>img2 &lt;- magick::image_graph(clip = FALSE)
testplot(&quot;Without clipping&quot;)
dev.off()
</code></pre>
<p><img alt="noclip.png" src="https://i2.wp.com/i.imgur.com/TtpjlLq.png?w=456&ssl=1" data-recalc-dims="1"></p>
<pre><code>img1 &lt;- magick::image_graph(clip = TRUE)
testplot(&quot;With clipping&quot;)
dev.off()
</code></pre>
<p><img alt="clip.png" src="https://i2.wp.com/i.imgur.com/JbWMElL.png?w=456&ssl=1" data-recalc-dims="1"></p>
<p>As we can see the latter image is now perfectly clipped. The colored lines are truncated exactly at the pixel where the axis starts. This is not always the case in base R <img alt="😉" src="https://s.w.org/images/core/emoji/2.3/72x72/1f609.png" class="wp-smiley"></p>
<h2>Font Families</h2>
<p>In magick there are two ways to render text on an image. You can either open the image or graphic in the magick graphics device and then use base R <code>text()</code> function to print text. Alternatively there is <code>image_annotate()</code> which is a simpler version to print some text on an image.</p>
<p>Wherever text rendering is involved, two major headache arise: encoding and fonts. The latter is tricky because different operating systems have different fonts with different names. In addition a font can be specified as a name, or family name, or alias.</p>
<p>Below is a simple test that I use to quickly inspect if fonts are working on different systems:</p>
<pre><code>img &lt;- image_graph(width = 800, height = 500, pointsize = 20, res = 96)
graphics::plot.new()
graphics::par(mar = c(0,0,3,0))
graphics::plot.window(xlim = c(0, 20), ylim = c(-.5, 8))
title(expression(Gamma %prop% sum(x[alpha], i==1, n) * sqrt(mu)), expression(hat(x)))

# Standard families as supported by other devices
text(0.95, 7, &quot;abcdefg  - Helvetica&quot;, pos = 4, family = &quot;helvetica&quot;)
text(0.95, 6, &quot;abcdefg  - Sans (Arial)&quot;, pos = 4, family = &quot;sans&quot;)
text(0.95, 5, &quot;abcdefg - Serif (Times)&quot;, pos = 4, family = &quot;serif&quot;)
text(0.95, 4, &quot;abcdefg - Monospace (Courier New)&quot;, pos = 4, family = &quot;mono&quot;)
text(0.95, 3, &quot;abcdefg - Symbol Face&quot;, pos = 4, font = 5)
text(0.95, 2, &quot;abcdefg  - Comic Sans&quot;, pos = 4, family = &quot;Comic Sans&quot;)
text(0.95, 1, &quot;abcdefg - Georgia Serif&quot;, pos = 4, family = &quot;Georgia&quot;)
text(0.95, 0, &quot;abcdefg - Courier&quot;, pos = 4, family = &quot;Courier&quot;)
dev.off()
img &lt;- image_border(img, 'red', geometry = '2x2')
</code></pre>
<p><img alt="families" src="https://i1.wp.com/i.imgur.com/tzIktip.png?w=456&ssl=1" data-recalc-dims="1"></p>
<p>R requires that a graphics device supports at least 4 font types: <code>serif</code>, <code>sans</code>, <code>mono</code> and <code>symbol</code>. The latter is a special 8bit font with some Greek letters and other characters needed for rendering math. This set of fonts corresponds to the original <strong>13 base fonts</strong> from the <a rel="nofollow" href="https://en.wikipedia.org/wiki/PostScript_fonts#Core_Font_Set" target="_blank">1984 postscript standard</a>:</p>
<ul>
<li>4x Courier (Regular, Oblique, Bold, Bold Oblique)</li>
<li>4x Helvetica (Regular, Oblique, Bold, Bold Oblique)</li>
<li>4x Times (Roman, Italic, Bold, Bold Italic)</li>
<li>Symbol</li>
</ul>
<p>Below a photo of the 1985 <a rel="nofollow" href="https://en.wikipedia.org/wiki/LaserWriter" target="_blank">Apple Laser Writer</a> which was <a rel="nofollow" href="https://en.wikipedia.org/wiki/PostScript_fonts#History" target="_blank">the first laser printer</a> to use the PostScript language and support all these fonts! Not much later PostScript graphics devices were adopted by R’s predecessor <a rel="nofollow" href="https://en.wikipedia.org/wiki/S_(programming_language)#.22New_S.22" target="_blank">“The New S”</a> (The New S Language, 1988).</p>
<p><img alt="printers" src="https://i0.wp.com/theappletimeline.com/images/color1000.jpg?w=456" data-recalc-dims="1"></p>
<h2>Geometry Helpers</h2>
<p>Another major improvement in this release is the introduction of helper functions for geometry and option strings. Many functions in magick require a special geometry syntax to specify a size, area, or point. For example to resize an image you need to specify a size:</p>
<pre><code>image_resize(img, &quot;50%&quot;)
image_resize(img, &quot;300x300&quot;)
image_resize(img, &quot;300x300!&quot;)
</code></pre>
<p>Or to crop you need to specify an area which consists of a size and offset:</p>
<pre><code>image_crop(img, &quot;300x300+100+100&quot;)
</code></pre>
<p>We added a few handy <code>?geometry</code> helper functions to generate proper geometry syntax</p>
<p><img alt="geometries" src="https://i1.wp.com/i.imgur.com/2jivLxi.png?w=456&ssl=1" data-recalc-dims="1"></p>
<h2>Magick Options</h2>
<p>A lot of the power in ImageMagick is contained in the hundreds of built-in filters, colorspaces, compose operators, disposal types, convolution kernels, noise types and what not. These are specified simply as a string in the function.</p>
<p>For example in our previous <a rel="nofollow" href="https://ropensci.org/technotes/2017/11/02/image-convolve/" target="_blank">post about Image Convolution</a> we discussed a few kernel types:</p>
<pre><code># Gaussian Kernel
img %>% image_convolve('Gaussian:0x5', scaling = '60,40%')

# Sobel Kernel
img %>% image_convolve('Sobel')

# Difference of Gaussians
img %>% image_convolve('DoG:0,0,2')
</code></pre>
<p>Supported values for each option are described in the online ImageMagick documentation. We now have added functions in the magick package that list all values for each option. This should make it a easier to see what is supported and harness the full power of built-in ImageMagick algorithms.</p>
<p><img alt="options" src="https://i2.wp.com/i.imgur.com/cid6JqU.png?w=456&ssl=1" data-recalc-dims="1"></p>
<p>So we can now easily list e.g. supported kernel types:</p>
<pre><code>> kernel_types()
 [1] &quot;Undefined&quot;     &quot;Unity&quot;         &quot;Gaussian&quot;      &quot;DoG&quot;          
 [5] &quot;LoG&quot;           &quot;Blur&quot;          &quot;Comet&quot;         &quot;Binomial&quot;     
 [9] &quot;Laplacian&quot;     &quot;Sobel&quot;         &quot;FreiChen&quot;      &quot;Roberts&quot;      
[13] &quot;Prewitt&quot;       &quot;Compass&quot;       &quot;Kirsch&quot;        &quot;Diamond&quot;      
[17] &quot;Square&quot;        &quot;Rectangle&quot;     &quot;Disk&quot;          &quot;Octagon&quot;      
[21] &quot;Plus&quot;          &quot;Cross&quot;         &quot;Ring&quot;          &quot;Peaks&quot;        
[25] &quot;Edges&quot;         &quot;Corners&quot;       &quot;Diagonals&quot;     &quot;ThinDiagonals&quot;
[29] &quot;LineEnds&quot;      &quot;LineJunctions&quot; &quot;Ridges&quot;        &quot;ConvexHull&quot;   
[33] &quot;ThinSe&quot;        &quot;Skeleton&quot;      &quot;Chebyshev&quot;     &quot;Manhattan&quot;    
[37] &quot;Octagonal&quot;     &quot;Euclidean&quot;     &quot;User Defined&quot; 
</code></pre>
<p>That’s a lot of kernels.</p>
<h2>Fuzz Scaling</h2>
<p>Finally one more (breaking) change: several functions in magick use a <code>fuzz</code> parameter to specify the max distance between two colors to be considered similar.</p>
<p>For example the flood fill algorithm (the paint-bucket button in ms-paint) changes the color of a given starting pixel, and then recursively all adjacent pixels that have the same color. However sometimes neighboring pixels are not precisely the same color, but nearly the same. The <code>fuzz</code> parameter allows the fill to continue when pixels are not the same but similar color.</p>
<pre><code># Paint the shirt orange
frink &lt;- image_read(&quot;https://jeroen.github.io/images/frink.png&quot;) %>%
  image_fill(&quot;orange&quot;, point = &quot;+100+200&quot;, fuzz = 25)
</code></pre>
<p><img alt="frink" src="https://i1.wp.com/i.imgur.com/VwlqYWy.png?w=456&ssl=1" data-recalc-dims="1"></p>
<p>What has changed in this version is that <code>fuzz</code> parameter been rescaled to a percentage. Hence you should always provide a value between 0 and 100. Previously it was the absolute distance between colors, but this depends on the type and color depth of the image at hand, which was very confusing.</p>
	<p>
<div>
<div>To <strong>leave a comment</strong> for the author, please follow the link and comment on their blog: <strong><a href="https://ropensci.org/technotes/2017/12/05/magick-16/"> rOpenSci - open tools for open science</a></strong>.</div>
<hr>
<a rel="nofollow" href="https://www.r-bloggers.com/">R-bloggers.com</a> offers <strong><a rel="nofollow" href="https://feedburner.google.com/fb/a/mailverify?uri=RBloggers">daily e-mail updates</a></strong> about <a rel="nofollow" href="https://www.r-project.org/" title="The R Project for Statistical Computing">R</a> news and <a rel="nofollow" href="https://www.r-bloggers.com/search/tutorial" title="R tutorials">tutorials</a> on topics such as: <a rel="nofollow" href="https://www.r-bloggers.com/search/data%20science" title="Data science">Data science</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/Big%20Data" title="Big Data">Big Data, <a rel="nofollow" href="https://www.r-users.com/" title="R jobs">R jobs</a>, visualization (<a rel="nofollow" href="https://www.r-bloggers.com/search/ggplot2" title="ggplot and ggplot2 tutorials">ggplot2</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/boxplot" title="Boxplots using lattice and ggplot2 tutorials">Boxplots</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/map" title="Maps and gis">maps</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/animation" title="Animation in R">animation</a>), programming (<a rel="nofollow" href="https://www.r-bloggers.com/search/RStudio" title="RStudio IDE for R">RStudio</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/sweave" title="Sweave and literate programming">Sweave</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/LaTeX" title="LaTeX in R">LaTeX</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/SQL" title="SQL and databases">SQL</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/eclipse" title="Eclipse IDE for R">Eclipse</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/git" title="git and github, Version Control System">git</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/hadoop" title="Large data in R using Hadoop">hadoop</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/Web+Scraping" title="Web Scraping of google, facebook, yahoo, twitter and more using R">Web Scraping</a>) statistics (<a rel="nofollow" href="https://www.r-bloggers.com/search/regression" title="Regressions and ANOVA analysis tutorials">regression</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/PCA" title="principal component analysis tutorial">PCA</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/time+series" title="Time series">time series</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/trading" title="finance trading">trading</a>) and more...
<img width="1" alt="" src="http://feeds.feedburner.com/~r/RBloggers/~4/S57Vcwq2YQg" height="1"></a></div>