С sRGB-понимают изменение размера изображения в подушку
Основная подушка Image.resize
функция, по-видимому, не имеет никаких опций для sRGB-aware фильтрации. Есть ли способ сделать SRGB-сознательное изменение размера в подушке?
Я мог бы сделать это вручную, преобразовав изображение в float и применив преобразование SRGB самостоятельно...но я надеюсь, что есть встроенный способ.
3 ответа:
В итоге я реализовал sRGB-aware resize, используя следующую процедуру. Он принимает 8-битное изображение RGB и целевой размер и фильтр повторной дискретизации.
from PIL import Image import numpy as np def SRGBResize(im, size, filter): # Convert to numpy array of float arr = np.array(im, dtype=np.float32) / 255.0 # Convert sRGB -> linear arr = np.where(arr <= 0.04045, arr/12.92, ((arr+0.055)/1.055)**2.4) # Resize using PIL arrOut = np.zeros((size[1], size[0], arr.shape[2])) for i in range(arr.shape[2]): chan = Image.fromarray(arr[:,:,i]) chan = chan.resize(size, filter) arrOut[:,:,i] = np.array(chan) # Convert linear -> sRGB arrOut = np.where(arrOut <= 0.0031308, 12.92*arrOut, 1.055*arrOut**(1.0/2.4) - 0.055) # Convert to 8-bit arrOut = np.uint8(np.rint(arrOut * 255.0)) # Convert back to PIL return Image.fromarray(arrOut)
После долгого чтения и проб и ошибок я наткнулся на хорошее решение. Он принимает изображение sRGB, преобразует его в линейное цветовое пространство для изменения размера, а затем преобразует обратно в sRGB.
Есть небольшой недостаток в том, что глубина цвета 8 бит на пиксель используется даже тогда, когда изображение имеет линейную форму. Это приводит к потере дисперсии в более темных областях. Чтение из этого выпуска post кажется, что нет никакого способа преобразовать в большую глубину с помощью подушки к несчастью.
from PIL import Image from PIL.ImageCms import profileToProfile SRGB_PROFILE = 'sRGB.icc' LINEARIZED_PROFILE = 'linearized-sRGB.icc' im = Image.open(IN_PATH) im = profileToProfile(im, SRGB_PROFILE, LINEARIZED_PROFILE) im = im.resize((WIDTH, HEIGHT), Image.ANTIALIAS) im = profileToProfile(im, LINEARIZED_PROFILE, SRGB_PROFILE) im.save(OUT_PATH)
Вам понадобится линеаризованный цветовой профиль ICC, поскольку Pillow/lcms не может обойтись без него. Вы можете получить один из этого выпуска post и автор упоминает в файле "нет авторских прав, использовать свободно". Вам также понадобится профиль sRGB, который должен быть легко доступен из вашей операционной системы или онлайн.
Большая часть времени обработки занимает вычисление преобразований из sRGB и обратно. Если вы собираетесь делать много этих операций, вы можете хранить их преобразования, чтобы повторно использовать их следующим образом:
from PIL.ImageCms import buildTransform, applyTransform SRGB_TO_LINEARIZED = buildTransform(SRGB_PROFILE, LINEARIZED_PROFILE, 'RGB', 'RGB') LINEARIZED_TO_SRGB = buildTransform(LINEARIZED_PROFILE, SRGB_PROFILE, 'RGB', 'RGB') im = applyTransform(im, SRGB_TO_LINEARIZED) im = im.resize((WIDTH, HEIGHT), Image.ANTIALIAS) im = applyTransform(im, LINEARIZED_TO_SRGB)
Я надеюсь, что это поможет, и мне было бы интересно узнать, есть ли у кого-нибудь идеи по решению проблемы 8-битного цветового пространства.
99% реализаций изменения размера изображения не получат sRGB правильно (что, к сожалению, составляет 99,9% материала изображения), а те, кто это делает, обычно делают это правильно по умолчанию и дают вам возможность отказаться от gamma de/encoding.
[самоуверенный режим включен, читайте внимательно]
IOW, если нет возможности, вам, вероятно, придется добавить код самостоятельно - или просто использовать pamscale. Если библиотека не получает sRGB правильно, у нее все равно будут другие недостатки.
[самоуверенный режим выключен]
Ты можно ли де / кодировать себя, как описано в
Http://www.imagemagick.org/discourse-server/viewtopic.php?t=15955
Но с первого взгляда кажется, что подушка не способна на этот трюк.