Метод сохранения подушки игнорирует информационные параметры

Я хочу читать, манипулировать, а затем сохранять изображение png, сохраняя при этом его исходные info свойства, в основном gamma. Я использую Pillow версию 9.0.1

В коде SO упоминается, что это можно сделать так:

from PIL import Image
img = Image.open("sample.png") # Sample image provided below code block
info = img.info
img.save("output.png", **info)

Образец изображения

Но info не переносится; изображения больше не похожи друг на друга из-за потери информации gamma и, что еще более очевидно, с помощью теста:

# Test
output_info = Image.open("output.png").info
print(info)                  # {'gamma': 2147.48365}
print(output_info)           # {}
print(output_info == info)   # False, should be True

Вопрос: Почему PIL's Image.saveнет пишет gamma?

Это не относится к gamma, никакой другой фрагмент не записывается так, как chromaticity и text.


sample.png по сравнению с output.png (при просмотре с помощью средства просмотра с поддержкой gAMA, например хрома) Метод сохранения подушки игнорирует информационные параметры

"... без использования PngInfo..." вы имеете в виду PngInfo в PIL? И какие возражения против этого, пожалуйста?
Mark Setchell 24.03.2022 08:40

@MarkSetchell Я не хочу спорить с байтами и иметь дело со стандартами. Параметра Image.savepnginfo должно быть достаточно, но это не так. И я спрашиваю, почему это так. Я думаю, что мог иметь в виду, что мне нужно решение для встраивания информации о гамме, которого у меня нет.

freshpasta 24.03.2022 15:50

Возможно, в таком случае поднимите вопрос в репозитории PIL Github... и добавьте сюда ссылку, чтобы другие люди могли ее найти.

Mark Setchell 24.03.2022 16:32

@MarkSetchell Подойдет. Просто подумал, что у этого случая была другая задокументированная семантика, о которой я просто не знал. Спасибо.

freshpasta 24.03.2022 16:46
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
0
4
49
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Вот способ сделать то, что вы просите, без использования чего-либо внешнего. Он вставляет блок ГАМА следующим образом:

  • он получает ПИЛ для кодирования изображения в PNG "в памяти"
  • он открывает выходной файл на диске в двоичном режиме
  • затем он берет 8-байтовую сигнатуру PNG, созданную ПИЛ, и записывает ее на диск.
  • аналогично 25-байтовый ИХДР, созданный ПИЛ
  • затем он создает фрагмент ГАМА с вашим значением, добавляет длину, добавляет CRC и записывает на диск
  • затем он копирует оставшуюся часть сгенерированного образа ПИЛ на диск

Примечание: Спецификация PNG предусматривает, что сначала должна идти подпись, а затем блок ИХДР. Он также предусматривает, что ГАМА должен предшествовать ИДАТ, поэтому нет причин, по которым мой код должен создавать недопустимый PNG, если только:

  • ПИЛ внезапно начинает генерировать фрагменты ГАМА, что привело бы к множеству таких фрагментов и было бы незаконным, но мы делаем это только потому, что PIL не записывает фрагменты ГАМА, или

  • предоставлено необоснованное значение гаммы, или

  • некоторый аспект записи в PNG на диск завершается сбоем из-за переполнения диска или другой ошибки ввода-вывода.


#!/usr/bin/env python3

import zlib
import struct
from io import BytesIO
from PIL import Image

def savePNGwithGamma(im, filename, gamma):
   """Save the image as PNG with specified gamma"""

   # Encode as PNG into memory buffer
   buffer = BytesIO()
   im.save(buffer, 'PNG')

   # Seek back to start of in-memory PNG
   buffer.seek(0)
   # Open output file in binary mode
   with open(filename, 'wb') as fd:
      # Read 8-byte PNG signature from memory and write to on-disk PNG
      signature = buffer.read(8)
      fd.write(signature)
      # Read 25-byte PNG IHDR chunk from memory and write to on-disk PNG
      IHDR = buffer.read(25)
      fd.write(IHDR)

      # Create our lovely new gAMA chunk - https://www.w3.org/TR/2003/REC-PNG-20031110/#11gAMA
      # Network byte ordering, scale factor of 100000
      gAMA = b'gAMA' + struct.pack('!I',int(gamma*100000))
      # 4-byte length, gAMA chunk, 4-byte CRC
      gAMA = struct.pack('!I', 4) + gAMA + struct.pack('!I', zlib.crc32(gAMA))
      # Insert into on-disk PNG after IHDR and before anything else such as PLTE, IDAT, IEND
      fd.write(gAMA)

      # Write remainder of PNG from memory to disk
      fd.write(buffer.read())

################################################################################
# main
################################################################################

# Load sample image
im = Image.open('sample.png')

# Save with desired gamma
savePNGwithGamma(im, 'result.png', 2.2)

Я действительно ценю ответ с большими усилиями, но это не то, что я ищу. Я прочитал Ваш ответ 2 года назад, где вы упомянули «Я не знаю, почему Pillow не может сохранить информацию о вашей гамме», и это то, что я хочу знать. Прошу прощения, возможно мой вопрос был не ясен.

freshpasta 24.03.2022 16:05
Ответ принят как подходящий

Похоже, мои ожидания не оправдались. Средство записи файлов PNG PIL не поддерживает аргумент ключевого слова gamma, поэтому он молча игнорируется. Точно так, как задокументировано:

The save() method supports the following options:

  • Image.save игнорирует нераспознанные аргументы ключевого слова:

Keyword options can be used to provide additional instructions to the writer. If a writer doesn’t recognise an option, it is silently ignored.

Другие вопросы по теме