def icon_to_dbus_menu_icon(icon, size=32): if icon.isNull(): return None ba = QByteArray() buf = QBuffer(ba) buf.open(QIODevice.OpenModeFlag.WriteOnly) icon.pixmap(32).save(buf, 'PNG') return dbus.ByteArray(ba)
def image_and_format_from_data(data): ' Create an image object from the specified data which should be a bytestring and also return the format of the image ' ba = QByteArray(data) buf = QBuffer(ba) buf.open(QIODevice.OpenModeFlag.ReadOnly) r = QImageReader(buf) fmt = bytes(r.format()).decode('utf-8') return r.read(), fmt
def to_png(bmp): from qt.core import QImage, QByteArray, QBuffer, QIODevice i = QImage() if not i.loadFromData(bmp): raise ValueError('Invalid image data') ba = QByteArray() buf = QBuffer(ba) buf.open(QIODevice.OpenModeFlag.WriteOnly) i.save(buf, 'png') return ba.data()
def send_reply(rq, mime_type, data): if sip.isdeleted(rq): return # make the buf a child of rq so that it is automatically deleted when # rq is deleted buf = QBuffer(parent=rq) buf.open(QIODevice.OpenModeFlag.WriteOnly) # we have to copy data into buf as it will be garbage # collected by python buf.write(data) buf.seek(0) buf.close() rq.reply(mime_type.encode('ascii'), buf)
def rasterize_svg(self, elem, width=0, height=0, format='PNG'): view_box = elem.get('viewBox', elem.get('viewbox', None)) sizes = None logger = self.oeb.logger if view_box is not None: try: box = [ float(x) for x in filter(None, re.split('[, ]', view_box)) ] sizes = [box[2] - box[0], box[3] - box[1]] except (TypeError, ValueError, IndexError): logger.warn( 'SVG image has invalid viewBox="%s", ignoring the viewBox' % view_box) else: for image in elem.xpath( 'descendant::*[local-name()="image" and ' '@height and contains(@height, "%")]'): logger.info( 'Found SVG image height in %, trying to convert...') try: h = float(image.get('height').replace('%', '')) / 100. image.set('height', str(h * sizes[1])) except: logger.exception( 'Failed to convert percentage height:', image.get('height')) data = QByteArray(xml2str(elem, with_tail=False)) svg = QSvgRenderer(data) size = svg.defaultSize() if size.width() == 100 and size.height() == 100 and sizes: size.setWidth(sizes[0]) size.setHeight(sizes[1]) if width or height: size.scale(int(width), int(height), Qt.AspectRatioMode.KeepAspectRatio) logger.info('Rasterizing %r to %dx%d' % (elem, size.width(), size.height())) image = QImage(size, QImage.Format.Format_ARGB32_Premultiplied) image.fill(QColor("white").rgb()) painter = QPainter(image) svg.render(painter) painter.end() array = QByteArray() buffer = QBuffer(array) buffer.open(QIODevice.OpenModeFlag.WriteOnly) image.save(buffer, format) return array.data()
def encode_jpeg(file_path, quality=80): from calibre.utils.speedups import ReadOnlyFileBuffer quality = max(0, min(100, int(quality))) exe = get_exe_path('cjpeg') cmd = [exe] + '-optimize -progressive -maxmemory 100M -quality'.split() + [str(quality)] img = QImage() if not img.load(file_path): raise ValueError('%s is not a valid image file' % file_path) ba = QByteArray() buf = QBuffer(ba) buf.open(QIODevice.OpenModeFlag.WriteOnly) if not img.save(buf, 'PPM'): raise ValueError('Failed to export image to PPM') return run_optimizer(file_path, cmd, as_filter=True, input_data=ReadOnlyFileBuffer(ba.data()))
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.GlobalColor.black).rgba() and img.colorTable().at(1) == QColor(Qt.GlobalColor.white).rgba()): if fmt == QImage.Format.Format_MonoLSB: image = image.convertToFormat(QImage.Format.Format_Mono) fmt = QImage.Format.Format_Mono else: if (fmt != QImage.Format.Format_RGB32 and fmt != QImage.Format.Format_ARGB32): image = image.convertToFormat(QImage.Format.Format_ARGB32) fmt = QImage.Format.Format_ARGB32 w = image.width() h = image.height() d = image.depth() if fmt == QImage.Format.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.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.Format_ARGB32_Premultiplied) background.fill(Qt.GlobalColor.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 image_to_data(img, compression_quality=95, fmt='JPEG', png_compression_level=9, jpeg_optimized=True, jpeg_progressive=False): ''' Serialize image to bytestring in the specified format. :param compression_quality: is for JPEG and goes from 0 to 100. 100 being lowest compression, highest image quality :param png_compression_level: is for PNG and goes from 0-9. 9 being highest compression. :param jpeg_optimized: Turns on the 'optimize' option for libjpeg which losslessly reduce file size :param jpeg_progressive: Turns on the 'progressive scan' option for libjpeg which allows JPEG images to be downloaded in streaming fashion ''' fmt = fmt.upper() ba = QByteArray() buf = QBuffer(ba) buf.open(QIODevice.OpenModeFlag.WriteOnly) if fmt == 'GIF': w = QImageWriter(buf, b'PNG') w.setQuality(90) if not w.write(img): raise ValueError('Failed to export image as ' + fmt + ' with error: ' + w.errorString()) return png_data_to_gif_data(ba.data()) is_jpeg = fmt in ('JPG', 'JPEG') w = QImageWriter(buf, fmt.encode('ascii')) if is_jpeg: if img.hasAlphaChannel(): img = blend_image(img) # QImageWriter only gained the following options in Qt 5.5 if jpeg_optimized: w.setOptimizedWrite(True) if jpeg_progressive: w.setProgressiveScanWrite(True) w.setQuality(compression_quality) elif fmt == 'PNG': cl = min(9, max(0, png_compression_level)) w.setQuality(10 * (9 - cl)) if not w.write(img): raise ValueError('Failed to export image as ' + fmt + ' with error: ' + w.errorString()) return ba.data()
def rasterize_external(self, elem, style, item, svgitem): width = style['width'] height = style['height'] width = (width / 72) * self.profile.dpi height = (height / 72) * self.profile.dpi data = QByteArray(svgitem.bytes_representation) svg = QSvgRenderer(data) size = svg.defaultSize() size.scale(width, height, Qt.AspectRatioMode.KeepAspectRatio) key = (svgitem.href, size.width(), size.height()) if key in self.images: href = self.images[key] else: logger = self.oeb.logger logger.info('Rasterizing %r to %dx%d' % (svgitem.href, size.width(), size.height())) image = QImage(size, QImage.Format.Format_ARGB32_Premultiplied) image.fill(QColor("white").rgb()) painter = QPainter(image) svg.render(painter) painter.end() array = QByteArray() buffer = QBuffer(array) buffer.open(QIODevice.OpenModeFlag.WriteOnly) image.save(buffer, 'PNG') data = array.data() manifest = self.oeb.manifest href = os.path.splitext(svgitem.href)[0] + '.png' id, href = manifest.generate(svgitem.id, href) manifest.add(id, href, PNG_MIME, data=data) self.images[key] = href elem.tag = XHTML('img') for attr in elem.attrib: if attr not in KEEP_ATTRS: del elem.attrib[attr] elem.attrib['src'] = item.relhref(href) if elem.text: elem.attrib['alt'] = elem.text elem.text = None for child in elem: elem.remove(child)
def image_to_data(image): # {{{ ba = QByteArray() buf = QBuffer(ba) buf.open(QIODevice.OpenModeFlag.WriteOnly) if not image.save(buf, CACHE_FORMAT): raise EncodeError('Failed to encode thumbnail') ret = ba.data() buf.close() return ret
def pixmap_to_data(pixmap): ba = QByteArray() buf = QBuffer(ba) buf.open(QIODevice.OpenModeFlag.WriteOnly) pixmap.save(buf, 'PNG') return bytearray(ba.data())