diff --git a/PIL/PyAccess.py b/PIL/PyAccess.py index 09ce86af4..f23f86152 100644 --- a/PIL/PyAccess.py +++ b/PIL/PyAccess.py @@ -188,6 +188,21 @@ class _PyAccessI16_N(PyAccess): self.pixels[y][x] = min(color[0], 65535) +class _PyAccessI16_NS(PyAccess): + """ I;16S access, native bitendian without conversion """ + def _post_init(self, *args, **kwargs): + self.pixels = ffi.cast('short **', self.image) + + def get_pixel(self, x, y): + return self.pixels[y][x] + + def set_pixel(self, x, y, color): + try: + self.pixels[y][x] = max(min(color, 2**15-1), -2**15) + except TypeError: + self.pixels[y][x] = max(min(color[0], 2**15-1), -2**15) + + class _PyAccessI16_L(PyAccess): """ I;16L access, with conversion """ def _post_init(self, *args, **kwargs): @@ -208,6 +223,34 @@ class _PyAccessI16_L(PyAccess): pixel.r = color >> 8 +class _PyAccessI16_LS(PyAccess): + """ Littleendian I;16S access, with conversion """ + def _post_init(self, *args, **kwargs): + self.pixels = ffi.cast('struct Pixel_I16 **', self.image) + + def reverse(self, i): + orig = ffi.new('short *', i) + chars = ffi.cast('unsigned char *', orig) + chars[0], chars[1], = chars[1], chars[0] + return ffi.cast('short *', chars)[0] + + def get_pixel(self, x, y): + return self.reverse(self.pixels[y][x]) + + def set_pixel(self, x, y, color): + pixel = self.pixels[y][x] + + try: + color = max(min(color, 2**15-1), -2**15) + except TypeError: + color = max(min(color[0], 2**15-1), -2**15) + + mask = color < 0 and 0x80 or 0x00 + + pixel.l = color & 0xFF + pixel.r = (color >> 8) | mask + + class _PyAccessI16_B(PyAccess): """ I;16B access, with conversion """ def _post_init(self, *args, **kwargs): @@ -298,6 +341,7 @@ if sys.byteorder == 'little': mode_map['I;16'] = _PyAccessI16_N mode_map['I;16L'] = _PyAccessI16_N mode_map['I;16B'] = _PyAccessI16_B + mode_map['I;16S'] = _PyAccessI16_NS mode_map['I;32L'] = _PyAccessI32_N mode_map['I;32B'] = _PyAccessI32_Swap @@ -305,6 +349,7 @@ else: mode_map['I;16'] = _PyAccessI16_L mode_map['I;16L'] = _PyAccessI16_L mode_map['I;16B'] = _PyAccessI16_N + mode_map['I;16S'] = _PyAccessI16_LS mode_map['I;32L'] = _PyAccessI32_Swap mode_map['I;32B'] = _PyAccessI32_N diff --git a/Tests/test_mode_i16.py b/Tests/test_mode_i16.py index 42d5ed83e..9679be7d3 100644 --- a/Tests/test_mode_i16.py +++ b/Tests/test_mode_i16.py @@ -6,6 +6,7 @@ import struct HAS_PYACCESS = False try: from PIL import PyAccess + HAS_PYACCESS = True except: pass class TestModeI16(PillowTestCase): @@ -134,9 +135,15 @@ class TestModeI16(PillowTestCase): if HAS_PYACCESS: py_access = PyAccess.new(im, im.readonly) for ix, val in enumerate(pixels): + self.assertEqual(access[(ix, 0)], val) + access[(ix,0)] = 0 + access[(ix,0)] = val self.assertEqual(access[(ix, 0)], val) if HAS_PYACCESS: self.assertEqual(py_access[(ix, 0)], val) + py_access[(ix,0)] = 0 + py_access[(ix,0)] = val + self.assertEqual(py_access[(ix, 0)], val) _test_access(im, pixels) _test_access(im.convert('I'), pixels) # lossless