From 864fb95cb1c1c2fb45bc35292ddf9e76783a11d6 Mon Sep 17 00:00:00 2001 From: wiredfool Date: Mon, 7 Apr 2014 22:10:45 -0700 Subject: [PATCH 1/7] Read test for 16 bit binary pgm file, #602 --- Tests/images/16_bit_binary.pgm | Bin 0 -> 4016 bytes Tests/images/16_bit_binary_pgm.png | Bin 0 -> 578 bytes Tests/test_file_ppm.py | 10 ++++++++++ 3 files changed, 10 insertions(+) create mode 100644 Tests/images/16_bit_binary.pgm create mode 100644 Tests/images/16_bit_binary_pgm.png diff --git a/Tests/images/16_bit_binary.pgm b/Tests/images/16_bit_binary.pgm new file mode 100644 index 0000000000000000000000000000000000000000..fd41a5c3d1b04b92408c7344cc67e52541a295b6 GIT binary patch literal 4016 zcma*U3r9l%0D#eqlxw7nlu=Vg%51GWkrF90rWq+?dKgp2lo=_JGG@w{GNy+yC8ms- zGNz355L3pKj45ME%#@M(3*R{=QRr2-Yt(8%CyH88_=A4u+3F+vGssqs*m5KLwZeY9 zv88dgc+S3eu!Su)|INP6vd?#HPGqwO?32J|T}i&b4znlFv5bwZvEd?nXlD14Y)Hul{p?Pa4cJ)!1H0YN`ogSN%6i=F zMxI?auxoL4wT)f&vhFhLva*ZUtW(1}LhM2i-kpXr%!VWdC1IuiGfz=sVZGzP(Se1|MuCQG*tn!xa>|+)CY+F4m jUt(Kc*yb@-cE&cfvJIQ8^ph2)*t#pWwuhDMvNg~@LpIA; literal 0 HcmV?d00001 diff --git a/Tests/images/16_bit_binary_pgm.png b/Tests/images/16_bit_binary_pgm.png new file mode 100644 index 0000000000000000000000000000000000000000..918be1ad41d738db5afe429469538df9e580d7d9 GIT binary patch literal 578 zcmeAS@N?(olHy`uVBq!ia0vp^B0!uX03;Yb2TTqIQY`6?zK#rxZ3_%vOp6EdnUcKS zUH<82DMc#HK4B-bTr#q6iAL1q1 z{qwxDzj){Gw?)6NJgvI-RO`H|?TezqM@9b*J9v-^+F?loI?shG!vX~#}WkDbP(*O@n6{{LwJ@>sh&JI}bpEGv&)mKCFxtS4-#_c(C+#VMyf z7N7nw>2yHn=>sj^UrsIEe|Bm4<)!LRF4;c6H1*-7n~#Mo3tp}$uH5|Kl2}QmY++^X zyH8$=D$hPm-RXU~$NTYKZ|CKwKif{iz#K_Rf*wV__0?4*9 kFqpgI_iPjmx%nxXX_dG&y!q;^4%EQl>FVdQ&MBb@0M*s{ZvX%Q literal 0 HcmV?d00001 diff --git a/Tests/test_file_ppm.py b/Tests/test_file_ppm.py index fccb94905..5e0aa84ac 100644 --- a/Tests/test_file_ppm.py +++ b/Tests/test_file_ppm.py @@ -12,3 +12,13 @@ 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) + From f5ba642b5e49253f7256e08aa5e53226aac1194e Mon Sep 17 00:00:00 2001 From: wiredfool Date: Mon, 7 Apr 2014 22:12:33 -0700 Subject: [PATCH 2/7] Read support for 16 bit pgm file --- PIL/PpmImagePlugin.py | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/PIL/PpmImagePlugin.py b/PIL/PpmImagePlugin.py index 9aa5b1135..d7af308c2 100644 --- a/PIL/PpmImagePlugin.py +++ b/PIL/PpmImagePlugin.py @@ -96,7 +96,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 - 1: + self.mode = 'I' + rawmode = 'I;16B' + else: + self.mode = 'I'; + rawmode = 'I;32B' + self.size = xsize, ysize self.tile = [("raw", (0, 0, xsize, ysize), From 2daac27713dfaf75ac7af872e891d357734b6706 Mon Sep 17 00:00:00 2001 From: wiredfool Date: Mon, 7 Apr 2014 22:22:42 -0700 Subject: [PATCH 3/7] Tests for writing hi bit pgm --- Tests/test_file_ppm.py | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/Tests/test_file_ppm.py b/Tests/test_file_ppm.py index 5e0aa84ac..34136a83c 100644 --- a/Tests/test_file_ppm.py +++ b/Tests/test_file_ppm.py @@ -22,3 +22,15 @@ def test_16bit_pgm(): 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) + + From 327ea209b8dd91b60945d74e3c32edbebee63810 Mon Sep 17 00:00:00 2001 From: wiredfool Date: Mon, 7 Apr 2014 22:23:04 -0700 Subject: [PATCH 4/7] Write support, fixes #602 --- PIL/PpmImagePlugin.py | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/PIL/PpmImagePlugin.py b/PIL/PpmImagePlugin.py index d7af308c2..a5f01891f 100644 --- a/PIL/PpmImagePlugin.py +++ b/PIL/PpmImagePlugin.py @@ -127,6 +127,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": @@ -134,8 +139,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 == "I": + 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 From 213cec00cb5556c1be735326280c7e649999531e Mon Sep 17 00:00:00 2001 From: wiredfool Date: Mon, 7 Apr 2014 22:24:48 -0700 Subject: [PATCH 5/7] consistency --- PIL/PpmImagePlugin.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/PIL/PpmImagePlugin.py b/PIL/PpmImagePlugin.py index a5f01891f..328892323 100644 --- a/PIL/PpmImagePlugin.py +++ b/PIL/PpmImagePlugin.py @@ -101,7 +101,7 @@ class PpmImageFile(ImageFile.ImageFile): if s > 255: if not mode == 'L': raise ValueError("Too many colors for band: %s" %s) - if s <= 2**16 - 1: + if s < 2**16: self.mode = 'I' rawmode = 'I;16B' else: From 88e235f3f540ea7629b4db3dff7d64437bdd596b Mon Sep 17 00:00:00 2001 From: wiredfool Date: Tue, 8 Apr 2014 22:43:57 -0700 Subject: [PATCH 6/7] sanity check on ascii integers --- PIL/PpmImagePlugin.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/PIL/PpmImagePlugin.py b/PIL/PpmImagePlugin.py index 328892323..a7cb08e75 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): From 398450a5e49b73c5b6209c15a1fd8b316a650844 Mon Sep 17 00:00:00 2001 From: wiredfool Date: Tue, 8 Apr 2014 22:44:24 -0700 Subject: [PATCH 7/7] Fix failing tests, turns out I is different than L --- PIL/PpmImagePlugin.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/PIL/PpmImagePlugin.py b/PIL/PpmImagePlugin.py index a7cb08e75..070efd185 100644 --- a/PIL/PpmImagePlugin.py +++ b/PIL/PpmImagePlugin.py @@ -146,7 +146,7 @@ def _save(im, fp, filename): if head == b"P6": fp.write(b"255\n") if head == b"P5": - if rawmode == "I": + if rawmode == "L": fp.write(b"255\n") elif rawmode == "I;16B": fp.write(b"65535\n")