# Two almost identical image convolve function different results

I think I have these two identical function (the difference is using acc inside a loop or not)

``````function convolve_image_bad(M::AbstractMatrix, K::AbstractMatrix)
M′ = zero(M)
nrow, ncol = size(M)
lr, lc = size(K) .÷ 2  # find K's center

for i in 1:nrow
for j in 1:ncol
for r_offset in -lr:lr
for c_offset in -lc:lc
# K centered at (lr+1, lc+1)
M′[i, j] += extend_mat(M, i+r_offset, j+c_offset) * K[lr+1+r_offset, lc+1+c_offset]
end
end
end
end
return M′
end
``````
``````function convolve_image(M::AbstractMatrix, K::AbstractMatrix)
M′ = zero(M)
nrow, ncol = size(M)
lr, lc = size(K) .÷ 2  # find K's center

for i in 1:nrow
for j in 1:ncol
acc = M′[i, j]
for r_offset in -lr:lr
for c_offset in -lc:lc
# K centered at (lr+1, lc+1)
acc += extend_mat(M, i+r_offset, j+c_offset) * K[lr+1+r_offset, lc+1+c_offset]
end
end
M′[i, j] = acc
end
end
return M′
end
``````

set my kernel to

``````K_test = [
1/16 1/8  1/16
1/8  1/4  1/8
1/16 1/8  1/16
]
``````

which sums up to 1.

some definitions are here

``````philip_file = download("https://i.imgur.com/VGPeJ6s.jpg")

decimate(image, ratio=5) = image[1:ratio:end, 1:ratio:end]

function extend_mat(M::AbstractMatrix, i, j)
nrow, ncol = size(M)
return M[clamp(i, 1, nrow), clamp(j, 1, ncol)]
end

philip = let
decimate(original, 8)
end
``````

when I applied the convolve_image_bad function on this picture

``````convolve_image_bad(philip, K_test)
``````

I got errors

``````ArgumentError: element type FixedPointNumbers.Normed{UInt8,8} is an 8-bit type representing 256 values from 0.0 to 1.0,

but the values (0.9120098039215686, 0.9495098039215686, 1.0036764705882353) do not lie within this range.

See the READMEs for FixedPointNumbers and ColorTypes for more information.

throw_colorerror_(::Type{FixedPointNumbers.Normed{UInt8,8}}, ::Tuple{Float64,Float64,Float64})@types.jl:686
throw_colorerror(::Type{ColorTypes.RGBX{FixedPointNumbers.Normed{UInt8,8}}}, ::Tuple{Float64,Float64,Float64})@types.jl:736
checkval@types.jl:654[inlined]
RGBX@types.jl:168[inlined]
_convert@conversions.jl:87[inlined]
cconvert@conversions.jl:76[inlined]
convert@conversions.jl:73[inlined]
setindex!@array.jl:849[inlined]
convolve_image(::Array{ColorTypes.RGBX{FixedPointNumbers.Normed{UInt8,8}},2}, ::Array{Float64,2})@Other: 11
top-level scope@Local: 1[inlined]
``````

which indicates during the loop the RGB value exceeded 1.0.

the image is a matrix of `RGBX{Normed{UInt8,8}}`
all the FixedPointNumbers.Normed{UInt8,8} is an 8-bit type representing 256 values from 0.0 to 1.0,
and my kernel sums up to 1.0, so no value should be exceeding 1.0 during the loop in theory.

more interestingly when I apply `convolve_image(philip, K_test)` it does the job without complaining.

I was wondering what causes the difference between the two convolve functions.