mirror of
https://github.com/python-pillow/Pillow.git
synced 2025-08-22 13:14:45 +03:00
Add basic support for decoding plain text PPM formats
This commit is contained in:
parent
8dfc0364fe
commit
91ac066fbc
|
@ -14,6 +14,7 @@
|
||||||
# See the README file for information on usage and redistribution.
|
# See the README file for information on usage and redistribution.
|
||||||
#
|
#
|
||||||
|
|
||||||
|
import struct
|
||||||
|
|
||||||
from . import Image, ImageFile
|
from . import Image, ImageFile
|
||||||
|
|
||||||
|
@ -23,21 +24,25 @@ from . import Image, ImageFile
|
||||||
b_whitespace = b"\x20\x09\x0a\x0b\x0c\x0d"
|
b_whitespace = b"\x20\x09\x0a\x0b\x0c\x0d"
|
||||||
|
|
||||||
MODES = {
|
MODES = {
|
||||||
# standard
|
# standard, plain
|
||||||
b"P4": "1",
|
b"P1": ("PPM", "1"),
|
||||||
b"P5": "L",
|
b"P2": ("PPM", "L"),
|
||||||
b"P6": "RGB",
|
b"P3": ("PPM", "RGB"),
|
||||||
|
# standard, raw
|
||||||
|
b"P4": ("raw", "1"),
|
||||||
|
b"P5": ("raw", "L"),
|
||||||
|
b"P6": ("raw", "RGB"),
|
||||||
# extensions
|
# extensions
|
||||||
b"P0CMYK": "CMYK",
|
b"P0CMYK": ("raw", "CMYK"),
|
||||||
# PIL extensions (for test purposes only)
|
# PIL extensions (for test purposes only)
|
||||||
b"PyP": "P",
|
b"PyP": ("raw", "P"),
|
||||||
b"PyRGBA": "RGBA",
|
b"PyRGBA": ("raw", "RGBA"),
|
||||||
b"PyCMYK": "CMYK",
|
b"PyCMYK": ("raw", "CMYK"),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
def _accept(prefix):
|
def _accept(prefix):
|
||||||
return prefix[0:1] == b"P" and prefix[1] in b"0456y"
|
return prefix[0:1] == b"P" and prefix[1] in b"0123456y"
|
||||||
|
|
||||||
|
|
||||||
##
|
##
|
||||||
|
@ -68,9 +73,12 @@ class PpmImageFile(ImageFile.ImageFile):
|
||||||
if s != b"P":
|
if s != b"P":
|
||||||
raise SyntaxError("not a PPM file")
|
raise SyntaxError("not a PPM file")
|
||||||
magic_number = self._token(s)
|
magic_number = self._token(s)
|
||||||
mode = MODES[magic_number]
|
decoder, mode = MODES[magic_number]
|
||||||
|
|
||||||
self.custom_mimetype = {
|
self.custom_mimetype = {
|
||||||
|
b"P1": "image/x-portable-bitmap",
|
||||||
|
b"P2": "image/x-portable-graymap",
|
||||||
|
b"P3": "image/x-portable-pixmap",
|
||||||
b"P4": "image/x-portable-bitmap",
|
b"P4": "image/x-portable-bitmap",
|
||||||
b"P5": "image/x-portable-graymap",
|
b"P5": "image/x-portable-graymap",
|
||||||
b"P6": "image/x-portable-pixmap",
|
b"P6": "image/x-portable-pixmap",
|
||||||
|
@ -113,11 +121,51 @@ class PpmImageFile(ImageFile.ImageFile):
|
||||||
rawmode = "I;32B"
|
rawmode = "I;32B"
|
||||||
|
|
||||||
self._size = xsize, ysize
|
self._size = xsize, ysize
|
||||||
self.tile = [("raw", (0, 0, xsize, ysize), self.fp.tell(), (rawmode, 0, 1))]
|
self.tile = [(decoder, (0, 0, xsize, ysize), self.fp.tell(), (rawmode, 0, 1))]
|
||||||
|
|
||||||
|
|
||||||
#
|
class PpmPlainDecoder(ImageFile.PyDecoder):
|
||||||
# --------------------------------------------------------------------
|
_pulls_fd = True
|
||||||
|
|
||||||
|
def decode(self, buffer):
|
||||||
|
data = b""
|
||||||
|
size = self.state.xsize * self.state.ysize
|
||||||
|
|
||||||
|
if self.mode == "1":
|
||||||
|
translate = bytes.maketrans(b"01", b"\xFF\x00")
|
||||||
|
delete = bytes(range(48)) + bytes(range(50, 256))
|
||||||
|
|
||||||
|
for line in self.fd:
|
||||||
|
line = line[: line.find("#")]
|
||||||
|
if self.mode == "1":
|
||||||
|
bytes_per_pixel = 1
|
||||||
|
data += line.translate(translate, delete)
|
||||||
|
else:
|
||||||
|
values = map(int, line.split())
|
||||||
|
if self.mode == "L":
|
||||||
|
bytes_per_pixel = 1
|
||||||
|
data += bytes(values)
|
||||||
|
elif self.mode == "I;16B":
|
||||||
|
bytes_per_pixel = 2
|
||||||
|
values = list(values)
|
||||||
|
data += struct.pack(f">{len(values)}H", *values)
|
||||||
|
elif self.mode == "I;32B":
|
||||||
|
bytes_per_pixel = 4
|
||||||
|
values = list(values)
|
||||||
|
data += struct.pack(f">{len(values)}L", *values)
|
||||||
|
else:
|
||||||
|
bytes_per_pixel = 3
|
||||||
|
data += bytes(values)
|
||||||
|
|
||||||
|
if len(data) >= size * bytes_per_pixel:
|
||||||
|
break
|
||||||
|
|
||||||
|
if self.mode == "1":
|
||||||
|
self.im.putdata(data[0:size])
|
||||||
|
else:
|
||||||
|
self.set_as_raw(data, rawmode=self.args[0])
|
||||||
|
|
||||||
|
return -1, 0
|
||||||
|
|
||||||
|
|
||||||
def _save(im, fp, filename):
|
def _save(im, fp, filename):
|
||||||
|
@ -156,6 +204,7 @@ def _save(im, fp, filename):
|
||||||
# --------------------------------------------------------------------
|
# --------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
|
Image.register_decoder("PPM", PpmPlainDecoder)
|
||||||
Image.register_open(PpmImageFile.format, PpmImageFile, _accept)
|
Image.register_open(PpmImageFile.format, PpmImageFile, _accept)
|
||||||
Image.register_save(PpmImageFile.format, _save)
|
Image.register_save(PpmImageFile.format, _save)
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user