Creating bitmap file with Magick

Han Oostdijk

2019/04/28

This post describes my struggle to create a bitmap file with the Magick package. My assumption is that I should be able to specify each bit of a bitmap file. After some experimenting I can now create a bitmap file with contents more or less (but not exactly) what I want. The following code is used:

make_plot <- function (window_width, line_width, start=1, res=72) {
	m2 = window_width / 2 ; m3 = window_width
	fig <- magick::image_graph(
		width = m3,	height = m3,	res = res)
	parold = par(mar = c(0, 0, 0, 0))
	plot.new()
	plot.window(c(1, m3), c(1, m3))
	rect(start,	m3,	m3,	start,
		border = 'black',	lty = 1, lwd = line_width)
	points( c(1, m2, m3),	c(m3, m2, 1),
		lty = 1, pch = 15, cex = line_width, col = 'red')
	d <- dev.off()
	par(parold)
	fig
}
window_width = 72
line_width = 1
fig72 = make_plot(window_width, line_width)

So I create a graphical Magick device with 72*72 pixels. I also specify a res (resolution) of 72 but I am not sure if that has any impact.
I create a plot window corresponding to these values (a pixel per unit?) and set the margins to zero to avoid an'Error in plot.new() : figure margins too large' message.
I draw a rectangle in the outer pixels of the plot and draw three point in the left-upper, right-bottom and in the middle of the plot.
Then I close the device.

If we view the characteristics of fig72 and view the figure on the screen everything looks fine

magick::image_info(fig72)
#> # A tibble: 1 x 7
#>   format width height colorspace matte filesize density
#>   <chr>  <int>  <int> <chr>      <lgl>    <int> <chr>  
#> 1 PNG       72     72 sRGB       TRUE         0 72x72
fig72

plot of chunk unnamed-chunk-2

but if we write the figure to a bitmap file

magick::image_write(fig72,path='fig72.bmp',format = 'bmp')

and view the file in an enlarged format with the Microsoft tools Paint and Snipping Tool we see the following plot of chunk unnamed-chunk-4

Case with 400 pixels instead of 72

Maybe with a greater number of pixels this will work fine? Let us try 400 pixels:

window_width = 400
line_width = 1
fig400 = make_plot(window_width, line_width)

Again writing the plot to a file

magick::image_write(fig400,path='fig400.bmp',format = 'bmp')

and viewing the file in an enlarged format we again see that the points and lines take more than one pixel:

plot of chunk unnamed-chunk-7

Case with 400 pixels instead of 72 and line_width 0.01

And if we try a smaller line_width as e.g. 0.01

window_width = 400
line_width = 0.01
fig400_2 = make_plot(window_width, line_width)

Again writing the plot to a file

magick::image_write(fig400_2,path='fig400_2.bmp',format = 'bmp')

and viewing the file in an enlarged format:

plot of chunk unnamed-chunk-10

Case with 400 pixels instead of 72 and line_width 0.01 and start 0

and with start = 0

window_width = 400
line_width = 0.01
fig400_3 = make_plot(window_width, line_width, start=0)

Again writing the plot to a file

magick::image_write(fig400_3,path='fig400_3.bmp',format = 'bmp')

and viewing the file in an enlarged format:

plot of chunk unnamed-chunk-13

Case with 400 pixels instead of 72 and line_width 0.01 and res 400

and with res = 400

window_width = 400
line_width = 0.01
fig400_4 = make_plot(window_width, line_width, res=400)
magick::image_info(fig400_4)
#> # A tibble: 1 x 7
#>   format width height colorspace matte filesize density
#>   <chr>  <int>  <int> <chr>      <lgl>    <int> <chr>  
#> 1 PNG      400    400 sRGB       TRUE         0 72x72

Again writing the plot to a file

magick::image_write(fig400_4,path='fig400_4.bmp',format = 'bmp')

and viewing the file in an enlarged format:

plot of chunk unnamed-chunk-16

Testje

Het volgende plaatje toont dat rect de coordinaten van de plot aanneemt. Blijkbaar doet plot.window ook iets met de coordinaten anders dan de pixel waarden overnemen.

png(file="../../static/post/2019-04-28-creating-bitmap-file-with-magick_files/testje1.png", bg="transparent")
plot(1:10)
rect(1, 5, 3, 7, col="white")
dev.off()
#> png 
#>   2

plot of chunk unnamed-chunk-17

Session Info

#> R version 3.6.0 (2019-04-26)
#> Platform: x86_64-w64-mingw32/x64 (64-bit)
#> Running under: Windows 10 x64 (build 18362)
#> 
#> Matrix products: default
#> 
#> locale:
#> [1] LC_COLLATE=English_United States.1252 
#> [2] LC_CTYPE=English_United States.1252   
#> [3] LC_MONETARY=English_United States.1252
#> [4] LC_NUMERIC=C                          
#> [5] LC_TIME=English_United States.1252    
#> 
#> attached base packages:
#> [1] stats     graphics  grDevices utils     datasets  methods   base     
#> 
#> other attached packages:
#>  [1] HOQCutil_0.1.10 jsonlite_1.6    glue_1.3.1      purrr_0.3.2    
#>  [5] xml2_1.2.2      ggspatial_1.0.3 ggplot2_3.2.1   sf_0.7-7       
#>  [9] dplyr_0.8.3     stringr_1.4.0   osmdata_0.1.1  
#> 
#> loaded via a namespace (and not attached):
#>  [1] tidyselect_0.2.5   xfun_0.8           lattice_0.20-38   
#>  [4] vctrs_0.2.0        colorspace_1.4-1   htmltools_0.3.6   
#>  [7] utf8_1.1.4         rlang_0.4.0        e1071_1.7-0       
#> [10] pillar_1.4.2       withr_2.1.2        DBI_1.0.0         
#> [13] sp_1.3-1           readxl_1.3.1       lifecycle_0.1.0   
#> [16] plyr_1.8.4         cellranger_1.1.0   munsell_0.5.0     
#> [19] blogdown_0.15      gtable_0.3.0       rvest_0.3.4       
#> [22] evaluate_0.14      knitr_1.24         prettymapr_0.2.2  
#> [25] curl_4.0           class_7.3-15       fansi_0.4.0       
#> [28] highr_0.8          Rcpp_1.0.2         KernSmooth_2.23-15
#> [31] backports_1.1.4    scales_1.0.0       classInt_0.3-3    
#> [34] magick_2.2         captioner_2.2.3    fs_1.3.1          
#> [37] png_0.1-7          digest_0.6.20      stringi_1.4.3     
#> [40] rosm_0.2.5         grid_3.6.0         cli_1.1.0         
#> [43] rgdal_1.4-4        tools_3.6.0        magrittr_1.5      
#> [46] lazyeval_0.2.1     tibble_2.1.3       zeallot_0.1.0     
#> [49] tidyr_1.0.0        crayon_1.3.4       pkgconfig_2.0.2   
#> [52] lubridate_1.7.4    assertthat_0.2.1   rmarkdown_1.15    
#> [55] httr_1.4.1         R6_2.4.0           units_0.6-2       
#> [58] compiler_3.6.0