Save Matrix of RGB Values to Image File with Huge Pixels

Hi,

so yesterday I tried to visualize a graph in the form of a matrix. A lot of people helped me in the forum and the chat. I ended up with turning the numerical values in my matrix to RGB values. So now I have e.g.:

using FileIO
using Images

c = RGB{Normed{UInt8,8}}[
        RGB{N0f8}(1.0,1.0,1.0) RGB{N0f8}(0.0,0.502,0.0) RGB{N0f8}(1.0,0.0,0.0);
        RGB{N0f8}(1.0,0.0,0.0) RGB{N0f8}(1.0,1.0,1.0) RGB{N0f8}(0.0,0.0,0.0);
        RGB{N0f8}(0.0,0.502,0.0) RGB{N0f8}(0.0,0.0,0.0) RGB{N0f8}(0.0,0.502,0.0)]

save("image.png", c) # For jupyter use FileIO.save("image.png", c)

Problem: I get an image of 3x3 pixels whereas is want a picture like
image

If anyone could help me figure out how to make my pixels huge, I’d be in love forever.The best szenario would be to define an image size nd then just have it scale automatically becuse the size of the matrix will change. :slight_smile:

With GMT

using GMT
im = ones(UInt8,2, 2, 3); im[1,1,1]=255; im[1,2,1]=255; im[1,1,2]=255; im[2,1,2]=255; im[1,1,3]=255; im[2,2,3]=255;

imshow(im,axes=:none, figsize=10, savefig="huge_pix.png")

What happens under the hood is:

  • a postscript file with exactly 10x10 cm is created
  • the postscript file is rasterized into a png witha certain desinsity that I don’t remember (would need to dive into the docs).

If you print the ps (or a converted to pdf) file you would get a printed image with exactly 10 cm.

1 Like

This is in PGFPlotsX.jl. It is slightly more awkward than ideal:

using Images, PGFPlotsX

cs = RGB{Normed{UInt8,8}}[
               RGB{N0f8}(1.0,1.0,1.0) RGB{N0f8}(0.0,0.502,0.0) RGB{N0f8}(1.0,0.0,0.0);
               RGB{N0f8}(1.0,0.0,0.0) RGB{N0f8}(1.0,1.0,1.0) RGB{N0f8}(0.0,0.0,0.0);
               RGB{N0f8}(0.0,0.502,0.0) RGB{N0f8}(0.0,0.0,0.0) RGB{N0f8}(0.0,0.502,0.0)]
x = vec(first.(Tuple.(CartesianIndices(cs))))
y = vec(last.(Tuple.(CartesianIndices(cs))))

c = Coordinates(
    x, y
    ; meta = vec(cs))

p = @pgf PGFPlotsX.Axis(
    {
        axis_equal,
        ticks="none",
    },
    PlotInc(
        {
            mark = "none",
            matrix_plot,
            "mesh/color input" = "explicit",
            "mesh/cols" = 3
        },
        c,
    )
);

pgfsave("image.pdf", p)

1 Like

You should be able to do this natively from Images.jl by specifying the interpolation type for imresize, but there’s a longstanding issue: https://github.com/JuliaImages/ImageTransformations.jl/issues/51. It’s not a complicated fix, but nobody’s taken the time to do it yet.

The easiest would probably be to just inner repeat your array

scale = 100 # times bigger you want the image
save("image.png", repeat(c, inner = (scale, scale))) 
1 Like

In Gaston.jl:

using Images, Gaston

c = RGB{Normed{UInt8,8}}[
               RGB{N0f8}(1.0,1.0,1.0) RGB{N0f8}(0.0,0.502,0.0) RGB{N0f8}(1.0,0.0,0.0);
               RGB{N0f8}(1.0,0.0,0.0) RGB{N0f8}(1.0,1.0,1.0) RGB{N0f8}(0.0,0.0,0.0);
               RGB{N0f8}(0.0,0.502,0.0) RGB{N0f8}(0.0,0.0,0.0) RGB{N0f8}(0.0,0.502,0.0)];
cc = channelview(c).*255; # convert to a 3-D array of RGB values
imagesc(cc,Axes(size="square",tics=:off))

image

1 Like

The proportions are distorted when I run the same GMT code in Windows 10 (GMT6.1.1):

Following up on yesterday’s discussion, here is what I do in Jupyterlab:

using Plots
#... like yesterday
function num2col(i)
    if i == 0
        return colorant"white"
    elseif i == 1
        return colorant"green"
    elseif i == 2
        return colorant"red"
    else
        return colorant"black"
    end
end
#
mat = [0 3; 2 1]
#
plot(num2col.(mat),xaxis=nothing,yaxis=nothing)

which produces the following in Jupyterlab:


Then I save the result as, e.g., an *.svg file:

savefig("c:/users/.../squares.svg")

I then import this file in, say, the LyX word processor:

If I do a pdf preview of this, I get:

If I import it into Word, I get:

I suspect the trick is to plot the matrix, and then use savefig – instead of just saving the matrix??

To adjust the size of the plot, you can use the size keyword of the plot function. You can, of course, also scale the svg file (or pdf or png) in your word processor.

Btw: the following is a better version of my num2col function (still assuming that the numeric values are integers in the range {0,1,2,…}):

function num2col(i;vcol = [colorant"red",colorant"green",colorant"blue"])
   return vcol[min(i+1,length(vcol))]
end

Then you find:

m = rand(0:3,2,4)
num2col.(m)

gives, say:

while specifying some colors like:

MYCOL = distinguisable_colors(4,colorant"red")
#
num2col.(m;vcol=MYCOL)

leads to

Here, function distinguishable_colors() gives maximally distinguishable colors where the first argument gives the number of colors, and the optionally second argument gives a “seed” for picking the colors. (The seed can be a “scalar” color, or a vector of colors, I think.)

Works correctly for me in my Win10 and WSL machines but can reproduce this issue in a CentosOS machine.
Have an idea where it might coming from but puzzled with this machines discrepancy. Better move this ito a GMT.jl issue

For the record, this issue has been fixed in the GMT master and will be part of next official release. The compiled Windows installer (GMT 6.2.0dev) provided by joa-quim does not show the bug:

1 Like