def get_indexed(data, w, h, colors=256, crop=True): palette = data[:colors * 4] table = [] for i in range(colors): b = palette[(i * 4) + 0] g = palette[(i * 4) + 1] r = palette[(i * 4) + 2] a = palette[(i * 4) + 3] table.append(qRgba(r, g, b, a)) img_start = colors * 4 mask_start = img_start + (w * h) image = data[img_start:mask_start] image = QImage(image, w, h, QImage.Format_Indexed8) image.setColorTable(table) image = image.convertToFormat(QImage.Format_ARGB32) mask = data[mask_start:] for i in range(len(mask)): x = i % w y = i / w pixel = image.pixel(x, y) pixel = qRgba(qRed(pixel), qGreen(pixel), qBlue(pixel), mask[i]) image.setPixel(x, y, pixel) if crop: image = image.copy(0, 0, w - 2, h - 2) return image, len(mask) > 0
def createImg(data): img = QImage(WIDTH, HEIGHT, QImage.Format_ARGB32_Premultiplied) for i in range(WIDTH): fore = qRgba(255, 255, 255, 255) foreInside = qRgba(127, 127, 127, 127) back = qRgba(0, 0, 0, 0) for j in range(HEIGHT): if data[i][0] <= j < data[i][1]: img.setPixel(i, j, fore) if data[i][1] <= j < data[i][2]: img.setPixel(i, j, foreInside) if data[i][2] <= j < data[i][3]: img.setPixel(i, j, fore) img.save('wave.png', 'png')
def createImg(data): img = QImage(WIDTH, HEIGHT, QImage.Format_ARGB32_Premultiplied) for i in range(WIDTH): fore = qRgba(255, 255, 255,255) foreInside = qRgba(127, 127, 127,127) back = qRgba(0, 0, 0, 0) for j in range(HEIGHT): if data[i][0] <= j < data[i][1]: img.setPixel(i, j, fore) if data[i][1] <= j < data[i][2]: img.setPixel(i, j, foreInside) if data[i][2] <= j < data[i][3]: img.setPixel(i, j, fore) img.save('wave.png', 'png')
def convert_shtx_8bit(data): width = to_u16(data[0:2]) height = to_u16(data[2:4]) unk = to_u16(data[4:6]) p = 6 palette = [] for i in range(256): palette.append(qRgba(data[p], data[p + 1], data[p + 2], data[p + 3])) p += 4 # For some reason, a couple images have blank palettes and are actually RGBA images. if not palette == [0L] * 256: pixels = data[p : p + (width * height)] img = QImage(pixels, width, height, QImage.Format_Indexed8) img.setColorTable(palette) else: pixels = data[p:] height = len(pixels) / width / 4 img = QImage(pixels, width, height, QImage.Format_ARGB32) return img
def render(self,fname): contentsSize = self.contentFrame.contentsSize() contentsSize -= QSize(self.m_scrollPosition.x(), self.m_scrollPosition.y()) frameRect = QRect(QPoint(0, 0), contentsSize) #if not self.m_clipRect.isEmpty(): # frameRect = self.m_clipRect viewportSize = self.contentPage.viewportSize() self.contentPage.setViewportSize(contentsSize) image = QImage(frameRect.size(), QImage.Format_ARGB32) image.fill(qRgba(255, 255, 255, 0)) painter = QPainter() # We use tiling approach to work-around Qt software rasterizer bug # when dealing with very large paint device. # See http://code.google.com/p/phantomjs/issues/detail?id=54. tileSize = 4096 htiles = (image.width() + tileSize - 1) / tileSize vtiles = (image.height() + tileSize - 1) / tileSize for x in range(htiles): for y in range(vtiles): tileBuffer = QImage(tileSize, tileSize, QImage.Format_ARGB32) tileBuffer.fill(qRgba(255, 255, 255, 0)) # Render the web page onto the small tile first painter.begin(tileBuffer) painter.setRenderHint(QPainter.Antialiasing, True) painter.setRenderHint(QPainter.TextAntialiasing, True) painter.setRenderHint(QPainter.SmoothPixmapTransform, True) painter.translate(-frameRect.left(), -frameRect.top()) painter.translate(-x * tileSize, -y * tileSize) self.contentFrame.render(painter, QRegion(frameRect)) painter.end() # Copy the tile to the main buffer painter.begin(image) painter.setCompositionMode(QPainter.CompositionMode_Source) painter.drawImage(x * tileSize, y * tileSize, tileBuffer) painter.end() self.contentPage.setViewportSize(viewportSize) image.save(fname) return True
def init_draw_mask(self, draw_mask, grid): mask_points = [] mask_iconlabel = [] for mask, label in draw_mask: w, h = mask.shape xx, yy = mask.nonzero() mask_points.append((xx - w / 2, yy - h / 2)) img = QImage(w, h, QImage.Format_ARGB32) img.fill(qRgba(255, 255, 255, 0)) for ii in range(xx.shape[0]): img.setPixel(xx[ii], yy[ii], qRgba(0, 0, 0, 255)) img = img.scaled(QSize(w * grid[0], h * grid[1])) icon = QIcon(QPixmap.fromImage(img)) mask_iconlabel.append((icon, label)) return mask_points, mask_iconlabel
def init_draw_mask(self, draw_mask, grid): mask_points = [] mask_iconlabel = [] for mask, label in draw_mask: w, h = mask.shape xx, yy = mask.nonzero() mask_points.append((xx - w/2, yy - h/2)) img = QImage(w, h, QImage.Format_ARGB32) img.fill(qRgba(255, 255, 255, 0)) for ii in range(xx.shape[0]): img.setPixel(xx[ii], yy[ii], qRgba(0, 0, 0, 255)) img = img.scaled(QSize(w * grid[0], h * grid[1])) icon = QIcon(QPixmap.fromImage(img)) mask_iconlabel.append((icon, label)) return mask_points, mask_iconlabel
def toGray(image): w, h = (image.width(), image.height()) for x in xrange(w): for y in xrange(h): pixel = image.pixel(x, y) gray = qGray(pixel) alpha = qAlpha(pixel) image.setPixel(x, y, qRgba(gray, gray, gray, alpha)) return image
def renderImage(self): contentsSize = self.m_mainFrame.contentsSize() contentsSize -= QSize(self.m_scrollPosition.x(), self.m_scrollPosition.y()) frameRect = QRect(QPoint(0, 0), contentsSize) if not self.m_clipRect.isEmpty(): frameRect = self.m_clipRect viewportSize = self.m_webPage.viewportSize() self.m_webPage.setViewportSize(contentsSize) image = QImage(frameRect.size(), QImage.Format_ARGB32) image.fill(qRgba(255, 255, 255, 0)) painter = QPainter() # We use tiling approach to work-around Qt software rasterizer bug # when dealing with very large paint device. # See http://code.google.com/p/phantomjs/issues/detail?id=54. tileSize = 4096 htiles = (image.width() + tileSize - 1) / tileSize vtiles = (image.height() + tileSize - 1) / tileSize for x in range(htiles): for y in range(vtiles): tileBuffer = QImage(tileSize, tileSize, QImage.Format_ARGB32) tileBuffer.fill(qRgba(255, 255, 255, 0)) # Render the web page onto the small tile first painter.begin(tileBuffer) painter.setRenderHint(QPainter.Antialiasing, True) painter.setRenderHint(QPainter.TextAntialiasing, True) painter.setRenderHint(QPainter.SmoothPixmapTransform, True) painter.translate(-frameRect.left(), -frameRect.top()) painter.translate(-x * tileSize, -y * tileSize) self.m_mainFrame.render(painter, QRegion(frameRect)) painter.end() # Copy the tile to the main buffer painter.begin(image) painter.setCompositionMode(QPainter.CompositionMode_Source) painter.drawImage(x * tileSize, y * tileSize, tileBuffer) painter.end() self.m_webPage.setViewportSize(viewportSize) return image
def blit(src, dst, x, y, masked): w = src.width() h = src.height() out = dst.copy() for i in range(w): for j in range(h): dst_pixel = dst.pixel(x + i, y + j) src_pixel = src.pixel(i, j) # If src has transparency data, we use it, otherwise, we borrow from dst. # This logic doesn't quite work for bustup/l/si4? if masked or dst_pixel == TRANSPARENT_COLOR: out_pixel = src_pixel else: out_pixel = qRgba(qRed(src_pixel), qGreen(src_pixel), qBlue(src_pixel), qAlpha(dst_pixel)) out.setPixel(x + i, y + j, out_pixel) return out
def render(self, fileName): fileInfo = QFileInfo(fileName) path = QDir() path.mkpath(fileInfo.absolutePath()) if fileName.lower().endswith('.pdf'): return self.renderPdf(fileName) viewportSize = QSize(self.m_page.viewportSize()) pageSize = QSize(self.m_page.mainFrame().contentsSize()) bufferSize = QSize() if not self.m_clipRect.isEmpty(): bufferSize = self.m_clipRect.size() else: bufferSize = self.m_page.mainFrame().contentsSize() if pageSize == '': return False image = QImage(bufferSize, QImage.Format_ARGB32) image.fill(qRgba(255, 255, 255, 0)) p = QPainter(image) p.setRenderHint(QPainter.Antialiasing, True) p.setRenderHint(QPainter.TextAntialiasing, True) p.setRenderHint(QPainter.SmoothPixmapTransform, True) self.m_page.setViewportSize(pageSize) if not self.m_clipRect.isEmpty(): p.translate(-self.m_clipRect.left(), -self.m_clipRect.top()) self.m_page.mainFrame().render(p, QRegion(self.m_clipRect)) else: self.m_page.mainFrame().render(p) p.end() self.m_page.setViewportSize(viewportSize) return image.save(fileName)
def convert_shtx_4bit(data): width = to_u16(data[0:2]) height = to_u16(data[2:4]) unk = data[4:12] p = 12 palette = [] for i in range(16): palette.append(qRgba(data[p], data[p + 1], data[p + 2], data[p + 3])) p += 4 pixels = data[p : p + (width * height / 2)] pixels2 = bytearray() for b in pixels: pixels2.append(b & 0x0F) pixels2.append(b >> 4) img = QImage(pixels2, width, height, QImage.Format_Indexed8) img.setColorTable(palette) return img
def drawIconWithShadow(cls, icon, rect, painter, iconMode, dipRadius=3, color=QColor(0, 0, 0, 130), dipOffset=QPoint(1, -2)): """ :type icon: QIcon :type rect: QRect :type painter: QPainter :type iconMode: QIcon.Mode :type dipRadius: int :type color: QColor :type dipOffset: QPoint """ cache = QPixmap() pixmapName = "icon {0} {1} {2}".format(icon.cacheKey(), iconMode, rect.height()) if not QPixmapCache.find(pixmapName, cache): # High-dpi support: The in parameters (rect, radius, offset) are in # device-independent pixels. The call to QIcon.pixmap() below might # return a high-dpi pixmap, which will in that case have a devicePixelRatio # different than 1. The shadow drawing calculations are done in device # pixels. from math import ceil px = icon.pixmap(rect.size()) devicePixelRatio = int(ceil(cls.pixmapDevicePixelRatio(px))) radius = dipRadius * devicePixelRatio offset = dipOffset * devicePixelRatio # result = QPoint, like dipOffset cache = QPixmap(px.size() + QSize(radius * 2, radius * 2)) cache.fill(Qt.transparent) cachePainter = QPainter(cache) if iconMode == QIcon.Disabled: im = px.toImage().convertToFormat(QImage.Format_ARGB32) for y in range(0, im.height()): scanLine = abs(im.scanLine(y)) for x in range(0, im.width()): pixel = scanLine intensity = qGray(pixel) scanLine = qRgba(intensity, intensity, intensity, qAlpha(pixel)) scanLine += 1 px = QPixmap.fromImage(im) # Draw shadow tmp = QImage(px.size() + QSize(radius * 2, radius * 2 + 1), QImage.Format_ARGB32_Premultiplied) tmp.fill(Qt.transparent) tmpPainter = QPainter(tmp) tmpPainter.setCompositionMode(QPainter.CompositionMode_Source) tmpPainter.drawPixmap(QRect(radius, radius, px.width(), px.height()), px) tmpPainter.end() # blur the alpha channel blurred = QImage(tmp.size(), QImage.Format_ARGB32_Premultiplied) blurred.fill(Qt.transparent) blurPainter = QPainter(blurred) # qt_blurImage is not available in PyQt4, skip it # 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.rect().height()), tmp) # Draw the actual pixmap... cachePainter.drawPixmap(QRect(QPoint(radius, radius) + offset, QSize(px.width(), px.height())), px) import PyQt4 if StrictVersion(PyQt4.QtCore.__version__).version[0] == 5: cache.setDevicePixelRatio(devicePixelRatio) QPixmapCache.insert(pixmapName, cache) targetRect = cache.rect() targetRect.setSize(targetRect.size() / cls.pixmapDevicePixelRatio(cache)) targetRect.moveCenter(rect.center() - dipOffset) painter.drawPixmap(targetRect, cache)
def rgba(r, g, b, a=255): if PYQT_VERSION <= 263172: return (qRgba(r, g, b, a) & 0xffffff) - 0x1000000 return qRgba(r, g, b, a)
def renderer(self): qgis = QgsApplication([], False) qgis.setPrefixPath(self.settings.get('path'), True) qgis.setMaxThreads(1) qgis.initQgis() while True: try: fndata, srs, render_size, extended, \ target_box, result = self.queue.get() layer = QgsVectorLayer(fndata, 'layer', 'ogr') crs = QgsCoordinateReferenceSystem(srs.id) layer.setCrs(crs) settings = QgsMapSettings() settings.setLayers([layer.id()]) settings.setFlag(QgsMapSettings.DrawLabeling) settings.setFlag(QgsMapSettings.Antialiasing) settings.setCrsTransformEnabled(True) settings.setDestinationCrs(crs) settings.setMapUnits(crs.mapUnits()) settings.setOutputSize(QSize(*render_size)) settings.setExtent(QgsRectangle(*extended)) settings.setOutputImageFormat(QImage.Format_ARGB32) bgcolor = QColor.fromRgba(qRgba(255, 255, 255, 0)) settings.setBackgroundColor(bgcolor) settings.setOutputDpi(96) QgsMapLayerRegistry.instance().addMapLayer(layer) settings.setLayers([layer.id()]) # Создаем QImage руками чтобы можно было использовать # QgsMapRendererCustomPainterJob. Остальные не позволяют # обойти баг с рисованием поверх старого. img = QImage(settings.outputSize(), QImage.Format_ARGB32) # Эти костыли нужны для того, чтобы корректно рисовались # слои на прозрачном фоне, без этого получается каша. img.fill(QColor.fromRgba(qRgba(255, 255, 255, 255))) img.fill(QColor.fromRgba(qRgba(255, 255, 255, 0))) # DPI должно быть таким же как в settings, иначе ошибка. В QImage # разрешение указывается в точках на метр по каждой оси. dpm = settings.outputDpi() / 25.4 * 1000 img.setDotsPerMeterX(dpm) img.setDotsPerMeterY(dpm) painter = QPainter(img) job = QgsMapRendererCustomPainterJob(settings, painter) job.renderSynchronously() painter.end() QgsMapLayerRegistry.instance().removeAllMapLayers() # Преобразование QImage в PIL ba = QByteArray() bf = QBuffer(ba) bf.open(QIODevice.WriteOnly) img.save(bf, 'PNG') bf.close() buf = StringIO() buf.write(bf.data()) buf.seek(0) img = PIL.Image.open(buf) # Вырезаем нужный нам кусок изображения result.put(img.crop(target_box)) except Exception as e: self.logger.error(e.message) qgis.exitQgis()
def renderer(self): if 'QGIS_AUTH_DB_DIR_PATH' not in os.environ: os.environ['QGIS_AUTH_DB_DIR_PATH'] = '/tmp' qgis = None while True: options, result = self.queue.get() # Don't start QGIS until first request if qgis is None: qgis = QgsApplication([], False) qgis.setPrefixPath(self.settings.get('path'), True) qgis.setDefaultSvgPaths(qgis.svgPaths() + self.settings.get('svgpaths')) qgis.setMaxThreads(1) qgis.initQgis() try: if isinstance(options, LegendOptions): style, = options layer = self._qgs_memory_layer(style) layer.setName(style.parent.display_name) QgsMapLayerRegistry.instance().addMapLayer(layer) root = QgsLayerTreeGroup() root.addLayer(layer) # 'Cannot create a QPixmap when no GUI is being used' # warning occurs here model = QgsLayerTreeModel(root) settings = QgsLegendSettings() settings.setTitle('') settings.setBoxSpace(1) settings.setSymbolSize(QSizeF(5, 3)) settings.setDpi(96) renderer = QgsLegendRenderer(model, settings) # Dots per mm dpmm = settings.dpi() / 25.4 min_size = renderer.minimumSize() size = QSize(dpmm * min_size.width(), dpmm * min_size.height()) img = QImage(size, QImage.Format_ARGB32) img.fill(QColor(0, 0, 0, 0)) painter = QPainter() painter.begin(img) painter.scale(dpmm, dpmm) renderer.drawLegend(painter) painter.end() QgsMapLayerRegistry.instance().removeAllMapLayers() ba = QByteArray() bf = QBuffer(ba) bf.open(QIODevice.WriteOnly) img.save(bf, 'PNG') bf.close() buf = StringIO() buf.write(bf.data()) buf.seek(0) result.put(buf) else: path = features = None if isinstance(options, VectorRenderOptions): style, features, render_size, \ extended, target_box = options layer = self._qgs_memory_layer(style, features=features) elif isinstance(options, RasterRenderOptions): style, path, render_size, \ extended, target_box = options layer = QgsRasterLayer(path) layer.loadNamedStyle( self.env.file_storage.filename(style.qml_fileobj)) settings = QgsMapSettings() settings.setLayers([layer.id()]) settings.setFlag(QgsMapSettings.DrawLabeling) settings.setFlag(QgsMapSettings.Antialiasing) settings.setCrsTransformEnabled(True) settings.setDestinationCrs(layer.crs()) settings.setMapUnits(layer.crs().mapUnits()) settings.setOutputSize(QSize(*render_size)) settings.setExtent(QgsRectangle(*extended)) settings.setOutputImageFormat(QImage.Format_ARGB32) bgcolor = QColor.fromRgba(qRgba(255, 255, 255, 0)) settings.setBackgroundColor(bgcolor) settings.setOutputDpi(96) QgsMapLayerRegistry.instance().addMapLayer(layer) settings.setLayers([layer.id()]) # Create QImage by hand to be able to use # QgsMapRendererCustomPainterJob. Others will not # allow to workaround a bug with overlay rendering. img = QImage(settings.outputSize(), QImage.Format_ARGB32) # These cludges are needed for rendering # on transparent background, otherwise it's a mess. img.fill(QColor.fromRgba(qRgba(255, 255, 255, 255))) img.fill(QColor.fromRgba(qRgba(255, 255, 255, 0))) # DPI should be equal to settings, otherwise an error. # In QImage the resolution is set in dots per meter # for each axis. dpm = settings.outputDpi() / 25.4 * 1000 img.setDotsPerMeterX(dpm) img.setDotsPerMeterY(dpm) painter = QPainter(img) job = QgsMapRendererCustomPainterJob(settings, painter) job.renderSynchronously() painter.end() QgsMapLayerRegistry.instance().removeAllMapLayers() img = self._qimage_to_pil(img) # Clip needed part result.put(img.crop(target_box)) # Cleanup if path is not None: gdal.Unlink(path) except Exception as exc: self.logger.error(exc.message) result.put(exc) qgis.exitQgis()