New user of Images.jl ... trouble saving grayscale PNG

I am getting a copy of the red channel of an image from the graphics card as a Float32. What I get back has a range of 0 to 1.865 (granted, I may have done something wrong, I would have figured it was supposed to be from 0 to 1), anyhow, to quiet down the errors, I divided by the maximum value to get the buffer back in the range from 0 to 1.

I then try to set the buffer up for saving to a file:

using Images

# ... elided ...

samples = reshape(samples, WIDTH, HEIGHT)
samples = transpose(colorview(Gray, n0f16.(samples)))
save("framebuffer.png", samples)

This generated a lot of error text, and I am not sure if I am using “save” correctly?

error text

(typeof(pixel_samples), minimum(pixel_samples), maximum(pixel_samples)) = (Matrix{Gray{N0f8}}, Gray{N0f8}(0.0), Gray{N0f8}(1.0))
┌ Warning: Mapping to the storage type failed; perhaps your data had out-of-range values?
│ Try `map(clamp01nan, img)` to clamp values to a valid range.
└ @ ImageMagick ~/.julia/packages/ImageMagick/KDZC2/src/ImageMagick.jl:179
Errors encountered while save FileIO.File{FileIO.DataFormat{:PNG}, String}("framebuffer.png").
All errors:
===========================================
MethodError: no method matching save(::FileIO.File{FileIO.DataFormat{:PNG}, String}, ::Tuple{DataType, Gray{N0f8}, Gray{N0f8}})

Closest candidates are:
  save(::FileIO.File{FileIO.DataFormat{:PNG}}, ::S; kwargs...) where {T, S<:Union{AbstractArray{T, 3}, AbstractMatrix}}
   @ ImageIO ~/.julia/packages/ImageIO/XthUV/src/ImageIO.jl:69
  save(::FileIO.File{FileIO.DataFormat{:QOI}}, ::Any...; kwargs...)
   @ ImageIO ~/.julia/packages/ImageIO/XthUV/src/ImageIO.jl:152
  save(::FileIO.File{FileIO.DataFormat{:EXR}}, ::Any...; kwargs...)
   @ ImageIO ~/.julia/packages/ImageIO/XthUV/src/ImageIO.jl:141

===========================================
MethodError: no method matching mapIM(::Type{Matrix{Gray{N0f8}}})

Closest candidates are:
  mapIM(::Bool)
   @ ImageMagick ~/.julia/packages/ImageMagick/KDZC2/src/ImageMagick.jl:319
  mapIM(::UInt32)
   @ ImageMagick ~/.julia/packages/ImageMagick/KDZC2/src/ImageMagick.jl:318
  mapIM(::UInt8)
   @ ImageMagick ~/.julia/packages/ImageMagick/KDZC2/src/ImageMagick.jl:316

===========================================
ArgumentError: Argument does not support conversion to png.
===========================================

Fatal error:
ERROR: LoadError: MethodError: no method matching save(::FileIO.File{FileIO.DataFormat{:PNG}, String}, ::Tuple{DataType, Gray{N0f8}, Gray{N0f8}})

Closest candidates are:
  save(::FileIO.File{FileIO.DataFormat{:PNG}}, ::S; kwargs...) where {T, S<:Union{AbstractArray{T, 3}, AbstractMatrix}}
   @ ImageIO ~/.julia/packages/ImageIO/XthUV/src/ImageIO.jl:69
  save(::FileIO.File{FileIO.DataFormat{:QOI}}, ::Any...; kwargs...)
   @ ImageIO ~/.julia/packages/ImageIO/XthUV/src/ImageIO.jl:152
  save(::FileIO.File{FileIO.DataFormat{:EXR}}, ::Any...; kwargs...)
   @ ImageIO ~/.julia/packages/ImageIO/XthUV/src/ImageIO.jl:141

Stacktrace:
 [1] #invokelatest#2
   @ FileIO ./essentials.jl:892 [inlined]
 [2] invokelatest
   @ FileIO ./essentials.jl:889 [inlined]
 [3] action(call::Symbol, libraries::Vector{Union{Base.PkgId, Module}}, file::FileIO.Formatted, args::Tuple{DataType, Gray{N0f8}, Gray{N0f8}}; options::@Kwargs{})
   @ FileIO ~/.julia/packages/FileIO/BE7iZ/src/loadsave.jl:219
 [4] action
   @ FileIO ~/.julia/packages/FileIO/BE7iZ/src/loadsave.jl:196 [inlined]
 [5] action
   @ FileIO ~/.julia/packages/FileIO/BE7iZ/src/loadsave.jl:185 [inlined]
 [6] save(file::String, args::Tuple{DataType, Gray{N0f8}, Gray{N0f8}}; options::@Kwargs{})
   @ FileIO ~/.julia/packages/FileIO/BE7iZ/src/loadsave.jl:129
 [7] save(file::String, args::Tuple{DataType, Gray{N0f8}, Gray{N0f8}})
   @ FileIO ~/.julia/packages/FileIO/BE7iZ/src/loadsave.jl:125
 [8] main()
   @ Main ~/Delete/simple.jl:50
 [9] top-level scope
   @ ~/Delete/simple.jl:54
Stacktrace:
  [1] handle_error(e::MethodError, q::Base.PkgId, bt::Vector{Union{Ptr{Nothing}, Base.InterpreterIP}})
    @ FileIO ~/.julia/packages/FileIO/BE7iZ/src/error_handling.jl:61
  [2] handle_exceptions(exceptions::Vector{Tuple{Any, Union{Base.PkgId, Module}, Vector}}, action::String)
    @ FileIO ~/.julia/packages/FileIO/BE7iZ/src/error_handling.jl:56
  [3] action(call::Symbol, libraries::Vector{Union{Base.PkgId, Module}}, file::FileIO.Formatted, args::Tuple{DataType, Gray{N0f8}, Gray{N0f8}}; options::@Kwargs{})
    @ FileIO ~/.julia/packages/FileIO/BE7iZ/src/loadsave.jl:228
  [4] action
    @ FileIO ~/.julia/packages/FileIO/BE7iZ/src/loadsave.jl:196 [inlined]
  [5] action
    @ FileIO ~/.julia/packages/FileIO/BE7iZ/src/loadsave.jl:185 [inlined]
  [6] save(file::String, args::Tuple{DataType, Gray{N0f8}, Gray{N0f8}}; options::@Kwargs{})
    @ FileIO ~/.julia/packages/FileIO/BE7iZ/src/loadsave.jl:129
  [7] save(file::String, args::Tuple{DataType, Gray{N0f8}, Gray{N0f8}})
    @ FileIO ~/.julia/packages/FileIO/BE7iZ/src/loadsave.jl:125
  [8] main()
    @ Main ~/Delete/simple.jl:50
  [9] top-level scope
    @ ~/Delete/simple.jl:54
 [10] include(fname::String)
    @ Base.MainInclude ./client.jl:489
 [11] top-level scope
    @ REPL[1]:1
 [12] top-level scope
    @ ~/opt/julia/usr/share/julia/stdlib/v1.11/REPL/src/REPL.jl:1426

Linking related thread

I tried again with FileIO added to the manifest, and using FileIO at the top … same error …

Did you also use ImageIO ?

1 Like

Right now, the include line is using Images, ImageIO, FileIO. Same error …

EDIT, ok, not same error … I removed some debug print text just to make sure, and it looks like the type of the result returned from my image-returning function switched from Matrix to tuple of Matrix and two numbers). I’ll go back in git history and figure out exactly what … but the only material changes that I made beyond that were including FileIO and ImageIO in the manifest. ImageIO seems to be the missing package that when added fixed it.

In short, thanks, you figured out my problem!