Skip to content

Commit

Permalink
New images for image formats chapter. Closes clauswilke#56.
Browse files Browse the repository at this point in the history
  • Loading branch information
clauswilke committed Nov 13, 2018
1 parent 7365830 commit d0c720e
Show file tree
Hide file tree
Showing 16 changed files with 133 additions and 20 deletions.
31 changes: 18 additions & 13 deletions boxplots_violins.Rmd
Original file line number Diff line number Diff line change
Expand Up @@ -21,19 +21,24 @@ The simplest approach to showing many distributions at once is to show their mea
(ref:lincoln-temp-points-errorbars) Mean daily temperatures in Lincoln, Nebraska in 2016. Points represent the average daily mean temperatures for each month, averaged over all days of the month, and error bars represent twice the standard deviation of the daily mean temperatures within each month.

```{r lincoln-temp-points-errorbars, fig.cap = '(ref:lincoln-temp-points-errorbars)'}
lincoln_weather %>% mutate(month_short = fct_recode(Month,
Jan = "January",
Feb = "February",
Mar = "March",
Apr = "April",
May = "May",
Jun = "June",
Jul = "July",
Aug = "August",
Sep = "September",
Oct = "October",
Nov = "November",
Dec = "December")) %>%
lincoln_weather %>%
mutate(
month_short = fct_recode(
Month,
Jan = "January",
Feb = "February",
Mar = "March",
Apr = "April",
May = "May",
Jun = "June",
Jul = "July",
Aug = "August",
Sep = "September",
Oct = "October",
Nov = "November",
Dec = "December"
)
) %>%
mutate(month_short = fct_rev(month_short)) -> lincoln_df
Expand Down
Binary file removed figures/iris.pdf
Binary file not shown.
Binary file removed figures/iris.png
Binary file not shown.
Binary file removed figures/iris_pdf_crops.idraw
Binary file not shown.
Binary file removed figures/iris_png_crops.idraw
Binary file not shown.
Binary file removed figures/iris_with_box.idraw
Binary file not shown.
Binary file removed figures/iris_with_box.pdf
Binary file not shown.
Binary file removed figures/iris_zoom.idraw
Binary file not shown.
Binary file removed figures/iris_zoom.pdf
Binary file not shown.
Binary file removed figures/iris_zoom.png
Binary file not shown.
Binary file modified figures/jpeg_example_combined.idraw
Binary file not shown.
Binary file removed figures/jpeg_example_combined.jpg
Binary file not shown.
Binary file modified figures/jpeg_example_combined.pdf
Binary file not shown.
Binary file added figures/jpeg_example_combined.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added figures/lincoln-temps.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
122 changes: 115 additions & 7 deletions image_file_formats.Rmd
Original file line number Diff line number Diff line change
Expand Up @@ -28,13 +28,121 @@ tiff Tagged Image File Format bitmap print production, accur
raw Raw Image File bitmap digital photography, needs post-processing
gif Graphics Interchange Format bitmap outdated, do not use

Vector graphics are also called "resolution-independent," because they can be magnified to arbitrary size without losing detail or sharpness. See Figure \@ref(fig:iris-zoom) for a demonstration.
Vector graphics are also called "resolution-independent," because they can be magnified to arbitrary size without losing detail or sharpness. See Figure \@ref(fig:bitmap-zoom) for a demonstration.

(ref:bitmap-zoom) Illustration of the key difference between vector graphics and bitmaps. (a) Original image. The black square indicates the area we are magnifying in parts (b) and (c). (b) Increasing magnification of the highlighted area from part (a) when the image has been stored as a bitmap graphic. We can see how the image becomes increasingly pixelated as we zoom in further. (c) Increasing magnification of a vector representation of the image. The image maintains perfect sharpness at arbitrary magnification levels.

```{r bitmap-zoom, fig.width = 8.5, fig.asp = 1/2.8, fig.cap='(ref:bitmap-zoom)'}
library(magick)
# support functions ---------------------------------------------------------
# cut square out of larger image
# x and y are center coordinates
cut_npc_square <- function(img, x, y, w) {
info <- magick::image_info(img)
width <- w*info$width
xpx <- x*info$width - 0.5*width
ypx <- (1-y)*info$height-0.5*width # reverse coordinate system
image_crop(img, geometry_area(width = width, height = width, x_off = xpx, y_off = ypx))
}
# add an image to a plot
# x and y are center coordinates, height is calculated from image aspect ratio
add_image <- function(img, x, y, width = NULL, interpolate = TRUE) {
info <- magick::image_info(img)
if (is.null(width)) {
width <- info$width
}
height <- width*info$height/info$width
x <- x - 0.5*width
y <- y - 0.5*height
draw_image(img, x, y, width, height, interpolate = interpolate)
}
# adds a box corresponding to the size of an image
# x and y are center coordinates
add_image_box <- function(img, x, y, width = NULL) {
info <- image_info(img)
if (is.null(width)) {
width <- info$width
}
height <- width*info$height/info$width
geom_rect(
data = data.frame(
xmin = x - 0.5*width, xmax = x + 0.5*width,
ymin = y - 0.5*height, ymax = y + 0.5*height
),
aes(xmin = xmin, xmax = xmax, ymin = ymin, ymax = ymax),
fill = NA,
color = "black"
)
}
# image drawing code ---------------------------------------------------------
img_hires <- image_read("figures/lincoln-temps.png")
xc <- 0.73 # relative x center
yc <- 0.58 # relative y center
bw <- 0.16 # relative box width
img <- image_scale(img_hires, "1800")
c5 <- cut_npc_square(img, xc, yc, bw)
img <- image_scale(img_hires, "3600")
c6 <- cut_npc_square(img, xc, yc, bw/2)
img <- image_scale(img_hires, "7200")
c7 <- cut_npc_square(img, xc, yc, bw/4)
c8 <- cut_npc_square(img_hires, xc, yc, bw/8)
img <- image_scale(img_hires, "1200")
c1 <- cut_npc_square(img, xc, yc, bw)
c2 <- cut_npc_square(img, xc, yc, bw/2)
c3 <- cut_npc_square(img, xc, yc, bw/4)
c4 <- cut_npc_square(img, xc, yc, bw/8)
info <- image_info(img)
p1 <- ggplot() +
expand_limits(
x = c(0, info$width-1),
y = c(-0.3*info$height, info$height-1) # add 30% vertical space below
) +
coord_fixed(expand = FALSE) +
draw_image(img, x = 0, y = 0, width = info$width, height = info$height) +
add_image_box(c1, xc*info$width, yc*info$height, width = bw*info$width) +
theme_nothing()
p2 <- ggplot() +
expand_limits(x = c(-0.01, 4.61), y = c(-0.01, 1.01)) +
coord_fixed(expand = FALSE) +
add_image(c1, x = 0.5, y = 0.5, width = 1, interpolate = FALSE) +
add_image(c2, x = 1.7, y = 0.5, width = 1, interpolate = FALSE) +
add_image(c3, x = 2.9, y = 0.5, width = 1, interpolate = FALSE) +
add_image(c4, x = 4.1, y = 0.5, width = 1, interpolate = FALSE) +
add_image_box(c1, x = 0.5, y = 0.5, width = 1) +
add_image_box(c2, x = 1.7, y = 0.5, width = 1) +
add_image_box(c3, x = 2.9, y = 0.5, width = 1) +
add_image_box(c4, x = 4.1, y = 0.5, width = 1) +
theme_nothing()
p3 <- ggplot() +
expand_limits(x = c(-0.01, 4.61), y = c(-0.01, 1.01)) +
coord_fixed(expand = FALSE) +
add_image(c5, x = 0.5, y = 0.5, width = 1) +
add_image(c6, x = 1.7, y = 0.5, width = 1) +
add_image(c7, x = 2.9, y = 0.5, width = 1) +
add_image(c8, x = 4.1, y = 0.5, width = 1) +
add_image_box(c5, x = 0.5, y = 0.5, width = 1) +
add_image_box(c6, x = 1.7, y = 0.5, width = 1) +
add_image_box(c7, x = 2.9, y = 0.5, width = 1) +
add_image_box(c8, x = 4.1, y = 0.5, width = 1) +
theme_nothing()
col <- plot_grid(p2, p3, labels = c("b", "c"), ncol = 1)
plot_grid(p1, col, labels = c("a", ""), nrow = 1, rel_widths = c(1, 1.5))
(ref:iris-zoom) Illustration of the key difference between vector graphics and bitmaps. (a) Original image. The black square around the number seven indicates the area we're magnifying in parts (b) and (c). (b) Increasing magnification of the highlighted area from part (a) when the image has been stored as a bitmap graphic. We can see how the image becomes increasingly pixelated and blurry as we zoom in further. (c) Increasing magnification of a vector representation of the image. The image maintains perfect sharpness at arbitrary magnification levels.

```{r iris-zoom, fig.cap='(ref:iris-zoom)'}
knitr::include_graphics("figures/iris_zoom.png")
```

Vector graphics have two downsides that can and often do cause trouble in real-world applications. First, because vector graphics are redrawn on the fly by the graphics program with which they are displayed, it can happen that there are differences in how the same graphic looks in two different programs, or on two different computers. This problem occurs most frequently with text, for example when the required font is not available and the rendering software substitutes a different font. Font substitutions will typically allow the viewer to read the text as intended, but the resulting image rarely looks good. There are ways to avoid these problems, such as outlining or embedding all fonts in a pdf file, but they may require special software and/or special technical knowledge to achieve. By contrast, bitmap images will always look correct.
Expand All @@ -52,10 +160,10 @@ Photographic images rarely have multiple pixels of identical color and brightnes
The most widely used lossy image format is jpeg (Table \@ref(tab:file-formats)), and indeed many digital cameras output images as jpeg by default. Jpeg compression works exceptionally well for photographic images, and huge reductions in file size can often be obtained with very little degradation in image quality. However, jpeg compression fails when images contain sharp edges, such as created by line drawings or by text. In those cases, jpeg compression can result in very noticeable artifacts (Figure \@ref(fig:jpeg-example)).


(ref:jpeg-example) Illustration of jpeg artifacts. (a) The same image is reproduced multiple times using increasingly severe jpeg compression. The resulting file size is shown in the top-right corner of each image. A reduction in file size by a factor of 10, from 432kB in the original image to 43kB in the compressed image, results in only minor perceptible reduction in image quality. However, a further reduction in file size by a factor of 2, to a mere 25kB, leads to numerous visible artifacts. (b) Zooming in to the most highly compressed image reveals the various compression artifacts. *Image credit: Claus O. Wilke*
(ref:jpeg-example) Illustration of jpeg artifacts. (a) The same image is reproduced multiple times using increasingly severe jpeg compression. The resulting file size is shown in red text above each image. A reduction in file size by a factor of 10, from 432kB in the original image to 43kB in the compressed image, results in only minor perceptible reduction in image quality. However, a further reduction in file size by a factor of 2, to a mere 25kB, leads to numerous visible artifacts. (b) Zooming in to the most highly compressed image reveals the various compression artifacts. *Image credit: Claus O. Wilke*

```{r jpeg-example, fig.cap='(ref:jpeg-example)'}
knitr::include_graphics("figures/jpeg_example_combined.jpg", dpi=600)
knitr::include_graphics("figures/jpeg_example_combined.png", dpi=210)
```

Even if jpeg artifacts are sufficiently subtle that they are not immediately visible to the naked eye they can cause trouble, for example in print production. Therefore, it is a good idea to avoid the jpeg format whenever possible. In particular, you should avoid it for images containing line drawings or text, as is the case for data visualizations or screen shots. The appropriate format for those images is png or tiff. I use the jpeg format exclusively for photographic images. And if an image contains both photographic elements and line drawings or text, you should still use png or tiff. The worst case scenario with those file formats is that your image files grow large, whereas the worst case scenario with jpeg is that your final product looks ugly.
Expand Down

0 comments on commit d0c720e

Please sign in to comment.