py3k: Actually fix the EPS encoder

The EPS encoder wasn't part of Gohlke's test suite, so the previous "fixes"
there were only expected syntactic ones. This gives a cleaner fix to the
encoder.

The decoder doesn't work in round-trip due to a missing eps_decoder method
on the core module, but it's clear it worked at some point.
This commit is contained in:
Brian Crowell 2012-10-23 22:21:19 -05:00 committed by Brian Crowell
parent 63be4a1334
commit 4f7d784a71
2 changed files with 42 additions and 25 deletions

View File

@ -21,6 +21,7 @@
__version__ = "0.5" __version__ = "0.5"
import re import re
import io
from . import Image, ImageFile, _binary from . import Image, ImageFile, _binary
# #
@ -90,6 +91,8 @@ class PSFile:
def seek(self, offset, whence=0): def seek(self, offset, whence=0):
self.char = None self.char = None
self.fp.seek(offset, whence) self.fp.seek(offset, whence)
def read(self, count):
return self.fp.read(count).decode('latin-1')
def tell(self): def tell(self):
pos = self.fp.tell() pos = self.fp.tell()
if self.char: if self.char:
@ -109,7 +112,7 @@ class PSFile:
self.char = self.fp.read(1) self.char = self.fp.read(1)
if self.char == b"\n": if self.char == b"\n":
self.char = None self.char = None
return s + b"\n" return s.decode('latin-1') + "\n"
def _accept(prefix): def _accept(prefix):
@ -193,13 +196,14 @@ class EpsImageFile(ImageFile.ImageFile):
if m: if m:
k = m.group(1) k = m.group(1)
if k == "EndComments": if k == "EndComments":
break break
if k[:8] == "PS-Adobe": if k[:8] == "PS-Adobe":
self.info[k[:8]] = k[9:] self.info[k[:8]] = k[9:]
else: else:
self.info[k] = "" self.info[k] = ""
elif s[0] == '%': elif s[0:1] == '%':
# handle non-DSC Postscript comments that some # handle non-DSC Postscript comments that some
# tools mistakenly put in the Comments section # tools mistakenly put in the Comments section
pass pass
@ -228,7 +232,7 @@ class EpsImageFile(ImageFile.ImageFile):
if s[:11] == "%ImageData:": if s[:11] == "%ImageData:":
[x, y, bi, mo, z3, z4, en, id] =\ [x, y, bi, mo, z3, z4, en, id] =\
s[11:].split(maxsplit=7) s[11:].split(None, 7)
x = int(x); y = int(y) x = int(x); y = int(y)
@ -299,42 +303,54 @@ def _save(im, fp, filename, eps=1):
# #
# determine postscript image mode # determine postscript image mode
if im.mode == "L": if im.mode == "L":
operator = (8, 1, b"image") operator = (8, 1, "image")
elif im.mode == "RGB": elif im.mode == "RGB":
operator = (8, 3, b"false 3 colorimage") operator = (8, 3, "false 3 colorimage")
elif im.mode == "CMYK": elif im.mode == "CMYK":
operator = (8, 4, b"false 4 colorimage") operator = (8, 4, "false 4 colorimage")
else: else:
raise ValueError("image mode is not supported") raise ValueError("image mode is not supported")
class NoCloseStream:
def __init__(self, fp):
self.fp = fp
def __getattr__(self, name):
return getattr(self.fp, name)
def close(self):
pass
base_fp = fp
fp = io.TextIOWrapper(NoCloseStream(fp), encoding='latin-1')
if eps: if eps:
# #
# write EPS header # write EPS header
fp.write(b"%!PS-Adobe-3.0 EPSF-3.0\n") fp.write("%!PS-Adobe-3.0 EPSF-3.0\n")
fp.write(b"%%Creator: PIL 0.1 EpsEncode\n") fp.write("%%Creator: PIL 0.1 EpsEncode\n")
#fp.write("%%CreationDate: %s"...) #fp.write("%%CreationDate: %s"...)
fp.write(("%%%%BoundingBox: 0 0 %d %d\n" % im.size).encode('ascii')) fp.write("%%%%BoundingBox: 0 0 %d %d\n" % im.size)
fp.write(b"%%Pages: 1\n") fp.write("%%Pages: 1\n")
fp.write(b"%%EndComments\n") fp.write("%%EndComments\n")
fp.write(b"%%Page: 1 1\n") fp.write("%%Page: 1 1\n")
fp.write(("%%ImageData: %d %d " % im.size).encode('ascii')) fp.write("%%ImageData: %d %d " % im.size)
fp.write(("%d %d 0 1 1 \"%s\"\n" % operator).encode('ascii')) fp.write("%d %d 0 1 1 \"%s\"\n" % operator)
# #
# image header # image header
fp.write(b"gsave\n") fp.write("gsave\n")
fp.write(b"10 dict begin\n") fp.write("10 dict begin\n")
fp.write(("/buf %d string def\n" % (im.size[0] * operator[1])).encode('ascii')) fp.write("/buf %d string def\n" % (im.size[0] * operator[1]))
fp.write(("%d %d scale\n" % im.size).encode('ascii')) fp.write("%d %d scale\n" % im.size)
fp.write(("%d %d 8\n" % im.size).encode('ascii')) # <= bits fp.write("%d %d 8\n" % im.size) # <= bits
fp.write(("[%d 0 0 -%d 0 %d]\n" % (im.size[0], im.size[1], im.size[1])).encode('ascii')) fp.write("[%d 0 0 -%d 0 %d]\n" % (im.size[0], im.size[1], im.size[1]))
fp.write(b"{ currentfile buf readhexstring pop } bind\n") fp.write("{ currentfile buf readhexstring pop } bind\n")
fp.write(operator[2] + b"\n") fp.write(operator[2] + "\n")
fp.flush()
ImageFile._save(im, fp, [("eps", (0,0)+im.size, 0, None)]) ImageFile._save(im, base_fp, [("eps", (0,0)+im.size, 0, None)])
fp.write(b"\n%%%%EndBinary\n") fp.write("\n%%%%EndBinary\n")
fp.write(b"grestore end\n") fp.write("grestore end\n")
fp.flush() fp.flush()
# #

View File

@ -40,6 +40,7 @@ def test_parser():
assert_image_equal(*roundtrip("PPM")) assert_image_equal(*roundtrip("PPM"))
assert_image_equal(*roundtrip("TIFF")) assert_image_equal(*roundtrip("TIFF"))
assert_image_equal(*roundtrip("XBM")) assert_image_equal(*roundtrip("XBM"))
#assert_image_equal(*roundtrip("EPS")) #no eps_decoder
assert_image_equal(*roundtrip("TGA")) assert_image_equal(*roundtrip("TGA"))
im1, im2 = roundtrip("JPEG") # lossy compression im1, im2 = roundtrip("JPEG") # lossy compression