diff --git a/src/border.jl b/src/border.jl index a33ffec..c0670b4 100644 --- a/src/border.jl +++ b/src/border.jl @@ -29,23 +29,94 @@ NoPad Base.getindex(np::NoPad) = np.border """ -`Pad` is a type that stores choices about padding. Instances must set `style`, a -Symbol specifying the boundary conditions of the image, one of: - -- `:replicate` (repeat edge values to infinity) -- `:circular` (image edges "wrap around") -- `:symmetric` (the image reflects relative to a position between pixels) -- `:reflect` (the image reflects relative to the edge itself) - -The default value is `:replicate`. - -It's worth emphasizing that padding is most straightforwardly specified as a string, - - imfilter(img, kernel, "replicate") - -rather than +```julia + struct Pad{N} <: AbstractBorder + style::Symbol + lo::Dims{N} # number to extend by on the lower edge for each dimension + hi::Dims{N} # number to extend by on the upper edge for each dimension + end +``` + +`Pad` is a type that designates the form of padding which should be used to +extrapolate pixels beyond the boundary of an image. Instances must set `style`, +a Symbol specifying the boundary conditions of the image. + +# Output + +The type `Pad` specifying how the boundary of an image should be padded. + +# Details +When representing a spatial image filtering operation as a discrete convolution +between the image and a ``D \\times D `` filter, the results are undefined for +pixels closer than ``D`` pixels from the border of the image. To define the +operation near and at the border, one needs a scheme for extrapolating pixels +beyond the edge. The `Pad` type allows one to specify the necessary +extrapolation scheme. + +You can specify a different amount of padding for the top, left, bottom and +right border of an image. + +## Options +Some valid `style` options are described below. As an indicative example of each +option the results of the padding are illustrated on an image consisting of a +row of six pixels which are specified alphabetically: ``\\boxed{a \\, b \\, c \\,d \\, e \\, f}``. +We show the effects of padding only on the left and right +border, but analogous consequences hold for the top and bottom border. + +### `:replicate` (Default) + +The border pixels extend beyond the image boundaries. +```math +\\boxed{ +\\begin{array}{l|c|r} + a\\, a\\, a\\, a & a \\, b \\, c \\, d \\, e \\, f & f \\, f \\, f \\, f +\\end{array} +} +``` +See also: [`Fill`](@ref), [`padarray`](@ref), [`Inner`](@ref) and +[`NoPad`](@ref) + +### `:circular` + +The border pixels wrap around. For instance, indexing beyond the left border +returns values starting from the right border. +```math +\\boxed{ +\\begin{array}{l|c|r} + c\\, d\\, e\\, f & a \\, b \\, c \\, d \\, e \\, f & a \\, b \\, c \\, d +\\end{array} +} +``` +See also: [`Fill`](@ref), [`padarray`](@ref), [`Inner`](@ref) and +[`NoPad`](@ref) + +### `:symmetric` +The border pixels reflect relative to a position between pixels. That is, the +border pixel is omitted when mirroring. +```math +\\boxed{ +\\begin{array}{l|c|r} + e\\, d\\, c\\, b & a \\, b \\, c \\, d \\, e \\, f & e \\, d \\, c \\, b +\\end{array} +} +``` +See also: [`Fill`](@ref),[`padarray`](@ref), [`Inner`](@ref) and +[`NoPad`](@ref) + +### `:reflect` +The border pixels reflect relative to the edge itself. +```math +\\boxed{ +\\begin{array}{l|c|r} + d\\, c\\, b\\, a & a \\, b \\, c \\, d \\, e \\, f & f \\, e \\, d \\, c +\\end{array} +} +``` +See also: [`Fill`](@ref),[`padarray`](@ref), [`Inner`](@ref) and +[`NoPad`](@ref) + +--- - imfilter(img, kernel, Pad(:replicate)) """ struct Pad{N} <: AbstractBorder style::Symbol @@ -53,6 +124,7 @@ struct Pad{N} <: AbstractBorder hi::Dims{N} # number to extend by on the upper edge for each dimension end + Pad{N}(style, lo::AbstractVector, hi::AbstractVector) where {N} = Pad{N}(style, (lo...), (hi...)) @@ -70,25 +142,68 @@ end borderinstance(b::AbstractBorder) = b """ +```julia Pad(style::Symbol, m, n, ...) +``` + +Construct an instance of [`Pad`](@ref) such that the image is prepended and appended symmetrically with `m` pixels at the lower and upper edge of dimension 1, `n` pixels for dimension 2, and so forth. + +#### Usage illustration +Use `Pad(:replicate,2,2)` to designate that the top and bottom border should be +replicated by two pixels, and the left and right border by four pixels. + + +--- -Pad the input image symmetrically, `m` pixels at the lower and upper edge of dimension 1, `n` pixels for dimension 2, and so forth. """ Pad(style::Symbol, both::Int...) = Pad(style, both, both) Pad(both::Int...) = Pad(:replicate, both, both) """ +```julia Pad(style::Symbol, (m,n)) +``` +Construct an instance of [`Pad`](@ref) such that the image is prepended and appended symmetrically with `m` pixels at the lower and upper edge of dimension 1, and `n` pixels for dimension 2. + +#### Usage illustration +Use `Pad(:circular,(0,3))` to designate that the top and bottom border should +not be padded, and that the left and right border should wrap around by three +pixels. + +--- -Pad the input image symmetrically, `m` pixels at the lower and upper edge of dimension 1, `n` pixels for dimension 2. """ Pad(style::Symbol, both::Dims) = Pad(style, both, both) + +""" +```julia + Pad(both::Dims) +``` +Construct an instance of [`Pad`](@ref) with default `:replicate` extrapolation, where the tuple `both` specifies the number of pixels which will be prepended and appended for each dimension. + +#### Usage illustration +Use `Pad((5,5))` to designate that the top, bottom, left and right border should +be replicated by five pixels. + +--- + +""" Pad(both::Dims) = Pad(:replicate, both, both) """ +```julia Pad(style::Symbol, lo::Dims, hi::Dims) +``` +Construct an instance of [`Pad`](@ref) such that the image is prepended by `lo` pixels and appended by `hi` pixels in each dimension. + +#### Usage illustration + +Use `Pad(:replicate,(1,2),(3,4))` to designate that the top and bottom border +should be replicated by one and two pixels, and that the left and right border +should be replicated by three and four pixels. + +--- -Pad the input image by `lo` pixels at the lower edge, and `hi` pixels at the upper edge. """ Pad(lo::Dims, hi::Dims) = Pad(:replicate, lo, hi) Pad(style::Symbol, lo::Tuple{}, hi::Tuple{}) = Pad{0}(style, lo, hi) @@ -99,10 +214,20 @@ Pad(style::Symbol, lo::AbstractVector{Int}, hi::AbstractVector{Int}) = Pad(style Pad(style::Symbol, inds::Indices) = Pad(style, map(lo,inds), map(hi,inds)) """ +```julia Pad(style, kernel) Pad(style)(kernel) +``` +Construct an instance of [`Pad`](@ref) by designating the value `val` and a filter array `kernel` which will be used to determine the amount of padding from the `indices` of `kernel`. + +#### Usage illustration + +Use `Pad(:circular,Kernel.sobel())` to specify a `:circular` border style and +the minimal amount of padding necessary to ensure that convolution with +[`Kernel.sobel`](@ref) will be defined at the borders of an image. + +--- -Given a filter array `kernel`, determine the amount of padding from the `indices` of `kernel`. """ (p::Pad{0})(kernel) = Pad(p.style, calculate_padding(kernel)) (p::Pad{0})(kernel, img, ::Alg) = p(kernel) @@ -135,13 +260,170 @@ end _padindices(border, ::Tuple{}, ::Tuple{}, ::Tuple{}) = () """ +```julia padarray([T], img, border) --> imgpadded - +``` Generate a padded image from an array `img` and a specification `border` of the boundary conditions and amount of padding to -add. `border` can be a `Pad`, `Fill`, or `Inner` object. +add. + +# Output + +An expansion of the input image in which additional pixels are derived +from the border of the input image using the extrapolation scheme specified by +`border`. + +# Details + +You can specify the element type `T` of the output image. + +## Options +Valid `border` options are described below. + +### `Pad` +The type `Pad` designates the form of padding which should be used to +extrapolate pixels beyond the boundary of an image. Instances must set `style`, +a Symbol specifying the boundary conditions of the image. +Symbol must be on one of: +- `:replicate` (repeat edge values to infinity), +- `:circular` (image edges "wrap around"), +- `:symmetric` (the image reflects relative to a position between pixels), +- `:reflect` (the image reflects relative to the edge itself). + +Refer to the documentation of [`Pad`](@ref) for more details and examples for +each option. + +### `Fill` +The type `Fill` designates a particular value which will be used to +extrapolate pixels beyond the boundary of an image. Refer to the documentation +of [`Fill`](@ref) for more details and illustrations. + +# Examples +Each example is based on the input array +```math +\\mathbf{A} = +\\boxed{ +\\begin{matrix} + 1 & 2 & 3 & 4 & 5 & 6 \\\\ + 2 & 4 & 6 & 8 & 10 & 12 \\\\ + 3 & 6 & 9 & 12 & 15 & 18 \\\\ + 4 & 8 & 12 & 16 & 20 & 24 \\\\ + 5 & 10 & 15 & 20 & 25 & 30 \\\\ + 6 & 12 & 18 & 24 & 30 & 36 + \\end{matrix}}. +``` +## Examples with `Pad` +The command `padarray(A, Pad(:replicate,4,4))` yields +```math +\\boxed{ +\\begin{array}{ccccccccccccc} +1 & 1 & 1 & 1 & 1 & 2 & 3 & 4 & 5 & 6 & 6 & 6 & 6 & 6 \\\\ +1 & 1 & 1 & 1 & 1 & 2 & 3 & 4 & 5 & 6 & 6 & 6 & 6 & 6 \\\\ +1 & 1 & 1 & 1 & 1 & 2 & 3 & 4 & 5 & 6 & 6 & 6 & 6 & 6 \\\\ +1 & 1 & 1 & 1 & 1 & 2 & 3 & 4 & 5 & 6 & 6 & 6 & 6 & 6 \\\\ +1 & 1 & 1 & 1 & \\boxed{1} & \\boxed{2} & \\boxed{3} & \\boxed{4} & \\boxed{5} & \\boxed{6} & 6 & 6 & 6 & 6 \\\\ +2 & 2 & 2 & 2 & \\boxed{2} & \\boxed{4} & \\boxed{6} & \\boxed{8} & \\boxed{10} & \\boxed{12} & 12 & 12 & 12 & 12 \\\\ +3 & 3 & 3 & 3 & \\boxed{3} & \\boxed{6} & \\boxed{9} & \\boxed{12} & \\boxed{15} & \\boxed{18} & 18 & 18 & 18 & 18 \\\\ +4 & 4 & 4 & 4 & \\boxed{4} & \\boxed{8} & \\boxed{12} & \\boxed{16} & \\boxed{20} & \\boxed{24} & 24 & 24 & 24 & 24 \\\\ +5 & 5 & 5 & 5 & \\boxed{5} & \\boxed{10} & \\boxed{15} & \\boxed{20} & \\boxed{25} & \\boxed{30} & 30 & 30 & 30 & 30 \\\\ +6 & 6 & 6 & 6 & \\boxed{6} & \\boxed{12} & \\boxed{18} & \\boxed{24} & \\boxed{30} & \\boxed{36} & 36 & 36 & 36 & 36 \\\\ +6 & 6 & 6 & 6 & 6 & 12 & 18 & 24 & 30 & 36 & 36 & 36 & 36 & 36 \\\\ +6 & 6 & 6 & 6 & 6 & 12 & 18 & 24 & 30 & 36 & 36 & 36 & 36 & 36 \\\\ +6 & 6 & 6 & 6 & 6 & 12 & 18 & 24 & 30 & 36 & 36 & 36 & 36 & 36 \\\\ +6 & 6 & 6 & 6 & 6 & 12 & 18 & 24 & 30 & 36 & 36 & 36 & 36 & 36 + \\end{array} +}. +``` + +The command `padarray(A, Pad(:circular,4,4))` yields +```math +\\boxed{ +\\begin{array}{ccccccccccccc} +9 & 12 & 15 & 18 & 3 & 6 & 9 & 12 & 15 & 18 & 3 & 6 & 9 & 12 \\\\ +12 & 16 & 20 & 24 & 4 & 8 & 12 & 16 & 20 & 24 & 4 & 8 & 12 & 16 \\\\ +15 & 20 & 25 & 30 & 5 & 10 & 15 & 20 & 25 & 30 & 5 & 10 & 15 & 20 \\\\ +18 & 24 & 30 & 36 & 6 & 12 & 18 & 24 & 30 & 36 & 6 & 12 & 18 & 24 \\\\ +3 & 4 & 5 & 6 & \\boxed{1} & \\boxed{2} & \\boxed{3} & \\boxed{4} & \\boxed{5} & \\boxed{6} & 1 & 2 & 3 & 4 \\\\ +6 & 8 & 10 & 12 & \\boxed{2} & \\boxed{4} & \\boxed{6} & \\boxed{8} & \\boxed{10} & \\boxed{12} & 2 & 4 & 6 & 8 \\\\ +9 & 12 & 15 & 18 & \\boxed{3} & \\boxed{6} & \\boxed{9} & \\boxed{12} & \\boxed{15} & \\boxed{18} & 3 & 6 & 9 & 12 \\\\ +12 & 16 & 20 & 24 &\\boxed{4} & \\boxed{8} & \\boxed{12} & \\boxed{16} & \\boxed{20} & \\boxed{24} & 4 & 8 & 12 & 16 \\\\ +15 & 20 & 25 & 30 &\\boxed{5} & \\boxed{10} & \\boxed{15} & \\boxed{20} & \\boxed{25} & \\boxed{30} & 5 & 10 & 15 & 20 \\\\ +18 & 24 & 30 & 36 &\\boxed{6} & \\boxed{12} & \\boxed{18} & \\boxed{24} & \\boxed{30} & \\boxed{36} & 6 & 12 & 18 & 24 \\\\ +3 & 4 & 5 & 6 & 1 & 2 & 3 & 4 & 5 & 6 & 1 & 2 & 3 & 4 \\\\ +6 & 8 & 10 & 12 & 2 & 4 & 6 & 8 & 10 & 12 & 2 & 4 & 6 & 8 \\\\ +9 & 12 & 15 & 18 & 3 & 6 & 9 & 12 & 15 & 18 & 3 & 6 & 9 & 12 \\\\ +12 & 16 & 20 & 24 & 4 & 8 & 12 & 16 & 20 & 24 & 4 & 8 & 12 & 16 +\\end{array} +}. +``` +The command `padarray(A, Pad(:symmetric,4,4))` yields +```math +\\boxed{ +\\begin{array}{ccccccccccccc} +16 & 12 & 8 & 4 & 4 & 8 & 12 & 16 & 20 & 24 & 24 & 20 & 16 & 12 \\\\ +12 & 9 & 6 & 3 & 3 & 6 & 9 & 12 & 15 & 18 & 18 & 15 & 12 & 9 \\\\ + 8 & 6 & 4 & 2 & 2 & 4 & 6 & 8 & 10 & 12 & 12 & 10 & 8 & 6 \\\\ + 4 & 3 & 2 & 1 & 1 & 2 & 3 & 4 & 5 & 6 & 6 & 5 & 4 & 3 \\\\ + 4 & 3 & 2 & 1 & \\boxed{1} & \\boxed{2} & \\boxed{3} & \\boxed{4} & \\boxed{5} & \\boxed{6} & 6 & 5 & 4 & 3 \\\\ + 8 & 6 & 4 & 2 & \\boxed{2} & \\boxed{4} & \\boxed{6} & \\boxed{8} & \\boxed{10} & \\boxed{12} & 12 & 10 & 8 & 6 \\\\ +12 & 9 & 6 & 3 & \\boxed{3} & \\boxed{6} & \\boxed{9} & \\boxed{12} & \\boxed{15} & \\boxed{18} & 18 & 15 & 12 & 9 \\\\ +16 & 12 & 8 & 4 & \\boxed{4} & \\boxed{8} & \\boxed{12} & \\boxed{16} & \\boxed{20} & \\boxed{24} & 24 & 20 & 16 & 12 \\\\ +20 & 15 & 10 & 5 & \\boxed{5} & \\boxed{10} & \\boxed{15} & \\boxed{20} & \\boxed{25} & \\boxed{30} & 30 & 25 & 20 & 15 \\\\ +24 & 18 & 12 & 6 & \\boxed{6} & \\boxed{12} & \\boxed{18} & \\boxed{24} & \\boxed{30} & \\boxed{36} & 36 & 30 & 24 & 18 \\\\ +24 & 18 & 12 & 6 & 6 & 12 & 18 & 24 & 30 & 36 & 36 & 30 & 24 & 18 \\\\ +20 & 15 & 10 & 5 & 5 & 10 & 15 & 20 & 25 & 30 & 30 & 25 & 20 & 15 \\\\ +16 & 12 & 8 & 4 & 4 & 8 & 12 & 16 & 20 & 24 & 24 & 20 & 16 & 12 \\\\ +12 & 9 & 6 & 3 & 3 & 6 & 9 & 12 & 15 & 18 & 18 & 15 & 12 & 9 +\\end{array} +}. +``` + +The command `padarray(A, Pad(:reflect,4,4))` yields +```math +\\boxed{ +\\begin{array}{ccccccccccccc} +25 & 20 & 15 & 10 & 5 & 10 & 15 & 20 & 25 & 30 & 25 & 20 & 15 & 10 \\\\ +20 & 16 & 12 & 8 & 4 & 8 & 12 & 16 & 20 & 24 & 20 & 16 & 12 & 8 \\\\ +15 & 12 & 9 & 6 & 3 & 6 & 9 & 12 & 15 & 18 & 15 & 12 & 9 & 6 \\\\ +10 & 8 & 6 & 4 & 2 & 4 & 6 & 8 & 10 & 12 & 10 & 8 & 6 & 4 \\\\ +5 & 4 & 3 & 2 & \\boxed{1} & \\boxed{2} & \\boxed{3} & \\boxed{4} & \\boxed{5} & \\boxed{6} & 5 & 4 & 3 & 2 \\\\ +10 & 8 & 6 & 4 & \\boxed{2} & \\boxed{4} & \\boxed{6} & \\boxed{8} & \\boxed{10} & \\boxed{12} & 10 & 8 & 6 & 4 \\\\ +15 & 12 & 9 & 6 & \\boxed{3} & \\boxed{6} & \\boxed{9} & \\boxed{12} & \\boxed{15} & \\boxed{18} & 15 & 12 & 9 & 6 \\\\ +20 & 16 & 12 & 8 & \\boxed{4} & \\boxed{8} & \\boxed{12} & \\boxed{16} & \\boxed{20} & \\boxed{24} & 20 & 16 & 12 & 8 \\\\ +25 & 20 & 15 & 10 & \\boxed{5} & \\boxed{10} & \\boxed{15} & \\boxed{20} & \\boxed{25} & \\boxed{30} & 25 & 20 & 15 & 10 \\\\ +30 & 24 & 18 & 12 & \\boxed{6} & \\boxed{12} & \\boxed{18} & \\boxed{24} & \\boxed{30} & \\boxed{36} & 30 & 24 & 18 & 12 \\\\ +25 & 20 & 15 & 10 & 5 & 10 & 15 & 20 & 25 & 30 & 25 & 20 & 15 & 10 \\\\ +20 & 16 & 12 & 8 & 4 & 8 & 12 & 16 & 20 & 24 & 20 & 16 & 12 & 8 \\\\ +15 & 12 & 9 & 6 & 3 & 6 & 9 & 12 & 15 & 18 & 15 & 12 & 9 & 6 \\\\ +10 & 8 & 6 & 4 & 2 & 4 & 6 & 8 & 10 & 12 & 10 & 8 & 6 & 4 +\\end{array} +}. +``` +## Examples with `Fill` + +The command `padarray(A, Fill(0,(4,4),(4,4)))` yields +```math +\\boxed{ +\\begin{array}{ccccccccccccc} +0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 \\\\ +0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 \\\\ +0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 \\\\ +0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 \\\\ +0 & 0 & 0 & 0 & \\boxed{1} & \\boxed{2} & \\boxed{3} & \\boxed{4} & \\boxed{5} & \\boxed{6} & 0 & 0 & 0 & 0 \\\\ +0 & 0 & 0 & 0 & \\boxed{2} & \\boxed{4} & \\boxed{6} & \\boxed{8} & \\boxed{10} & \\boxed{12} & 0 & 0 & 0 & 0 \\\\ +0 & 0 & 0 & 0 & \\boxed{3} & \\boxed{6} & \\boxed{9} & \\boxed{12} & \\boxed{15} & \\boxed{18} & 0 & 0 & 0 & 0 \\\\ +0 & 0 & 0 & 0 & \\boxed{4} & \\boxed{8} & \\boxed{12} & \\boxed{16} & \\boxed{20} & \\boxed{24} & 0 & 0 & 0 & 0 \\\\ +0 & 0 & 0 & 0 & \\boxed{5} & \\boxed{10} & \\boxed{15} & \\boxed{20} & \\boxed{25} & \\boxed{30} & 0 & 0 & 0 & 0 \\\\ +0 & 0 & 0 & 0 & \\boxed{6} & \\boxed{12} & \\boxed{18} & \\boxed{24} & \\boxed{30} & \\boxed{36} & 0 & 0 & 0 & 0 \\\\ +0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 \\\\ +0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 \\\\ +0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 \\\\ +0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 +\\end{array} +}. +``` +--- -Optionally provide the element type `T` of `imgpadded`. """ padarray(img::AbstractArray, border::Pad) = padarray(eltype(img), img, border) function padarray(::Type{T}, img::AbstractArray, border::Pad) where T @@ -236,16 +518,52 @@ padarray(::Type{T}, img::AbstractArray{T}, border::Inner) where {T} = copy(img) padarray(::Type{T}, img::AbstractArray, border::Inner) where {T} = copy!(similar(Array{T}, indices(img)), img) """ - Fill(val) - Fill(val, lo, hi) - -Pad the edges of the image with a constant value, `val`. - -Optionally supply the extent of the padding, see `Pad`. - -# Example: +```julia + struct Fill{T,N} <: AbstractBorder + value::T + lo::Dims{N} + hi::Dims{N} + end +``` + +`Fill` is a type that designates a particular value which will be used to +extrapolate pixels beyond the boundary of an image. + +# Output + +The type `Fill` specifying the value with which the boundary of an image should +be padded. + +# Details +When representing a spatial image filtering operation as a discrete convolution +between the image and a ``D \\times D `` filter, the results are undefined for +pixels closer than ``D`` pixels from the border of the image. To define the +operation near and at the border, one needs a scheme for extrapolating pixels +beyond the edge. The `Fill` type allows one to specify a particular value which +will be used in the extrapolation. For more elaborate extrapolation schemes +refer to the documentation of [`Pad`](@ref). + +You can specify a different amount of padding for the top, left, bottom and +right border of an image. + +As an indicative example consider an image consisting of a +row of six pixels which are specified alphabetically: ``\\boxed{a \\, b \\, c \\, +d \\, e \\, f}``. We show the effects of padding with a constant value +``m`` only on the left and right +border, but analogous consequences hold for the top and bottom border. + +```math +\\boxed{ +\\begin{array}{l|c|r} + m\\, m\\, m\\, m & a \\, b \\, c \\, d \\, e \\, f & m \\, m \\, m \\, m +\\end{array} +} +``` +See also: [`Pad`](@ref), [`padarray`](@ref), [`Inner`](@ref) and +[`NoPad`](@ref) + +--- - imfilter(img, kernel, Fill(zero(eltype(img)))) """ struct Fill{T,N} <: AbstractBorder value::T @@ -256,11 +574,108 @@ struct Fill{T,N} <: AbstractBorder Fill{T,N}(value::T, lo::Dims{N}, hi::Dims{N}) where {T,N} = new{T,N}(value, lo, hi) end +""" +```julia +Fill(value::T) +``` + +Construct an instance of [`Fill`](@ref) designating a `value` and zero padding (i.e. no padding). + +--- + +""" Fill(value::T) where {T} = Fill{T,0}(value) + +""" +```julia + Fill(value::T, lo::Dims{N}, hi::Dims{N}) +``` +Construct an instance of [`Fill`](@ref) designating a `value` and tuples +`lo` and `hi` which stipulate the number of row and columns which will be predended +and appended to the image. + +The tuple `lo` specifies how many row and columns to prepend the +image with—the padding for the top and left border. The tuple `hi` specifies +how many pixels to append the image with—the padding for the bottom and right +border. + +#### Usage illustration +Use `Fill(5,(2,2),(2,2))` to specify a padding of two pixels for the top, +bottom, left and right edge with the value five. + + +Use `Fill(zero(eltype(img))(1,2),(3,4))` to specify a padding of one, two, three +and four pixels for the top, left, bottom and right edge respectively using a +value of zero with the same type as `img`. + + +--- + +""" Fill(value::T, lo::Dims{N}, hi::Dims{N}) where {T,N} = Fill{T,N}(value, lo, hi) + +""" +```julia + Fill(value::T, both::Dims{N}) +``` +Construct an instance of [`Fill`](@ref) designating a `value` and a tuple +`both` which stipulate the number of row and columns which will be prepended +and appended to the image. + +#### Usage illustration +Use `Fill(0,(5,10))` to stipulate a padding of five pixels for the top and left +edge, and a padding of ten pixels for the bottom and right edge with a value of +zero. + + +--- + +""" Fill(value::T, both::Dims{N}) where {T,N} = Fill{T,N}(value, both, both) + +""" +```julia + Fill(value, lo::AbstractVector, hi::AbstractVector) +``` +Construct an instance of [`Fill`](@ref) designating a `value` and vectors +`lo` and `hi` which stipulate the number of row and columns which will be prepended +and appended to the image. + +The tuple `lo` specifies how many row and columns to prepend the +image with—the padding for the top and left border. The tuple `hi` specifies +how many pixels to append the image with—the padding for the bottom and right +border. + +#### Usage illustration +Use `Fill(0,[1,2],[3,4]` to specify a padding of one, two, three and four pixels +for the top, left, bottom and right edge respectively with the value zero. + + +--- + +""" Fill(value, lo::AbstractVector, hi::AbstractVector) = Fill(value, (lo...,), (hi...,)) Fill(value::T, inds::Base.Indices{N}) where {T,N} = Fill{T,N}(value, map(lo,inds), map(hi,inds)) + +""" +```julia + Fill(value, kernel) +``` +Construct an instance of [`Fill`](@ref) by designating a `value` and a +`kernel` which will be used to infer an appropriate padding. + +A minimal amount of padding is added which ensures that a convolution between the image +and the kernel is defined at the boundary. + +#### Usage illustration +Use `Fill(0,Kernel.sobel())` to specify a value of zero and the minimal amount +of padding necessary to ensure that convolution with [`Kernel.sobel`](@ref) will +be defined at the borders of an image. + + +--- + +""" Fill(value, kernel) = Fill(value, calculate_padding(kernel)) (p::Fill)(kernel) = Fill(p.value, kernel)