2015-07-08 5 views
4

У базовой функции Image.resize подушки нет никаких параметров для фильтрации с поддержкой SRGB. Есть ли способ изменить размеры SRGB в подушке?SRGB-изображение для изменения размера изображения в подушке

Я мог бы сделать это вручную, преобразовывая изображение в плавающее и применяя преобразования SRGB самостоятельно ... но я надеюсь, что есть встроенный способ.

+0

Непонятно, что для изменения размера изображения требуется знание SRGB. Что заставляет вас думать, что это так? – martineau

+0

@martineau Если размер изображения меньше, видимая яркость в идеале не должна меняться. Если вы не осведомлены о цветовом пространстве, оно * изменится. –

+0

Точнее, If * c (r ', g', b ') * коммутирует с формулой интерполяции, тогда и только тогда осознание c не требуется. * C * для sRGB не является линейным, поэтому он не коммутирует ни с одним линейным фильтром. Может случиться, что он коммутирует с умножением и степенями. Я должен легко доказать или опровергнуть через простую вещественную алгебру.Но это не используется для изменения размера изображения, так что в этом случае это не имеет значения. – user877329

ответ

2

Я закончил реализацию sRGB-aware, изменив размер самостоятельно, используя следующую процедуру. Он занимает 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) 
1

99% реализаций изображения не будут иметь права sRGB (что, к сожалению, составляет 99,9% от материала изображения), а те, кто обычно делает это правильно, по умолчанию и дают вам возможность отказаться от гамма-де/кодирование.

[упрямый режим включен, ознакомьтесь с осторожностью]

IOW, если нет опции вы, вероятно, придется добавить код самостоятельно - или просто использовать pamscale. Если библиотека не получит права sRGB, в любом случае у нее будут другие недостатки.

[упрямый режим выключен]

Вы можете де/кодировать себя, как описано в

http://www.imagemagick.org/discourse-server/viewtopic.php?t=15955

но от быстрого взгляда, кажется, подушка не может делать этот трюк.

+0

Я сделал это сам, преобразовывая изображение в массив numpy, применяя преобразование sRGB-to-linear, обратно к изображению Pillow (теперь с плавающей запятой), изменяя размер, а затем обратно в numpy, linear-to-sRGB , круглые до 8-бит и, наконец, обратно в подушку. Я отправлю ответ с кодом в следующий раз, когда я на работе. Вздох. –

+0

Рад, что вы это сделали - к сожалению, это пример дополнительных усилий, требуемых для правильного масштабирования изображения. Можно подумать, что для этого нужны библиотеки, например, подушки;) –

+0

Я разделяю ваш мрачный взгляд на библиотеки обработки изображений, которые не обрабатывают гамма должным образом. Интересно, существует ли тот, который даже существует ... –

0

После долгих чтений и испытаний и ошибок я наткнулся на хорошее решение. Он принимает изображение sRGB, преобразует его в линейное цветовое пространство для изменения размера, а затем преобразует обратно в sRGB.

Существует небольшая недостатка в том, что глубина цвета 8 бит на пиксель используется даже тогда, когда изображение находится в линейной форме. Это приводит к потере дисперсии в более темных регионах. Чтение с this issue post кажется, что нет способа конвертировать в более высокую глубину, используя, к сожалению, Pillow.

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 цветовой профиль в качестве подушки/LCMS не может сделать это без. Вы можете получить его от this issue 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-битного цветового пространства.

Смежные вопросы