import sys, os from CoreGraphics import * class ImageDecorator: """Rescales and decorates images.""" def __init__(self, maxWidth=320, maxHeight=240, borderWidth=5, shadowOffset=5, shadowBlur=2, bgColor=(1, 1, 1, 1), quality=kCGInterpolationHigh): self._maxWidth = maxWidth self._maxHeight = maxHeight self._borderWidth = borderWidth self._shadowOffset = shadowOffset self._shadowBlur = shadowBlur # This is the total amount of image # space to reserve for the shadow: self._margin = shadowOffset + shadowBlur # This will be the bitmap graphics context # into which we render the decorated # image: self._gc = None self._newWidth = self._newHeight = 0 self._bgColor = bgColor self._quality = quality def _loadImage(self, pathname): return CGImageImport( CGDataProviderCreateWithFilename( pathname)) def _findInsideSize(self, img, margin): # Find the rescaled size of an img, # so that it will fit within max image # dimensions when padded with the # specified margin. width = img.getWidth() height = img.getHeight() aspect = float(width) / height if aspect > 1.0: insideWidth = (self._maxWidth - margin) insideHeight = (insideWidth / aspect) else: insideHeight = (self._maxHeight - margin) insideWidth = (insideHeight * aspect) return (insideWidth, insideHeight) def _findRescaledSize(self, img): margin = (self._borderWidth + self._margin) (insideWidth, insideHeight) = self._findInsideSize( img, margin) self._newWidth = insideWidth + margin self._newHeight = insideHeight + margin def _getGraphicsContext(self): self._gc = CGBitmapContextCreateWithColor( self._newWidth, self._newHeight, CGColorSpaceCreateDeviceRGB(), self._bgColor) def _drawShadowedBorder(self): shadowedRect = CGRectMake( 0, self._margin, self._newWidth - self._margin, self._newHeight - self._margin) self._gc.addRect(shadowedRect) self._gc.setShadow( CGSizeMake(self._shadowOffset, -self._shadowOffset), self._shadowBlur) self._gc.setRGBFillColor(1, 1, 1, 1) self._gc.fillPath() # Remove the shadow: self._gc.setShadow(CGSizeMake(0, 0), 0) def _drawOutline(self): self._gc.setRGBStrokeColor(0.5, 0.5, 0.5, 0.5) self._gc.setLineWidth(0.5) margin = self._margin outlineRect = CGRectMake( 0, margin + 0.5, self._newWidth - margin - 0.5, self._newHeight - margin - 1) self._gc.addRect(outlineRect) self._gc.strokePath() def _getBorderedRect(self): w = self._newWidth h = self._newHeight margin = self._margin border = self._borderWidth return CGRectMake( border, border + margin, w - margin - 2 * border, h - margin - 2 * border) def _renderSrcImage(self, img): r = self._getBorderedRect() self._gc.setInterpolationQuality( self._quality) self._gc.drawImage(r, img) def _saveAs(self, pathname): extToFormat = { ".png": kCGImageFormatPNG, ".jpg": kCGImageFormatJPEG, ".tif": kCGImageFormatTIFF, } extension = os.path.splitext(pathname)[1] try: imgFormat = extToFormat[extension.lower()] self._gc.writeToFile(pathname, imgFormat) except KeyError: raise ValueError( "Can't save image as %r -- " "unknown format %s" % (pathname, extension)) def decorate(self, srcPathname, destPathname): img = self._loadImage(srcPathname) self._findRescaledSize(img) self._getGraphicsContext() self._drawShadowedBorder() self._drawOutline() self._renderSrcImage(img) self._saveAs(destPathname) def setBGColor(self, newBGColor): self._bgColor = newBGColor def setQuality(self, newQuality): self._quality = newQuality def main(): decorator = ImageDecorator( bgColor=(0, 0, 0, 0)) srcFilename = "image_1.jpg" destFilename = "transparent_image_1.png" decorator.decorate(srcFilename, destFilename) os.system("open %s" % destFilename) if __name__ == "__main__": main()