Skip to content

Commit

Permalink
Merge pull request #1813 from wiredfool/DIB_1293
Browse files Browse the repository at this point in the history
Fix for DIB/BMP images
  • Loading branch information
hugovk committed Apr 6, 2016
2 parents 3242b5c + 0e3caec commit a7c678b
Show file tree
Hide file tree
Showing 5 changed files with 41 additions and 3 deletions.
21 changes: 18 additions & 3 deletions PIL/BmpImagePlugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,12 @@ def _bitmap(self, header=0, offset=0):
for idx, mask in enumerate(['r_mask', 'g_mask', 'b_mask', 'a_mask']):
file_info[mask] = i32(header_data[36+idx*4:40+idx*4])
else:
for mask in ['r_mask', 'g_mask', 'b_mask', 'a_mask']:
# 40 byte headers only have the three components in the bitfields masks,
# ref: https://msdn.microsoft.com/en-us/library/windows/desktop/dd183376(v=vs.85).aspx
# See also https://github.com/python-pillow/Pillow/issues/1293
# Note below, None is a key in the SUPPORTED and MASK_MODES structures.
file_info['a_mask'] = None
for mask in ['r_mask', 'g_mask', 'b_mask']:
file_info[mask] = i32(read(4))
file_info['rgb_mask'] = (file_info['r_mask'], file_info['g_mask'], file_info['b_mask'])
file_info['rgba_mask'] = (file_info['r_mask'], file_info['g_mask'], file_info['b_mask'], file_info['a_mask'])
Expand All @@ -130,12 +135,22 @@ def _bitmap(self, header=0, offset=0):
# ----------------- Process BMP with Bitfields compression (not palette)
if file_info['compression'] == self.BITFIELDS:
SUPPORTED = {
32: [(0xff0000, 0xff00, 0xff, 0x0), (0xff0000, 0xff00, 0xff, 0xff000000), (0x0, 0x0, 0x0, 0x0)],
32: [(0xff0000, 0xff00, 0xff, 0x0),
(0xff0000, 0xff00, 0xff, None),
(0xff0000, 0xff00, 0xff, 0xff000000),
(0x0, 0x0, 0x0, 0x0)],
24: [(0xff0000, 0xff00, 0xff)],
16: [(0xf800, 0x7e0, 0x1f), (0x7c00, 0x3e0, 0x1f)]
}
# From inspecting DIB files from Vista screenshots, the
# file format is a 32 bit color image, where the 'Alpha'
# channel for screenshots is actually a transparency mask
# (255-alpha) where 00 is solid and ff is transparent. I
# can't find documentation of this, but it matches
# imagemagick's conversion of the .dib file into a .png.
MASK_MODES = {
(32, (0xff0000, 0xff00, 0xff, 0x0)): "BGRX",
(32, (0xff0000, 0xff00, 0xff, None)): "BGRT",
(32, (0xff0000, 0xff00, 0xff, 0xff000000)): "BGRA",
(32, (0x0, 0x0, 0x0, 0x0)): "BGRA",
(24, (0xff0000, 0xff00, 0xff)): "BGR",
Expand All @@ -145,7 +160,7 @@ def _bitmap(self, header=0, offset=0):
if file_info['bits'] in SUPPORTED:
if file_info['bits'] == 32 and file_info['rgba_mask'] in SUPPORTED[file_info['bits']]:
raw_mode = MASK_MODES[(file_info['bits'], file_info['rgba_mask'])]
self.mode = "RGBA" if raw_mode in ("BGRA",) else self.mode
self.mode = "RGBA" if raw_mode in ("BGRA", "BGRT") else self.mode
elif file_info['bits'] in (24, 16) and file_info['rgb_mask'] in SUPPORTED[file_info['bits']]:
raw_mode = MASK_MODES[(file_info['bits'], file_info['rgb_mask'])]
else:
Expand Down
Binary file added Tests/images/clipboard.dib
Binary file not shown.
Binary file added Tests/images/clipboard_target.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
7 changes: 7 additions & 0 deletions Tests/test_file_bmp.py
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,13 @@ def test_save_bmp_with_dpi(self):
self.assertEqual(im.size, reloaded.size)
self.assertEqual(reloaded.format, "JPEG")

def test_load_dib(self):
# test for #1293, Imagegrab returning Unsupported Bitfields Format
im = BmpImagePlugin.DibImageFile('Tests/images/clipboard.dib')
target = Image.open('Tests/images/clipboard_target.png')
self.assert_image_equal(im.convert('RGB'), target.convert('RGB'))
self.assert_image_similar(im, target, 1)


if __name__ == '__main__':
unittest.main()
Expand Down
16 changes: 16 additions & 0 deletions libImaging/Unpack.c
Original file line number Diff line number Diff line change
Expand Up @@ -832,6 +832,21 @@ unpackBGRA(UINT8* out, const UINT8* in, int pixels)
}
}

static void
unpackBGRT(UINT8* out, const UINT8* in, int pixels)
{
int i;
/* RGBA, reversed bytes */
/* Transparency map, rather than an alpha channel */
for (i = 0; i < pixels; i++) {
out[R] = in[2];
out[G] = in[1];
out[B] = in[0];
out[A] = 255 - in[3];
out += 4; in += 4;
}
}


/* Unpack to "CMYK" image */

Expand Down Expand Up @@ -1213,6 +1228,7 @@ static struct {
{"RGBA", "RGBA;4B", 16, ImagingUnpackRGBA4B},
{"RGBA", "RGBA;16B", 64, unpackRGBA16B},
{"RGBA", "BGRA", 32, unpackBGRA},
{"RGBA", "BGRT", 32, unpackBGRT},
{"RGBA", "ARGB", 32, unpackARGB},
{"RGBA", "ABGR", 32, unpackABGR},
{"RGBA", "YCCA;P", 32, ImagingUnpackYCCA},
Expand Down

0 comments on commit a7c678b

Please sign in to comment.