Skip to content Skip to sidebar Skip to footer

Resizing A 48bit Png Retaining Its 48bits, Without Dropping It To A 24bit File

I'm trying to resize the following 48bit PNG from 1242 x 375 to 256 x 256 but retain its 48 bits. This PNG Ground Truth Image is available for download here I was wondering if the

Solution 1:

You can use imageio with freeimage library using format='PNG-FI' in imageio.imread / imageoio.imwrite.

Based on information in source code of freeimage.py in imageio to install freeimage library you can use imageio:

  • in command line (on Linux it works even without full path)

    imageio_download_bin freeimage
    
  • using python code

    import imageio
    
    imageio.plugins.freeimage.download()
    

Probably if you install library (.dll/.so) directly from FreeImage webpage then it will also work.


Image has to be copied (img.copy()). Because making image smaller it removed pixels with the biggest values so I work with part of image and make its bigger.

# read 48bit color
img = imageio.imread("..\\..\\000000_10.png", format='PNG-FI')

# max values in imageprint('shape:', img.shape)
print('max R:', img[:,:,0].max())
print('max G:', img[:,:,1].max())
print('max B:', img[:,:,2].max())
print('---')

# cut-off part of image (with)
img = img.copy()
img = img[370:375,1020:1025,:]
img = img.copy()
img.resize((256,256,3))

print('shape:', img.shape)
print('max R:', img[:,:,0].max())
print('max G:', img[:,:,1].max())
print('max B:', img[:,:,2].max())
print('---')

# find X,Y for first max red valueprint('max X:', img[:,:,0].max(axis=0).argmax())
print('max Y:', img[:,:,0].max(axis=1).argmax())
print(' flat:', img[:,:,0].argmax())
print('---')

# find X,Y for all max red values
max_r = img[:,:,0].max()

for y, row inenumerate(img[:,:,0]):
    for x, it inenumerate(row):
        if it == max_r:
            print('value/x/y:', max_r, x, y)

# write 48bit color
imageio.imwrite('output_48bit.png', img, format='PNG-FI')

Output:

shape:(375,1242,3)max R:40827max G:36674max B:1---shape:(256,256,3)max R:40827max G:36506max B:1---max X:14max Y:0flat:14---value/x/y:40827140

In Linux I can use program `file in command line to check if file use 48bit color (16bits per color)

$file000000_10.png000000_10.png:PNGimagedata,1242 x375,16-bit/colorRGB,non-interlaced$fileoutput_48bit.pngoutput_48bit.png:PNGimagedata,256x256,16-bit/colorRGB,non-interlaced

If you have RGBA then it will use 64bit color.

Example from imageio issues: Unable to properly read multi-channel 16-bit png files

import imageio
import numpy as np

img_out = np.zeros((256, 256, 4), dtype=np.uint16)
color_grad = np.reshape(np.arange(2**16), (256,-1))
img_out[:, :, 0] = color_grad
img_out[:, :, 1] = np.rot90(color_grad, 1)
img_out[:, :, 2] = np.rot90(color_grad, 2)
img_out[:, :, 3] = np.rot90(color_grad, 3)

print('Write unique values: R={}, G={}, B={}, A={}'.format(
    len(set(img_out[:, :, 0].flatten().tolist())),
    len(set(img_out[:, :, 1].flatten().tolist())),
    len(set(img_out[:, :, 2].flatten().tolist())),
    len(set(img_out[:, :, 3].flatten().tolist()))))
imageio.imwrite('64bit_imageio.png', img_out, format='PNG-FI')

img_in_imageio = imageio.imread('64bit_imageio.png', format='PNG-FI')
print('imageio PNG unique values: R={}, G={}, B={}, A={}'.format(
    len(set(img_in_imageio[:, :, 0].flatten().tolist())),
    len(set(img_in_imageio[:, :, 1].flatten().tolist())),
    len(set(img_in_imageio[:, :, 2].flatten().tolist())),
    len(set(img_in_imageio[:, :, 3].flatten().tolist()))))

Output:

Write uniquevalues: R=65536, G=65536, B=65536, A=65536
imageio PNG uniquevalues: R=65536, G=65536, B=65536, A=65536

output_48bit.png: PNG image data, 5 x 5, 16-bit/color RGB, non-interlaced

EDIT: Your last code with more readable names for variables (lower_case_names) and few free lines to make it also more readable.

In original code you had mess so finally you wrote original image instead of resized one.

import cv2
import imageio

# need it only once #imageio.plugins.freeimage.download()

input_filename  = "..\\..\\000000_10.png"
output_filename = "..\\..\\000000_10_resized.png"

input_image  = imageio.imread(input_filename, format='PNG-FI')
output_image = cv2.resize(input_image, (256, 256))

imageio.imwrite(output_filename, output_image, format='PNG-FI')

Solution 2:

# Resize 48bit PNG file and maintain 48bit PNG when saving to file WORKINGimport cv2
import imageio
imageio.plugins.freeimage.download()
PNG_Location_Filepath = "..\\..\\000000_10.png"
Resized_Location_Filepath = "..\\..\\000000_10_resized.png"
img_in_imageio = imageio.imread(PNG_Location_Filepath, format='PNG-FI')
Resized_Image = cv2.resize(img_in_imageio, (256,256))
Saved_Filename = Resized_Location_Filepath
imageio.imwrite(Saved_Filename, Resized_Image, format='PNG-FI')

#This works to resize the image, keeping 48bits

Post a Comment for "Resizing A 48bit Png Retaining Its 48bits, Without Dropping It To A 24bit File"