From 15fd982907c9a310d329ecab5515e2f7bb627b25 Mon Sep 17 00:00:00 2001 From: aoles Date: Fri, 8 Sep 2017 11:09:02 +0200 Subject: [PATCH] version 4.19.9 - correct way of checking for out-of-bounds points in `floodFill` (fixes https://github.com/aoles/EBImage/issues/23) - improved interace to `floodFill` for single-frame images (see https://github.com/aoles/EBImage/issues/21) --- DESCRIPTION | 2 +- R/floodFill.R | 35 +++++++++++++++++++---------------- man/floodFill.Rd | 9 ++++----- 3 files changed, 24 insertions(+), 22 deletions(-) diff --git a/DESCRIPTION b/DESCRIPTION index 5dd3cdb..9930616 100755 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -1,5 +1,5 @@ Package: EBImage -Version: 4.19.8 +Version: 4.19.9 Title: Image processing and analysis toolbox for R Encoding: UTF-8 Author: Andrzej OleÅ›, Gregoire Pau, Mike Smith, Oleg Sklyar, Wolfgang Huber, with contributions from Joseph Barry and Philip A. Marais diff --git a/R/floodFill.R b/R/floodFill.R index 5d22907..6d54f5f 100644 --- a/R/floodFill.R +++ b/R/floodFill.R @@ -15,34 +15,37 @@ # LGPL license wording: http://www.gnu.org/licenses/lgpl.html ## - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -floodFill = function(x, pt, col, tolerance=0) { +floodFill = function(x, pts, col, tolerance=0) { validImage(x) nf = numberOfFrames(x, 'render') nc = numberOfChannels(x) ## make sure that `pt` and `col` are lists of length matching the number of frames - if ( is.list(pt) ) { - if ( length(pt) != nf ) stop("length of 'pt' must match the number of 'render' frames") - } else { - pt = rep(list(pt), nf) - } - if ( is.list(col) ) { - if ( length(col) != nf ) stop("length of 'col' must match the number of 'render' frames") - } else { - col = rep(list(col), nf) + format_as_list = function(x, nf) { + if ( is.list(x) ) + if ( length(x)==nf ) + return(x) + else if ( nf > 1L) + stop(sprintf("length of '%s' must match the number of 'render' frames"), deparse(substitute(x))) + rep(list(x), nf) } + pts = format_as_list(pts, nf) + col = format_as_list(col, nf) for (i in seq_len(nf) ) { - pti = pt[[i]] + pti = pts[[i]] if ( is.list(pti) ) - pti = unlist(pti, use.names=FALSE) + if ( is.data.frame(pti) ) + pti = as.matrix(pti) + else + pti = unlist(pti, use.names=FALSE) storage.mode(pti) = "integer" - if ( any(pti<1L) || any(pti>dim(x)[1:2]) ) - stop("coordinates of starting point(s) 'pt' must be inside image boundaries") if ( !is.matrix(pti) || dim(pti)[2L]!=2L ) pti = matrix(pti, nrow=length(pti)/2, ncol=2L, byrow=TRUE) np = dim(pti)[1L] - pt[[i]] = pti + if ( any( pti<1L ) || any( pti>rep(dim(x)[1:2], each=np) ) ) + stop("coordinates of starting point(s) 'pts' must be inside image boundaries") + pts[[i]] = pti cli = col[[i]] cli = if ( is.character(cli) ) @@ -54,7 +57,7 @@ floodFill = function(x, pt, col, tolerance=0) { col[[i]] = cli } - return( .Call(C_floodFill, x, pt, col, as.numeric(tolerance))) + return( .Call(C_floodFill, x, pts, col, as.numeric(tolerance))) } ## - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/man/floodFill.Rd b/man/floodFill.Rd index 831e41e..84f4fd4 100644 --- a/man/floodFill.Rd +++ b/man/floodFill.Rd @@ -9,16 +9,15 @@ } \usage{ -floodFill(x, pt, col, tolerance=0) +floodFill(x, pts, col, tolerance=0) } \arguments{ \item{x}{An \code{Image} object or an array.} - \item{pt}{Coordinates of the start filling points provided as a matrix where rows represent points and columns are the x and y cordinates. For image stacks different points for each frame can be specified by providing a list whose length matches the number of 'render' frames.} + \item{pts}{Coordinates of the start filling points given as either of the following: a vector of the form \code{c(x1, y1, x2, y2, ...)}, a list of points, a matrix or data frame where rows represent points and columns are the x and y coordinates. For image stacks different points for each frame can be specified by providing them in a list of length matching the number of 'render' frames.} - \item{col}{Fill color. This argument should be a numeric for Grayscale images - and an R color for Color images. Values are recycled such that their length matches the number of points in `pt`. Can be a list similarly as `pt`.} + \item{col}{Fill color. This argument should be a numeric for Grayscale images and an R color for Color images. Values are recycled such that their length matches the number of points in \code{pts}. Can be a list of length matching the number of 'render' frames similarly as \code{pts}.} \item{tolerance}{Color tolerance used during the fill.} } @@ -30,7 +29,7 @@ floodFill(x, pt, col, tolerance=0) \details{ Flood fill is performed using the fast scan line algorithm. Filling - starts at \code{pt} and grows in connected areas where the absolute + starts at \code{pts} and grows in connected areas where the absolute difference of the pixels intensities (or colors) remains below \code{tolerance}. }