2012-05-04 3 views
5

Я попытался преобразовать 32-битный битмап в 32-разрядный PNG с использованием PIL.Загрузить растровое изображение RGBA с PIL

from PIL import Image 
im = Image.open('example.bmp') 
print im.mode 
# it prints 'RGB', but expected was 'RGBA' 
im.save('output.png', format='PNG') 

Ожидаемый режим изображения - «RGBA», но на самом деле я получаю «RGB».

Я также пробовал следующий код, но он не работает.

from PIL import Image 
im = Image.open('example.bmp') 
im = im.convert('RGBA') 
im.save('output.png', format='PNG') 
+1

Я считаю, что 32-битный файл растрового изображения является нестандартным форматом, который не поддерживает PIL. Пытаясь записать RGBA-изображение в .bmp, выдается ошибка 'can not write mode RGBA as BMP'. –

ответ

3

Хорошо, вот что с чего начать. Поскольку я не знаю конкретно, какой формат является вашим файлом BMP, я обрабатывал только конкретный случай BMP с полным альфа-каналом, который у меня есть. Вид BMP, который я обрабатываю здесь, может быть получен путем преобразования, например, PNG с альфой в BMP с использованием ImageMagick. Это создаст так называемое «BITMAPV5». Учитывая ваше описание, у вас нет BitmapV5 (потому что PIL не смог бы даже открыть его), поэтому нам понадобится итерация с обсуждениями для решения вашего конкретного случая.

Итак, вам либо нужен новый файловый декодер, либо исправленный BmpImagePlugin.py. Как сделать первый, описано в руководстве PIL. Для более позднего вам, очевидно, нужно будет отправить патч и надеяться получить его в следующей версии PIL. Мое внимание сосредоточено на создании нового декодера:

from PIL import ImageFile, BmpImagePlugin 

_i16, _i32 = BmpImagePlugin.i16, BmpImagePlugin.i32 

class BmpAlphaImageFile(ImageFile.ImageFile): 
    format = "BMP+Alpha" 
    format_description = "BMP with full alpha channel" 

    def _open(self): 
     s = self.fp.read(14) 
     if s[:2] != 'BM': 
      raise SyntaxError("Not a BMP file") 
     offset = _i32(s[10:]) 

     self._read_bitmap(offset) 

    def _read_bitmap(self, offset): 

     s = self.fp.read(4) 
     s += ImageFile._safe_read(self.fp, _i32(s) - 4) 

     if len(s) not in (40, 108, 124): 
      # Only accept BMP v3, v4, and v5. 
      raise IOError("Unsupported BMP header type (%d)" % len(s)) 

     bpp = _i16(s[14:]) 
     if bpp != 32: 
      # Only accept BMP with alpha. 
      raise IOError("Unsupported BMP pixel depth (%d)" % bpp) 

     compression = _i32(s[16:]) 
     if compression == 3: 
      # BI_BITFIELDS compression 
      mask = (_i32(self.fp.read(4)), _i32(self.fp.read(4)), 
        _i32(self.fp.read(4)), _i32(self.fp.read(4))) 
      # XXX Handle mask. 
     elif compression != 0: 
      # Only accept uncompressed BMP. 
      raise IOError("Unsupported BMP compression (%d)" % compression) 

     self.mode, rawmode = 'RGBA', 'BGRA' 

     self.size = (_i32(s[4:]), _i32(s[8:])) 
     direction = -1 
     if s[11] == '\xff': 
      # upside-down storage 
      self.size = self.size[0], 2**32 - self.size[1] 
      direction = 0 

     self.info["compression"] = compression 

     # data descriptor 
     self.tile = [("raw", (0, 0) + self.size, offset, 
      (rawmode, 0, direction))] 

Чтобы правильно использовать это, канонический путь якобы для выполнения:

from PIL import Image 
Image.register_open(BmpAlphaImageFile.format, BmpAlphaImageFile) 
# XXX register_save 

Image.register_extension(BmpAlphaImageFile.format, ".bmp") 

Проблема заключается в том, что уже существует плагин для обработки».bmp », и я не потрудился узнать, как я мог бы добавить это новое расширение, поэтому он используется до использования BmpImagePlugin (я также не знаю, можно ли это сделать в PIL). Говорит, что, я на самом деле использовали код непосредственно, как в:

from BmpAlphaImagePlugin import BmpAlphaImageFile 

x = BmpAlphaImageFile('gearscolor.bmp') 
print x.mode 
x.save('abc1.png') 

Где gearscolor.bmp представляет собой образец растрового изображения с полным альфа-каналом, как описано ранее. Получившийся png сохраняется с альфа-данными. Если вы проверите код BmpImagePlugin.py, вы заметите, что я использовал большую часть своего кода.

+0

У меня есть ошибка «Неподдерживаемый тип заголовка BMP (40)» для моего растрового файла – stanleyxu2005

+0

Я ожидал этого. Можете ли вы загрузить свой конкретный bmp где-нибудь? – mmgp

+0

См. Обновленный код, мне едва нужно что-то изменить для обработки вашего формата файла. – mmgp

0

PIL неисправен и не работает должным образом с прозрачными файлами BMP.

Если я хорошо помню, что wxPython, похоже, правильно работает с ними. Я написал небольшую обертку между ними около года назад, только если бы смог найти код.

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