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()
