JuliaIO / ImageMagick.jl

Thin Wrapper for the library ImageMagick
Other
53 stars 37 forks source link

Grayscale image isn't saved correctly for BMP format #218

Open ehgus opened 1 year ago

ehgus commented 1 year ago

I discovered that a grayscale image is saved like a color image. I have compared the saved images from Julia and Matlab:

using Images
using FileIO

img = Gray.(rand(512,512));
save("image_julia.bmp",img);
img = rand(512,512);
imwrite(img,"image_matlab.bmp");

The result shows that Matlab represents an image as true grayscale, whereas Julia changes img to a colored view before saving. The image from Julia is obviously three times larger. Such unwanted behavior is not discovered in PNG format.

timholy commented 1 year ago

Are you sure Matlab is using ImageMagick? Julia is not "forcing" the conversion: what gets passed to ccall((:MagickWriteImages, libwand), ... is a wand created with grayscale UInt8 values: with

tim@diva:~/.julia/dev/ImageMagick/src$ git diff libmagickwand.jl
diff --git a/src/libmagickwand.jl b/src/libmagickwand.jl
index 51766d7..7e1d971 100644
--- a/src/libmagickwand.jl
+++ b/src/libmagickwand.jl
@@ -242,6 +242,7 @@ function constituteimage(buffer::AbstractArray{T}, wand::MagickWand, colorspace:
     ncolors = colorsize(buffer, channelorder)
     p = pointer(buffer)
     depth = T == Bool ? 1 : bitdepth(buffer)
+    @show cols rows nimages ncolors depth colorspace channelorder
     for i = 1:nimages
         status = ccall((:MagickConstituteImage, libwand), Cint, (Ptr{Cvoid}, Cssize_t, Cssize_t, Ptr{UInt8}, Cint, Ptr{Cvoid}), wand, cols, rows, channelorder, storagetype(T), p)
         status == 0 && error(wand)

I get

julia> save("image_julia.bmp",img)
cols = 512
rows = 512
nimages = 1
ncolors = 1
depth = 8
colorspace = "Gray"
channelorder = "I"

Seems like we're doing everything we can to convince it to save as a grayscale image; the fault might lie with the ImageMagick C library itself. If that's the case, this is a bug that would have to be reported to their developers.