После долгих чтений и испытаний и ошибок я наткнулся на хорошее решение. Он принимает изображение 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-битного цветового пространства.
Непонятно, что для изменения размера изображения требуется знание SRGB. Что заставляет вас думать, что это так? – martineau
@martineau Если размер изображения меньше, видимая яркость в идеале не должна меняться. Если вы не осведомлены о цветовом пространстве, оно * изменится. –
Точнее, If * c (r ', g', b ') * коммутирует с формулой интерполяции, тогда и только тогда осознание c не требуется. * C * для sRGB не является линейным, поэтому он не коммутирует ни с одним линейным фильтром. Может случиться, что он коммутирует с умножением и степенями. Я должен легко доказать или опровергнуть через простую вещественную алгебру.Но это не используется для изменения размера изображения, так что в этом случае это не имеет значения. – user877329