From 502d6a526854e3f40f4e43ab2e2b1b63fddfa837 Mon Sep 17 00:00:00 2001 From: Kesler <4ck@mac101489.ornl.gov> Date: Mon, 3 Jun 2019 12:46:13 -0400 Subject: [PATCH 01/11] Added checkbounds() testing to all draw!() functions as to not throw errors when shapes which are partially in the images are attempted to be drawn. --- src/core.jl | 22 +++++++++++++++++++--- src/cross.jl | 4 ++-- src/ellipse2d.jl | 8 ++++---- src/line2d.jl | 14 +++++++------- src/paths.jl | 35 ++++++++++++++++++++++------------- 5 files changed, 54 insertions(+), 29 deletions(-) diff --git a/src/core.jl b/src/core.jl index 7115383..4fa1ff6 100644 --- a/src/core.jl +++ b/src/core.jl @@ -182,8 +182,24 @@ Point(τ::Tuple{Int, Int}) = Point(τ...) Point(p::CartesianIndex) = Point(p[2], p[1]) function draw!(img::AbstractArray{T,2}, point::Point, color::T) where T<:Colorant - if checkbounds(Bool, img, point.y, point.x) - img[point.y, point.x] = color - end + drawifinbounds!(img, point, color) +end + +""" + + img_new = drawifinbounds!(img, y, x, color) + img_new = drawifinbounds!(img, Point, color) + img_new = drawifinbounds!(img, CartesianIndex, color) + +Draws a single point after checkbounds() for coordinate in the image. +Color Defaults to oneunit(T) + +""" + +drawifinbounds!(img::AbstractArray{T,2}, p::Point, color::T = oneunit(T)) where {T<:Colorant} = drawifinbounds!(img, p.y, p.x, color) +drawifinbounds!(img::AbstractArray{T,2}, p::CartesianIndex{2}, color::T = oneunit(T)) where {T<:Colorant} = drawifinbounds!(img, Point(p), color) + +function drawifinbounds!(img::AbstractArray{T,2}, y::Int, x::Int, color::T) where {T<:Colorant} + if checkbounds(Bool, img, y, x) img[y, x] = color end img end diff --git a/src/cross.jl b/src/cross.jl index ae9c9d6..cbf070a 100644 --- a/src/cross.jl +++ b/src/cross.jl @@ -6,10 +6,10 @@ Cross(c, arm::Int) = Cross(c, -arm:arm) function draw!(img::AbstractArray{T, 2}, cross::Cross, color::T) where T<:Colorant for Δx in cross.range - img[cross.c.y, cross.c.x + Δx] = color + drawifinbounds!(img, cross.c.y, cross.c.x + Δx, color) end for Δy in cross.range - img[cross.c.y + Δy, cross.c.x] = color + drawifinbounds!(img, cross.c.y + Δy, cross.c.x, color) end img end diff --git a/src/ellipse2d.jl b/src/ellipse2d.jl index 85bb407..9a166df 100644 --- a/src/ellipse2d.jl +++ b/src/ellipse2d.jl @@ -17,10 +17,10 @@ function draw!(img::AbstractArray{T, 2}, ellipse::Ellipse, color::T) where T<:Co end end for (yi, xi) in zip(ys, xs) - img[yi, xi] = color - img[2 * ellipse.center.y - yi, xi] = color - img[yi, 2 * ellipse.center.x - xi] = color - img[2 * ellipse.center.y - yi, 2 * ellipse.center.x - xi] = color + drawifinbounds!(img, yi, xi, color) + drawifinbounds!(img,2 * ellipse.center.y - yi, xi, color) + drawifinbounds!(img,yi, 2 * ellipse.center.x - xi, color) + drawifinbounds!(img, 2 * ellipse.center.y - yi, 2 * ellipse.center.x - xi, color) end img end diff --git a/src/line2d.jl b/src/line2d.jl index dd0781d..5689e7e 100644 --- a/src/line2d.jl +++ b/src/line2d.jl @@ -79,7 +79,7 @@ function bresenham(img::AbstractArray{T, 2}, y0::Int, x0::Int, y1::Int, x1::Int, err = (dx > dy ? dx : -dy) / 2 while true - img[y0, x0] = color + drawifinbounds!(img, y0, x0, color) (x0 != x1 || y0 != y1) || break e2 = err if e2 > -dx @@ -125,9 +125,9 @@ function xiaolin_wu(img::AbstractArray{T, 2}, y0::Int, x0::Int, y1::Int, x1::Int xpxl0 = xend ypxl0 = trunc(Int, yend) index = swapped ? CartesianIndex(xpxl0, ypxl0) : CartesianIndex(ypxl0, xpxl0) - if checkbounds(Bool, img, index) img[index] = T(rfpart(yend) * xgap) end + drawifinbounds!(img, index, T(rfpart(yend) * xgap)) index = swapped ? CartesianIndex(xpxl0, ypxl0 + 1) : CartesianIndex(ypxl0 + 1, xpxl0) - if checkbounds(Bool, img, index) img[index] = T(fpart(yend) * xgap) end + drawifinbounds!(img, index, T(fpart(yend) * xgap)) intery = yend + gradient xend = round(Int, x1) @@ -136,15 +136,15 @@ function xiaolin_wu(img::AbstractArray{T, 2}, y0::Int, x0::Int, y1::Int, x1::Int xpxl1 = xend ypxl1 = trunc(Int, yend) index = swapped ? CartesianIndex(xpxl1, ypxl1) : CartesianIndex(ypxl1, xpxl1) - if checkbounds(Bool, img, index) img[index] = T(rfpart(yend) * xgap) end + drawifinbounds!(img, index, T(rfpart(yend) * xgap)) index = swapped ? CartesianIndex(xpxl1, ypxl1 + 1) : CartesianIndex(ypxl1 + 1, xpxl1) - if checkbounds(Bool, img, index) img[index] = T(fpart(yend) * xgap) end + drawifinbounds!(img, index, T(fpart(yend) * xgap)) for i in (xpxl0 + 1):(xpxl1 - 1) index = swapped ? CartesianIndex(i, trunc(Int, intery)) : CartesianIndex(trunc(Int, intery), i) - if checkbounds(Bool, img, index) img[index] = T(rfpart(intery)) end + drawifinbounds!(img, index, T(rfpart(intery))) index = swapped ? CartesianIndex(i, trunc(Int, intery) + 1) : CartesianIndex(trunc(Int, intery) + 1, i) - if checkbounds(Bool, img, index) img[index] = T(fpart(intery)) end + drawifinbounds!(img, index, T(fpart(intery))) intery += gradient end img diff --git a/src/paths.jl b/src/paths.jl index b880ab7..3221b65 100644 --- a/src/paths.jl +++ b/src/paths.jl @@ -5,22 +5,31 @@ Path(v::AbstractVector{CartesianIndex{2}}) = Path([Point(p) for p in v]) function draw!(img::AbstractArray{T, 2}, path::Path, color::T) where T<:Colorant vertices = [CartesianIndex(p.y, p.x) for p in path.vertices] - f = CartesianIndex(map(r->first(r)-1, axes(img))) - l = CartesianIndex(map(r->last(r), axes(img))) - - if min(f,vertices[1])!=f || max(l,vertices[1])!=l - println(vertices[1]) - error("Point coordinates out of range.") - end for i in 1:length(vertices)-1 - if min(f,vertices[i+1])==f && max(l,vertices[i+1])==l - draw!(img, LineSegment(vertices[i], vertices[i+1]), color) - else - println(vertices[i+1]) - error("Point coordinates out of range.") - end + draw!(img, LineSegment(vertices[i], vertices[i+1]), color) end + + # No need for corrdinate checking at this level as draw!(::LineSegment, ...) + # checks and only draws pixels which are on the image + + # f = CartesianIndex(map(r->first(r)-1, axes(img))) + # l = CartesianIndex(map(r->last(r), axes(img))) + + # if min(f,vertices[1])!=f || max(l,vertices[1])!=l + # println(vertices[1]) + # error("Point coordinates out of range.") + # end + # + # for i in 1:length(vertices)-1 + # if min(f,vertices[i+1])==f && max(l,vertices[i+1])==l + # draw!(img, LineSegment(vertices[i], vertices[i+1]), color) + # else + # println(vertices[i+1]) + # error("Point coordinates out of range.") + # end + # end + end #Polygon methods From 40bda8017c57da5330cd7d40c1e83e11750e85cb Mon Sep 17 00:00:00 2001 From: Kesler <4ck@mac101489.ornl.gov> Date: Mon, 3 Jun 2019 15:42:42 -0400 Subject: [PATCH 02/11] Changed Test Files to no longer check for Exception thrown for drawing paths that went 'off image' --- src/paths.jl | 57 +++++++++++++++++++++++++++------------------------ test/paths.jl | 12 ++++++----- 2 files changed, 37 insertions(+), 32 deletions(-) diff --git a/src/paths.jl b/src/paths.jl index 3221b65..6c9de5f 100644 --- a/src/paths.jl +++ b/src/paths.jl @@ -4,33 +4,36 @@ Path(v::AbstractVector{Tuple{Int, Int}}) = Path([Point(p...) for p in v]) Path(v::AbstractVector{CartesianIndex{2}}) = Path([Point(p) for p in v]) function draw!(img::AbstractArray{T, 2}, path::Path, color::T) where T<:Colorant - vertices = [CartesianIndex(p.y, p.x) for p in path.vertices] - - for i in 1:length(vertices)-1 - draw!(img, LineSegment(vertices[i], vertices[i+1]), color) - end - - # No need for corrdinate checking at this level as draw!(::LineSegment, ...) - # checks and only draws pixels which are on the image - - # f = CartesianIndex(map(r->first(r)-1, axes(img))) - # l = CartesianIndex(map(r->last(r), axes(img))) - - # if min(f,vertices[1])!=f || max(l,vertices[1])!=l - # println(vertices[1]) - # error("Point coordinates out of range.") - # end - # - # for i in 1:length(vertices)-1 - # if min(f,vertices[i+1])==f && max(l,vertices[i+1])==l - # draw!(img, LineSegment(vertices[i], vertices[i+1]), color) - # else - # println(vertices[i+1]) - # error("Point coordinates out of range.") - # end - # end - -end + vertices = [CartesianIndex(p.y, p.x) for p in path.vertices] + f = CartesianIndex(map(r->first(r)-1, axes(img))) + l = CartesianIndex(map(r->last(r), axes(img))) + + for i in 1:length(vertices)-1 + draw!(img, LineSegment(vertices[i], vertices[i+1]), color) + end + + img + # No need for corrdinate checking at this level as draw!(::LineSegment, ...) + # checks and only draws pixels which are on the image + + # f = CartesianIndex(map(r->first(r)-1, axes(img))) + # l = CartesianIndex(map(r->last(r), axes(img))) + + # if min(f,vertices[1])!=f || max(l,vertices[1])!=l + # println(vertices[1]) + # error("Point coordinates out of range.") + # end + # + # for i in 1:length(vertices)-1 + # if min(f,vertices[i+1])==f && max(l,vertices[i+1])==l + # draw!(img, LineSegment(vertices[i], vertices[i+1]), color) + # else + # println(vertices[i+1]) + # error("Point coordinates out of range.") + # end + # end + + end #Polygon methods diff --git a/test/paths.jl b/test/paths.jl index fa5cf8e..6488b3e 100644 --- a/test/paths.jl +++ b/test/paths.jl @@ -65,12 +65,14 @@ end @test all(x->x==RGB{N0f8}(0,0,0), img[2,1:3])==true @test img[2,4]==RGB{N0f8}(1,1,1) - img = zeros(Gray{N0f8},5,5) - invalid_points = [(6,1), (4,4), (1,7), (7,6)] - @test_throws ErrorException draw!(img, Path(invalid_points)) + # No longer invalid, the program will draw what it can on the image - invalid_points = [(4,4), (1,7), (7,6)] - @test_throws ErrorException draw!(img, Path(invalid_points)) + # img = zeros(Gray{N0f8},5,5) + # invalid_points = [(6,1), (4,4), (1,7), (7,6)] + # @test_throws ErrorException draw!(img, Path(invalid_points)) + # + # invalid_points = [(4,4), (1,7), (7,6)] + # @test_throws ErrorException draw!(img, Path(invalid_points)) end @testset "RegularPolygon" begin From de360830a92e7b9532f2c3e1199d2d0a8fa320b9 Mon Sep 17 00:00:00 2001 From: Kesler <4ck@mac101489.ornl.gov> Date: Tue, 4 Jun 2019 10:30:49 -0400 Subject: [PATCH 03/11] Fixed spacing and deleted unnecessary code --- src/paths.jl | 36 ++++++------------------------------ 1 file changed, 6 insertions(+), 30 deletions(-) diff --git a/src/paths.jl b/src/paths.jl index 6c9de5f..02bcd8b 100644 --- a/src/paths.jl +++ b/src/paths.jl @@ -4,36 +4,12 @@ Path(v::AbstractVector{Tuple{Int, Int}}) = Path([Point(p...) for p in v]) Path(v::AbstractVector{CartesianIndex{2}}) = Path([Point(p) for p in v]) function draw!(img::AbstractArray{T, 2}, path::Path, color::T) where T<:Colorant - vertices = [CartesianIndex(p.y, p.x) for p in path.vertices] - f = CartesianIndex(map(r->first(r)-1, axes(img))) - l = CartesianIndex(map(r->last(r), axes(img))) - - for i in 1:length(vertices)-1 - draw!(img, LineSegment(vertices[i], vertices[i+1]), color) - end - - img - # No need for corrdinate checking at this level as draw!(::LineSegment, ...) - # checks and only draws pixels which are on the image - - # f = CartesianIndex(map(r->first(r)-1, axes(img))) - # l = CartesianIndex(map(r->last(r), axes(img))) - - # if min(f,vertices[1])!=f || max(l,vertices[1])!=l - # println(vertices[1]) - # error("Point coordinates out of range.") - # end - # - # for i in 1:length(vertices)-1 - # if min(f,vertices[i+1])==f && max(l,vertices[i+1])==l - # draw!(img, LineSegment(vertices[i], vertices[i+1]), color) - # else - # println(vertices[i+1]) - # error("Point coordinates out of range.") - # end - # end - - end + vertices = [CartesianIndex(p.y, p.x) for p in path.vertices] + for i in 1:length(vertices)-1 + draw!(img, LineSegment(vertices[i], vertices[i+1]), color) + end + img +end #Polygon methods From d84042d58b2c36ce2030e9e76793d44a79f4f7c3 Mon Sep 17 00:00:00 2001 From: Kesler <4ck@mac101489.ornl.gov> Date: Tue, 25 Jun 2019 13:28:08 -0400 Subject: [PATCH 04/11] Fix --- Project.toml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Project.toml b/Project.toml index dac0219..2af7de4 100644 --- a/Project.toml +++ b/Project.toml @@ -1,11 +1,10 @@ name = "ImageDraw" uuid = "4381153b-2b60-58ae-a1ba-fd683676385f" -version = "0.2.2" +version = "0.2.1" [deps] Distances = "b4f34e82-e78d-54a5-968a-f98e89d6e8f7" ImageCore = "a09fc81d-aa75-5fe9-8630-4744c3626534" -LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e" [compat] Distances = ">= 0.1.0" From 108996cf84a46d05fc5789bed49bf5445f828e5b Mon Sep 17 00:00:00 2001 From: Kesler <4ck@mac101489.ornl.gov> Date: Tue, 25 Jun 2019 15:49:41 -0400 Subject: [PATCH 05/11] Added ability to draw lines with thickness --- .DS_Store | Bin 0 -> 6148 bytes Project.toml | 2 ++ src/ImageDraw.jl | 2 +- src/core.jl | 63 ++++++++++++++++++++++++++++++++++++----------- src/cross.jl | 6 ++--- src/line2d.jl | 31 +++++++++++++---------- src/paths.jl | 14 +++++------ 7 files changed, 79 insertions(+), 39 deletions(-) create mode 100644 .DS_Store diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..6f37de5da342fa7594f7484009ffd833cdb2d0d9 GIT binary patch literal 6148 zcmeHK%Wl&^6ur|JuuUtnKq~CKL1GbAiD-!ss+6YbA`+kqBUk`x?Kn_ZjwgzpMr{c4 zhCNFJU%;>M1AGV{0B0Vc)F~{h2+fV|oI5l3cxH~}nG6xJ_Bd(~Rf))k3$$Dm7ntZ5 zzF;f5#Q`$;j6R(brx9%cjTr@u0?V#|_;yz*pdo%IH2?h$DCs7=7bZMJj@Td`!tef+ zhKR_eN7SWV+M_4rquihYMJ3MH5@(GbW3-fFdV|q2%E8L9XDp1y)=SJ)+Q-hq=@`7; zKX@NXJcpiQZadV$$QRC${U|XinAeDUrIl*L(&byhgZhFYU<;V_A_yk7s#Rw~w& ztJiGXwcR!MwSUAXejeoGtR0MAirRjVAB8%8#(DB54#MYge{xX0xy#c$h|~T^lH;h4 zlvgj}G~$ysAE!|!pW~|z+jeZ{pn7{c-E3~vyheTN!K~&@o6UO7+q`#wHgoLtJB{t` z;o$Ua`fm3AGu8rQ*tMnI(D)m^AkgbO@keRG)3<05*%p+S@2#Ycc+a2a)IrtQk}II! zzI}bk=V_*A6fg>0z5-%@@ZbVl8ViMT>p&r|06+`P(h!Tk3WDQlY-ubMq6fwl6{x68 zUon`XqutYaEscdjMJJ{&A54$T^bLi{(eZpwrW0!^G^J6%C~#hZimFz{`M>w~`~P{8 zsTl=~0{@i)% 0 - method(img, round(Int,valid_intersections[1][2]), round(Int,valid_intersections[1][1]), round(Int,valid_intersections[2][2]), round(Int,valid_intersections[2][1]), color) + method(img, round(Int,valid_intersections[1][2]), round(Int,valid_intersections[1][1]), round(Int,valid_intersections[2][2]), round(Int,valid_intersections[2][1]), color, thickness) else img end @@ -40,9 +42,9 @@ end LineNormal(τ::Tuple{T,U}) where {T<:Real, U<:Real} = LineNormal(τ...) draw!(img::AbstractArray{T,2}, line::LineNormal, method::Function = bresenham) where {T<:Colorant} = - draw!(img, line, oneunit(T), method) + draw!(img, line, oneunit(T), 1, method) -function draw!(img::AbstractArray{T, 2}, line::LineNormal, color::T, method::Function = bresenham) where T<:Colorant +function draw!(img::AbstractArray{T, 2}, line::LineNormal, color::T, thickness::Int=1, method::Function = bresenham) where T<:Colorant indsy, indsx = axes(img) cosθ = cos(line.θ) sinθ = sin(line.θ) @@ -50,7 +52,7 @@ function draw!(img::AbstractArray{T, 2}, line::LineNormal, color::T, method::Fun intersections_y = [((line.ρ - y*sinθ)/cosθ, y) for y in (first(indsy), last(indsy))] valid_intersections = get_valid_intersections(vcat(intersections_x, intersections_y), indsx, indsy) if length(valid_intersections) > 0 - method(img, round(Int,valid_intersections[1][2]), round(Int,valid_intersections[1][1]), round(Int,valid_intersections[2][2]), round(Int,valid_intersections[2][1]), color) + method(img, round(Int,valid_intersections[1][2]), round(Int,valid_intersections[1][1]), round(Int,valid_intersections[2][2]), round(Int,valid_intersections[2][1]), color, thickness) else img end @@ -62,14 +64,16 @@ LineSegment(x0::Int, y0::Int, x1::Int, y1::Int) = LineSegment(Point(x0, y0), Poi LineSegment(p1::CartesianIndex, p2::CartesianIndex) = LineSegment(Point(p1), Point(p2)) draw!(img::AbstractArray{T,2}, line::LineSegment, method::Function = bresenham) where {T<:Colorant} = - draw!(img, line, oneunit(T), method) + draw!(img, line, oneunit(T), 1, method) draw!(img::AbstractArray{T,2}, line::LineSegment, color::T, method::Function = bresenham) where {T<:Colorant} = - method(img, line.p1.y, line.p1.x, line.p2.y, line.p2.x, color) + draw!(img, line, color, 1, method) -# Methods to draw lines +draw!(img::AbstractArray{T,2}, line::LineSegment, color::T, thickness::Int, method::Function = bresenham) where {T<:Colorant} = + method(img, line.p1.y, line.p1.x, line.p2.y, line.p2.x, color, thickness) -function bresenham(img::AbstractArray{T, 2}, y0::Int, x0::Int, y1::Int, x1::Int, color::T) where T<:Colorant +# Methods to draw lines +function bresenham(img::AbstractArray{T, 2}, y0::Int, x0::Int, y1::Int, x1::Int, color::T, thickness::Int=1) where T<:Colorant dx = abs(x1 - x0) dy = abs(y1 - y0) @@ -79,7 +83,7 @@ function bresenham(img::AbstractArray{T, 2}, y0::Int, x0::Int, y1::Int, x1::Int, err = (dx > dy ? dx : -dy) / 2 while true - drawifinbounds!(img, y0, x0, color) + drawwiththickness!(img, y0, x0, color, thickness) (x0 != x1 || y0 != y1) || break e2 = err if e2 > -dx @@ -95,6 +99,7 @@ function bresenham(img::AbstractArray{T, 2}, y0::Int, x0::Int, y1::Int, x1::Int, img end + fpart(pixel::T) where {T} = pixel - T(trunc(pixel)) rfpart(pixel::T) where {T} = oneunit(T) - fpart(pixel) @@ -102,7 +107,7 @@ function swap(x, y) y, x end -function xiaolin_wu(img::AbstractArray{T, 2}, y0::Int, x0::Int, y1::Int, x1::Int, color::T) where T<:Gray +function xiaolin_wu(img::AbstractArray{T, 2}, y0::Int, x0::Int, y1::Int, x1::Int, color::T, thickness::Int=1) where T<:Gray dx = x1 - x0 dy = y1 - y0 diff --git a/src/paths.jl b/src/paths.jl index 02bcd8b..d8eb5f5 100644 --- a/src/paths.jl +++ b/src/paths.jl @@ -3,10 +3,10 @@ Path(v::AbstractVector{Tuple{Int, Int}}) = Path([Point(p...) for p in v]) Path(v::AbstractVector{CartesianIndex{2}}) = Path([Point(p) for p in v]) -function draw!(img::AbstractArray{T, 2}, path::Path, color::T) where T<:Colorant +function draw!(img::AbstractArray{T, 2}, path::Path, color::T, thickness::Int=1) where T<:Colorant vertices = [CartesianIndex(p.y, p.x) for p in path.vertices] for i in 1:length(vertices)-1 - draw!(img, LineSegment(vertices[i], vertices[i+1]), color) + draw!(img, LineSegment(vertices[i], vertices[i+1]), color, thickness) end img end @@ -16,9 +16,9 @@ end Polygon(v::AbstractVector{Tuple{Int, Int}}) = Polygon([Point(p...) for p in v]) Polygon(v::AbstractVector{CartesianIndex{2}}) = Polygon([Point(p) for p in v]) -function draw!(img::AbstractArray{T, 2}, polygon::Polygon, color::T) where T<:Colorant - draw!(img, Path(polygon.vertices), color) - draw!(img, LineSegment(first(polygon.vertices), last(polygon.vertices)), color) +function draw!(img::AbstractArray{T, 2}, polygon::Polygon, color::T, thickness::Int=1) where T<:Colorant + draw!(img, Path(polygon.vertices), color, thickness) + draw!(img, LineSegment(first(polygon.vertices), last(polygon.vertices)), color, thickness) end #RegularPolygon methods @@ -26,9 +26,9 @@ end RegularPolygon(point::CartesianIndex{2}, side_count::Int, side_length::T, θ::U) where {T<:Real, U<:Real} = RegularPolygon(Point(point), side_count, side_length, θ) -function draw!(img::AbstractArray{T, 2}, rp::RegularPolygon, color::T) where T<:Colorant +function draw!(img::AbstractArray{T, 2}, rp::RegularPolygon, color::T, thickness::Int=1) where T<:Colorant n = rp.side_count ρ = rp.side_length/(2*sin(π/n)) polygon = Polygon([ Point(round(Int, rp.center.x + ρ*cos(rp.θ + 2π*k/n)), round(Int, rp.center.y + ρ*sin(rp.θ + 2π*k/n))) for k in 1:n ]) - draw!(img, polygon, color) + draw!(img, polygon, color, thickness) end From f0b0b3bbbcb09b133f16fd48cf3ff2f31bb1f844 Mon Sep 17 00:00:00 2001 From: Codyk12 Date: Tue, 25 Jun 2019 15:53:35 -0400 Subject: [PATCH 06/11] Updated Version Number --- Project.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Project.toml b/Project.toml index 41b0d1f..3ee752a 100644 --- a/Project.toml +++ b/Project.toml @@ -1,6 +1,6 @@ name = "ImageDraw" uuid = "4381153b-2b60-58ae-a1ba-fd683676385f" -version = "0.2.1" +version = "0.2.3" [deps] Combinatorics = "861a8166-3701-5b0c-9a16-15d98fcdc6aa" From 1fb3dd02a4309c6ad387d88ee6bdaff17615fcfd Mon Sep 17 00:00:00 2001 From: Codyk12 Date: Fri, 28 Jun 2019 12:07:26 -0400 Subject: [PATCH 07/11] Added ability to create a solid background with given type, or striped background with a given number and colors --- src/ImageDraw.jl | 6 +++++ src/background.jl | 64 ++++++++++++++++++++++++++++++++++++++++++++++ src/core.jl | 26 +++++++++++++++++++ test/background.jl | 54 ++++++++++++++++++++++++++++++++++++++ test/runtests.jl | 3 ++- 5 files changed, 152 insertions(+), 1 deletion(-) create mode 100644 src/background.jl create mode 100644 test/background.jl diff --git a/src/ImageDraw.jl b/src/ImageDraw.jl index 4fb8ec1..822c4ac 100644 --- a/src/ImageDraw.jl +++ b/src/ImageDraw.jl @@ -9,11 +9,13 @@ include("ellipse2d.jl") include("circle2d.jl") include("paths.jl") include("cross.jl") +include("background.jl") #export methods export draw, draw!, + generatecanvas, bresenham, xiaolin_wu @@ -22,6 +24,10 @@ export #Drawable Drawable, + #backgrounds + SolidBackground, + StripedBackground, + #Point Point, diff --git a/src/background.jl b/src/background.jl new file mode 100644 index 0000000..b85d3e2 --- /dev/null +++ b/src/background.jl @@ -0,0 +1,64 @@ +""" + gen_img = generatecanvas(colortype, x, y) + gen_img = generatecanvas(colortype, x, y, background) + gen_img = generatecanvas(colortype, [x,y]) + gen_img = generatecanvas(colortype, [x,y], background) + + Creates an image of with the given colortype and size. + Defaults to a black solid image +""" +generatecanvas(colortype::Type, x::Int, y::Int) = zeros(colortype, (x,y)) + +generatecanvas(colortype::Type, size::Vector{Int}) = zeros(colortype, (size...)) + +generatecanvas(colortype::Type, x::Int, y::Int, b::AbstractBackground) = + generatecanvas(colortype, [x,y], b) + +function generatecanvas(colortype::Type, size::Vector{Int}, b::AbstractBackground) + draw!(zeros(colortype, (size...)), b) +end + + +""" + new_img = draw!(img, solid_background) + + Paints the entire given image a solid color +""" +function draw!(img::AbstractArray{T,2}, b::SolidBackground) where {T<:Colorant} + b.color == zero(typeof(b.color)) ? (return img) : nothing + x, y = size(img) + for i = 1:y + for j = 1:x + draw!(img, Point(j, i), b.color) + end + end + img +end + +""" + new_img = draw!(img, striped_background) + + Layers colors onto a given image to set a "background" +""" +function draw!(img::AbstractArray{T,2}, b::StripedBackground) where {T<:Colorant} + x,y = size(img) + for (e,(c,d)) in enumerate(zip(b.colors,b.distances)) + draw!(img, LineNormal(d,b.θ), c) + for i = 1:y + cnt = 0 + for j = 1:x + if img[i,j] == zero(typeof(c)) + draw!(img, Point(j,i), c) + cnt += 1 + elseif img[i,j] == c + break + elseif img[i,j] in b.colors[1:e-1] + cnt = 1 + continue + end + end + cnt == 0 ? break : continue + end + end + img +end diff --git a/src/core.jl b/src/core.jl index fba4bf9..45a6ced 100644 --- a/src/core.jl +++ b/src/core.jl @@ -17,11 +17,37 @@ end abstract type AbstractPath <: Drawable end abstract type AbstractLine <: Drawable end abstract type AbstractShape <: Drawable end +abstract type AbstractBackground <: Drawable end + abstract type AbstractPolygon <: AbstractShape end abstract type AbstractEllipse <: AbstractShape end abstract type AbstractCircle <: AbstractEllipse end +""" + background = SolidBackground(color) + +A `Drawable` background that will fill the 'background' of an image with +the set color +""" + +struct SolidBackground{T<:Colorant} <: AbstractBackground + color::T +end + +""" + background = StripedBackground(color) + +A `Drawable` background that will fill the 'background' of an image with +the given colors at the intervals given at the given angle +""" + +struct StripedBackground{T<:Colorant, U<:Real, V<:Real} <: AbstractBackground + colors::Vector{T} + distances::Vector{U} + θ::V +end + """ line = LineTwoPoints(p1, p2) diff --git a/test/background.jl b/test/background.jl new file mode 100644 index 0000000..811a14f --- /dev/null +++ b/test/background.jl @@ -0,0 +1,54 @@ + +@testset "Background" begin + @testset "SolidBackground" begin + + res = generatecanvas(Gray{N0f8}, 10,10) + expected = zeros(Gray{N0f8}, (10,10)) + + @test all(expected .== res) == true + + res = generatecanvas(Gray{N0f8}, 10,10, SolidBackground(Gray{N0f8}(1.0))) + expected = ones(Gray{N0f8}, (10,10)) + + @test all(expected .== res) == true + + + end + + @testset "StripedBackground" begin + + res = generatecanvas(Gray{N0f8}, [10,10], StripedBackground([Gray{N0f8}(1.0),Gray{N0f8}(.5), Gray{N0f8}(.2)], [2, 5, 8], pi/2)) + expected = Gray{N0f8}[ 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 + 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 + 0.502 0.502 0.502 0.502 0.502 0.502 0.502 0.502 0.502 0.502 + 0.502 0.502 0.502 0.502 0.502 0.502 0.502 0.502 0.502 0.502 + 0.502 0.502 0.502 0.502 0.502 0.502 0.502 0.502 0.502 0.502 + 0.2 0.2 0.2 0.2 0.2 0.2 0.2 0.2 0.2 0.2 + 0.2 0.2 0.2 0.2 0.2 0.2 0.2 0.2 0.2 0.2 + 0.2 0.2 0.2 0.2 0.2 0.2 0.2 0.2 0.2 0.2 + 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 ] + + @test all(expected .== res) == true + + res = generatecanvas(RGB, [5,5], StripedBackground([RGB(.3,.6,.7),RGB(.5,.2,.9)], [2, 4], 0)) + expected = RGB[ RGB(.3,.6,.7) RGB(.3,.6,.7) RGB(.5,.2,.9) RGB(.5,.2,.9) RGB(0,0,0) + RGB(.3,.6,.7) RGB(.3,.6,.7) RGB(.5,.2,.9) RGB(.5,.2,.9) RGB(0,0,0) + RGB(.3,.6,.7) RGB(.3,.6,.7) RGB(.5,.2,.9) RGB(.5,.2,.9) RGB(0,0,0) + RGB(.3,.6,.7) RGB(.3,.6,.7) RGB(.5,.2,.9) RGB(.5,.2,.9) RGB(0,0,0) + RGB(.3,.6,.7) RGB(.3,.6,.7) RGB(.5,.2,.9) RGB(.5,.2,.9) RGB(0,0,0) ] + + @test all(expected .== res) == true + + res = generatecanvas(RGB, [5,5], StripedBackground([RGB(.3,.6,.7),RGB(.5,.2,.9)], [2, 4], pi/4)) + expected = RGB[ RGB(.3,.6,.7) RGB(.3,.6,.7) RGB(.5,.2,.9) RGB(.5,.2,.9) RGB(.5,.2,.9) + RGB(.3,.6,.7) RGB(.5,.2,.9) RGB(.5,.2,.9) RGB(.5,.2,.9) RGB(0,0,0) + RGB(.5,.2,.9) RGB(.5,.2,.9) RGB(.5,.2,.9) RGB(0,0,0) RGB(0,0,0) + RGB(.5,.2,.9) RGB(.5,.2,.9) RGB(0,0,0) RGB(0,0,0) RGB(0,0,0) + RGB(.5,.2,.9) RGB(0,0,0) RGB(0,0,0) RGB(0,0,0) RGB(0,0,0) ] + + @test all(expected .== res) == true + + end + +end diff --git a/test/runtests.jl b/test/runtests.jl index 5aaca03..7ac4531 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -9,7 +9,8 @@ tests = [ "ellipse2d.jl", "circle2d.jl", "paths.jl", - "cross.jl" + "cross.jl", + "background.jl" ] for t in tests From 32ca23902b3f68b8e5a27ba722760c12ae99c7cb Mon Sep 17 00:00:00 2001 From: Codyk12 Date: Fri, 28 Jun 2019 12:10:56 -0400 Subject: [PATCH 08/11] Deleted ds_store --- .DS_Store | Bin 6148 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 .DS_Store diff --git a/.DS_Store b/.DS_Store deleted file mode 100644 index 6f37de5da342fa7594f7484009ffd833cdb2d0d9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6148 zcmeHK%Wl&^6ur|JuuUtnKq~CKL1GbAiD-!ss+6YbA`+kqBUk`x?Kn_ZjwgzpMr{c4 zhCNFJU%;>M1AGV{0B0Vc)F~{h2+fV|oI5l3cxH~}nG6xJ_Bd(~Rf))k3$$Dm7ntZ5 zzF;f5#Q`$;j6R(brx9%cjTr@u0?V#|_;yz*pdo%IH2?h$DCs7=7bZMJj@Td`!tef+ zhKR_eN7SWV+M_4rquihYMJ3MH5@(GbW3-fFdV|q2%E8L9XDp1y)=SJ)+Q-hq=@`7; zKX@NXJcpiQZadV$$QRC${U|XinAeDUrIl*L(&byhgZhFYU<;V_A_yk7s#Rw~w& ztJiGXwcR!MwSUAXejeoGtR0MAirRjVAB8%8#(DB54#MYge{xX0xy#c$h|~T^lH;h4 zlvgj}G~$ysAE!|!pW~|z+jeZ{pn7{c-E3~vyheTN!K~&@o6UO7+q`#wHgoLtJB{t` z;o$Ua`fm3AGu8rQ*tMnI(D)m^AkgbO@keRG)3<05*%p+S@2#Ycc+a2a)IrtQk}II! zzI}bk=V_*A6fg>0z5-%@@ZbVl8ViMT>p&r|06+`P(h!Tk3WDQlY-ubMq6fwl6{x68 zUon`XqutYaEscdjMJJ{&A54$T^bLi{(eZpwrW0!^G^J6%C~#hZimFz{`M>w~`~P{8 zsTl=~0{@i)% Date: Fri, 28 Jun 2019 12:40:45 -0400 Subject: [PATCH 09/11] Added ability to change thickness with default color --- src/paths.jl | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/paths.jl b/src/paths.jl index d8eb5f5..ac67704 100644 --- a/src/paths.jl +++ b/src/paths.jl @@ -3,6 +3,9 @@ Path(v::AbstractVector{Tuple{Int, Int}}) = Path([Point(p...) for p in v]) Path(v::AbstractVector{CartesianIndex{2}}) = Path([Point(p) for p in v]) +draw!(img::AbstractArray{T, 2}, path::Path, thickness::Int) where T<:Colorant = + draw!(img, path, oneunit(T), thickness) + function draw!(img::AbstractArray{T, 2}, path::Path, color::T, thickness::Int=1) where T<:Colorant vertices = [CartesianIndex(p.y, p.x) for p in path.vertices] for i in 1:length(vertices)-1 @@ -16,6 +19,9 @@ end Polygon(v::AbstractVector{Tuple{Int, Int}}) = Polygon([Point(p...) for p in v]) Polygon(v::AbstractVector{CartesianIndex{2}}) = Polygon([Point(p) for p in v]) +draw!(img::AbstractArray{T, 2}, polygon::Polygon, thickness::Int) where T<:Colorant = + draw!(img, path, oneunit(T), thickness) + function draw!(img::AbstractArray{T, 2}, polygon::Polygon, color::T, thickness::Int=1) where T<:Colorant draw!(img, Path(polygon.vertices), color, thickness) draw!(img, LineSegment(first(polygon.vertices), last(polygon.vertices)), color, thickness) @@ -26,6 +32,9 @@ end RegularPolygon(point::CartesianIndex{2}, side_count::Int, side_length::T, θ::U) where {T<:Real, U<:Real} = RegularPolygon(Point(point), side_count, side_length, θ) +draw!(img::AbstractArray{T, 2}, rp::RegularPolygon, thickness::Int) where T<:Colorant = + draw!(img, rp, oneunit(T), thickness) + function draw!(img::AbstractArray{T, 2}, rp::RegularPolygon, color::T, thickness::Int=1) where T<:Colorant n = rp.side_count ρ = rp.side_length/(2*sin(π/n)) From fd23e93b9af41f8fd409be740e458e4dffc87ab4 Mon Sep 17 00:00:00 2001 From: Codyk12 Date: Tue, 2 Jul 2019 17:41:24 -0400 Subject: [PATCH 10/11] Changed Vector to Tuple for image size in canvas creation --- src/background.jl | 6 +++--- test/background.jl | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/background.jl b/src/background.jl index b85d3e2..dfe5dba 100644 --- a/src/background.jl +++ b/src/background.jl @@ -9,12 +9,12 @@ """ generatecanvas(colortype::Type, x::Int, y::Int) = zeros(colortype, (x,y)) -generatecanvas(colortype::Type, size::Vector{Int}) = zeros(colortype, (size...)) +generatecanvas(colortype::Type, size::NTuple{Int, 2}) = zeros(colortype, (size...)) generatecanvas(colortype::Type, x::Int, y::Int, b::AbstractBackground) = - generatecanvas(colortype, [x,y], b) + generatecanvas(colortype, (x,y), b) -function generatecanvas(colortype::Type, size::Vector{Int}, b::AbstractBackground) +function generatecanvas(colortype::Type, size::NTuple{Int, 2}, b::AbstractBackground) draw!(zeros(colortype, (size...)), b) end diff --git a/test/background.jl b/test/background.jl index 811a14f..9289259 100644 --- a/test/background.jl +++ b/test/background.jl @@ -17,7 +17,7 @@ @testset "StripedBackground" begin - res = generatecanvas(Gray{N0f8}, [10,10], StripedBackground([Gray{N0f8}(1.0),Gray{N0f8}(.5), Gray{N0f8}(.2)], [2, 5, 8], pi/2)) + res = generatecanvas(Gray{N0f8}, (10,10), StripedBackground([Gray{N0f8}(1.0),Gray{N0f8}(.5), Gray{N0f8}(.2)], [2, 5, 8], pi/2)) expected = Gray{N0f8}[ 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 0.502 0.502 0.502 0.502 0.502 0.502 0.502 0.502 0.502 0.502 @@ -31,7 +31,7 @@ @test all(expected .== res) == true - res = generatecanvas(RGB, [5,5], StripedBackground([RGB(.3,.6,.7),RGB(.5,.2,.9)], [2, 4], 0)) + res = generatecanvas(RGB, (5,5), StripedBackground([RGB(.3,.6,.7),RGB(.5,.2,.9)], [2, 4], 0)) expected = RGB[ RGB(.3,.6,.7) RGB(.3,.6,.7) RGB(.5,.2,.9) RGB(.5,.2,.9) RGB(0,0,0) RGB(.3,.6,.7) RGB(.3,.6,.7) RGB(.5,.2,.9) RGB(.5,.2,.9) RGB(0,0,0) RGB(.3,.6,.7) RGB(.3,.6,.7) RGB(.5,.2,.9) RGB(.5,.2,.9) RGB(0,0,0) @@ -40,7 +40,7 @@ @test all(expected .== res) == true - res = generatecanvas(RGB, [5,5], StripedBackground([RGB(.3,.6,.7),RGB(.5,.2,.9)], [2, 4], pi/4)) + res = generatecanvas(RGB, (5,5), StripedBackground([RGB(.3,.6,.7),RGB(.5,.2,.9)], [2, 4], pi/4)) expected = RGB[ RGB(.3,.6,.7) RGB(.3,.6,.7) RGB(.5,.2,.9) RGB(.5,.2,.9) RGB(.5,.2,.9) RGB(.3,.6,.7) RGB(.5,.2,.9) RGB(.5,.2,.9) RGB(.5,.2,.9) RGB(0,0,0) RGB(.5,.2,.9) RGB(.5,.2,.9) RGB(.5,.2,.9) RGB(0,0,0) RGB(0,0,0) From 4c72bd66f07d7b0f4062c8de86d6bbe6d82ddbf6 Mon Sep 17 00:00:00 2001 From: Codyk12 Date: Tue, 9 Jul 2019 12:49:05 -0400 Subject: [PATCH 11/11] Typos --- src/background.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/background.jl b/src/background.jl index dfe5dba..e68db16 100644 --- a/src/background.jl +++ b/src/background.jl @@ -9,12 +9,12 @@ """ generatecanvas(colortype::Type, x::Int, y::Int) = zeros(colortype, (x,y)) -generatecanvas(colortype::Type, size::NTuple{Int, 2}) = zeros(colortype, (size...)) +generatecanvas(colortype::Type, size::NTuple{2, Int}) = zeros(colortype, size) generatecanvas(colortype::Type, x::Int, y::Int, b::AbstractBackground) = generatecanvas(colortype, (x,y), b) -function generatecanvas(colortype::Type, size::NTuple{Int, 2}, b::AbstractBackground) +function generatecanvas(colortype::Type, size::NTuple{2, Int}, b::AbstractBackground) draw!(zeros(colortype, (size...)), b) end