How to open a TIF (CMYK, 16-bit) image file?

。_饼干妹妹 提交于 2019-12-02 08:07:17

Seems like the other images are working, so I will focus on the 16 bit cmyk tif conversion to 8 bit rgb jpeg. I guess this approach will apply for other conversions too with a few tweaks.

Here are a few ways to convert it. The first two uses GDAL since you suggested that, the last approach uses libtiff, which i think is a slightly more appropriate for your use case.

GDAL from command line

From pure command line I got it working with two commands and an intermediate tif.

First convert the 16 bit tif to an 8 bit tif

gdal_translate -scale -ot byte -of GTIFF cmyk-16.tif cmyk-out.tif -co PHOTOMETRIC=CMYK

The file cmyk-out.tif is now in 8 bit. It can now be converted into jpeg with the following command

gdal_translate -of JPEG cmyk-out.tif cmyk-out.jpg

Hence you can just create a batch script chaining the two commands (and maybe deleting the intermediate tif)

GDAL (and numpy and PIL) from python

If the problem seems to be that the image can not be opened by PIL, you could use GDAL for the opening, numpy for the conversion to 8 bit and PIL for the conversion to RGB.

from osgeo import gdal
import numpy as np
from PIL import Image

def reduceDepth(image, display_min, display_max):
    image -= display_min
    image = np.floor_divide(image, (display_min - display_max + 1) / 256)
    image = image.astype(np.uint8)
    return image

raster = gdal.Open("cmyk-16.tif")
c = raster.GetRasterBand(1).ReadAsArray()
m = raster.GetRasterBand(2).ReadAsArray()
y = raster.GetRasterBand(3).ReadAsArray()
k = raster.GetRasterBand(4).ReadAsArray()

cmyk = np.dstack((c, m, y, k))
cmyk8 = reduceDepth(cmyk, 0, 65536)

im = Image.fromarray(cmyk8)
im = im.convert('RGB')
im.save("cmyk-out.jpeg")

Using libtiff instead of GDAL

You can also use libtiff to open the tif instead of gdal. Then the above script will look like this

import numpy as np
from PIL import Image
from libtiff import TIFF

input = TIFF.open("cmyk-16.tif").read_image()

def reduceDepth(image, display_min, display_max):
    image -= display_min
    image = np.floor_divide(image, (display_min - display_max + 1) / 256)
    image = image.astype(np.uint8)
    return image

v8 = reduceDepth(input, 0, 65536)

im = Image.fromarray(v8)
im = im.convert('RGB')
im.save("cmyk-out.jpeg")
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!