def raster(self, filename, client): """Takes a filename and converts it to a raster image reportlab can process""" if not os.path.exists(filename): log.error("Missing image file: %s",filename) return missing try: # First try to rasterize using the suggested backend backend = self.get_backend(filename, client)[1] return backend.raster(filename, client) except: pass # Last resort: try everything if sys.platform[0:4] == 'java': try: from javax.imageio import ImageIO from java.io import File iis = ImageIO.createImageInputStream(File(filename)) readers = ImageIO.getImageReaders(iis) if readers.hasNext(): reader = readers.next() reader.setInput(iis, True) metadata = reader.getImageMetadata(0) # this means imageio can read it return filename else: log.warning("Java's ImageIO cannot read the file [%s]", filename) except Exception, error: log.warning("Could not use Java's ImageIO to read the file [%s]: %s", filename, str(error))
def size_for_node(self, node, client): '''Given a docutils image node, returns the size the image should have in the PDF document, and what 'kind' of size that is. That involves lots of guesswork''' uri = str(node.get("uri")) if uri.split("://")[0].lower() not in ('http','ftp','https'): uri = os.path.join(client.basedir,uri) else: uri, _ = urllib.urlretrieve(uri) client.to_unlink.append(uri) srcinfo = client, uri # Extract all the information from the URI imgname, extension, options = self.split_uri(uri) if not os.path.isfile(imgname): imgname = missing scale = float(node.get('scale', 100))/100 size_known = False # Figuring out the size to display of an image is ... annoying. # If the user provides a size with a unit, it's simple, adjustUnits # will return it in points and we're done. # However, often the unit wil be "%" (specially if it's meant for # HTML originally. In which case, we will use a percentage of # the containing frame. # Find the image size in pixels: kind = 'direct' xdpi, ydpi = client.styles.def_dpi, client.styles.def_dpi extension = imgname.split('.')[-1].lower() if extension in ['svg','svgz'] and SVGImage.available(): iw, ih = SVGImage(imgname, srcinfo=srcinfo).wrap(0, 0) # These are in pt, so convert to px iw = iw * xdpi / 72 ih = ih * ydpi / 72 elif extension in [ "ai", "ccx", "cdr", "cgm", "cmx", "sk1", "sk", "xml", "wmf", "fig"] and VectorImage.available(): iw, ih = VectorImage(imgname, srcinfo=srcinfo).wrap(0, 0) # These are in pt, so convert to px iw = iw * xdpi / 72 ih = ih * ydpi / 72 elif extension == 'pdf': if VectorPdf is not None: box = VectorPdf.load_xobj(srcinfo).BBox else: pdf = LazyImports.pdfinfo if pdf is None: log.warning('PDF images are not supported without pyPdf or pdfrw [%s]', nodeid(node)) return 0, 0, 'direct' reader = pdf.PdfFileReader(open(imgname, 'rb')) box = [float(x) for x in reader.getPage(0)['/MediaBox']] x1, y1, x2, y2 = box # These are in pt, so convert to px iw = float((x2-x1) * xdpi / 72) ih = float((y2-y1) * ydpi / 72) size_known = True # Assume size from original PDF is OK else: keeptrying = True if sys.platform[0:4] == 'java': try: from javax.imageio import ImageIO from java.io import File iis = ImageIO.createImageInputStream(File(imgname)) readers = ImageIO.getImageReaders(iis) if readers.hasNext(): reader = readers.next() reader.setInput(iis, True) metadata = reader.getImageMetadata(0) iw = reader.getWidth(0) ih = reader.getHeight(0) xdpi = None ydpi = None if metadata.getNativeMetadataFormatName() == 'javax_imageio_png_1.0': png_metadata = metadata.getAsTree(metadata.getNativeMetadataFormatName()) if png_metadata is not None: phys_metadata = png_metadata.getElementsByTagName('pHYs') if phys_metadata.getLength() == 1: xdpi = phys_metadata.item(0).getAttribute('pixelsPerUnitXAxis') if xdpi is not None: xdpi = float(xdpi) ydpi = phys_metadata.item(0).getAttribute('pixelsPerUnitYAxis') if ydpi is not None: ydpi = float(ydpi) elif metadata.getNativeMetadataFormatName() == 'javax_imageio_jpeg_image_1.0': jpg_metadata = metadata.getAsTree(metadata.getNativeMetadataFormatName()) if jpg_metadata is not None: jfif_metadata = jpg_metadata.getElementsByTagName('app0JFIF') if jfif_metadata.getLength() == 1: resUnits = jfif_metadata.item(0).getAttribute('resUnits') # 0 = plain aspect ratio, 1 = dots per inch, 2 = dots per cm if resUnits is not None and (resUnits == '1' or resUnits == '2'): xdpi = jfif_metadata.item(0).getAttribute('pixelsPerUnitXAxis') if xdpi is not None: xdpi = float(xdpi) if resUnits == '2': xdpi = xdpi * 2.54 ydpi = jfif_metadata.item(0).getAttribute('pixelsPerUnitYAxis') if ydpi is not None: ydpi = float(ydpi) if resUnits == '2': ydpi = ydpi * 2.54 if xdpi is None: xdpi = 300 if ydpi is None: ydpi = 300 keeptrying = False except Exception, err: log.error('Error %s', str(err)) pass if LazyImports.PILImage: try: img = LazyImports.PILImage.open(imgname) img.load() iw, ih = img.size xdpi, ydpi = img.info.get('dpi', (xdpi, ydpi)) keeptrying = False except IOError: # PIL throws this when it's a broken/unknown image pass if keeptrying and LazyImports.PMImage: img = LazyImports.PMImage(imgname) iw = img.size().width() ih = img.size().height() density=img.density() # The density is in pixelspercentimeter (!?) xdpi=density.width()*2.54 ydpi=density.height()*2.54 keeptrying = False if keeptrying: if extension not in ['jpg', 'jpeg']: log.error("The image (%s, %s) is broken or in an unknown format" , imgname, nodeid(node)) raise ValueError else: # Can be handled by reportlab log.warning("Can't figure out size of the image (%s, %s). Install PIL for better results." , imgname, nodeid(node)) iw = 1000 ih = 1000