Skip to content
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

Wrong color conversion from HSV string #7225

Closed
matenestor opened this issue Jun 22, 2023 · 4 comments · Fixed by #7226
Closed

Wrong color conversion from HSV string #7225

matenestor opened this issue Jun 22, 2023 · 4 comments · Fixed by #7226

Comments

@matenestor
Copy link

What did you do?

I tried to create an image with HSV mode and set its color to blue with following kwargs

  • color=(170, 255, 255) # 170 == 255 * (2/3)
  • color="hsv(240, 100%, 100%)"

What did you expect to happen?

To get a blue image with both approaches.

What actually happened?

The color="hsv(240, 100%, 100%)" kwarg created a white image.

What are your OS, Python and Pillow versions?

  • OS: Arch Linux
  • Python: Python 3.10.11
  • Pillow: 9.4.0

Image.new("HSV", (200, 200), (170, 255, 255)).show()

tmp7n00mtvm

Image.new("HSV", (200, 200), color="hsv(240, 100%, 100%)").show()

tmpewrf26xo

I tried converting to RGB first, but that has the same result.

# blue
Image.new("HSV", (200, 200), color=(170, 255, 255)).convert("RGB").save("image.png")

# white
Image.new("HSV", (200, 200), color="hsv(240, 100%, 100%)").convert("RGB").save("image.png")

Something weird is also happening with getpixel() method.

When a tuple is used to set a color it works. The image is still in HSV mode, so 170 is 240 hue, and 255 is 100% saturation and value.
The pixel bytes have expected values.

Image.new("HSV", (200, 200), (170, 255, 255)).getpixel((0,0))
Out[173]: (170, 255, 255)

However, when a string is used, then the pixel bytes are totally off. It looks like it is returning RGB mode, since this is blue color in RGB code.

Image.new("HSV", (200, 200), color="hsv(240, 100%, 100%)").getpixel((0,0))
Out[174]: (0, 0, 255)

So I tried using RGB mode for the image and that works as expected.

Image.new("RGB", (200, 200), (0, 0, 255)).getpixel((0,0))
Out[177]: (0, 0, 255)

Image.new("RGB", (200, 200), color="hsv(240, 100%, 100%)").getpixel((0,0))
Out[178]: (0, 0, 255)
@radarhere
Copy link
Member

The documentation for Image.new() states

When creating RGB images, you can also use color strings as supported by the ImageColor module.

This is your problem. When creating RGB images.

So color="hsv(240, 100%, 100%)" is being interpreted as a RGB value of (0, 0, 255), which is then read by the HSV mode as hsv(0, 0%, 100%), a.k.a white.

@matenestor
Copy link
Author

Aha, I just read source code of getrgb() and I see it indeed returns RGB code only.

However, that makes it a bit bad developer experience. It would be nice if the string was interpreted according to the mode I set. So this would create a blue image:

im = Image.new("HSV", (200, 200), color="hsv(240, 100%, 100%)")

# would print: (170, 255, 255)
print(im.getpixel((0, 0)))

# would show blue image, it would need to convert it to RGB color space before, of course
im.show()

I would say this can be a feature request for getcolor(), that would call gethsv() instead of getrgb() when HSV mode is set. 🙂

@radarhere
Copy link
Member

I've created PR #7226 to resolve this.

@matenestor
Copy link
Author

Nice, thank you!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants