def _bracepath(self, x0_pt, y0_pt, x1_pt, y1_pt): # <<< height_pt = unit.topt(self.totalheight) totallength_pt = math.hypot(x1_pt - x0_pt, y1_pt - y0_pt) leftlength_pt = self.middlerelpos * totallength_pt rightlength_pt = totallength_pt - leftlength_pt ithick_pt = unit.topt(self.innerstrokesthickness) othick_pt = unit.topt(self.outerstrokesthickness) bthick_pt = unit.topt(self.barthickness) # create the left halfbrace with positive slanting # because we will mirror this part cos_iangle = math.cos( math.radians(0.5 * self.innerstrokesangle - self.slantstrokesangle)) sin_iangle = math.sin( math.radians(0.5 * self.innerstrokesangle - self.slantstrokesangle)) cos_oangle = math.cos( math.radians(self.outerstrokesangle - self.slantstrokesangle)) sin_oangle = math.sin( math.radians(self.outerstrokesangle - self.slantstrokesangle)) cos_slangle = math.cos(math.radians(-self.slantstrokesangle)) sin_slangle = math.sin(math.radians(-self.slantstrokesangle)) ilength_pt = self.innerstrokesrelheight * height_pt / cos_iangle olength_pt = self.outerstrokesrelheight * height_pt / cos_oangle bracepath = self._halfbracepath_pt( leftlength_pt, height_pt, ilength_pt, olength_pt, ithick_pt, othick_pt, bthick_pt, cos_iangle, sin_iangle, cos_oangle, sin_oangle, cos_slangle, sin_slangle).reversed().transformed(trafo.mirror(90)) # create the right halfbrace with negative slanting cos_iangle = math.cos( math.radians(0.5 * self.innerstrokesangle + self.slantstrokesangle)) sin_iangle = math.sin( math.radians(0.5 * self.innerstrokesangle + self.slantstrokesangle)) cos_oangle = math.cos( math.radians(self.outerstrokesangle + self.slantstrokesangle)) sin_oangle = math.sin( math.radians(self.outerstrokesangle + self.slantstrokesangle)) cos_slangle = math.cos(math.radians(-self.slantstrokesangle)) sin_slangle = math.sin(math.radians(-self.slantstrokesangle)) ilength_pt = self.innerstrokesrelheight * height_pt / cos_iangle olength_pt = self.outerstrokesrelheight * height_pt / cos_oangle bracepath = bracepath << self._halfbracepath_pt( rightlength_pt, height_pt, ilength_pt, olength_pt, ithick_pt, othick_pt, bthick_pt, cos_iangle, sin_iangle, cos_oangle, sin_oangle, cos_slangle, sin_slangle) return bracepath.transformed( # two trafos for matching the given endpoints trafo.translate_pt(x0_pt, y0_pt) * trafo.rotate_pt( math.degrees(math.atan2(y1_pt - y0_pt, x1_pt - x0_pt))) * # one trafo to move the brace's left outer stroke to zero trafo.translate_pt(leftlength_pt, 0))
def _bracepath(self, x0_pt, y0_pt, x1_pt, y1_pt): # <<< height_pt = unit.topt(self.totalheight) totallength_pt = math.hypot(x1_pt - x0_pt, y1_pt - y0_pt) leftlength_pt = self.middlerelpos * totallength_pt rightlength_pt = totallength_pt - leftlength_pt ithick_pt = unit.topt(self.innerstrokesthickness) othick_pt = unit.topt(self.outerstrokesthickness) bthick_pt = unit.topt(self.barthickness) # create the left halfbrace with positive slanting # because we will mirror this part cos_iangle = math.cos(math.radians(0.5*self.innerstrokesangle - self.slantstrokesangle)) sin_iangle = math.sin(math.radians(0.5*self.innerstrokesangle - self.slantstrokesangle)) cos_oangle = math.cos(math.radians(self.outerstrokesangle - self.slantstrokesangle)) sin_oangle = math.sin(math.radians(self.outerstrokesangle - self.slantstrokesangle)) cos_slangle = math.cos(math.radians(-self.slantstrokesangle)) sin_slangle = math.sin(math.radians(-self.slantstrokesangle)) ilength_pt = self.innerstrokesrelheight * height_pt / cos_iangle olength_pt = self.outerstrokesrelheight * height_pt / cos_oangle bracepath = self._halfbracepath_pt(leftlength_pt, height_pt, ilength_pt, olength_pt, ithick_pt, othick_pt, bthick_pt, cos_iangle, sin_iangle, cos_oangle, sin_oangle, cos_slangle, sin_slangle).reversed().transformed(trafo.mirror(90)) # create the right halfbrace with negative slanting cos_iangle = math.cos(math.radians(0.5*self.innerstrokesangle + self.slantstrokesangle)) sin_iangle = math.sin(math.radians(0.5*self.innerstrokesangle + self.slantstrokesangle)) cos_oangle = math.cos(math.radians(self.outerstrokesangle + self.slantstrokesangle)) sin_oangle = math.sin(math.radians(self.outerstrokesangle + self.slantstrokesangle)) cos_slangle = math.cos(math.radians(-self.slantstrokesangle)) sin_slangle = math.sin(math.radians(-self.slantstrokesangle)) ilength_pt = self.innerstrokesrelheight * height_pt / cos_iangle olength_pt = self.outerstrokesrelheight * height_pt / cos_oangle bracepath = bracepath << self._halfbracepath_pt(rightlength_pt, height_pt, ilength_pt, olength_pt, ithick_pt, othick_pt, bthick_pt, cos_iangle, sin_iangle, cos_oangle, sin_oangle, cos_slangle, sin_slangle) return bracepath.transformed( # two trafos for matching the given endpoints trafo.translate_pt(x0_pt, y0_pt) * trafo.rotate_pt(math.degrees(math.atan2(y1_pt-y0_pt, x1_pt-x0_pt))) * # one trafo to move the brace's left outer stroke to zero trafo.translate_pt(leftlength_pt, 0))
def __init__(self, xpos, ypos, image, width=None, height=None, ratio=None, PSstoreimage=0, PSmaxstrlen=4093, PSbinexpand=1, compressmode="Flate", flatecompresslevel=6, dctquality=75, dctoptimize=0, dctprogression=0): # keep a copy of the image instance to ensure different id's self.image = image self.xpos = xpos self.ypos = ypos self.imagewidth, self.imageheight = image.size self.PSstoreimage = PSstoreimage self.PSmaxstrlen = PSmaxstrlen self.PSbinexpand = PSbinexpand if width is not None or height is not None: self.width = width self.height = height if self.width is None: if ratio is None: self.width = self.height * self.imagewidth / float( self.imageheight) else: self.width = ratio * self.height elif self.height is None: if ratio is None: self.height = self.width * self.imageheight / float( self.imagewidth) else: self.height = (1.0 / ratio) * self.width elif ratio is not None: raise ValueError( "can't specify a ratio when setting width and height") else: if ratio is not None: raise ValueError("must specify width or height to set a ratio") widthdpi, heightdpi = image.info[ "dpi"] # fails when no dpi information available self.width = self.imagewidth / float(widthdpi) * unit.t_inch self.height = self.imageheight / float(heightdpi) * unit.t_inch self.xpos_pt = unit.topt(self.xpos) self.ypos_pt = unit.topt(self.ypos) self.width_pt = unit.topt(self.width) self.height_pt = unit.topt(self.height) # create decode and colorspace self.colorspace = self.palettecolorspace = self.palettedata = None if image.mode == "P": palettemode, self.palettedata = image.palette.getdata() self.decode = "[0 255]" try: self.palettecolorspace = { "L": "/DeviceGray", "RGB": "/DeviceRGB", "CMYK": "/DeviceCMYK" }[palettemode] except KeyError: warnings.warn( "image with unknown palette mode '%s' converted to rgb image" % palettemode) image = image.convert("RGB") self.decode = "[0 1 0 1 0 1]" self.palettedata = None self.colorspace = "/DeviceRGB" elif len(image.mode) == 1: if image.mode != "L": image = image.convert("L") warnings.warn( "specific single channel image mode not natively supported, converted to regular grayscale" ) self.decode = "[0 1]" self.colorspace = "/DeviceGray" elif image.mode == "CMYK": self.decode = "[0 1 0 1 0 1 0 1]" self.colorspace = "/DeviceCMYK" else: if image.mode != "RGB": image = image.convert("RGB") warnings.warn("image with unknown mode converted to rgb") self.decode = "[0 1 0 1 0 1]" self.colorspace = "/DeviceRGB" # create imagematrix self.imagematrixPS = (trafo.mirror(0).translated_pt( -self.xpos_pt, self.ypos_pt + self.height_pt).scaled_pt( self.imagewidth / self.width_pt, self.imageheight / self.height_pt)) self.imagematrixPDF = (trafo.scale_pt(self.width_pt, self.height_pt).translated_pt( self.xpos_pt, self.ypos_pt)) # check whether imagedata is compressed or not try: imagecompressed = image.compressed except: imagecompressed = None if compressmode != None and imagecompressed != None: raise ValueError("compression of a compressed image not supported") self.compressmode = compressmode if compressmode is not None and compressmode not in ["Flate", "DCT"]: raise ValueError("invalid compressmode '%s'" % compressmode) if imagecompressed is not None: self.compressmode = imagecompressed if imagecompressed not in ["Flate", "DCT"]: raise ValueError("invalid compressed image '%s'" % imagecompressed) if not haszlib and compressmode == "Flate": warnings.warn("zlib module not available, disable compression") self.compressmode = compressmode = None # create data if compressmode == "Flate": self.data = zlib.compress(image.tostring(), flatecompresslevel) elif compressmode == "DCT": self.data = image.tostring("jpeg", image.mode, dctquality, dctoptimize, dctprogression) else: self.data = image.tostring() self.PSsinglestring = self.PSstoreimage and len( self.data) < self.PSmaxstrlen if self.PSsinglestring: self.PSimagename = "image-%d-%s-singlestring" % (id(image), compressmode) else: self.PSimagename = "image-%d-%s-stringarray" % (id(image), compressmode) self.PDFimagename = "image-%d-%s" % (id(image), compressmode)
def processPS(self, file, writer, context, registry, bbox): mode, data, alpha, palettemode, palettedata = self.imagedata(True) imagematrixPS = (trafo.mirror(0).translated_pt( -self.xpos_pt, self.ypos_pt + self.height_pt).scaled_pt( self.imagewidth / self.width_pt, self.imageheight / self.height_pt)) PSsinglestring = self.PSstoreimage and len(data) < self.PSmaxstrlen if PSsinglestring: PSimagename = "image-%d-%s-singlestring" % (id( self.image), self.compressmode) else: PSimagename = "image-%d-%s-stringarray" % (id( self.image), self.compressmode) if self.PSstoreimage and not PSsinglestring: registry.add( pswriter.PSdefinition( "imagedataaccess", "{ /imagedataindex load " # get list index "dup 1 add /imagedataindex exch store " # store increased index "/imagedataid load exch get }") ) # select string from array if self.PSstoreimage: registry.add( PSimagedata(PSimagename, data, PSsinglestring, self.PSmaxstrlen)) bbox += self.bbox() file.write("gsave\n") if palettedata is not None: file.write("[ /Indexed %s %i\n" % (devicenames[palettemode], len(palettedata) / 3 - 1)) file.write("%%%%BeginData: %i ASCII Lines\n" % ascii85lines(len(palettedata))) file.write("<~") ascii85stream(file, palettedata) file.write("~>\n" "%%EndData\n") file.write("] setcolorspace\n") else: file.write("%s setcolorspace\n" % devicenames[mode]) if self.PSstoreimage and not PSsinglestring: file.write( "/imagedataindex 0 store\n" # not use the stack since interpreters differ in their stack usage "/imagedataid %s store\n" % PSimagename) file.write("<<\n") if alpha: file.write("/ImageType 3\n" "/DataDict\n" "<<\n") file.write("/ImageType 1\n" "/Width %i\n" % self.imagewidth) file.write("/Height %i\n" % self.imageheight) file.write("/BitsPerComponent 8\n" "/ImageMatrix %s\n" % imagematrixPS) file.write("/Decode %s\n" % decodestrings[mode]) file.write("/DataSource ") if self.PSstoreimage: if PSsinglestring: file.write("/%s load" % PSimagename) else: file.write( "/imagedataaccess load" ) # some printers do not allow for inline code here -> we store it in a resource else: if self.PSbinexpand == 2: file.write("currentfile /ASCIIHexDecode filter") else: file.write("currentfile /ASCII85Decode filter") if self.compressmode or self.imagecompressed: file.write(" /%sDecode filter" % (self.compressmode or self.imagecompressed)) file.write("\n") file.write(">>\n") if alpha: file.write("/MaskDict\n" "<<\n" "/ImageType 1\n" "/Width %i\n" % self.imagewidth) file.write("/Height %i\n" % self.imageheight) file.write("/BitsPerComponent 8\n" "/ImageMatrix %s\n" % imagematrixPS) file.write("/Decode [1 0]\n" ">>\n" "/InterleaveType 1\n" ">>\n") if self.PSstoreimage: file.write("image\n") else: if self.PSbinexpand == 2: file.write("%%%%BeginData: %i ASCII Lines\n" "image\n" % (asciihexlines(len(data)) + 1)) asciihexstream(file, data) else: # the datasource is currentstream (plus some filters) file.write("%%%%BeginData: %i ASCII Lines\n" "image\n" % (ascii85lines(len(data)) + 1)) ascii85stream(file, data) file.write("~>\n") file.write("%%EndData\n") file.write("grestore\n")
def processPS(self, file, writer, context, registry, bbox): mode, data, alpha, palettemode, palettedata = self.imagedata(True) imagematrixPS = (trafo.mirror(0) .translated_pt(-self.xpos_pt, self.ypos_pt+self.height_pt) .scaled_pt(self.imagewidth/self.width_pt, self.imageheight/self.height_pt)) PSsinglestring = self.PSstoreimage and len(data) < self.PSmaxstrlen if PSsinglestring: PSimagename = "image-%d-%s-singlestring" % (id(self.image), self.compressmode) else: PSimagename = "image-%d-%s-stringarray" % (id(self.image), self.compressmode) if self.PSstoreimage and not PSsinglestring: registry.add(pswriter.PSdefinition("imagedataaccess", "{ /imagedataindex load " # get list index "dup 1 add /imagedataindex exch store " # store increased index "/imagedataid load exch get }")) # select string from array if self.PSstoreimage: registry.add(PSimagedata(PSimagename, data, PSsinglestring, self.PSmaxstrlen)) bbox += self.bbox() file.write("gsave\n") if palettedata is not None: file.write("[ /Indexed %s %i\n" % (devicenames[palettemode], len(palettedata)/3-1)) file.write("%%%%BeginData: %i ASCII Lines\n" % ascii85lines(len(palettedata))) file.write("<~") ascii85stream(file, palettedata) file.write("~>\n" "%%EndData\n") file.write("] setcolorspace\n") else: file.write("%s setcolorspace\n" % devicenames[mode]) if self.PSstoreimage and not PSsinglestring: file.write("/imagedataindex 0 store\n" # not use the stack since interpreters differ in their stack usage "/imagedataid %s store\n" % PSimagename) file.write("<<\n") if alpha: file.write("/ImageType 3\n" "/DataDict\n" "<<\n") file.write("/ImageType 1\n" "/Width %i\n" % self.imagewidth) file.write("/Height %i\n" % self.imageheight) file.write("/BitsPerComponent 8\n" "/ImageMatrix %s\n" % imagematrixPS) file.write("/Decode %s\n" % decodestrings[mode]) file.write("/DataSource ") if self.PSstoreimage: if PSsinglestring: file.write("/%s load" % PSimagename) else: file.write("/imagedataaccess load") # some printers do not allow for inline code here -> we store it in a resource else: if self.PSbinexpand == 2: file.write("currentfile /ASCIIHexDecode filter") else: file.write("currentfile /ASCII85Decode filter") if self.compressmode or self.imagecompressed: file.write(" /%sDecode filter" % (self.compressmode or self.imagecompressed)) file.write("\n") file.write(">>\n") if alpha: file.write("/MaskDict\n" "<<\n" "/ImageType 1\n" "/Width %i\n" % self.imagewidth) file.write("/Height %i\n" % self.imageheight) file.write("/BitsPerComponent 8\n" "/ImageMatrix %s\n" % imagematrixPS) file.write("/Decode [1 0]\n" ">>\n" "/InterleaveType 1\n" ">>\n") if self.PSstoreimage: file.write("image\n") else: if self.PSbinexpand == 2: file.write("%%%%BeginData: %i ASCII Lines\n" "image\n" % (asciihexlines(len(data)) + 1)) asciihexstream(file, data) else: # the datasource is currentstream (plus some filters) file.write("%%%%BeginData: %i ASCII Lines\n" "image\n" % (ascii85lines(len(data)) + 1)) ascii85stream(file, data) file.write("~>\n") file.write("%%EndData\n") file.write("grestore\n")
def __init__(self, xpos, ypos, image, width=None, height=None, ratio=None, PSstoreimage=0, PSmaxstrlen=4093, PSbinexpand=1, compressmode="Flate", flatecompresslevel=6, dctquality=75, dctoptimize=0, dctprogression=0): # keep a copy of the image instance to ensure different id's self.image = image self.xpos = xpos self.ypos = ypos self.imagewidth, self.imageheight = image.size self.PSstoreimage = PSstoreimage self.PSmaxstrlen = PSmaxstrlen self.PSbinexpand = PSbinexpand if width is not None or height is not None: self.width = width self.height = height if self.width is None: if ratio is None: self.width = self.height * self.imagewidth / float(self.imageheight) else: self.width = ratio * self.height elif self.height is None: if ratio is None: self.height = self.width * self.imageheight / float(self.imagewidth) else: self.height = (1.0/ratio) * self.width elif ratio is not None: raise ValueError("can't specify a ratio when setting width and height") else: if ratio is not None: raise ValueError("must specify width or height to set a ratio") widthdpi, heightdpi = image.info["dpi"] # fails when no dpi information available self.width = self.imagewidth / float(widthdpi) * unit.t_inch self.height = self.imageheight / float(heightdpi) * unit.t_inch self.xpos_pt = unit.topt(self.xpos) self.ypos_pt = unit.topt(self.ypos) self.width_pt = unit.topt(self.width) self.height_pt = unit.topt(self.height) # create decode and colorspace self.colorspace = self.palettecolorspace = self.palettedata = None if image.mode == "P": palettemode, self.palettedata = image.palette.getdata() self.decode = "[0 255]" try: self.palettecolorspace = {"L": "/DeviceGray", "RGB": "/DeviceRGB", "CMYK": "/DeviceCMYK"}[palettemode] except KeyError: warnings.warn("image with unknown palette mode '%s' converted to rgb image" % palettemode) image = image.convert("RGB") self.decode = "[0 1 0 1 0 1]" self.palettedata = None self.colorspace = "/DeviceRGB" elif len(image.mode) == 1: if image.mode != "L": image = image.convert("L") warnings.warn("specific single channel image mode not natively supported, converted to regular grayscale") self.decode = "[0 1]" self.colorspace = "/DeviceGray" elif image.mode == "CMYK": self.decode = "[0 1 0 1 0 1 0 1]" self.colorspace = "/DeviceCMYK" else: if image.mode != "RGB": image = image.convert("RGB") warnings.warn("image with unknown mode converted to rgb") self.decode = "[0 1 0 1 0 1]" self.colorspace = "/DeviceRGB" # create imagematrix self.imagematrixPS = (trafo.mirror(0) .translated_pt(-self.xpos_pt, self.ypos_pt+self.height_pt) .scaled_pt(self.imagewidth/self.width_pt, self.imageheight/self.height_pt)) self.imagematrixPDF = (trafo.scale_pt(self.width_pt, self.height_pt) .translated_pt(self.xpos_pt, self.ypos_pt)) # check whether imagedata is compressed or not try: imagecompressed = image.compressed except: imagecompressed = None if compressmode != None and imagecompressed != None: raise ValueError("compression of a compressed image not supported") self.compressmode = compressmode if compressmode is not None and compressmode not in ["Flate", "DCT"]: raise ValueError("invalid compressmode '%s'" % compressmode) if imagecompressed is not None: self.compressmode = imagecompressed if imagecompressed not in ["Flate", "DCT"]: raise ValueError("invalid compressed image '%s'" % imagecompressed) if not haszlib and compressmode == "Flate": warnings.warn("zlib module not available, disable compression") self.compressmode = compressmode = None # create data if compressmode == "Flate": self.data = zlib.compress(image.tostring(), flatecompresslevel) elif compressmode == "DCT": self.data = image.tostring("jpeg", image.mode, dctquality, dctoptimize, dctprogression) else: self.data = image.tostring() self.PSsinglestring = self.PSstoreimage and len(self.data) < self.PSmaxstrlen if self.PSsinglestring: self.PSimagename = "image-%d-%s-singlestring" % (id(image), compressmode) else: self.PSimagename = "image-%d-%s-stringarray" % (id(image), compressmode) self.PDFimagename = "image-%d-%s" % (id(image), compressmode)