Как прочитать сырое изображение с помощью 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 () является 'mode'. Однако, глядя на документацию и поиск в Google, я не смог найти подробностей о том, что на самом деле означает этот аргумент (я считаю, что он связан с цветовым пространством или чем-то в этом роде). Кто-нибудь знает, где я могу найти более подробную ссылку о функции fromstring () и что означает аргумент mode?
4 ответа
Конкретная документация находится по адресу http://effbot.org/imagingbook/concepts.htm:
Режим
Режим изображения определяет тип и глубину пикселя в изображении. Текущая версия поддерживает следующие стандартные режимы:
- 1 (1-битные пиксели, черно-белые, сохраняются с одним пикселем на байт)
- L (8-битные пиксели, черно-белые)
- P (8-битные пиксели, сопоставленные с любым другим режимом с использованием цветовой палитры)
- RGB (3x8-битные пиксели, настоящий цвет)
- RGBA (4x8-битные пиксели, настоящий цвет с маской прозрачности)
- CMYK (4x8-битные пиксели, цветоделение)
- YCbCr (3x8-битные пиксели, цветной видеоформат)
- I (32-разрядное целое число со знаком)
- F (32-битные пиксели с плавающей точкой)
PIL также обеспечивает ограниченную поддержку для нескольких специальных режимов, включая LA (L с альфа-каналом), RGBX (истинный цвет с отступом) и RGBa (истинный цвет с предварительно умноженным альфа-каналом).
Image.frombuffer(режим, размер, данные) => изображение
(Новое в PIL 1.1.4). Создает память изображений из данных пикселей в строковом или буферном объекте, используя стандартный "сырой" декодер. В некоторых режимах память изображений разделяет память с исходным буфером (это означает, что изменения в исходном объекте буфера отражаются на изображении). Не все режимы могут совместно использовать память; Поддерживаемые режимы включают "L", "RGBX", "RGBA" и "CMYK". Для других режимов эта функция ведет себя как соответствующий вызов функции fromstring.
Я не уверен, что означает "L", но "RGBA" означает "красный-зеленый-синий-альфа", поэтому я предполагаю, что RGBX эквивалентен RGB (редактировать: после тестирования это не так)? CMYK это Cyan-Magenta-Yellow-Kelvin, который является другим типом цветового пространства. Конечно, я предполагаю, что если вы знаете о PIL, вы также знаете о цветовых пространствах. Если нет, то в Википедии есть отличная статья.
Что касается того, что это действительно означает (если этого недостаточно): значения пикселей будут кодироваться по-разному для каждого цветового пространства. В обычном RGB у вас есть 3 байта на пиксель - 0-254, 0-254, 0-254. Для Альфы вы добавляете еще один байт к каждому пикселю. Если вы декодируете изображение 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. Вообще-то, это забавный эксперимент.
Если ничего не помогает, вы всегда можете прочитать исходный код. Для PIL, загрузки здесь.
Вы никогда не говорили точно, в каком формате были пиксельные данные в 16-битных целых числах без знака, но я бы предположил, что это что-то вроде RRRRRGGGGGGBBBBBB (5-битный красный, 6-битный зеленый, 5-битный синий) или RRRRRGGGGGBBBBBA (5- красный бит, 5-битный зеленый, 5-битный синий, 1-битная альфа или прозрачность). Я не видел поддержки этих форматов после очень быстрого просмотра некоторых источников самостоятельно, но точно не могу сказать, так или иначе.
На той же веб-странице, где находятся загрузки PIL, они упоминают, что можно отправлять вопросы в список рассылки Python Image SIG и предоставлять ссылку на него. Это может быть лучшим источником, чем спрашивать здесь.
Надеюсь это поможет.
Это старый вопрос, но это может помочь кому-то в будущем. Одна из проблем с оригинальным фрагментом кода заключается в том, что в 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')