Skip to content

Commit

Permalink
Merge pull request #54 from JuliaIO/nontransparent_images_with_backgr…
Browse files Browse the repository at this point in the history
…ound

Support opaque images with background chunks
  • Loading branch information
Drvi authored Feb 5, 2022
2 parents 63701b1 + 7b7f226 commit 74a8cee
Show file tree
Hide file tree
Showing 3 changed files with 25 additions and 12 deletions.
17 changes: 7 additions & 10 deletions src/io.jl
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,10 @@ function _load(png_ptr, info_ptr; gamma::Union{Nothing,Float64}=nothing, expand_
interlace_type = png_get_interlace_type(png_ptr, info_ptr)
background_color = nothing
is_transparent = valid_tRNS | (color_type & PNG_COLOR_MASK_ALPHA) != 0
is_gray = (color_type == PNG_COLOR_TYPE_GRAY_ALPHA) | (color_type == PNG_COLOR_TYPE_GRAY)

read_as_paletted = !expand_paletted && color_type == PNG_COLOR_TYPE_PALETTE && bit_depth == 8 && valid_PLTE
read_with_background = _check_background_load(background, is_gray, valid_PLTE, read_as_paletted)

screen_gamma = PNG_DEFAULT_sRGB
image_gamma = Ref{Cdouble}(-1.0)
Expand All @@ -148,11 +152,6 @@ function _load(png_ptr, info_ptr; gamma::Union{Nothing,Float64}=nothing, expand_
png_set_gamma(png_ptr, screen_gamma, image_gamma[])
end

read_as_paletted = !expand_paletted &&
color_type == PNG_COLOR_TYPE_PALETTE &&
bit_depth == 8 &&
valid_PLTE

if !read_as_paletted
if color_type == PNG_COLOR_TYPE_PALETTE
png_set_palette_to_rgb(png_ptr)
Expand All @@ -172,7 +171,7 @@ function _load(png_ptr, info_ptr; gamma::Union{Nothing,Float64}=nothing, expand_
end
end

if valid_bKGD & ((color_type | PNG_COLOR_MASK_ALPHA) > 0)
if read_with_background & valid_bKGD & is_transparent
png_set_filler(png_ptr, 0xff, PNG_FILLER_AFTER)
end
buffer_eltype = _buffer_color_type(color_type, bit_depth)
Expand All @@ -182,10 +181,9 @@ function _load(png_ptr, info_ptr; gamma::Union{Nothing,Float64}=nothing, expand_
buffer_eltype = UInt8
end

is_gray = (color_type == PNG_COLOR_TYPE_GRAY_ALPHA) | (color_type == PNG_COLOR_TYPE_GRAY)
if _check_background_load(background, is_gray, valid_PLTE, read_as_paletted)
is_transparent || throw(ArgumentError("Only transparent images can have a background"))
if read_with_background
background_color = process_background(png_ptr, info_ptr, _adjust_background_bitdepth(background, bit_depth))
is_transparent || @warn("Background color for non-transparent image: $(background_color)")
end

n_passes = png_set_interlace_handling(png_ptr)
Expand Down Expand Up @@ -468,7 +466,6 @@ function _save(png_ptr, info_ptr, image::S;
end
end
if !(background === nothing)
is_transparent || throw(ArgumentError("Only transparent images can have a background"))
_check_background_save(background, color_type)
_png_set_bKGD(png_ptr, info_ptr, _adjust_background_bitdepth(background, bit_depth))
end
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
20 changes: 18 additions & 2 deletions test/test_invalid_inputs.jl
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,11 @@ incompatible_background_arguments = [
("graya_img_rgb_background", ArgumentError, rand(127, 257, 2), "temp/PngSuite/bgbn4a08.png", RGB{N0f8}(1.0, 0.5, 0.0)),
("graya_img_index_background", ArgumentError, rand(127, 257, 2), "temp/PngSuite/bgbn4a08.png", 0x00),
("rgba_img_index_background", ArgumentError, rand(127, 257, 4), "temp/PngSuite/bgwn6a08.png", 0x00),
("rgb_no_alpha_background", ArgumentError, rand(127, 257, 3), "temp/PngSuite/basn2c08.png", RGB{N0f8}(0.0)),
("gray_no_alpha_background", ArgumentError, rand(127, 257, 1), "temp/PngSuite/basn0g08.png", Gray{N0f8}(1.0)),
]

warn_background_arguments = [
("rgb_no_alpha_background", rand(127, 257, 3), "temp/PngSuite/basn2c08.png", RGB{N0f8}(0.0)),
("gray_no_alpha_background", rand(127, 257, 1), "temp/PngSuite/basn0g08.png", Gray{N0f8}(0.0)),
]

@testset "Invalid inputs" begin
Expand Down Expand Up @@ -53,4 +56,17 @@ incompatible_background_arguments = [
@test_throws ArgumentError PNGFiles.load("test_images/paletted_implicit_transparency.png", background=0x00)
end
end

warn_msg = "Background color for non-transparent image: PNGFiles._png_color_16_struct(0x00, 0x0000, 0x0000, 0x0000, 0x0000)"
for (case, image, load_path, bg) in warn_background_arguments
@testset "$(case) throws save" begin
@test PNGFiles.save(joinpath(PNG_TEST_PATH, "test_img_err_$(case).png"), image, background=bg) === nothing
end
@testset "$(case) throws load" begin
@test_logs (:warn, warn_msg) PNGFiles.load(load_path, background=bg)
end
end
@testset "non_transparent_image_with_background_warns" begin
@test_throws ArgumentError PNGFiles.load("test_images/nontransparent_image_with_background.png", background=0x00)
end
end

0 comments on commit 74a8cee

Please sign in to comment.