Как читать сырое изображение с помощью PIL?
У меня есть исходное изображение, где каждый пиксель соответствует целому числу без знака 16 бит. Я пытаюсь читать с помощью функции PIL Image.fromstring(), как в следующем коде:
if __name__ == "__main__":
if (len(sys.argv) != 4):
print 'Error: missing input argument'
sys.exit()
file = open(sys.argv[1], 'rb')
rawData = file.read()
file.close()
imgSize = (int(sys.argv[2]), int(sys.argv[3]))
# Use the PIL raw decoder to read the data.
# - the 'F;16' informs the raw decoder that we are reading a little endian, unsigned integer 16 bit data.
img = Image.fromstring('L', imgSize, rawData, 'raw', 'F;16')
im.save('out.png')
Документация PIL сообщает, что первым аргументом функции fromstring() является "режим". Однако, глядя на документацию и поиск в Google, я не смог найти подробностей о том, что на самом деле означает этот аргумент (я считаю, что это связано с цветовым пространством или что-то в этом роде). Кто-нибудь знает, где я могу найти более подробную ссылку о функции fromstring() и что означает аргумент mode?
Ответы
Ответ 1
Конкретная документация находится на http://effbot.org/imagingbook/concepts.htm:
Mode
Режим изображения определяет тип и глубину пикселя в изображении. текущая версия поддерживает следующие стандартные режимы:
- 1 (1-битные пиксели, черно-белые, сохраненные с одним пикселем на каждый байт)
- L (8-битные пиксели, черно-белые)
- P (8-битные пиксели, отображаемые в любой другой режим с использованием цветовой палитры)
- RGB (3х8-битные пиксели, истинный цвет)
- RGBA (4x8-битные пиксели, истинный цвет с маской прозрачности)
- CMYK (4x8-битные пиксели, цветоделение)
- YCbCr (3х8-битные пиксели, цветной формат видео)
- я (32-разрядные знаковые целочисленные пиксели)
- F (32-разрядные пиксели с плавающей запятой)
PIL также обеспечивает ограниченную поддержку несколько специальных режимов, включая LA (L с альфой), RGBX (истинный цвет с padding) и RGBa (истинный цвет с предварительно умноженная альфа).
Ответ 2
Image.frombuffer(режим, размер, данные) = > изображение
(Новое в PIL 1.1.4). Создает память изображений из пиксельных данных в строке или буфере, используя стандартный "необработанный" декодер. В некоторых режимах память изображений будет совместно использовать память с исходным буфером (это означает, что изменения в исходном буфере объекта отражаются на изображении). Не все режимы могут обмениваться памятью; поддерживаемые режимы включают "L", "RGBX", "RGBA" и "CMYK". Для других режимов эта функция ведет себя как соответствующий вызов функции fromstring.
Я не уверен, что означает "L", но "RGBA" означает Red-Green-Blue-Alpha, поэтому я предполагаю, что RGBX эквивалентен RGB (изменить: при тестировании это не так)? CMYK - Cyan-Magenta-Yellow-Kelvin, который является другим типом цветового пространства. Конечно, я предполагаю, что, если вы знаете о PIL, вы также знаете о цветовых пространствах. Если нет, Wikipedia имеет отличную статью.
Что касается того, что на самом деле означает (если этого недостаточно): значения пикселей будут закодированы по-разному для каждого цветового пространства. В регулярном RGB у вас есть 3 байта на пиксель - 0-254, 0-254, 0-254. Для Alpha вы добавляете еще один байт на каждый пиксель. Если вы декодируете RGB-изображение как RGBA, вы закончите чтение R-пикселя справа от первого пикселя в качестве альфы, что означает, что вы получите G-пиксель в качестве значения R. Это будет увеличено в зависимости от того, насколько велико ваш образ, но это действительно сделает ваши цвета неудобными. Точно так же попытка считывать изображение с кодировкой CMYK как RGB (или RGBA) сделает ваше изображение очень не похожим на него. Например, попробуйте сделать это с изображением:
i = Image.open('image.png')
imgSize = i.size
rawData = i.tostring()
img = Image.fromstring('L', imgSize, rawData)
img.save('lmode.png')
img = Image.fromstring('RGB', imgSize, rawData)
img.save('rgbmode.png')
img = Image.fromstring('RGBX', imgSize, rawData)
img.save('rgbxmode.jfif')
img = Image.fromstring('RGBA', imgSize, rawData)
img.save('rgbamode.png')
img = Image.fromstring('CMYK', imgSize, rawData)
img.save('rgbamode.tiff')
И вы увидите, что делают разные режимы - попробуйте использовать различные входные изображения: png с альфой, png без альфа, bmp, gif и jpeg. Это действительно забавный эксперимент.
Ответ 3
Если все остальное не удается, вы всегда можете прочитать исходный код. Для PIL загрузки здесь.
Вы точно не указали, в каком формате были пиксельные данные в 16-битных целых числах без знака, но я бы предположил, что это что-то вроде RRRRRGGGGGGBBBBBB (5-битный красный, 6-битный зеленый, 5-битовый синий) или RRRRRGGGGGBBBBBA (5-битный красный, 5-битный зеленый, 5-битный синий, 1-битный альфа или прозрачность). Я не видел поддержки этих форматов после очень быстрого просмотра некоторых источников, но не могу сказать точно так или иначе.
На той же веб-странице, где находятся загрузки PIL, они упоминают, что можно отправить вопросы в список рассылки Python Image SIG и предоставить для нее ссылку. Это может быть лучшим источником, чем просить здесь.
Надеюсь, что это поможет.
Ответ 4
Это старый вопрос, но это может помочь кому-то в будущем. Одна из проблем с исходным фрагментом кода заключается в том, что в Image.fromstring('L', imgSize, rawData, 'raw', 'F;16')
часть F;16
работает в режиме 'F'
.
Это работает для меня:
image = Image.fromstring('F', imgSize, rawData, 'raw', 'F;16')
image.convert('L').save('out.png')