Fixed reading 9 and 11-15-bit PGM

This commit is contained in:
Andrew Murray 2022-03-05 00:43:29 +11:00
parent 72b738768b
commit 45988ab6b6
17 changed files with 48 additions and 25 deletions

View File

Before

Width:  |  Height:  |  Size: 17 KiB

After

Width:  |  Height:  |  Size: 17 KiB

BIN
Tests/images/ppm/11_bit.pgm Normal file

Binary file not shown.

BIN
Tests/images/ppm/11_bit.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

BIN
Tests/images/ppm/12_bit.pgm Normal file

Binary file not shown.

BIN
Tests/images/ppm/12_bit.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

BIN
Tests/images/ppm/13_bit.pgm Normal file

Binary file not shown.

BIN
Tests/images/ppm/13_bit.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

BIN
Tests/images/ppm/14_bit.pgm Normal file

Binary file not shown.

BIN
Tests/images/ppm/14_bit.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

BIN
Tests/images/ppm/15_bit.pgm Normal file

Binary file not shown.

BIN
Tests/images/ppm/15_bit.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

BIN
Tests/images/ppm/9_bit.pgm Normal file

Binary file not shown.

BIN
Tests/images/ppm/9_bit.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

View File

@ -20,14 +20,16 @@ def test_sanity():
assert im.get_format_mimetype() == "image/x-portable-pixmap"
def test_10bit_pgm():
with Image.open("Tests/images/10_bit_binary.pgm") as im:
@pytest.mark.parametrize("depth", range(9, 16))
def test_less_than_16bit_pgm(depth):
name = "Tests/images/ppm/" + str(depth) + "_bit"
with Image.open(name + ".pgm") as im:
im.load()
assert im.mode == "I"
assert im.size == (128, 128)
assert im.get_format_mimetype() == "image/x-portable-graymap"
assert_image_equal_tofile(im, "Tests/images/10_bit_binary_pgm.png")
assert_image_equal_tofile(im, name + ".png")
def test_16bit_pgm():

View File

@ -115,15 +115,13 @@ class PpmImageFile(ImageFile.ImageFile):
if maxval > 255:
if mode != "L":
raise ValueError(f"Too many colors for band: {token}")
if maxval == 1023:
self.mode = "I"
rawmode = "I;10B"
elif maxval < 2**16:
self.mode = "I"
rawmode = "I;16B"
for bit in range(9, 16):
if maxval == 2**bit - 1:
break
else:
self.mode = "I"
rawmode = "I;32B"
bit = 16 if maxval < 2**16 else 32
rawmode = "I;" + str(bit) + "B"
self._size = xsize, ysize
self.tile = [("raw", (0, 0, xsize, ysize), self.fp.tell(), (rawmode, 0, 1))]

View File

@ -1182,22 +1182,39 @@ unpackI12_I16(UINT8 *out, const UINT8 *in, int pixels) {
}
}
static void
unpackI10B(UINT8 *out, const UINT8 *in, int pixels) {
int i, pixel;
for (i = 0; i < pixels; i++) {
pixel = ((in[0] << 8) + in[1]) << 6;
#ifdef WORDS_BIGENDIAN
out[2] = pixel >> 8;
out[3] = pixel;
#define UNPACK_IXB(NAME, DEPTH) \
static void NAME(UINT8 *out, const UINT8 *in, int pixels) { \
int i, pixel; \
for (i = 0; i < pixels; i++) { \
pixel = ((in[0] << 8) + in[1]) << (16 - DEPTH); \
out[2] = pixel >> 8; \
out[3] = pixel; \
in += 2; \
out += 4; \
} \
}
#else
out[0] = pixel;
out[1] = pixel >> 8;
#define UNPACK_IXB(NAME, DEPTH) \
static void NAME(UINT8 *out, const UINT8 *in, int pixels) { \
int i, pixel; \
for (i = 0; i < pixels; i++) { \
pixel = ((in[0] << 8) + in[1]) << (16 - DEPTH); \
out[0] = pixel; \
out[1] = pixel >> 8; \
in += 2; \
out += 4; \
} \
}
#endif
in += 2;
out += 4;
}
}
UNPACK_IXB(unpackI9B, 9)
UNPACK_IXB(unpackI10B, 10)
UNPACK_IXB(unpackI11B, 11)
UNPACK_IXB(unpackI12B, 12)
UNPACK_IXB(unpackI13B, 13)
UNPACK_IXB(unpackI14B, 14)
UNPACK_IXB(unpackI15B, 15)
static void
copy1(UINT8 *out, const UINT8 *in, int pixels) {
@ -1701,7 +1718,13 @@ static struct {
{"I", "I", 32, copy4},
{"I", "I;8", 8, unpackI8},
{"I", "I;8S", 8, unpackI8S},
{"I", "I;9B", 16, unpackI9B},
{"I", "I;10B", 16, unpackI10B},
{"I", "I;11B", 16, unpackI11B},
{"I", "I;12B", 16, unpackI12B},
{"I", "I;13B", 16, unpackI13B},
{"I", "I;14B", 16, unpackI14B},
{"I", "I;15B", 16, unpackI15B},
{"I", "I;16", 16, unpackI16},
{"I", "I;16S", 16, unpackI16S},
{"I", "I;16B", 16, unpackI16B},