2012-05-04 36 views
5

Tôi đã cố chuyển đổi bitmap 32 bit thành PNG 32 bit bằng PIL.Tải bitmap RGBA với 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') 

Chế độ hình ảnh dự kiến ​​là 'RGBA', nhưng thực sự tôi nhận được 'RGB'.

Tôi cũng đã thử mã sau, nhưng nó không hoạt động.

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

Tôi nghĩ rằng tệp bitmap 32 bit là định dạng không chuẩn mà PIL không hỗ trợ. Cố gắng để viết một hình ảnh RGBA để .bmp sản xuất lỗi 'không thể viết chế độ RGBA như BMP'. –

Trả lời

3

Ok, đây là một cái gì đó để bắt đầu. Vì tôi không biết cụ thể định dạng nào là tệp BMP của bạn nên tôi chỉ xử lý một trường hợp cụ thể của BMP với kênh alpha đầy đủ mà tôi đã có. Các loại BMP tôi đang xử lý ở đây có thể thu được bằng cách chuyển đổi, ví dụ, PNG với alpha sang BMP bằng cách sử dụng ImageMagick. Điều này sẽ tạo ra những gì được gọi là "BITMAPV5". Với mô tả của bạn, bạn không có BitmapV5 (vì PIL sẽ không mở được nó), vì vậy chúng tôi sẽ cần lặp lại với các cuộc thảo luận để giải quyết trường hợp cụ thể của bạn.

Vì vậy, bạn cần bộ giải mã tệp mới hoặc bản vá BmpImagePlugin.py được vá. Làm thế nào để làm việc trước đây được mô tả trong hướng dẫn sử dụng của PIL. Đối với sau này bạn rõ ràng sẽ cần phải gửi một bản vá và hy vọng để có được nó vào phiên bản kế tiếp PIL. Trọng tâm của tôi là về việc tạo ra một bộ giải mã mới:

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))] 

Để sử dụng đúng cách này, cách kinh điển được cho là để thực hiện:

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

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

Vấn đề là ở đó đã là một plugin để xử lý" .bmp ", và tôi không bận tâm để tìm hiểu làm thế nào tôi có thể thêm phần mở rộng mới này vì vậy nó được sử dụng trước khi BmpImagePlugin được sử dụng (tôi cũng không biết nếu nó có thể làm điều đó trong PIL). Nói rằng, tôi thực sự đã sử dụng mã trực tiếp, như sau:

from BmpAlphaImagePlugin import BmpAlphaImageFile 

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

Trường hợp gearscolor.bmp là bitmap mẫu có kênh alpha đầy đủ như được mô tả trước đó. Kết quả png được lưu với dữ liệu alpha. Nếu bạn kiểm tra mã của BmpImagePlugin.py, bạn sẽ thấy rằng tôi đã sử dụng lại hầu hết mã của nó.

+0

Tôi gặp lỗi "Loại đầu đề BMP không được hỗ trợ (40)" cho tệp bitmap – stanleyxu2005

+0

Tôi đã mong đợi điều đó. Bạn có thể tải lên bmp chính xác của bạn một nơi nào đó? – mmgp

+0

Xem mã được cập nhật, tôi hầu như không cần thay đổi bất kỳ thứ gì để xử lý định dạng tệp của bạn. – mmgp

0

PIL bị lỗi và không hoạt động đúng với tệp BMP trong suốt.

Nếu tôi nhớ rõ wxPython có vẻ hoạt động đúng với chúng. Tôi đã viết một wrapper nhỏ giữa hai khoảng một năm trước đây, chỉ khi tôi có thể tìm thấy mã.

Các vấn đề liên quan