コード例 #1
0
ファイル: MspImagePlugin.py プロジェクト: samis/blockBox
def _save(im, fp, filename):

    if im.mode != "1":
        raise IOError, "cannot write mode %s as MSP" % im.mode

    # create MSP header
    header = [0] * 16

    header[0], header[1] = i16("Da"), i16("nM")  # version 1
    header[2], header[3] = im.size
    header[4], header[5] = 1, 1
    header[6], header[7] = 1, 1
    header[8], header[9] = im.size

    sum = 0
    for h in header:
        sum = sum ^ h
    header[12] = sum  # FIXME: is this the right field?

    # header
    for h in header:
        fp.write(o16(h))

    # image body
    ImageFile._save(im, fp, [("raw", (0, 0) + im.size, 32, ("1", 0, 1))])
コード例 #2
0
def _save(im, fp, filename):

    if im.mode != "1":
        raise IOError, "cannot write mode %s as MSP" % im.mode

        # create MSP header
    header = [0] * 16

    header[0], header[1] = i16("Da"), i16("nM")  # version 1
    header[2], header[3] = im.size
    header[4], header[5] = 1, 1
    header[6], header[7] = 1, 1
    header[8], header[9] = im.size

    sum = 0
    for h in header:
        sum = sum ^ h
    header[12] = sum  # FIXME: is this the right field?

    # header
    for h in header:
        fp.write(o16(h))

        # image body
    ImageFile._save(im, fp, [("raw", (0, 0) + im.size, 32, ("1", 0, 1))])
コード例 #3
0
def getdata(im, offset = (0, 0), **params):
	"""Return a list of strings representing this image.
	   The first string is a local image header, the rest contains
	   encoded image data."""

	class collector:
		data = []
		def write(self, data):
			self.data.append(data)

	im.load() # make sure raster data is available

	fp = collector()

	try:
		im.encoderinfo = params

		# local image header
		fp.write("," +
				 o16(offset[0]) +	   # offset
				 o16(offset[1]) +
				 o16(im.size[0]) +	  # size
				 o16(im.size[1]) +
				 chr(0) +			   # flags
				 chr(8))				# bits

		ImageFile._save(im, fp, [("gif", (0,0)+im.size, 0, RAWMODE[im.mode])])

		fp.write("\0") # end of image data

	finally:
		del im.encoderinfo

	return fp.data
コード例 #4
0
ファイル: TgaImagePlugin.py プロジェクト: samis/blockBox
def _save(im, fp, filename, check=0):

    try:
        rawmode, bits, colormaptype, imagetype = SAVE[im.mode]
    except KeyError:
        raise IOError("cannot write mode %s as TGA" % im.mode)

    if check:
        return check

    if colormaptype:
        colormapfirst, colormaplength, colormapentry = 0, 256, 24
    else:
        colormapfirst, colormaplength, colormapentry = 0, 0, 0

    if im.mode == "RGBA":
        flags = 8
    else:
        flags = 0

    orientation = im.info.get("orientation", -1)
    if orientation > 0:
        flags = flags | 0x20

    fp.write("\000" + chr(colormaptype) + chr(imagetype) + o16(colormapfirst) +
             o16(colormaplength) + chr(colormapentry) + o16(0) + o16(0) +
             o16(im.size[0]) + o16(im.size[1]) + chr(bits) + chr(flags))

    if colormaptype:
        fp.write(im.im.getpalette("RGB", "BGR"))

    ImageFile._save(im, fp,
                    [("raw", (0, 0) + im.size, 0, (rawmode, 0, orientation))])
コード例 #5
0
ファイル: ImImagePlugin.py プロジェクト: samis/blockBox
def _save(im, fp, filename, check=0):

    try:
        type, rawmode = SAVE[im.mode]
    except KeyError:
        raise ValueError, "Cannot save %s images as IM" % im.mode

    try:
        frames = im.encoderinfo["frames"]
    except KeyError:
        frames = 1

    if check:
        return check

    fp.write("Image type: %s image\r\n" % type)
    if filename:
        fp.write("Name: %s\r\n" % filename)
    fp.write("Image size (x*y): %d*%d\r\n" % im.size)
    fp.write("File size (no of images): %d\r\n" % frames)
    if im.mode == "P":
        fp.write("Lut: 1\r\n")
    fp.write("\000" * (511 - fp.tell()) + "\032")
    if im.mode == "P":
        fp.write(im.im.getpalette("RGB", "RGB;L"))  # 768 bytes
    ImageFile._save(im, fp, [("raw", (0, 0) + im.size, 0, (rawmode, 0, -1))])
コード例 #6
0
ファイル: JpegImagePlugin.py プロジェクト: samis/blockBox
def _save(im, fp, filename):

	try:
		rawmode = RAWMODE[im.mode]
	except KeyError:
		raise IOError("cannot write mode %s as JPEG" % im.mode)

	info = im.encoderinfo

	dpi = info.get("dpi", (0, 0))

	subsampling = info.get("subsampling", -1)
	if subsampling == "4:4:4":
		subsampling = 0
	elif subsampling == "4:2:2":
		subsampling = 1
	elif subsampling == "4:1:1":
		subsampling = 2

	extra = ""

	icc_profile = info.get("icc_profile")
	if icc_profile:
		ICC_OVERHEAD_LEN = 14
		MAX_BYTES_IN_MARKER = 65533
		MAX_DATA_BYTES_IN_MARKER = MAX_BYTES_IN_MARKER - ICC_OVERHEAD_LEN
		markers = []
		while icc_profile:
			markers.append(icc_profile[:MAX_DATA_BYTES_IN_MARKER])
			icc_profile = icc_profile[MAX_DATA_BYTES_IN_MARKER:]
		i = 1
		for marker in markers:
			size = struct.pack(">H", 2 + ICC_OVERHEAD_LEN + len(marker))
			extra = extra + ("\xFF\xE2" + size + "ICC_PROFILE\0" + chr(i) + chr(len(markers)) + marker)
			i = i + 1

	# get keyword arguments
	im.encoderconfig = (
		info.get("quality", 0),
		# "progressive" is the official name, but older documentation
		# says "progression"
		# FIXME: issue a warning if the wrong form is used (post-1.1.7)
		info.has_key("progressive") or info.has_key("progression"),
		info.get("smooth", 0),
		info.has_key("optimize"),
		info.get("streamtype", 0),
		dpi[0], dpi[1],
		subsampling,
		extra,
		)

	ImageFile._save(im, fp, [("jpeg", (0,0)+im.size, 0, rawmode)])
コード例 #7
0
def _save(im, fp, filename):
	if im.mode == "1":
		rawmode, head = "1;I", "P4"
	elif im.mode == "L":
		rawmode, head = "L", "P5"
	elif im.mode == "RGB":
		rawmode, head = "RGB", "P6"
	elif im.mode == "RGBA":
		rawmode, head = "RGB", "P6"
	else:
		raise IOError, "cannot write mode %s as PPM" % im.mode
	fp.write(head + "\n%d %d\n" % im.size)
	if head != "P4":
		fp.write("255\n")
	ImageFile._save(im, fp, [("raw", (0,0)+im.size, 0, (rawmode, 0, 1))])
コード例 #8
0
ファイル: PpmImagePlugin.py プロジェクト: samis/blockBox
def _save(im, fp, filename):
    if im.mode == "1":
        rawmode, head = "1;I", "P4"
    elif im.mode == "L":
        rawmode, head = "L", "P5"
    elif im.mode == "RGB":
        rawmode, head = "RGB", "P6"
    elif im.mode == "RGBA":
        rawmode, head = "RGB", "P6"
    else:
        raise IOError, "cannot write mode %s as PPM" % im.mode
    fp.write(head + "\n%d %d\n" % im.size)
    if head != "P4":
        fp.write("255\n")
    ImageFile._save(im, fp, [("raw", (0, 0) + im.size, 0, (rawmode, 0, 1))])
コード例 #9
0
def _save(im, fp, filename, check=0):

    try:
        rawmode, bits, colors = SAVE[im.mode]
    except KeyError:
        raise IOError("cannot write mode %s as BMP" % im.mode)

    if check:
        return check

    stride = ((im.size[0] * bits + 7) / 8 + 3) & (~3)
    header = 40  # or 64 for OS/2 version 2
    offset = 14 + header + colors * 4
    image = stride * im.size[1]

    # bitmap header
    fp.write("BM" +  # file type (magic)
             o32(offset + image) +  # file size
             o32(0) +  # reserved
             o32(offset))  # image data offset

    # bitmap info header
    fp.write(
        o32(header) +  # info header size
        o32(im.size[0]) +  # width
        o32(im.size[1]) +  # height
        o16(1) +  # planes
        o16(bits) +  # depth
        o32(0) +  # compression (0=uncompressed)
        o32(image) +  # size of bitmap
        o32(1) + o32(1) +  # resolution
        o32(colors) +  # colors used
        o32(colors))  # colors important

    fp.write("\000" * (header - 40))  # padding (for OS/2 format)

    if im.mode == "1":
        for i in (0, 255):
            fp.write(chr(i) * 4)
    elif im.mode == "L":
        for i in range(256):
            fp.write(chr(i) * 4)
    elif im.mode == "P":
        fp.write(im.im.getpalette("RGB", "BGRX"))

    ImageFile._save(im, fp,
                    [("raw", (0, 0) + im.size, 0, (rawmode, stride, -1))])
コード例 #10
0
def _save(im, fp, filename, check=0):

	try:
		rawmode, bits, colors = SAVE[im.mode]
	except KeyError:
		raise IOError("cannot write mode %s as BMP" % im.mode)

	if check:
		return check

	stride = ((im.size[0]*bits+7)/8+3)&(~3)
	header = 40 # or 64 for OS/2 version 2
	offset = 14 + header + colors * 4
	image  = stride * im.size[1]

	# bitmap header
	fp.write("BM" +					 # file type (magic)
			 o32(offset+image) +		# file size
			 o32(0) +				   # reserved
			 o32(offset))			   # image data offset

	# bitmap info header
	fp.write(o32(header) +			  # info header size
			 o32(im.size[0]) +		  # width
			 o32(im.size[1]) +		  # height
			 o16(1) +				   # planes
			 o16(bits) +				# depth
			 o32(0) +				   # compression (0=uncompressed)
			 o32(image) +			   # size of bitmap
			 o32(1) + o32(1) +		  # resolution
			 o32(colors) +			  # colors used
			 o32(colors))			   # colors important

	fp.write("\000" * (header - 40))	# padding (for OS/2 format)

	if im.mode == "1":
		for i in (0, 255):
			fp.write(chr(i) * 4)
	elif im.mode == "L":
		for i in range(256):
			fp.write(chr(i) * 4)
	elif im.mode == "P":
		fp.write(im.im.getpalette("RGB", "BGRX"))

	ImageFile._save(im, fp, [("raw", (0,0)+im.size, 0, (rawmode, stride, -1))])
コード例 #11
0
def _save(im, fp, filename):

	if im.mode != "1":
		raise IOError, "cannot write mode %s as XBM" % im.mode

	fp.write("#define im_width %d\n" % im.size[0])
	fp.write("#define im_height %d\n" % im.size[1])

	hotspot = im.encoderinfo.get("hotspot")
	if hotspot:
		fp.write("#define im_x_hot %d\n" % hotspot[0])
		fp.write("#define im_y_hot %d\n" % hotspot[1])

	fp.write("static char im_bits[] = {\n")

	ImageFile._save(im, fp, [("xbm", (0,0)+im.size, 0, None)])

	fp.write("};\n")
コード例 #12
0
ファイル: XbmImagePlugin.py プロジェクト: samis/blockBox
def _save(im, fp, filename):

    if im.mode != "1":
        raise IOError, "cannot write mode %s as XBM" % im.mode

    fp.write("#define im_width %d\n" % im.size[0])
    fp.write("#define im_height %d\n" % im.size[1])

    hotspot = im.encoderinfo.get("hotspot")
    if hotspot:
        fp.write("#define im_x_hot %d\n" % hotspot[0])
        fp.write("#define im_y_hot %d\n" % hotspot[1])

    fp.write("static char im_bits[] = {\n")

    ImageFile._save(im, fp, [("xbm", (0, 0) + im.size, 0, None)])

    fp.write("};\n")
コード例 #13
0
def _save(im, fp, filename):
    if im.mode[0] != "F":
        im = im.convert('F')

    hdr = makeSpiderHeader(im)
    if len(hdr) < 256:
        raise IOError, "Error creating Spider header"

    # write the SPIDER header
    try:
        fp = open(filename, 'wb')
    except:
        raise IOError, "Unable to open %s for writing" % filename
    fp.writelines(hdr)

    rawmode = "F;32NF"  #32-bit native floating point
    ImageFile._save(im, fp, [("raw", (0, 0) + im.size, 0, (rawmode, 0, 1))])

    fp.close()
コード例 #14
0
def _save(im, fp, filename):
	if im.mode[0] != "F":
		im = im.convert('F')

	hdr = makeSpiderHeader(im)
	if len(hdr) < 256:
		raise IOError, "Error creating Spider header"

	# write the SPIDER header
	try:
		fp = open(filename, 'wb')
	except:
		raise IOError, "Unable to open %s for writing" % filename
	fp.writelines(hdr)

	rawmode = "F;32NF"  #32-bit native floating point
	ImageFile._save(im, fp, [("raw", (0,0)+im.size, 0, (rawmode,0,1))])

	fp.close()
コード例 #15
0
def _save(im, fp, filename, check=0):

	try:
		version, bits, planes, rawmode = SAVE[im.mode]
	except KeyError:
		raise ValueError, "Cannot save %s images as PCX" % im.mode

	if check:
		return check

	# bytes per plane
	stride = (im.size[0] * bits + 7) / 8

	# under windows, we could determine the current screen size with
	# "Image.core.display_mode()[1]", but I think that's overkill...

	screen = im.size

	dpi = 100, 100

	# PCX header
	fp.write(
		chr(10) + chr(version) + chr(1) + chr(bits) + o16(0) +
		o16(0) + o16(im.size[0]-1) + o16(im.size[1]-1) + o16(dpi[0]) +
		o16(dpi[1]) + chr(0)*24 + chr(255)*24 + chr(0) + chr(planes) +
		o16(stride) + o16(1) + o16(screen[0]) + o16(screen[1]) +
		chr(0)*54
		)

	assert fp.tell() == 128

	ImageFile._save(im, fp, [("pcx", (0,0)+im.size, 0,
							  (rawmode, bits*planes))])

	if im.mode == "P":
		# colour palette
		fp.write(chr(12))
		fp.write(im.im.getpalette("RGB", "RGB")) # 768 bytes
	elif im.mode == "L":
		# greyscale palette
		fp.write(chr(12))
		for i in range(256):
			fp.write(chr(i)*3)
コード例 #16
0
def _save(im, fp, filename, check=0):

	try:
		rawmode, bits, colormaptype, imagetype = SAVE[im.mode]
	except KeyError:
		raise IOError("cannot write mode %s as TGA" % im.mode)

	if check:
		return check

	if colormaptype:
		colormapfirst, colormaplength, colormapentry = 0, 256, 24
	else:
		colormapfirst, colormaplength, colormapentry = 0, 0, 0

	if im.mode == "RGBA":
		flags = 8
	else:
		flags = 0

	orientation = im.info.get("orientation", -1)
	if orientation > 0:
		flags = flags | 0x20

	fp.write("\000" +
			 chr(colormaptype) +
			 chr(imagetype) +
			 o16(colormapfirst) +
			 o16(colormaplength) +
			 chr(colormapentry) +
			 o16(0) +
			 o16(0) +
			 o16(im.size[0]) +
			 o16(im.size[1]) +
			 chr(bits) +
			 chr(flags))

	if colormaptype:
		fp.write(im.im.getpalette("RGB", "BGR"))

	ImageFile._save(im, fp, [("raw", (0,0)+im.size, 0, (rawmode, 0, orientation))])
コード例 #17
0
ファイル: PcxImagePlugin.py プロジェクト: samis/blockBox
def _save(im, fp, filename, check=0):

    try:
        version, bits, planes, rawmode = SAVE[im.mode]
    except KeyError:
        raise ValueError, "Cannot save %s images as PCX" % im.mode

    if check:
        return check

    # bytes per plane
    stride = (im.size[0] * bits + 7) / 8

    # under windows, we could determine the current screen size with
    # "Image.core.display_mode()[1]", but I think that's overkill...

    screen = im.size

    dpi = 100, 100

    # PCX header
    fp.write(
        chr(10) + chr(version) + chr(1) + chr(bits) + o16(0) + o16(0) +
        o16(im.size[0] - 1) + o16(im.size[1] - 1) + o16(dpi[0]) + o16(dpi[1]) +
        chr(0) * 24 + chr(255) * 24 + chr(0) + chr(planes) + o16(stride) +
        o16(1) + o16(screen[0]) + o16(screen[1]) + chr(0) * 54)

    assert fp.tell() == 128

    ImageFile._save(im, fp,
                    [("pcx", (0, 0) + im.size, 0, (rawmode, bits * planes))])

    if im.mode == "P":
        # colour palette
        fp.write(chr(12))
        fp.write(im.im.getpalette("RGB", "RGB"))  # 768 bytes
    elif im.mode == "L":
        # greyscale palette
        fp.write(chr(12))
        for i in range(256):
            fp.write(chr(i) * 3)
コード例 #18
0
def _save(im, fp, filename):

    try:
        rawmode, prefix, photo, format, bits, extra = SAVE_INFO[im.mode]
    except KeyError:
        raise IOError, "cannot write mode %s as TIFF" % im.mode

    ifd = ImageFileDirectory(prefix)

    # -- multi-page -- skip TIFF header on subsequent pages
    if fp.tell() == 0:
        # tiff header (write via IFD to get everything right)
        # PIL always starts the first IFD at offset 8
        fp.write(ifd.prefix + ifd.o16(42) + ifd.o32(8))

    ifd[IMAGEWIDTH] = im.size[0]
    ifd[IMAGELENGTH] = im.size[1]

    # additions written by Greg Couch, [email protected]
    # inspired by image-sig posting from Kevin Cazabon, [email protected]
    if hasattr(im, 'tag'):
        # preserve tags from original TIFF image file
        for key in (RESOLUTION_UNIT, X_RESOLUTION, Y_RESOLUTION):
            if im.tag.tagdata.has_key(key):
                ifd[key] = im.tag.tagdata.get(key)
        # preserve some more tags from original TIFF image file
        # -- 2008-06-06 Florian Hoech
        ifd.tagtype = im.tag.tagtype
        for key in (IPTC_NAA_CHUNK, PHOTOSHOP_CHUNK, XMP):
            if im.tag.has_key(key):
                ifd[key] = im.tag[key]
        # preserve ICC profile (should also work when saving other formats
        # which support profiles as TIFF) -- 2008-06-06 Florian Hoech
        if im.info.has_key("icc_profile"):
            ifd[ICCPROFILE] = im.info["icc_profile"]
    if im.encoderinfo.has_key("description"):
        ifd[IMAGEDESCRIPTION] = im.encoderinfo["description"]
    if im.encoderinfo.has_key("resolution"):
        ifd[X_RESOLUTION] = ifd[Y_RESOLUTION] \
              = _cvt_res(im.encoderinfo["resolution"])
    if im.encoderinfo.has_key("x resolution"):
        ifd[X_RESOLUTION] = _cvt_res(im.encoderinfo["x resolution"])
    if im.encoderinfo.has_key("y resolution"):
        ifd[Y_RESOLUTION] = _cvt_res(im.encoderinfo["y resolution"])
    if im.encoderinfo.has_key("resolution unit"):
        unit = im.encoderinfo["resolution unit"]
        if unit == "inch":
            ifd[RESOLUTION_UNIT] = 2
        elif unit == "cm" or unit == "centimeter":
            ifd[RESOLUTION_UNIT] = 3
        else:
            ifd[RESOLUTION_UNIT] = 1
    if im.encoderinfo.has_key("software"):
        ifd[SOFTWARE] = im.encoderinfo["software"]
    if im.encoderinfo.has_key("date time"):
        ifd[DATE_TIME] = im.encoderinfo["date time"]
    if im.encoderinfo.has_key("artist"):
        ifd[ARTIST] = im.encoderinfo["artist"]
    if im.encoderinfo.has_key("copyright"):
        ifd[COPYRIGHT] = im.encoderinfo["copyright"]

    dpi = im.encoderinfo.get("dpi")
    if dpi:
        ifd[RESOLUTION_UNIT] = 2
        ifd[X_RESOLUTION] = _cvt_res(dpi[0])
        ifd[Y_RESOLUTION] = _cvt_res(dpi[1])

    if bits != (1, ):
        ifd[BITSPERSAMPLE] = bits
        if len(bits) != 1:
            ifd[SAMPLESPERPIXEL] = len(bits)
    if extra is not None:
        ifd[EXTRASAMPLES] = extra
    if format != 1:
        ifd[SAMPLEFORMAT] = format

    ifd[PHOTOMETRIC_INTERPRETATION] = photo

    if im.mode == "P":
        lut = im.im.getpalette("RGB", "RGB;L")
        ifd[COLORMAP] = tuple(map(lambda v: ord(v) * 256, lut))

    # data orientation
    stride = len(bits) * ((im.size[0] * bits[0] + 7) / 8)
    ifd[ROWSPERSTRIP] = im.size[1]
    ifd[STRIPBYTECOUNTS] = stride * im.size[1]
    ifd[STRIPOFFSETS] = 0  # this is adjusted by IFD writer
    ifd[COMPRESSION] = 1  # no compression

    offset = ifd.save(fp)

    ImageFile._save(im, fp,
                    [("raw", (0, 0) + im.size, offset, (rawmode, stride, 1))])

    # -- helper for multi-page save --
    if im.encoderinfo.has_key("_debug_multipage"):
        #just to access o32 and o16 (using correct byte order)
        im._debug_multipage = ifd
コード例 #19
0
def _save(im, fp, filename):
	resolution = im.encoderinfo.get("resolution", 72.0)

	#
	# make sure image data is available
	im.load()

	xref = [0]*(5+1) # placeholders

	fp.write("%PDF-1.2\n")
	fp.write("% created by PIL PDF driver " + __version__ + "\n")

	#
	# Get image characteristics

	width, height = im.size

	# FIXME: Should replace ASCIIHexDecode with RunLengthDecode (packbits)
	# or LZWDecode (tiff/lzw compression).  Note that PDF 1.2 also supports
	# Flatedecode (zip compression).

	bits = 8
	params = None

	if im.mode == "1":
		filter = "/ASCIIHexDecode"
		colorspace = "/DeviceGray"
		procset = "/ImageB" # grayscale
		bits = 1
	elif im.mode == "L":
		filter = "/DCTDecode"
		# params = "<< /Predictor 15 /Columns %d >>" % (width-2)
		colorspace = "/DeviceGray"
		procset = "/ImageB" # grayscale
	elif im.mode == "P":
		filter = "/ASCIIHexDecode"
		colorspace = "[ /Indexed /DeviceRGB 255 <"
		palette = im.im.getpalette("RGB")
		for i in range(256):
			r = ord(palette[i*3])
			g = ord(palette[i*3+1])
			b = ord(palette[i*3+2])
			colorspace = colorspace + "%02x%02x%02x " % (r, g, b)
		colorspace = colorspace + "> ]"
		procset = "/ImageI" # indexed color
	elif im.mode == "RGB":
		filter = "/DCTDecode"
		colorspace = "/DeviceRGB"
		procset = "/ImageC" # color images
	elif im.mode == "CMYK":
		filter = "/DCTDecode"
		colorspace = "/DeviceCMYK"
		procset = "/ImageC" # color images
	else:
		raise ValueError("cannot save mode %s" % im.mode)

	#
	# catalogue

	xref[1] = fp.tell()
	_obj(fp, 1, Type = "/Catalog",
				Pages = "2 0 R")
	_endobj(fp)

	#
	# pages

	xref[2] = fp.tell()
	_obj(fp, 2, Type = "/Pages",
				Count = 1,
				Kids = "[4 0 R]")
	_endobj(fp)

	#
	# image

	op = StringIO.StringIO()

	if filter == "/ASCIIHexDecode":
		if bits == 1:
			# FIXME: the hex encoder doesn't support packed 1-bit
			# images; do things the hard way...
			data = im.tostring("raw", "1")
			im = Image.new("L", (len(data), 1), None)
			im.putdata(data)
		ImageFile._save(im, op, [("hex", (0,0)+im.size, 0, im.mode)])
	elif filter == "/DCTDecode":
		ImageFile._save(im, op, [("jpeg", (0,0)+im.size, 0, im.mode)])
	elif filter == "/FlateDecode":
		ImageFile._save(im, op, [("zip", (0,0)+im.size, 0, im.mode)])
	elif filter == "/RunLengthDecode":
		ImageFile._save(im, op, [("packbits", (0,0)+im.size, 0, im.mode)])
	else:
		raise ValueError("unsupported PDF filter (%s)" % filter)

	xref[3] = fp.tell()
	_obj(fp, 3, Type = "/XObject",
				Subtype = "/Image",
				Width = width, # * 72.0 / resolution,
				Height = height, # * 72.0 / resolution,
				Length = len(op.getvalue()),
				Filter = filter,
				BitsPerComponent = bits,
				DecodeParams = params,
				ColorSpace = colorspace)

	fp.write("stream\n")
	fp.write(op.getvalue())
	fp.write("\nendstream\n")

	_endobj(fp)

	#
	# page

	xref[4] = fp.tell()
	_obj(fp, 4)
	fp.write("<<\n/Type /Page\n/Parent 2 0 R\n"\
			 "/Resources <<\n/ProcSet [ /PDF %s ]\n"\
			 "/XObject << /image 3 0 R >>\n>>\n"\
			 "/MediaBox [ 0 0 %d %d ]\n/Contents 5 0 R\n>>\n" %\
			 (procset, int(width * 72.0 /resolution) , int(height * 72.0 / resolution)))
	_endobj(fp)

	#
	# page contents

	op = StringIO.StringIO()

	op.write("q %d 0 0 %d 0 0 cm /image Do Q\n" % (int(width * 72.0 / resolution), int(height * 72.0 / resolution)))

	xref[5] = fp.tell()
	_obj(fp, 5, Length = len(op.getvalue()))

	fp.write("stream\n")
	fp.write(op.getvalue())
	fp.write("\nendstream\n")

	_endobj(fp)

	#
	# trailer
	startxref = fp.tell()
	fp.write("xref\n0 %d\n0000000000 65535 f \n" % len(xref))
	for x in xref[1:]:
		fp.write("%010d 00000 n \n" % x)
	fp.write("trailer\n<<\n/Size %d\n/Root 1 0 R\n>>\n" % len(xref))
	fp.write("startxref\n%d\n%%%%EOF\n" % startxref)
	fp.flush()
コード例 #20
0
def _save(im, fp, filename):

	try:
		rawmode, prefix, photo, format, bits, extra = SAVE_INFO[im.mode]
	except KeyError:
		raise IOError, "cannot write mode %s as TIFF" % im.mode

	ifd = ImageFileDirectory(prefix)

	# -- multi-page -- skip TIFF header on subsequent pages
	if fp.tell() == 0:
		# tiff header (write via IFD to get everything right)
		# PIL always starts the first IFD at offset 8
		fp.write(ifd.prefix + ifd.o16(42) + ifd.o32(8))

	ifd[IMAGEWIDTH] = im.size[0]
	ifd[IMAGELENGTH] = im.size[1]

	# additions written by Greg Couch, [email protected]
	# inspired by image-sig posting from Kevin Cazabon, [email protected]
	if hasattr(im, 'tag'):
		# preserve tags from original TIFF image file
		for key in (RESOLUTION_UNIT, X_RESOLUTION, Y_RESOLUTION):
			if im.tag.tagdata.has_key(key):
				ifd[key] = im.tag.tagdata.get(key)
		# preserve some more tags from original TIFF image file
		# -- 2008-06-06 Florian Hoech
		ifd.tagtype = im.tag.tagtype
		for key in (IPTC_NAA_CHUNK, PHOTOSHOP_CHUNK, XMP):
			if im.tag.has_key(key):
				ifd[key] = im.tag[key]
		# preserve ICC profile (should also work when saving other formats
		# which support profiles as TIFF) -- 2008-06-06 Florian Hoech
		if im.info.has_key("icc_profile"):
			ifd[ICCPROFILE] = im.info["icc_profile"]
	if im.encoderinfo.has_key("description"):
		ifd[IMAGEDESCRIPTION] = im.encoderinfo["description"]
	if im.encoderinfo.has_key("resolution"):
		ifd[X_RESOLUTION] = ifd[Y_RESOLUTION] \
								= _cvt_res(im.encoderinfo["resolution"])
	if im.encoderinfo.has_key("x resolution"):
		ifd[X_RESOLUTION] = _cvt_res(im.encoderinfo["x resolution"])
	if im.encoderinfo.has_key("y resolution"):
		ifd[Y_RESOLUTION] = _cvt_res(im.encoderinfo["y resolution"])
	if im.encoderinfo.has_key("resolution unit"):
		unit = im.encoderinfo["resolution unit"]
		if unit == "inch":
			ifd[RESOLUTION_UNIT] = 2
		elif unit == "cm" or unit == "centimeter":
			ifd[RESOLUTION_UNIT] = 3
		else:
			ifd[RESOLUTION_UNIT] = 1
	if im.encoderinfo.has_key("software"):
		ifd[SOFTWARE] = im.encoderinfo["software"]
	if im.encoderinfo.has_key("date time"):
		ifd[DATE_TIME] = im.encoderinfo["date time"]
	if im.encoderinfo.has_key("artist"):
		ifd[ARTIST] = im.encoderinfo["artist"]
	if im.encoderinfo.has_key("copyright"):
		ifd[COPYRIGHT] = im.encoderinfo["copyright"]

	dpi = im.encoderinfo.get("dpi")
	if dpi:
		ifd[RESOLUTION_UNIT] = 2
		ifd[X_RESOLUTION] = _cvt_res(dpi[0])
		ifd[Y_RESOLUTION] = _cvt_res(dpi[1])

	if bits != (1,):
		ifd[BITSPERSAMPLE] = bits
		if len(bits) != 1:
			ifd[SAMPLESPERPIXEL] = len(bits)
	if extra is not None:
		ifd[EXTRASAMPLES] = extra
	if format != 1:
		ifd[SAMPLEFORMAT] = format

	ifd[PHOTOMETRIC_INTERPRETATION] = photo

	if im.mode == "P":
		lut = im.im.getpalette("RGB", "RGB;L")
		ifd[COLORMAP] = tuple(map(lambda v: ord(v) * 256, lut))

	# data orientation
	stride = len(bits) * ((im.size[0]*bits[0]+7)/8)
	ifd[ROWSPERSTRIP] = im.size[1]
	ifd[STRIPBYTECOUNTS] = stride * im.size[1]
	ifd[STRIPOFFSETS] = 0 # this is adjusted by IFD writer
	ifd[COMPRESSION] = 1 # no compression

	offset = ifd.save(fp)

	ImageFile._save(im, fp, [
		("raw", (0,0)+im.size, offset, (rawmode, stride, 1))
		])


	# -- helper for multi-page save --
	if im.encoderinfo.has_key("_debug_multipage"):
		#just to access o32 and o16 (using correct byte order)
		im._debug_multipage = ifd
コード例 #21
0
ファイル: PngImagePlugin.py プロジェクト: samis/blockBox
def _save(im, fp, filename, chunk=putchunk, check=0):
    # save an image to disk (called by the save method)

    mode = im.mode

    if mode == "P":

        #
        # attempt to minimize storage requirements for palette images

        if im.encoderinfo.has_key("bits"):

            # number of bits specified by user
            n = 1 << im.encoderinfo["bits"]

        else:

            # check palette contents
            n = 256  # FIXME

        if n <= 2:
            bits = 1
        elif n <= 4:
            bits = 2
        elif n <= 16:
            bits = 4
        else:
            bits = 8

        if bits != 8:
            mode = "%s;%d" % (mode, bits)

    # encoder options
    if im.encoderinfo.has_key("dictionary"):
        dictionary = im.encoderinfo["dictionary"]
    else:
        dictionary = ""

    im.encoderconfig = (im.encoderinfo.has_key("optimize"), dictionary)

    # get the corresponding PNG mode
    try:
        rawmode, mode = _OUTMODES[mode]
    except KeyError:
        raise IOError, "cannot write mode %s as PNG" % mode

    if check:
        return check

    #
    # write minimal PNG file

    fp.write(_MAGIC)

    chunk(
        fp,
        "IHDR",
        o32(im.size[0]),
        o32(im.size[1]),  #  0: size
        mode,  #  8: depth/type
        chr(0),  # 10: compression
        chr(0),  # 11: filter category
        chr(0))  # 12: interlace flag

    if im.mode == "P":
        chunk(fp, "PLTE", im.im.getpalette("RGB"))

    if im.encoderinfo.has_key("transparency"):
        if im.mode == "P":
            transparency = max(0, min(255, im.encoderinfo["transparency"]))
            chunk(fp, "tRNS", chr(255) * transparency + chr(0))
        elif im.mode == "L":
            transparency = max(0, min(65535, im.encoderinfo["transparency"]))
            chunk(fp, "tRNS", o16(transparency))
        elif im.mode == "RGB":
            red, green, blue = im.encoderinfo["transparency"]
            chunk(fp, "tRNS", o16(red) + o16(green) + o16(blue))
        else:
            raise IOError("cannot use transparency for this mode")

    if 0:
        # FIXME: to be supported some day
        chunk(fp, "gAMA", o32(int(gamma * 100000.0)))

    dpi = im.encoderinfo.get("dpi")
    if dpi:
        chunk(fp, "pHYs", o32(int(dpi[0] / 0.0254 + 0.5)),
              o32(int(dpi[1] / 0.0254 + 0.5)), chr(1))

    info = im.encoderinfo.get("pnginfo")
    if info:
        for cid, data in info.chunks:
            chunk(fp, cid, data)

    # ICC profile writing support -- 2008-06-06 Florian Hoech
    if im.info.has_key("icc_profile"):
        # ICC profile
        # according to PNG spec, the iCCP chunk contains:
        # Profile name  1-79 bytes (character string)
        # Null separator		1 byte (null character)
        # Compression method	1 byte (0)
        # Compressed profile	n bytes (zlib with deflate compression)
        try:
            import ICCProfile
            p = ICCProfile.ICCProfile(im.info["icc_profile"])
            name = p.tags.desc.get(
                "ASCII",
                p.tags.desc.get(
                    "Unicode",
                    p.tags.desc.get(
                        "Macintosh",
                        p.tags.desc.get("en",
                                        {}).get("US", "ICC Profile")))).encode(
                                            "latin1", "replace")[:79]
        except ImportError:
            name = "ICC Profile"
        data = name + "\0\0" + zlib.compress(im.info["icc_profile"])
        chunk(fp, "iCCP", data)

    ImageFile._save(im, _idat(fp, chunk),
                    [("zip", (0, 0) + im.size, 0, rawmode)])

    chunk(fp, "IEND", "")

    try:
        fp.flush()
    except:
        pass
コード例 #22
0
def _save(im, fp, filename, chunk=putchunk, check=0):
	# save an image to disk (called by the save method)

	mode = im.mode

	if mode == "P":

		#
		# attempt to minimize storage requirements for palette images

		if im.encoderinfo.has_key("bits"):

			# number of bits specified by user
			n = 1 << im.encoderinfo["bits"]

		else:

			# check palette contents
			n = 256 # FIXME

		if n <= 2:
			bits = 1
		elif n <= 4:
			bits = 2
		elif n <= 16:
			bits = 4
		else:
			bits = 8

		if bits != 8:
			mode = "%s;%d" % (mode, bits)

	# encoder options
	if im.encoderinfo.has_key("dictionary"):
		dictionary = im.encoderinfo["dictionary"]
	else:
		dictionary = ""

	im.encoderconfig = (im.encoderinfo.has_key("optimize"), dictionary)

	# get the corresponding PNG mode
	try:
		rawmode, mode = _OUTMODES[mode]
	except KeyError:
		raise IOError, "cannot write mode %s as PNG" % mode

	if check:
		return check

	#
	# write minimal PNG file

	fp.write(_MAGIC)

	chunk(fp, "IHDR",
		  o32(im.size[0]), o32(im.size[1]),	 #  0: size
		  mode,								 #  8: depth/type
		  chr(0),							   # 10: compression
		  chr(0),							   # 11: filter category
		  chr(0))							   # 12: interlace flag

	if im.mode == "P":
		chunk(fp, "PLTE", im.im.getpalette("RGB"))

	if im.encoderinfo.has_key("transparency"):
		if im.mode == "P":
			transparency = max(0, min(255, im.encoderinfo["transparency"]))
			chunk(fp, "tRNS", chr(255) * transparency + chr(0))
		elif im.mode == "L":
			transparency = max(0, min(65535, im.encoderinfo["transparency"]))
			chunk(fp, "tRNS", o16(transparency))
		elif im.mode == "RGB":
			red, green, blue = im.encoderinfo["transparency"]
			chunk(fp, "tRNS", o16(red) + o16(green) + o16(blue))
		else:
			raise IOError("cannot use transparency for this mode")

	if 0:
		# FIXME: to be supported some day
		chunk(fp, "gAMA", o32(int(gamma * 100000.0)))

	dpi = im.encoderinfo.get("dpi")
	if dpi:
		chunk(fp, "pHYs",
			  o32(int(dpi[0] / 0.0254 + 0.5)),
			  o32(int(dpi[1] / 0.0254 + 0.5)),
			  chr(1))

	info = im.encoderinfo.get("pnginfo")
	if info:
		for cid, data in info.chunks:
			chunk(fp, cid, data)

	# ICC profile writing support -- 2008-06-06 Florian Hoech
	if im.info.has_key("icc_profile"):
		# ICC profile
		# according to PNG spec, the iCCP chunk contains:
		# Profile name  1-79 bytes (character string)
		# Null separator		1 byte (null character)
		# Compression method	1 byte (0)
		# Compressed profile	n bytes (zlib with deflate compression)
		try:
			import ICCProfile
			p = ICCProfile.ICCProfile(im.info["icc_profile"])
			name = p.tags.desc.get("ASCII", p.tags.desc.get("Unicode", p.tags.desc.get("Macintosh", p.tags.desc.get("en", {}).get("US", "ICC Profile")))).encode("latin1", "replace")[:79]
		except ImportError:
			name = "ICC Profile"
		data = name + "\0\0" + zlib.compress(im.info["icc_profile"])
		chunk(fp, "iCCP", data)

	ImageFile._save(im, _idat(fp, chunk), [("zip", (0,0)+im.size, 0, rawmode)])

	chunk(fp, "IEND", "")

	try:
		fp.flush()
	except:
		pass
コード例 #23
0
ファイル: PalmImagePlugin.py プロジェクト: samis/blockBox
def _save(im, fp, filename, check=0):

    if im.mode == "P":

        # we assume this is a color Palm image with the standard colormap,
        # unless the "info" dict has a "custom-colormap" field

        rawmode = "P"
        bpp = 8
        version = 1

    elif im.mode == "L" and im.encoderinfo.has_key(
            "bpp") and im.encoderinfo["bpp"] in (1, 2, 4):

        # this is 8-bit grayscale, so we shift it to get the high-order bits, and invert it because
        # Palm does greyscale from white (0) to black (1)
        bpp = im.encoderinfo["bpp"]
        im = im.point(lambda x, shift=8 - bpp, maxval=(1 << bpp) - 1: maxval -
                      (x >> shift))
        # we ignore the palette here
        im.mode = "P"
        rawmode = "P;" + str(bpp)
        version = 1

    elif im.mode == "L" and im.info.has_key("bpp") and im.info["bpp"] in (1, 2,
                                                                          4):

        # here we assume that even though the inherent mode is 8-bit grayscale, only
        # the lower bpp bits are significant.  We invert them to match the Palm.
        bpp = im.info["bpp"]
        im = im.point(lambda x, maxval=(1 << bpp) - 1: maxval - (x & maxval))
        # we ignore the palette here
        im.mode = "P"
        rawmode = "P;" + str(bpp)
        version = 1

    elif im.mode == "1":

        # monochrome -- write it inverted, as is the Palm standard
        rawmode = "1;I"
        bpp = 1
        version = 0

    else:

        raise IOError, "cannot write mode %s as Palm" % im.mode

    if check:
        return check

    #
    # make sure image data is available
    im.load()

    # write header

    cols = im.size[0]
    rows = im.size[1]

    rowbytes = ((cols + (16 / bpp - 1)) / (16 / bpp)) * 2
    transparent_index = 0
    compression_type = _COMPRESSION_TYPES["none"]

    flags = 0
    if im.mode == "P" and im.info.has_key("custom-colormap"):
        flags = flags & _FLAGS["custom-colormap"]
        colormapsize = 4 * 256 + 2
        colormapmode = im.palette.mode
        colormap = im.getdata().getpalette()
    else:
        colormapsize = 0

    if im.info.has_key("offset"):
        offset = (rowbytes * rows + 16 + 3 + colormapsize) / 4
    else:
        offset = 0

    fp.write(o16b(cols) + o16b(rows) + o16b(rowbytes) + o16b(flags))
    fp.write(chr(bpp))
    fp.write(chr(version))
    fp.write(o16b(offset))
    fp.write(chr(transparent_index))
    fp.write(chr(compression_type))
    fp.write(o16b(0))  # reserved by Palm

    # now write colormap if necessary

    if colormapsize > 0:
        fp.write(o16b(256))
        for i in range(256):
            fp.write(chr(i))
            if colormapmode == 'RGB':
                fp.write(
                    chr(colormap[3 * i]) + chr(colormap[3 * i + 1]) +
                    chr(colormap[3 * i + 2]))
            elif colormapmode == 'RGBA':
                fp.write(
                    chr(colormap[4 * i]) + chr(colormap[4 * i + 1]) +
                    chr(colormap[4 * i + 2]))

    # now convert data to raw form
    ImageFile._save(im, fp,
                    [("raw", (0, 0) + im.size, 0, (rawmode, rowbytes, 1))])

    fp.flush()
コード例 #24
0
def _save(im, fp, filename, check=0):

	if im.mode == "P":

		# we assume this is a color Palm image with the standard colormap,
		# unless the "info" dict has a "custom-colormap" field

		rawmode = "P"
		bpp = 8
		version = 1

	elif im.mode == "L" and im.encoderinfo.has_key("bpp") and im.encoderinfo["bpp"] in (1, 2, 4):

		# this is 8-bit grayscale, so we shift it to get the high-order bits, and invert it because
		# Palm does greyscale from white (0) to black (1)
		bpp = im.encoderinfo["bpp"]
		im = im.point(lambda x, shift=8-bpp, maxval=(1 << bpp)-1: maxval - (x >> shift))
		# we ignore the palette here
		im.mode = "P"
		rawmode = "P;" + str(bpp)
		version = 1

	elif im.mode == "L" and im.info.has_key("bpp") and im.info["bpp"] in (1, 2, 4):

		# here we assume that even though the inherent mode is 8-bit grayscale, only
		# the lower bpp bits are significant.  We invert them to match the Palm.
		bpp = im.info["bpp"]
		im = im.point(lambda x, maxval=(1 << bpp)-1: maxval - (x & maxval))
		# we ignore the palette here
		im.mode = "P"
		rawmode = "P;" + str(bpp)
		version = 1

	elif im.mode == "1":

		# monochrome -- write it inverted, as is the Palm standard
		rawmode = "1;I"
		bpp = 1
		version = 0

	else:

		raise IOError, "cannot write mode %s as Palm" % im.mode

	if check:
		return check

	#
	# make sure image data is available
	im.load()

	# write header

	cols = im.size[0]
	rows = im.size[1]

	rowbytes = ((cols + (16/bpp - 1)) / (16 / bpp)) * 2;
	transparent_index = 0
	compression_type = _COMPRESSION_TYPES["none"]

	flags = 0;
	if im.mode == "P" and im.info.has_key("custom-colormap"):
		flags = flags & _FLAGS["custom-colormap"]
		colormapsize = 4 * 256 + 2;
		colormapmode = im.palette.mode
		colormap = im.getdata().getpalette()
	else:
		colormapsize = 0

	if im.info.has_key("offset"):
		offset = (rowbytes * rows + 16 + 3 + colormapsize) / 4;
	else:
		offset = 0

	fp.write(o16b(cols) + o16b(rows) + o16b(rowbytes) + o16b(flags))
	fp.write(chr(bpp))
	fp.write(chr(version))
	fp.write(o16b(offset))
	fp.write(chr(transparent_index))
	fp.write(chr(compression_type))
	fp.write(o16b(0))   # reserved by Palm

	# now write colormap if necessary

	if colormapsize > 0:
		fp.write(o16b(256))
		for i in range(256):
			fp.write(chr(i))
			if colormapmode == 'RGB':
				fp.write(chr(colormap[3 * i]) + chr(colormap[3 * i + 1]) + chr(colormap[3 * i + 2]))
			elif colormapmode == 'RGBA':
				fp.write(chr(colormap[4 * i]) + chr(colormap[4 * i + 1]) + chr(colormap[4 * i + 2]))

	# now convert data to raw form
	ImageFile._save(im, fp, [("raw", (0,0)+im.size, 0, (rawmode, rowbytes, 1))])

	fp.flush()
コード例 #25
0
def _save(im, fp, filename):

	if _imaging_gif:
		# call external driver
		try:
			_imaging_gif.save(im, fp, filename)
			return
		except IOError:
			pass # write uncompressed file

	try:
		rawmode = RAWMODE[im.mode]
		imOut = im
	except KeyError:
		# convert on the fly (EXPERIMENTAL -- I'm not sure PIL
		# should automatically convert images on save...)
		if Image.getmodebase(im.mode) == "RGB":
			imOut = im.convert("P")
			rawmode = "P"
		else:
			imOut = im.convert("L")
			rawmode = "L"

	# header
	for s in getheader(imOut, im.encoderinfo):
		fp.write(s)

	flags = 0

	try:
		interlace = im.encoderinfo["interlace"]
	except KeyError:
		interlace = 1

	# workaround for @PIL153
	if min(im.size) < 16:
		interlace = 0

	if interlace:
		flags = flags | 64

	try:
		transparency = im.encoderinfo["transparency"]
	except KeyError:
		pass
	else:
		# transparency extension block
		fp.write("!" +
				 chr(249) +			 # extension intro
				 chr(4) +			   # length
				 chr(1) +			   # transparency info present
				 o16(0) +			   # duration
				 chr(int(transparency)) # transparency index
				 + chr(0))

	# local image header
	fp.write("," +
			 o16(0) + o16(0) +		  # bounding box
			 o16(im.size[0]) +		  # size
			 o16(im.size[1]) +
			 chr(flags) +			   # flags
			 chr(8))					# bits

	imOut.encoderconfig = (8, interlace)

	ImageFile._save(imOut, fp, [("gif", (0,0)+im.size, 0, rawmode)])

	fp.write("\0") # end of image data

	fp.write(";") # end of file

	try:
		fp.flush()
	except: pass
コード例 #26
0
ファイル: PdfImagePlugin.py プロジェクト: samis/blockBox
def _save(im, fp, filename):
    resolution = im.encoderinfo.get("resolution", 72.0)

    #
    # make sure image data is available
    im.load()

    xref = [0] * (5 + 1)  # placeholders

    fp.write("%PDF-1.2\n")
    fp.write("% created by PIL PDF driver " + __version__ + "\n")

    #
    # Get image characteristics

    width, height = im.size

    # FIXME: Should replace ASCIIHexDecode with RunLengthDecode (packbits)
    # or LZWDecode (tiff/lzw compression).  Note that PDF 1.2 also supports
    # Flatedecode (zip compression).

    bits = 8
    params = None

    if im.mode == "1":
        filter = "/ASCIIHexDecode"
        colorspace = "/DeviceGray"
        procset = "/ImageB"  # grayscale
        bits = 1
    elif im.mode == "L":
        filter = "/DCTDecode"
        # params = "<< /Predictor 15 /Columns %d >>" % (width-2)
        colorspace = "/DeviceGray"
        procset = "/ImageB"  # grayscale
    elif im.mode == "P":
        filter = "/ASCIIHexDecode"
        colorspace = "[ /Indexed /DeviceRGB 255 <"
        palette = im.im.getpalette("RGB")
        for i in range(256):
            r = ord(palette[i * 3])
            g = ord(palette[i * 3 + 1])
            b = ord(palette[i * 3 + 2])
            colorspace = colorspace + "%02x%02x%02x " % (r, g, b)
        colorspace = colorspace + "> ]"
        procset = "/ImageI"  # indexed color
    elif im.mode == "RGB":
        filter = "/DCTDecode"
        colorspace = "/DeviceRGB"
        procset = "/ImageC"  # color images
    elif im.mode == "CMYK":
        filter = "/DCTDecode"
        colorspace = "/DeviceCMYK"
        procset = "/ImageC"  # color images
    else:
        raise ValueError("cannot save mode %s" % im.mode)

    #
    # catalogue

    xref[1] = fp.tell()
    _obj(fp, 1, Type="/Catalog", Pages="2 0 R")
    _endobj(fp)

    #
    # pages

    xref[2] = fp.tell()
    _obj(fp, 2, Type="/Pages", Count=1, Kids="[4 0 R]")
    _endobj(fp)

    #
    # image

    op = StringIO.StringIO()

    if filter == "/ASCIIHexDecode":
        if bits == 1:
            # FIXME: the hex encoder doesn't support packed 1-bit
            # images; do things the hard way...
            data = im.tostring("raw", "1")
            im = Image.new("L", (len(data), 1), None)
            im.putdata(data)
        ImageFile._save(im, op, [("hex", (0, 0) + im.size, 0, im.mode)])
    elif filter == "/DCTDecode":
        ImageFile._save(im, op, [("jpeg", (0, 0) + im.size, 0, im.mode)])
    elif filter == "/FlateDecode":
        ImageFile._save(im, op, [("zip", (0, 0) + im.size, 0, im.mode)])
    elif filter == "/RunLengthDecode":
        ImageFile._save(im, op, [("packbits", (0, 0) + im.size, 0, im.mode)])
    else:
        raise ValueError("unsupported PDF filter (%s)" % filter)

    xref[3] = fp.tell()
    _obj(
        fp,
        3,
        Type="/XObject",
        Subtype="/Image",
        Width=width,  # * 72.0 / resolution,
        Height=height,  # * 72.0 / resolution,
        Length=len(op.getvalue()),
        Filter=filter,
        BitsPerComponent=bits,
        DecodeParams=params,
        ColorSpace=colorspace)

    fp.write("stream\n")
    fp.write(op.getvalue())
    fp.write("\nendstream\n")

    _endobj(fp)

    #
    # page

    xref[4] = fp.tell()
    _obj(fp, 4)
    fp.write("<<\n/Type /Page\n/Parent 2 0 R\n"\
       "/Resources <<\n/ProcSet [ /PDF %s ]\n"\
       "/XObject << /image 3 0 R >>\n>>\n"\
       "/MediaBox [ 0 0 %d %d ]\n/Contents 5 0 R\n>>\n" %\
       (procset, int(width * 72.0 /resolution) , int(height * 72.0 / resolution)))
    _endobj(fp)

    #
    # page contents

    op = StringIO.StringIO()

    op.write("q %d 0 0 %d 0 0 cm /image Do Q\n" %
             (int(width * 72.0 / resolution), int(height * 72.0 / resolution)))

    xref[5] = fp.tell()
    _obj(fp, 5, Length=len(op.getvalue()))

    fp.write("stream\n")
    fp.write(op.getvalue())
    fp.write("\nendstream\n")

    _endobj(fp)

    #
    # trailer
    startxref = fp.tell()
    fp.write("xref\n0 %d\n0000000000 65535 f \n" % len(xref))
    for x in xref[1:]:
        fp.write("%010d 00000 n \n" % x)
    fp.write("trailer\n<<\n/Size %d\n/Root 1 0 R\n>>\n" % len(xref))
    fp.write("startxref\n%d\n%%%%EOF\n" % startxref)
    fp.flush()