def drag_icon(self, cover, multiple): cover = cover.scaledToHeight(120, Qt.SmoothTransformation) if multiple: base_width = cover.width() base_height = cover.height() base = QImage(base_width+21, base_height+21, QImage.Format_ARGB32_Premultiplied) base.fill(QColor(255, 255, 255, 0).rgba()) p = QPainter(base) rect = QRect(20, 0, base_width, base_height) p.fillRect(rect, QColor('white')) p.drawRect(rect) rect.moveLeft(10) rect.moveTop(10) p.fillRect(rect, QColor('white')) p.drawRect(rect) rect.moveLeft(0) rect.moveTop(20) p.fillRect(rect, QColor('white')) p.save() p.setCompositionMode(p.CompositionMode_SourceAtop) p.drawImage(rect.topLeft(), cover) p.restore() p.drawRect(rect) p.end() cover = base return QPixmap.fromImage(cover)
def scale_image(data, width=60, height=80, compression_quality=70, as_png=False, preserve_aspect_ratio=True): ''' Scale an image, returning it as either JPEG or PNG data (bytestring). Transparency is alpha blended with white when converting to JPEG. Is thread safe and does not require a QApplication. ''' # We use Qt instead of ImageMagick here because ImageMagick seems to use # some kind of memory pool, causing memory consumption to sky rocket. if isinstance(data, QImage): img = data else: img = QImage() if not img.loadFromData(data): raise ValueError('Could not load image for thumbnail generation') if preserve_aspect_ratio: scaled, nwidth, nheight = fit_image(img.width(), img.height(), width, height) if scaled: img = img.scaled(nwidth, nheight, Qt.KeepAspectRatio, Qt.SmoothTransformation) else: if img.width() != width or img.height() != height: img = img.scaled(width, height, Qt.IgnoreAspectRatio, Qt.SmoothTransformation) if not as_png and img.hasAlphaChannel(): nimg = QImage(img.size(), QImage.Format_RGB32) nimg.fill(Qt.white) p = QPainter(nimg) p.drawImage(0, 0, img) p.end() img = nimg ba = QByteArray() buf = QBuffer(ba) buf.open(QBuffer.WriteOnly) fmt = 'PNG' if as_png else 'JPEG' if not img.save(buf, fmt, quality=compression_quality): raise ValueError('Failed to export thumbnail image to: ' + fmt) return img.width(), img.height(), ba.data()
def drag_icon(self, cover, multiple): cover = cover.scaledToHeight(120, Qt.SmoothTransformation) if multiple: base_width = cover.width() base_height = cover.height() base = QImage(base_width+21, base_height+21, QImage.Format_ARGB32_Premultiplied) base.fill(QColor(255, 255, 255, 0).rgba()) p = QPainter(base) rect = QRect(20, 0, base_width, base_height) p.fillRect(rect, QColor('white')) p.drawRect(rect) rect.moveLeft(10) rect.moveTop(10) p.fillRect(rect, QColor('white')) p.drawRect(rect) rect.moveLeft(0) rect.moveTop(20) p.fillRect(rect, QColor('white')) p.save() p.setCompositionMode(p.CompositionMode_SourceAtop) p.drawImage(rect.topLeft(), cover) p.restore() p.drawRect(rect) p.end() cover = base return QPixmap.fromImage(cover)
def add_image(self, img, cache_key): ref = self.get_image(cache_key) if ref is not None: return ref fmt = img.format() image = QImage(img) if (image.depth() == 1 and img.colorTable().size() == 2 and img.colorTable().at(0) == QColor(Qt.black).rgba() and img.colorTable().at(1) == QColor(Qt.white).rgba()): if fmt == QImage.Format_MonoLSB: image = image.convertToFormat(QImage.Format_Mono) fmt = QImage.Format_Mono else: if (fmt != QImage.Format_RGB32 and fmt != QImage.Format_ARGB32): image = image.convertToFormat(QImage.Format_ARGB32) fmt = QImage.Format_ARGB32 w = image.width() h = image.height() d = image.depth() if fmt == QImage.Format_Mono: bytes_per_line = (w + 7) >> 3 data = image.constBits().asstring(bytes_per_line * h) return self.write_image(data, w, h, d, cache_key=cache_key) has_alpha = False soft_mask = None if fmt == QImage.Format_ARGB32: tmask = image.constBits().asstring(4*w*h)[self.alpha_bit::4] sdata = bytearray(tmask) vals = set(sdata) vals.discard(255) # discard opaque pixels has_alpha = bool(vals) if has_alpha: # Blend image onto a white background as otherwise Qt will render # transparent pixels as black background = QImage(image.size(), QImage.Format_ARGB32_Premultiplied) background.fill(Qt.white) painter = QPainter(background) painter.drawImage(0, 0, image) painter.end() image = background ba = QByteArray() buf = QBuffer(ba) image.save(buf, 'jpeg', 94) data = ba.data() if has_alpha: soft_mask = self.write_image(tmask, w, h, 8) return self.write_image(data, w, h, 32, dct=True, soft_mask=soft_mask, cache_key=cache_key)
def add_image(self, img, cache_key): ref = self.get_image(cache_key) if ref is not None: return ref fmt = img.format() image = QImage(img) if (image.depth() == 1 and img.colorTable().size() == 2 and img.colorTable().at(0) == QColor(Qt.black).rgba() and img.colorTable().at(1) == QColor(Qt.white).rgba()): if fmt == QImage.Format_MonoLSB: image = image.convertToFormat(QImage.Format_Mono) fmt = QImage.Format_Mono else: if (fmt != QImage.Format_RGB32 and fmt != QImage.Format_ARGB32): image = image.convertToFormat(QImage.Format_ARGB32) fmt = QImage.Format_ARGB32 w = image.width() h = image.height() d = image.depth() if fmt == QImage.Format_Mono: bytes_per_line = (w + 7) >> 3 data = image.constBits().asstring(bytes_per_line * h) return self.write_image(data, w, h, d, cache_key=cache_key) has_alpha = False soft_mask = None if fmt == QImage.Format_ARGB32: tmask = image.constBits().asstring(4*w*h)[self.alpha_bit::4] sdata = bytearray(tmask) vals = set(sdata) vals.discard(255) # discard opaque pixels has_alpha = bool(vals) if has_alpha: # Blend image onto a white background as otherwise Qt will render # transparent pixels as black background = QImage(image.size(), QImage.Format_ARGB32_Premultiplied) background.fill(Qt.white) painter = QPainter(background) painter.drawImage(0, 0, image) painter.end() image = background ba = QByteArray() buf = QBuffer(ba) image.save(buf, 'jpeg', 94) data = bytes(ba.data()) if has_alpha: soft_mask = self.write_image(tmask, w, h, 8) return self.write_image(data, w, h, 32, dct=True, soft_mask=soft_mask, cache_key=cache_key)
def __call__(self, canvas): if canvas.has_selection and canvas.selection_state.rect is not None: pimg = self.after_image img = self.after_image = QImage(canvas.current_image) rect = QRectF(*get_selection_rect(img, canvas.selection_state.rect, canvas.target)) p = QPainter(img) p.setRenderHint(p.SmoothPixmapTransform, True) p.drawImage(rect, pimg, QRectF(pimg.rect())) p.end() return self.after_image
def __call__(self, canvas): if canvas.has_selection and canvas.selection_state.rect is not None: pimg = self.after_image img = self.after_image = QImage(canvas.current_image) rect = QRectF(*get_selection_rect(img, canvas.selection_state.rect, canvas.target)) p = QPainter(img) p.setRenderHint(p.SmoothPixmapTransform, True) p.drawImage(rect, pimg, QRectF(pimg.rect())) p.end() return self.after_image
def makeQPixmap(self, width, height): data = numpy.zeros((width, height), float) data[...] = (numpy.arange(width) / (width - 1.))[:, numpy.newaxis] # make brush image -- diag background, with colormap on top img = QPixmap(width, height) painter = QPainter(img) painter.fillRect(0, 0, width, height, QBrush(QColor("white"))) painter.fillRect(0, 0, width, height, QBrush(Qt.BDiagPattern)) painter.drawImage(0, 0, self.colorize(data)) painter.end() return img
def paint(self, paint: QPainter, style: QStyleOptionGraphicsItem, widget=None): qpen = QPen() qpen.setColor(Qt.white) # paint.setBackground() paint.setPen(qpen) aspect = self.head_img.width() / self.head_img.height() ratio = self.height * 0.2 target = QRectF(0, 0, aspect * ratio, ratio) source = QRectF(0, 0, self.head_img.width(), self.head_img.height()) paint.drawImage(target, self.head_img, source)
def image_to_data(img, compression_quality=95, fmt='JPEG'): ba = QByteArray() buf = QBuffer(ba) buf.open(QBuffer.WriteOnly) fmt = fmt.upper() if img.hasAlphaChannel() and fmt in 'JPEG JPG'.split(): nimg = QImage(img.size(), QImage.Format_RGB32) nimg.fill(Qt.white) p = QPainter(nimg) p.drawImage(0, 0, img) p.end() img = nimg if not img.save(buf, fmt, quality=compression_quality): raise ValueError('Failed to export image as ' + fmt) return ba.data()
def overlay_image(img, canvas=None, left=0, top=0): if canvas is None: canvas = QImage(img.size(), QImage.Format_RGB32) canvas.fill(Qt.white) if imageops is None: # This is for people running from source who have not updated the # binary and so do not have the imageops module from PyQt5.Qt import QPainter from calibre.gui2 import ensure_app ensure_app() p = QPainter(canvas) p.drawImage(left, top, img) p.end() else: imageops.overlay(img, canvas, left, top) return canvas
def scale_image(data, width=60, height=80, compression_quality=70, as_png=False, preserve_aspect_ratio=True): ''' Scale an image, returning it as either JPEG or PNG data (bytestring). Transparency is alpha blended with white when converting to JPEG. Is thread safe and does not require a QApplication. ''' # We use Qt instead of ImageMagick here because ImageMagick seems to use # some kind of memory pool, causing memory consumption to sky rocket. if isinstance(data, QImage): img = data else: img = QImage() if not img.loadFromData(data): raise ValueError('Could not load image for thumbnail generation') if preserve_aspect_ratio: scaled, nwidth, nheight = fit_image(img.width(), img.height(), width, height) if scaled: img = img.scaled(nwidth, nheight, Qt.KeepAspectRatio, Qt.SmoothTransformation) else: if img.width() != width or img.height() != height: img = img.scaled(width, height, Qt.IgnoreAspectRatio, Qt.SmoothTransformation) if not as_png and img.hasAlphaChannel(): nimg = QImage(img.size(), QImage.Format_RGB32) nimg.fill(Qt.white) p = QPainter(nimg) p.drawImage(0, 0, img) p.end() img = nimg ba = QByteArray() buf = QBuffer(ba) buf.open(QBuffer.WriteOnly) fmt = 'PNG' if as_png else 'JPEG' if not img.save(buf, fmt, quality=compression_quality): raise ValueError('Failed to export thumbnail image to: ' + fmt) return img.width(), img.height(), ba.data()
def paintEvent(self, event): ''' @param: event QPaintEvent ''' if not (self._options & self._MultiIconOption): super().paintEvent(event) return p = QPainter(self) w = self._multiIcon.width() h4 = self._multiIcon.height() / 4 if not self.isEnabled(): p.drawImage(0, 0, self._multiIcon, 0, h4 * 3, w, h4) elif self.isDown(): p.drawImage(0, 0, self._multiIcon, 0, h4 * 2, w, h4) elif self.underMouse(): p.drawImage(0, 0, self._multiIcon, 0, h4 * 1, w, h4) else: p.drawImage(0, 0, self._multiIcon, 0, h4 * 0, w, h4)
def run(self): time.sleep(0.5) # create hash dict of current list self._hash_item_dict = {} for item in self._item_list: self._hash_item_dict[item.hash] = item # compare and swap between lists if new item is not generated for new_hash in self._hash_item_dict.keys(): if new_hash in self._old_hash_item_dict.keys(): # swap to avoid generating uselessly : self._hash_item_dict[ new_hash] = self._old_hash_item_dict[new_hash] else: # generate _ = self._hash_item_dict[new_hash].image # append generated images # images_list.append() pix_list = [] for new_item in self._item_list: usable_item = self._hash_item_dict[new_item.hash] pix_list.append(usable_item.image) # draw pixmaps in one : image = QImage(20, 20, QImage.Format_ARGB32_Premultiplied) image.fill(Qt.white) point = QPoint(0, 0) width_list = [pix.width() for pix in pix_list] max_width = max(width_list) self._max_width_found = max([max_width, self._max_width_found]) for pix in pix_list: last_image = image image = QImage(self._max_width_found, image.height( ) + pix.height(), QImage.Format_ARGB32_Premultiplied) pix_paint = QPainter(image) image.fill(Qt.white) pix_paint.drawImage(0, 0, last_image) pix_paint.drawImage(point, pix) point = QPoint(0, point.y() + pix.height()) pix_paint.end() ''' pixmap = QImage(21,21, QImage.Format_ARGB32_Premultiplied) # temp pixPaint = QPainter(pixmap) myPen = QPen( Qt.black) pixPaint.setPen(myPen) pixPaint.drawRect(0,0, 20,20); pixPaint.end() image = pixmap painter.drawImage(point, pix) point = QPoint(0, point.y() + pix.height()) painter.end() ''' final_pixmap = QPixmap.fromImage(image, Qt.AutoColor) self.image_generated.emit(final_pixmap) self._old_item_list = self._item_list self._old_hash_item_dict = self._hash_item_dict
class PaintBoard(QWidget): def __init__(self): QWidget.__init__(self) # self.label = QLabel(self) # self.gridLayout = QGridLayout(self) # self.gridLayout.addWidget(self.label) self.pixmap = QPixmap(1,1) self.pixmap.fill(Qt.white) self.img = QImage(self.pixmap.toImage()) # self.label.setFrameShape(1) # # self.label.setPixmap(self.pixmap) # self.label.setScaledContents(True) # self.label.setVisible(False) self.pen = QPainter() def paintEvent(self, paintEvent): self.pixmap = self.pixmap.scaled(self.width(), self.height()) self.pen.begin(self) # self.pen.drawPixmap(0, 0, self.pixmap) self.img = QImage(self.pixmap.toImage()) self.pen.drawImage(0, 0, self.img) self.pen.end() def drawPoints(self, x, y): # print(self.width(),self.height()) m = int(self.width()/2) + x n = int(self.height()/2) - y self.pen.begin(self.pixmap) self.pen.setPen(QPen(Qt.black,1)) self.pen.drawPoint(m, n) self.pen.end() self.update() # self.repaint() def load_img(self, img): self.pixmap.load(img) self.update() #DDA def drawLine(self, x0, y0, x1, y1): self.Clear() dx = x1 - x0 dy = y1 - y0 if fabs(dx) > fabs(dy): steps = fabs(dx) else: steps = fabs(dy) self.drawPoints(int(x0+0.5), int(y0+0.5)) xInc = dx/steps yInc = dy/steps for i in range(int(steps+0.5)): x0 += xInc y0 += yInc self.drawPoints(int(x0+0.5), int(y0+0.5)) #中点法画圆 def CirclePlot(self, xc, yc, x, y): self.drawPoints(x+xc, y+yc) self.drawPoints(-x+xc, y+yc) self.drawPoints(x+xc, -y+yc) self.drawPoints(-x+xc, -y+yc) self.drawPoints(y+xc, x+yc) self.drawPoints(y+xc, -x+yc) self.drawPoints(-y+xc, x+yc) self.drawPoints(-y+xc, -x+yc) def drawRound(self, xc, yc, r): self.Clear() x = 0 y = r d = 3-2*r self.CirclePlot(xc, yc, x, y) while x<y: if d<0: d = d+4*x+6 else: d = d+4*(x-y)+10 y -= 1 x +=1 self.CirclePlot(xc, yc, x, y) ''' # 边界填充 def fill(self, x, y): w = int(self.width()/2) h = int(self.height()/2) block = deque([(x, y)]) while 1: if len(block) == 0: break else: # print(block) point = block.popleft() m = point[0] n = point[1] # c = self.img.pixel(w+m, h+n) # colors = QColor(c).getRgb() # if colors != (0, 0, 0, 255): self.drawPoints(m, n) # result.append((m,n)) c = self.img.pixel(w+m, h+n-1) colors = QColor(c).getRgb() if colors != (0, 0, 0, 255): if (m,n-1) not in block: block.append((m,n-1)) c = self.img.pixel(w+m, h+n+1) colors = QColor(c).getRgb() if colors != (0, 0, 0, 255): if (m,n+1) not in block: block.append((m,n+1)) c = self.img.pixel(w+m-1, h+n) colors = QColor(c).getRgb() if colors != (0, 0, 0, 255): if (m-1,n) not in block: block.append((m-1,n)) c = self.img.pixel(w+m+1, h+n) colors = QColor(c).getRgb() if colors != (0, 0, 0, 255): if (m+1,n) not in block: block.append((m+1,n)) print(results) ''' #边界填充 #种子边界填充 def fill(self, x, y): w = int(self.width()/2) h = int(self.height()/2) block = deque([(x, y)]) results = [] while 1: if len(block) == 0: break else: point = block.popleft() m = point[0] n = point[1] results.append((m,n)) c = self.img.pixel(w+m, h+n-1) colors = QColor(c).getRgb() if colors != (0, 0, 0, 255): if (m,n-1) not in block: if (m,n-1) not in results: block.append((m,n-1)) c = self.img.pixel(w+m, h+n+1) colors = QColor(c).getRgb() if colors != (0, 0, 0, 255): if (m,n+1) not in block: if (m,n+1) not in results: block.append((m,n+1)) c = self.img.pixel(w+m-1, h+n) colors = QColor(c).getRgb() if colors != (0, 0, 0, 255): if (m-1,n) not in block: if (m-1,n) not in results: block.append((m-1,n)) c = self.img.pixel(w+m+1, h+n) colors = QColor(c).getRgb() if colors != (0, 0, 0, 255): if (m+1,n) not in block: if (m+1,n) not in results: block.append((m+1,n)) for point in results: self.drawPoints(point[0], point[1]) def Clear(self): self.pixmap.fill(Qt.white) self.update()
def _populate_covers(self): ''' Display calibre cover for both unless mismatch ''' def _fetch_marvin_cover(border_width=0): ''' Retrieve LargeCoverJpg from cache ''' #self._log_location('border_width: {0}'.format(border_width)) con = sqlite3.connect(self.marvin_db_path) with con: con.row_factory = sqlite3.Row # Fetch Hash from mainDb cover_cur = con.cursor() cover_cur.execute('''SELECT Hash FROM Books WHERE ID = '{0}' '''.format(self.book_id)) row = cover_cur.fetchone() book_hash = row[b'Hash'] large_covers_subpath = self.connected_device._cover_subpath(size="large") cover_path = '/'.join([large_covers_subpath, '%s.jpg' % book_hash]) stats = self.parent.ios.exists(cover_path) if stats: self._log("fetching large cover from cache") #self._log("cover size: {:,} bytes".format(int(stats['st_size']))) cover_bytes = self.parent.ios.read(cover_path, mode='rb') m_image = QImage() m_image.loadFromData(cover_bytes) if border_width: # Construct a QPixmap with oversized yellow background m_image = m_image.scaledToHeight( self.COVER_ICON_SIZE - border_width * 2, Qt.SmoothTransformation) self.m_pixmap = QPixmap( QSize(m_image.width() + border_width * 2, m_image.height() + border_width * 2)) m_painter = QPainter(self.m_pixmap) m_painter.setRenderHints(m_painter.Antialiasing) m_painter.fillRect(self.m_pixmap.rect(), self.MISMATCH_COLOR) m_painter.drawImage(border_width, border_width, m_image) else: m_image = m_image.scaledToHeight( self.COVER_ICON_SIZE, Qt.SmoothTransformation) self.m_pixmap = QPixmap( QSize(m_image.width(), m_image.height())) m_painter = QPainter(self.m_pixmap) m_painter.setRenderHints(m_painter.Antialiasing) m_painter.drawImage(0, 0, m_image) self.marvin_cover.setPixmap(self.m_pixmap) else: # No cover available, use generic self._log("No cached cover, using generic") pixmap = QPixmap() pixmap.load(I('book.png')) pixmap = pixmap.scaled(self.COVER_ICON_SIZE, self.COVER_ICON_SIZE, aspectRatioMode=Qt.KeepAspectRatio, transformMode=Qt.SmoothTransformation) self.marvin_cover.setPixmap(pixmap) self.calibre_cover.setMaximumSize(QSize(self.COVER_ICON_SIZE, self.COVER_ICON_SIZE)) self.calibre_cover.setText('') self.calibre_cover.setScaledContents(False) self.marvin_cover.setMaximumSize(QSize(self.COVER_ICON_SIZE, self.COVER_ICON_SIZE)) self.marvin_cover.setText('') self.marvin_cover.setScaledContents(False) if self.cid: db = self.opts.gui.current_db if 'cover_hash' not in self.mismatches: mi = db.get_metadata(self.cid, index_is_id=True, get_cover=True, cover_as_data=True) c_image = QImage() if mi.has_cover: c_image.loadFromData(mi.cover_data[1]) c_image = c_image.scaledToHeight(self.COVER_ICON_SIZE, Qt.SmoothTransformation) self.c_pixmap = QPixmap(QSize(c_image.width(), c_image.height())) c_painter = QPainter(self.c_pixmap) c_painter.setRenderHints(c_painter.Antialiasing) c_painter.drawImage(0, 0, c_image) else: c_image.load(I('book.png')) c_image = c_image.scaledToWidth(135, Qt.SmoothTransformation) # Construct a QPixmap with dialog background self.c_pixmap = QPixmap( QSize(c_image.width(), c_image.height())) c_painter = QPainter(self.c_pixmap) c_painter.setRenderHints(c_painter.Antialiasing) bgcolor = self.palette().color(QPalette.Background) c_painter.fillRect(self.c_pixmap.rect(), bgcolor) c_painter.drawImage(0, 0, c_image) # Set calibre cover self.calibre_cover.setPixmap(self.c_pixmap) if self.opts.prefs.get('development_mode', False): # Show individual covers _fetch_marvin_cover() else: # Show calibre cover on both sides self.marvin_cover.setPixmap(self.c_pixmap) else: # Covers don't match - render with border # Construct a QImage with the cover sized to fit inside border c_image = QImage() cdata = db.cover(self.cid, index_is_id=True) if cdata is None: c_image.load(I('book.png')) self.calibre_cover.setScaledContents(True) else: c_image.loadFromData(cdata) c_image = c_image.scaledToHeight( self.COVER_ICON_SIZE - self.BORDER_WIDTH * 2, Qt.SmoothTransformation) # Construct a QPixmap with yellow background self.c_pixmap = QPixmap( QSize(c_image.width() + self.BORDER_WIDTH * 2, c_image.height() + self.BORDER_WIDTH * 2)) c_painter = QPainter(self.c_pixmap) c_painter.setRenderHints(c_painter.Antialiasing) c_painter.fillRect(self.c_pixmap.rect(),self.MISMATCH_COLOR) c_painter.drawImage(self.BORDER_WIDTH, self.BORDER_WIDTH, c_image) self.calibre_cover.setPixmap(self.c_pixmap) # Render Marvin cover with small border if different covers, # large cover if no cover hash (loaded via OPDS) border_width = self.BORDER_WIDTH if self.mismatches['cover_hash']['Marvin'] is None: border_width = self.BORDER_WIDTH * 3 _fetch_marvin_cover(border_width=border_width) else: _fetch_marvin_cover()
def drawIconWithShadow(self, icon, rect, painter, iconMode, radius=3, color=QColor(0, 0, 0, 130), offset=QPoint(1, -2)): ''' @brief: Draw a cached pixmap with shadow @param: icon QIcon @param: rect QRect @param: painter QPainter @param: iconMode QIcon.Mode @param: radius int @param: color QColor @param: offset QPoint ''' cache = QPixmap() pixmapName = 'icon %s %s %s' % (icon.cacheKey(), iconMode, rect.height()) cache = QPixmapCache.find(pixmapName) if not cache: px = icon.pixmap(rect.size(), iconMode) px.setDevicePixelRatio(gVar.app.devicePixelRatio()) cache = QPixmap(px.size() + QSize(radius * 2, radius * 2)) cache.setDevicePixelRatio(px.devicePixelRatioF()) cache.fill(Qt.transparent) cachePainter = QPainter(cache) # Draw shadow tmp = QImage(px.size() + QSize(radius * 2, radius * 2 + 1), QImage.Format_ARGB32_Premultiplied) tmp.setDevicePixelRatio(px.devicePixelRatioF()) tmp.fill(Qt.transparent) tmpPainter = QPainter(tmp) tmpPainter.setCompositionMode(QPainter.CompositionMode_Source) tmpPainter.drawPixmap(QPoint(radius, radius), px) tmpPainter.end() # blur the alpha channel blurred = QImage(tmp.size(), QImage.Format_ARGB32_Premultiplied) blurred.fill(Qt.transparent) blurPainter = QPainter(blurred) # TODO: #qt_blurImage(blurPainter, tmp, radius, False, True) blurPainter.end() tmp = blurred # blacken the image... tmpPainter.begin(tmp) tmpPainter.setCompositionMode(QPainter.CompositionMode_SourceIn) tmpPainter.fillRect(tmp.rect(), color) tmpPainter.end() tmpPainter.begin(tmp) tmpPainter.setCompositionMode(QPainter.CompositionMode_SourceIn) tmpPainter.fillRect(tmp.rect(), color) tmpPainter.end() # draw the blurred drop shadow... cachePainter.drawImage( QRect(0, 0, cache.rect().width() / cache.devicePixelRatioF(), cache.rect().height() / cache.devicePixelRatioF()), tmp) # Draw the actual pixmap... cachePainter.drawPixmap(QPoint(radius, radius) + offset, px) if self.usePixmapCache(): QPixmapCache.insert(pixmapName, cache) sip.delete(cachePainter) sip.delete(tmpPainter) sip.delete(blurPainter) targetRect = QRect(cache.rect()) targetRect.setWidth(cache.rect().width() / cache.devicePixelRatioF()) targetRect.setHeight(cache.rect().height() / cache.devicePixelRatioF()) targetRect.moveCenter(rect.center()) painter.drawPixmap(targetRect.topLeft() - offset, cache)
def _fetch_marvin_cover(border_width=0): ''' Retrieve LargeCoverJpg from cache ''' #self._log_location('border_width: {0}'.format(border_width)) con = sqlite3.connect(self.marvin_db_path) with con: con.row_factory = sqlite3.Row # Fetch Hash from mainDb cover_cur = con.cursor() cover_cur.execute('''SELECT Hash FROM Books WHERE ID = '{0}' '''.format(self.book_id)) row = cover_cur.fetchone() book_hash = row[b'Hash'] large_covers_subpath = self.connected_device._cover_subpath( size="large") cover_path = '/'.join([large_covers_subpath, '%s.jpg' % book_hash]) stats = self.parent.ios.exists(cover_path) if stats: self._log("fetching large cover from cache") #self._log("cover size: {:,} bytes".format(int(stats['st_size']))) cover_bytes = self.parent.ios.read(cover_path, mode='rb') m_image = QImage() m_image.loadFromData(cover_bytes) if border_width: # Construct a QPixmap with oversized yellow background m_image = m_image.scaledToHeight( self.COVER_ICON_SIZE - border_width * 2, Qt.SmoothTransformation) self.m_pixmap = QPixmap( QSize(m_image.width() + border_width * 2, m_image.height() + border_width * 2)) m_painter = QPainter(self.m_pixmap) m_painter.setRenderHints(m_painter.Antialiasing) m_painter.fillRect(self.m_pixmap.rect(), self.MISMATCH_COLOR) m_painter.drawImage(border_width, border_width, m_image) else: m_image = m_image.scaledToHeight(self.COVER_ICON_SIZE, Qt.SmoothTransformation) self.m_pixmap = QPixmap( QSize(m_image.width(), m_image.height())) m_painter = QPainter(self.m_pixmap) m_painter.setRenderHints(m_painter.Antialiasing) m_painter.drawImage(0, 0, m_image) self.marvin_cover.setPixmap(self.m_pixmap) else: # No cover available, use generic self._log("No cached cover, using generic") pixmap = QPixmap() pixmap.load(I('book.png')) pixmap = pixmap.scaled(self.COVER_ICON_SIZE, self.COVER_ICON_SIZE, aspectRatioMode=Qt.KeepAspectRatio, transformMode=Qt.SmoothTransformation) self.marvin_cover.setPixmap(pixmap)
def _populate_covers(self): ''' Display calibre cover for both unless mismatch ''' def _fetch_marvin_cover(border_width=0): ''' Retrieve LargeCoverJpg from cache ''' #self._log_location('border_width: {0}'.format(border_width)) con = sqlite3.connect(self.marvin_db_path) with con: con.row_factory = sqlite3.Row # Fetch Hash from mainDb cover_cur = con.cursor() cover_cur.execute('''SELECT Hash FROM Books WHERE ID = '{0}' '''.format(self.book_id)) row = cover_cur.fetchone() book_hash = row[b'Hash'] large_covers_subpath = self.connected_device._cover_subpath( size="large") cover_path = '/'.join([large_covers_subpath, '%s.jpg' % book_hash]) stats = self.parent.ios.exists(cover_path) if stats: self._log("fetching large cover from cache") #self._log("cover size: {:,} bytes".format(int(stats['st_size']))) cover_bytes = self.parent.ios.read(cover_path, mode='rb') m_image = QImage() m_image.loadFromData(cover_bytes) if border_width: # Construct a QPixmap with oversized yellow background m_image = m_image.scaledToHeight( self.COVER_ICON_SIZE - border_width * 2, Qt.SmoothTransformation) self.m_pixmap = QPixmap( QSize(m_image.width() + border_width * 2, m_image.height() + border_width * 2)) m_painter = QPainter(self.m_pixmap) m_painter.setRenderHints(m_painter.Antialiasing) m_painter.fillRect(self.m_pixmap.rect(), self.MISMATCH_COLOR) m_painter.drawImage(border_width, border_width, m_image) else: m_image = m_image.scaledToHeight(self.COVER_ICON_SIZE, Qt.SmoothTransformation) self.m_pixmap = QPixmap( QSize(m_image.width(), m_image.height())) m_painter = QPainter(self.m_pixmap) m_painter.setRenderHints(m_painter.Antialiasing) m_painter.drawImage(0, 0, m_image) self.marvin_cover.setPixmap(self.m_pixmap) else: # No cover available, use generic self._log("No cached cover, using generic") pixmap = QPixmap() pixmap.load(I('book.png')) pixmap = pixmap.scaled(self.COVER_ICON_SIZE, self.COVER_ICON_SIZE, aspectRatioMode=Qt.KeepAspectRatio, transformMode=Qt.SmoothTransformation) self.marvin_cover.setPixmap(pixmap) self.calibre_cover.setMaximumSize( QSize(self.COVER_ICON_SIZE, self.COVER_ICON_SIZE)) self.calibre_cover.setText('') self.calibre_cover.setScaledContents(False) self.marvin_cover.setMaximumSize( QSize(self.COVER_ICON_SIZE, self.COVER_ICON_SIZE)) self.marvin_cover.setText('') self.marvin_cover.setScaledContents(False) if self.cid: db = self.opts.gui.current_db if 'cover_hash' not in self.mismatches: mi = db.get_metadata(self.cid, index_is_id=True, get_cover=True, cover_as_data=True) c_image = QImage() if mi.has_cover: c_image.loadFromData(mi.cover_data[1]) c_image = c_image.scaledToHeight(self.COVER_ICON_SIZE, Qt.SmoothTransformation) self.c_pixmap = QPixmap( QSize(c_image.width(), c_image.height())) c_painter = QPainter(self.c_pixmap) c_painter.setRenderHints(c_painter.Antialiasing) c_painter.drawImage(0, 0, c_image) else: c_image.load(I('book.png')) c_image = c_image.scaledToWidth(135, Qt.SmoothTransformation) # Construct a QPixmap with dialog background self.c_pixmap = QPixmap( QSize(c_image.width(), c_image.height())) c_painter = QPainter(self.c_pixmap) c_painter.setRenderHints(c_painter.Antialiasing) bgcolor = self.palette().color(QPalette.Background) c_painter.fillRect(self.c_pixmap.rect(), bgcolor) c_painter.drawImage(0, 0, c_image) # Set calibre cover self.calibre_cover.setPixmap(self.c_pixmap) if self.opts.prefs.get('development_mode', False): # Show individual covers _fetch_marvin_cover() else: # Show calibre cover on both sides self.marvin_cover.setPixmap(self.c_pixmap) else: # Covers don't match - render with border # Construct a QImage with the cover sized to fit inside border c_image = QImage() cdata = db.cover(self.cid, index_is_id=True) if cdata is None: c_image.load(I('book.png')) self.calibre_cover.setScaledContents(True) else: c_image.loadFromData(cdata) c_image = c_image.scaledToHeight( self.COVER_ICON_SIZE - self.BORDER_WIDTH * 2, Qt.SmoothTransformation) # Construct a QPixmap with yellow background self.c_pixmap = QPixmap( QSize(c_image.width() + self.BORDER_WIDTH * 2, c_image.height() + self.BORDER_WIDTH * 2)) c_painter = QPainter(self.c_pixmap) c_painter.setRenderHints(c_painter.Antialiasing) c_painter.fillRect(self.c_pixmap.rect(), self.MISMATCH_COLOR) c_painter.drawImage(self.BORDER_WIDTH, self.BORDER_WIDTH, c_image) self.calibre_cover.setPixmap(self.c_pixmap) # Render Marvin cover with small border if different covers, # large cover if no cover hash (loaded via OPDS) border_width = self.BORDER_WIDTH if self.mismatches['cover_hash']['Marvin'] is None: border_width = self.BORDER_WIDTH * 3 _fetch_marvin_cover(border_width=border_width) else: _fetch_marvin_cover()
def _fetch_marvin_cover(border_width=0): ''' Retrieve LargeCoverJpg from cache ''' #self._log_location('border_width: {0}'.format(border_width)) con = sqlite3.connect(self.marvin_db_path) with con: con.row_factory = sqlite3.Row # Fetch Hash from mainDb cover_cur = con.cursor() cover_cur.execute('''SELECT Hash FROM Books WHERE ID = '{0}' '''.format(self.book_id)) row = cover_cur.fetchone() book_hash = row[b'Hash'] large_covers_subpath = self.connected_device._cover_subpath(size="large") cover_path = '/'.join([large_covers_subpath, '%s.jpg' % book_hash]) stats = self.parent.ios.exists(cover_path) if stats: self._log("fetching large cover from cache") #self._log("cover size: {:,} bytes".format(int(stats['st_size']))) cover_bytes = self.parent.ios.read(cover_path, mode='rb') m_image = QImage() m_image.loadFromData(cover_bytes) if border_width: # Construct a QPixmap with oversized yellow background m_image = m_image.scaledToHeight( self.COVER_ICON_SIZE - border_width * 2, Qt.SmoothTransformation) self.m_pixmap = QPixmap( QSize(m_image.width() + border_width * 2, m_image.height() + border_width * 2)) m_painter = QPainter(self.m_pixmap) m_painter.setRenderHints(m_painter.Antialiasing) m_painter.fillRect(self.m_pixmap.rect(), self.MISMATCH_COLOR) m_painter.drawImage(border_width, border_width, m_image) else: m_image = m_image.scaledToHeight( self.COVER_ICON_SIZE, Qt.SmoothTransformation) self.m_pixmap = QPixmap( QSize(m_image.width(), m_image.height())) m_painter = QPainter(self.m_pixmap) m_painter.setRenderHints(m_painter.Antialiasing) m_painter.drawImage(0, 0, m_image) self.marvin_cover.setPixmap(self.m_pixmap) else: # No cover available, use generic self._log("No cached cover, using generic") pixmap = QPixmap() pixmap.load(I('book.png')) pixmap = pixmap.scaled(self.COVER_ICON_SIZE, self.COVER_ICON_SIZE, aspectRatioMode=Qt.KeepAspectRatio, transformMode=Qt.SmoothTransformation) self.marvin_cover.setPixmap(pixmap)
def _generate_image(self): h = 2 w = 1 def draw_char(pos, pen_color): pix_paint.setPen(QPen(pen_color)) rect = QRect(i * w + i, 1, w, h) pix_paint.drawRect(rect) pix_paint.fillRect(rect, pen_color) # range of tab: tab_default = 80 text = "m" px = QPixmap(100, 100) p = QPainter(px) fm = p.fontMetrics() width = fm.width(text) p.end() number_chars_in_one_tab = int(tab_default / width) p_text = self._prepared_text() split_p_text = p_text.split("N") pix_list = [] for text in split_p_text: line_num = 0 i = 0 length = len(text) if length == 0: length = 1 pixmap = QImage(length * w + length, h * 2, QImage.Format_ARGB32_Premultiplied) pixmap.fill(Qt.white) pix_paint = QPainter(pixmap) for char in text: if char == "c": draw_char(i, Qt.black) if char == "t": for _ in range(0, number_chars_in_one_tab): draw_char(i, Qt.transparent) i += 1 if char == "_": draw_char(i, Qt.transparent) i += 1 pix_list.append(pixmap) line_num += 1 pix_paint.end() # find max width: width_list = [pix.width() for pix in pix_list] max_width = max(width_list) image = QImage(max_width, pix_list[0].height() * len(pix_list), QImage.Format_ARGB32_Premultiplied) image.fill(Qt.white) painter = QPainter(image) for pix in pix_list: y = pix_list[0].height() * pix_list.index(pix) painter.drawImage(0, y, pix) painter.end() return image
def run(self): time.sleep(0.5) # create hash dict of current list self._hash_item_dict = {} for item in self._item_list: self._hash_item_dict[item.hash] = item # compare and swap between lists if new item is not generated for new_hash in self._hash_item_dict.keys(): if new_hash in self._old_hash_item_dict.keys(): # swap to avoid generating uselessly : self._hash_item_dict[new_hash] = self._old_hash_item_dict[ new_hash] else: # generate _ = self._hash_item_dict[new_hash].image # append generated images # images_list.append() pix_list = [] for new_item in self._item_list: usable_item = self._hash_item_dict[new_item.hash] pix_list.append(usable_item.image) # draw pixmaps in one : image = QImage(20, 20, QImage.Format_ARGB32_Premultiplied) image.fill(Qt.white) point = QPoint(0, 0) width_list = [pix.width() for pix in pix_list] max_width = max(width_list) self._max_width_found = max([max_width, self._max_width_found]) for pix in pix_list: last_image = image image = QImage(self._max_width_found, image.height() + pix.height(), QImage.Format_ARGB32_Premultiplied) pix_paint = QPainter(image) image.fill(Qt.white) pix_paint.drawImage(0, 0, last_image) pix_paint.drawImage(point, pix) point = QPoint(0, point.y() + pix.height()) pix_paint.end() ''' pixmap = QImage(21,21, QImage.Format_ARGB32_Premultiplied) # temp pixPaint = QPainter(pixmap) myPen = QPen( Qt.black) pixPaint.setPen(myPen) pixPaint.drawRect(0,0, 20,20); pixPaint.end() image = pixmap painter.drawImage(point, pix) point = QPoint(0, point.y() + pix.height()) painter.end() ''' final_pixmap = QPixmap.fromImage(image, Qt.AutoColor) self.image_generated.emit(final_pixmap) self._old_item_list = self._item_list self._old_hash_item_dict = self._hash_item_dict
def _generate_image(self): h = 2 w = 1 def draw_char(pos, pen_color): pix_paint.setPen(QPen(pen_color)) rect = QRect(i * w + i, 1, w, h) pix_paint.drawRect(rect) pix_paint.fillRect(rect, pen_color) # range of tab: tab_default = 80 text = "m" px = QPixmap(100, 100) p = QPainter(px) fm = p.fontMetrics() width = fm.width(text) p.end() number_chars_in_one_tab = int(tab_default / width) p_text = self._prepared_text() split_p_text = p_text.split("N") pix_list = [] for text in split_p_text: line_num = 0 i = 0 length = len(text) if length == 0: length = 1 pixmap = QImage( length * w + length, h * 2, QImage.Format_ARGB32_Premultiplied) pixmap.fill(Qt.white) pix_paint = QPainter(pixmap) for char in text: if char == "c": draw_char(i, Qt.black) if char == "t": for _ in range(0, number_chars_in_one_tab): draw_char(i, Qt.transparent) i += 1 if char == "_": draw_char(i, Qt.transparent) i += 1 pix_list.append(pixmap) line_num += 1 pix_paint.end() # find max width: width_list = [pix.width() for pix in pix_list] max_width = max(width_list) image = QImage(max_width, pix_list[ 0].height() * len(pix_list), QImage.Format_ARGB32_Premultiplied) image.fill(Qt.white) painter = QPainter(image) for pix in pix_list: y = pix_list[0].height() * pix_list.index(pix) painter.drawImage(0, y, pix) painter.end() return image