diff --git a/PIL/PpmImagePlugin.py b/PIL/PpmImagePlugin.py index 9aa5b1135..070efd185 100644 --- a/PIL/PpmImagePlugin.py +++ b/PIL/PpmImagePlugin.py @@ -63,7 +63,11 @@ class PpmImageFile(ImageFile.ImageFile): c = self.fp.read(1) if not c or c in b_whitespace: break + if c > b'\x79': + raise ValueError("Expected ASCII value, found binary") s = s + c + if (len(s) > 9): + raise ValueError("Expected int, got > 9 digits") return s def _open(self): @@ -96,7 +100,18 @@ class PpmImageFile(ImageFile.ImageFile): ysize = s if mode == "1": break - + elif ix == 2: + # maxgrey + if s > 255: + if not mode == 'L': + raise ValueError("Too many colors for band: %s" %s) + if s < 2**16: + self.mode = 'I' + rawmode = 'I;16B' + else: + self.mode = 'I'; + rawmode = 'I;32B' + self.size = xsize, ysize self.tile = [("raw", (0, 0, xsize, ysize), @@ -116,6 +131,11 @@ def _save(im, fp, filename): rawmode, head = "1;I", b"P4" elif im.mode == "L": rawmode, head = "L", b"P5" + elif im.mode == "I": + if im.getextrema()[1] < 2**16: + rawmode, head = "I;16B", b"P5" + else: + rawmode, head = "I;32B", b"P5" elif im.mode == "RGB": rawmode, head = "RGB", b"P6" elif im.mode == "RGBA": @@ -123,8 +143,15 @@ def _save(im, fp, filename): else: raise IOError("cannot write mode %s as PPM" % im.mode) fp.write(head + ("\n%d %d\n" % im.size).encode('ascii')) - if head != b"P4": + if head == b"P6": fp.write(b"255\n") + if head == b"P5": + if rawmode == "L": + fp.write(b"255\n") + elif rawmode == "I;16B": + fp.write(b"65535\n") + elif rawmode == "I;32B": + fp.write(b"2147483648\n") ImageFile._save(im, fp, [("raw", (0,0)+im.size, 0, (rawmode, 0, 1))]) # ALTERNATIVE: save via builtin debug function diff --git a/Tests/images/16_bit_binary.pgm b/Tests/images/16_bit_binary.pgm new file mode 100644 index 000000000..fd41a5c3d Binary files /dev/null and b/Tests/images/16_bit_binary.pgm differ diff --git a/Tests/images/16_bit_binary_pgm.png b/Tests/images/16_bit_binary_pgm.png new file mode 100644 index 000000000..918be1ad4 Binary files /dev/null and b/Tests/images/16_bit_binary_pgm.png differ diff --git a/Tests/test_file_ppm.py b/Tests/test_file_ppm.py index fccb94905..34136a83c 100644 --- a/Tests/test_file_ppm.py +++ b/Tests/test_file_ppm.py @@ -12,3 +12,25 @@ def test_sanity(): assert_equal(im.mode, "RGB") assert_equal(im.size, (128, 128)) assert_equal(im.format, "PPM") + +def test_16bit_pgm(): + im = Image.open('Tests/images/16_bit_binary.pgm') + im.load() + assert_equal(im.mode, 'I') + assert_equal(im.size, (20,100)) + + tgt = Image.open('Tests/images/16_bit_binary_pgm.png') + assert_image_equal(im, tgt) + + +def test_16bit_pgm_write(): + im = Image.open('Tests/images/16_bit_binary.pgm') + im.load() + + f = tempfile('temp.pgm') + assert_no_exception(lambda: im.save(f, 'PPM')) + + reloaded = Image.open(f) + assert_image_equal(im, reloaded) + +