minitypes
minitypes
is a package of type conversion tools for R atomic vectors.
This package is built upon R’s type conversion tools and aims to:
- have a consistent interface for converting between types
- add handling for types not handled by R explicitly e.g.
uint8
It’s available from github.
Worked Example - Parsing an ICO favicon
- Read in a favicon file (ICO) as raw bytes (ICO values are represented in little-endian byte order)
- Manually parse the ICO header (see e.g. ICO format)
- Parse out the pixels and plot
Read the favicon as raw bytes
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# cran.r-project favicon!
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# https://cran.r-project.org/favicon.ico
ico_filename <- "../../static/img/minitypes/favicon.ico"
ico <- readBin(ico_filename, 'raw', n = file.size(ico_filename))
head(ico, 50)
[1] 00 00 01 00 02 00 10 10 00 00 01 00 20 00 68 04 00 00 26 00 00 00 20 20 00
[26] 00 01 00 20 00 a8 10 00 00 8e 04 00 00 28 00 00 00 10 00 00 00 20 00 00 00
Read the header to find where the iamge data starts
# Reserved - must always be zero
raw_to_uint16(ico[1:2], endian = 'little')
[1] 0
# image type. 1 = ICO, 2 = CUR
raw_to_uint16(ico[3:4], endian = 'little')
[1] 1
# number of images in the file
raw_to_uint16(ico[5:6], endian = 'little')
[1] 2
# width, height
raw_to_uint8(ico[7:8], endian = 'little')
[1] 16 16
# number of color planes
raw_to_uint16(ico[11:12], endian = 'little')
[1] 1
# bits per pixel
raw_to_uint16(ico[13:14], endian = 'little')
[1] 32
# number of bytes of image data
raw_to_int32(ico[15:18], endian = 'little')
[1] 1128
# Image data offset
raw_to_int32(ico[19:22], endian = 'little')
[1] 38
Read one channel of the image data
# read 4bytes per pixel for 16x16 pixels.
# Skip to the image data offset (+38), and jump over the BMP data header(?) (+44)
image <- raw_to_int32(ico[38 + 44 - 1 + seq_len(16*16*4)])
# Reshape to be a 16x16 matrix, keeping only the lowest byte.
image <- (matrix(image %% 256, 16, 16, byrow=TRUE))[16:1,]
# plot as raster
rim <- raster(image)
plot(rim, col = grey(seq(1, 0, length.out = 16)), ann = FALSE)