Как открыть файл изображения в формате TIF (CMYK, 16-bit)? - PullRequest
0 голосов
/ 08 июня 2018

У меня есть скрипт, который обрабатывает десятки файлов изображений (используя подушку).Недавно я заметил, что мой скрипт не работает в формате TIF (CMYK / 16).Итак, я создал контрольный пример .

images = [
    "cmyk-8.tif",
    "cmyk-16.tif",
    "rgb-8.tif",
    "rgb-16.tif",
]

for img_name in images:
    path = img_dir + "\\" + img_name
    try:
        img = Image.open(path)
    except OSError as e:
        print(e)
    else:
        print("success: " + img_name)

. Это приводит к следующему выводу:

success: cmyk-8.tif
cannot identify image file '...\\cmyk-16.tif'
success: rgb-8.tif
success: rgb-16.tif

Так что проблема определенно связана с TIF (CMYK /16) формат.

Как открыть этот конкретный формат или преобразовать его в открываемый (?) Формат (т. Е. RGB / 8, RGB / 16, CMYK / 8), а затем открыть его?


В другом QA было предложено GDAL для решения проблемы.Я пробовал (установить GDAL, связать его с Python и заставить его работать с текущим скриптом), но в итоге отказался (слишком проблематично).Поэтому я решил просто сосредоточиться на gdal_translate .

Я установил "gdal-203-1911-x64-core.msi" из GISInternals и попытался выполнить преобразование:

"C:\Program Files\GDAL\gdal_translate.exe" -scale -ot byte -of JPEG "C:\Users\%username%\Documents\GitHub\dump\python\tif-cmyk-16\images\cmyk-16.tif" "cmyk-16.jpg"

но это не сработало.Я получил неправильное преобразование:

output comparison

Я не знаком с GDAL, поэтому я должен что-то делать не так.Как заставить это сделать правильное преобразование?

Кроме того, это вывод cmd:

ERROR 1: Can't load requested DLL: C:\Program Files\GDAL\gdalplugins\ogr_MSSQLSpatial.dll
126: The specified module could not be found.

ERROR 1: Can't load requested DLL: C:\Program Files\GDAL\gdalplugins\ogr_MSSQLSpatial.dll
126: The specified module could not be found.

Input file size is 200, 200
0...10...20...30...40...50...60...70...80...90...100 - done.
Press any key to continue . . .

Кажется, что-то не хватает, и я не знаю, если преобразование inccorectсвязано с этим.

Связанные скрипты и выходные файлы можно найти здесь .

1 Ответ

0 голосов
/ 09 июня 2018

Похоже, что другие изображения работают, поэтому я остановлюсь на 16-битном преобразовании cmyk tif в 8-битный rgb jpeg.Я полагаю, что этот подход будет применяться и для других конверсий с некоторыми изменениями.

Вот несколько способов конвертировать его.Первые два используют GDAL, поскольку вы предположили, что в последнем подходе используется libtiff, что, я думаю, немного более подходит для вашего варианта использования.

GDAL из командной строки

Из чистой командной строки я начал работать с двумя командами и промежуточным tif.

Сначала преобразовать 16-битный tif в 8-битный tif

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

Файл cmyk-out.tif теперь находится в 8 битах.Теперь его можно преобразовать в jpeg с помощью следующей команды

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

Следовательно, вы можете просто создать пакетный скрипт, объединяющий две команды (и, возможно, удалив промежуточный tif)

GDAL (и numpy и PIL) из python

Если проблема заключается в том, что изображение не может быть открыто PIL, вы можете использовать GDAL для открытия, numpy дляпреобразование в 8 бит и PIL для преобразования в 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")

Использование libtiff вместо GDAL

Вы также можете использовать libtiff, чтобы открыть tif вместо gdal,Тогда приведенный выше скрипт будет выглядеть так:

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")
...