<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>image processing | Adrian Gadient-Brügger</title>
    <link>/tag/image-processing/</link>
      <atom:link href="/tag/image-processing/index.xml" rel="self" type="application/rss+xml" />
    <description>image processing</description>
    <generator>Wowchemy (https://wowchemy.com)</generator><language>en-us</language><lastBuildDate>Tue, 01 Nov 2022 00:00:00 +0000</lastBuildDate>
    <image>
      <url>/images/icon_huaf89efe5379de1a05284391d3347ab6a_20288_512x512_fill_lanczos_center_2.png</url>
      <title>image processing</title>
      <link>/tag/image-processing/</link>
    </image>
    
    <item>
      <title>Using R to create variations of images for research projects</title>
      <link>/post/create-images/</link>
      <pubDate>Tue, 01 Nov 2022 00:00:00 +0000</pubDate>
      <guid>/post/create-images/</guid>
      <description>


&lt;p&gt;This blogpost briefly summarizes how &lt;code&gt;R&lt;/code&gt; and the package &lt;code&gt;magick&lt;/code&gt; can be used to programmatically create images. This automated approach &lt;strong&gt;saves time&lt;/strong&gt;, makes the process &lt;strong&gt;transparent&lt;/strong&gt;, easy to &lt;strong&gt;replicate&lt;/strong&gt;, and &lt;strong&gt;reduces errors&lt;/strong&gt; from manual copy-and-pasting. The code is explained below and also available on &lt;a href=&#34;https://github.com/abruegger/pics_in_R&#34;&gt;github&lt;/a&gt;.&lt;/p&gt;
&lt;div id=&#34;background&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Background&lt;/h2&gt;
&lt;p&gt;In &lt;a href=&#34;https://www.consumer.imu.unibe.ch/&#34;&gt;our research group&lt;/a&gt; we recently prepared an experiment that is interested in how different carbon labels may affect consumers. More specifically, we wanted to compare the following three labels to a control condition (without carbon label):&lt;/p&gt;
&lt;ol style=&#34;list-style-type: upper-alpha&#34;&gt;
&lt;li&gt;&lt;p&gt;The &lt;em&gt;absolute&lt;/em&gt; label simply shows the amount of CO2 that is caused by producing a food item&lt;br /&gt;
&lt;img src=&#34;absolute_Butter.png&#34; alt=&#34;Label with amount of CO2&#34; /&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The &lt;em&gt;traffic&lt;/em&gt; label uses five colours to indicate the climate impact of the product relative to comparable products (similar to the &lt;a href=&#34;https://en.wikipedia.org/wiki/Nutri-Score&#34;&gt;nutri-score label&lt;/a&gt; and the &lt;a href=&#34;https://en.wikipedia.org/wiki/European_Union_energy_label&#34;&gt;energy label&lt;/a&gt;)&lt;br /&gt;
&lt;img src=&#34;traffic_Butter.png&#34; alt=&#34;Traffic label&#34; /&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The &lt;em&gt;combined&lt;/em&gt; label uses both the numeric information from A) and the colours from B)&lt;br /&gt;
&lt;img src=&#34;combined_Butter.png&#34; alt=&#34;Combined label&#34; /&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;For the experiment, we wanted to use images that include the name of the product, its origin, and the label (or no label in the control condition). The initial approach to create the images was to manually assemble the relevant information in PowerPoint and then save each image. However, with approximately 150 images to create, this turned out to be a &lt;strong&gt;very long and error-prone process&lt;/strong&gt;. Things such as changing the design (e.g., background colour, font type / size) took forever and there was a considerable risk of adding wrong information to the images.&lt;/p&gt;
&lt;p&gt;To automate the process and make it easier to quickly apply changes to all images, I turned to &lt;code&gt;R&lt;/code&gt; and the image processing package &lt;code&gt;magick&lt;/code&gt;. A really nice side effect is that the process of creating the images is now more &lt;strong&gt;transparent&lt;/strong&gt;. Moreover, the code can be relatively easy be adapted for other projects.&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;preparation&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Preparation&lt;/h2&gt;
&lt;p&gt;Before doing anything in &lt;code&gt;R&lt;/code&gt;, it is a good idea to prepare all the information so &lt;code&gt;R&lt;/code&gt; can access and process it. More specifically, I prepared a table in which each line represents a product and the columns contain relevant information such as the name of the product, where it is produced, the amount of CO2 that is emitted during the production, the name of the image file that shows the product, and the path to the folder that contains the image.&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;building-elements&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Building elements&lt;/h2&gt;
&lt;p&gt;Depending on the experimental condition, the images should consist of 1-3 elements with varying content:&lt;/p&gt;
&lt;ol style=&#34;list-style-type: decimal&#34;&gt;
&lt;li&gt;Header with product name, origin, and product image&lt;/li&gt;
&lt;li&gt;Label (or no label in the control condition)&lt;/li&gt;
&lt;li&gt;Text indicating the carbon emissions of the product (in the conditions “absolute” and “combined”)&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;To combine these elements into a single image with &lt;code&gt;magick&lt;/code&gt;, each element or combination of elements needs to be saved as an image. &lt;code&gt;Magick&lt;/code&gt; can combine such elements in different ways. If the three elements had consistently the same dimensions (height and width), one could simply create a background / base layer with fixed dimensions and then “paste” the elements where they belong with the r function &lt;code&gt;image_composite&lt;/code&gt;. However, the height of the used product images varied and this simple way didn’t work; the three parts cannot be directly put on a base layer (or at least I couldn’t figure out how).&lt;/p&gt;
&lt;p&gt;The alternative is to first create the header. Then the other parts are created (traffic label / label with amount of CO2 / combined label) and put below the header.&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;details-and-code&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Details and code&lt;/h2&gt;
&lt;p&gt;Below you find the code for creating the images. The code, the data, and images are also availabe on my &lt;a href=&#34;https://github.com/abruegger/pics_in_R&#34;&gt;github repository&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Load packages (install if not yet available):&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;if (!require(&amp;quot;pacman&amp;quot;)) install.packages(&amp;quot;pacman&amp;quot;)
pacman::p_load(&amp;quot;tidyverse&amp;quot;,&amp;quot;readxl&amp;quot;, &amp;quot;stringr&amp;quot;,&amp;quot;magick&amp;quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Import and prepare data (incl. adjusting the path to the prodcut images):&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;# import specific sheet from Excel file
df &amp;lt;- readxl::read_excel(&amp;quot;../product_info.xlsx&amp;quot;, sheet = &amp;quot;stimuli_data&amp;quot;)

# indicate path to product images
df$image_path &amp;lt;- stringr::str_c(&amp;quot;../images/originals/products/&amp;quot;,df$image_product)
  
# update path to label templates
df$label_path &amp;lt;- stringr::str_c(&amp;quot;../images/originals/labels/&amp;quot;,df$label,&amp;quot;_V2_1.png&amp;quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Create the header:&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;# create head / basic image consisting of product name and image 
# lapply applies the function defined below for all elements / rows in the column &amp;quot;image_path&amp;quot; (could also be a different column with unique information)
img_lst &amp;lt;- lapply(seq_along(df$image_path), function(i){
  # create white background
  background &amp;lt;- image_blank(width = 770, height = 160, color = &amp;quot;grey25&amp;quot;)
  # get product name
  product_en &amp;lt;- df$product_en[[i]]
  # get image
  product_image &amp;lt;- image_read(df$image_path[[i]]) 
  # add text to background
  base &amp;lt;- background %&amp;gt;% 
    # add product name from variable &amp;quot;product_en&amp;quot;
    image_annotate(paste0(df$product_en[[i]]), size = 82, color = &amp;quot;white&amp;quot;, weight=700, 
                   location = &amp;quot;+6+2&amp;quot;, font= &amp;quot;Helvetica&amp;quot;) %&amp;gt;% 
    # add fix text for place of production 
    image_annotate(&amp;quot;Produced in:&amp;quot;, size = 48, color = &amp;quot;white&amp;quot;, weight=500, 
                   location = &amp;quot;+6+96&amp;quot;, font= &amp;quot;Helvetica&amp;quot;) %&amp;gt;% 
    # add origin from variable &amp;quot;origin_en&amp;quot;
    image_annotate(paste0(df$origin_en[[i]]), size = 48, color = &amp;quot;white&amp;quot;, weight=500, 
                   location = &amp;quot;+300+96&amp;quot;) 
  # create image consisting of base with text + image
  img &amp;lt;- c(base,product_image)
  # explain how to combine these elements
  image_append(image_scale(img, &amp;quot;770&amp;quot;), stack = TRUE) %&amp;gt;% 
    # save image
    image_write(path = paste0(&amp;quot;../images/final/&amp;quot;, &amp;quot;control_&amp;quot;,product_en, &amp;quot;.png&amp;quot;), format = &amp;quot;png&amp;quot;) #, quality = 50) #, compression = 
})&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The result looks like this and is actually also the control condition:
&lt;img src=&#34;control_Butter.png&#34; alt=&#34;Combined label&#34; /&gt;&lt;/p&gt;
&lt;p&gt;The next step is to prepare the foot for the experimental condition “absolute” (single foot with amount of CO2).&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;# very similar logic as above
img_lst &amp;lt;- lapply(seq_along(df$image_path), function(i){
  # get relevant information
  product_en &amp;lt;- df$product_en[[i]]
  image_read(&amp;quot;../images/originals/labels/White_V2.png&amp;quot;)  %&amp;gt;% 
    # print information about CO2 in correct place
    image_annotate(paste0(sprintf(&amp;quot;%.1f&amp;quot;,round(df$co2[[i]], 1))), size = 83, color = &amp;quot;black&amp;quot;, weight=700, 
                   location = &amp;quot;+73+150&amp;quot;,font= &amp;quot;Helvetica&amp;quot;) %&amp;gt;% 
    # add constant information kg/CO2
    image_annotate(&amp;quot; kg\nCO2&amp;quot;, size = 55, color = &amp;quot;black&amp;quot;, weight=700, 
                   location = &amp;quot;+89+230&amp;quot;,font= &amp;quot;Helvetica&amp;quot;) %&amp;gt;% 
    image_background(&amp;quot;grey25&amp;quot;) %&amp;gt;% 
    image_border(&amp;quot;grey25&amp;quot;, &amp;quot;400x0&amp;quot;) %&amp;gt;% # add border so that foot will be similarly large as in traffic version
    image_write(path = paste0(&amp;quot;../images/absolute/&amp;quot;, product_en, &amp;quot;.png&amp;quot;), format = &amp;quot;png&amp;quot;) #, quality = 50) #, compression = 
})

# move text for large numbers, otherwise it doesn&amp;#39;t appear in the correct place (outside the foot)
# overwrite  products with co2 &amp;gt;=10
df_big &amp;lt;- df %&amp;gt;% filter(co2 &amp;gt;=10)
img_lst &amp;lt;- lapply(seq_along(df_big$image_path), function(i){
  product_en &amp;lt;- df_big$product_en[[i]]
  image_read(&amp;quot;../images/originals/labels/White_V2.png&amp;quot;)  %&amp;gt;% 
    image_annotate(paste0(sprintf(&amp;quot;%.1f&amp;quot;,round(df_big$co2[[i]], 1))), size = 83, color = &amp;quot;black&amp;quot;, weight=700, 
                   location = &amp;quot;+40+150&amp;quot;,font= &amp;quot;Helvetica&amp;quot;) %&amp;gt;% 
    image_annotate(&amp;quot; kg\nCO2&amp;quot;, size = 55, color = &amp;quot;black&amp;quot;, weight=700, 
                   location = &amp;quot;+89+230&amp;quot;,font= &amp;quot;Helvetica&amp;quot;) %&amp;gt;% 
    image_background(&amp;quot;grey25&amp;quot;) %&amp;gt;% 
    image_border(&amp;quot;grey25&amp;quot;, &amp;quot;400x0&amp;quot;) %&amp;gt;% # add border so that foot will be similarly large as in traffic version
    image_write(path = paste0(&amp;quot;../images/absolute/&amp;quot;, product_en, &amp;quot;.png&amp;quot;), format = &amp;quot;png&amp;quot;) #, quality = 50) #, compression = 
})&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And then add it to the header.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;# combine image and foot (all absolute images)
img_lst &amp;lt;- lapply(seq_along(df$image_path), function(i){
  product_en &amp;lt;- df$product_en[[i]]
  header &amp;lt;- image_read(path = paste0(&amp;quot;../images/final/control_&amp;quot;, df$product_en[[i]], &amp;quot;.png&amp;quot;)) 
  label  &amp;lt;- image_read(path = paste0(&amp;quot;../images/absolute/&amp;quot;, df$product_en[[i]], &amp;quot;.png&amp;quot;)) 
  img &amp;lt;- c(header,label)
  image_append(image_scale(img,&amp;quot;770&amp;quot;), stack = TRUE) %&amp;gt;% 
    image_write(path = paste0(&amp;quot;../images/final/&amp;quot;, &amp;quot;absolute_&amp;quot;, product_en, &amp;quot;.png&amp;quot;), format = &amp;quot;png&amp;quot;) #, quality = 50) #, compression = 
})&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The result looks like this:
&lt;img src=&#34;absolute_Butter%202.png&#34; alt=&#34;Label with amount of CO2&#34; /&gt;&lt;/p&gt;
&lt;p&gt;Then we create the images for the experimental condition “traffic” (“relative” feet without indication of CO2).&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;img_lst &amp;lt;- lapply(seq_along(df$product_en), function(i){
  product_en &amp;lt;- df$product_en[[i]]
  image_read(df$label_path[[i]]) %&amp;gt;% 
    image_background(&amp;quot;grey25&amp;quot;) %&amp;gt;% 
    image_border(&amp;quot;grey25&amp;quot;, &amp;quot;80x10&amp;quot;) %&amp;gt;% # add border so that image will end up smaller in the final version
    image_crop(geometry=&amp;quot;1200x445&amp;quot;,repage=TRUE) %&amp;gt;% # crop bottom to make picture less high
    image_write(path = paste0(&amp;quot;../images/traffic/&amp;quot;, product_en, &amp;quot;.png&amp;quot;), format = &amp;quot;png&amp;quot;) #, quality = 50) #, compression = 
})

# combine image and foot and save
img_lst &amp;lt;- lapply(seq_along(df$image_path), function(i){
  product_en &amp;lt;- df$product_en[[i]]
  header &amp;lt;- image_read(path = paste0(&amp;quot;../images/final/control_&amp;quot;, df$product_en[[i]], &amp;quot;.png&amp;quot;)) 
  label  &amp;lt;- image_read(path = paste0(&amp;quot;../images/traffic/&amp;quot;, df$product_en[[i]], &amp;quot;.png&amp;quot;)) 
  img &amp;lt;- c(header,label)
  image_append(image_scale(img,&amp;quot;770&amp;quot;), stack = TRUE) %&amp;gt;% 
    image_write(path = paste0(&amp;quot;../images/final/&amp;quot;, &amp;quot;traffic_&amp;quot;, product_en, &amp;quot;.png&amp;quot;), format = &amp;quot;png&amp;quot;) #, quality = 50) #, compression = 
})&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Resulting example image:
&lt;img src=&#34;traffic_Butter%202.png&#34; alt=&#34;Combined label&#34; /&gt;&lt;/p&gt;
&lt;p&gt;And finally the code for the combined version. Note that these images need to be created separately for each level of the label (A, B, C, D, E) to ensure that the text is placed on the correct position (different for each enlarged foot).&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;# do A - Labels
df_A &amp;lt;- df %&amp;gt;% filter(label==&amp;quot;A&amp;quot;)

img_lst &amp;lt;- lapply(seq_along(df_A$label_path), function(i){
  product_en &amp;lt;- df_A$product_en[[i]]
  image_read(df_A$label_path[[i]]) %&amp;gt;% 
    image_annotate(paste0(sprintf(&amp;quot;%.1f&amp;quot;,round(df_A$co2[[i]], 1))), size = 70, color = &amp;quot;black&amp;quot;, weight=700, 
                   location = &amp;quot;+40+120&amp;quot;,font= &amp;quot;Helvetica&amp;quot;) %&amp;gt;% 
    image_annotate(&amp;quot; kg\nCO2&amp;quot;, size = 43, color = &amp;quot;black&amp;quot;, weight=700, 
                   location = &amp;quot;+50+190&amp;quot;,font= &amp;quot;Helvetica&amp;quot;) %&amp;gt;% 
    image_background(&amp;quot;grey25&amp;quot;) %&amp;gt;% 
    image_border(&amp;quot;grey25&amp;quot;, &amp;quot;80x10&amp;quot;) %&amp;gt;% # add border so that image will end up smaller in the final version
    image_crop(geometry=&amp;quot;1200x435&amp;quot;,repage=TRUE) %&amp;gt;% # crop bottom to make picture less high
    image_write(path = paste0(&amp;quot;../images/combined/&amp;quot;, product_en, &amp;quot;.png&amp;quot;), format = &amp;quot;png&amp;quot;) #, quality = 50) #, compression = 
})


# do B - Labels

df_B &amp;lt;- df %&amp;gt;% filter(label==&amp;quot;B&amp;quot;)

img_lst &amp;lt;- lapply(seq_along(df_B$label_path), function(i){
  product_en &amp;lt;- df_B$product_en[[i]]
  image_read(df_B$label_path[[i]])  %&amp;gt;% 
    image_annotate(paste0(sprintf(&amp;quot;%.1f&amp;quot;,round(df_B$co2[[i]], 1))), size = 70, color = &amp;quot;black&amp;quot;, weight=700, 
                   location = &amp;quot;+164+120&amp;quot;,font= &amp;quot;Helvetica&amp;quot;) %&amp;gt;% 
    image_annotate(&amp;quot; kg\nCO2&amp;quot;, size = 43, color = &amp;quot;black&amp;quot;, weight=700, 
                   location = &amp;quot;+174+190&amp;quot;,font= &amp;quot;Helvetica&amp;quot;) %&amp;gt;% 
    image_background(&amp;quot;grey25&amp;quot;) %&amp;gt;% 
    image_border(&amp;quot;grey25&amp;quot;, &amp;quot;80x10&amp;quot;) %&amp;gt;% # add border so that image will end up smaller in the final version
    image_crop(geometry=&amp;quot;1200x435&amp;quot;,repage=TRUE) %&amp;gt;% # crop bottom to make picture less high
    image_write(path = paste0(&amp;quot;../images/combined/&amp;quot;, product_en, &amp;quot;.png&amp;quot;), format = &amp;quot;png&amp;quot;) #, quality = 50) #, compression = 
})



# C - Labels
df_C &amp;lt;- df %&amp;gt;% filter(label==&amp;quot;C&amp;quot;)

img_lst &amp;lt;- lapply(seq_along(df_C$label_path), function(i){
  product_en &amp;lt;- df_C$product_en[[i]]
  image_read(df_C$label_path[[i]])  %&amp;gt;% 
    image_annotate(paste0(sprintf(&amp;quot;%.1f&amp;quot;,round(df_C$co2[[i]], 1))), size = 70, color = &amp;quot;black&amp;quot;, weight=700, 
                   location = &amp;quot;+284+120&amp;quot;,font= &amp;quot;Helvetica&amp;quot;) %&amp;gt;% 
    image_annotate(&amp;quot; kg\nCO2&amp;quot;, size = 43, color = &amp;quot;black&amp;quot;, weight=700, 
                   location = &amp;quot;+294+190&amp;quot;,font= &amp;quot;Helvetica&amp;quot;) %&amp;gt;% 
    image_background(&amp;quot;grey25&amp;quot;) %&amp;gt;% 
    image_border(&amp;quot;grey25&amp;quot;, &amp;quot;80x10&amp;quot;) %&amp;gt;% # add border so that image will end up smaller in the final version
    image_crop(geometry=&amp;quot;1200x435&amp;quot;,repage=TRUE) %&amp;gt;% # crop bottom to make picture less high
    image_write(path = paste0(&amp;quot;../images/combined/&amp;quot;, product_en, &amp;quot;.png&amp;quot;), format = &amp;quot;png&amp;quot;) #, quality = 50) #, compression = 
})


# D - Labels

df_D &amp;lt;- df %&amp;gt;% filter(label==&amp;quot;D&amp;quot;)

img_lst &amp;lt;- lapply(seq_along(df_D$label_path), function(i){
  product_en &amp;lt;- df_D$product_en[[i]]
  image_read(df_D$label_path[[i]])  %&amp;gt;% 
    image_annotate(paste0(sprintf(&amp;quot;%.1f&amp;quot;,round(df_D$co2[[i]], 1))), size = 70, color = &amp;quot;black&amp;quot;, weight=700, 
                   location = &amp;quot;+424+120&amp;quot;,font= &amp;quot;Helvetica&amp;quot;) %&amp;gt;% 
    image_annotate(&amp;quot; kg\nCO2&amp;quot;, size = 43, color = &amp;quot;black&amp;quot;, weight=700, 
                   location = &amp;quot;+433+190&amp;quot;,font= &amp;quot;Helvetica&amp;quot;) %&amp;gt;% 
    image_background(&amp;quot;grey25&amp;quot;) %&amp;gt;% 
    image_border(&amp;quot;grey25&amp;quot;, &amp;quot;80x10&amp;quot;) %&amp;gt;% # add border so that image will end up smaller in the final version
    image_crop(geometry=&amp;quot;1200x440&amp;quot;,repage=TRUE) %&amp;gt;% # crop bottom to make picture less high
    image_write(path = paste0(&amp;quot;../images/combined/&amp;quot;, product_en, &amp;quot;.png&amp;quot;), format = &amp;quot;png&amp;quot;) #, quality = 50) #, compression = 
})


# E - Labels
df_E &amp;lt;- df %&amp;gt;% filter(label==&amp;quot;E&amp;quot;)

img_lst &amp;lt;- lapply(seq_along(df_E$label_path), function(i){
  product_en &amp;lt;- df_E$product_en[[i]]
  image_read(df_E$label_path[[i]])  %&amp;gt;% 
    image_annotate(paste0(sprintf(&amp;quot;%.1f&amp;quot;,round(df_E$co2[[i]], 1))), size = 70, color = &amp;quot;black&amp;quot;, weight=700, 
                   location = &amp;quot;+549+120&amp;quot;,font= &amp;quot;Helvetica&amp;quot;) %&amp;gt;% 
    image_annotate(&amp;quot; kg\nCO2&amp;quot;, size = 43, color = &amp;quot;black&amp;quot;, weight=700, 
                   location = &amp;quot;+559+190&amp;quot;,font= &amp;quot;Helvetica&amp;quot;) %&amp;gt;% 
    image_background(&amp;quot;grey25&amp;quot;) %&amp;gt;% 
    image_border(&amp;quot;grey25&amp;quot;, &amp;quot;80x10&amp;quot;) %&amp;gt;% # add border so that image will end up smaller in the final version
    image_crop(geometry=&amp;quot;1200x445&amp;quot;,repage=TRUE) %&amp;gt;% # crop bottom to make picture less high
    image_write(path = paste0(&amp;quot;../images/combined/&amp;quot;, product_en, &amp;quot;.png&amp;quot;), format = &amp;quot;png&amp;quot;) #, quality = 50) #, compression = 
})

# overwrite  products with co2 &amp;gt;=10 so that text appears in good place
df_E &amp;lt;- df %&amp;gt;% filter(label==&amp;quot;E&amp;quot;) %&amp;gt;% filter(co2 &amp;gt;=10)

img_lst &amp;lt;- lapply(seq_along(df_E$label_path), function(i){
  product_en &amp;lt;- df_E$product_en[[i]]
  image_read(df_E$label_path[[i]])  %&amp;gt;% 
    image_annotate(paste0(sprintf(&amp;quot;%.1f&amp;quot;,round(df_E$co2[[i]], 1))), size = 70, color = &amp;quot;black&amp;quot;, weight=700, 
                   location = &amp;quot;+520+120&amp;quot;,font= &amp;quot;Helvetica&amp;quot;) %&amp;gt;% 
    image_annotate(&amp;quot; kg\nCO2&amp;quot;, size = 43, color = &amp;quot;black&amp;quot;, weight=700, 
                   location = &amp;quot;+559+190&amp;quot;,font= &amp;quot;Helvetica&amp;quot;) %&amp;gt;% 
    image_background(&amp;quot;grey25&amp;quot;) %&amp;gt;% 
    image_border(&amp;quot;grey25&amp;quot;, &amp;quot;80x10&amp;quot;) %&amp;gt;% # add border so that image will end up smaller in the final version
    image_crop(geometry=&amp;quot;1200x445&amp;quot;,repage=TRUE) %&amp;gt;% # crop bottom to make picture less high
    image_write(path = paste0(&amp;quot;../images/combined/&amp;quot;, product_en, &amp;quot;.png&amp;quot;), format = &amp;quot;png&amp;quot;) #, quality = 50) #, compression = 
})


# combine image and foot (all combined images)
img_lst &amp;lt;- lapply(seq_along(df$image_path), function(i){
  product_en &amp;lt;- df$product_en[[i]]
  header &amp;lt;- image_read(path = paste0(&amp;quot;../images/final/control_&amp;quot;, df$product_en[[i]], &amp;quot;.png&amp;quot;)) 
  label  &amp;lt;- image_read(path = paste0(&amp;quot;../images/combined/&amp;quot;, df$product_en[[i]], &amp;quot;.png&amp;quot;)) 
  img &amp;lt;- c(header,label)
  image_append(image_scale(img,&amp;quot;770&amp;quot;), stack = TRUE) %&amp;gt;% 
    image_write(path = paste0(&amp;quot;../images/final/&amp;quot;, &amp;quot;combined-&amp;quot;, product_en, &amp;quot;.png&amp;quot;), format = &amp;quot;png&amp;quot;) #, quality = 50) #, compression = 
})&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Resulting example image:
&lt;img src=&#34;combined_Butter%202.png&#34; alt=&#34;Combined label&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;conclusion&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;This is the first time I used &lt;code&gt;magick&lt;/code&gt;. I was really surprised how powerful the package is and how quickly the code for this quite complex task was written. Now that this code is available, it will be easier still for future me and others with similar tasks on their hand to create such visual stimuli.&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;credit&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Credit&lt;/h2&gt;
&lt;p&gt;Parts of the crucial &lt;code&gt;lapply&lt;/code&gt; function was adapted from &lt;a href=&#34;https://github.com/ropensci/magick/issues/297&#34; class=&#34;uri&#34;&gt;https://github.com/ropensci/magick/issues/297&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
</description>
    </item>
    
  </channel>
</rss>
