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

Is PIL reading RGB values correctly? #3420

Closed
fdncred opened this issue Oct 19, 2018 · 7 comments
Closed

Is PIL reading RGB values correctly? #3420

fdncred opened this issue Oct 19, 2018 · 7 comments

Comments

@fdncred
Copy link

fdncred commented Oct 19, 2018

What did you do?

I loaded an image like this.

import numpy as np
from PIL import Image
pil_image = Image.open(filename)
img = np.array(pil_image)

What did you expect to happen?

I expect it to load the image as it resides on the disk without manipulating RGB values. My implication is that PIL is not reading the data right.

What actually happened?

When I look at index 207 in the first row of data, the values look like this:

>> img[0][207]
array([243, 243, 245], dtype=uint8)

However, if I load the image with Leptonica in c++ and c# or with dotnet's built in imaging classes, index 207 looks like this:

-	[207]	{byte[3]}	byte[]
		[0]	243	byte
		[1]	243	byte
		[2]	243	byte

So, my question is, who is right or who should I believe?

What are your OS, Python and Pillow versions?

  • OS: Windows
  • Python: 3.6
  • Pillow: 5.3,

The image in question:
notesa1-quarter-tl

@radarhere
Copy link
Member

On macOS 10.14, I get (243, 243, 245) from Gimp as well as Pillow. Are you able to test the point with an application like Gimp, rather than another programming library?

@fdncred
Copy link
Author

fdncred commented Oct 19, 2018

On my mac (10.13.6) I get 243,243,245 with PIL. I don't have Gimp but I tried OpenCV to see what it did. Here are the results.

OpenCV

Python 3.7.0 (default, Jun 28 2018, 07:39:16)
[Clang 4.0.1 (tags/RELEASE_401/final)] :: Anaconda, Inc. on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import numpy as np
>>> import cv2
>>> img = cv2.imread('qtr.jpg')
>>> img[0][207]
array([243, 243, 243], dtype=uint8)

Pillow

Python 3.7.0 (default, Jun 28 2018, 07:39:16)
[Clang 4.0.1 (tags/RELEASE_401/final)] :: Anaconda, Inc. on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import numpy as np
>>> from PIL import Image
>>> pil_image = Image.open('qtr.jpg')
>>> img2 = np.array(pil_image)
>>> img2[0][207]
array([243, 243, 245], dtype=uint8)

I'm confused why PIL says one thing opencv says another.

@hugovk
Copy link
Member

hugovk commented Oct 30, 2018

I also get 243, 243, 243 with cv2.
I also get 243, 243, 245 with Pillow/NumPy, and also with Pillow/pixel access, and also ImageMagick.

import os
import numpy as np
from PIL import Image

x, y = 207, 0
filename = "qtr.jpg"


def pixel_access():
    #     Image.LOAD_TRUNCATED_IMAGES = True
    im = Image.open(filename)
    px = im.load()

    print("pixel_access")
    r, g, b = px[x, y]
    print(r, g, b)


def numpy_array():
    im = Image.open(filename)
    im_array = np.array(im)

    print("numpy_array")
    r, g, b = im_array[y][x]
    print(r, g, b)


def cv2_imread():
    import cv2

    im_cv2 = cv2.imread(filename)

    print("cv2_imread")
    b, g, r = im_cv2[y][x]  # Note BGR
    print(r, g, b)


def imagemagick():
    # https://www.imagemagick.org/discourse-server/viewtopic.php?t=13694
    cmd = f"convert '{filename}[1x1+{x}+{y}]' -format '%[fx:int(255*r)] %[fx:int(255*g)] %[fx:int(255*b)]' info:"

    print("imagemagick")
    os.system(cmd)
    print("")


print(filename)
numpy_array()
pixel_access()
imagemagick()
cv2_imread()
qtr.jpg
numpy_array
243 243 245
pixel_access
243 243 245
imagemagick
243 243 245
cv2_imread
243 243 243

Different JPEG decoders?

If I convert qtr.jpg qtr.png and run on that image, the numbers are all 243, 243, 245, perhaps because ImageMagick has read and saved the value losslessly.

@fdncred
Copy link
Author

fdncred commented Oct 30, 2018

Different JPEG decoders is a good guess. Perhaps if it was saved as a lossless format like PNG then they'd all return the same value?

@hugovk
Copy link
Member

hugovk commented Oct 30, 2018

Sound reasonable.

@hugovk hugovk closed this as completed Nov 17, 2018
@addisonklinke
Copy link

@hugovk I think this article helps shed more light on the differences

Well, this difference is arising from the fact that OpenCV, by default, uses integer accurate decompression of the JPEG image ... PIL, by default, doesn’t provide any way to use integer accurate decompression

Is it possible to provide an integer accurate decompression in the future for better compatibility?

@radarhere
Copy link
Member

#6047 was opened by another user referencing the same article. They found that their problem was fixed by upgrading to Pillow 9.0.1

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

No branches or pull requests

4 participants