コード例 #1
0
void PagePainter::paintPageOnPainter( const KPDFPage * page, int id, int flags,
    QPainter * destPainter, const QRect & limits, int width, int height )
{
    QPixmap * pixmap = 0;

    // if a pixmap is present for given id, use it
    if ( page->m_pixmaps.contains( id ) )
        pixmap = page->m_pixmaps[ id ];

    // else find the closest match using pixmaps of other IDs (great optim!)
    else if ( !page->m_pixmaps.isEmpty() && width != -1 )
    {
        int minDistance = -1;
        QMap< int,QPixmap * >::const_iterator it = page->m_pixmaps.begin(), end = page->m_pixmaps.end();
        for ( ; it != end; ++it )
        {
            int pixWidth = (*it)->width(),
                distance = pixWidth > width ? pixWidth - width : width - pixWidth;
            if ( minDistance == -1 || distance < minDistance )
            {
                pixmap = *it;
                minDistance = distance;
            }
        }
    }

    // if have no pixmap, draw blank page with gray cross and exit
    if ( !pixmap )
    {
        QColor color = Qt::white;
        if ( KpdfSettings::changeColors() )
        {
            switch ( KpdfSettings::renderMode() )
            {
                case KpdfSettings::EnumRenderMode::Inverted:
                    color = Qt::black;
                    break;
                case KpdfSettings::EnumRenderMode::Paper:
                    color = KpdfSettings::paperColor();
                    break;
                case KpdfSettings::EnumRenderMode::Recolor:
                    color = KpdfSettings::recolorBackground();
                    break;
                default: ;
            }
        }
        destPainter->fillRect( limits, color );

        // draw a cross (to  that the pixmap as not yet been loaded)
        // helps a lot on pages that take much to render
        destPainter->setPen( Qt::gray );
        destPainter->drawLine( 0, 0, width-1, height-1 );
        destPainter->drawLine( 0, height-1, width-1, 0 );
        // idea here: draw a hourglass (or kpdf icon :-) on top-left corner
        return;
    }

    // find out what to paint over the pixmap (manipulations / overlays)
    bool paintAccessibility = (flags & Accessibility) && KpdfSettings::changeColors() && (KpdfSettings::renderMode() != KpdfSettings::EnumRenderMode::Paper);
    bool paintHighlights = (flags & Highlights) && !page->m_highlights.isEmpty();
    bool enhanceLinks = (flags & EnhanceLinks) && KpdfSettings::highlightLinks();
    bool enhanceImages = (flags & EnhanceImages) && KpdfSettings::highlightImages();
    // check if there are really some highlightRects to paint
    if ( paintHighlights )
    {
        // precalc normalized 'limits rect' for intersection
        double nXMin = (double)limits.left() / (double)width,
               nXMax = (double)limits.right() / (double)width,
               nYMin = (double)limits.top() / (double)height,
               nYMax = (double)limits.bottom() / (double)height;
        // if no rect intersects limits, disable paintHighlights
        paintHighlights = false;
        QValueList< HighlightRect * >::const_iterator hIt = page->m_highlights.begin(), hEnd = page->m_highlights.end();
        for ( ; hIt != hEnd; ++hIt )
        {
            if ( (*hIt)->intersects( nXMin, nYMin, nXMax, nYMax ) )
            {
                paintHighlights = true;
                break;
            }
        }
    }

    // use backBuffer if 'pixmap direct manipulation' is needed
    bool backBuffer = paintAccessibility || paintHighlights;
    QPixmap * backPixmap = 0;
    QPainter * p = destPainter;
    if ( backBuffer )
    {
        // let's paint using a buffered painter
        backPixmap = new QPixmap( limits.width(), limits.height() );
        p = new QPainter( backPixmap );
        p->translate( -limits.left(), -limits.top() );
    }

    // 1. fast blit the pixmap if it has the right size..
    if ( pixmap->width() == width && pixmap->height() == height )
        p->drawPixmap( limits.topLeft(), *pixmap, limits );
    // ..else set a scale matrix to the painter and paint a quick 'zoomed' pixmap
    else
    {
        p->save();
        // TODO paint only the needed part (note: hope that Qt4 transforms are faster)
        p->scale( width / (double)pixmap->width(), height / (double)pixmap->height() );
        p->drawPixmap( 0,0, *pixmap, 0,0, pixmap->width(), pixmap->height() );
        p->restore();
    }

    // 2. mangle pixmap: convert it to 32-bit qimage and perform pixel-level manipulations
    if ( backBuffer )
    {
        QImage backImage = backPixmap->convertToImage();
        // 2.1. modify pixmap following accessibility settings
        if ( paintAccessibility )
        {
            switch ( KpdfSettings::renderMode() )
            {
                case KpdfSettings::EnumRenderMode::Inverted:
                    // Invert image pixels using QImage internal function
                    backImage.invertPixels(false);
                    break;
                case KpdfSettings::EnumRenderMode::Recolor:
                    // Recolor image using KImageEffect::flatten with dither:0
                    KImageEffect::flatten( backImage, KpdfSettings::recolorForeground(), KpdfSettings::recolorBackground() );
                    break;
                case KpdfSettings::EnumRenderMode::BlackWhite:
                    // Manual Gray and Contrast
                    unsigned int * data = (unsigned int *)backImage.bits();
                    int val, pixels = backImage.width() * backImage.height(),
                        con = KpdfSettings::bWContrast(), thr = 255 - KpdfSettings::bWThreshold();
                    for( int i = 0; i < pixels; ++i )
                    {
                        val = qGray( data[i] );
                        if ( val > thr )
                            val = 128 + (127 * (val - thr)) / (255 - thr);
                        else if ( val < thr )
                            val = (128 * val) / thr;
                        if ( con > 2 )
                        {
                            val = con * ( val - thr ) / 2 + thr;
                            if ( val > 255 )
                                val = 255;
                            else if ( val < 0 )
                                val = 0;
                        }
                        data[i] = qRgba( val, val, val, 255 );
                    }
                    break;
            }
        }
        // 2.2. highlight rects in page
        if ( paintHighlights )
        {
            // draw highlights that are inside the 'limits' paint region
            QValueList< HighlightRect * >::const_iterator hIt = page->m_highlights.begin(), hEnd = page->m_highlights.end();
            for ( ; hIt != hEnd; ++hIt )
            {
                HighlightRect * r = *hIt;
                QRect highlightRect = r->geometry( width, height );
                if ( highlightRect.isValid() && highlightRect.intersects( limits ) )
                {
                    // find out the rect to highlight on pixmap
                    highlightRect = highlightRect.intersect( limits );
                    highlightRect.moveBy( -limits.left(), -limits.top() );

                    // highlight composition (product: highlight color * destcolor)
                    unsigned int * data = (unsigned int *)backImage.bits();
                    int val, newR, newG, newB,
                        rh = r->color.red(),
                        gh = r->color.green(),
                        bh = r->color.blue(),
                        offset = highlightRect.top() * backImage.width();
                    for( int y = highlightRect.top(); y <= highlightRect.bottom(); ++y )
                    {
                        for( int x = highlightRect.left(); x <= highlightRect.right(); ++x )
                        {
                            val = data[ x + offset ];
                            newR = (qRed(val) * rh) / 255;
                            newG = (qGreen(val) * gh) / 255;
                            newB = (qBlue(val) * bh) / 255;
                            data[ x + offset ] = qRgba( newR, newG, newB, 255 );
                        }
                        offset += backImage.width();
                    }
                }
            }
        }
        backPixmap->convertFromImage( backImage );
    }

    // 3. visually enchance links and images if requested
    if ( enhanceLinks || enhanceImages )
    {
        QColor normalColor = QApplication::palette().active().highlight();
        QColor lightColor = normalColor.light( 140 );
        // enlarging limits for intersection is like growing the 'rectGeometry' below
        QRect limitsEnlarged = limits;
        limitsEnlarged.addCoords( -2, -2, 2, 2 );
        // draw rects that are inside the 'limits' paint region as opaque rects
        QValueList< ObjectRect * >::const_iterator lIt = page->m_rects.begin(), lEnd = page->m_rects.end();
        for ( ; lIt != lEnd; ++lIt )
        {
            ObjectRect * rect = *lIt;
            if ( (enhanceLinks && rect->objectType() == ObjectRect::Link) ||
                 (enhanceImages && rect->objectType() == ObjectRect::Image) )
            {
                QRect rectGeometry = rect->geometry( width, height );
                if ( rectGeometry.intersects( limitsEnlarged ) )
                {
                    // expand rect and draw inner border
                    rectGeometry.addCoords( -1,-1,1,1 );
                    p->setPen( lightColor );
                    p->drawRect( rectGeometry );
                    // expand rect to draw outer border
                    rectGeometry.addCoords( -1,-1,1,1 );
                    p->setPen( normalColor );
                    p->drawRect( rectGeometry );
                }
            }
        }
    }

    // 4. if was backbuffering, copy the backPixmap to destination
    if ( backBuffer )
    {
        delete p;
        destPainter->drawPixmap( limits.left(), limits.top(), *backPixmap );
        delete backPixmap;
    }
}
コード例 #2
0
void doMagicIn(QString path, QString q, QString OPath)
{
    QRegExp isMask = QRegExp("*m.gif");
    isMask.setPatternSyntax(QRegExp::Wildcard);

    QRegExp isBackupDir = QRegExp("*/_backup/");
    isBackupDir.setPatternSyntax(QRegExp::Wildcard);

    if(isBackupDir.exactMatch(path))
        return; //Skip backup directories

    if(isMask.exactMatch(q))
        return;

    QImage target;
    QString imgFileM;
    QStringList tmp = q.split(".", QString::SkipEmptyParts);
    if(tmp.size()==2)
        imgFileM = tmp[0] + "m." + tmp[1];
    else
        return;

    //skip unexists pairs
    if(!QFile(path+q).exists())
        return;

    if(!QFile(path+imgFileM).exists())
    {
        QString saveTo;

        QImage image = loadQImage(path+q);
        if(image.isNull()) return;

        QTextStream(stdout) << QString(path+q+"\n").toUtf8().data();

        saveTo = QString(OPath+(tmp[0].toLower())+".gif");
        //overwrite source image (convert BMP to GIF)
        if(toGif( image, saveTo ) ) //Write gif
        {
            QTextStream(stdout) <<"GIF-1 only\n";
        }
        else
        {
            QTextStream(stdout) <<"BMP-1 only\n";
            image.save(saveTo, "BMP"); //If failed, write BMP
        }
        return;
    }

    if(!noBackUp)
    {
        //create backup dir
        QDir backup(path+"_backup/");
        if(!backup.exists())
        {
            QTextStream(stdout) << QString("Create backup with path %1\n").arg(path+"_backup");
            if(!backup.mkdir("."))
                QTextStream(stderr) << QString("WARNING! Can't create backup directory %1\n").arg(path+"_backup");

        }

        //create Back UP of source images
        if(!QFile(path+"_backup/"+q).exists())
            QFile::copy(path+q, path+"_backup/"+q);
        if(!QFile(path+"_backup/"+imgFileM).exists())
            QFile::copy(path+imgFileM, path+"_backup/"+imgFileM);
    }

    QImage image = loadQImage(path+q);
    QImage mask = loadQImage(path+imgFileM);

    if(mask.isNull()) //Skip null masks
        return;

    target = setAlphaMask(image, mask);

    if(!target.isNull())
    {
        //Save before fix
        //target.save(OPath+tmp[0]+"_before.png");
        //mask.save(OPath+tmp[0]+"_mask_before.png");
        QTextStream(stdout) << QString(path+q+"\n").toUtf8().data();

        //fix
        if(image.size()!= mask.size())
            mask = mask.copy(0,0, image.width(), image.height());

        mask = target.alphaChannel();
        mask.invertPixels();

        //Save after fix
        //target.save(OPath+tmp[0]+"_after.bmp", "BMP");
        QString saveTo;


        saveTo = QString(OPath+(tmp[0].toLower())+".gif");

        //overwrite source image (convert BMP to GIF)
        if(toGif(image, saveTo ) ) //Write gif
        {
            QTextStream(stdout) <<"GIF-1 ";
        }
        else
        {
            QTextStream(stdout) <<"BMP-1 ";
            image.save(saveTo, "BMP"); //If failed, write BMP
        }

        saveTo = QString(OPath+(tmp[0].toLower())+"m.gif");

        //overwrite mask image
        if( toGif(mask, saveTo ) ) //Write gif
        {
            QTextStream(stdout) <<"GIF-2\n";
        }
        else
        {
            mask.save(saveTo, "BMP"); //If failed, write BMP
            QTextStream(stdout) <<"BMP-2\n";
        }
    }
    else
        QTextStream(stderr) << path+q+" - WRONG!\n";
}
コード例 #3
0
ファイル: CPixmap.cpp プロジェクト: vince06fr/fotowall
void CPixmap::toInvertedColors() {
    m_effects.push_back(CEffect::InvertColors);
    QImage img = this->toImage();
    img.invertPixels();
    updateImage(img);
}
コード例 #4
0
void QImageTextureGlyphCache::fillTexture(const Coord &c, glyph_t g, QFixed subPixelPosition)
{
    QImage mask = textureMapForGlyph(g, subPixelPosition);

#ifdef CACHE_DEBUG
    printf("fillTexture of %dx%d at %d,%d in the cache of %dx%d\n", c.w, c.h, c.x, c.y, m_image.width(), m_image.height());
    if (mask.width() > c.w || mask.height() > c.h) {
        printf("   ERROR; mask is bigger than reserved space! %dx%d instead of %dx%d\n", mask.width(), mask.height(), c.w,c.h);
        return;
    }
#endif

    if (m_type == QFontEngineGlyphCache::Raster_RGBMask) {        
        QImage ref(m_image.bits() + (c.x * 4 + c.y * m_image.bytesPerLine()),
                   qMax(mask.width(), c.w), qMax(mask.height(), c.h), m_image.bytesPerLine(),
                   m_image.format());
        QPainter p(&ref);
        p.setCompositionMode(QPainter::CompositionMode_Source);
        p.fillRect(0, 0, c.w, c.h, QColor(0,0,0,0)); // TODO optimize this
        p.drawImage(0, 0, mask);
        p.end();
    } else if (m_type == QFontEngineGlyphCache::Raster_Mono) {
        if (mask.depth() > 1) {
            // TODO optimize this
            mask = mask.alphaChannel();
            mask.invertPixels();
            mask = mask.convertToFormat(QImage::Format_Mono);
        }

        int mw = qMin(mask.width(), c.w);
        int mh = qMin(mask.height(), c.h);
        uchar *d = m_image.bits();
        int dbpl = m_image.bytesPerLine();

        for (int y = 0; y < c.h; ++y) {
            uchar *dest = d + (c.y + y) *dbpl + c.x/8;

            if (y < mh) {
                uchar *src = mask.scanLine(y);
                for (int x = 0; x < c.w/8; ++x) {
                    if (x < (mw+7)/8)
                        dest[x] = src[x];
                    else
                        dest[x] = 0;
                }
            } else {
                for (int x = 0; x < c.w/8; ++x)
                    dest[x] = 0;
            }
        }
    } else { // A8
        int mw = qMin(mask.width(), c.w);
        int mh = qMin(mask.height(), c.h);
        uchar *d = m_image.bits();
        int dbpl = m_image.bytesPerLine();

        if (mask.depth() == 1) {
            for (int y = 0; y < c.h; ++y) {
                uchar *dest = d + (c.y + y) *dbpl + c.x;
                if (y < mh) {
                    uchar *src = (uchar *) mask.scanLine(y);
                    for (int x = 0; x < c.w; ++x) {
                        if (x < mw)
                            dest[x] = (src[x >> 3] & (1 << (7 - (x & 7)))) > 0 ? 255 : 0;
                    }
                }
            }
        } else if (mask.depth() == 8) {
コード例 #5
0
ファイル: imageeffect.cpp プロジェクト: DHalens/kamerka
void ImageEffect::invert(QImage &i) {
    i.invertPixels();
}
コード例 #6
0
void QVGPixmapData::fromNativeType(void* pixmap, NativeType type)
{
    if (type == QPixmapData::SgImage && pixmap) {
#if defined(QT_SYMBIAN_SUPPORTS_SGIMAGE) && !defined(QT_NO_EGL)
        RSgImage *sgImage = reinterpret_cast<RSgImage*>(pixmap);

        destroyImages();
        prevSize = QSize();

        TInt err = 0;

        RSgDriver driver;
        err = driver.Open();
        if (err != KErrNone) {
            cleanup();
            return;
        }

        if (sgImage->IsNull()) {
            cleanup();
            driver.Close();
            return;
        }

        TSgImageInfo sgImageInfo;
        err = sgImage->GetInfo(sgImageInfo);
        if (err != KErrNone) {
            cleanup();
            driver.Close();
            return;
        }

        pfnVgCreateEGLImageTargetKHR vgCreateEGLImageTargetKHR = (pfnVgCreateEGLImageTargetKHR) eglGetProcAddress("vgCreateEGLImageTargetKHR");

        if (eglGetError() != EGL_SUCCESS || !(QEgl::hasExtension("EGL_KHR_image") || QEgl::hasExtension("EGL_KHR_image_pixmap")) || !vgCreateEGLImageTargetKHR) {
            cleanup();
            driver.Close();
            return;
        }

        const EGLint KEglImageAttribs[] = {EGL_IMAGE_PRESERVED_SYMBIAN, EGL_TRUE, EGL_NONE};
        EGLImageKHR eglImage = QEgl::eglCreateImageKHR(QEgl::display(),
                EGL_NO_CONTEXT,
                EGL_NATIVE_PIXMAP_KHR,
                (EGLClientBuffer)sgImage,
                (EGLint*)KEglImageAttribs);

        if (eglGetError() != EGL_SUCCESS) {
            cleanup();
            driver.Close();
            return;
        }

        vgImage = vgCreateEGLImageTargetKHR(eglImage);
        if (vgGetError() != VG_NO_ERROR) {
            cleanup();
            QEgl::eglDestroyImageKHR(QEgl::display(), eglImage);
            driver.Close();
            return;
        }

        w = sgImageInfo.iSizeInPixels.iWidth;
        h = sgImageInfo.iSizeInPixels.iHeight;
        d = 32; // We always use ARGB_Premultiplied for VG pixmaps.
        is_null = (w <= 0 || h <= 0);
        source = QImage();
        recreate = false;
        prevSize = QSize(w, h);
        setSerialNumber(++qt_vg_pixmap_serial);
        // release stuff
        QEgl::eglDestroyImageKHR(QEgl::display(), eglImage);
        driver.Close();
#endif
    } else if (type == QPixmapData::FbsBitmap) {
        CFbsBitmap *bitmap = reinterpret_cast<CFbsBitmap*>(pixmap);

        bool deleteSourceBitmap = false;

#ifdef Q_SYMBIAN_HAS_EXTENDED_BITMAP_TYPE

        // Rasterize extended bitmaps

        TUid extendedBitmapType = bitmap->ExtendedBitmapType();
        if (extendedBitmapType != KNullUid) {
            bitmap = createBlitCopy(bitmap);
            deleteSourceBitmap = true;
        }
#endif

        if (bitmap->IsCompressedInRAM()) {
            bitmap = createBlitCopy(bitmap);
            deleteSourceBitmap = true;
        }

        TDisplayMode displayMode = bitmap->DisplayMode();
        QImage::Format format = qt_TDisplayMode2Format(displayMode);

        TSize size = bitmap->SizeInPixels();

        bitmap->BeginDataAccess();
        uchar *bytes = (uchar*)bitmap->DataAddress();
        QImage img = QImage(bytes, size.iWidth, size.iHeight, format);
        img = img.copy();
        bitmap->EndDataAccess();

        if(displayMode == EGray2) {
            //Symbian thinks set pixels are white/transparent, Qt thinks they are foreground/solid
            //So invert mono bitmaps so that masks work correctly.
            img.invertPixels();
        } else if(displayMode == EColor16M) {
            img = img.rgbSwapped(); // EColor16M is BGR
        }

        fromImage(img, Qt::AutoColor);

        if(deleteSourceBitmap)
            delete bitmap;
    }
}
コード例 #7
0
ファイル: worker.cpp プロジェクト: meisterT/katarakt
void Worker::run() {
	while (1) {
		res->requestSemaphore.acquire(1);
		if (die) {
			break;
		}

		// get next page to render
		res->requestMutex.lock();
		int page, width, index;
		map<int,pair<int,int> >::iterator less = res->requests.lower_bound(res->center_page);
		map<int,pair<int,int> >::iterator greater = less--;

		if (greater != res->requests.end()) {
			if (greater != res->requests.begin()) {
				// favour nearby page, go down first
				if (greater->first + less->first <= res->center_page * 2) {
					page = greater->first;
					index = greater->second.first;
					width = greater->second.second;
					res->requests.erase(greater);
				} else {
					page = less->first;
					index = less->second.first;
					width = less->second.second;
					res->requests.erase(less);
				}
			} else {
				page = greater->first;
				index = greater->second.first;
				width = greater->second.second;
				res->requests.erase(greater);
			}
		} else {
			page = less->first;
			index = less->second.first;
			width = less->second.second;
			res->requests.erase(less);
		}
		res->requestMutex.unlock();

		// check for duplicate requests
		res->k_page[page].mutex.lock();
		if (res->k_page[page].status[index] == width &&
				res->k_page[page].rotation[index] == res->rotation) {
			res->k_page[page].mutex.unlock();
			continue;
		}
		int rotation = res->rotation;
		res->k_page[page].mutex.unlock();

		// open page
#ifdef DEBUG
		cerr << "    rendering page " << page << " for index " << index << endl;
#endif
		Poppler::Page *p = res->doc->page(page);
		if (p == NULL) {
			cerr << "failed to load page " << page << endl;
			continue;
		}

		// render page
		float dpi = 72.0 * width / res->get_page_width(page);
		QImage img = p->renderToImage(dpi, dpi, -1, -1, -1, -1,
				static_cast<Poppler::Page::Rotation>(rotation));

		if (img.isNull()) {
			cerr << "failed to render page " << page << endl;
			continue;
		}

		// invert to current color setting
		if (res->inverted_colors) {
			img.invertPixels();
		}

		// put page
		res->k_page[page].mutex.lock();
		if (!res->k_page[page].img[index].isNull()) {
			res->k_page[page].img[index] = QImage(); // assign null image
		}

		// adjust all available images to current color setting
		if (res->k_page[page].inverted_colors != res->inverted_colors) {
			res->k_page[page].inverted_colors = res->inverted_colors;
			for (int i = 0; i < 3; i++) {
				res->k_page[page].img[i].invertPixels();
			}
			res->k_page[page].thumbnail.invertPixels();
		}
		res->k_page[page].img[index] = img;
		res->k_page[page].status[index] = width;
		res->k_page[page].rotation[index] = rotation;
		res->k_page[page].mutex.unlock();

		res->garbageMutex.lock();
		res->garbage.insert(page); // TODO add index information?
		res->garbageMutex.unlock();

		emit page_rendered(page);

		// collect goto links
		res->link_mutex.lock();
		if (res->k_page[page].links == NULL) {
			res->link_mutex.unlock();

			QList<Poppler::Link *> *links = new QList<Poppler::Link *>;
			QList<Poppler::Link *> l = p->links();
			links->swap(l);

			res->link_mutex.lock();
			res->k_page[page].links = links;
		}
		if (res->k_page[page].text == NULL) {
			res->link_mutex.unlock();

			QList<Poppler::TextBox *> text = p->textList();
			// assign boxes to lines
			// make single parts from chained boxes
			set<Poppler::TextBox *> used;
			QList<SelectionPart *> selection_parts;
			Q_FOREACH(Poppler::TextBox *box, text) {
				if (used.find(box) != used.end()) {
					continue;
				}
				used.insert(box);

				SelectionPart *p = new SelectionPart(box);
				selection_parts.push_back(p);
				Poppler::TextBox *next = box->nextWord();
				while (next != NULL) {
					used.insert(next);
					p->add_word(next);
					next = next->nextWord();
				}
			}

			// sort by y coordinate
			qStableSort(selection_parts.begin(), selection_parts.end(), selection_less_y);

			QRectF line_box;
			QList<SelectionLine *> *lines = new QList<SelectionLine *>();
			Q_FOREACH(SelectionPart *part, selection_parts) {
				QRectF box = part->get_bbox();
				// box fits into line_box's line
				if (!lines->empty() && box.y() <= line_box.center().y() && box.bottom() > line_box.center().y()) {
					float ratio_w = box.width() / line_box.width();
					float ratio_h = box.height() / line_box.height();
					if (ratio_w < 1.0f) {
						ratio_w = 1.0f / ratio_w;
					}
					if (ratio_h < 1.0f) {
						ratio_h = 1.0f / ratio_h;
					}
					if (ratio_w > 1.3f && ratio_h > 1.3f) {
						lines->back()->sort();
						lines->push_back(new SelectionLine(part));
						line_box = part->get_bbox();
					} else {
						lines->back()->add_part(part);
					}
				// it doesn't fit, create new line
				} else {
					if (!lines->empty()) {
						lines->back()->sort();
					}
					lines->push_back(new SelectionLine(part));
					line_box = part->get_bbox();
				}
			}
			if (!lines->empty()) {
				lines->back()->sort();
			}

			res->link_mutex.lock();
			res->k_page[page].text = lines;
		}
コード例 #8
0
// static
QPixmap QPixmap::fromPmHBITMAP(HBITMAP hbm, HBITMAP hbmMask)
{
    QPixmap res;

    if (hbm == NULLHANDLE)
        return res;

    // bitmap header + 2 palette entries (for the monochrome bitmap)
    char bmi[sizeof(BITMAPINFOHEADER2) + 4 * 2];
    memset(bmi, 0, sizeof(bmi));
    PBITMAPINFOHEADER2 bmh = (PBITMAPINFOHEADER2)bmi;
    bmh->cbFix = sizeof(BITMAPINFOHEADER2);
    PULONG pal = (PULONG)(bmi + sizeof(BITMAPINFOHEADER2));

    if (!GpiQueryBitmapInfoHeader(hbm, bmh))
        return res;

    HPS hps = qt_alloc_mem_ps(bmh->cx, bmh->cy * 2);
    if (hps == NULLHANDLE)
        return res;

    GpiSetBitmap(hps, hbm);

    QImage img;
    bool succeeded = false;

    if (bmh->cPlanes == 1 && bmh->cBitCount == 1) {
        // monochrome bitmap
        img = QImage(bmh->cx, bmh->cy, QImage::Format_Mono);
        if (GpiQueryBitmapBits(hps, 0, img.height(), (PBYTE)img.bits(),
                               (PBITMAPINFO2)&bmi) != GPI_ALTERROR) {
            succeeded = true;
            // take the palette
            QVector<QRgb> colors(2);
            colors[0] = QRgb(pal[0]);
            colors[1] = QRgb(pal[1]);
            img.setColorTable(colors);
        }
    } else {
        // always convert to 32-bit otherwise
        img = QImage(bmh->cx, bmh->cy, QImage::Format_RGB32);
        bmh->cPlanes = 1;
        bmh->cBitCount = 32;
        if (GpiQueryBitmapBits(hps, 0, img.height(), (PBYTE)img.bits(),
                               (PBITMAPINFO2)&bmi) != GPI_ALTERROR) {
            succeeded = true;
            // try to auto-detect if there is a real alpha channel
            bool allZero = true;
            for (int i = 0; i < img.numBytes(); ++i) {
                if (img.bits()[i] & 0xFF000000) {
                    allZero = false;
                    break;
                }
            }
            if (!allZero) {
                // assume we've got the alpha channel
                QImage alphaImg = QImage(bmh->cx, bmh->cy, QImage::Format_ARGB32);
                memcpy(alphaImg.bits(), img.bits(), img.numBytes());
                img = alphaImg;
            }
            // flip the bitmap top to bottom to cancel PM inversion
            img = img.mirrored();
        }
    }

    QImage mask;

    if (hbmMask != NULLHANDLE && GpiQueryBitmapInfoHeader(hbmMask, bmh)) {
        // get the AND+XOR mask
        if ((int)bmh->cx == img.width() &&
            (int)bmh->cy == img.height() * 2 &&
            bmh->cPlanes == 1 && bmh->cBitCount == 1) {
            GpiSetBitmap(hps, hbmMask);
            mask = QImage(bmh->cx, bmh->cy, QImage::Format_Mono);
            if (GpiQueryBitmapBits(hps, 0, mask.height(), (PBYTE)mask.bits(),
                                   (PBITMAPINFO2)&bmi) != GPI_ALTERROR) {
                // take the palette
                QVector<QRgb> colors(2);
                colors[0] = QRgb(pal[0]);
                colors[1] = QRgb(pal[1]);
                mask.setColorTable(colors);
                // flip the bitmap top to bottom to cancel PM inversion
                mask = mask.mirrored(false, true);
                // drop the XOR mask
                mask = mask.copy(0, 0, mask.width(), mask.height() / 2);
                // create a normal mask from the AND mask
                mask.invertPixels();
            } else {
                mask = QImage();
            }
            GpiSetBitmap(hps, NULLHANDLE);
        } else {
            Q_ASSERT(false);
        }
    }

    qt_free_mem_ps(hps);

    if (succeeded) {
        res = QPixmap::fromImage(img);
        if (!mask.isNull())
            res.setMask(QBitmap::fromImage(mask));
    }

    return res;
}
コード例 #9
0
int doMagicIn(QString path, QString q, QString OPath)
{
    //skip unexists pairs
    if(!QFile(path+q).exists())
        return CNV_SKIPPED;

    QImage ImgSrc;
    QImage image;
    QImage mask;

    ImgSrc = loadQImage(path+q);

    if(ImgSrc.isNull()) //Skip null images
        return CNV_FAILED;
    QString bname = QFileInfo(path+q).baseName();

    QString saveToImg = QString(OPath+(bname.toLower())+".gif");
    QString saveToMask = QString(OPath+(bname.toLower())+"m.gif");

    QTextStream(stdout) << path+q+"\n";

    mask = ImgSrc.alphaChannel();
    mask.invertPixels();

    //Write mask image
    if( toGif(mask, saveToMask ) ) //Write gif
    {
        QTextStream(stdout) <<"GIF-1\n";
    }
    else
    {
        mask.save(saveToMask, "BMP"); //If failed, write BMP
        QTextStream(stdout) <<"BMP-1\n";
    }



    image = ImgSrc.convertToFormat(QImage::Format_RGB32);
    mask = ImgSrc.alphaChannel();
    mask.invertPixels();
    for(int w=0; w < mask.width(); w++)
        for(int h=0; h < mask.height(); h++)
        {
            if(mask.pixel(w,h)==qRgb(0xFF,0xFF,0xFF)) //Fill white pixel into black on image
            {
                image.setPixel(w,h, qRgb(0,0,0));
            }
            else
            if(mask.pixel(w,h)!=qRgb(0,0,0)) //Fill non-black pixel color into black on mask
            {
                mask.setPixel(w,h, qGray(0,0,0));
            }
        }
    mask.invertPixels();
    image.setAlphaChannel(mask);

    //Write mask image
    if( toGif(image, saveToImg ) ) //Write gif
    {
        QTextStream(stdout) <<"GIF-2\n";
    }
    else
    {
        image.save(saveToImg, "BMP"); //If failed, write BMP
        QTextStream(stdout) <<"BMP-2\n";
    }

    if(removeSource) QFile(path+q).remove();

    return CNV_SUCCESS;
}
コード例 #10
0
/*!
    Creates a \c HBITMAP equivalent to the QPixmap. Returns the \c HBITMAP
    handle.

    If \a mask is not NULL, the mask mode is turned on. In this mode, the bitmap
    mask is also created from the QPixmap's mask and returned in the given
    variable. This bitmap mask will contain two vertically adjacent sections,
    the first of which is the AND mask and the second one is the XOR mask
    (according to WinCreatePointer() specification). Also, in mask mode, the
    HBITMAP returned for the pixmap itself will be prepared for masking (with
    transparent pixels made black). This mode is useful for creating system
    icons and pointers (\sa toPmHPOINTER()).

    if \a embedRealAlpha is \c true, the real alpha chennel (not the 1bpp mask)
    will be embedded in the high 8 bits of the 32-bit pixel value for each pixel
    in the created bitmap (which always has 1 plane and the 32-bit depth). This
    extra information isn't touched by PM/GPI but may be used by custom drawing
    routines to do real alpha blending.

    Note that if \a mask is not NULL but the pixmap does neither have a mask nor
    the alpha channel, an emptpy bitmap mask with no transparency (zeroed AND
    and XOR parts) will be created and returned.

    It is the caller's responsibility to free both returned \c HBITMAP handes
    after use.

    \warning This function is only available on OS/2.

    \sa fromPmHBITMAP(), toPmHPOINTER()
*/
HBITMAP QPixmap::toPmHBITMAP(HBITMAP *mask, bool embedRealAlpha) const
{
    if (data->classId() != QPixmapData::RasterClass) {
        QPixmapData *data = new QRasterPixmapData(depth() == 1 ?
                                                  QPixmapData::BitmapType :
                                                  QPixmapData::PixmapType);
        data->fromImage(toImage(), Qt::AutoColor);
        return QPixmap(data).toPmHBITMAP(mask, embedRealAlpha);
    }

    QRasterPixmapData* d = static_cast<QRasterPixmapData*>(data.data());
    int w = d->image.width();
    int h = d->image.height();

    HPS hps = qt_alloc_mem_ps(w, h * 2);
    if (hps == NULLHANDLE)
        return NULLHANDLE;

    HBITMAP hbm = NULLHANDLE;
    HBITMAP hbmMask = NULLHANDLE;

    // Note that we always use ARGB32 even if embedRealAlpha is false because
    // in this case we will use the alpha channel to dither the 1bpp mask
    QImage image = d->image.convertToFormat(QImage::Format_ARGB32);
    // flip the bitmap top to bottom for PM
    image = image.mirrored();

    // bitmap header + 2 palette entries (for the mask)
    char bmi[sizeof(BITMAPINFOHEADER2) + 4 * 2];
    memset(bmi, 0, sizeof(bmi));
    PBITMAPINFOHEADER2 bmh = (PBITMAPINFOHEADER2)bmi;
    bmh->cbFix = sizeof(BITMAPINFOHEADER2);
    PULONG pal = (PULONG)(bmi + sizeof(BITMAPINFOHEADER2));

    // create the normal bitmap from the pixmap data
    bmh->cx = w;
    bmh->cy = h;
    bmh->cPlanes = 1;
    bmh->cBitCount = 32;
    hbm = GpiCreateBitmap(hps, bmh, CBM_INIT, (PBYTE)(const uchar *)image.bits(),
                          (PBITMAPINFO2)&bmi);

    if (mask) {
        // get the mask
        QImage mask;
        if (hasAlpha()) {
            if (!embedRealAlpha) {
                // We prefer QImage::createAlphaMask() over QPixmap::mask()
                // since the former will dither while the latter will convert any
                // non-zero alpha value to an opaque pixel
                mask = image.createAlphaMask().convertToFormat(QImage::Format_Mono);

                // note: for some strange reason, createAlphaMask() (as opposed to
                // mask().toImage()) returns an image already flipped top to bottom,
                // so take it into account

                // create the AND mask
                mask.invertPixels();
                // add the XOR mask (and leave it zeroed)
                mask = mask.copy(0, -h, w, h * 2);
            } else {
                // if we embedded real alpha, we still need a mask if we are going
                // to create a pointer out of this pixmap (WinCreatePointerIndirect()
                // requirement), but we will use QPixmap::mask() because it won't be
                // able to destroy the alpha channel of non-fully transparent pixels
                // when preparing the color bitmap for masking later. We could also
                // skip this prepare step, but well, let's go this way, it won't hurt.
                mask = this->mask().toImage().convertToFormat(QImage::Format_Mono);

                // create the AND mask
                mask.invertPixels();
                // add the XOR mask (and leave it zeroed)
                mask = mask.copy(0, 0, w, h * 2);
                // flip the bitmap top to bottom for PM
                mask = mask.mirrored(false, true);
            }
        } else {
            mask = QImage(w, h * 2, QImage::Format_Mono);
            mask.fill(0);
        }

        // create the mask bitmap
        bmh->cbFix = sizeof(BITMAPINFOHEADER2);
        bmh->cx = w;
        bmh->cy = h * 2;
        bmh->cPlanes = 1;
        bmh->cBitCount = 1;
        bmh->cclrUsed = 2;
        pal[0] = 0;
        pal[1] = 0x00FFFFFF;
        hbmMask = GpiCreateBitmap(hps, bmh, CBM_INIT,
                                  (PBYTE)(const uchar *)mask.bits(),
                                  (PBITMAPINFO2)&bmi);

        // prepare the bitmap for masking by setting transparent pixels to black
        GpiSetBitmap(hps, hbm);

        POINTL ptls[] = {
            { 0, 0 }, { w - 1, h - 1 },     // dst: inclusive-inclusive
            { 0, h }, { w, h * 2 },         // src: inclusive-exclusive
        };
        ptls[0].y -= h;
        ptls[1].y -= h;
        enum { AllImageAttrs = IBB_COLOR | IBB_BACK_COLOR |
                               IBB_MIX_MODE | IBB_BACK_MIX_MODE };
        IMAGEBUNDLE ib = { CLR_TRUE, CLR_FALSE, FM_OVERPAINT, BM_OVERPAINT };
        GpiSetAttrs(hps, PRIM_IMAGE, AllImageAttrs, 0, (PBUNDLE)&ib);
        GpiDrawBits(hps, (PBYTE)(const uchar *)mask.bits(), (PBITMAPINFO2)&bmi,
                    4, ptls, ROP_SRCAND, BBO_IGNORE);
    }

    qt_free_mem_ps(hps);

    if (mask)
        *mask = hbmMask;

    return hbm;
}
コード例 #11
0
ファイル: ctkQImageView.cpp プロジェクト: malaterre/CTK
// -------------------------------------------------------------------------
void ctkQImageView::update( bool zoomChanged,
  bool sizeChanged )
{
  Q_D( ctkQImageView );
  if( d->SliceNumber >= 0 && d->SliceNumber < d->ImageList.size() )
    {
    const QImage * img = & ( d->ImageList[ d->SliceNumber ] );
    if( zoomChanged || sizeChanged )
      {
      if( this->width() > 0 &&  this->height() > 0 
        && d->TmpXMax > d->TmpXMin && d->TmpYMax > d->TmpYMin)
        {
        int tmpXRange = d->TmpXMax - d->TmpXMin;
        int tmpYRange = d->TmpYMax - d->TmpYMin;
        double tmpAspectRatio = static_cast<double>(tmpYRange) / tmpXRange;
        double screenAspectRatio = static_cast<double>(this->height())
          / this->width();
        if( screenAspectRatio > tmpAspectRatio )
          {
          int extraTmpYAbove = d->TmpYMin;
          int extraTmpYBelow = img->height() - d->TmpYMax;
          int extraTmpYNeeded = tmpXRange * screenAspectRatio 
            - tmpYRange;
          int minExtra = extraTmpYAbove;
          if( extraTmpYBelow < minExtra )
            {
            minExtra = extraTmpYBelow;
            }
          if(2 * minExtra >= extraTmpYNeeded)
            {
            int minNeeded = extraTmpYNeeded / 2.0;
            int maxNeeded = extraTmpYNeeded - minNeeded;
            d->TmpYMin -= minNeeded;
            d->TmpYMax += maxNeeded;
            }
          else if(extraTmpYAbove + extraTmpYBelow >= extraTmpYNeeded)
            {
            if(extraTmpYAbove < extraTmpYBelow)
              {
              d->TmpYMin = 0;
              d->TmpYMax += extraTmpYNeeded - extraTmpYAbove;
              }
            else
              {
              d->TmpYMax = img->height();
              d->TmpYMin -= extraTmpYNeeded - extraTmpYBelow;
              }
            }
          else
            {
            d->TmpYMin = 0;
            d->TmpYMax = img->height();
            }
          d->TmpImage = QPixmap( this->width(),
            static_cast<unsigned int>( 
              static_cast<double>(d->TmpYMax - d->TmpYMin) 
              / (d->TmpXMax - d->TmpXMin)
              * this->width() + 0.5 ) );
          }
        else if(screenAspectRatio < tmpAspectRatio)
          {
          int extraTmpXLeft = d->TmpXMin;
          int extraTmpXRight = img->width() - d->TmpXMax;
          int extraTmpXNeeded = static_cast<double>(tmpYRange) 
            / screenAspectRatio - tmpXRange;
          int minExtra = extraTmpXLeft;
          if( extraTmpXRight < minExtra )
            {
            minExtra = extraTmpXRight;
            }
          if(2 * minExtra >= extraTmpXNeeded)
            {
            int minNeeded = extraTmpXNeeded / 2.0;
            int maxNeeded = extraTmpXNeeded - minNeeded;
            d->TmpXMin -= minNeeded;
            d->TmpXMax += maxNeeded;
            }
          else if(extraTmpXLeft + extraTmpXRight >= extraTmpXNeeded)
            {
            if(extraTmpXLeft < extraTmpXRight)
              {
              d->TmpXMin = 0;
              d->TmpXMax += extraTmpXNeeded - extraTmpXLeft;
              }
            else
              {
              d->TmpXMax = img->width();
              d->TmpXMin -= extraTmpXNeeded - extraTmpXRight;
              }
            }
           else
            {
            d->TmpXMin = 0;
            d->TmpXMax = img->width();
            }
          d->TmpImage = QPixmap( static_cast<unsigned int>( this->height()
            / ( static_cast<double>(d->TmpYMax - d->TmpYMin) 
            / (d->TmpXMax - d->TmpXMin) ) 
            + 0.5 ), this->height() );
          }
        else
          {
          d->TmpImage = QPixmap( this->width(),  this->height() );
          }
        }
      }

    if( d->TmpImage.width() > 0 &&  d->TmpImage.height() > 0)
      {
      QRectF target( 0, 0, d->TmpImage.width(), d->TmpImage.height() );
      double sourceX = d->TmpXMin;
      double sourceY = d->TmpYMin;
      double sourceW = d->TmpXMax - d->TmpXMin;
      double sourceH = d->TmpYMax - d->TmpYMin;
      QPainter painter( &(d->TmpImage) );
      QImage tmpI = *img;
      if( d->InvertImage )
        {
        tmpI.invertPixels();
        }
      if( d->FlipXAxis || d->FlipYAxis )
        {
        tmpI = tmpI.mirrored( d->FlipXAxis, d->FlipYAxis );
        if( d->FlipXAxis )
          {
          sourceX = tmpI.width() - (d->TmpXMax - d->TmpXMin) - d->TmpXMin;
          }
        if( d->FlipYAxis )
          {
          sourceY = tmpI.height() - (d->TmpYMax - d->TmpYMin) - d->TmpYMin;
          }
        }
      QRectF source( sourceX, sourceY, sourceW, sourceH );
      painter.drawPixmap( target, QPixmap::fromImage( tmpI ), source );

      //if( ! sizeChanged )
        {
        int maxNumCharsPerLine = 50;
        int fontPointSize = 12;
        if( fontPointSize * maxNumCharsPerLine > this->width() )
          {
          fontPointSize = this->width() / maxNumCharsPerLine;
          }
        if( fontPointSize > 7 )
          {
          QString fontFamily( "Helvetica" );
          QFont textFont( fontFamily, fontPointSize );
          painter.setFont( textFont );
          QColor textColor;
          textColor.setNamedColor( "lime" );
          textColor.setAlpha( 128 );
          painter.setPen( textColor );
    
          int textFlags = Qt::AlignLeft | Qt::TextDontClip;
    
          QRectF pointRect( 0, 0, 1, 1 );
          QRectF spaceBound = painter.boundingRect( pointRect, textFlags,
            "X" );
    
          if( img->isGrayscale() )
            {
            QString intString = "Intensity Range = ";
            intString.append( QString::number( d->IntensityMin,
              'f', 3 ) );
            intString.append( " - " );
            intString.append( QString::number( d->IntensityMax,
              'f', 3 ) );
            QRectF intBound = painter.boundingRect( pointRect, textFlags,
              intString );
            QRectF intRect( 
              spaceBound.width()/2,
              spaceBound.height()/8,
              intBound.width(), intBound.height() );
            painter.drawText( intRect, textFlags, intString,
              &intBound );

            QString wlString = "W / L = ";
            wlString.append( QString::number( this->intensityWindow(),
              'f', 3 ) );
            wlString.append( " / " );
            wlString.append( QString::number( this->intensityLevel(),
              'f', 3 ) );
            QRectF wlBound = painter.boundingRect( pointRect, textFlags,
              wlString );
            QRectF wlRect( 
              spaceBound.width()/2,
              intRect.y() + intRect.height() + spaceBound.height()/8,
              wlBound.width(), wlBound.height() );
            painter.drawText( wlRect, textFlags, wlString,
              &wlBound );
            }

          QString spacingString = "Spacing = ";
          spacingString.append( QString::number( this->xSpacing(),
            'f', 3 ) );
          spacingString.append( ", " );
          spacingString.append( QString::number( this->ySpacing(),
            'f', 3 ) );
          spacingString.append( ", " );
          spacingString.append( QString::number( this->sliceThickness(),
            'f', 3 ) );
          QRectF spacingBound = painter.boundingRect( pointRect, textFlags,
            spacingString );
          QRectF spacingRect( 
            this->width() - spacingBound.width() - spaceBound.width()/2,
            this->height() - spacingBound.height() - spaceBound.height()/8,
            spacingBound.width(), spacingBound.height() );
          painter.drawText( spacingRect, textFlags, spacingString,
            &spacingBound );
    
          QString dimString = "Size = ";
          dimString.append( 
            QString::number( d->ImageList[ d->SliceNumber ].width() ) );
          dimString.append( ", " );
          dimString.append( 
            QString::number( d->ImageList[ d->SliceNumber ].height() ) );
          dimString.append( ", " );
          dimString.append( 
            QString::number( d->ImageList.size() ) );
          QRectF dimBound = painter.boundingRect( pointRect, textFlags,
            dimString );
          QRectF dimRect( 
            this->width() - dimBound.width() - spaceBound.width()/2,
            spacingBound.y() - dimBound.height() - spaceBound.height()/8,
            dimBound.width(), dimBound.height() );
          painter.drawText( dimRect, textFlags, dimString, &dimBound );
    
          QString rasString = "RAS = ";
          rasString.append( QString::number( 
            this->xPosition() * this->xSpacing(), 'f', 3 ) );
          rasString.append( ", " );
          rasString.append( QString::number( 
            this->yPosition() * this->ySpacing(), 'f', 3 ) );
          rasString.append( ", " );
          rasString.append( QString::number( 
            this->slicePosition() * this->sliceSpacing(), 'f', 3 ) );
          QRectF rasBound = painter.boundingRect( pointRect, textFlags,
            rasString );
          QRectF rasRect( 
            spaceBound.width()/2,
            this->height() - rasBound.height() - spaceBound.height()/8,
            rasBound.width(), rasBound.height() );
          painter.drawText( rasRect, textFlags, rasString,
            &rasBound );
    
          QString ijkString = "IJK = ";
          ijkString.append( QString::number( this->xPosition() ) );
          ijkString.append( ", " );
          ijkString.append( QString::number( this->yPosition() ) );
          ijkString.append( ", " );
          ijkString.append( QString::number( this->slicePosition() ) );
          QRectF ijkBound = painter.boundingRect( pointRect, textFlags,
            ijkString );
          QRectF ijkRect( 
            spaceBound.width()/2,
            rasBound.y() - ijkBound.height() - spaceBound.height()/8,
            ijkBound.width(), ijkBound.height() );
          painter.drawText( ijkRect, textFlags, ijkString, &ijkBound );
    
          QString valString = "Value = ";
          valString.append( QString::number( this->positionValue(),
            'f', 3 ) );
          QRectF valBound = painter.boundingRect( pointRect, textFlags,
            valString );
          QRectF valRect( 
            spaceBound.width()/2,
            ijkBound.y() - valBound.height() - spaceBound.height()/8,
            valBound.width(), valBound.height() );
          painter.drawText( valRect, textFlags, valString, &valBound );
          }
    
        QColor lineColor;
        lineColor.setNamedColor( "red" );
        lineColor.setAlpha( 128 );
        painter.setPen( lineColor );
        double x = ( this->xPosition() - d->TmpXMin ) 
          / (d->TmpXMax - d->TmpXMin) * this->width();
        double y = ( this->yPosition() - d->TmpYMin ) 
          / (d->TmpYMax - d->TmpYMin) * this->height();
        if( d->FlipXAxis )
          {
          x = this->width() - x;
          }
        if( d->FlipYAxis )
          {
          y = this->height() - y;
          }
        QLine lineX( x, 0, x, this->height() );
        painter.drawLine( lineX );
        QLine lineY( 0, y, this->width(), y );
        painter.drawLine( lineY );
        }
      }

    d->Window->setPixmap( d->TmpImage );
    }
  else
    {
    d->Window->setText( "No Image Loaded." );
    }
}
コード例 #12
0
// Hàm dùng lọc ảnh bằng các filter tương ứng
QImage ExtraFiltersPlugin::filterImage(const QString &filter,
                                       const QImage &image, QWidget *parent) {
    // Chuyển đổi định dạng ảnh sang RGB 32-bit để các hàm làm việc như mong
    // đợi
    QImage original = image.convertToFormat(QImage::Format_RGB32);
    QImage result = original;

    if (filter == tr("Lật ngang")) {
        // Nếu filter là "Lật ngang" thì hoán đổi các pixel của ảnh theo chiều
        // ngang của ảnh
        for (int y = 0; y < original.height(); ++y) {
            for (int x = 0; x < original.width(); ++x) {
                int pixel = original.pixel(original.width() - x - 1, y);
                result.setPixel(x, y, pixel);
            }
        }
    } else if (filter == tr("Lật dọc")) {
        // Nếu filter là "Lật dọc" thì hoán đổi các pixel của ảnh theo chiều
        // dọc của ảnh
        for (int y = 0; y < original.height(); ++y) {
            for (int x = 0; x < original.width(); ++x) {
                int pixel = original.pixel(x, original.height() - y - 1);
                result.setPixel(x, y, pixel);
            }
        }
    } else if (filter == tr("Làm mờ")) {
        // Ta sẽ nhân từng điểm ảnh với ma trận tích chập để làm mờ
        // trừ các điểm ở biên.
        int kernel[5][5] = {{0, 0, 1, 0, 0},
            {0, 1, 3, 1, 0},
            {1, 3, 7, 3, 1},
            {0, 1, 3, 1, 0},
            {0, 0, 1, 0, 0}
        };
        int kernelSize = 5;
        int sumKernel = 27;
        int r, g, b;
        int pixel;

        for (int x = kernelSize / 2; x < original.width() - (kernelSize / 2); ++x) {
            for (int y = kernelSize / 2; y < original.height() - (kernelSize / 2); ++y) {
                r = 0;
                g = 0;
                b = 0;
                // Tính tổng giá trị màu của điểm pixel và các điểm ảnh xung quanh
                for ( int i =  -kernelSize / 2 ; i <= kernelSize / 2 ; ++i) {
                    for ( int j =  -kernelSize / 2 ; j <= kernelSize / 2 ; ++j) {
                        pixel = original.pixel ( x + i , y + j );
                        r += qRed(pixel) * kernel[kernelSize / 2 + i][kernelSize / 2 + j] ;
                        g += qGreen(pixel) * kernel[kernelSize / 2 + i][kernelSize / 2 + j];
                        b += qBlue(pixel) * kernel[kernelSize / 2 + i][kernelSize / 2 + j];
                    }
                }

                // Kiểm tra giá trị các màu trong khoảng giới hạn
                r = qBound ( 0 , r / sumKernel ,  255 );
                g = qBound ( 0 , g / sumKernel ,  255 );
                b = qBound ( 0 , b / sumKernel ,  255 );

                result.setPixel ( x, y, qRgba(r , g , b, qAlpha(pixel)));
            }
        }

    } else if (filter == tr("Ảnh nhị phân")) {
        // Nếu filter là "Ảnh nhị phân" thì bật QInputDialog lên cho người dùng
        // nhập vào giá trị ngưỡng, nằm trong khoảng 0 đến 255
        bool ok; // Kiểm tra giá trị nhập
        int threshold = QInputDialog::getInt(parent, tr("Ảnh nhị phân"),
                                             tr("Nhập ngưỡng:"),
                                             85, 0, 255, 1, &ok);
        // Đầu tiên ta chuyển ảnh về ảnh đa mức xám rồi so sánh từng pixel của
        // ảnh với giá trị ngưỡng.
        if (ok) {
            for (int y = 0; y < original.height(); ++y) {
                for (int x = 0; x < original.width(); ++x) {
                    int pixel = original.pixel(x, y);
                    int gray = qGray(pixel);
                    gray = gray > threshold ? 255 : 0;
                    pixel = qRgb(gray, gray, gray);
                    result.setPixel(x, y, pixel);
                }
            }
        }
    } else if (filter == tr("Ảnh âm bản")) {
        // Dùng hàm invertPixels() để đảo ngược các pixel.
        result.invertPixels();
    } else if (filter == tr("Đảo màu (RGB->BGR)")) {
        // Dùng hàm rgbSwapped() để chuyển kênh màu của ảnh từ RGB sang BGR
        result = result.rgbSwapped();
    } else if (filter == tr("Đa mức xám")) {
        //
        for (int y = 0; y < result.height(); ++y) {
            for (int x = 0; x < result.width(); ++x) {
                int pixel = result.pixel(x, y);
                int gray = qGray(pixel);
                int alpha = qAlpha(pixel);
                result.setPixel(x, y, qRgba(gray, gray, gray, alpha));
            }
        }
    } else if (filter == tr("Độ sáng")) {
        // Nếu filter là "Độ sáng" thì bật QInputDialog lên cho người dùng
        // nhập vào giá trị ngưỡng, giá trị này trong khoảng -255 đến 255
        bool ok;  // Kiểm tra giá trị nhập
        int brighness = QInputDialog::getInt(parent, tr("Độ sáng"),
                                             tr("Nhập độ sáng:"),
                                             10, -255, 255, 1, &ok);
        // Ta tăng hoặc giảm giá trị các màu của từng pixel
        if (ok) {
            int r, g, b;

            for (int x = 0; x < original.width(); x++) {
                for (int y = 0; y < original.height(); y++) {

                    int pixel = original.pixel(x, y);

                    r = qRed(pixel) + brighness;
                    g = qGreen(pixel) + brighness;
                    b = qBlue(pixel) + brighness;

                    //Ta kiểm tra các giá trị mới trong khoảng cho phép.
                    r = qBound(0, r, 255);
                    g = qBound(0, g, 255);
                    b = qBound(0, b, 255);

                    result.setPixel(x, y, qRgba(r, g, b, qAlpha(pixel)));
                }
            }
        }
    } else if (filter == tr("Làm ấm")) {
        // Nếu filter là "Làm ấm" thì bật QInputDialog lên cho người dùng
        // nhập vào giá trị, giá trị này trong khoảng 1 đến 255
        bool ok;  // Kiểm tra giá trị nhập
        int delta = QInputDialog::getInt(parent, tr("Lầm ấm"),
                                         tr("Nhập mức độ ấm:"),
                                         10, 1, 255, 1, &ok);
        // Hình sẽ trong ấm hơn nếu ta tăng độ vàng của ảnh, và màu vàng được
        // tổng hợp từ màu đỏ và xanh lục trong kênh màu RGB
        if (ok) {
            int r, g, b;

            for (int x = 0; x < original.width(); x++) {
                for (int y = 0; y < original.height(); y++) {

                    int pixel = original.pixel(x, y);

                    r = qRed(pixel) + delta;
                    g = qGreen(pixel) + delta;
                    b = qBlue(pixel);

                    //Ta kiểm tra các giá trị mới trong khoảng cho phép.
                    r = qBound(0, r, 255);
                    g = qBound(0, g, 255);

                    result.setPixel(x, y, qRgba(r, g, b, qAlpha(pixel)));
                }
            }
        }
    } else if (filter == tr("Làm mát...")) {
        // Nếu filter là "Làm mát" thì bật QInputDialog lên cho người dùng
        // nhập vào giá trị, giá trị này trong khoảng 1 đến 255
        bool ok;  // Kiểm tra giá trị nhập
        int delta = QInputDialog::getInt(parent, tr("Lầm mát"),
                                         tr("Nhập mức độ mát:"),
                                         10, 1, 256, 1, &ok);
        // Hình sẽ có cảm giác mát hơn khi ta tăng giá trị kênh màu xanh lam
        if (ok) {
            int r, g, b;

            for (int x = 0; x < original.width(); x++) {
                for (int y = 0; y < original.height(); y++) {

                    int pixel = original.pixel(x, y);

                    r = qRed(pixel);
                    g = qGreen(pixel);
                    b = qBlue(pixel) + delta;

                    //Ta kiểm tra giá trị mới trong khoảng cho phép.
                    b = qBound(0, b, 255);

                    result.setPixel(x, y, qRgba(r, g, b, qAlpha(pixel)));
                }
            }
        }
    } else if (filter == tr("Độ bão hòa")) {
        // Nếu filter là "Độ bão hòa" thì bật QInputDialog lên cho người dùng
        // nhập vào giá trị, giá trị này trong khoảng -255 đến 255
        bool ok; // Kiểm tra giá trị nhập vào
        int delta = QInputDialog::getInt(parent, tr("Độ bão hòa"),
                                         tr("Nhập độ bão hòa:"),
                                         10, -255, 255, 1, &ok);
        QColor newClolor;
        QColor oldColor;
        int h, s, l;

        // Ta chuyển hình về kênh màu HSL rồi sau đó tăng hoặc giảm kênh
        // saturation để tăng hoặc giảm độ bão hòa sau đó lại chuyển ảnh về RGB
        if (ok) {
            for (int y = 0; y < original.height(); ++y) {
                for (int x = 0; x < original.width(); ++x) {

                    oldColor = QColor(original.pixel(x, y));
                    newClolor = oldColor.toHsl();

                    h = newClolor.hue();
                    s = newClolor.saturation() + delta;
                    l = newClolor.lightness();

                    // Ta kiểm tra giá trị mới trong khoảng cho phép
                    s = qBound(0, s, 255);

                    newClolor.setHsl(h, s, l);

                    result.setPixel(x, y, qRgba(newClolor.red(),
                                                newClolor.green(),
                                                newClolor.blue(),
                                                newClolor.alpha()));
                }
            }
        }
    }
    return result;
}
コード例 #13
0
ファイル: transformacio.cpp プロジェクト: pauek/edoo
QImage Invertir::executa(QImage &I) const {
  I.invertPixels();
  return I;
}
コード例 #14
0
ファイル: cursorimage.cpp プロジェクト: Greedysky/qmmp
QCursor createCursor(QString path)
{
	if (path.isEmpty())
        return QCursor();
	
	// read file headers
	QFile curFile(path);
	curFile.open(QIODevice::ReadOnly);
	QDataStream curStream(&curFile);
	curStream.setByteOrder(QDataStream::LittleEndian);
	
	struct {
		quint16 zero;
		quint16 type;
		quint16 icons;
	} header2;
	curStream >> header2.zero >> header2.type >> header2.icons;

	struct {
		quint8 width;
		quint8 height;
		quint8 ncolours;
		quint8 zero;
		quint16 xhot;
		quint16 yhot;
		quint32 bytes;
		quint32 dibOffset;
	} directory2;
	curStream >> directory2.width >> directory2.height >> directory2.ncolours >> directory2.zero >> directory2.xhot >> directory2.yhot >> directory2.bytes >> directory2.dibOffset;
	
	curFile.seek(directory2.dibOffset);
	
	// prepare a .bmp for delegating decoding to qt
	struct {
		unsigned char magic[2];
		quint32 size;
		quint32 zero;
		quint32 rdataOffset;
	} bmpHeader;
	int bmpHeaderSize = (2+4+4+4);
	struct {
		quint32 hdrSize;
		quint32 width;
		quint32 height;
		quint16 planes;
		quint16 bpp;
		quint32 compression;
		quint32 dataSize;
		quint32 unused1;
		quint32 unused2;
		quint32 unused3;
		quint32 unused4;
	} dibHeader;
	int dibHeaderSize = (4+4+4+2+2+4+4+4+4+4+4);
	
	bmpHeader.magic[0] = 'B'; bmpHeader.magic[1] = 'M';
	bmpHeader.zero = 0;
	bmpHeader.size = bmpHeaderSize + directory2.bytes;
	bmpHeader.rdataOffset = bmpHeaderSize + dibHeaderSize + directory2.ncolours * 4;
	
	curStream >> dibHeader.hdrSize >> dibHeader.width >> dibHeader.height >> dibHeader.planes >> dibHeader.bpp >> dibHeader.compression >> dibHeader.dataSize >> dibHeader.unused1 >> dibHeader.unused2 >> dibHeader.unused3 >> dibHeader.unused4;
	dibHeader.height >>= 1;
	
	// the bmp bytes are in 'bmpData'
	QByteArray bmpData;
	QDataStream bmpStream(&bmpData, QIODevice::WriteOnly);
	bmpStream.setByteOrder(QDataStream::LittleEndian);
	bmpStream.writeRawData((char*) bmpHeader.magic, 2);
	bmpStream << bmpHeader.size << bmpHeader.zero << bmpHeader.rdataOffset;
	bmpStream << dibHeader.hdrSize << dibHeader.width << dibHeader.height << dibHeader.planes << dibHeader.bpp << dibHeader.compression << dibHeader.dataSize << dibHeader.unused1 << dibHeader.unused2 << dibHeader.unused3 << dibHeader.unused4;
	bmpData.append(curFile.read(directory2.bytes - dibHeaderSize));
	
	// decode the image into 'pix'
	int width = directory2.width;
	int height = directory2.height;
	QImage image;
	image.loadFromData(bmpData);
	//qDebug() << image.rect() << path;
	QPixmap pix = QPixmap::fromImage(image);
	
	// now we need the mask (transparency)
	QByteArray maskData = bmpData.right((width * height) / 8);
	QImage maskImage = QBitmap::fromData(QSize(width, height), (const uchar*) maskData.constData(), QImage::Format_Mono).toImage().mirrored(false, true);
	maskImage.invertPixels();
	pix.setMask(QBitmap::fromImage(maskImage));
	
	return QCursor(pix, directory2.xhot, directory2.yhot);
}