View Single Post
Old 04-11-2010, 05:24 AM   #5
Junior Member
hansd began at the beginning.
Posts: 5
Karma: 12
Join Date: Apr 2010
Device: dr1000
Default cover with custom image

Instead of fully replacing the cover using the cover_url, just replace the stock image of the default cover with a given image.

Add a cover_img_url field with the url in the definition of the class, and add the following code (imports and fuctions). There is no need to call any of these functions directly, all is handled via the redefined default_cover function.

The code is based on the code from BasicRecipe itself

import os
from contextlib import nested, closing
from calibre import strftime, __appname__, __version__
import calibre.utils.PythonMagickWand as pw
from ctypes import byref
from calibre import fit_image

    def get_cover_img_url(self):
        return getattr(self, 'cover_img_url', None)

    def _download_cover_img(self):
        # hack to reuse download_cover
        old_cu = None
            old_cu = self.get_cover_ur()
        new_cu = self.get_cover_img_url()
        self.cover_url = new_cu     

        outfile = os.path.join(self.output_dir, 'cover_img.jpg')
        self.prepare_masthead_image(self.cover_path, outfile) 
        self.cover_url = old_cu
        self.cover_img_path = outfile

    def download_cover_img(self):
            self.report_progress(1, _('Downloaded cover to %s') % self.cover_img_path)
            self.log.exception('Failed to download cover img')
            self.cover_img_path = None
    def prepare_cover_image(self, path_to_image, out_path):
        with pw.ImageMagick():
            img = pw.NewMagickWand()
            if img < 0:
                raise RuntimeError('Out of memory')
            if not pw.MagickReadImage(img, path_to_image):
                severity = pw.ExceptionType(0)
                msg = pw.MagickGetException(img, byref(severity))
                raise IOError('Failed to read image from: %s: %s'
                        %(path_to_image, msg))
            if not pw.MagickWriteImage(img, out_path):
                raise RuntimeError('Failed to save image to %s'%out_path)

    def default_cover(self, cover_file):
        Create a generic cover for recipes that have a special cover img
                from PIL import Image, ImageDraw, ImageFont
                Image, ImageDraw, ImageFont
            except ImportError:
                import Image, ImageDraw, ImageFont
            font_path = P('fonts/liberation/LiberationSerif-Bold.ttf')
            title = self.title if isinstance(self.title, unicode) else \
                    self.title.decode(preferred_encoding, 'replace')
            date = strftime(self.timefmt)
            app = '['+__appname__ +' '+__version__+']'

            COVER_WIDTH, COVER_HEIGHT = 590, 750
            img ='RGB', (COVER_WIDTH, COVER_HEIGHT), 'white')
            draw = ImageDraw.Draw(img)
            # Title
            font = ImageFont.truetype(font_path, 44)
            width, height = draw.textsize(title, font=font)
            left = max(int((COVER_WIDTH - width)/2.), 0)
            top = 15
            draw.text((left, top), title, fill=(0,0,0), font=font)
            bottom = top + height
            # Date
            font = ImageFont.truetype(font_path, 32)
            width, height = draw.textsize(date, font=font)
            left = max(int((COVER_WIDTH - width)/2.), 0)
            draw.text((left, bottom+15), date, fill=(0,0,0), font=font)
            # Vanity
            font = ImageFont.truetype(font_path, 28)
            width, height = draw.textsize(app, font=font)
            left = max(int((COVER_WIDTH - width)/2.), 0)
            top = COVER_HEIGHT - height - 15
            draw.text((left, top), app, fill=(0,0,0), font=font)

            # Logo
            logo_file = I('library.png')
            if getattr(self, 'cover_img_path', None) is not None:
                logo_file = self.cover_img_path
            self.report_progress(1, _('using cover img from %s') % logo_file)
            logo =, 'r')
            width, height = logo.size
            left = max(int((COVER_WIDTH - width)/2.), 0)
            top = max(int((COVER_HEIGHT - height)/2.), 0)
            img.paste(logo, (left, top))
            img = img.convert('RGB').convert('P', palette=Image.ADAPTIVE)
            img.convert('RGB').save(cover_file, 'JPEG')
        except Exception, e:
            self.log.exception('Failed to generate default cover ', e)
            return False
        return True

Last edited by Starson17; 02-25-2011 at 09:09 PM. Reason: refactored _download_cover_img
hansd is offline   Reply With Quote