def render_cover(self, book_id): if self.ignore_render_requests.is_set(): return tcdata, timestamp = self.thumbnail_cache[book_id] use_cache = False if timestamp is None: # Not in cache has_cover, cdata, timestamp = self.model( ).db.new_api.cover_or_cache(book_id, 0) else: has_cover, cdata, timestamp = self.model( ).db.new_api.cover_or_cache(book_id, timestamp) if has_cover and cdata is None: # The cached cover is fresh cdata = tcdata use_cache = True if has_cover: p = QImage() p.loadFromData(cdata, CACHE_FORMAT if cdata is tcdata else 'JPEG') dpr = self.device_pixel_ratio p.setDevicePixelRatio(dpr) if p.isNull() and cdata is tcdata: # Invalid image in cache self.thumbnail_cache.invalidate((book_id, )) self.update_item.emit(book_id) return cdata = None if p.isNull() else p if not use_cache: # cache is stale if cdata is not None: width, height = p.width(), p.height() scaled, nwidth, nheight = fit_image( width, height, int(dpr * self.delegate.cover_size.width()), int(dpr * self.delegate.cover_size.height())) if scaled: if self.ignore_render_requests.is_set(): return p = p.scaled(nwidth, nheight, Qt.IgnoreAspectRatio, Qt.SmoothTransformation) p.setDevicePixelRatio(dpr) cdata = p # update cache if cdata is None: self.thumbnail_cache.invalidate((book_id, )) else: try: self.thumbnail_cache.insert(book_id, timestamp, image_to_data(cdata)) except EncodeError as err: self.thumbnail_cache.invalidate((book_id, )) prints(err) except Exception: import traceback traceback.print_exc() elif tcdata is not None: # Cover was removed, but it exists in cache, remove from cache self.thumbnail_cache.invalidate((book_id, )) self.delegate.cover_cache.set(book_id, cdata) self.update_item.emit(book_id)
def render_cover(self, book_id): if self.ignore_render_requests.is_set(): return dpr = self.device_pixel_ratio page_width = int(dpr * self.delegate.cover_size.width()) page_height = int(dpr * self.delegate.cover_size.height()) tcdata, timestamp = self.thumbnail_cache[book_id] use_cache = False if timestamp is None: # Not in cache has_cover, cdata, timestamp = self.model().db.new_api.cover_or_cache(book_id, 0) else: has_cover, cdata, timestamp = self.model().db.new_api.cover_or_cache(book_id, timestamp) if has_cover and cdata is None: # The cached cover is fresh cdata = tcdata use_cache = True if has_cover: p = QImage() p.loadFromData(cdata, CACHE_FORMAT if cdata is tcdata else 'JPEG') p.setDevicePixelRatio(dpr) if p.isNull() and cdata is tcdata: # Invalid image in cache self.thumbnail_cache.invalidate((book_id,)) self.update_item.emit(book_id) return cdata = None if p.isNull() else p if not use_cache: # cache is stale if cdata is not None: width, height = p.width(), p.height() scaled, nwidth, nheight = fit_image( width, height, page_width, page_height) if scaled: if self.ignore_render_requests.is_set(): return p = p.scaled(nwidth, nheight, Qt.IgnoreAspectRatio, Qt.SmoothTransformation) p.setDevicePixelRatio(dpr) cdata = p # update cache if cdata is None: self.thumbnail_cache.invalidate((book_id,)) else: try: self.thumbnail_cache.insert(book_id, timestamp, image_to_data(cdata)) except EncodeError as err: self.thumbnail_cache.invalidate((book_id,)) prints(err) except Exception: import traceback traceback.print_exc() elif tcdata is not None: # Cover was removed, but it exists in cache, remove from cache self.thumbnail_cache.invalidate((book_id,)) self.delegate.cover_cache.set(book_id, cdata) self.update_item.emit(book_id)
def imageForDomain(cls, url, allowNull=False): ''' @param: url QUrl @return: QIcon ''' if not url.host(): if allowNull: return QImage() return cls.emptyWebImage() with cls.instance()._iconCacheMutex: for url0, img in cls.instance()._iconBuffer: if url0.host() == url.host(): return img # TODO: is it necessary to use escapeSqlGlobString escapedHost = gVar.appTools.escapeSqlGlobString(url.host()) hostPattern = '*%s*' % escapedHost icon = IconsDbModel.select().filter( IconsDbModel.url.contains(hostPattern)).first() img = QImage() if icon: img.loadFromData(icon.icon) if not img.isNull(): return img if not allowNull: return cls.emptyWebImage() return img
def createThumb (self,path_to_perso): list_pic = os.listdir (path_to_perso) if len(list_pic) > 0 : find = False for pic in list_pic : self.success = True if self.thumb_ext not in pic : if "portrait" in pic : find = True thumbnail = QImage(os.path.join(path_to_perso,pic)) if (thumbnail.isNull()): print ('IMAGE NULL',os.path.join(path_to_perso,pic)) thumbnail = thumbnail.scaledToWidth(self.thumb_width) pic_basename = pic.split(".") result = thumbnail.save(os.path.join(path_to_perso,self.thumb_ext+".jpg")) try: os.rename(os.path.join(path_to_perso,pic),os.path.join(path_to_perso,self.portrait_ext+".jpg")) self.nb_rename[1] = self.nb_rename[1]+1 except FileExistsError : self.nb_rename_failed[1] = self.nb_rename_failed[1]+1 pass if result == False : self.nb_echec_thumb_creation[1] = self.nb_echec_thumb_creation[1]+ 1 try : qDebug("Echec de la creation de la miniature :"+os.path.join(path_to_perso,self.thumb_ext+".jpg")) self.echec_list.append("FAILED save"+str(os.path.join(path_to_perso,self.thumb_ext+".jpg"))) except UnicodeEncodeError : qDebug("echec sauvegarde ****") else: self.nb_success_thumb_creation[1] = self.nb_success_thumb_creation[1]+1 else : pass #une image principale n existe pas if find == False : #on fait l hypothese que portrai_ext et thumb_ext contienne tous 2 le mot "portrait" thumbnail = QImage(os.path.join(path_to_perso,pic)) thumbnail = thumbnail.scaledToWidth(self.thumb_width) pic_basename = pic.split(".") result = thumbnail.save(os.path.join(path_to_perso,self.thumb_ext+".jpg")) if result == False : try : qDebug("Echec de la creation de la miniature :"+str(os.path.join(path_to_perso,self.thumb_ext+".jpg"))) self.echec_list.append("FAILED save"+str(os.path.join(path_to_perso,self.thumb_ext+".jpg"))) except UnicodeEncodeError : qDebug("echec sauvegarde ****") self.nb_echec_thumb_creation[1] = self.nb_echec_thumb_creation[1]+1 else: self.nb_success_thumb_creation[1] = self.nb_success_thumb_creation[1] + 1 try: os.rename(os.path.join(path_to_perso,pic), os.path.join(path_to_perso,self.portrait_ext+".jpg")) self.nb_rename[1] = self.nb_rename[1] + 1 except FileExistsError : self.nb_rename_failed[1] = self.nb_rename_failed[1] + 1 pass else: self.echec_list.append("FAILED no portrait found"+str(path_to_perso))
def get_icon(path, pixmap_to_data=None, as_data=False, size=64): if not path: return with TemporaryDirectory() as tdir: iconset = os.path.join(tdir, 'output.iconset') try: subprocess.check_call( ['iconutil', '-c', 'iconset', '-o', 'output.iconset', path], cwd=tdir) except subprocess.CalledProcessError: return try: names = os.listdir(iconset) except EnvironmentError: return if not names: return from PyQt5.Qt import QImage, Qt names.sort(key=numeric_sort_key) for name in names: m = re.search(r'(\d+)x\d+', name) if m is not None and int(m.group(1)) >= size: ans = QImage(os.path.join(iconset, name)) if not ans.isNull(): break else: return ans = ans.scaled(size, size, transformMode=Qt.SmoothTransformation) if as_data: ans = pixmap_to_data(ans) return ans
def get_icon(path, pixmap_to_data=None, as_data=False, size=64): if not path: return with TemporaryDirectory() as tdir: iconset = os.path.join(tdir, 'output.iconset') try: subprocess.check_call(['iconutil', '-c', 'iconset', '-o', 'output.iconset', path], cwd=tdir) except subprocess.CalledProcessError: return try: names = os.listdir(iconset) except EnvironmentError: return if not names: return from PyQt5.Qt import QImage, Qt names.sort(key=numeric_sort_key) for name in names: m = re.search('(\d+)x\d+', name) if m is not None and int(m.group(1)) >= size: ans = QImage(os.path.join(iconset, name)) if not ans.isNull(): break else: return ans = ans.scaled(size, size, transformMode=Qt.SmoothTransformation) if as_data: ans = pixmap_to_data(ans) return ans
def paste(self): clipboard = QApplication.clipboard() md = clipboard.mimeData() if md.hasImage(): img = QImage(md.imageData()) if not img.isNull(): self.undo_stack.push(Replace(img, _("Paste image"), self)) else: error_dialog(self, _("No image"), _("No image available in the clipboard"), show=True)
def paste(self): clipboard = QApplication.clipboard() md = clipboard.mimeData() if md.hasImage(): img = QImage(md.imageData()) if not img.isNull(): self.undo_stack.push(Replace(img, _('Paste image'), self)) else: error_dialog(self, _('No image'), _( 'No image available in the clipboard'), show=True)
def __init__(self, dirpath): pictureflow.FlowImages.__init__(self) self.images = [] self.captions = [] self.subtitles = [] for f in os.listdir(dirpath): f = os.path.join(dirpath, f) img = QImage(f) if not img.isNull(): self.images.append(img) self.captions.append(os.path.basename(f)) self.subtitles.append('%d bytes'%os.stat(f).st_size)
def getImage(name: str, get_null: bool = False) -> QImage: """PNG image called name in assets.""" if name in imageResources: return imageResources[name] else: resource = QImage(os.path.join(wd, "assets", name + ".png")) if resource.isNull(): if not get_null: raise ValueError(f"Resource {name}.png doesn't exist") else: imageResources[name] = resource return resource
def __call__(self, container): from PyQt5.Qt import QImage from calibre.gui2 import pixmap_to_data ext = container.mime_map[self.name].split('/')[-1].upper() if ext == 'JPG': ext = 'JPEG' if ext not in ('PNG', 'JPEG', 'GIF'): return False with container.open(self.name, 'r+b') as f: raw = f.read() i = QImage() i.loadFromData(raw) if i.isNull(): return False raw = pixmap_to_data(i, format=ext, quality=95) f.seek(0) f.truncate() f.write(raw) return True
def imageForUrl(cls, url, allowNull=False): ''' @param: url QUrl @return: QImage ''' if not url.path(): return allowNull and QImage() or cls.emptyWebImage() with cls.instance()._iconCacheMutex: encUrl = encodeUrl(url) # find in urlImageCache img = cls.instance()._urlImageCache.get(encUrl, None) if img: if not img.isNull(): return img if not allowNull: return cls.emptyWebImage() return img # find from icon buffer for url0, img in cls.instance()._iconBuffer: if encodeUrl(url0) == encUrl: return img # TODO: is it necessary to use escapeSqlGlobString escapedUrl = gVar.appTools.escapeSqlGlobString( encUrl.data().decode()) urlPattern = '%s*' % escapedUrl icon = IconsDbModel.select().filter( IconsDbModel.url.contains(urlPattern)).first() img = QImage() if icon: img.loadFromData(icon.icon) cls.instance()._urlImageCache[encUrl] = img if not img.isNull(): return img if not allowNull: return cls.emptyWebImage() return img
def dropEvent(self, event): event.setDropAction(Qt.CopyAction) md = event.mimeData() x, y = dnd_get_image(md) if x is not None: # We have an image, set cover event.accept() if y is None: # Local image self.undo_stack.push(Replace(x.toImage(), _('Drop image'), self)) else: d = DownloadDialog(x, y, self.gui) d.start_download() if d.err is None: with open(d.fpath, 'rb') as f: img = QImage() img.loadFromData(f.read()) if not img.isNull(): self.undo_stack.push(Replace(img, _('Drop image'), self)) event.accept()
def rescale(self): from calibre.utils.magick.draw import Image is_image_collection = getattr(self.opts, 'is_image_collection', False) if is_image_collection: page_width, page_height = self.opts.dest.comic_screen_size else: page_width, page_height = self.opts.dest.width, self.opts.dest.height page_width -= (self.opts.margin_left + self.opts.margin_right) * self.opts.dest.dpi / 72. page_height -= (self.opts.margin_top + self.opts.margin_bottom) * self.opts.dest.dpi / 72. for item in self.oeb.manifest: if item.media_type.startswith('image'): ext = item.media_type.split('/')[-1].upper() if ext == 'JPG': ext = 'JPEG' if ext not in ('PNG', 'JPEG', 'GIF'): ext = 'JPEG' raw = item.data if hasattr(raw, 'xpath') or not raw: # Probably an svg image continue try: img = Image() img.load(raw) except: continue width, height = img.size try: if self.check_colorspaces and img.colorspace == 'CMYKColorspace': # We cannot do an imagemagick conversion of CMYK to RGB as # ImageMagick inverts colors if you just set the colorspace # to rgb. See for example: https://bugs.launchpad.net/bugs/1246710 from PyQt5.Qt import QImage from calibre.gui2 import pixmap_to_data qimg = QImage() qimg.loadFromData(raw) if not qimg.isNull(): raw = item.data = pixmap_to_data(qimg, format=ext, quality=95) img = Image() img.load(raw) self.log.warn( 'The image %s is in the CMYK colorspace, converting it ' 'to RGB as Adobe Digital Editions cannot display CMYK' % item.href) else: self.log.warn( 'The image %s is in the CMYK colorspace, you should convert' ' it to sRGB as Adobe Digital Editions cannot render CMYK' % item.href) except Exception: pass scaled, new_width, new_height = fit_image( width, height, page_width, page_height) if scaled: new_width = max(1, new_width) new_height = max(1, new_height) self.log( 'Rescaling image from %dx%d to %dx%d' % (width, height, new_width, new_height), item.href) try: img.size = (new_width, new_height) data = img.export(ext.lower()) except KeyboardInterrupt: raise except: self.log.exception('Failed to rescale image') else: item.data = data item.unload_data_from_memory()
def rescale(self): from calibre.utils.magick.draw import Image is_image_collection = getattr(self.opts, 'is_image_collection', False) if is_image_collection: page_width, page_height = self.opts.dest.comic_screen_size else: page_width, page_height = self.opts.dest.width, self.opts.dest.height page_width -= (self.opts.margin_left + self.opts.margin_right) * self.opts.dest.dpi/72. page_height -= (self.opts.margin_top + self.opts.margin_bottom) * self.opts.dest.dpi/72. for item in self.oeb.manifest: if item.media_type.startswith('image'): ext = item.media_type.split('/')[-1].upper() if ext == 'JPG': ext = 'JPEG' if ext not in ('PNG', 'JPEG', 'GIF'): ext = 'JPEG' raw = item.data if hasattr(raw, 'xpath') or not raw: # Probably an svg image continue try: img = Image() img.load(raw) except: continue width, height = img.size try: if self.check_colorspaces and img.colorspace == 'CMYKColorspace': # We cannot do an imagemagick conversion of CMYK to RGB as # ImageMagick inverts colors if you just set the colorspace # to rgb. See for example: https://bugs.launchpad.net/bugs/1246710 from PyQt5.Qt import QImage from calibre.gui2 import pixmap_to_data qimg = QImage() qimg.loadFromData(raw) if not qimg.isNull(): raw = item.data = pixmap_to_data(qimg, format=ext, quality=95) img = Image() img.load(raw) self.log.warn( 'The image %s is in the CMYK colorspace, converting it ' 'to RGB as Adobe Digital Editions cannot display CMYK' % item.href) else: self.log.warn( 'The image %s is in the CMYK colorspace, you should convert' ' it to sRGB as Adobe Digital Editions cannot render CMYK' % item.href) except Exception: pass scaled, new_width, new_height = fit_image(width, height, page_width, page_height) if scaled: new_width = max(1, new_width) new_height = max(1, new_height) self.log('Rescaling image from %dx%d to %dx%d'%( width, height, new_width, new_height), item.href) try: img.size = (new_width, new_height) data = img.export(ext.lower()) except KeyboardInterrupt: raise except: self.log.exception('Failed to rescale image') else: item.data = data item.unload_data_from_memory()