Exemplo n.º 1
0
// mostly duplicated from qimage.cpp (QImageData::checkForAlphaPixels)
static bool checkForAlphaPixels(const QImage &img)
{
    const uchar *bits = img.bits();
    const int bytes_per_line = img.bytesPerLine();
    const uchar *end_bits = bits + bytes_per_line;
    const int width = img.width();
    const int height = img.height();
    switch (img.format()) {
    case QImage::Format_Indexed8:
        return img.hasAlphaChannel();
    case QImage::Format_ARGB32:
    case QImage::Format_ARGB32_Premultiplied:
        for (int y=0; y<height; ++y) {
            for (int x=0; x<width; ++x) {
                if ((((uint *)bits)[x] & 0xff000000) != 0xff000000) {
                    return true;
                }
            }
            bits += bytes_per_line;
        }
        break;

    case QImage::Format_ARGB8555_Premultiplied:
    case QImage::Format_ARGB8565_Premultiplied:
        for (int y=0; y<height; ++y) {
            while (bits < end_bits) {
                if (bits[0] != 0) {
                    return true;
                }
                bits += 3;
            }
            bits = end_bits;
            end_bits += bytes_per_line;
        }
        break;

    case QImage::Format_ARGB6666_Premultiplied:
        for (int y=0; y<height; ++y) {
            while (bits < end_bits) {
                if ((bits[0] & 0xfc) != 0) {
                    return true;
                }
                bits += 3;
            }
            bits = end_bits;
            end_bits += bytes_per_line;
        }
        break;

    case QImage::Format_ARGB4444_Premultiplied:
        for (int y=0; y<height; ++y) {
            while (bits < end_bits) {
                if ((bits[0] & 0xf0) != 0) {
                    return true;
                }
                bits += 2;
            }
            bits = end_bits;
            end_bits += bytes_per_line;
        }
        break;

    default:
        break;
    }

    return false;
}
Exemplo n.º 2
0
void QSkinObject::fastbluralpha(QImage &img, int radius)
{
    if (radius < 1) {
        return;
    }

    QRgb *pix = (QRgb*)img.bits();
    int w   = img.width();
    int h   = img.height();
    int wm  = w-1;
    int hm  = h-1;
    int wh  = w*h;
    int div = radius+radius+1;

    int *r = new int[wh];
    int *g = new int[wh];
    int *b = new int[wh];
    int *a = new int[wh];
    int rsum, gsum, bsum, asum, x, y, i, yp, yi, yw;
    QRgb p;
    int *vmin = new int[qMax(w,h)];

    int divsum = (div+1)>>1;
    divsum *= divsum;
    int *dv = new int[256*divsum];
    for (i=0; i < 256*divsum; ++i) {
        dv[i] = (i/divsum);
    }

    yw = yi = 0;

    int **stack = new int*[div];
    for(int i = 0; i < div; ++i) {
        stack[i] = new int[4];
    }


    int stackpointer;
    int stackstart;
    int *sir;
    int rbs;
    int r1 = radius+1;
    int routsum, goutsum, boutsum, aoutsum;
    int rinsum, ginsum, binsum, ainsum;

    for (y = 0; y < h; ++y){
        rinsum = ginsum = binsum = ainsum
               = routsum = goutsum = boutsum = aoutsum
               = rsum = gsum = bsum = asum = 0;
        for(i =- radius; i <= radius; ++i) {
            p = pix[yi+qMin(wm,qMax(i,0))];
            sir = stack[i+radius];
            sir[0] = qRed(p);
            sir[1] = qGreen(p);
            sir[2] = qBlue(p);
            sir[3] = qAlpha(p);
            
            rbs = r1-abs(i);
            rsum += sir[0]*rbs;
            gsum += sir[1]*rbs;
            bsum += sir[2]*rbs;
            asum += sir[3]*rbs;
            
            if (i > 0){
                rinsum += sir[0];
                ginsum += sir[1];
                binsum += sir[2];
                ainsum += sir[3];
            } else {
                routsum += sir[0];
                goutsum += sir[1];
                boutsum += sir[2];
                aoutsum += sir[3];
            }
        }
        stackpointer = radius;

        for (x=0; x < w; ++x) {

            r[yi] = dv[rsum];
            g[yi] = dv[gsum];
            b[yi] = dv[bsum];
            a[yi] = dv[asum];

            rsum -= routsum;
            gsum -= goutsum;
            bsum -= boutsum;
            asum -= aoutsum;

            stackstart = stackpointer-radius+div;
            sir = stack[stackstart%div];

            routsum -= sir[0];
            goutsum -= sir[1];
            boutsum -= sir[2];
            aoutsum -= sir[3];

            if (y == 0) {
                vmin[x] = qMin(x+radius+1,wm);
            }
            p = pix[yw+vmin[x]];

            sir[0] = qRed(p);
            sir[1] = qGreen(p);
            sir[2] = qBlue(p);
            sir[3] = qAlpha(p);

            rinsum += sir[0];
            ginsum += sir[1];
            binsum += sir[2];
            ainsum += sir[3];

            rsum += rinsum;
            gsum += ginsum;
            bsum += binsum;
            asum += ainsum;

            stackpointer = (stackpointer+1)%div;
            sir = stack[(stackpointer)%div];

            routsum += sir[0];
            goutsum += sir[1];
            boutsum += sir[2];
            aoutsum += sir[3];

            rinsum -= sir[0];
            ginsum -= sir[1];
            binsum -= sir[2];
            ainsum -= sir[3];

            ++yi;
        }
        yw += w;
    }
    for (x=0; x < w; ++x){
        rinsum = ginsum = binsum = ainsum 
               = routsum = goutsum = boutsum = aoutsum 
               = rsum = gsum = bsum = asum = 0;
        
        yp =- radius * w;
        
        for(i=-radius; i <= radius; ++i) {
            yi=qMax(0,yp)+x;

            sir = stack[i+radius];

            sir[0] = r[yi];
            sir[1] = g[yi];
            sir[2] = b[yi];
            sir[3] = a[yi];

            rbs = r1-abs(i);

            rsum += r[yi]*rbs;
            gsum += g[yi]*rbs;
            bsum += b[yi]*rbs;
            asum += a[yi]*rbs;

            if (i > 0) {
                rinsum += sir[0];
                ginsum += sir[1];
                binsum += sir[2];
                ainsum += sir[3];
            } else {
                routsum += sir[0];
                goutsum += sir[1];
                boutsum += sir[2];
                aoutsum += sir[3];
            }

            if (i < hm){
                yp += w;
            }
        }

        yi = x;
        stackpointer = radius;

        for (y=0; y < h; ++y){
            pix[yi] = qRgba(dv[rsum], dv[gsum], dv[bsum], dv[asum]);

            rsum -= routsum;
            gsum -= goutsum;
            bsum -= boutsum;
            asum -= aoutsum;

            stackstart = stackpointer-radius+div;
            sir = stack[stackstart%div];

            routsum -= sir[0];
            goutsum -= sir[1];
            boutsum -= sir[2];
            aoutsum -= sir[3];

            if (x==0){
                vmin[y] = qMin(y+r1,hm)*w;
            }
            p = x+vmin[y];

            sir[0] = r[p];
            sir[1] = g[p];
            sir[2] = b[p];
            sir[3] = a[p];

            rinsum += sir[0];
            ginsum += sir[1];
            binsum += sir[2];
            ainsum += sir[3];

            rsum += rinsum;
            gsum += ginsum;
            bsum += binsum;
            asum += ainsum;

            stackpointer = (stackpointer+1)%div;
            sir = stack[stackpointer];

            routsum += sir[0];
            goutsum += sir[1];
            boutsum += sir[2];
            aoutsum += sir[3];

            rinsum -= sir[0];
            ginsum -= sir[1];
            binsum -= sir[2];
            ainsum -= sir[3];

            yi += w;
        }
    }
    delete [] r;
    delete [] g;
    delete [] b;
    delete [] a;
    delete [] vmin;
    delete [] dv;

    for(int i = 0; i < div; ++i) {
        delete [] stack[i];
    }
    delete [] stack;
}
void GLApplication::initTexture() {
    QImage img;
    img.load("../media/lagoon.jpg");
    img=img.convertToFormat(QImage::Format_ARGB32).mirrored();

    glGenTextures(1,&_textureId);
    glBindTexture(GL_TEXTURE_2D,_textureId);
    glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA,img.width(),img.height(),0,GL_BGRA,GL_UNSIGNED_BYTE,img.bits());



    glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
    glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);

    glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_REPEAT);
    glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_REPEAT);
}
Exemplo n.º 4
0
void Uic::embed( QTextStream& out, const char* project, const QStringList& images )
{

    QString cProject = convertToCIdentifier( project );

    QStringList::ConstIterator it;
    out << "/****************************************************************************\n";
    out << "** Image collection for project '" << project << "'.\n";
    out << "**\n";
    out << "** Generated from reading image files: \n";
    for ( it = images.begin(); it != images.end(); ++it )
	out << "**      " << *it << "\n";
    out << "**\n";
    out << "** Created: " << QDateTime::currentDateTime().toString() << "\n";
    out << "**      by: The User Interface Compiler ($Id: embed.cpp 2 2005-11-16 15:49:26Z dmik $)\n";
    out << "**\n";
    out << "** WARNING! All changes made in this file will be lost!\n";
    out << "****************************************************************************/\n";
    out << "\n";

    out << "#include <qimage.h>\n";
    out << "#include <qdict.h>\n";
    out << "#include <qmime.h>\n";
    out << "#include <qdragobject.h>\n";
    out << "\n";

    QPtrList<EmbedImage> list_image;
    list_image.setAutoDelete( TRUE );
    int image_count = 0;
    for ( it = images.begin(); it != images.end(); ++it ) {
	QImage img;
	if ( !img.load( *it ) ) {
	    fprintf( stderr, "uic: cannot load image file %s\n", (*it).latin1() );
	    continue;
	}
	EmbedImage *e = new EmbedImage;
	e->width = img.width();
	e->height = img.height();
	e->depth = img.depth();
	e->numColors = img.numColors();
	e->colorTable = new QRgb[e->numColors];
	e->alpha = img.hasAlphaBuffer();
	memcpy(e->colorTable, img.colorTable(), e->numColors*sizeof(QRgb));
	QFileInfo fi( *it );
	e->name = fi.fileName();
	e->cname = QString("image_%1").arg( image_count++);
	list_image.append( e );
	out << "// " << *it << "\n";
	QString s;
	if ( e->depth == 1 )
	    img = img.convertBitOrder(QImage::BigEndian);
	out << s.sprintf( "static const unsigned char %s_data[] = {",
			  (const char *)e->cname );
#ifndef QT_NO_IMAGE_COLLECTION_COMPRESSION
	e->compressed =
#endif
	    embedData( out, img.bits(), img.numBytes() );
	out << "\n};\n\n";
	if ( e->numColors ) {
	    out << s.sprintf( "static const QRgb %s_ctable[] = {",
			      (const char *)e->cname );
	    embedData( out, e->colorTable, e->numColors );
	    out << "\n};\n\n";
	}
    }

    if ( !list_image.isEmpty() ) {
	out << "static struct EmbedImage {\n"
	    "    int width, height, depth;\n"
	    "    const unsigned char *data;\n"
#ifndef QT_NO_IMAGE_COLLECTION_COMPRESSION
	    "    ulong compressed;\n"
#endif
	    "    int numColors;\n"
	    "    const QRgb *colorTable;\n"
	    "    bool alpha;\n"
	    "    const char *name;\n"
	    "} embed_image_vec[] = {\n";
	EmbedImage *e = list_image.first();
	while ( e ) {
	    out << "    { "
		<< e->width << ", "
		<< e->height << ", "
		<< e->depth << ", "
		<< "(const unsigned char*)" << e->cname << "_data, "
#ifndef QT_NO_IMAGE_COLLECTION_COMPRESSION
		<< e->compressed << ", "
#endif
		<< e->numColors << ", ";
	    if ( e->numColors )
		out << e->cname << "_ctable, ";
	    else
		out << "0, ";
	    if ( e->alpha )
		out << "TRUE, ";
	    else
		out << "FALSE, ";
	    out << "\"" << e->name << "\" },\n";
	    e = list_image.next();
	}
#ifndef QT_NO_IMAGE_COLLECTION_COMPRESSION
	out << "    { 0, 0, 0, 0, 0, 0, 0, 0, 0 }\n};\n";
#else
	out << "    { 0, 0, 0, 0, 0, 0, 0, 0 }\n};\n";
#endif

	out << "\n"
	    "static QImage uic_findImage( const QString& name )\n"
	    "{\n"
	    "    for ( int i=0; embed_image_vec[i].data; i++ ) {\n"
	    "	if ( QString::fromUtf8(embed_image_vec[i].name) == name ) {\n"
#ifndef QT_NO_IMAGE_COLLECTION_COMPRESSION
	    "	    QByteArray baunzip;\n"
	    "	    baunzip = qUncompress( embed_image_vec[i].data, \n"
	    "		embed_image_vec[i].compressed );\n"
	    "	    QImage img((uchar*)baunzip.data(),\n"
	    "			embed_image_vec[i].width,\n"
	    "			embed_image_vec[i].height,\n"
	    "			embed_image_vec[i].depth,\n"
	    "			(QRgb*)embed_image_vec[i].colorTable,\n"
	    "			embed_image_vec[i].numColors,\n"
	    "			QImage::BigEndian\n"
	    "		);\n"
	    "	    img = img.copy();\n"
#else
	    "	    QImage img((uchar*)embed_image_vec[i].data,\n"
	    "			embed_image_vec[i].width,\n"
	    "			embed_image_vec[i].height,\n"
	    "			embed_image_vec[i].depth,\n"
	    "			(QRgb*)embed_image_vec[i].colorTable,\n"
	    "			embed_image_vec[i].numColors,\n"
	    "			QImage::BigEndian\n"
	    "		);\n"
#endif
	    "	    if ( embed_image_vec[i].alpha )\n"
	    "		img.setAlphaBuffer(TRUE);\n"
	    "	    return img;\n"
	    "        }\n"
	    "    }\n"
	    "    return QImage();\n"
	    "}\n\n";

	out << "class MimeSourceFactory_" << cProject << " : public QMimeSourceFactory\n";
	out << "{\n";
	out << "public:\n";
	out << "    MimeSourceFactory_" << cProject << "() {}\n";
	out << "    ~MimeSourceFactory_" << cProject << "() {}\n";
	out << "    const QMimeSource* data( const QString& abs_name ) const {\n";
	out << "\tconst QMimeSource* d = QMimeSourceFactory::data( abs_name );\n";
	out << "\tif ( d || abs_name.isNull() ) return d;\n";
	out << "\tQImage img = uic_findImage( abs_name );\n";
	out << "\tif ( !img.isNull() )\n";
	out << "\t    ((QMimeSourceFactory*)this)->setImage( abs_name, img );\n";
	out << "\treturn QMimeSourceFactory::data( abs_name );\n";
	out << "    };\n";
	out << "};\n\n";

	out << "static QMimeSourceFactory* factory = 0;\n";
	out << "\n";

	out << "void qInitImages_" << cProject << "()\n";
	out << "{\n";
	out << "    if ( !factory ) {\n";
	out << "\tfactory = new MimeSourceFactory_" << cProject << ";\n";
	out << "\tQMimeSourceFactory::defaultFactory()->addFactory( factory );\n";
	out << "    }\n";
	out << "}\n\n";

	out << "void qCleanupImages_" << cProject << "()\n";
	out << "{\n";
	out << "    if ( factory ) {\n";
	out << "\tQMimeSourceFactory::defaultFactory()->removeFactory( factory );\n";
	out << "\tdelete factory;\n";
	out << "\tfactory = 0;\n";
	out << "    }\n";
	out << "}\n\n";

	out << "class StaticInitImages_" << cProject << "\n";
	out << "{\n";
	out << "public:\n";
	out << "    StaticInitImages_" << cProject << "() { qInitImages_" << cProject << "(); }\n";
	out << "#if defined(Q_OS_SCO) || defined(Q_OS_UNIXWARE)\n";
	out << "    ~StaticInitImages_" << cProject << "() { }\n";
	out << "#else\n";
	out << "    ~StaticInitImages_" << cProject << "() { qCleanupImages_" << cProject << "(); }\n";
	out << "#endif\n";
	out << "};\n\n";

	out << "static StaticInitImages_" << cProject << " staticImages;\n";
    }
}
Exemplo n.º 5
0
cv::Mat ImageFormat::QImage2Mat(QImage const& src) {
	 cv::Mat tmp(src.height(),src.width(),CV_8UC3,(uchar*)src.bits(),src.bytesPerLine());
	 cv::Mat result;
	 cvtColor(tmp, result,CV_BGR2RGB);
	 return result;
}
void MyWindow::PrepareTexture(GLenum TextureTarget, const QString& FileName, GLuint& TexObject, bool flip)
{
    QImage TexImg;

    if (!TexImg.load(FileName)) qDebug() << "Erreur chargement texture";
    if (flip==true) TexImg=TexImg.mirrored();

    glGenTextures(1, &TexObject);
    glBindTexture(TextureTarget, TexObject);
    glTexImage2D(TextureTarget, 0, GL_RGB, TexImg.width(), TexImg.height(), 0, GL_BGRA, GL_UNSIGNED_BYTE, TexImg.bits());
    glTexParameterf(TextureTarget, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameterf(TextureTarget, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
}
Exemplo n.º 7
0
void MyGLWidget::loadTextures()
{
  QImage image;
  if (image.load(":/Crate.bmp")) {
      image =  convertToGLFormat(image);
      glGenTextures(3, texture);
      // Create Nearest Filtered Texture
      glBindTexture(GL_TEXTURE_2D, texture[0]);
      glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST);
      glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST);
      glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, image.width(), image.height(), 0, GL_RGBA, GL_UNSIGNED_BYTE, image.bits());

      // Create Linear Filtered Texture
      glBindTexture(GL_TEXTURE_2D, texture[1]);
      glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
      glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
      glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, image.width(), image.height(), 0, GL_RGBA, GL_UNSIGNED_BYTE, image.bits());

      // Create MipMapped Texture
      glBindTexture(GL_TEXTURE_2D, texture[2]);
      glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
      glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR_MIPMAP_NEAREST);
      gluBuild2DMipmaps(GL_TEXTURE_2D, GL_RGBA, image.width(), image.height(), GL_RGBA, GL_UNSIGNED_BYTE, image.bits());
  }
}
Exemplo n.º 8
0
/**
 Draw the robot into a copy of the tracking image
 before displaying in a named window.

 TODO: this function has grown too big - need to refactor!
 **/
QImage showRobotTrack( const RobotTracker* tracker, bool tracking )
{
    const int DONT_FLIP = 0;

    const IplImage* const currentImg = tracker->GetCurrentImage();

    IplImage* img = cvCreateImage( cvSize( currentImg->width,
                                           currentImg->height ), IPL_DEPTH_8U, 3 );
    cvConvertImage( currentImg, img );

    CvPoint2D32f oldPosf, newPosf;

    // Draw the path taken so far (but each point needs
    // to be converted from plane, to image co-ordinates)
    const TrackHistory& history = tracker->GetHistory();

    if ( history.size() > 1 )
    {
        CvPoint2D32f pos = history[0].GetPosition();
        float angle = history[0].GetOrientation();
        oldPosf = tracker->AdjustTrackForRobotHeight( pos, angle );
        CvPoint oldPos = cvPoint( ( int )oldPosf.x, ( int )oldPosf.y );

        for ( unsigned int i = 1; i < history.size(); ++i )
        {
            double tdiff = fabs( history[i].t() - history[i - 1].t() );
            pos = history[i].GetPosition();
            angle = history[i].GetOrientation();

            if ( tdiff > 2000.0 / 3.0 )
            {
                oldPosf = tracker->AdjustTrackForRobotHeight( pos, angle );
                oldPos = cvPoint( ( int )oldPosf.x, ( int )oldPosf.y );
            }
            else
            {
                newPosf = tracker->AdjustTrackForRobotHeight( pos, angle );
                CvPoint newPos = cvPoint( ( int )newPosf.x, ( int )newPosf.y );

                CvScalar colour;
                colour = cvScalar( 0, 0, 255 );
                cvLine( img, oldPos, newPos, colour, 1, CV_AA );

                oldPos = newPos;
            }
        }
    }


    if (tracking)
    {
        // Draw circle around base of robot
        CvPoint2D32f pos = tracker->GetPosition();
        float angle = tracker->GetHeading();

        float baseRadius = tracker->GetMetrics()->GetBasePx();
        float robotRadius = tracker->GetMetrics()->GetRadiusPx();

        CvPoint2D32f basePos = tracker->AdjustTrackForRobotHeight( pos, angle );
        CvPoint pb = cvPoint( ( int )( basePos.x + .5f ), ( int )( basePos.y + .5f ) );

        cvCircle( img, pb, ( int )( baseRadius ), CV_RGB( 250,250,0 ), 1, CV_AA );

        // Draw circle around top of robot
        pos = tracker->GetPosition();
        CvPoint p = cvPoint( ( int )( pos.x + .5f ), ( int )( pos.y + .5f ) );

        cvCircle( img, p, ( int )( robotRadius + 1.5f ), cvScalar( 255, 0, 0 ), 1, CV_AA );

        // Draw heading
        float heading = tracker->GetHeading();
        float offset = F_PI * ( 2.0f / 3.0f );
        CvPoint2D32f h;
        CvPoint a, b;

        for ( unsigned int c = 0; c < 3; ++c )
        {
            switch ( c )
            {
                case 0:
                {
                    angle = heading;
                    break;
                }
                case 1:
                {
                    angle = heading + offset;
                    break;
                }
                case 2:
                {
                    angle = heading - offset;
                    break;
                }
                default:
                    angle = 0.f;
                    break;
            }

            h = cvPoint2D32f( cos( -angle ), sin( -angle ) );
            a = cvPoint( ( int )( p.x - ( ( robotRadius - 5.f ) * h.x + .5f ) ),
                         ( int )( p.y - ( ( robotRadius - 5.f ) * h.y + .5f ) ) );
            b = cvPoint( ( int )( p.x - ( ( robotRadius + 7.f ) * h.x + .5f ) ),
                         ( int )( p.y - ( ( robotRadius + 7.f ) * h.y + .5f ) ) );

            cvLine( img, a, b, cvScalar( 255, 0, 0 ), 2, CV_AA );
        }

        // Draw brush bar
        CvPoint2D32f pl = tracker->GetBrushBarLeft( basePos, heading );
        CvPoint2D32f pr = tracker->GetBrushBarRight( basePos, heading );

        cvLine( img, cvPoint( ( int )pl.x, ( int )pl.y ),
                     cvPoint( ( int )pr.x, ( int )pr.y ),
                     cvScalar( 0, 0, 255 ),
                     3,
                     CV_AA );
    }

    // Convert from IplImage to QImage...
    const QSize imgSize( img->width, img->height );
    QImage qimage = QImage( imgSize, QImage::Format_RGB888 );

    CvMat mtxWrapper;
    cvInitMatHeader( &mtxWrapper,
                     img->height,
                     img->width,
                     CV_8UC3,
                     qimage.bits() );

    cvConvertImage( img, &mtxWrapper, DONT_FLIP );

    cvReleaseImage( &img );

    return qimage;
}
Exemplo n.º 9
0
/**
 Draw the robot position in the original image sequence.
 Need to know the entire camera calibration (and more) for this...
 **/
QImage showRobotTrackUndistorted( IplImage*           img,        ///< original avi image
                                  const RobotTracker* tracker,    ///< robot tracker
                                  int                 flip        ///< flip output coords?
                                )
{
    // Convert from IplImage to QImage...
    const QSize imgSize( img->width,img->height );
    QImage qimage = QImage( imgSize, QImage::Format_RGB888 );

    CvMat mtxWrapper;
    cvInitMatHeader( &mtxWrapper,
                     img->height,
                     img->width,
                     CV_8UC3,
                     qimage.bits() );

    cvConvertImage( img, &mtxWrapper, flip );

    // Now draw on top of the QImage...

    QPainter painter(&qimage);
    painter.setRenderHint(QPainter::Antialiasing, true);

    QPen penRed( QColor(255,0,0) );
    QPen penBlue( QColor(0,0,255) );
    QPen penRedGreen( QColor(255,255,0) );

    CvPoint2D32f offset = *tracker->GetOffsetParams();
    const CameraCalibration* cal = tracker->GetCalibration();

    // Draw the path taken so far (but each point needs to be converted from plane, to image co-ordinates)
    const TrackHistory& history = tracker->GetHistory();

    if ( history.size() > 1 )
    {
        CvPoint2D32f pos = history[0].GetPosition();
        pos.x += offset.x;
        pos.y += offset.y;
        CvPoint2D32f oldPosf = cal->PlaneToImage( pos );

        if ( flip )
        {
            oldPosf.y = img->height - oldPosf.y;
        }

        CvPoint oldPos = cvPoint( ( int )oldPosf.x, ( int )oldPosf.y );

        for ( unsigned int i = 1; i < history.size(); ++i )
        {
            double tdiff = fabs( history[i].t() - history[i - 1].t() );

            if ( tdiff > 2000.0 / 3.0 )
            {
                pos = history[i].GetPosition();
                pos.x += offset.x;
                pos.y += offset.y;
                oldPosf = cal->PlaneToImage( pos );

                if ( flip )
                {
                    oldPosf.y = img->height - oldPosf.y;
                }

                oldPos = cvPoint( ( int )oldPosf.x, ( int )oldPosf.y );
            }
            else
            {
                pos = history[i].GetPosition();
                pos.x += offset.x;
                pos.y += offset.y;
                CvPoint2D32f newPosf = cal->PlaneToImage( pos );

                if ( flip )
                {
                    newPosf.y = img->height - newPosf.y;
                }

                CvPoint newPos = cvPoint( ( int )newPosf.x, ( int )newPosf.y );

                //CvScalar colour;

                //float err = expf( -powf( (1.f-history[i].GetError())/0.5f, 4) );
                //float col = 255*err;
                //colour = CV_RGB( 255,0,0 ); //cvScalar( col, col, 255 );
                //  if ( err > 0.35f )
                //  {
                //      colour = cvScalar(0,255,0);
                //  }
                //  else
                //  {
                //      colour = cvScalar(0,0,255);
                //  }

                //cvLine( img, oldPos, newPos, colour, 1, CV_AA );

                penRed.setWidth( 2 );
                painter.setPen( penRed );
                painter.drawLine( oldPos.x, oldPos.y, newPos.x, newPos.y );
                oldPos = newPos;
            }
        }
    }

    return qimage;
}
Exemplo n.º 10
0
bool SSAO::loadNoiseTxt(){

    QImage image = QImage();
    QString textureName = QString(":/rand.png");
    if (QFile(textureName).exists())
    {
        image = QImage(textureName);
        noiseWidth=image.width();
        noiseHeight=image.height();

        QImage tmpGL = QGLWidget::convertToGLFormat(image);
        image = QImage(tmpGL);
    }
    else {
        qDebug("Warning failed to load noise texture!");
        assert(0);
        return false;
    }

    // Creates The Texture
    glGenTextures(1, &(this->_noise));
    glBindTexture(GL_TEXTURE_2D, this->_noise);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, noiseWidth , noiseHeight, 0, GL_RGB, GL_UNSIGNED_BYTE, image.bits());

    return true;
}
Exemplo n.º 11
0
/**
 * Use the sketch as an input to the pretrained network, and obtain the probabilities as output.
 * Then, display the options ordered by the probabilities.
 */
void GLWidget3D::predict() {
	QImage swapped = sketch.scaled(256, 256).rgbSwapped();
	cv::Mat img = cv::Mat(swapped.height(), swapped.width(), CV_8UC3, const_cast<uchar*>(swapped.bits()), swapped.bytesPerLine()).clone();

	std::vector<Prediction> predictions = classifier->Classify(img, 10);
	mainWin->clearList();
	QPainter painter(&sketch);
	for (size_t i = 0; i < predictions.size(); ++i) {
		Prediction p = predictions[i];
		mainWin->addListItem(QString::number(p.second, 'f', 3), images[p.first], p.first);
	}

	update();
}
void Terrain::uploadMaterial(QString fileName, GLuint textureID) {
    QImage material = QGLWidget::convertToGLFormat(QImage(fileName));

    glBindTexture(GL_TEXTURE_2D, textureID);
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, material.width(), material.height(), 0, GL_RGBA, GL_UNSIGNED_BYTE, material.bits());
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
    glGenerateMipmap(GL_TEXTURE_2D);
    glBindTexture(GL_TEXTURE_2D, 0);

    checkGLErrors("material upload");
}
Exemplo n.º 13
0
void Texture::load(const QString &fileName)
{
    // загружаем изображение из файла
    QImage image(fileName);
    if (!image.isNull())
    {
        // конвертируем изображение в формат, подходящий для OpenGL
        QImage GLImage = QGLWidget::convertToGLFormat(image);
        mSize = GLImage.size();

        // создаем текстуру
        glGenTextures(1, &mHandle);
        glBindTexture(GL_TEXTURE_2D, mHandle);
        glTexImage2D(GL_TEXTURE_2D, 0, 4, GLImage.width(), GLImage.height(), 0, GL_RGBA, GL_UNSIGNED_BYTE, GLImage.bits());

        // настраиваем параметры текстуры
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
    }
}
Exemplo n.º 14
0
int main(int argc, char *argv[])
{
	QApplication app(argc, argv);
	QString folder = QFileDialog::getExistingDirectory(NULL, "Load Video");

	loadHomographies(folder.toStdString());
	loadBoards(folder.toStdString());

	RX::VideoDecoder _profVideo, _otherVideo;
	QImage frame;
	_profVideo.openFile(folder+"/VideoProf.avi");
	_profVideo.seekNextFrame();
	_profVideo.getFrame(frame);

	QImage frame2;
	_otherVideo.openFile(folder+"/Video.avi");
	_otherVideo.seekNextFrame();
	_otherVideo.getFrame(frame2);

	int h = frame.height();
	int w = frame.width();

	unsigned char *screen = new unsigned char[w*h*4];

	RX::mat3 _hom;
	_hom.setIdentity();
	int f = 0;

	// get intersections
	vector< vector<bool> > intersections;
	do
	{
		_otherVideo.getFrame(frame2);
		_profVideo.getFrame(frame);

		for(int i = 0; i < h; ++i) {
			for(int j = 0; j < w; ++j) {
				if(frame.bits()[(i*w + j)*3] != 0 || frame.bits()[(i*w + j)*3 + 1] != 0 || frame.bits()[(i*w + j)*3 + 2] != 0) 
				{
					frame.bits()[(i*w + j)*3] = 255;
					frame.bits()[(i*w + j)*3 + 1] = 0;
					frame.bits()[(i*w + j)*3 + 2] = 255;
				}
			}
		}
		_hom = _homographies[f].inverse();

		int totalPinks = RX::SoftwareRenderer::countColor(RX::vec3(255, 0, 255), RX::vec3(0, 0, 1), RX::vec3(w, 0, 1), RX::vec3(w, h, 1), RX::vec3(0, h, 1), frame.bits(), w, h, 3, 3);

		vector<bool> intersecting;
		for(int i = 0; i < _boards[f].size(); ++i) 
		{	
			intersecting.push_back(false);

			RX::vec3 p[4];
			for(int j = 0; j < 4; ++j) {
				p[j] = _hom * RX::vec3(_boards[f][i].points[j].x, _boards[f][i].points[j].y, 1);
			}

			memcpy(screen, frame.bits(), w*h*3);
			RX::SoftwareRenderer::render(RX::vec3(0, 255, 0), p[0], p[1], p[2], p[3], screen, frame.width(), frame.height(), 3);

			if(i == 0)
			{
				char buf[40];
				sprintf(buf, "image_%d.png", f);
				QImage image(screen, w, h, QImage::Format_RGB888);
				image.save(buf);

				sprintf(buf, "image_%d_b.png", f);
				frame2.save(buf);
			}

			int newPinks = RX::SoftwareRenderer::countColor(RX::vec3(255, 0, 255), RX::vec3(0, 0, 1), RX::vec3(w, 0, 1), RX::vec3(w, h, 1), RX::vec3(0, h, 1), screen, w, h, 3, 3);
			if(newPinks < totalPinks)
				intersecting[i] = true;
		}
		intersections.push_back(intersecting);
		++f;
		cout << f << endl;
		// provisory
		if(f == 10000)
			break;

		_otherVideo.seekNextFrame();
	}
	while(_profVideo.seekNextFrame());
	
	delete[] screen;

	// change intersections into intervals
	std::ofstream intersectFile("intersectFile.txt");
	intersectFile << intersections.size() << std::endl;
	for(int i = 0; i < intersections.size(); ++i)
	{
		for(int j = 0; j < intersections[i].size(); ++j)
		{
			intersectFile << j << " " << intersections[i][j] << " " << std::endl;
		}
		intersectFile << "#####################################################################" << std::endl;
	}

	vector<bool> state;
	for(int i = 0; i < _boards[0].size(); ++i) {
		state.push_back(true);
		_intervals.push_back(vector<Interval>());
	}

	for(int i = 0; i < intersections.size(); ++i)
	{
		for(int j = 0; j < state.size(); ++j)
		{
			if(state[j] != intersections[i][j])
			{
				if(intersections[i][j])
					_intervals[j][_intervals[j].size()-1].end = i-1;
				else
					_intervals[j].push_back(Interval(i, -1));

				state[j] = intersections[i][j];
			}
		}
	}
	for(int i = 0; i < _intervals.size(); ++i)
		for(int j = 0; j < _intervals[i].size(); ++j)
			if(_intervals[i][j].end == -1)
				_intervals[i][j].end = f;

	saveIntervals(folder.toStdString());

}
void
get_transformed_pixmap(QPixmap* originalPixmap,
		       QPixmap* destPixmap,
		       int src_x, int src_y, 
		       int src_width, int src_height,
		       int transform,
		       bool hasAlpha) {

    QImage originalImage = originalPixmap->convertToImage();

    if ( hasAlpha ) {
	// Qt's handling of the alpha channel in the conversion
	// process between QPixmap and QImage is buggy.
	// If the pixmap's pixels only have alpha values 0x00 and 0xFF
	// then the resulting QImage from conversion will return
	// false for hasAlphaBuffer().
	// so we set our own flag instead of depending on Qt to 
	// maintain alpha information.
	originalImage.setAlphaBuffer(TRUE);
    }

    /*Qt gives us this useful API that returns a section of a QImage*/
    QImage sectionImage  = originalImage.copy(src_x, src_y, 
					      src_width, src_height);
    /* Skip this pixel-by-pixel copy if there is no transform */
    if (0 != transform) {
	QImage sectionImage32bpp = sectionImage.convertDepth(32);
	QImage processedImage;
	
	
	int nXOriginSrc = 0;
	int nYOriginSrc = 0;
	int nWidth      = src_width;
	int nHeight     = src_height;
	
	/*scan length of the source image*/
	int imageWidth  = src_width;
	/*number of rows of the source image*/
	int imageHeight = src_height;
	
	int imgLen;
	int srcImgLen;
	
	int t_width;
	int t_height;
	
	int srcX;
	int srcY;
	int xStart;
	int yStart;
	int xIncr;
	int yIncr;
	int destX;
	int destY;
	int yCounter;
	int xCounter;
	
	int srcIndex;
	int destIndex;
	
	uchar* srcBits     = NULL;
	uchar* destBits    = NULL;
	
	uchar* srcBitsPtr  = NULL;
	uchar* destBitsPtr = NULL;
	
	
	/* set dimensions of image being created,
	   depending on transform */
	if (transform & TRANSFORM_INVERTED_AXES) {
	    t_width  = src_height;
	    t_height = src_width;
	} else {
	    t_width  = src_width;
	    t_height = src_height;
	}
	
	/* width * height * 4 gives us the size of a 32 bpp image */
	imgLen = nWidth * nHeight << 2;
	srcImgLen = imageWidth  * imageHeight << 2;
	
	/* Qt specific */
	processedImage.create(t_width, t_height, 32);
	
	srcBits  = sectionImage32bpp.bits();
	destBits = processedImage.bits();
	/* ----------- */
	
	if (transform & TRANSFORM_Y_FLIP) {
	    yStart = nHeight-1;
	    yIncr = -1;
	} else {
	    yStart = 0;
	    yIncr = +1;
	}
	
	if (transform & TRANSFORM_X_FLIP) {
	    xStart = nWidth-1;
	    xIncr = -1;
	} else {
	    xStart = 0;
	    xIncr = +1;
	}
	
	srcBitsPtr  = srcBits;
	destBitsPtr = destBits;
	
	
	/* increment srcX,Y regular. increment destX,Y according to transform.
	   this makes handling of mask and alpha values easier */
	
	for (srcY = nYOriginSrc, destY = yStart, yCounter = 0; 
	     yCounter < nHeight; 
	     srcY++, destY+=yIncr, yCounter++) {
	    
	    /* in the current implementation we have source bitmap
	       dimension as the width of the image and the height of the region
	       destination bitmap is of the dimensions of the region */
	    
	    for (srcX = nXOriginSrc, destX = xStart, xCounter = 0; 
		 xCounter < nWidth; 
		 srcX++, destX+=xIncr, xCounter++) {
		
		if ( transform & TRANSFORM_INVERTED_AXES ) {
		    destIndex =  ( ( (destX) * t_width) + (destY) );
		} else {
		    destIndex =  ( ( (destY) * t_width) + (destX) );
		}
		
		destBitsPtr =  destBits + (destIndex * 4) ;
		
		srcIndex = (((srcY) * imageWidth) + (srcX));
		srcBitsPtr = srcBits + (srcIndex * 4);
		
		
		/* copy the pixel that is pointed to */
		*((int *)destBitsPtr) = *((int *)srcBitsPtr);
		
	    } /*for x*/
	    
	} /* for y */
	
	
	/* ---------- */

	if(TRUE == sectionImage.hasAlphaBuffer() ) {
	    processedImage.setAlphaBuffer(TRUE);
	} else {
	    processedImage.setAlphaBuffer(FALSE);
	}
	
	destPixmap->convertFromImage(processedImage);
    } else {
	/* No transform, just copy the image sub-section */
	destPixmap->convertFromImage(sectionImage);
    }
}
Exemplo n.º 16
0
void TerrainProfileWidget::initialize()
{
  QVBoxLayout* vStack = new QVBoxLayout();
  vStack->setSpacing(0);
  vStack->setContentsMargins(0, 0, 0, 0);
  setLayout(vStack);

  // create actions
  _captureAction = new QAction(QIcon(":/images/crosshair.png"), tr(""), this);
  _captureAction->setToolTip(tr("Capture map clicks"));
  _captureAction->setCheckable(true);
  connect(_captureAction, SIGNAL(toggled(bool)), this, SLOT(onCaptureToggled(bool)));

  _undoZoomAction = new QAction(QIcon(":/images/undo.png"), tr(""), this);
  _undoZoomAction->setToolTip(tr("Undo zoom"));
  connect(_undoZoomAction, SIGNAL(triggered()), this, SLOT(onUndoZoom()));
  _undoZoomAction->setEnabled(false);

  // create toolbar
  QToolBar *buttonToolbar = new QToolBar(tr("Action Toolbar"));
  buttonToolbar->setIconSize(QSize(24, 24));
  buttonToolbar->addAction(_captureAction);
  buttonToolbar->addSeparator();
  buttonToolbar->addAction(_undoZoomAction);
  vStack->addWidget(buttonToolbar);

  // create graph widget
  _graph = new TerrainProfileGraph(_calculator, new UpdatePositionShim(this));
  vStack->addWidget(_graph);

  // define a style for the line
  osgEarth::Symbology::LineSymbol* ls = _lineStyle.getOrCreateSymbol<osgEarth::Symbology::LineSymbol>();
  ls->stroke()->color() = osgEarth::Symbology::Color::White;
  ls->stroke()->width() = 2.0f;
  ls->tessellation() = 20;
  _lineStyle.getOrCreate<osgEarth::Symbology::AltitudeSymbol>()->clamping() = osgEarth::Symbology::AltitudeSymbol::CLAMP_TO_TERRAIN;

  // load marker image
  QImage image(":/images/marker.png"); 
  QImage glImage = QGLWidget::convertToGLFormat(image); 

  unsigned char* data = new unsigned char[glImage.byteCount()];
	for(int i=0; i<glImage.byteCount(); i++)
	{
		data[i] = glImage.bits()[i];
	}

  _markerImage = new osg::Image(); 
  _markerImage->setImage(glImage.width(), 
                         glImage.height(), 
                         1, 
                         4, 
                         GL_RGBA, 
                         GL_UNSIGNED_BYTE, 
                         data, 
                         osg::Image::USE_NEW_DELETE, 
                         1); 

  // setup placemark style
  _placeStyle.getOrCreate<AltitudeSymbol>()->clamping() = AltitudeSymbol::CLAMP_TO_TERRAIN;
}
Exemplo n.º 17
0
QImage edge_detector::blob_extract(const QImage image)
{
    QImage destImage = QImage( image);
    merge_find mf;

    int H = destImage.height();
    int W = destImage.width();

    int* srcData = (int *)image.bits();
    int* destData = (int *)destImage.bits();

    // target image initialized with numbers
    for (int row=0; row<H; row++)
    {
        for (int column=0; column<W; column++)
        {
            QColor qc = QColor(srcData[row*W+column]);
#ifdef Canny_Edge_Detection
            // this initiation is used as step 5, edge tracking, of Canny Edge Detection
            // assign the pixel as black:0, white:1, yellow:2, red:3, green:4, blue:5
            int color = 0;
            if (qc.red() == 255 && qc.green() == 255 && qc.blue() == 255) color = 1;
            else if (qc.red() == 255 && qc.green() == 255) color = 2;
            else if (qc.red() == 255) color = 3;
            else if (qc.green() == 255) color = 4;
            else if (qc.blue() == 255) color = 5;
            destData[row*W+column] = color;
#else
            // this initiation is used for blobs categorizing
            // to be white if not background.
            destData[row*W+column] = (srcData[row*W+column] & 0x0000ff) > 200 ? 1 : 0;
#endif // Canny_Edge_Detection
       }
    }

    vector<Node> linked;
    vector<int> n_labels;

    int nextLabel(1);

    // First pass
    for (int row=0; row<H; row++)
    {
        for (int column=0; column<W; column++)
        {
            if (int color = destData[row*W+column] & 0x000007) // is not Background
            {
                // neighbors = connected elements with the current element's value
                int** neighbors = get_neighbor_pixels(destImage, column, row, 1);

                int lowest = mf.find_lowest(neighbors, 1);

                if (lowest == 0) // if neighbor is empty
                {
                    Node node = /*new*/ Node(nextLabel, destData[row*W+column] & 0x000007);
                    linked.push_back(node);
                    destData[row*W+column] = nextLabel;
                    nextLabel++;
                }
                else // to assign the smallest label
                {
                    destData[row*W+column] = lowest;
                    n_labels = mf.get_neighbor_labels(neighbors, 1);

                    // this is the key to link weak points to strong
                    if (color == 1)
                        linked[lowest-1].color = 1;

                    for (int l=0; l<(int)n_labels.size(); l++)
                        if (n_labels[l] > 0)
                            mf.merge(linked[n_labels[l]-1], linked[lowest-1]);
                }
                deleteArray(neighbors, 3); // 3=1*2+1
            }
        }
    }

    // Second pass
    for (int row=0; row<H; row++)
    {
        for (int column=0; column<W; column++)
        {
            int x = destData[row*W+column] & 0x0000ff;

            if (x) // is not Background
            {
                Node root = mf.find(linked[x-1]);
#ifdef Canny_Edge_Detection
                // this color recovery is for Canny Edge Detection
                QColor qc = (root.color == 1) ? Qt::white : Qt::black;
//                            (root.color == 2) ? Qt::yellow : // test
//                            (root.color == 3) ? Qt::red :
//                            (root.color == 4) ? Qt::green :
//                            (root.color == 5) ? Qt::blue : Qt::black;
                destData[row*W+column] = qc.rgba();
#else
                // Blobs categorizing
                destData[row*W+column] = 0x0000ff << root.label;
#endif // Canny_Edge_Detection
                //printf("(%i %i) ", x, root.color);
            }
        }
    }

    return destImage;
}
Exemplo n.º 18
0
void Controller::matchWCQimage2Mat(QImage image)
{
	cv::Mat mat(image.height(),image.width(),CV_8UC3,(uchar*)image.bits(),image.bytesPerLine());
}
Exemplo n.º 19
0
void VideoProgress::onNextFrame() {
  size_t maxFrames = encoder->fpsValue() * durationSeconds;

  renderSurface->renderNow(frameCount/float(encoder->fpsValue()));
  QImage image = renderSurface->getImage();

  //if (!frameCount || frameCount % 3 == 0) {
    QImage preview = image.scaled(320,200,Qt::KeepAspectRatio,Qt::FastTransformation);
    frame->setPixmap(QPixmap::fromImage(preview));
  //}

  image = image.convertToFormat(QImage::Format_RGB888);

  vpx_image_t* vpxImage = vpx_img_alloc(NULL, VPX_IMG_FMT_RGB24, renderSurface->width(), renderSurface->height(), 1);
  if (!vpxImage) {
    finishCapture("An error occured during capture: Out of memory.");
    return;
  }

  size_t size = renderSurface->width() * renderSurface->height() * 3;
  if (size != size_t(image.byteCount())) {
    finishCapture("An error occured during capture: Image size error.");
    vpx_img_free(vpxImage);
    return;
  }

  memcpy(vpxImage->img_data, image.bits(), size);

  if (!encoder->writeFrame(vpxImage)) {
    finishCapture("An error occured during capture: Frame write error.");
    vpx_img_free(vpxImage);
    return;
  }

  if (vpxImage) {
    vpx_img_free(vpxImage);
  }

  bool complete = false;
  if (++frameCount == maxFrames) {
    finalFrame = true;
    complete = true;
  } else {
    bar->setValue(frameCount/float(maxFrames)*100);
  }

  if (finalFrame) {
    bar->setValue(100);
    encoder->finish();
    delete encoder;
    if (complete) {
      finishCapture("The capture is complete.");
    } else {
      finishCapture("The capture was canceled.");
    }
  }

  if (!finalFrame) {
    QTimer::singleShot(0, this, SLOT(onNextFrame()));
  }
}
Exemplo n.º 20
0
osg::Image* QgsOsgEarthTileSource::createImage( const TileKey& key, ProgressCallback* progress )
{
  QString kname = key.str().c_str();
  kname.replace( '/', '_' );

  Q_UNUSED( progress );

  //Get the extents of the tile
  int tileSize = getPixelsPerTile();
  if ( tileSize <= 0 )
  {
    QgsDebugMsg( "Tile size too small." );
    return ImageUtils::createEmptyImage();
  }

  QgsRectangle viewExtent = mQGisIface->mapCanvas()->fullExtent();
  if ( mCoordTransform )
  {
    QgsDebugMsg( QString( "vext0:%1" ).arg( viewExtent.toString( 5 ) ) );
    viewExtent = mCoordTransform->transformBoundingBox( viewExtent );
  }

  QgsDebugMsg( QString( "vext1:%1" ).arg( viewExtent.toString( 5 ) ) );

  double xmin, ymin, xmax, ymax;
  key.getExtent().getBounds( xmin, ymin, xmax, ymax );
  QgsRectangle tileExtent( xmin, ymin, xmax, ymax );

  QgsDebugMsg( QString( "text0:%1" ).arg( tileExtent.toString( 5 ) ) );
  if ( !viewExtent.intersects( tileExtent ) )
  {
    QgsDebugMsg( QString( "earth tile key:%1 ext:%2: NO INTERSECT" ).arg( kname ).arg( tileExtent.toString( 5 ) ) );
    return ImageUtils::createEmptyImage();
  }

#ifdef USE_RENDERER
  QImage *qImage = createQImage( tileSize, tileSize );
  if ( !qImage )
  {
    QgsDebugMsg( QString( "earth tile key:%1 ext:%2: EMPTY IMAGE" ).arg( kname ).arg( tileExtent.toString( 5 ) ) );
    return ImageUtils::createEmptyImage();
  }

  mMapRenderer->setLayerSet( mQGisIface->mapCanvas()->mapRenderer()->layerSet() );
  mMapRenderer->setOutputSize( QSize( tileSize, tileSize ), qImage->logicalDpiX() );
  mMapRenderer->setExtent( tileExtent );

  QPainter thePainter( qImage );
  mMapRenderer->render( &thePainter );
#else
  mMapSettings.setLayers( mQGisIface->mapCanvas()->mapSettings().layers() );
  mMapSettings.setOutputSize( QSize( tileSize, tileSize ) );
  mMapSettings.setOutputDpi( QgsApplication::desktop()->logicalDpiX() );
  mMapSettings.setExtent( tileExtent );
  mMapSettings.setBackgroundColor( QColor( 0, 0, 0, 0 ) );

  QgsMapRendererSequentialJob job( mMapSettings );
  job.start();
  job.waitForFinished();

  QImage *qImage = new QImage( job.renderedImage() );
  if ( !qImage )
  {
    QgsDebugMsg( QString( "earth tile key:%1 ext:%2: EMPTY IMAGE" ).arg( kname ).arg( tileExtent.toString( 5 ) ) );
    return ImageUtils::createEmptyImage();
  }

  Q_ASSERT( qImage->logicalDpiX() == QgsApplication::desktop()->logicalDpiX() );
  Q_ASSERT( qImage->format() == QImage::Format_ARGB32_Premultiplied );
#endif

  QgsDebugMsg( QString( "earth tile key:%1 ext:%2" ).arg( kname ).arg( tileExtent.toString( 5 ) ) );
#if 0
  qImage->save( QString( "/tmp/tile-%1.png" ).arg( kname ) );
#endif

  osg::ref_ptr<osg::Image> image = new osg::Image;

  //The pixel format is always RGBA to support transparency
  image->setImage( tileSize, tileSize, 1, 4, // width, height, depth, pixelFormat?
                   GL_BGRA, GL_UNSIGNED_BYTE, //Why not GL_RGBA - Qt bug?
                   qImage->bits(),
                   osg::Image::NO_DELETE, 1 );

  image->flipVertical();

  //Create a transparent image if we don't have an image
  if ( !image.valid() )
  {
    QgsDebugMsg( "image is invalid" );
    return ImageUtils::createEmptyImage();
  }

  QgsDebugMsg( "returning image" );
  return image.release();
}
Exemplo n.º 21
0
// Function is adapted from:
//   http://stackoverflow.com/questions/10684705/texture-loading-with-opengl-in-qt
void GLWidget::loadGLTextures()
{
        QImage t;
        QImage b;

        if ( !b.load( "models/iphone/Textures/Iphone_texture.jpg" ) )
        {
                qDebug("Unable to open the image.");
                b = QImage( 16, 16, QImage::Format_RGB32 );
                b.fill( 1 );
        }

        t = QGLWidget::convertToGLFormat( b );
        glGenTextures( 1, asset->GetTexCoordVBO() );
        glBindTexture( GL_TEXTURE_2D, *(asset->GetTexCoordVBO()) );

        printf( "%p\n", asset->GetTexCoordVBO() );

        unsigned int p2 = *(asset->GetTexCoordVBO());
        std::cout << "*(asset->GetTexCoordVBO()) = " << p2 << std::endl;

        glTexImage2D( GL_TEXTURE_2D, 0, 3, t.width(), t.height(), 0, GL_RGBA, GL_UNSIGNED_BYTE, t.bits() );
        //glTexImage2D( GL_TEXTURE_2D, 0, 3, t.height(), t.width(), 0, GL_RGBA, GL_UNSIGNED_BYTE, t.bits() );
        glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
        glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
        glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
}
Exemplo n.º 22
0
void DccVideoSJpegCodec::decode(KviDataBuffer * stream,KviDataBuffer * videoSignal,KviDataBuffer * textSignal)
{
	static unsigned const char jpg_magic_init[4] = { 0xFF, 0xD8, 0xFF, 0xE0}; //SOI + APP0
	static unsigned const char jpg_magic_end[2] = { 0xFF, 0xD9}; //EOI

	static unsigned const char *irct_magic_init = (unsigned const char*) "\0<text>\0";
	static unsigned const char *irct_magic_end = (unsigned const char*) "\0</text>\0";

	if(stream->size() < 1)return;


	int txtStart = stream->find(irct_magic_init, 8);
	int txtEnd = stream->find(irct_magic_end, 9);

	int jpgStart = stream->find(jpg_magic_init, 4);

	if(txtStart!=-1 && txtEnd !=-1 && txtStart<jpgStart)
	{
		qDebug("a txtStart %d txtEnd %d",txtStart,txtEnd);
		stream->remove(txtStart+8);
		int len = txtEnd - txtStart -8; //-8 irct_magic_init
		if(len>0)
		{
			textSignal->append(stream->data(), len);
			char*txt=(char*)malloc(len+1);
			memcpy(txt,stream->data(), len);
			txt[len]='\0';
			qDebug("a recv |%s| %d",txt,len);
		}
		stream->remove(len+9);
	}

	if(stream->size() < 1)return;

	jpgStart = stream->find(jpg_magic_init, 4);
	int jpgEnd = stream->find(jpg_magic_end, 2);

	if(jpgStart != -1 && jpgEnd != -1)
	{
// 		qDebug("jpgStart %d jpgEnd %d",jpgStart,jpgEnd);
		QImage img;
		//remove junk before jpeg start
		if(jpgStart > 0)
			stream->remove(jpgStart);

		int len = jpgEnd - jpgStart + 1;

		img.loadFromData(stream->data(), stream->size());
		if(!img.isNull())
		{
			videoSignal->clear();
			videoSignal->append(img.bits(),img.byteCount());
		}
		stream->remove(len);
	}

	txtStart = stream->find(irct_magic_init, 8);
	txtEnd = stream->find(irct_magic_end, 9);

	if(txtStart!=-1 && txtEnd !=-1)
	{
		qDebug("b txtStart %d txtEnd %d",txtStart,txtEnd);
		stream->remove(txtStart+8);
		int len = txtEnd - txtStart -8; //-8 irct_magic_init
		if(len>0)
		{
			textSignal->append(stream->data(), len);
			char*txt=(char*)malloc(len+1);
			memcpy(txt,stream->data(), len);
			txt[len]='\0';
			qDebug("b recv |%s| %d",txt,len);
		}
		stream->remove(len+9);
	}
}
Exemplo n.º 23
0
Moon::Moon()
{

    QImage img;
    if( !img.load("/Users/mrigyaagarwal/Desktop/third_year/graphics/Graphics/solarSystem/OpenGL_Framework 2/moon.bmp")){
        qWarning("ERROR LOADING IMAGE");
    }

   // img.save("/Users/christinegraff/Documents/OpenGL_Framework 2/asdasd.bmp");

    //img.save("asd");
    //cout<< img << endl;
    img = QGLWidget::convertToGLFormat(img);
    glGenTextures(1, &name);
    glBindTexture(GL_TEXTURE_2D, name);
    glTexImage2D(GL_TEXTURE_2D,0, GL_RGBA, img.width(), img.height(), 0,GL_RGBA, GL_UNSIGNED_BYTE,img.bits());
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);

    glGenerateMipmap(GL_TEXTURE_2D);

    glEnable(GL_TEXTURE_2D);
    glBindTexture(GL_TEXTURE_2D, name);


    GLenum err;
        while ((err = glGetError()) != GL_NO_ERROR) {
            cerr << "OpenGL error: " << err << endl;
        }
}
Exemplo n.º 24
0
void C3DS::GenerateTexture(stMaterial *m, QString textureFile){
    QImage image;
    if(image.load(QString("./data/images/") + textureFile)){
        glGenTextures(1, &m->GLTextureId);
        glBindTexture(GL_TEXTURE_2D, m->GLTextureId);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT ) ;
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT ) ;

        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
        glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);

        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, image.width(), image.height(), 0, GL_BGRA, GL_UNSIGNED_BYTE, image.bits());
    }
}
void QGLTextureGlyphCache::fillTexture(const Coord &c, glyph_t glyph)
{
    QImage mask = textureMapForGlyph(glyph);
    const int maskWidth = mask.width();
    const int maskHeight = mask.height();

    if (mask.format() == QImage::Format_Mono) {
        mask = mask.convertToFormat(QImage::Format_Indexed8);
        for (int y = 0; y < maskHeight; ++y) {
            uchar *src = (uchar *) mask.scanLine(y);
            for (int x = 0; x < maskWidth; ++x)
                src[x] = -src[x]; // convert 0 and 1 into 0 and 255
        }
    } else if (mask.format() == QImage::Format_RGB32) {
        // Make the alpha component equal to the average of the RGB values.
        // This is needed when drawing sub-pixel antialiased text on translucent targets.
        for (int y = 0; y < maskHeight; ++y) {
            quint32 *src = (quint32 *) mask.scanLine(y);
            for (int x = 0; x < maskWidth; ++x) {
                uchar r = src[x] >> 16;
                uchar g = src[x] >> 8;
                uchar b = src[x];
                quint32 avg = (quint32(r) + quint32(g) + quint32(b) + 1) / 3; // "+1" for rounding.
                src[x] = (src[x] & 0x00ffffff) | (avg << 24);
            }
        }
    }

    glBindTexture(GL_TEXTURE_2D, m_texture);
    if (mask.format() == QImage::Format_RGB32) {
        glTexSubImage2D(GL_TEXTURE_2D, 0, c.x, c.y, maskWidth, maskHeight, GL_BGRA, GL_UNSIGNED_BYTE, mask.bits());
    } else {
#ifdef QT_OPENGL_ES2
        glTexSubImage2D(GL_TEXTURE_2D, 0, c.x, c.y, maskWidth, maskHeight, GL_ALPHA, GL_UNSIGNED_BYTE, mask.bits());
#else
        // glTexSubImage2D() might cause some garbage to appear in the texture if the mask width is
        // not a multiple of four bytes. The bug appeared on a computer with 32-bit Windows Vista
        // and nVidia GeForce 8500GT. GL_UNPACK_ALIGNMENT is set to four bytes, 'mask' has a
        // multiple of four bytes per line, and most of the glyph shows up correctly in the
        // texture, which makes me think that this is a driver bug.
        // One workaround is to make sure the mask width is a multiple of four bytes, for instance
        // by converting it to a format with four bytes per pixel. Another is to copy one line at a
        // time.

        for (int i = 0; i < maskHeight; ++i)
            glTexSubImage2D(GL_TEXTURE_2D, 0, c.x, c.y + i, maskWidth, 1, GL_ALPHA, GL_UNSIGNED_BYTE, mask.scanLine(i));
#endif
    }
}
Exemplo n.º 26
0
cv::Mat BasicPro::QImage2Mat(QImage &src)
{
    return cv::Mat(src.height(),src.width(),CV_8UC4,(uchar*)src.bits(),src.bytesPerLine());
}
Exemplo n.º 27
0
GLTexture::GLTexture(const QImage& image, GLenum target)
    : d_ptr(new GLTexturePrivate())
{
    Q_D(GLTexture);

    if (image.isNull())
        return;

    d->m_target = target;

    if (d->m_target != GL_TEXTURE_RECTANGLE_ARB) {
        d->m_scale.setWidth(1.0 / image.width());
        d->m_scale.setHeight(1.0 / image.height());
    } else {
        d->m_scale.setWidth(1.0);
        d->m_scale.setHeight(1.0);
    }

    d->m_size = image.size();
    d->m_yInverted = true;
    d->m_canUseMipmaps = false;
    d->m_mipLevels = 1;

    d->updateMatrix();

    glGenTextures(1, &d->m_texture);
    bind();

    if (!GLPlatform::instance()->isGLES()) {
        // Note: Blending is set up to expect premultiplied data, so non-premultiplied
        //       formats must always be converted.
        struct {
            GLenum internalFormat;
            GLenum format;
            GLenum type;
        } static const table[] = {
            { 0,           0,       0                              }, // QImage::Format_Invalid
            { 0,           0,       0                              }, // QImage::Format_Mono
            { 0,           0,       0                              }, // QImage::Format_MonoLSB
            { GL_R8,       GL_RED,  GL_UNSIGNED_BYTE               }, // QImage::Format_Indexed8
            { GL_RGB8,     GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV    }, // QImage::Format_RGB32
            { 0,           0,       0                              }, // QImage::Format_ARGB32
            { GL_RGBA8,    GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV    }, // QImage::Format_ARGB32_Premultiplied
            { GL_RGB8,     GL_BGR,  GL_UNSIGNED_SHORT_5_6_5_REV    }, // QImage::Format_RGB16
            { 0,           0,       0                              }, // QImage::Format_ARGB8565_Premultiplied
            { 0,           0,       0                              }, // QImage::Format_RGB666
            { GL_RGB5,     GL_BGRA, GL_UNSIGNED_SHORT_1_5_5_5_REV  }, // QImage::Format_RGB555
            { 0,           0,       0                              }, // QImage::Format_ARGB8555_Premultiplied
            { GL_RGB8,     GL_RGB,  GL_UNSIGNED_BYTE               }, // QImage::Format_RGB888
            { GL_RGB4,     GL_BGRA, GL_UNSIGNED_SHORT_4_4_4_4_REV  }, // QImage::Format_RGB444
            { GL_RGBA4,    GL_BGRA, GL_UNSIGNED_SHORT_4_4_4_4_REV  }, // QImage::Format_ARGB4444_Premultiplied
            { GL_RGB8,     GL_RGBA, GL_UNSIGNED_BYTE               }, // QImage::Format_RGBX8888
            { 0,           0,       0                              }, // QImage::Format_RGBA8888
            { GL_RGBA8,    GL_RGBA, GL_UNSIGNED_BYTE               }, // QImage::Format_RGBA8888_Premultiplied
            { GL_RGB10,    GL_RGBA, GL_UNSIGNED_INT_2_10_10_10_REV }, // QImage::Format_BGR30
            { GL_RGB10_A2, GL_RGBA, GL_UNSIGNED_INT_2_10_10_10_REV }, // QImage::Format_A2BGR30_Premultiplied
            { GL_RGB10,    GL_BGRA, GL_UNSIGNED_INT_2_10_10_10_REV }, // QImage::Format_RGB30
            { GL_RGB10_A2, GL_BGRA, GL_UNSIGNED_INT_2_10_10_10_REV }, // QImage::Format_A2RGB30_Premultiplied
        };

        QImage im;
        GLenum internalFormat;
        GLenum format;
        GLenum type;

        const QImage::Format index = image.format();

        if (index < sizeof(table) / sizeof(table[0]) && table[index].internalFormat &&
            !(index == QImage::Format_Indexed8 && image.colorCount() > 0)) {
            internalFormat = table[index].internalFormat;
            format = table[index].format;
            type = table[index].type;
            im = image;
        } else {
            im = image.convertToFormat(QImage::Format_ARGB32_Premultiplied);
            internalFormat = GL_RGBA8;
            format = GL_BGRA;
            type = GL_UNSIGNED_INT_8_8_8_8_REV;
        }

        d->m_internalFormat = internalFormat;

        if (d->s_supportsTextureStorage) {
            glTexStorage2D(d->m_target, 1, internalFormat, im.width(), im.height());
            glTexSubImage2D(d->m_target, 0, 0, 0, im.width(), im.height(),
                            format, type, im.bits());
            d->m_immutable = true;
        } else {
            glTexParameteri(d->m_target, GL_TEXTURE_MAX_LEVEL, d->m_mipLevels - 1);
            glTexImage2D(d->m_target, 0, internalFormat, im.width(), im.height(), 0,
                         format, type, im.bits());
        }
    } else {
        d->m_internalFormat = GL_RGBA8;

        if (d->s_supportsARGB32) {
            const QImage im = image.convertToFormat(QImage::Format_ARGB32_Premultiplied);
            glTexImage2D(d->m_target, 0, GL_BGRA_EXT, im.width(), im.height(),
                         0, GL_BGRA_EXT, GL_UNSIGNED_BYTE, im.bits());
        } else {
            const QImage im = image.convertToFormat(QImage::Format_RGBA8888_Premultiplied);
            glTexImage2D(d->m_target, 0, GL_RGBA, im.width(), im.height(),
                         0, GL_RGBA, GL_UNSIGNED_BYTE, im.bits());
        }
    }

    unbind();
    setFilter(GL_LINEAR);
}
/*
 * Helper function to transform QImages
 *
 * @param srcQImage the QImage to be transformed
 * @param transform the transform to perform on the image
 */
void transform_image(QImage* srcQImage, int transform) {
    /* make sure the source image depth is 32 */
    if (32 != srcQImage->depth()) {
        *srcQImage = srcQImage->convertDepth(32);
    }

    int nXOriginSrc = 0;
    int nYOriginSrc = 0;
    int nWidth      = srcQImage->width();
    int nHeight     = srcQImage->height();
        
    /*scan length of the source image*/
    int imageWidth  = nWidth;
    /*number of rows of the source image*/
    int imageHeight = nHeight;
        
    int imgLen;
    int srcImgLen;
        
    int t_width;
    int t_height;
        
    int srcX;
    int srcY;
    int xStart;
    int yStart;
    int xIncr;
    int yIncr;
    int destX;
    int destY;
    int yCounter;
    int xCounter;
        
    int srcIndex;
    int destIndex;
        
    uchar* srcBits     = NULL;
    uchar* destBits    = NULL;
    
    uchar* srcBitsPtr  = NULL;
    uchar* destBitsPtr = NULL;
        
        
    /* set dimensions of image being created,
       depending on transform */
    if (transform & TRANSFORM_INVERTED_AXES) {
      t_width  = nHeight;
      t_height = nWidth;
    } else {
      t_width  = nWidth;
      t_height = nHeight;
    }
        
    /* width * height * 4 gives us the size of a 32 bpp image */
    imgLen = nWidth * nHeight << 2;
    srcImgLen = imageWidth  * imageHeight << 2;
        
    /* Qt specific */
    QImage processedQImage = QImage(t_width, t_height, 32);

    srcBits  = srcQImage->bits();
    destBits = processedQImage.bits();
    /* ----------- */
    
    if (transform & TRANSFORM_Y_FLIP) {
      yStart = nHeight-1;
      yIncr = -1;
    } else {
      yStart = 0;
      yIncr = +1;
    }
    
    if (transform & TRANSFORM_X_FLIP) {
      xStart = nWidth-1;
      xIncr = -1;
    } else {
      xStart = 0;
      xIncr = +1;
    }
        
    srcBitsPtr  = srcBits;
    destBitsPtr = destBits;
        
        
    /* increment srcX,Y regular. increment destX,Y according to transform.
       this makes handling of mask and alpha values easier */
    
    for (srcY = nYOriginSrc, destY = yStart, yCounter = 0; 
         yCounter < nHeight; 
         srcY++, destY+=yIncr, yCounter++) {
      
      /* in the current implementation we have source bitmap
         dimension as the width of the image and the height of the region
         destination bitmap is of the dimensions of the region */
      
      for (srcX = nXOriginSrc, destX = xStart, xCounter = 0; 
           xCounter < nWidth; 
           srcX++, destX+=xIncr, xCounter++) {
        
        if ( transform & TRANSFORM_INVERTED_AXES ) {
          destIndex =  ( ( (destX) * t_width) + (destY) );
        } else {
          destIndex =  ( ( (destY) * t_width) + (destX) );
        }
        
        destBitsPtr =  destBits + (destIndex * 4) ;
        
        srcIndex = (((srcY) * imageWidth) + (srcX));
        srcBitsPtr = srcBits + (srcIndex * 4);
        
        
        /* copy the pixel that is pointed to */
        *((int *)destBitsPtr) = *((int *)srcBitsPtr);
        
      } /*for x*/
      
    } /* for y */
    
    
    /* ---------- */
    
    processedQImage.setAlphaBuffer(srcQImage->hasAlphaBuffer());

    *srcQImage = processedQImage;
}
Exemplo n.º 29
0
void MyWindow::PrepareTexture(GLenum TextureUnit, GLenum TextureTarget, const QString& FileName, bool flip)
{
    QImage TexImg;

    if (!TexImg.load(FileName)) qDebug() << "Erreur chargement texture " << FileName;
    if (flip==true) TexImg=TexImg.mirrored();

    glActiveTexture(TextureUnit);
    GLuint TexID;
    glGenTextures(1, &TexID);
    glBindTexture(TextureTarget, TexID);
    mFuncs->glTexStorage2D(TextureTarget, 1, GL_RGBA8, TexImg.width(), TexImg.height());
    mFuncs->glTexSubImage2D(TextureTarget, 0, 0, 0, TexImg.width(), TexImg.height(), GL_BGRA, GL_UNSIGNED_BYTE, TexImg.bits());
    //glTexImage2D(TextureTarget, 0, GL_RGB, TexImg.width(), TexImg.height(), 0, GL_BGRA, GL_UNSIGNED_BYTE, TexImg.bits());
    glTexParameteri(TextureTarget, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameteri(TextureTarget, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
}
Exemplo n.º 30
0
void QAnimationWriter::appendFrame(const QImage& frm, const QPoint& offset)
{
    if (!dev)
        return;

    const QImage frame = frm.convertToFormat(QImage::Format_RGB32);
    const int alignx = 1;
    if (prev.isNull() || !d->canCompose()) {
        d->setImage(frame);
    } else {
        bool done;
        int minx, maxx, miny, maxy;
        int w = frame.width();
        int h = frame.height();

        const quint32 *framePtr = reinterpret_cast<const quint32*>(frame.bits());
        const quint32 *prevPtr = reinterpret_cast<const quint32*>(prev.bits());
        const int frameStride = frame.bytesPerLine() / sizeof(quint32);
        const int prevStride = prev.bytesPerLine() / sizeof(quint32);

        // Find left edge of change
        done = false;
        for (minx = 0; minx < w && !done; ++minx) {
            const quint32 *p1 = framePtr + minx;
            const quint32 *p2 = prevPtr + minx + offset.x();
            for (int y = 0; y < h; ++y) {
                if (*p1 != *p2) {
                    done = true;
                    break;
                }
                p1 += frameStride;
                p2 += prevStride;
            }
        }
        --minx;

        // Find right edge of change
        done = false;
        for (maxx = w-1; maxx >= 0 && !done; --maxx) {
            const quint32 *p1 = framePtr + maxx;
            const quint32 *p2 = prevPtr + maxx + offset.x();
            for (int y = 0; y < h; ++y) {
                if (*p1 != *p2) {
                    done = true;
                    break;
                }
                p1 += frameStride;
                p2 += prevStride;
            }
        }
        ++maxx;

        // Find top edge of change
        done = false;
        for (miny = 0; miny < h && !done; ++miny) {
            const quint32 *p1 = framePtr + miny * frameStride;
            const quint32 *p2 = prevPtr + miny * prevStride + offset.x();
            for (int x = 0; x < w; ++x) {
                if (*p1 != *p2) {
                    done = true;
                    break;
                }
                ++p1;
                ++p2;
            }
        }
        --miny;

        // Find right edge of change
        done = false;
        for (maxy = h-1; maxy >= 0 && !done; --maxy) {
            const quint32 *p1 = framePtr + maxy * frameStride;
            const quint32 *p2 = prevPtr + maxy * prevStride + offset.x();
            for (int x = 0; x < w; ++x) {
                if (*p1 != *p2) {
                    done = true;
                    break;
                }
                ++p1;
                ++p2;
            }
        }
        ++maxy;

        if (minx > maxx)
            minx = maxx = 0;
        if (miny > maxy)
            miny = maxy = 0;

        if (alignx > 1) {
            minx -= minx % alignx;
            maxx = maxx - maxx % alignx + alignx - 1;
        }

        int dw = maxx - minx + 1;
        int dh = maxy - miny + 1;

        QImage diff(dw, dh, QImage::Format_ARGB32);

        int x, y;
        for (y = 0; y < dh; ++y) {
            QRgb* li = (QRgb*)frame.scanLine(y+miny)+minx;
            QRgb* lp = (QRgb*)prev.scanLine(y+miny+offset.y())+minx+offset.x();
            QRgb* ld = (QRgb*)diff.scanLine(y);
            if (alignx) {
                for (x = 0; x < dw; x += alignx) {
                    int i;
                    for (i = 0; i < alignx; ++i) {
                        if (li[x+i] != lp[x+i])
                            break;
                    }
                    if (i == alignx) {
                        // All the same
                        for (i = 0; i < alignx; ++i)
                            ld[x+i] = qRgba(0,0,0,0);
                    } else {
                        // Some different
                        for (i = 0; i < alignx; ++i)
                            ld[x+i] = 0xff000000 | li[x+i];
                    }
                }
            } else {
                for (x = 0; x < dw; ++x) {
                    if (li[x] != lp[x])
                        ld[x] = 0xff000000 | li[x];
                    else
                        ld[x] = qRgba(0,0,0,0);
                }
            }
        }

        d->composeImage(diff, QPoint(minx, miny) + offset);
    }
    if (prev.isNull() || (prev.size() == frame.size() && offset == QPoint(0,0))) {
        prev = frame;
    } else {
        QPainter p(&prev);
        p.drawImage(offset.x(), offset.y(), frame, 0, 0,
                    frame.width(), frame.height());
    }
}