void QgsMapRenderer::render( QPainter* painter, double* forceWidthScale ) { //Lock render method for concurrent threads (e.g. from globe) QMutexLocker renderLock( &mRenderMutex ); //flag to see if the render context has changed //since the last time we rendered. If it hasnt changed we can //take some shortcuts with rendering bool mySameAsLastFlag = true; QgsDebugMsg( "========== Rendering ==========" ); if ( mExtent.isEmpty() ) { QgsDebugMsg( "empty extent... not rendering" ); return; } if ( mSize.width() == 1 && mSize.height() == 1 ) { QgsDebugMsg( "size 1x1... not rendering" ); return; } QPaintDevice* thePaintDevice = painter->device(); if ( !thePaintDevice ) { return; } // wait if ( mDrawing ) { QgsDebugMsg( "already rendering" ); QCoreApplication::processEvents(); } if ( mDrawing ) { QgsDebugMsg( "still rendering - skipping" ); return; } mDrawing = true; QgsCoordinateTransform* ct; #ifdef QGISDEBUG QgsDebugMsg( "Starting to render layer stack." ); QTime renderTime; renderTime.start(); #endif if ( mOverview ) mRenderContext.setDrawEditingInformation( !mOverview ); mRenderContext.setPainter( painter ); mRenderContext.setCoordinateTransform( 0 ); //this flag is only for stopping during the current rendering progress, //so must be false at every new render operation mRenderContext.setRenderingStopped( false ); //calculate scale factor //use the specified dpi and not those from the paint device //because sometimes QPainter units are in a local coord sys (e.g. in case of QGraphicsScene) double sceneDpi = mScaleCalculator->dpi(); double scaleFactor = 1.0; if ( mOutputUnits == QgsMapRenderer::Millimeters ) { if ( forceWidthScale ) { scaleFactor = *forceWidthScale; } else { scaleFactor = sceneDpi / 25.4; } } double rasterScaleFactor = ( thePaintDevice->logicalDpiX() + thePaintDevice->logicalDpiY() ) / 2.0 / sceneDpi; if ( mRenderContext.rasterScaleFactor() != rasterScaleFactor ) { mRenderContext.setRasterScaleFactor( rasterScaleFactor ); mySameAsLastFlag = false; } if ( mRenderContext.scaleFactor() != scaleFactor ) { mRenderContext.setScaleFactor( scaleFactor ); mySameAsLastFlag = false; } if ( mRenderContext.rendererScale() != mScale ) { //add map scale to render context mRenderContext.setRendererScale( mScale ); mySameAsLastFlag = false; } if ( mLastExtent != mExtent ) { mLastExtent = mExtent; mySameAsLastFlag = false; } mRenderContext.setLabelingEngine( mLabelingEngine ); if ( mLabelingEngine ) mLabelingEngine->init( this ); // know we know if this render is just a repeat of the last time, we // can clear caches if it has changed if ( !mySameAsLastFlag ) { //clear the cache pixmap if we changed resolution / extent QSettings mySettings; if ( mySettings.value( "/qgis/enable_render_caching", false ).toBool() ) { QgsMapLayerRegistry::instance()->clearAllLayerCaches(); } } QgsOverlayObjectPositionManager* overlayManager = overlayManagerFromSettings(); QList<QgsVectorOverlay*> allOverlayList; //list of all overlays, used to draw them after layers have been rendered // render all layers in the stack, starting at the base QListIterator<QString> li( mLayerSet ); li.toBack(); QgsRectangle r1, r2; while ( li.hasPrevious() ) { if ( mRenderContext.renderingStopped() ) { break; } // Store the painter in case we need to swap it out for the // cache painter QPainter * mypContextPainter = mRenderContext.painter(); QString layerId = li.previous(); QgsDebugMsg( "Rendering at layer item " + layerId ); // This call is supposed to cause the progress bar to // advance. However, it seems that updating the progress bar is // incompatible with having a QPainter active (the one that is // passed into this function), as Qt produces a number of errors // when try to do so. I'm (Gavin) not sure how to fix this, but // added these comments and debug statement to help others... QgsDebugMsg( "If there is a QPaintEngine error here, it is caused by an emit call" ); //emit drawingProgress(myRenderCounter++, mLayerSet.size()); QgsMapLayer *ml = QgsMapLayerRegistry::instance()->mapLayer( layerId ); if ( !ml ) { QgsDebugMsg( "Layer not found in registry!" ); continue; } QgsDebugMsg( QString( "layer %1: minscale:%2 maxscale:%3 scaledepvis:%4 extent:%5" ) .arg( ml->name() ) .arg( ml->minimumScale() ) .arg( ml->maximumScale() ) .arg( ml->hasScaleBasedVisibility() ) .arg( ml->extent().toString() ) ); if ( !ml->hasScaleBasedVisibility() || ( ml->minimumScale() <= mScale && mScale < ml->maximumScale() ) || mOverview ) { connect( ml, SIGNAL( drawingProgress( int, int ) ), this, SLOT( onDrawingProgress( int, int ) ) ); // // Now do the call to the layer that actually does // the rendering work! // bool split = false; if ( hasCrsTransformEnabled() ) { r1 = mExtent; split = splitLayersExtent( ml, r1, r2 ); ct = new QgsCoordinateTransform( ml->crs(), *mDestCRS ); mRenderContext.setExtent( r1 ); QgsDebugMsg( " extent 1: " + r1.toString() ); QgsDebugMsg( " extent 2: " + r2.toString() ); if ( !r1.isFinite() || !r2.isFinite() ) //there was a problem transforming the extent. Skip the layer { continue; } } else { ct = NULL; } mRenderContext.setCoordinateTransform( ct ); //decide if we have to scale the raster //this is necessary in case QGraphicsScene is used bool scaleRaster = false; QgsMapToPixel rasterMapToPixel; QgsMapToPixel bk_mapToPixel; if ( ml->type() == QgsMapLayer::RasterLayer && qAbs( rasterScaleFactor - 1.0 ) > 0.000001 ) { scaleRaster = true; } //create overlay objects for features within the view extent if ( ml->type() == QgsMapLayer::VectorLayer && overlayManager ) { QgsVectorLayer* vl = qobject_cast<QgsVectorLayer *>( ml ); if ( vl ) { QList<QgsVectorOverlay*> thisLayerOverlayList; vl->vectorOverlays( thisLayerOverlayList ); QList<QgsVectorOverlay*>::iterator overlayIt = thisLayerOverlayList.begin(); for ( ; overlayIt != thisLayerOverlayList.end(); ++overlayIt ) { if (( *overlayIt )->displayFlag() ) { ( *overlayIt )->createOverlayObjects( mRenderContext ); allOverlayList.push_back( *overlayIt ); } } overlayManager->addLayer( vl, thisLayerOverlayList ); } } // Force render of layers that are being edited // or if there's a labeling engine that needs the layer to register features if ( ml->type() == QgsMapLayer::VectorLayer ) { QgsVectorLayer* vl = qobject_cast<QgsVectorLayer *>( ml ); if ( vl->isEditable() || ( mRenderContext.labelingEngine() && mRenderContext.labelingEngine()->willUseLayer( vl ) ) ) { ml->setCacheImage( 0 ); } } QSettings mySettings; if ( ! split )//render caching does not yet cater for split extents { if ( mySettings.value( "/qgis/enable_render_caching", false ).toBool() ) { if ( !mySameAsLastFlag || ml->cacheImage() == 0 ) { QgsDebugMsg( "Caching enabled but layer redraw forced by extent change or empty cache" ); QImage * mypImage = new QImage( mRenderContext.painter()->device()->width(), mRenderContext.painter()->device()->height(), QImage::Format_ARGB32 ); mypImage->fill( 0 ); ml->setCacheImage( mypImage ); //no need to delete the old one, maplayer does it for you QPainter * mypPainter = new QPainter( ml->cacheImage() ); // Changed to enable anti aliasing by default in QGIS 1.7 if ( mySettings.value( "/qgis/enable_anti_aliasing", true ).toBool() ) { mypPainter->setRenderHint( QPainter::Antialiasing ); } mRenderContext.setPainter( mypPainter ); } else if ( mySameAsLastFlag ) { //draw from cached image QgsDebugMsg( "Caching enabled --- drawing layer from cached image" ); mypContextPainter->drawImage( 0, 0, *( ml->cacheImage() ) ); disconnect( ml, SIGNAL( drawingProgress( int, int ) ), this, SLOT( onDrawingProgress( int, int ) ) ); //short circuit as there is nothing else to do... continue; } } } if ( scaleRaster ) { bk_mapToPixel = mRenderContext.mapToPixel(); rasterMapToPixel = mRenderContext.mapToPixel(); rasterMapToPixel.setMapUnitsPerPixel( mRenderContext.mapToPixel().mapUnitsPerPixel() / rasterScaleFactor ); rasterMapToPixel.setYMaximum( mSize.height() * rasterScaleFactor ); mRenderContext.setMapToPixel( rasterMapToPixel ); mRenderContext.painter()->save(); mRenderContext.painter()->scale( 1.0 / rasterScaleFactor, 1.0 / rasterScaleFactor ); } if ( !ml->draw( mRenderContext ) ) { emit drawError( ml ); } else { QgsDebugMsg( "Layer rendered without issues" ); } if ( split ) { mRenderContext.setExtent( r2 ); if ( !ml->draw( mRenderContext ) ) { emit drawError( ml ); } } if ( scaleRaster ) { mRenderContext.setMapToPixel( bk_mapToPixel ); mRenderContext.painter()->restore(); } if ( mySettings.value( "/qgis/enable_render_caching", false ).toBool() ) { if ( !split ) { // composite the cached image into our view and then clean up from caching // by reinstating the painter as it was swapped out for caching renders delete mRenderContext.painter(); mRenderContext.setPainter( mypContextPainter ); //draw from cached image that we created further up mypContextPainter->drawImage( 0, 0, *( ml->cacheImage() ) ); } } disconnect( ml, SIGNAL( drawingProgress( int, int ) ), this, SLOT( onDrawingProgress( int, int ) ) ); } else // layer not visible due to scale {
void ClipObject::loadCaption(QString ct, QFont cf, QColor cc, QColor chc) { m_captionText = ct; m_captionFont = cf; m_captionColor = cc; m_captionHaloColor = chc; if (m_captionText.isEmpty()) { m_captionPresent = false; return; } QFontMetrics metric(m_captionFont); int mde = metric.descent(); int fht = metric.height(); int fwd = metric.width(m_captionText)+2; //------------------- QImage bImage = QImage(fwd, fht, QImage::Format_ARGB32); bImage.fill(0); { QPainter bpainter(&bImage); // we have image as ARGB, but we want RGBA // so switch red and blue colors here itself QColor penColor(m_captionHaloColor.blue(), m_captionHaloColor.green(), m_captionHaloColor.red()); // do not use alpha(), // opacity will be modulated using clip-plane's opacity parameter bpainter.setPen(penColor); bpainter.setFont(m_captionFont); bpainter.drawText(1, fht-mde, m_captionText); uchar *dbits = new uchar[4*fht*fwd]; uchar *bits = bImage.bits(); memcpy(dbits, bits, 4*fht*fwd); for(int i=2; i<fht-2; i++) for(int j=2; j<fwd-2; j++) { for (int k=0; k<4; k++) { int sum = 0; for(int i0=-2; i0<=2; i0++) for(int j0=-2; j0<=2; j0++) sum += dbits[4*((i+i0)*fwd+(j+j0)) + k]; bits[4*(i*fwd+j) + k] = sum/25; } } delete [] dbits; } //------------------- QImage cImage = QImage(fwd, fht, QImage::Format_ARGB32); cImage.fill(0); QPainter cpainter(&cImage); // first draw the halo image cpainter.drawImage(0, 0, bImage); // we have image as ARGB, but we want RGBA // so switch red and blue colors here itself QColor penColor(m_captionColor.blue(), m_captionColor.green(), m_captionColor.red()); // do not use alpha(), // opacity will be modulated using clip-plane's opacity parameter cpainter.setPen(penColor); cpainter.setFont(m_captionFont); cpainter.drawText(1, fht-mde, m_captionText); m_textureWidth = fwd; m_textureHeight = fht; unsigned char *image = new unsigned char[4*m_textureWidth*m_textureHeight]; memcpy(image, cImage.bits(), 4*m_textureWidth*m_textureHeight); if (m_imageTex) glDeleteTextures(1, &m_imageTex); glGenTextures(1, &m_imageTex); glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_RECTANGLE_ARB, m_imageTex); glTexParameterf(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameterf(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, 4, m_textureWidth, m_textureHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, image); glDisable(GL_TEXTURE_RECTANGLE_ARB); delete [] image; clearImage(); m_captionPresent = true; }
QSizeF QgsSymbolV2LegendNode::drawSymbol( const QgsLegendSettings& settings, ItemContext* ctx, double itemHeight ) const { QgsSymbolV2* s = mItem.symbol(); if ( !s ) { return QSizeF(); } // setup temporary render context QgsRenderContext context; context.setScaleFactor( settings.dpi() / 25.4 ); context.setRendererScale( settings.mapScale() ); context.setMapToPixel( QgsMapToPixel( 1 / ( settings.mmPerMapUnit() * context.scaleFactor() ) ) ); context.setForceVectorOutput( true ); context.setPainter( ctx ? ctx->painter : 0 ); //Consider symbol size for point markers double height = settings.symbolSize().height(); double width = settings.symbolSize().width(); double size = 0; //Center small marker symbols double widthOffset = 0; double heightOffset = 0; if ( QgsMarkerSymbolV2* markerSymbol = dynamic_cast<QgsMarkerSymbolV2*>( s ) ) { // allow marker symbol to occupy bigger area if necessary size = markerSymbol->size() * QgsSymbolLayerV2Utils::lineWidthScaleFactor( context, s->outputUnit(), s->mapUnitScale() ) / context.scaleFactor(); height = size; width = size; if ( width < settings.symbolSize().width() ) { widthOffset = ( settings.symbolSize().width() - width ) / 2.0; } if ( height < settings.symbolSize().height() ) { heightOffset = ( settings.symbolSize().height() - height ) / 2.0; } } if ( ctx ) { double currentXPosition = ctx->point.x(); double currentYCoord = ctx->point.y() + ( itemHeight - settings.symbolSize().height() ) / 2; QPainter* p = ctx->painter; //setup painter scaling to dots so that raster symbology is drawn to scale double dotsPerMM = context.scaleFactor(); int opacity = 255; if ( QgsVectorLayer* vectorLayer = dynamic_cast<QgsVectorLayer*>( layerNode()->layer() ) ) opacity = 255 - ( 255 * vectorLayer->layerTransparency() / 100 ); p->save(); p->setRenderHint( QPainter::Antialiasing ); p->translate( currentXPosition + widthOffset, currentYCoord + heightOffset ); p->scale( 1.0 / dotsPerMM, 1.0 / dotsPerMM ); if ( opacity != 255 && settings.useAdvancedEffects() ) { //semi transparent layer, so need to draw symbol to an image (to flatten it first) //create image which is same size as legend rect, in case symbol bleeds outside its alloted space QSize tempImageSize( width * dotsPerMM, height * dotsPerMM ); QImage tempImage = QImage( tempImageSize, QImage::Format_ARGB32 ); tempImage.fill( Qt::transparent ); QPainter imagePainter( &tempImage ); context.setPainter( &imagePainter ); s->drawPreviewIcon( &imagePainter, tempImageSize, &context ); context.setPainter( ctx->painter ); //reduce opacity of image imagePainter.setCompositionMode( QPainter::CompositionMode_DestinationIn ); imagePainter.fillRect( tempImage.rect(), QColor( 0, 0, 0, opacity ) ); imagePainter.end(); //draw rendered symbol image p->drawImage( 0, 0, tempImage ); } else { s->drawPreviewIcon( p, QSize( width * dotsPerMM, height * dotsPerMM ), &context ); } p->restore(); } return QSizeF( qMax( width + 2 * widthOffset, ( double ) settings.symbolSize().width() ), qMax( height + 2 * heightOffset, ( double ) settings.symbolSize().height() ) ); }
bool GroundPlaneGenerator::generateGroundPlaneUnit(const QString & boardSvg, QSizeF boardImageSize, const QString & svg, QSizeF copperImageSize, QStringList & exceptions, QGraphicsItem * board, double res, const QString & color, const QString & layerName, QPointF whereToStart, double blurBy) { double bWidth, bHeight; QImage * image = generateGroundPlaneAux(boardSvg, boardImageSize, svg, copperImageSize, exceptions, board, res, bWidth, bHeight, blurBy); if (image == NULL) return false; QPoint s(qRound(res * (whereToStart.x() - board->pos().x()) / FSvgRenderer::printerScale()), qRound(res * (whereToStart.y() - board->pos().y()) / FSvgRenderer::printerScale())); QBitArray redMarker(image->height() * image->width(), false); QRgb pixel = image->pixel(s); int gray = QGRAY(pixel); if (gray <= THRESHOLD) { // starting off in bad territory delete image; return false; } // step 1 flood fill white to "red" (keep max locations) int minY = image->height(); int maxY = 0; int minX = image->width(); int maxX = 0; QList<QPoint> stack; stack << s; while (stack.count() > 0) { QPoint p = stack.takeFirst(); if (p.x() < 0) continue; if (p.y() < 0) continue; if (p.x() >= image->width()) continue; if (p.y() >= image->height()) continue; if (redMarker.testBit(OFFSET(p.x(), p.y(), image))) continue; // already been here QRgb pixel = image->pixel(p); int gray = QGRAY(pixel); if (gray <= THRESHOLD) continue; // black; bail redMarker.setBit(OFFSET(p.x(), p.y(), image), true); if (p.x() > maxX) maxX = p.x(); if (p.x() < minX) minX = p.x(); if (p.y() > maxY) maxY = p.y(); if (p.y() < minY) minY = p.y(); stack.append(QPoint(p.x() - 1, p.y())); stack.append(QPoint(p.x() + 1, p.y())); stack.append(QPoint(p.x(), p.y() - 1)); stack.append(QPoint(p.x(), p.y() + 1)); } //image->save("testPoly1.png"); // step 2 replace white with black image->fill(0); // step 3 replace "red" with white for (int y = 0; y < image->height(); y++) { for (int x = 0; x < image->width(); x++) { if (redMarker.testBit(OFFSET(x, y, image))) { image->setPixel(x, y, 1); } } } #ifndef QT_NO_DEBUG image->save("testGroundPlaneUnit3.png"); #endif scanImage(*image, bWidth, bHeight, GraphicsUtils::StandardFritzingDPI / res, res, color, layerName, true, res / 50, true, QSizeF(.05, .05), 1 / FSvgRenderer::printerScale(), QPointF(0,0)); delete image; return true; }
QImage * GroundPlaneGenerator::generateGroundPlaneAux(const QString & boardSvg, QSizeF boardImageSize, const QString & svg, QSizeF copperImageSize, QStringList & exceptions, QGraphicsItem * board, double res, double & bWidth, double & bHeight, double blurBy) { QByteArray boardByteArray; QString tempColor("#ffffff"); if (!SvgFileSplitter::changeColors(boardSvg, tempColor, exceptions, boardByteArray)) { return NULL; } /* QFile file0("testGroundFillBoard.svg"); file0.open(QIODevice::WriteOnly); QTextStream out0(&file0); out0 << boardByteArray; file0.close(); */ QByteArray copperByteArray; if (!SvgFileSplitter::changeStrokeWidth(svg, 50, false, copperByteArray)) { return NULL; } /* QFile file1("testGroundFillCopper.svg"); file1.open(QIODevice::WriteOnly); QTextStream out1(&file1); out1 << copperByteArray; file1.close(); */ double svgWidth = res * qMax(boardImageSize.width(), copperImageSize.width()) / FSvgRenderer::printerScale(); double svgHeight = res * qMax(boardImageSize.height(), copperImageSize.height()) / FSvgRenderer::printerScale(); QRectF br = board->sceneBoundingRect(); bWidth = res * br.width() / FSvgRenderer::printerScale(); bHeight = res * br.height() / FSvgRenderer::printerScale(); QImage * image = new QImage(qMax(svgWidth, bWidth), qMax(svgHeight, bHeight), QImage::Format_Mono); // image->setDotsPerMeterX(res * GraphicsUtils::InchesPerMeter); image->setDotsPerMeterY(res * GraphicsUtils::InchesPerMeter); image->fill(0x0); QSvgRenderer renderer(boardByteArray); QPainter painter; painter.begin(image); painter.setRenderHint(QPainter::Antialiasing, false); renderer.render(&painter, QRectF(0, 0, res * boardImageSize.width() / FSvgRenderer::printerScale(), res * boardImageSize.height() / FSvgRenderer::printerScale())); painter.end(); #ifndef QT_NO_DEBUG image->save("testGroundFillBoard.png"); #endif for (double m = 0; m < .004; m += (1.0 / res)) { QList<QPoint> points; collectBorderPoints(*image, points); #ifndef QT_NO_DEBUG // for debugging double pixelFactor = GraphicsUtils::StandardFritzingDPI / res; QPolygon polygon; foreach(QPoint p, points) { polygon.append(QPoint(p.x() * pixelFactor, p.y() * pixelFactor)); } QList<QPolygon> polygons; polygons.append(polygon); QPointF offset; QString pSvg = makePolySvg(polygons, res, bWidth, bHeight, pixelFactor, "#ffffff", "debug", false, NULL, QSizeF(0,0), 0, QPointF(0, 0)); #endif foreach (QPoint p, points) image->setPixel(p, 0); }
/******************************************************************************* Stitch together two images using the homography transformation image1 - first input image image2 - second input image hom - homography transformation (image1 -> image2) homInv - inverse homography transformation (image2 -> image1) stitchedImage - returned stitched image *******************************************************************************/ void MainWindow::Stitch(QImage image1, QImage image2, double hom[3][3], double homInv[3][3], QImage &stitchedImage) { int r, c, i; QRgb pixel; int ws, hs; int w1 = image1.width(); int h1 = image1.height(); int w2 = image2.width(); int h2 = image2.height(); int cmin = 0; int cmax = w1; int rmin = 0; int rmax = h1; double corners[8]; corners[0] = corners[1] = corners[3] = corners[4] = 0.0; corners[2] = corners[6] = (double) w2; corners[5] = corners[7] = (double) h2; // Compute ws and has by projecting four corners of image2 to image1 for(i = 0; i < 4; i++) { double x, y; Project(corners[i * 2], corners[i * 2 + 1], x, y, homInv); int r = floor(y + 0.5); int c = floor(x + 0.5); cmin = cmin > c ? c : cmin; cmax = cmax < c ? c : cmax; rmin = rmin > r ? r : rmin; rmax = rmax < r ? r : rmax; } ws = cmax - cmin; hs = rmax - rmin; // Initialize the stitchedImage stitchedImage = QImage(ws, hs, QImage::Format_RGB32); stitchedImage.fill(qRgb(0,0,0)); // Warp image1 and image2 to stitchedImage. // Copy image1 to stitchedImage for(r = 0; r < h1; r++) { for(c = 0; c < w1; c++) { pixel = image1.pixel(c, r); stitchedImage.setPixel(c - cmin, r - rmin, pixel); } } // Project each pixel of stitchedImage onto image2 // bilinearInterpolate the value for(r = 0; r < hs; r++) { for(c = 0; c < ws; c++) { double x, y; double rgb[3]; pixel = stitchedImage.pixel(c, r); Project((double)(c + cmin), (double)(r + rmin), x, y, hom); if(BilinearInterpolation(&image2, x, y, rgb)) { stitchedImage.setPixel(c, r, qRgb((int) rgb[0], (int) rgb[1], (int) rgb[2])); } } } }
void CameraTab::redraw() { // cout << "Calling redraw\n"; QImage image = QImage(IMAGE_COLS, IMAGE_ROWS, QImage::Format_RGB32); pointCloud.points.resize(0); if(topFrame && botFrame) { //display normal image for (unsigned int row = 0; row < IMAGE_ROWS; ++row) { for (unsigned int col = 0; col < IMAGE_COLS; ++col) { QRgb rgb = getRGB(col, row, topFrame, TOP_IMAGE_COLS); image.setPixel(col, row, rgb); int r, g, b; QColor::fromRgb(rgb).getRgb(&r, &g, &b); pointCloud.points.push_back(make_pair(qglviewer::Vec(r / 255.0, g / 255.0, b / 255.0), qglviewer::Vec (gety(topFrame, row, col) / 255.0, getu(topFrame, row, col) / 255.0, getv(topFrame, row, col) / 255.0))); } } } else { image.fill(Qt::darkGray); } QPixmap imagePixmap = QPixmap(QPixmap::fromImage(image.scaled(IMAGE_COLS/2, IMAGE_ROWS/2))); imageLabels[CAMERA]->setPixmap(imagePixmap); // Create histograms //Histogram RGBHistogram(0x00000000U, 0x00ffffffU); YUVHistogram yuvHistogram(0x00000000U, 0x00ffffffU); //Histogram redHistogram(0x00U, 0xffU); //Histogram greenHistogram(0x00U, 0xffU); //Histogram blueHistogram(0x00U, 0xffU); // Process image for (unsigned int row = 0; row < IMAGE_ROWS; ++row) { for (unsigned int col = 0; col < IMAGE_COLS; ++col) { unsigned int YUVValue = 0x00ffffff & ((gety(topFrame, row, col) << 16) | (getu(topFrame, row, col) << 8) | getv(topFrame, row, col)); //RGBHistogram.addDatapoint(getRGB(col, row, currentFrame) & MAX_RGB_VALUE); yuvHistogram.addDatapoint(YUVValue); //redHistogram.addDatapoint((getRGB(col, row, currentFrame) & RED_MASK) >> 16); //greenHistogram.addDatapoint((getRGB(col, row, currentFrame) & GREEN_MASK) >> 8); //blueHistogram.addDatapoint(getRGB(col, row, currentFrame) & BLUE_MASK); } } /******************************************************************************* REMOVED FOR EFFICIENCY // Print statistics to terminal ostringstream ost; ost << "RGB Histogram "; //RGBHistogram.printStatistics(ost); ost << "YUV Histogram "; //yuvHistogram.printStatistics(ost); ost << "Red Histogram "; redHistogram.printStatistics(ost); ost << "Green Histogram "; greenHistogram.printStatistics(ost); ost << "Blue Histogram "; blueHistogram.printStatistics(ost); // cout << ost.str(); *******************************************************************************/ // Draw histograms // set initial background of pixmaps imagePixmaps[RGB].fill(Qt::darkGray); imagePixmaps[YUV].fill(Qt::darkGray); imagePixmaps[HSV].fill(Qt::darkGray); // draw each histogram //RGBHistogram.drawHistogram(imagePixmaps[RGB], (unsigned int)(IMAGE_COLS/2), (unsigned int)(IMAGE_ROWS/2), Histogram::eRGB); yuvHistogram.drawHistogram(imagePixmaps[YUV], (unsigned int)(IMAGE_COLS/2), (unsigned int)(IMAGE_ROWS/2), YUVHistogram::eYUV); //redHistogram.drawHistogram(imagePixmaps[HSV], (unsigned int)(IMAGE_COLS/2), (unsigned int)(IMAGE_ROWS/2), Histogram::eRED); //greenHistogram.drawHistogram(imagePixmaps[HSV], (unsigned int)(IMAGE_COLS/2), (unsigned int)(IMAGE_ROWS/2), Histogram::eGREEN); //blueHistogram.drawHistogram(imagePixmaps[HSV], (unsigned int)(IMAGE_COLS/2), (unsigned int)(IMAGE_ROWS/2), Histogram::eBLUE); // display them in camera tab imageLabels[YUV]->setPixmap(imagePixmaps[YUV]); //imageLabels[RGB]->setPixmap(imagePixmaps[RGB]); //imageLabels[HSV]->setPixmap(imagePixmaps[HSV]); // USE HSV PIXMAP FOR TESTING - CHANGE LATER // Display entropy in message bar /******************************************************************************************************* ostringstream est; est << "Your entropy is "; est << redHistogram.getEntropyValue(); est << " + "; est << greenHistogram.getEntropyValue(); est << " + "; est << blueHistogram.getEntropyValue(); est << " = "; est << redHistogram.getEntropyValue() + greenHistogram.getEntropyValue() + blueHistogram.getEntropyValue(); est << " That's a mess!"; //est << RGBHistogram.getEntropyValue(); emit showMessage(QString(est.str().c_str())); *******************************************************************************************************/ if (autoTuneOn) { tuneValue(yuvHistogram.getEntropyValue()); /******************************************************************************************************* tuneValue(redHistogram.getEntropyValue() + greenHistogram.getEntropyValue() + blueHistogram.getEntropyValue()); *******************************************************************************************************/ } }
QImage* MyTextEffect::drawImage() { QFont myFont; QPen myPen; myPen.setJoinStyle( Qt::RoundJoin ); QBrush myBrush( QColor(0,0,0,0) ); QColor backgroundColor(0,0,0,0); int outline = 0; int align = 1; int arrowType = 0, arrowSize = 0, arrowPos = 0; QStringList sl = currentText.split("\n"); while ( !sl.isEmpty() ) { if ( sl.last().trimmed().isEmpty() ) sl.takeLast(); else break; } if ( sl.count() ) { QStringList desc = sl[0].split("|"); if ( desc.count() >= 9 ) { myFont.fromString( desc[0] ); myFont.setPointSize( desc[1].toInt() ); myFont.setBold( desc[2].toInt() ); myFont.setItalic( desc[3].toInt() ); QStringList fc = desc[4].split( "." ); if ( fc.count() == 2 ) { QColor col; col.setNamedColor( fc[ 0 ] ); col.setAlpha( fc[ 1 ].toInt() ); myPen.setColor( col ); myBrush.setColor( col ); } QStringList bc = desc[5].split( "." ); if ( bc.count() == 2 ) { backgroundColor.setNamedColor( bc[ 0 ] ); backgroundColor.setAlpha( bc[ 1 ].toInt() ); } align = desc[6].toInt(); int osize = desc[7].toInt(); if ( osize > 0 ) { QStringList oc = desc[8].split( "." ); if ( oc.count() == 2 ) { outline = osize; myPen.setWidth( osize ); myFont.setStyleStrategy( QFont::ForceOutline ); QColor col; col.setNamedColor( oc[ 0 ] ); col.setAlpha( oc[ 1 ].toInt() ); myPen.setColor( col ); } } } if ( desc.count() >= 12 ) { arrowType = desc[9].toInt(); arrowSize = desc[10].toInt(); arrowPos = desc[11].toInt(); } sl.takeFirst(); } QImage *image = new QImage( 10, 10, QImage::Format_ARGB32_Premultiplied ); QPainter painter; painter.begin( image ); painter.setPen( myPen ); painter.setBrush( myBrush ); painter.setFont( myFont ); QList<QRectF> br; QFontMetrics metrics( myFont ); int h = sl.count() * metrics.lineSpacing(); int w = 0; for ( int i = 0; i < sl.count(); ++i ) { QRectF minrect( 0, 0, 1, 1 ); QRectF r = painter.boundingRect( minrect, Qt::AlignHCenter | Qt::AlignVCenter, sl[i] ); if ( r.width() > w ) w = r.width(); br.append( r ); } QRectF minrect( 0, 0, 1, 1 ); int margin = qMax( painter.boundingRect( minrect, Qt::AlignHCenter | Qt::AlignVCenter, "M" ).width() / 3.0, 3.0 ); painter.end(); double x = ((double)outline + margin * 2) / 2.0; double y = x; w += 2 * x; h += 2 * y; if ( w > iwidth ) { x -= (w - iwidth) / 2.0; w = iwidth; } if ( h > iheight ) { y -= (h - iheight) / 2.0; h = iheight; } QPointF polygon[7]; arrowSize = h * arrowSize / 100.0; int n = 0; int leftOffset = 0, topOffset = 0; int wMargin = 0, hMargin = 0; if (arrowType) { switch (arrowType) { case 1: { leftOffset = arrowSize; wMargin = arrowSize; polygon[n].setX(1 + arrowSize); polygon[n++].setY(1); polygon[n].setY(qMax(1.0, qMin(h - 1.0, h * arrowPos / 100.0 - arrowSize / 2.0) ) ); polygon[n++].setX(1 + arrowSize); polygon[n].setY(qMax(1.0, qMin(h - 1.0, h * arrowPos / 100.0) ) ); polygon[n++].setX(1); polygon[n].setY(qMax(1.0, qMin(h - 1.0, h * arrowPos / 100.0 + arrowSize / 2.0) ) ); polygon[n++].setX(1 + arrowSize); polygon[n].setX(1 + arrowSize); polygon[n++].setY(h - 1); polygon[n].setX(w - 1 + arrowSize); polygon[n++].setY(h - 1); polygon[n].setX(w - 1 + arrowSize); polygon[n++].setY(1); break; } case 2: { wMargin = arrowSize; polygon[n].setX(1); polygon[n++].setY(1); polygon[n].setX(1); polygon[n++].setY(h - 1); polygon[n].setX(w - 1); polygon[n++].setY(h - 1); polygon[n].setY(qMax(1.0, qMin(h - 1.0, h * arrowPos / 100.0 + arrowSize / 2.0) ) ); polygon[n++].setX(w - 1); polygon[n].setY(qMax(1.0, qMin(h - 1.0, h * arrowPos / 100.0) ) ); polygon[n++].setX(w - 1 + arrowSize); polygon[n].setY(qMax(1.0, qMin(h - 1.0, h * arrowPos / 100.0 - arrowSize / 2.0) ) ); polygon[n++].setX(w - 1); polygon[n].setX(w - 1); polygon[n++].setY(1); break; } case 3: { topOffset = arrowSize; hMargin = arrowSize; polygon[n].setX(1); polygon[n++].setY(1 + arrowSize); polygon[n].setX(1); polygon[n++].setY(h - 1 + arrowSize); polygon[n].setX(w - 1); polygon[n++].setY(h - 1 + arrowSize); polygon[n].setX(w - 1); polygon[n++].setY(1 + arrowSize); polygon[n].setX(qMax(1.0, qMin(w - 1.0, w * arrowPos / 100.0 + arrowSize / 2.0) ) ); polygon[n++].setY(1 + arrowSize); polygon[n].setX(qMax(1.0, qMin(w - 1.0, w * arrowPos / 100.0) ) ); polygon[n++].setY(1); polygon[n].setX(qMax(1.0, qMin(w - 1.0, w * arrowPos / 100.0 - arrowSize / 2.0) ) ); polygon[n++].setY(1 + arrowSize); break; } case 4: { hMargin = arrowSize; polygon[n].setX(1); polygon[n++].setY(1); polygon[n].setX(1); polygon[n++].setY(h - 1); polygon[n].setX(qMax(1.0, qMin(w - 1.0, w * arrowPos / 100.0 - arrowSize / 2.0) ) ); polygon[n++].setY(h - 1); polygon[n].setX(qMax(1.0, qMin(w - 1.0, w * arrowPos / 100.0) ) ); polygon[n++].setY(h - 1 + arrowSize); polygon[n].setX(qMax(1.0, qMin(w - 1.0, w * arrowPos / 100.0 + arrowSize / 2.0) ) ); polygon[n++].setY(h - 1); polygon[n].setX(w - 1); polygon[n++].setY(h - 1); polygon[n].setX(w - 1); polygon[n++].setY(1); break; } } } delete image; image = new QImage( w + wMargin, h + hMargin, QImage::Format_ARGB32_Premultiplied ); image->fill( QColor(0,0,0,0) ); painter.begin( image ); painter.setRenderHints( QPainter::Antialiasing | QPainter::TextAntialiasing ); if ( backgroundColor.alpha() > 0 ) { painter.setPen( QColor(0,0,0,0) ); painter.setBrush( backgroundColor ); if (arrowType) { painter.drawPolygon( polygon, 7 ); } else { painter.drawRect( 1, 1, w - 2, h - 2 ); } } painter.setPen( myPen ); painter.setBrush( myBrush ); painter.setFont( myFont ); for ( int i = 0; i < sl.count(); ++i ) { QPointF point( 0, y + topOffset + metrics.ascent() ); switch ( align ) { case 2: { point.setX( leftOffset + (double)w / 2.0 - br[i].width() / 2.0 ); break; } case 3: { point.setX( leftOffset + w - x - br[i].width() ); break; } default: { point.setX( leftOffset + x ); break; } } if ( outline ) { QPainterPath myPath; myPath.addText( point, myFont, sl[i] ); painter.drawPath( myPath ); } else painter.drawText( point, sl[i] ); y += metrics.lineSpacing(); } painter.end(); return image; }
void LibraryItemDelegate::paintCoverOnTrack(QPainter *painter, const QStyleOptionViewItem &opt, const QStandardItem *track) const { Settings *settings = Settings::instance(); const QImage *image = _libraryTreeView->expandedCover(static_cast<AlbumItem*>(track->parent())); if (image && !image->isNull()) { // Copy QStyleOptionViewItem to be able to expand it to the left, and take the maximum available space QStyleOptionViewItem option(opt); option.rect.setX(0); int totalHeight = track->model()->rowCount(track->parent()->index()) * option.rect.height(); QImage scaled; QRect subRect; int row = _proxy->mapFromSource(track->index()).row(); if (totalHeight > option.rect.width()) { scaled = image->scaledToWidth(option.rect.width()); subRect = option.rect.translated(option.rect.width() - scaled.width(), -option.rect.y() + option.rect.height() * row); } else { scaled = image->scaledToHeight(totalHeight); int dx = option.rect.width() - scaled.width(); subRect = option.rect.translated(-dx, -option.rect.y() + option.rect.height() * row); } // Fill with white when there are too much tracks to paint (height of all tracks is greater than the scaled image) QImage subImage = scaled.copy(subRect); if (scaled.height() < subRect.y() + subRect.height()) { subImage.fill(option.palette.base().color()); } painter->save(); painter->setOpacity(1 - settings->coverBelowTracksOpacity()); painter->drawImage(option.rect, subImage); // Over paint black pixel in white QRect t(option.rect.x(), option.rect.y(), option.rect.width() - scaled.width(), option.rect.height()); QImage white(t.size(), QImage::Format_ARGB32); white.fill(option.palette.base().color()); painter->setOpacity(1.0); painter->drawImage(t, white); // Create a mix with 2 images: first one is a 3 pixels subimage of the album cover which is expanded to the left border // The second one is a computer generated gradient focused on alpha channel QImage leftBorder = scaled.copy(0, subRect.y(), 3, option.rect.height()); if (!leftBorder.isNull()) { // Because the expanded border can look strange to one, is blurred with some gaussian function leftBorder = leftBorder.scaled(t.width(), option.rect.height(), Qt::IgnoreAspectRatio, Qt::SmoothTransformation); leftBorder = ImageUtils::blurred(leftBorder, leftBorder.rect(), 10, false); painter->setOpacity(1 - settings->coverBelowTracksOpacity()); painter->drawImage(t, leftBorder); QLinearGradient linearAlphaBrush(0, 0, leftBorder.width(), 0); linearAlphaBrush.setColorAt(0, QApplication::palette().base().color()); linearAlphaBrush.setColorAt(1, Qt::transparent); painter->setOpacity(1.0); painter->setCompositionMode(QPainter::CompositionMode_SourceOver); painter->setPen(Qt::NoPen); painter->setBrush(linearAlphaBrush); painter->drawRect(t); } painter->restore(); } // Display a light selection rectangle when one is moving the cursor painter->save(); QColor color = opt.palette.highlight().color(); color.setAlphaF(0.66); if (opt.state.testFlag(QStyle::State_MouseOver) && !opt.state.testFlag(QStyle::State_Selected)) { painter->setPen(opt.palette.highlight().color()); painter->setBrush(color.lighter(lighterValue)); painter->drawRect(opt.rect.adjusted(0, 0, -1, -1)); } else if (opt.state.testFlag(QStyle::State_Selected)) { // Display a not so light rectangle when one has chosen an item. It's darker than the mouse over painter->setPen(opt.palette.highlight().color()); painter->setBrush(color.lighter(150)); painter->drawRect(opt.rect.adjusted(0, 0, -1, -1)); } painter->restore(); }
void QgsMapRenderer::render( QPainter* painter, double* forceWidthScale ) { //Lock render method for concurrent threads (e.g. from globe) QMutexLocker renderLock( &mRenderMutex ); QgsDebugMsg( "========== Rendering ==========" ); if ( mExtent.isEmpty() ) { QgsDebugMsg( "empty extent... not rendering" ); return; } if ( mSize.width() == 1 && mSize.height() == 1 ) { QgsDebugMsg( "size 1x1... not rendering" ); return; } QPaintDevice* thePaintDevice = painter->device(); if ( !thePaintDevice ) { return; } // wait if ( mDrawing ) { QgsDebugMsg( "already rendering" ); QCoreApplication::processEvents(); } if ( mDrawing ) { QgsDebugMsg( "still rendering - skipping" ); return; } mDrawing = true; const QgsCoordinateTransform *ct; #ifdef QGISDEBUG QgsDebugMsg( "Starting to render layer stack." ); QTime renderTime; renderTime.start(); #endif if ( mOverview ) mRenderContext.setDrawEditingInformation( !mOverview ); mRenderContext.setPainter( painter ); mRenderContext.setCoordinateTransform( 0 ); //this flag is only for stopping during the current rendering progress, //so must be false at every new render operation mRenderContext.setRenderingStopped( false ); // set selection color QgsProject* prj = QgsProject::instance(); int myRed = prj->readNumEntry( "Gui", "/SelectionColorRedPart", 255 ); int myGreen = prj->readNumEntry( "Gui", "/SelectionColorGreenPart", 255 ); int myBlue = prj->readNumEntry( "Gui", "/SelectionColorBluePart", 0 ); int myAlpha = prj->readNumEntry( "Gui", "/SelectionColorAlphaPart", 255 ); mRenderContext.setSelectionColor( QColor( myRed, myGreen, myBlue, myAlpha ) ); //calculate scale factor //use the specified dpi and not those from the paint device //because sometimes QPainter units are in a local coord sys (e.g. in case of QGraphicsScene) double sceneDpi = mScaleCalculator->dpi(); double scaleFactor = 1.0; if ( mOutputUnits == QgsMapRenderer::Millimeters ) { if ( forceWidthScale ) { scaleFactor = *forceWidthScale; } else { scaleFactor = sceneDpi / 25.4; } } double rasterScaleFactor = ( thePaintDevice->logicalDpiX() + thePaintDevice->logicalDpiY() ) / 2.0 / sceneDpi; if ( mRenderContext.rasterScaleFactor() != rasterScaleFactor ) { mRenderContext.setRasterScaleFactor( rasterScaleFactor ); } if ( mRenderContext.scaleFactor() != scaleFactor ) { mRenderContext.setScaleFactor( scaleFactor ); } if ( mRenderContext.rendererScale() != mScale ) { //add map scale to render context mRenderContext.setRendererScale( mScale ); } if ( mLastExtent != mExtent ) { mLastExtent = mExtent; } mRenderContext.setLabelingEngine( mLabelingEngine ); if ( mLabelingEngine ) mLabelingEngine->init( mapSettings() ); // render all layers in the stack, starting at the base QListIterator<QString> li( mLayerSet ); li.toBack(); QgsRectangle r1, r2; while ( li.hasPrevious() ) { if ( mRenderContext.renderingStopped() ) { break; } // Store the painter in case we need to swap it out for the // cache painter QPainter * mypContextPainter = mRenderContext.painter(); // Flattened image for drawing when a blending mode is set QImage * mypFlattenedImage = 0; QString layerId = li.previous(); QgsDebugMsg( "Rendering at layer item " + layerId ); // This call is supposed to cause the progress bar to // advance. However, it seems that updating the progress bar is // incompatible with having a QPainter active (the one that is // passed into this function), as Qt produces a number of errors // when try to do so. I'm (Gavin) not sure how to fix this, but // added these comments and debug statement to help others... QgsDebugMsg( "If there is a QPaintEngine error here, it is caused by an emit call" ); //emit drawingProgress(myRenderCounter++, mLayerSet.size()); QgsMapLayer *ml = QgsMapLayerRegistry::instance()->mapLayer( layerId ); if ( !ml ) { QgsDebugMsg( "Layer not found in registry!" ); continue; } QgsDebugMsg( QString( "layer %1: minscale:%2 maxscale:%3 scaledepvis:%4 extent:%5 blendmode:%6" ) .arg( ml->name() ) .arg( ml->minimumScale() ) .arg( ml->maximumScale() ) .arg( ml->hasScaleBasedVisibility() ) .arg( ml->extent().toString() ) .arg( ml->blendMode() ) ); if ( mRenderContext.useAdvancedEffects() ) { // Set the QPainter composition mode so that this layer is rendered using // the desired blending mode mypContextPainter->setCompositionMode( ml->blendMode() ); } if ( !ml->hasScaleBasedVisibility() || ( ml->minimumScale() <= mScale && mScale < ml->maximumScale() ) || mOverview ) { connect( ml, SIGNAL( drawingProgress( int, int ) ), this, SLOT( onDrawingProgress( int, int ) ) ); // // Now do the call to the layer that actually does // the rendering work! // bool split = false; if ( hasCrsTransformEnabled() ) { r1 = mExtent; split = splitLayersExtent( ml, r1, r2 ); ct = transformation( ml ); mRenderContext.setExtent( r1 ); QgsDebugMsg( " extent 1: " + r1.toString() ); QgsDebugMsg( " extent 2: " + r2.toString() ); if ( !r1.isFinite() || !r2.isFinite() ) //there was a problem transforming the extent. Skip the layer { continue; } } else { ct = NULL; } mRenderContext.setCoordinateTransform( ct ); //decide if we have to scale the raster //this is necessary in case QGraphicsScene is used bool scaleRaster = false; QgsMapToPixel rasterMapToPixel; QgsMapToPixel bk_mapToPixel; if ( ml->type() == QgsMapLayer::RasterLayer && qAbs( rasterScaleFactor - 1.0 ) > 0.000001 ) { scaleRaster = true; } QSettings mySettings; // If we are drawing with an alternative blending mode then we need to render to a separate image // before compositing this on the map. This effectively flattens the layer and prevents // blending occuring between objects on the layer // (this is not required for raster layers or when layer caching is enabled, since that has the same effect) bool flattenedLayer = false; if (( mRenderContext.useAdvancedEffects() ) && ( ml->type() == QgsMapLayer::VectorLayer ) ) { QgsVectorLayer* vl = qobject_cast<QgsVectorLayer *>( ml ); if ((( vl->blendMode() != QPainter::CompositionMode_SourceOver ) || ( vl->featureBlendMode() != QPainter::CompositionMode_SourceOver ) || ( vl->layerTransparency() != 0 ) ) ) { flattenedLayer = true; mypFlattenedImage = new QImage( mRenderContext.painter()->device()->width(), mRenderContext.painter()->device()->height(), QImage::Format_ARGB32 ); if ( mypFlattenedImage->isNull() ) { QgsDebugMsg( "insufficient memory for image " + QString::number( mRenderContext.painter()->device()->width() ) + "x" + QString::number( mRenderContext.painter()->device()->height() ) ); emit drawError( ml ); painter->end(); // drawError is not caught by anyone, so we end painting to notify caller return; } mypFlattenedImage->fill( 0 ); QPainter * mypPainter = new QPainter( mypFlattenedImage ); if ( mySettings.value( "/qgis/enable_anti_aliasing", true ).toBool() ) { mypPainter->setRenderHint( QPainter::Antialiasing ); } mypPainter->scale( rasterScaleFactor, rasterScaleFactor ); mRenderContext.setPainter( mypPainter ); } } // Per feature blending mode if (( mRenderContext.useAdvancedEffects() ) && ( ml->type() == QgsMapLayer::VectorLayer ) ) { QgsVectorLayer* vl = qobject_cast<QgsVectorLayer *>( ml ); if ( vl->featureBlendMode() != QPainter::CompositionMode_SourceOver ) { // set the painter to the feature blend mode, so that features drawn // on this layer will interact and blend with each other mRenderContext.painter()->setCompositionMode( vl->featureBlendMode() ); } } if ( scaleRaster ) { bk_mapToPixel = mRenderContext.mapToPixel(); rasterMapToPixel = mRenderContext.mapToPixel(); rasterMapToPixel.setMapUnitsPerPixel( mRenderContext.mapToPixel().mapUnitsPerPixel() / rasterScaleFactor ); rasterMapToPixel.setYMaximum( mSize.height() * rasterScaleFactor ); mRenderContext.setMapToPixel( rasterMapToPixel ); mRenderContext.painter()->save(); mRenderContext.painter()->scale( 1.0 / rasterScaleFactor, 1.0 / rasterScaleFactor ); } if ( !ml->draw( mRenderContext ) ) { emit drawError( ml ); } else { QgsDebugMsg( "Layer rendered without issues" ); } if ( split ) { mRenderContext.setExtent( r2 ); if ( !ml->draw( mRenderContext ) ) { emit drawError( ml ); } } if ( scaleRaster ) { mRenderContext.setMapToPixel( bk_mapToPixel ); mRenderContext.painter()->restore(); } //apply layer transparency for vector layers if (( mRenderContext.useAdvancedEffects() ) && ( ml->type() == QgsMapLayer::VectorLayer ) ) { QgsVectorLayer* vl = qobject_cast<QgsVectorLayer *>( ml ); if ( vl->layerTransparency() != 0 ) { // a layer transparency has been set, so update the alpha for the flattened layer // by combining it with the layer transparency QColor transparentFillColor = QColor( 0, 0, 0, 255 - ( 255 * vl->layerTransparency() / 100 ) ); // use destination in composition mode to merge source's alpha with destination mRenderContext.painter()->setCompositionMode( QPainter::CompositionMode_DestinationIn ); mRenderContext.painter()->fillRect( 0, 0, mRenderContext.painter()->device()->width(), mRenderContext.painter()->device()->height(), transparentFillColor ); } } if ( flattenedLayer ) { // If we flattened this layer for alternate blend modes, composite it now delete mRenderContext.painter(); mRenderContext.setPainter( mypContextPainter ); mypContextPainter->save(); mypContextPainter->scale( 1.0 / rasterScaleFactor, 1.0 / rasterScaleFactor ); mypContextPainter->drawImage( 0, 0, *( mypFlattenedImage ) ); mypContextPainter->restore(); delete mypFlattenedImage; mypFlattenedImage = 0; } disconnect( ml, SIGNAL( drawingProgress( int, int ) ), this, SLOT( onDrawingProgress( int, int ) ) ); } else // layer not visible due to scale {
void Window::init() { m_data = new PrivateData; m_data->bar = new QScrollBar(Qt::Vertical, this); connect(m_data->bar, SIGNAL(valueChanged(int)), this, SLOT(update())); m_data->bar->setEnabled(true); m_data->bar->setRange(0, 32678 - 600); m_data->bar->setValue(0); m_data->bar->move(width() - 30, 0); m_data->bar->resize(30, height()); m_data->renderer = new GraphLib::GraphAggRenderer(); m_data->interactiveRenderer = new GraphLib::GraphAggInteractiveRenderer((GraphLib::GraphRenderer *)m_data->renderer); // //m_data->interactiveRenderer->setSize(NULL, 500, 500); // // QImage *image = new QImage(10.00, 32.678, QImage::Format_ARGB32); image->fill(Qt::darkYellow); m_data->interactiveRenderer->setSize((void *)image, image->width(), image->height()); //m_data->renderer->beginRender(); m_data->interactiveRenderer->fillPixelRect(200, 50, 30, 30, new QColor(Qt::red)); GraphLib::Rectangle rect1(0, 0, 300, 300); m_data->interactiveRenderer->clipRegionAddRect(&rect1); resize(800, 600); m_data->renderer->beginRender(); m_data->interactiveRenderer->fillPixelRect(200, 50, 30, 30, new QColor(Qt::red)); m_data->renderer->setLineWidth(0.3); m_data->renderer->drawLine(new GraphLib::Point(10, 10), new GraphLib::Point(30, 50), new QColor(Qt::red)); m_data->renderer->drawRect(new GraphLib::Point(50, 100), new GraphLib::Point(150, 40201), new QColor(Qt::blue)); m_data->renderer->fillRect(new GraphLib::Point(80, 50), new GraphLib::Point(100, 70), new QColor(Qt::cyan)); m_data->renderer->drawEllipse(new GraphLib::Point(50, 100), 20, 20, new QColor(0, 1, 0)); m_data->renderer->fillEllipse(new GraphLib::Point(100, 100), 20, 20, new QColor(1, 1, 0)); GraphLib::Point polyline[] = {QPoint(110, 210), QPoint(120,210), QPoint(130,220)}; m_data->renderer->drawPolyline(polyline, 3, new QColor(1, 1, 0)); GraphLib::Point polygon[] = {QPoint(110, 310), QPoint(120,310), QPoint(130,320)}; m_data->renderer->drawPolygon(polygon, 3, new QColor(1, 1, 0)); GraphLib::Point polygon1[] = {QPoint(110, 410), QPoint(120,410), QPoint(130,420)}; m_data->renderer->fillPolygon(polygon1, 3, new QColor(1, 1, 0)); //for (int i = 100; i < 99900; i+= 20) { for (int i = 100; i < 1000; i+= 20) { QString str = QString("line %1").arg(i); m_data->renderer->drawString(str, new GraphLib::Point(20, i), 0, new QColor(1, 1, 0)); } GraphLib::GraphAggRenderer *r = m_data->renderer; r->beginPath(); r->moveTo(30, 30); r->lineTo(500, 500); r->moveTo(200, 200.2); r->lineTo(400, 200.2); r->moveTo(200, 100); r->lineTo(400, 100); r->moveTo(50.5, 50); r->lineTo(50.5, 200); r->setLineWidth(0.5); r->endPath(); m_data->renderer->endRender(); }
QImage *createArrowBackground(const QMatrix &matrix) const { QRect scaledRect; scaledRect = matrix.mapRect(QRect(0, 0, this->logicalSize.width(), this->logicalSize.height())); QImage *image = new QImage(scaledRect.width(), scaledRect.height(), QImage::Format_ARGB32_Premultiplied); image->fill(QColor(0, 0, 0, 0).rgba()); QPainter painter(image); painter.setRenderHint(QPainter::SmoothPixmapTransform); painter.setRenderHint(QPainter::Antialiasing); painter.setPen(Qt::NoPen); if (Colors::useEightBitPalette){ painter.setPen(QColor(120, 120, 120)); if (this->pressed) painter.setBrush(QColor(60, 60, 60)); else if (this->highlighted) painter.setBrush(QColor(100, 100, 100)); else painter.setBrush(QColor(80, 80, 80)); } else { QLinearGradient outlinebrush(0, 0, 0, scaledRect.height()); QLinearGradient brush(0, 0, 0, scaledRect.height()); brush.setSpread(QLinearGradient::PadSpread); QColor highlight(255, 255, 255, 70); QColor shadow(0, 0, 0, 70); QColor sunken(220, 220, 220, 30); QColor normal1 = QColor(200, 170, 160, 50); QColor normal2 = QColor(50, 10, 0, 50); if (pressed) { outlinebrush.setColorAt(0.0f, shadow); outlinebrush.setColorAt(1.0f, highlight); brush.setColorAt(0.0f, sunken); painter.setPen(Qt::NoPen); } else { outlinebrush.setColorAt(1.0f, shadow); outlinebrush.setColorAt(0.0f, highlight); brush.setColorAt(0.0f, normal1); if (!this->highlighted) brush.setColorAt(1.0f, normal2); painter.setPen(QPen(outlinebrush, 1)); } painter.setBrush(brush); } painter.drawRect(0, 0, scaledRect.width(), scaledRect.height()); float xOff = scaledRect.width() / 2; float yOff = scaledRect.height() / 2; float sizex = 3.0f * matrix.m11(); float sizey = 1.5f * matrix.m22(); if (this->type == TextButton::UP) sizey *= -1; QPainterPath path; path.moveTo(xOff, yOff + (5 * sizey)); path.lineTo(xOff - (4 * sizex), yOff - (3 * sizey)); path.lineTo(xOff + (4 * sizex), yOff - (3 * sizey)); path.lineTo(xOff, yOff + (5 * sizey)); painter.drawPath(path); return image; }
void ScaleBarObject::draw(float pixelGLRatio, int screenWidth, int screenHeight, int viewWidth, int viewHeight, bool grabsMouse) { VolumeInformation pvlInfo = VolumeInformation::volumeInformation(); QString str; bool horizontal = m_type; float slen = voxels(); if (pvlInfo.voxelUnit > 0) { float avg = (pvlInfo.voxelSize[0] + pvlInfo.voxelSize[1] + pvlInfo.voxelSize[2])/3.0f; str = QString("%1 %2"). \ arg(slen, 0, 'f', Global::floatPrecision()). \ arg(pvlInfo.voxelUnitStringShort()); slen /= avg; } else str = QString("%1 voxels").arg(slen); slen = slen/pixelGLRatio; Vec s0 = Vec(m_pos.x()*viewWidth, m_pos.y()*viewHeight, 1); Vec s1 = s0; if (horizontal) { slen *= (float)viewWidth/(float)screenWidth; s0 -= Vec(slen/2, 0, 0); s1 += Vec(slen/2, 0, 0); } else { slen *= (float)viewHeight/(float)screenHeight; s0 -= Vec(0, slen/2, 0); s1 += Vec(0, slen/2, 0); } glEnable(GL_BLEND); glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); // back to front glColor4f(0, 0, 0, 0.8f); if (grabsMouse) { glColor4f(0.5f, 0, 0, 0.8f); glBegin(GL_QUADS); if (horizontal) { glVertex2f(s0.x-5, s0.y-10); glVertex2f(s1.x+5, s0.y-10); glVertex2f(s1.x+5, s0.y+10); glVertex2f(s0.x-5, s0.y+10); } else { glVertex2f(s0.x-10, s0.y-5); glVertex2f(s0.x-10, s1.y+5); glVertex2f(s0.x+10, s1.y+5); glVertex2f(s0.x+10, s0.y-5); } glEnd(); } glDisable(GL_BLEND); glColor3f(1,1,1); glLineWidth(10); glBegin(GL_LINES); glVertex3fv(s0); glVertex3fv(s1); glEnd(); glColor3f(0.5,0.5,0.5); glLineWidth(2); glBegin(GL_LINES); if (horizontal) { glVertex2f(s0.x+slen/2, s0.y-3); glVertex2f(s0.x+slen/2, s1.y+3); } else { glVertex2f(s1.x-3, (s1.y+s0.y)/2); glVertex2f(s0.x+3, (s1.y+s0.y)/2); } glEnd(); glColor3f(0,0,0); glLineWidth(2); glBegin(GL_LINES); if (horizontal) { glVertex2f(s0.x+1, s0.y); glVertex2f(s1.x-1, s1.y); } else { glVertex2f(s0.x, s0.y+1); glVertex2f(s1.x, s1.y-1); } glEnd(); glLineWidth(1); glColor3f(1,1,1); { Vec w0 = Vec(m_pos.x()*screenWidth, (1-m_pos.y())*screenHeight,1); Vec w1 = w0; if (horizontal) { w0 -= Vec(slen/2, 0, 0); w1 += Vec(slen/2, 0, 0); } else { w0 -= Vec(0, slen/2, 0); w1 += Vec(0, slen/2, 0); } QFont tfont = QFont("Helvetica", 12); tfont.setStyleStrategy(QFont::PreferAntialias); QFontMetrics metric(tfont); int mde = metric.descent(); int fht = metric.height()+2; int fwd = metric.width(str)+2; QImage bImage = QImage(fwd, fht, QImage::Format_ARGB32); bImage.fill(0); QPainter bpainter(&bImage); Vec bgcolor = Global::backgroundColor(); bpainter.setBackgroundMode(Qt::OpaqueMode); bpainter.setBackground(QColor(bgcolor.z*255, bgcolor.y*255, bgcolor.x*255)); float bgintensity = (0.3*bgcolor.x + 0.5*bgcolor.y + 0.2*bgcolor.z); QColor penColor(Qt::white); if (bgintensity > 0.5) penColor = Qt::black; bpainter.setPen(penColor); bpainter.setFont(tfont); bpainter.drawText(1, fht-mde, str); QImage cImage = bImage.mirrored(); if (!horizontal) { QMatrix matrix; matrix.rotate(90); cImage = cImage.transformed(matrix); } int x,y; if (horizontal) { x = (w0.x+w1.x)/2 - cImage.width()/2; y = w0.y-3-cImage.height(); if (!m_textpos) y = w0.y+6; } else { x = w1.x+3; if (!m_textpos) x = w1.x-5-cImage.width(); y = (w0.y+w1.y)/2 - cImage.height()/2; } glWindowPos2i(x,y); const uchar *bits = cImage.bits(); glDrawPixels(cImage.width(), cImage.height(), GL_RGBA, GL_UNSIGNED_BYTE, bits); } }
QImage * GroundPlaneGenerator::generateGroundPlaneAux(const QString & boardSvg, QSizeF boardImageSize, const QString & svg, QSizeF copperImageSize, QStringList & exceptions, QGraphicsItem * board, double res, double & bWidth, double & bHeight) { QByteArray boardByteArray; QString tempColor("#ffffff"); if (!SvgFileSplitter::changeColors(boardSvg, tempColor, exceptions, boardByteArray)) { return NULL; } //QFile file0("testGroundFillBoard.svg"); //file0.open(QIODevice::WriteOnly); //QTextStream out0(&file0); //out0 << boardByteArray; //file0.close(); QByteArray copperByteArray; if (!SvgFileSplitter::changeStrokeWidth(svg, m_strokeWidthIncrement, false, copperByteArray)) { return NULL; } //QFile file1("testGroundFillCopper.svg"); //file1.open(QIODevice::WriteOnly); //QTextStream out1(&file1); //out1 << copperByteArray; //file1.close(); double svgWidth = res * qMax(boardImageSize.width(), copperImageSize.width()) / FSvgRenderer::printerScale(); double svgHeight = res * qMax(boardImageSize.height(), copperImageSize.height()) / FSvgRenderer::printerScale(); QRectF br = board->sceneBoundingRect(); bWidth = res * br.width() / FSvgRenderer::printerScale(); bHeight = res * br.height() / FSvgRenderer::printerScale(); QImage * image = new QImage(qMax(svgWidth, bWidth), qMax(svgHeight, bHeight), QImage::Format_Mono); // image->setDotsPerMeterX(res * GraphicsUtils::InchesPerMeter); image->setDotsPerMeterY(res * GraphicsUtils::InchesPerMeter); image->fill(0x0); QSvgRenderer renderer(boardByteArray); QPainter painter; painter.begin(image); painter.setRenderHint(QPainter::Antialiasing, false); QRectF boardBounds(0, 0, res * boardImageSize.width() / FSvgRenderer::printerScale(), res * boardImageSize.height() / FSvgRenderer::printerScale()); DebugDialog::debug("boardbounds", boardBounds); renderer.render(&painter, boardBounds); painter.end(); #ifndef QT_NO_DEBUG image->save("testGroundFillBoard.png"); #endif for (double m = 0; m < BORDERINCHES; m += (1.0 / res)) { // 1 mm QList<QPoint> points; collectBorderPoints(*image, points); #ifndef QT_NO_DEBUG /* // for debugging double pixelFactor = GraphicsUtils::StandardFritzingDPI / res; QPolygon polygon; foreach(QPoint p, points) { polygon.append(QPoint(p.x() * pixelFactor, p.y() * pixelFactor)); } QList<QPolygon> polygons; polygons.append(polygon); QPointF offset; this QString pSvg = makePolySvg(polygons, res, bWidth, bHeight, pixelFactor, "#ffffff", false, NULL, QSizeF(0,0), 0, QPointF(0, 0)); */ #endif foreach (QPoint p, points) image->setPixel(p, 0); } #ifndef QT_NO_DEBUG image->save("testGroundFillBoardBorder.png"); #endif // "blur" the image a little QSvgRenderer renderer2(copperByteArray); painter.begin(image); painter.setRenderHint(QPainter::Antialiasing, false); QRectF bounds(0, 0, res * copperImageSize.width() / FSvgRenderer::printerScale(), res * copperImageSize.height() / FSvgRenderer::printerScale()); DebugDialog::debug("copperbounds", bounds); renderer2.render(&painter, bounds); if (m_blurBy != 0) { bounds.moveTo(m_blurBy, 0); renderer2.render(&painter, bounds); bounds.moveTo(-m_blurBy, 0); renderer2.render(&painter, bounds); bounds.moveTo(0, m_blurBy); renderer2.render(&painter, bounds); bounds.moveTo(0, -m_blurBy); renderer2.render(&painter, bounds); bounds.moveTo(m_blurBy, m_blurBy); renderer2.render(&painter, bounds); bounds.moveTo(-m_blurBy, -m_blurBy); renderer2.render(&painter, bounds); bounds.moveTo(-m_blurBy, m_blurBy); renderer2.render(&painter, bounds); bounds.moveTo(m_blurBy, -m_blurBy); renderer2.render(&painter, bounds); } painter.end(); #ifndef QT_NO_DEBUG image->save("testGroundFillCopper.png"); #endif emit postImageSignal(this, image, board); return image; }