コード例 #1
0
 def export(self, fmt='JPEG'):
     if fmt.lower() == 'gif':
         data = image_to_data(self.img, fmt='PNG', png_compression_level=0)
         from PIL import Image
         i = Image.open(BytesIO(data))
         buf = BytesIO()
         i.save(buf, 'gif')
         return buf.getvalue()
     return image_to_data(self.img, fmt=fmt)
コード例 #2
0
ファイル: legacy.py プロジェクト: j-howell/calibre
 def export(self, fmt='JPEG'):
     if fmt.lower() == 'gif':
         data = image_to_data(self.img, fmt='PNG', png_compression_level=0)
         from PIL import Image
         i = Image.open(BytesIO(data))
         buf = BytesIO()
         i.save(buf, 'gif')
         return buf.getvalue()
     return image_to_data(self.img, fmt=fmt)
コード例 #3
0
ファイル: pdftohtml.py プロジェクト: JimmXinu/calibre
def flip_image(img, flip):
    from calibre.utils.img import flip_image, image_and_format_from_data, image_to_data
    with lopen(img, 'r+b') as f:
        img, fmt = image_and_format_from_data(f.read())
        img = flip_image(img, horizontal='x' in flip, vertical='y' in flip)
        f.seek(0), f.truncate()
        f.write(image_to_data(img, fmt=fmt))
コード例 #4
0
ファイル: images.py プロジェクト: j-howell/calibre
 def resize_image(self, raw, base, max_width, max_height):
     resized, img = resize_to_fit(raw, max_width, max_height)
     if resized:
         base, ext = os.path.splitext(base)
         base = base + '-%dx%d%s' % (max_width, max_height, ext)
         raw = image_to_data(img, fmt=ext[1:])
     return raw, base, resized
コード例 #5
0
ファイル: pdftohtml.py プロジェクト: wh0197m/calibre
def flip_image(img, flip):
    from calibre.utils.img import flip_image, image_and_format_from_data, image_to_data
    with lopen(img, 'r+b') as f:
        img, fmt = image_and_format_from_data(f.read())
        img = flip_image(img, horizontal='x' in flip, vertical='y' in flip)
        f.seek(0), f.truncate()
        f.write(image_to_data(img, fmt=fmt))
コード例 #6
0
def rescale_image(data, scale_news_images, compress_news_images_max_size, compress_news_images_auto_size):
    orig_data = data  # save it in case compression fails
    img = image_from_data(data)
    orig_w, orig_h = img.width(), img.height()
    if scale_news_images is not None:
        wmax, hmax = scale_news_images
        if wmax < orig_w or hmax < orig_h:
            orig_w, orig_h, data = scale_image(img, wmax, hmax, compression_quality=95)
    if compress_news_images_max_size is None:
        if compress_news_images_auto_size is None:  # not compressing
            return data
        maxsizeb = (orig_w * orig_h)/compress_news_images_auto_size
    else:
        maxsizeb = compress_news_images_max_size * 1024

    if len(data) <= maxsizeb:  # no compression required
        return data

    scaled_data = data  # save it in case compression fails
    quality = 90
    while len(data) >= maxsizeb and quality >= 5:
        data = image_to_data(image_from_data(scaled_data), compression_quality=quality)
        quality -= 5

    if len(data) >= len(scaled_data):  # compression failed
        return orig_data if len(orig_data) <= len(scaled_data) else scaled_data

    if len(data) >= len(orig_data):  # no improvement
        return orig_data

    return data
コード例 #7
0
 def resize_image(self, raw, base, max_width, max_height):
     resized, img = resize_to_fit(raw, max_width, max_height)
     if resized:
         base, ext = os.path.splitext(base)
         base = base + '-%dx%d%s' % (max_width, max_height, ext)
         raw = image_to_data(img, fmt=ext[1:])
     return raw, base, resized
コード例 #8
0
 def convert_webp(self, item):
     from calibre.utils.img import image_and_format_from_data, image_to_data
     img, fmt = image_and_format_from_data(item.data)
     if fmt == 'webp' and not img.isNull():
         self.log.info(f'Converting WebP image {item.href} to PNG')
         item.data = image_to_data(img, fmt='PNG')
         item.media_type = 'image/png'
コード例 #9
0
ファイル: test_build.py プロジェクト: NathanaelA/calibre
    def test_qt(self):
        from PyQt5.Qt import QImageReader, QNetworkAccessManager, QFontDatabase
        from calibre.utils.img import image_from_data, image_to_data, test
        # Ensure that images can be read before QApplication is constructed.
        # Note that this requires QCoreApplication.libraryPaths() to return the
        # path to the Qt plugins which it always does in the frozen build,
        # because the QT_PLUGIN_PATH env var is set. On non-frozen builds,
        # it should just work because the hard-coded paths of the Qt
        # installation should work. If they do not, then it is a distro
        # problem.
        fmts = set(map(unicode, QImageReader.supportedImageFormats()))
        testf = {'jpg', 'png', 'svg', 'ico', 'gif'}
        self.assertEqual(testf.intersection(fmts), testf, "Qt doesn't seem to be able to load some of its image plugins. Available plugins: %s" % fmts)
        data = I('blank.png', allow_user_override=False, data=True)
        img = image_from_data(data)
        image_from_data(P('catalog/mastheadImage.gif', allow_user_override=False, data=True))
        for fmt in 'png bmp jpeg'.split():
            d = image_to_data(img, fmt=fmt)
            image_from_data(d)
        # Run the imaging tests
        test()

        from calibre.gui2 import Application
        os.environ.pop('DISPLAY', None)
        app = Application([], headless=islinux)
        self.assertGreaterEqual(len(QFontDatabase().families()), 5, 'The QPA headless plugin is not able to locate enough system fonts via fontconfig')
        na = QNetworkAccessManager()
        self.assertTrue(hasattr(na, 'sslErrors'), 'Qt not compiled with openssl')
        from PyQt5.QtWebKitWidgets import QWebView
        QWebView()
        del QWebView
        del na
        del app
コード例 #10
0
def thumbnail(data,
              width=120,
              height=120,
              bgcolor='#ffffff',
              fmt='jpg',
              preserve_aspect_ratio=True,
              compression_quality=70):
    img = Image()
    img.load(data)
    owidth, oheight = img.size
    if width is None:
        width = owidth
    if height is None:
        height = oheight
    if not preserve_aspect_ratio:
        scaled = owidth > width or oheight > height
        nwidth = width
        nheight = height
    else:
        scaled, nwidth, nheight = fit_image(owidth, oheight, width, height)
    if scaled:
        img.size = (nwidth, nheight)
    canvas = create_canvas(img.size[0], img.size[1], bgcolor)
    canvas.compose(img)
    data = image_to_data(canvas.img, compression_quality=compression_quality)
    return (canvas.size[0], canvas.size[1], data)
コード例 #11
0
def convert_jxr_to_tiff(jxr_data, resource_name):

    if calibre_numeric_version is not None and calibre_numeric_version >= (
            3, 9, 0):

        try:
            from calibre.utils.img import (load_jxr_data, image_to_data)
            img = load_jxr_data(jxr_data)
            tiff_data = image_to_data(img, fmt="TIFF")

            if tiff_data:
                return tiff_data
        except Exception as e:
            log.warning("Conversion of JPEG-XR resource failed: %s" % repr(e))

        log.info("Using fallback JPEG-XR conversion for %s" % resource_name)

    start_time = time.time()

    im = JXRContainer(jxr_data).unpack_image()

    duration = time.time() - start_time
    if duration >= 0.5:
        log.info("JPEG-XR to TIFF conversion took %0.1f sec" % duration)

    outfile = io.BytesIO()
    with disable_debug_log():
        im.save(outfile, "TIFF")
        im.close()

    return outfile.getvalue()
コード例 #12
0
ファイル: text.py プロジェクト: T30rGRB7/calibre-python3
    def insertFromMimeData(self, md):
        files = tuple(self.get_droppable_files(md))
        base = self.highlighter.doc_name or None

        def get_name(name):
            return get_recommended_folders(current_container(),
                                           (name, ))[name] + '/' + name

        def get_href(name):
            return current_container().name_to_href(name, base)

        def insert_text(text):
            c = self.textCursor()
            c.insertText(text)
            self.setTextCursor(c)
            self.ensureCursorVisible()

        def add_file(name, data, mt=None):
            from calibre.gui2.tweak_book.boss import get_boss
            name = current_container().add_file(name,
                                                data,
                                                media_type=mt,
                                                modify_name_if_needed=True)
            get_boss().refresh_file_list()
            return name

        if files:
            for path, mt, is_name in files:
                if is_name:
                    name = path
                else:
                    name = get_name(os.path.basename(path))
                    with lopen(path, 'rb') as f:
                        name = add_file(name, f.read(), mt)
                href = get_href(name)
                if mt.startswith('image/'):
                    self.insert_image(href)
                elif mt in OEB_STYLES:
                    insert_text(
                        '<link href="{}" rel="stylesheet" type="text/css"/>'.
                        format(href))
                elif mt in OEB_DOCS:
                    self.insert_hyperlink(href, name)
            self.ensureCursorVisible()
            return
        if md.hasImage():
            img = md.imageData()
            if img is not None and img.isValid():
                data = image_to_data(img, fmt='PNG')
                name = add_file(get_name('dropped_image.png', data))
                self.insert_image(get_href(name))
                self.ensureCursorVisible()
                return
        if md.hasText():
            return insert_text(md.text())
        if md.hasHtml():
            insert_text(md.html())
            return
コード例 #13
0
def calibre_cover(title, author_string, series_string=None,
        output_format='jpg', title_size=46, author_size=36, logo_path=None):
    title = normalize(title)
    author_string = normalize(author_string)
    series_string = normalize(series_string)
    from calibre.ebooks.covers import calibre_cover2
    from calibre.utils.img import image_to_data
    ans = calibre_cover2(title, author_string or '', series_string or '', logo_path=logo_path, as_qimage=True)
    return image_to_data(ans, fmt=output_format)
コード例 #14
0
def rescale_image(data, maxsizeb=IMAGE_MAX_SIZE, dimen=None):
    '''
    Convert image setting all transparent pixels to white and changing format
    to JPEG. Ensure the resultant image has a byte size less than
    maxsizeb.

    If dimen is not None, generate a thumbnail of
    width=dimen, height=dimen or width, height = dimen (depending on the type
    of dimen)

    Returns the image as a bytestring
    '''
    if dimen is not None:
        if hasattr(dimen, '__len__'):
            width, height = dimen
        else:
            width = height = dimen
        data = scale_image(data,
                           width=width,
                           height=height,
                           compression_quality=90)[-1]
    else:
        # Replace transparent pixels with white pixels and convert to JPEG
        data = save_cover_data_to(data)
    if len(data) <= maxsizeb:
        return data
    orig_data = data  # save it in case compression fails
    quality = 90
    while len(data) > maxsizeb and quality >= 5:
        data = image_to_data(image_from_data(orig_data),
                             compression_quality=quality)
        quality -= 5
    if len(data) <= maxsizeb:
        return data
    orig_data = data

    scale = 0.9
    while len(data) > maxsizeb and scale >= 0.05:
        img = image_from_data(data)
        w, h = img.width(), img.height()
        img = resize_image(img, int(scale * w), int(scale * h))
        data = image_to_data(img, compression_quality=quality)
        scale -= 0.05
    return data
コード例 #15
0
ファイル: text.py プロジェクト: j-howell/calibre
    def insertFromMimeData(self, md):
        files = tuple(self.get_droppable_files(md))
        base = self.highlighter.doc_name or None

        def get_name(name):
            folder = get_recommended_folders(current_container(), (name,))[name] or ''
            if folder:
                folder += '/'
            return folder + name

        def get_href(name):
            return current_container().name_to_href(name, base)

        def insert_text(text):
            c = self.textCursor()
            c.insertText(text)
            self.setTextCursor(c)
            self.ensureCursorVisible()

        def add_file(name, data, mt=None):
            from calibre.gui2.tweak_book.boss import get_boss
            name = current_container().add_file(name, data, media_type=mt, modify_name_if_needed=True)
            get_boss().refresh_file_list()
            return name

        if files:
            for path, mt, is_name in files:
                if is_name:
                    name = path
                else:
                    name = get_name(os.path.basename(path))
                    with lopen(path, 'rb') as f:
                        name = add_file(name, f.read(), mt)
                href = get_href(name)
                if mt.startswith('image/'):
                    self.insert_image(href)
                elif mt in OEB_STYLES:
                    insert_text('<link href="{}" rel="stylesheet" type="text/css"/>'.format(href))
                elif mt in OEB_DOCS:
                    self.insert_hyperlink(href, name)
            self.ensureCursorVisible()
            return
        if md.hasImage():
            img = md.imageData()
            if img is not None and not img.isNull():
                data = image_to_data(img, fmt='PNG')
                name = add_file(get_name('dropped_image.png'), data)
                self.insert_image(get_href(name))
                self.ensureCursorVisible()
                return
        if md.hasText():
            return insert_text(md.text())
        if md.hasHtml():
            insert_text(md.html())
            return
コード例 #16
0
ファイル: test_build.py プロジェクト: timpalpant/calibre
def test_image_formats():
    # Must be run before QApplication is constructed
    # Test that the image formats are available without a QApplication being
    # constructed
    from calibre.utils.img import image_from_data, image_to_data
    data = I('blank.png', allow_user_override=False, data=True)
    img = image_from_data(data)
    image_from_data(P('catalog/mastheadImage.gif', allow_user_override=False, data=True))
    for fmt in 'png bmp jpeg'.split():
        d = image_to_data(img, fmt=fmt)
        image_from_data(d)
コード例 #17
0
ファイル: test_build.py プロジェクト: elonchen/calibre
    def test_qt(self):
        from PyQt5.QtGui import QImageReader, QFontDatabase
        from PyQt5.QtNetwork import QNetworkAccessManager
        from calibre.utils.img import image_from_data, image_to_data, test
        # Ensure that images can be read before QApplication is constructed.
        # Note that this requires QCoreApplication.libraryPaths() to return the
        # path to the Qt plugins which it always does in the frozen build,
        # because the QT_PLUGIN_PATH env var is set. On non-frozen builds,
        # it should just work because the hard-coded paths of the Qt
        # installation should work. If they do not, then it is a distro
        # problem.
        fmts = set(
            map(lambda x: x.data().decode('utf-8'),
                QImageReader.supportedImageFormats()))  # no2to3
        testf = {'jpg', 'png', 'svg', 'ico', 'gif'}
        self.assertEqual(
            testf.intersection(fmts), testf,
            "Qt doesn't seem to be able to load some of its image plugins. Available plugins: %s"
            % fmts)
        data = P('images/blank.png', allow_user_override=False, data=True)
        img = image_from_data(data)
        image_from_data(
            P('catalog/mastheadImage.gif',
              allow_user_override=False,
              data=True))
        for fmt in 'png bmp jpeg'.split():
            d = image_to_data(img, fmt=fmt)
            image_from_data(d)
        # Run the imaging tests
        test()

        from calibre.gui2 import Application
        os.environ.pop('DISPLAY', None)
        has_headless = isosx or islinux
        app = Application([], headless=has_headless)
        self.assertGreaterEqual(
            len(QFontDatabase().families()), 5,
            'The QPA headless plugin is not able to locate enough system fonts via fontconfig'
        )
        if has_headless:
            from calibre.ebooks.covers import create_cover
            create_cover('xxx', ['yyy'])
        na = QNetworkAccessManager()
        self.assertTrue(hasattr(na, 'sslErrors'),
                        'Qt not compiled with openssl')
        from PyQt5.QtWebKitWidgets import QWebView
        if iswindows:
            from PyQt5.Qt import QtWin
            QtWin
        QWebView()
        del QWebView
        del na
        del app
コード例 #18
0
ファイル: book_details.py プロジェクト: buoyantair/calibre
 def manual_trim_cover(self):
     book_id = self.data.get('id')
     if not book_id:
         return
     from calibre.gui2.dialogs.trim_image import TrimImage
     from calibre.utils.img import image_to_data
     cdata = image_to_data(image_from_x(self.pixmap), fmt='PNG', png_compression_level=1)
     d = TrimImage(cdata, parent=self)
     if d.exec() == QDialog.DialogCode.Accepted and d.image_data is not None:
         self.last_trim_id = book_id
         self.last_trim_pixmap = self.pixmap
         self.update_cover(cdata=d.image_data)
コード例 #19
0
ファイル: utils.py プロジェクト: j-howell/calibre
def rescale_image(data, maxsizeb=IMAGE_MAX_SIZE, dimen=None):
    '''
    Convert image setting all transparent pixels to white and changing format
    to JPEG. Ensure the resultant image has a byte size less than
    maxsizeb.

    If dimen is not None, generate a thumbnail of
    width=dimen, height=dimen or width, height = dimen (depending on the type
    of dimen)

    Returns the image as a bytestring
    '''
    if dimen is not None:
        if hasattr(dimen, '__len__'):
            width, height = dimen
        else:
            width = height = dimen
        data = scale_image(data, width=width, height=height, compression_quality=90)[-1]
    else:
        # Replace transparent pixels with white pixels and convert to JPEG
        data = save_cover_data_to(data)
    if len(data) <= maxsizeb:
        return data
    orig_data = data  # save it in case compression fails
    quality = 90
    while len(data) > maxsizeb and quality >= 5:
        data = image_to_data(image_from_data(orig_data), compression_quality=quality)
        quality -= 5
    if len(data) <= maxsizeb:
        return data
    orig_data = data

    scale = 0.9
    while len(data) > maxsizeb and scale >= 0.05:
        img = image_from_data(data)
        w, h = img.width(), img.height()
        img = resize_image(img, int(scale*w), int(scale*h))
        data = image_to_data(img, compression_quality=quality)
        scale -= 0.05
    return data
コード例 #20
0
ファイル: test_build.py プロジェクト: vrosnet/calibre
def test_image_formats():
    # Must be run before QApplication is constructed
    # Test that the image formats are available without a QApplication being
    # constructed
    from calibre.utils.img import image_from_data, image_to_data, test
    data = I('blank.png', allow_user_override=False, data=True)
    img = image_from_data(data)
    image_from_data(
        P('catalog/mastheadImage.gif', allow_user_override=False, data=True))
    for fmt in 'png bmp jpeg'.split():
        d = image_to_data(img, fmt=fmt)
        image_from_data(d)
    # Run the imaging tests
    test()
コード例 #21
0
def add_borders_to_image(img_data,
                         left=0,
                         top=0,
                         right=0,
                         bottom=0,
                         border_color='#ffffff',
                         fmt='jpg'):
    img = abti(img_data,
               left=left,
               top=top,
               right=right,
               bottom=bottom,
               border_color=border_color)
    return image_to_data(img, fmt=fmt)
コード例 #22
0
ファイル: canvas.py プロジェクト: yandong2023/calibre
 def get_image_data(self, quality=90):
     if not self.is_modified:
         return self.original_image_data
     fmt = self.original_image_format or 'JPEG'
     if fmt.lower() not in set(map(lambda x:bytes(x).decode('ascii'), QImageWriter.supportedImageFormats())):
         if fmt.lower() == 'gif':
             data = image_to_data(self.current_image, fmt='PNG', png_compression_level=0)
             from PIL import Image
             i = Image.open(BytesIO(data))
             buf = BytesIO()
             i.save(buf, 'gif')
             return buf.getvalue()
         else:
             raise ValueError('Cannot save %s format images' % fmt)
     return pixmap_to_data(self.current_image, format=fmt, quality=90)
コード例 #23
0
ファイル: covers.py プロジェクト: Coi-l/calibre
def process_result(log, result):
    plugin, data = result
    try:
        if getattr(plugin, 'auto_trim_covers', False):
            img = image_from_data(data)
            nimg = remove_borders_from_image(img)
            if nimg is not img:
                data = image_to_data(nimg)
        fmt, width, height = identify(data)
        if width < 0 or height < 0:
            raise ValueError('Could not read cover image dimensions')
        if width < 50 or height < 50:
            raise ValueError('Image too small')
        data = save_cover_data_to(data)
    except Exception:
        log.exception('Invalid cover from', plugin.name)
        return None
    return (plugin, width, height, fmt, data)
コード例 #24
0
ファイル: covers.py プロジェクト: zyhong/calibre
def process_result(log, result):
    plugin, data = result
    try:
        if getattr(plugin, 'auto_trim_covers', False):
            img = image_from_data(data)
            nimg = remove_borders_from_image(img)
            if nimg is not img:
                data = image_to_data(nimg)
        fmt, width, height = identify(data)
        if width < 0 or height < 0:
            raise ValueError('Could not read cover image dimensions')
        if width < 50 or height < 50:
            raise ValueError('Image too small')
        data = save_cover_data_to(data)
    except Exception:
        log.exception('Invalid cover from', plugin.name)
        return None
    return (plugin, width, height, fmt, data)
コード例 #25
0
ファイル: draw.py プロジェクト: Coi-l/calibre
def thumbnail(data, width=120, height=120, bgcolor='#ffffff', fmt='jpg',
              preserve_aspect_ratio=True, compression_quality=70):
    img = Image()
    img.load(data)
    owidth, oheight = img.size
    if width is None:
        width = owidth
    if height is None:
        height = oheight
    if not preserve_aspect_ratio:
        scaled = owidth > width or oheight > height
        nwidth = width
        nheight = height
    else:
        scaled, nwidth, nheight = fit_image(owidth, oheight, width, height)
    if scaled:
        img.size = (nwidth, nheight)
    canvas = create_canvas(img.size[0], img.size[1], bgcolor)
    canvas.compose(img)
    data = image_to_data(canvas.img, compression_quality=compression_quality)
    return (canvas.size[0], canvas.size[1], data)
コード例 #26
0
 def HandleImage(self, imageData, imagePath):
     from calibre.utils.img import image_from_data, resize_image, image_to_data
     img = image_from_data(imageData)
     x, y = img.width(), img.height()
     if self.opts:
         if self.opts.snb_full_screen:
             SCREEN_X, SCREEN_Y = self.opts.output_profile.screen_size
         else:
             SCREEN_X, SCREEN_Y = self.opts.output_profile.comic_screen_size
     else:
         SCREEN_X = 540
         SCREEN_Y = 700
     # Handle big image only
     if x > SCREEN_X or y > SCREEN_Y:
         xScale = float(x) / SCREEN_X
         yScale = float(y) / SCREEN_Y
         scale = max(xScale, yScale)
         # TODO : intelligent image rotation
         #     img = img.rotate(90)
         #     x,y = y,x
         img = resize_image(img, x // scale, y // scale)
     with lopen(imagePath, 'wb') as f:
         f.write(image_to_data(img, fmt=imagePath.rpartition('.')[-1]))
コード例 #27
0
ファイル: snb_output.py プロジェクト: artbycrunk/calibre
 def HandleImage(self, imageData, imagePath):
     from calibre.utils.img import image_from_data, resize_image, image_to_data
     img = image_from_data(imageData)
     x, y = img.width(), img.height()
     if self.opts:
         if self.opts.snb_full_screen:
             SCREEN_X, SCREEN_Y = self.opts.output_profile.screen_size
         else:
             SCREEN_X, SCREEN_Y = self.opts.output_profile.comic_screen_size
     else:
         SCREEN_X = 540
         SCREEN_Y = 700
     # Handle big image only
     if x > SCREEN_X or y > SCREEN_Y:
         xScale = float(x) / SCREEN_X
         yScale = float(y) / SCREEN_Y
         scale = max(xScale, yScale)
         # TODO : intelligent image rotation
         #     img = img.rotate(90)
         #     x,y = y,x
         img = resize_image(img, x / scale, y / scale)
     with lopen(imagePath, 'wb') as f:
         f.write(image_to_data(img, fmt=imagePath.rpartition('.')[-1]))
コード例 #28
0
ファイル: simple.py プロジェクト: Coi-l/calibre
 def process_images(self, soup, baseurl):
     diskpath = unicode_path(os.path.join(self.current_dir, 'images'))
     if not os.path.exists(diskpath):
         os.mkdir(diskpath)
     c = 0
     for tag in soup.findAll(lambda tag: tag.name.lower()=='img' and tag.has_key('src')):
         iurl = tag['src']
         if iurl.startswith('data:image/'):
             try:
                 data = b64decode(iurl.partition(',')[-1])
             except:
                 self.log.exception('Failed to decode embedded image')
                 continue
         else:
             if callable(self.image_url_processor):
                 iurl = self.image_url_processor(baseurl, iurl)
             if not urlparse.urlsplit(iurl).scheme:
                 iurl = urlparse.urljoin(baseurl, iurl, False)
             with self.imagemap_lock:
                 if self.imagemap.has_key(iurl):
                     tag['src'] = self.imagemap[iurl]
                     continue
             try:
                 data = self.fetch_url(iurl)
                 if data == 'GIF89a\x01':
                     # Skip empty GIF files as PIL errors on them anyway
                     continue
             except Exception:
                 self.log.exception('Could not fetch image ', iurl)
                 continue
         c += 1
         fname = ascii_filename('img'+str(c))
         if isinstance(fname, unicode):
             fname = fname.encode('ascii', 'replace')
         itype = what(None, data)
         if itype is None and b'<svg' in data[:1024]:
             # SVG image
             imgpath = os.path.join(diskpath, fname+'.svg')
             with self.imagemap_lock:
                 self.imagemap[iurl] = imgpath
             with open(imgpath, 'wb') as x:
                 x.write(data)
             tag['src'] = imgpath
         else:
             try:
                 # Ensure image is valid
                 img = image_from_data(data)
                 if itype not in {'png', 'jpg', 'jpeg'}:
                     itype = 'png' if itype == 'gif' else 'jpeg'
                     data = image_to_data(img, fmt=itype)
                 if self.compress_news_images and itype in {'jpg','jpeg'}:
                     try:
                         data = self.rescale_image(data)
                     except Exception:
                         self.log.exception('failed to compress image '+iurl)
                 # Moon+ apparently cannot handle .jpeg files
                 if itype == 'jpeg':
                     itype = 'jpg'
                 imgpath = os.path.join(diskpath, fname+'.'+itype)
                 with self.imagemap_lock:
                     self.imagemap[iurl] = imgpath
                 with open(imgpath, 'wb') as x:
                     x.write(data)
                 tag['src'] = imgpath
             except Exception:
                 traceback.print_exc()
                 continue
コード例 #29
0
ファイル: draw.py プロジェクト: Coi-l/calibre
def add_borders_to_image(img_data, left=0, top=0, right=0, bottom=0,
        border_color='#ffffff', fmt='jpg'):
    img = abti(img_data, left=left, top=top, right=right, bottom=bottom, border_color=border_color)
    return image_to_data(img, fmt=fmt)
コード例 #30
0
    def process_pages(self):
        from calibre.utils.img import (image_to_data, rotate_image,
                                       remove_borders_from_image,
                                       normalize_image, add_borders_to_image,
                                       resize_image, gaussian_sharpen_image,
                                       grayscale_image, despeckle_image,
                                       quantize_image)
        for i, img in enumerate(self.pages):
            if self.rotate:
                img = rotate_image(img, -90)

            if not self.opts.disable_trim:
                img = remove_borders_from_image(img)

            # Do the Photoshop "Auto Levels" equivalent
            if not self.opts.dont_normalize:
                img = normalize_image(img)
            sizex, sizey = img.width(), img.height()

            SCRWIDTH, SCRHEIGHT = self.opts.output_profile.comic_screen_size

            try:
                if self.opts.comic_image_size:
                    SCRWIDTH, SCRHEIGHT = map(int, [
                        x.strip()
                        for x in self.opts.comic_image_size.split('x')
                    ])
            except:
                pass  # Ignore

            if self.opts.keep_aspect_ratio:
                # Preserve the aspect ratio by adding border
                aspect = float(sizex) / float(sizey)
                if aspect <= (float(SCRWIDTH) / float(SCRHEIGHT)):
                    newsizey = SCRHEIGHT
                    newsizex = int(newsizey * aspect)
                    deltax = (SCRWIDTH - newsizex) // 2
                    deltay = 0
                else:
                    newsizex = SCRWIDTH
                    newsizey = int(newsizex // aspect)
                    deltax = 0
                    deltay = (SCRHEIGHT - newsizey) // 2
                if newsizex < MAX_SCREEN_SIZE and newsizey < MAX_SCREEN_SIZE:
                    # Too large and resizing fails, so better
                    # to leave it as original size
                    img = resize_image(img, newsizex, newsizey)
                    img = add_borders_to_image(img,
                                               left=deltax,
                                               right=deltax,
                                               top=deltay,
                                               bottom=deltay)
            elif self.opts.wide:
                # Keep aspect and Use device height as scaled image width so landscape mode is clean
                aspect = float(sizex) / float(sizey)
                screen_aspect = float(SCRWIDTH) / float(SCRHEIGHT)
                # Get dimensions of the landscape mode screen
                # Add 25px back to height for the battery bar.
                wscreenx = SCRHEIGHT + 25
                wscreeny = int(wscreenx // screen_aspect)
                if aspect <= screen_aspect:
                    newsizey = wscreeny
                    newsizex = int(newsizey * aspect)
                    deltax = (wscreenx - newsizex) // 2
                    deltay = 0
                else:
                    newsizex = wscreenx
                    newsizey = int(newsizex // aspect)
                    deltax = 0
                    deltay = (wscreeny - newsizey) // 2
                if newsizex < MAX_SCREEN_SIZE and newsizey < MAX_SCREEN_SIZE:
                    # Too large and resizing fails, so better
                    # to leave it as original size
                    img = resize_image(img, newsizex, newsizey)
                    img = add_borders_to_image(img,
                                               left=deltax,
                                               right=deltax,
                                               top=deltay,
                                               bottom=deltay)
            else:
                if SCRWIDTH < MAX_SCREEN_SIZE and SCRHEIGHT < MAX_SCREEN_SIZE:
                    img = resize_image(img, SCRWIDTH, SCRHEIGHT)

            if not self.opts.dont_sharpen:
                img = gaussian_sharpen_image(img, 0.0, 1.0)

            if not self.opts.dont_grayscale:
                img = grayscale_image(img)

            if self.opts.despeckle:
                img = despeckle_image(img)

            if self.opts.output_format.lower() == 'png' and self.opts.colors:
                img = quantize_image(img,
                                     max_colors=min(256, self.opts.colors))
            dest = '%d_%d.%s' % (self.num, i, self.opts.output_format)
            dest = os.path.join(self.dest, dest)
            with lopen(dest, 'wb') as f:
                f.write(image_to_data(img, fmt=self.opts.output_format))
            self.append(dest)
コード例 #31
0
ファイル: utils.py プロジェクト: MarioJC/calibre
def prepare_masthead_image(path_to_image, out_path, mi_width, mi_height):
    with lopen(path_to_image, 'rb') as f:
        img = image_from_data(f.read())
    img = blend_on_canvas(img, mi_width, mi_height)
    with lopen(out_path, 'wb') as f:
        f.write(image_to_data(img))
コード例 #32
0
 def process_images(self, soup, baseurl):
     diskpath = unicode_path(os.path.join(self.current_dir, 'images'))
     if not os.path.exists(diskpath):
         os.mkdir(diskpath)
     c = 0
     for tag in soup.findAll(lambda tag: tag.name.lower() == 'img' and tag.
                             has_key('src')):  # noqa
         iurl = tag['src']
         if iurl.startswith('data:image/'):
             try:
                 data = b64decode(iurl.partition(',')[-1])
             except:
                 self.log.exception('Failed to decode embedded image')
                 continue
         else:
             if callable(self.image_url_processor):
                 iurl = self.image_url_processor(baseurl, iurl)
             if not urlsplit(iurl).scheme:
                 iurl = urljoin(baseurl, iurl, False)
             with self.imagemap_lock:
                 if self.imagemap.has_key(iurl):  # noqa
                     tag['src'] = self.imagemap[iurl]
                     continue
             try:
                 data = self.fetch_url(iurl)
                 if data == 'GIF89a\x01':
                     # Skip empty GIF files as PIL errors on them anyway
                     continue
             except Exception:
                 self.log.exception('Could not fetch image ', iurl)
                 continue
         c += 1
         fname = ascii_filename('img' + str(c))
         if isinstance(fname, unicode_type):
             fname = fname.encode('ascii', 'replace')
         data = self.preprocess_image_ext(
             data, iurl) if self.preprocess_image_ext is not None else data
         if data is None:
             continue
         itype = what(None, data)
         if itype == 'svg' or (itype is None and b'<svg' in data[:1024]):
             # SVG image
             imgpath = os.path.join(diskpath, fname + '.svg')
             with self.imagemap_lock:
                 self.imagemap[iurl] = imgpath
             with open(imgpath, 'wb') as x:
                 x.write(data)
             tag['src'] = imgpath
         else:
             try:
                 # Ensure image is valid
                 img = image_from_data(data)
                 if itype not in {'png', 'jpg', 'jpeg'}:
                     itype = 'png' if itype == 'gif' else 'jpeg'
                     data = image_to_data(img, fmt=itype)
                 if self.compress_news_images and itype in {'jpg', 'jpeg'}:
                     try:
                         data = self.rescale_image(data)
                     except Exception:
                         self.log.exception('failed to compress image ' +
                                            iurl)
                 # Moon+ apparently cannot handle .jpeg files
                 if itype == 'jpeg':
                     itype = 'jpg'
                 imgpath = os.path.join(diskpath, fname + '.' + itype)
                 with self.imagemap_lock:
                     self.imagemap[iurl] = imgpath
                 with open(imgpath, 'wb') as x:
                     x.write(data)
                 tag['src'] = imgpath
             except Exception:
                 traceback.print_exc()
                 continue
コード例 #33
0
def prepare_masthead_image(path_to_image, out_path, mi_width, mi_height):
    with lopen(path_to_image, 'rb') as f:
        img = image_from_data(f.read())
    img = blend_on_canvas(img, mi_width, mi_height)
    with lopen(out_path, 'wb') as f:
        f.write(image_to_data(img))
コード例 #34
0
ファイル: input.py プロジェクト: Coi-l/calibre
    def process_pages(self):
        from calibre.utils.img import (
            image_to_data, rotate_image, remove_borders_from_image, normalize_image,
            add_borders_to_image, resize_image, gaussian_sharpen_image, grayscale_image,
            despeckle_image, quantize_image
        )
        for i, img in enumerate(self.pages):
            if self.rotate:
                img = rotate_image(img, -90)

            if not self.opts.disable_trim:
                img = remove_borders_from_image(img)

            # Do the Photoshop "Auto Levels" equivalent
            if not self.opts.dont_normalize:
                img = normalize_image(img)
            sizex, sizey = img.width(), img.height()

            SCRWIDTH, SCRHEIGHT = self.opts.output_profile.comic_screen_size

            try:
                if self.opts.comic_image_size:
                    SCRWIDTH, SCRHEIGHT = map(int, [x.strip() for x in
                        self.opts.comic_image_size.split('x')])
            except:
                pass  # Ignore

            if self.opts.keep_aspect_ratio:
                # Preserve the aspect ratio by adding border
                aspect = float(sizex) / float(sizey)
                if aspect <= (float(SCRWIDTH) / float(SCRHEIGHT)):
                    newsizey = SCRHEIGHT
                    newsizex = int(newsizey * aspect)
                    deltax = (SCRWIDTH - newsizex) / 2
                    deltay = 0
                else:
                    newsizex = SCRWIDTH
                    newsizey = int(newsizex / aspect)
                    deltax = 0
                    deltay = (SCRHEIGHT - newsizey) / 2
                if newsizex < MAX_SCREEN_SIZE and newsizey < MAX_SCREEN_SIZE:
                    # Too large and resizing fails, so better
                    # to leave it as original size
                    img = resize_image(img, newsizex, newsizey)
                    img = add_borders_to_image(img, left=deltax, right=deltax, top=deltay, bottom=deltay)
            elif self.opts.wide:
                # Keep aspect and Use device height as scaled image width so landscape mode is clean
                aspect = float(sizex) / float(sizey)
                screen_aspect = float(SCRWIDTH) / float(SCRHEIGHT)
                # Get dimensions of the landscape mode screen
                # Add 25px back to height for the battery bar.
                wscreenx = SCRHEIGHT + 25
                wscreeny = int(wscreenx / screen_aspect)
                if aspect <= screen_aspect:
                    newsizey = wscreeny
                    newsizex = int(newsizey * aspect)
                    deltax = (wscreenx - newsizex) / 2
                    deltay = 0
                else:
                    newsizex = wscreenx
                    newsizey = int(newsizex / aspect)
                    deltax = 0
                    deltay = (wscreeny - newsizey) / 2
                if newsizex < MAX_SCREEN_SIZE and newsizey < MAX_SCREEN_SIZE:
                    # Too large and resizing fails, so better
                    # to leave it as original size
                    img = resize_image(img, newsizex, newsizey)
                    img = add_borders_to_image(img, left=deltax, right=deltax, top=deltay, bottom=deltay)
            else:
                if SCRWIDTH < MAX_SCREEN_SIZE and SCRHEIGHT < MAX_SCREEN_SIZE:
                    img = resize_image(img, SCRWIDTH, SCRHEIGHT)

            if not self.opts.dont_sharpen:
                img = gaussian_sharpen_image(img, 0.0, 1.0)

            if not self.opts.dont_grayscale:
                img = grayscale_image(img)

            if self.opts.despeckle:
                img = despeckle_image(img)

            if self.opts.output_format.lower() == 'png' and self.opts.colors:
                img = quantize_image(img, max_colors=min(256, self.opts.colors))
            dest = '%d_%d.%s'%(self.num, i, self.opts.output_format)
            dest = os.path.join(self.dest, dest)
            with lopen(dest, 'wb') as f:
                f.write(image_to_data(img, fmt=self.opts.output_format))
            self.append(dest)
コード例 #35
0
    def test_qt(self):
        from PyQt5.QtCore import QTimer
        from PyQt5.QtWidgets import QApplication
        from PyQt5.QtWebEngineWidgets import QWebEnginePage
        from PyQt5.QtGui import QImageReader, QFontDatabase
        from PyQt5.QtNetwork import QNetworkAccessManager
        from calibre.utils.img import image_from_data, image_to_data, test
        # Ensure that images can be read before QApplication is constructed.
        # Note that this requires QCoreApplication.libraryPaths() to return the
        # path to the Qt plugins which it always does in the frozen build,
        # because Qt is patched to know the layout of the calibre application
        # package. On non-frozen builds, it should just work because the
        # hard-coded paths of the Qt installation should work. If they do not,
        # then it is a distro problem.
        fmts = set(map(lambda x: x.data().decode('utf-8'), QImageReader.supportedImageFormats()))  # no2to3
        testf = {'jpg', 'png', 'svg', 'ico', 'gif'}
        self.assertEqual(testf.intersection(fmts), testf, "Qt doesn't seem to be able to load some of its image plugins. Available plugins: %s" % fmts)
        data = P('images/blank.png', allow_user_override=False, data=True)
        img = image_from_data(data)
        image_from_data(P('catalog/mastheadImage.gif', allow_user_override=False, data=True))
        for fmt in 'png bmp jpeg'.split():
            d = image_to_data(img, fmt=fmt)
            image_from_data(d)
        # Run the imaging tests
        test()

        from calibre.gui2 import ensure_app, destroy_app
        display_env_var = os.environ.pop('DISPLAY', None)
        try:
            ensure_app()
            self.assertGreaterEqual(len(QFontDatabase().families()), 5, 'The QPA headless plugin is not able to locate enough system fonts via fontconfig')
            from calibre.ebooks.covers import create_cover
            create_cover('xxx', ['yyy'])
            na = QNetworkAccessManager()
            self.assertTrue(hasattr(na, 'sslErrors'), 'Qt not compiled with openssl')
            if iswindows:
                from PyQt5.Qt import QtWin
                QtWin
            p = QWebEnginePage()

            def callback(result):
                callback.result = result
                if hasattr(print_callback, 'result'):
                    QApplication.instance().quit()

            def print_callback(result):
                print_callback.result = result
                if hasattr(callback, 'result'):
                    QApplication.instance().quit()

            p.runJavaScript('1 + 1', callback)
            p.printToPdf(print_callback)
            QTimer.singleShot(5000, lambda: QApplication.instance().quit())
            QApplication.instance().exec_()
            test_flaky = ismacos and not is_ci
            if not test_flaky:
                self.assertEqual(callback.result, 2, 'Simple JS computation failed')
                self.assertIn(b'Skia/PDF', bytes(print_callback.result), 'Print to PDF failed')
            del p
            del na
            destroy_app()
            del QWebEnginePage
        finally:
            if display_env_var is not None:
                os.environ['DISPLAY'] = display_env_var
コード例 #36
0
 def process_images(self, soup, baseurl):
     diskpath = unicode_path(os.path.join(self.current_dir, 'images'))
     if not os.path.exists(diskpath):
         os.mkdir(diskpath)
     c = 0
     for tag in soup.findAll('img', src=True):
         iurl = tag['src']
         if iurl.startswith('data:'):
             try:
                 data = urlopen(iurl).read()
             except Exception:
                 self.log.exception('Failed to decode embedded image')
                 continue
         else:
             if callable(self.image_url_processor):
                 iurl = self.image_url_processor(baseurl, iurl)
             if not urlsplit(iurl).scheme:
                 iurl = urljoin(baseurl, iurl, False)
             found_in_cache = False
             with self.imagemap_lock:
                 if iurl in self.imagemap:
                     tag['src'] = self.imagemap[iurl]
                     found_in_cache = True
             if found_in_cache:
                 continue
             try:
                 data = self.fetch_url(iurl)
                 if data == b'GIF89a\x01':
                     # Skip empty GIF files as PIL errors on them anyway
                     continue
             except Exception:
                 self.log.exception('Could not fetch image ', iurl)
                 continue
         c += 1
         fname = ascii_filename('img' + str(c))
         data = self.preprocess_image_ext(
             data, iurl) if self.preprocess_image_ext is not None else data
         if data is None:
             continue
         itype = what(None, data)
         if itype == 'svg' or (itype is None and b'<svg' in data[:1024]):
             # SVG image
             imgpath = os.path.join(diskpath, fname + '.svg')
             with self.imagemap_lock:
                 self.imagemap[iurl] = imgpath
             with open(imgpath, 'wb') as x:
                 x.write(data)
             tag['src'] = imgpath
         else:
             from calibre.utils.img import image_from_data, image_to_data
             try:
                 # Ensure image is valid
                 img = image_from_data(data)
                 if itype not in {'png', 'jpg', 'jpeg'}:
                     itype = 'png' if itype == 'gif' else 'jpeg'
                     data = image_to_data(img, fmt=itype)
                 if self.compress_news_images and itype in {'jpg', 'jpeg'}:
                     try:
                         data = self.rescale_image(data)
                     except Exception:
                         self.log.exception('failed to compress image ' +
                                            iurl)
                 # Moon+ apparently cannot handle .jpeg files
                 if itype == 'jpeg':
                     itype = 'jpg'
                 imgpath = os.path.join(diskpath, fname + '.' + itype)
                 with self.imagemap_lock:
                     self.imagemap[iurl] = imgpath
                 with open(imgpath, 'wb') as x:
                     x.write(data)
                 tag['src'] = imgpath
             except Exception:
                 traceback.print_exc()
                 continue
コード例 #37
0
ファイル: metadata_bulk.py プロジェクト: timpalpant/calibre
    def do_all(self):
        cache = self.db.new_api
        args = self.args

        # Title and authors
        if args.do_swap_ta:
            title_map = cache.all_field_for('title', self.ids)
            authors_map = cache.all_field_for('authors', self.ids)
            def new_title(authors):
                ans = authors_to_string(authors)
                return titlecase(ans) if args.do_title_case else ans
            new_title_map = {bid:new_title(authors) for bid, authors in authors_map.iteritems()}
            new_authors_map = {bid:string_to_authors(title) for bid, title in title_map.iteritems()}
            cache.set_field('authors', new_authors_map)
            cache.set_field('title', new_title_map)

        if args.do_title_case and not args.do_swap_ta:
            title_map = cache.all_field_for('title', self.ids)
            cache.set_field('title', {bid:titlecase(title) for bid, title in title_map.iteritems()})

        if args.do_title_sort:
            lang_map = cache.all_field_for('languages', self.ids)
            title_map = cache.all_field_for('title', self.ids)
            def get_sort(book_id):
                if args.languages:
                    lang = args.languages[0]
                else:
                    try:
                        lang = lang_map[book_id][0]
                    except (KeyError, IndexError, TypeError, AttributeError):
                        lang = 'eng'
                return title_sort(title_map[book_id], lang=lang)
            cache.set_field('sort', {bid:get_sort(bid) for bid in self.ids})

        if args.au:
            authors = string_to_authors(args.au)
            cache.set_field('authors', {bid:authors for bid in self.ids})

        if args.do_auto_author:
            aus_map = cache.author_sort_strings_for_books(self.ids)
            cache.set_field('author_sort', {book_id:' & '.join(aus_map[book_id]) for book_id in aus_map})

        if args.aus and args.do_aus:
            cache.set_field('author_sort', {bid:args.aus for bid in self.ids})

        # Covers
        if args.cover_action == 'remove':
            cache.set_cover({bid:None for bid in self.ids})
        elif args.cover_action == 'generate':
            from calibre.ebooks.covers import generate_cover
            for book_id in self.ids:
                mi = self.db.get_metadata(book_id, index_is_id=True)
                cdata = generate_cover(mi, prefs=args.generate_cover_settings)
                cache.set_cover({book_id:cdata})
        elif args.cover_action == 'fromfmt':
            for book_id in self.ids:
                fmts = cache.formats(book_id, verify_formats=False)
                if fmts:
                    covers = []
                    for fmt in fmts:
                        fmtf = cache.format(book_id, fmt, as_file=True)
                        if fmtf is None:
                            continue
                        cdata, area = get_cover_data(fmtf, fmt)
                        if cdata:
                            covers.append((cdata, area))
                    covers.sort(key=lambda x: x[1])
                    if covers:
                        cache.set_cover({book_id:covers[-1][0]})
        elif args.cover_action == 'trim':
            from calibre.utils.img import remove_borders, image_to_data, image_from_data
            for book_id in self.ids:
                cdata = cache.cover(book_id)
                if cdata:
                    img = image_from_data(cdata)
                    nimg = remove_borders(img)
                    if nimg is not img:
                        cdata = image_to_data(nimg)
                        cache.set_cover({book_id:cdata})
        elif args.cover_action == 'clone':
            cdata = None
            for book_id in self.ids:
                cdata = cache.cover(book_id)
                if cdata:
                    break
            if cdata:
                cache.set_cover({bid:cdata for bid in self.ids if bid != book_id})

        # Formats
        if args.do_remove_format:
            cache.remove_formats({bid:(args.remove_format,) for bid in self.ids})

        if args.restore_original:
            for book_id in self.ids:
                formats = cache.formats(book_id)
                originals = tuple(x.upper() for x in formats if x.upper().startswith('ORIGINAL_'))
                for ofmt in originals:
                    cache.restore_original_format(book_id, ofmt)

        # Various fields
        if args.rating != -1:
            cache.set_field('rating', {bid:args.rating*2 for bid in self.ids})

        if args.clear_pub:
            cache.set_field('publisher', {bid:'' for bid in self.ids})

        if args.pub:
            cache.set_field('publisher', {bid:args.pub for bid in self.ids})

        if args.clear_series:
            cache.set_field('series', {bid:'' for bid in self.ids})

        if args.pubdate is not None:
            cache.set_field('pubdate', {bid:args.pubdate for bid in self.ids})

        if args.adddate is not None:
            cache.set_field('timestamp', {bid:args.adddate for bid in self.ids})

        if args.do_series:
            sval = args.series_start_value if args.do_series_restart else cache.get_next_series_num_for(args.series, current_indices=True)
            cache.set_field('series', {bid:args.series for bid in self.ids})
            if not args.series:
                cache.set_field('series_index', {bid:1.0 for bid in self.ids})
            else:
                def next_series_num(bid, i):
                    if args.do_series_restart:
                        return sval + (i * args.series_increment)
                    next_num = _get_next_series_num_for_list(sorted(sval.itervalues()), unwrap=False)
                    sval[bid] = next_num
                    return next_num

                smap = {bid:next_series_num(bid, i) for i, bid in enumerate(self.ids)}
                if args.do_autonumber:
                    cache.set_field('series_index', smap)
                elif tweaks['series_index_auto_increment'] != 'no_change':
                    cache.set_field('series_index', {bid:1.0 for bid in self.ids})

        if args.comments is not null:
            cache.set_field('comments', {bid:args.comments for bid in self.ids})

        if args.do_remove_conv:
            cache.delete_conversion_options(self.ids)

        if args.clear_languages:
            cache.set_field('languages', {bid:() for bid in self.ids})
        elif args.languages:
            cache.set_field('languages', {bid:args.languages for bid in self.ids})

        if args.remove_all:
            cache.set_field('tags', {bid:() for bid in self.ids})
        if args.add or args.remove:
            self.db.bulk_modify_tags(self.ids, add=args.add, remove=args.remove)

        if self.do_sr:
            for book_id in self.ids:
                self.s_r_func(book_id)
            if self.sr_calls:
                for field, book_id_val_map in self.sr_calls.iteritems():
                    self.refresh_books.update(self.db.new_api.set_field(field, book_id_val_map))