Skip to content

[Bug]: I give an RGB image to imsave but I don't have the right color map! #29183

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
zef126 opened this issue Nov 24, 2024 · 28 comments
Closed
Labels
Difficulty: Easy https://matplotlib.org/devdocs/devel/contribute.html#good-first-issues Good first issue Open a pull request against these issues if there are no active ones! status: confirmed bug
Milestone

Comments

@zef126
Copy link

zef126 commented Nov 24, 2024

Bug summary

When I give an RGB image as a list of list of list to imsave, I don't have the right colormap and there is no rgb colormap!

Code for reproduction

import matplotlib.pyplot as plt
I = plt.imread("notre-dame.jpg")
m,n,p = I.shape #m=largeur, n=hauteur, p=uplet
J=[[[0 for d in range(p)] for e in range(n)] for f in range(m)]
K=[[[0 for d in range(p)] for e in range(n)] for f in range(m)]
L=[[[0 for d in range(p)] for e in range(n)] for f in range(m)]
for i in range(m) :
    for j in range(n) :
        J[i][j]=[int(I[i][j][0]),0,0]
        K[i][j]=[0,int(I[i][j][1]),0]
        L[i][j]=[0,0,int(I[i][j][2])]
fig, ax=plt.subplots(4,figsize=(28,10))
ax[0].imshow(I)
ax[1].imshow(J)
ax[2].imshow(K)
ax[3].imshow(L)
ax[0].set_axis_off()
ax[1].set_axis_off()
ax[2].set_axis_off()
ax[3].set_axis_off()
ax[0].set_title('Image complete')
ax[1].set_title('Composante rouge')
ax[2].set_title('Composante bleue')
ax[3].set_title('Composante verte')
fig.suptitle("Image de Notre-Dame", x=0.51,y=.93)
plt.imsave("Notre-Dame_rouge.png",J) #The problem is here!
plt.savefig("Notre-Dame_composante_ex1.png",dpi=750,bbox_inches="tight")
plt.savefig("Notre-Dame_composante_ex1.pdf",dpi=750,bbox_inches="tight")
plt.show()

Actual outcome

Notre-Dame_rouge

Expected outcome

Notre-Dame_composante_ex1
The red one in a png image!

Additional information

notre-dame
The original image

Operating system

Win 11

Matplotlib Version

3.9.2

Matplotlib Backend

module://matplotlib_inline.backend_inline

Python version

3.11.10

Jupyter version

No response

Installation

conda

@tacaswell
Copy link
Member

The source of the problem is that in figimage we only check for RGB if the input is already a numpy array. Is there a reason you need to work with list-of-list-of-list? Using numpy (which I is already a numpy array) the code becomes simpler (no nested loop), faster (numpy does array work at or near c-speed), and avoids the bug:

import matplotlib.pyplot as plt
import numpy as np
I = plt.imread("notre-dame.jpg")

J = np.zeros_like(I)
# RGB version of the image with only one plane non-zero
J[..., 0] = I[..., 0]
K = np.zeros_like(I)
K[..., 0] = I[..., 1]
L = np.zeros_like(I)
L[..., 0] = I[..., 2]


# share the axis so that panning / zooming on one pans/zooms on all
fig, axs = plt.subplots(4, figsize=(28, 10), sharex='all', sharey='all')
# loop over axes, data, and title strings
for ax, data, title in zip(
    axs,
    (I, J, K, L),
    ("Image complete", "Composante rouge", "Composante bleue", "Composante verte"),
):
    ax.imshow(data)
    ax.set_title(title)

fig.suptitle("Image de Notre-Dame", x=0.51, y=0.93)

fig.savefig("Notre-Dame_composante_ex1.png", dpi=750, bbox_inches="tight")
fig.savefig("Notre-Dame_composante_ex1.pdf", dpi=750, bbox_inches="tight")

plt.imsave("Notre-Dame_rouge.png", J)  # The problem is here!
plt.show()

As a short-term fix you can also do np.array(J) before passing to fig.imsave which will go through the correct code path.

@tacaswell tacaswell added status: confirmed bug Difficulty: Easy https://matplotlib.org/devdocs/devel/contribute.html#good-first-issues Good first issue Open a pull request against these issues if there are no active ones! labels Nov 25, 2024
Copy link

Good first issue - notes for new contributors

This issue is suited to new contributors because it does not require understanding of the
Matplotlib internals. To get started, please see our contributing
guide
.

We do not assign issues. Check the Development section in the sidebar for linked pull
requests (PRs). If there are none, feel free to start working on it. If there is an open PR, please
collaborate on the work by reviewing it rather than duplicating it in a competing PR.

If something is unclear, please reach out on any of our communication
channels
.

@tacaswell
Copy link
Member

This is a good first issue as it should require no API choices and we have a good reference for the expected behavior already in the code base.

The issue is that when passing a list-of-list-of-list to plt.imsave and saving to a format that pillow and write the check that sees if it is an RGB image (which should not be color mapped) or a 1-channel luminescence image (which should) is avoided and we always color map.

The steps are:

  • look at Axes.imshow to see how we do the input normalization there
  • do the same thing is matplotlib.image.imsave
  • add a test (round-trip with imread and a small synthetic RGB image)

@tacaswell tacaswell added this to the v3.10.1 milestone Nov 25, 2024
@Frostbyte72
Copy link

Hi I am a new contributor to opensource and believe I can fix this could I be assigned to this issue?

@tacaswell
Copy link
Member

We do not assign issues.

Please review https://matplotlib.org/stable/devel/index and open a PR when you are ready!

@zef126
Copy link
Author

zef126 commented Nov 25, 2024

Thank you so much for your help...it is very useful, I will try to use arrays!
The point is that I am in preparation class in France and parts of the code are strictly imposed by the teacher!

@zef126
Copy link
Author

zef126 commented Nov 25, 2024

It is the first repo where i fond kindness and attention, it is really appreciated!

@zef126
Copy link
Author

zef126 commented Nov 25, 2024

Now it's just a code issue...I don't understand why I get that:
Notre-Dame_composante_ex1_2
Instead of that:
Notre-Dame_composante_ex1
with your code @tacaswell !
And by the way how can i save my lists in rgb files ...if it's possible?
I tried to convert them in numpy.arrays like that:
plt.imsave("Notre-Dame_rouge.png", np.array(J))
but it returned that:
ValueError: Image RGB array must be uint8 or floating point; found int64
Thank you again for your help!

@QuLogic
Copy link
Member

QuLogic commented Nov 26, 2024

J[..., 0] = I[..., 0]
K = np.zeros_like(I)
K[..., 0] = I[..., 1]
L = np.zeros_like(I)
L[..., 0] = I[..., 2]

K and L should use 1 and 2, respectively.

@tacaswell
Copy link
Member

🤦🏻

as noteed, should be

J[..., 0] = I[..., 0]
K = np.zeros_like(I)
K[..., 1] = I[..., 1]
L = np.zeros_like(I)
L[..., 2] = I[..., 2]

and np.asarray(J, dtype=np.int8)

@zef126
Copy link
Author

zef126 commented Nov 26, 2024

Thank you very much!
I just got this for saving the list of list of list:

plt.imsave("Notre-Dame_rouge.png", np.asarray(J, dtype=np.int8))

OverflowError: Python integer 128 out of bounds for int8

@NGWi
Copy link
Contributor

NGWi commented Nov 27, 2024

@zef126 Can you please try plt.imsave("Notre-Dame_rouge.png", np.asarray(J, dtype=np.uint8)) instead?
np.int8 holds values from -128 to 127, while np.uint8 (the u stands for unsigned) will handle the normal range of RGB values (0 to 255).

gpxxlt pushed a commit to gpxxlt/matplotlib-issue-fix that referenced this issue Nov 28, 2024
@zef126
Copy link
Author

zef126 commented Dec 8, 2024

@zef126 Can you please try plt.imsave("Notre-Dame_rouge.png", np.asarray(J, dtype=np.uint8)) instead? np.int8 holds values from -128 to 127, while np.uint8 (the u stands for unsigned) will handle the normal range of RGB values (0 to 255).

Thank you, @NGWi, it worked perfectly!

@AvAdiii
Copy link

AvAdiii commented Dec 18, 2024

(Hi everyone, this is my first time commenting on an issue here, so please let me know if I’ve missed anything! 😊)

The suggestion to convert lists of lists to a NumPy array before using plt.imsave addresses the immediate issue, but I noticed this is still open. Are there additional concerns or improvements being considered?

Here are a few thoughts:

  • The current behavior raises an indirect error when lists of lists are passed to plt.imsave. Could a more explicit error message clarify that the input must be a NumPy array?

  • Should plt.imsave automatically convert valid RGB list-like structures (e.g., lists of lists of lists) into NumPy arrays? This could improve usability.

  • The documentation could explicitly mention the requirement for a NumPy array and provide an example of converting list-based RGB structures.

I’d be happy to contribute to any of these changes. Looking forward to hearing your thoughts!

@timhoffm
Copy link
Member

@AvAdiii Thanks for your interest to contribute. However, if you look above, there's already a pull request open to fix this #29203. This particular issue does not need additional input/help.

@NGWi
Copy link
Contributor

NGWi commented Dec 18, 2024

@AvAdiii Thanks for your interest to contribute. However, if you look above, there's already a pull request open to fix this #29203. This particular issue does not need additional input/help.

So, does this Close the issue?

@timhoffm
Copy link
Member

I anticipate it will. - There are still some changes to be done.

@shreyas-koduvayur
Copy link

Is there any help still required with this as I want to make my first open source contributions.

@timhoffm
Copy link
Member

@shreyas-koduvayur There's currently no help needed. We're waiting for the repsonse of the author of #29203. If there's no feedback in a couple of days, you could take over.

@timhoffm
Copy link
Member

Below is the full code for the script, including the fix for the imsave function to handle nested lists properly. I included headers to describe exactly what each code block function as and how it was changed.

@aragan22 This is not adding meaningfully to the issue. You are only rewriting the original restating the original minimal example with comments - but the example and issue is well understood. Nobody with the capability of fixing the issue needs these comments. Please think carefully to not post repetitive or unneeded stuff.

@aragan22
Copy link

Below is the full code for the script, including the fix for the imsave function to handle nested lists properly. I included headers to describe exactly what each code block function as and how it was changed.

@aragan22 This is not adding meaningfully to the issue. You are only rewriting the original restating the original minimal example with comments - but the example and issue is well understood. Nobody with the capability of fixing the issue needs these comments. Please think carefully to not post repetitive or unneeded stuff.

Apologies, I did not mean to comment that portion. That was simply for myself as I tried to understand the issue and work around it in my own way. Thank you for pointing this out, apologies again for the confusion.

@ksunden ksunden modified the milestones: v3.10.1, v3.10.2 Feb 21, 2025
@Dronten
Copy link

Dronten commented Mar 22, 2025

is this issue still up and can i work in this ?

@rcomer
Copy link
Member

rcomer commented Mar 22, 2025

@Dronten yes it looks like #29203 has stalled so you are welcome to go ahead. Please see our contributors’ guide:
https://matplotlib.org/devdocs/devel/index.html

@Aftabby
Copy link

Aftabby commented Apr 8, 2025

Has the issue been solved? Else I'd like to take over.

@timhoffm
Copy link
Member

timhoffm commented Apr 9, 2025

@Aftabby it looks like #29203 has stalled so you are welcome to go ahead. Please see our contributors’ guide:
https://matplotlib.org/devdocs/devel/index.html

@guillermodotn
Copy link
Contributor

I have opened PR #29931 for this issue, based on the latest code review in #29203.

@ksunden ksunden modified the milestones: v3.10.2, v3.10.3 May 2, 2025
@jk2500
Copy link

jk2500 commented May 6, 2025

Hey there, I tried running the code in the snippet and it shows the expected output. Does this mean the issue can be closed?

@timhoffm
Copy link
Member

timhoffm commented May 7, 2025

Yes, closed by #29931.

@timhoffm timhoffm closed this as completed May 7, 2025
@QuLogic QuLogic modified the milestones: v3.10.3, v3.10.2 May 7, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Difficulty: Easy https://matplotlib.org/devdocs/devel/contribute.html#good-first-issues Good first issue Open a pull request against these issues if there are no active ones! status: confirmed bug
Projects
None yet
Development

Successfully merging a pull request may close this issue.