Skip to content

Instantly share code, notes, and snippets.

@JEFworks
Last active October 18, 2024 17:23
Show Gist options
  • Save JEFworks/637308c2a1dd8a6faff7b6264104847a to your computer and use it in GitHub Desktop.
Save JEFworks/637308c2a1dd8a6faff7b6264104847a to your computer and use it in GitHub Desktop.
A fast Floyd-Steinberg dithering filter in C++ using Rcpp
library(Rcpp)
#' Floyd-Steinberg dithering
#'
#' @description Rcpp C++ function for Floyd-Steinberg dithering
#' More info: https://en.wikipedia.org/wiki/Floyd%E2%80%93Steinberg_dithering
#' Note, this is a C++ translation of the FloydConvolution function by Todos Logos
#' from https://www.r-bloggers.com/r-is-a-cool-image-editor-2-dithering-algorithms/
#'
#' @param x Greyscaled 2D image matrix
#' @return Dithered image matrix
#'
#' @examples {
#' ## Read image
#' library(jpeg)
#' img <- readJPEG(system.file("img", "Rlogo.jpg", package="jpeg"))
#' ## Take red channel as greyscale
#' imgGrey <- img[,,1]
#' dither <- ditherC(imgGrey)
#' ## Plot
#' image(t(apply(dither, 2, rev)), useRaster=TRUE, axes=FALSE, col = grey(seq(0, 1, length = 256)))
#' }
cppFunction('NumericMatrix ditherC(NumericMatrix x) {
NumericMatrix a = x;
int nrow = a.nrow(), ncol = a.ncol();
for (int i = 1; i < nrow-1; i++) {
for (int j = 1; j < ncol-1; j++) {
int P = trunc(a(i, j)+0.5);
double e = a(i, j) - P;
a(i, j) = P;
a(i, j+1) = a(i, j+1) + (e * 7/16);
a(i+1, j-1) = a(i+1, j-1) + (e * 3/16);
a(i+1, j) = a(i+1, j) + (e * 5/16);
a(i+1, j+1) = a(i+1, j+1) + (e * 1/16);
}
}
return a;
}')
@JEFworks
Copy link
Author

Sample output

image

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment