bitstreamio is a package for reading bits from a connection or raw
vector.
This package has no requirement that reads/write operations be byte aligned. This is useful for input/output with packed binary file formats e.g. h264-compressed video, mp3 audio etc.
In addition to reading individual bits, this package also provides for:
- Reading/writing unaligned bytes as raw vectors
- Reading/writing unsigned integers (i.e. non-negative integers) at bit depths from 1 to 31
- Read/write signed/unsigned integers with Exponential-Golomb coding
What’s in the box
- Read write: bits, bytes, unsigned integers, integers coded with
exponential golomb (signed and unsigned variants).
bs_write_bit(),bs_read_bit()bs_write_byte(),bs_read_byte()bs_write_uint(),bs_read_uint()bs_write_uint_exp_golomb(),bs_read_uint_exp_golomb()bs_write_sint_exp_golomb(),bs_read_sint_exp_golomb()
- Bitstream utilities
bs_open(),bs_close()bs_is_aligned(),bs_align()bs_advance(),bs_peek()
Installation
This package can be installed from CRAN
install.packages('bitstreamio')You can install the latest development version from GitHub with:
# install.package('remotes') remotes::install_github('coolbutuseless/bitstreamio')
Pre-built source/binary versions can also be installed from R-universe
install.packages('bitstreamio', repos = c('https://coolbutuseless.r-universe.dev', 'https://cloud.r-project.org'))
Read/Write with a raw vector
library(bitstreamio) #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # Write bits to a raw vector #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ bs <- bs_open(raw(), "w") bs_write_bit(bs, c(TRUE , FALSE, FALSE, FALSE)) bs_write_byte(bs, c(0x01, 0x7f)) # write unaligned byte values bs_write_bit(bs, c(FALSE, FALSE, FALSE, TRUE)) raw_vec <- bs_close(bs) raw_vec
#> [1] 80 17 f1
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # Read bits back from raw vector #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ bs <- bs_open(raw_vec, mode = 'r') bs_read_bit(bs, 4)
#> [1] TRUE FALSE FALSE FALSE
bs_read_byte(bs, 2) # unaligned byte read
#> [1] 01 7f
bs_read_bit(bs, 4)
#> [1] FALSE FALSE FALSE TRUE
bs_close(bs)Reading/Write with a connection
filename <- tempfile() #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # Write bits to a file #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ con <- file(filename, "wb") bs <- bs_open(con, mode = 'w') bs_write_bit(bs, c(TRUE , FALSE, FALSE, FALSE)) bs_write_byte(bs, c(1, 127)) bs_write_bit(bs, c(FALSE, FALSE, FALSE, TRUE)) bs_close(bs) close(con) #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # Read the bits back in #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ con <- file(filename, "rb") bs <- bs_open(con, mode = 'r') bs_read_bit(bs, 4)
#> [1] TRUE FALSE FALSE FALSE
bs_read_uint(bs, nbits = 8, n = 2)
#> [1] 1 127
bs_read_bit(bs, 4)
#> [1] FALSE FALSE FALSE TRUE
bs_close(bs) close(con)
Read/write unsigned integers at varying bit depths
library(bitstreamio) #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # Write bits to a raw vector #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ bs <- bs_open(raw(), "w") bs_write_uint(bs, 0:7 , nbits = 3) # write 8 * 3-bit integers bs_write_uint(bs, 10:15, nbits = 4) # write 6 * 4-bit integers raw_vec <- bs_close(bs) raw_vec
#> [1] 05 39 77 ab cd ef
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # Read bits back from raw vector #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ bs <- bs_open(raw_vec, mode = 'r') bs_read_uint(bs, nbits = 3, n = 8)
#> [1] 0 1 2 3 4 5 6 7
bs_read_uint(bs, nbits = 4, n = 6)
#> [1] 10 11 12 13 14 15
bs_close(bs)Read/write integers with Exponential-Golomb coding
Exponential-Golomb coding is a way of encoding integers to bit sequences. These bit sequences are often smaller than any standard integer type, and are often used to save space when packing data into a stream when the size of the integer is not known ahead of time.
# Converstion of unsigned integers to Exponential-Golomb coded bit sequences uint_to_exp_golomb_bits(0)
#> [1] TRUE
uint_to_exp_golomb_bits(1)#> [1] FALSE TRUE FALSE
uint_to_exp_golomb_bits(2)#> [1] FALSE TRUE TRUE
uint_to_exp_golomb_bits(3)#> [1] FALSE FALSE TRUE FALSE FALSE
# Converstion of signed integers to Exponential-Golomb coded bit sequences sint_to_exp_golomb_bits(0)
#> [1] TRUE
sint_to_exp_golomb_bits(-1)
#> [1] FALSE TRUE TRUE
sint_to_exp_golomb_bits(-2)
#> [1] FALSE FALSE TRUE FALSE TRUE
sint_to_exp_golomb_bits(3)#> [1] FALSE FALSE TRUE TRUE FALSE
library(bitstreamio) #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # Write bits to a raw vector #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ bs <- bs_open(raw(), "w") bs_write_uint_exp_golomb(bs, 0:9) raw_vec <- bs_close(bs) # 10 integers encoded into 6 bytes raw_vec
#> [1] a6 42 98 e2 04 8a
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # Read bits back from raw vector #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ bs <- bs_open(raw_vec, mode = 'r') bs_read_uint_exp_golomb(bs, 10)
#> [1] 0 1 2 3 4 5 6 7 8 9
bs_close(bs)Related Software
- ctypesio - for
reading/writing standard C types with connections e.g.
uint16,float,doubleetc.