Skip to content

Image conversion should scale pixel values accordingly #3159

Open
@SolarLiner

Description

@SolarLiner

What did you do?

I tried to convert grayscale images of different modes together

What did you expect to happen?

Conversion should scale values; for example, converting from float to 8-bit should have the values scaled by 255, converting from 8-bit to 16-bit should have the values scaled by 65535/255, etc.

What actually happened?

Values are being clamped

>>> img = Image.open('16bit_image.png')
>>> img.mode
'I'
>>> numpy.array(img)
array([[51559, 52726, 50875, ..., 30493, 30991, 29907],
       [51743, 52185, 51221, ..., 30841, 29920, 30793],
       [51279, 50534, 51128, ..., 31532, 30852, 30651],
       ...,
       [28288, 27868, 28032, ..., 34367, 34235, 34312],
       [26900, 27567, 28120, ..., 36229, 34607, 33399],
       [27966, 28224, 27962, ..., 36223, 35851, 34477]], dtype=int32)
>>> numpy.array(img.convert('L'))
array([[255, 255, 255, ..., 255, 255, 255],
       [255, 255, 255, ..., 255, 255, 255],
       [255, 255, 255, ..., 255, 255, 255],
       ...,
       [255, 255, 255, ..., 255, 255, 255],
       [255, 255, 255, ..., 255, 255, 255],
       [255, 255, 255, ..., 255, 255, 255]], dtype=uint8)

Floating point data really doesn't go over well either

>>> img_float = Image.fromarray(numpy.divide(numpy.array(img), 2**16-1))
>>> numpy.array(img_float)
array([[0.7867399 , 0.8045472 , 0.77630275, ..., 0.46529335, 0.47289234,
        0.45635158],
       [0.78954756, 0.79629207, 0.78158236, ..., 0.4706035 , 0.45654994,
        0.46987107],
       [0.78246737, 0.7710994 , 0.7801633 , ..., 0.48114747, 0.47077134,
        0.46770427],
       ...,
       [0.4316472 , 0.42523843, 0.4277409 , ..., 0.5244068 , 0.52239263,
        0.52356756],
       [0.41046768, 0.42064545, 0.4290837 , ..., 0.55281913, 0.52806896,
        0.50963604],
       [0.4267338 , 0.43067065, 0.42667276, ..., 0.5527275 , 0.5470512 ,
        0.5260853 ]], dtype=float32)
>>> img_oct = img_float.convert('L')
>>> numpy.array(img_oct)
array([[0, 0, 0, ..., 0, 0, 0],
       [0, 0, 0, ..., 0, 0, 0],
       [0, 0, 0, ..., 0, 0, 0],
       ...,
       [0, 0, 0, ..., 0, 0, 0],
       [0, 0, 0, ..., 0, 0, 0],
       [0, 0, 0, ..., 0, 0, 0]], dtype=uint8)
>>>

The input image is a 16 bit PNG made with GIMP, as attached below.
terrain_input.png

What versions of Pillow and Python are you using?

Using Python 3.6.5 and Pillow 5.1.0

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions