Repository: python-pillow/Pillow

Issue:
Add support for dib images
https://www.imagemagick.org/script/formats.php

> DIB is a BMP file without the BMP header.





Discussion:

Resolving patch:
diff --git a/src/PIL/BmpImagePlugin.py b/src/PIL/BmpImagePlugin.py
--- a/src/PIL/BmpImagePlugin.py
+++ b/src/PIL/BmpImagePlugin.py
@@ -52,6 +52,10 @@ def _accept(prefix):
     return prefix[:2] == b"BM"
 
 
+def _dib_accept(prefix):
+    return i32(prefix[:4]) in [12, 40, 64, 108, 124]
+
+
 # =============================================================================
 # Image plugin for the Windows BMP format.
 # =============================================================================
@@ -291,7 +295,11 @@ def _open(self):
 }
 
 
-def _save(im, fp, filename):
+def _dib_save(im, fp, filename):
+    _save(im, fp, filename, False)
+
+
+def _save(im, fp, filename, bitmap_header=True):
     try:
         rawmode, bits, colors = SAVE[im.mode]
     except KeyError:
@@ -306,14 +314,15 @@ def _save(im, fp, filename):
 
     stride = ((im.size[0]*bits+7)//8+3) & (~3)
     header = 40  # or 64 for OS/2 version 2
-    offset = 14 + header + colors * 4
     image = stride * im.size[1]
 
     # bitmap header
-    fp.write(b"BM" +                      # file type (magic)
-             o32(offset+image) +          # file size
-             o32(0) +                     # reserved
-             o32(offset))                 # image data offset
+    if bitmap_header:
+        offset = 14 + header + colors * 4
+        fp.write(b"BM" +                      # file type (magic)
+                 o32(offset+image) +          # file size
+                 o32(0) +                     # reserved
+                 o32(offset))                 # image data offset
 
     # bitmap info header
     fp.write(o32(header) +                # info header size
@@ -352,3 +361,10 @@ def _save(im, fp, filename):
 Image.register_extension(BmpImageFile.format, ".bmp")
 
 Image.register_mime(BmpImageFile.format, "image/bmp")
+
+Image.register_open(DibImageFile.format, DibImageFile, _dib_accept)
+Image.register_save(DibImageFile.format, _dib_save)
+
+Image.register_extension(DibImageFile.format, ".dib")
+
+Image.register_mime(DibImageFile.format, "image/bmp")


Test patch:
diff --git a/Tests/test_file_bmp.py b/Tests/test_file_bmp.py
--- a/Tests/test_file_bmp.py
+++ b/Tests/test_file_bmp.py
@@ -16,6 +16,7 @@ def roundtrip(self, im):
         self.assertEqual(im.mode, reloaded.mode)
         self.assertEqual(im.size, reloaded.size)
         self.assertEqual(reloaded.format, "BMP")
+        self.assertEqual(reloaded.get_format_mimetype(), "image/bmp")
 
     def test_sanity(self):
         self.roundtrip(hopper())
@@ -72,6 +73,20 @@ def test_save_bmp_with_dpi(self):
 
     def test_load_dib(self):
         # test for #1293, Imagegrab returning Unsupported Bitfields Format
-        im = BmpImagePlugin.DibImageFile('Tests/images/clipboard.dib')
+        im = Image.open('Tests/images/clipboard.dib')
+        self.assertEqual(im.format, "DIB")
+        self.assertEqual(im.get_format_mimetype(), "image/bmp")
+
         target = Image.open('Tests/images/clipboard_target.png')
         self.assert_image_equal(im, target)
+
+    def test_save_dib(self):
+        outfile = self.tempfile("temp.dib")
+
+        im = Image.open('Tests/images/clipboard.dib')
+        im.save(outfile)
+
+        reloaded = Image.open(outfile)
+        self.assertEqual(reloaded.format, "DIB")
+        self.assertEqual(reloaded.get_format_mimetype(), "image/bmp")
+        self.assert_image_equal(im, reloaded)