From 86e775daa3dfc23908d29c08f151111520251821 Mon Sep 17 00:00:00 2001 From: Eric L Frederich Date: Thu, 17 Sep 2015 09:32:15 -0400 Subject: [PATCH] bug fix: Qt wants data aligned to 32 bits Images in Qt show up incorrectly if each line is not aligned to 32 bits. It is pretty common for an image's lines to be 32-bit alinged by chance. Obviously any 32-bit image will not have any problem. For the bug to manifest itself you'd need... * a 1-bit image whose width is not a multiple of 32 * an 8-bit image who width is not a multiple of 4 Testing more images now and added a 7x13 png test image --- PIL/ImageQt.py | 29 ++++++++++++++++++++++++++++- Tests/images/7x13.png | Bin 0 -> 204 bytes Tests/test_image_fromqimage.py | 23 +++++++++++++++++------ 3 files changed, 45 insertions(+), 7 deletions(-) create mode 100644 Tests/images/7x13.png diff --git a/PIL/ImageQt.py b/PIL/ImageQt.py index 0e8cee00908..2131f8264ed 100644 --- a/PIL/ImageQt.py +++ b/PIL/ImageQt.py @@ -80,6 +80,33 @@ def fromqpixmap(im): # bytes_io.seek(0) # return PIL.Image.open(bytes_io) +def align8to32(bytes, width, mode): + """ + converts each scanline of data from 8 bit to 32 bit aligned + """ + + bits_per_pixel = { + '1': 1, + 'L': 8, + 'P': 8, + }[mode] + + # calculate bytes per line and the extra padding if needed + bits_per_line = bits_per_pixel * width + full_bytes_per_line, remaining_bits_per_line = divmod(bits_per_line, 8) + bytes_per_line = full_bytes_per_line + (1 if remaining_bits_per_line else 0) + + extra_padding = -bytes_per_line % 4 + + # already 32 bit aligned by luck + if not extra_padding: + return bytes + + new_data = [] + for i in range(len(bytes) / bytes_per_line): + new_data.append(bytes[i*bytes_per_line:(i+1)*bytes_per_line] + '\x00' * extra_padding) + + return ''.join(new_data) def _toqclass_helper(im): data = None @@ -123,7 +150,7 @@ def _toqclass_helper(im): raise ValueError("unsupported image mode %r" % im.mode) # must keep a reference, or Qt will crash! - __data = data or im.tobytes() + __data = data or align8to32(im.tobytes(), im.size[0], im.mode) return { 'data': __data, 'im': im, 'format': format, 'colortable': colortable } diff --git a/Tests/images/7x13.png b/Tests/images/7x13.png new file mode 100644 index 0000000000000000000000000000000000000000..d160c8b3877fbbdfaadf72672cc15d9a0b483fe0 GIT binary patch literal 204 zcmeAS@N?(olHy`uVBq!ia0vp^>>xG=6Oeqh`tc(m#aZAHSlKuBT-R4S2kKx4NNGHk1thcv)4v=*C=xV)BHNexMY}MvW qjrwf|W2;h%JM%L2PtV)>MqHTtpE{e|q{UxA)_A)5xvX