2010-10-11 9 views
5

QT4 ¿Cómo desenfocar la imagen de QPixmap?QT4 ¿Cómo desenfocar la imagen de QPixmap?

Busco algo así como uno de los siguientes:

Blur(pixmap); 
painter.Blur(); 
painter.Blur(rect); 

¿Cuál es la mejor manera de hacer esto?

+0

Creo que liuyanghejerry ha esperado el tiempo suficiente para obtener la mejor respuesta. –

Respuesta

0

A Gaussian blur es una forma simple de crear un efecto de desenfoque.

Edit: Y lo, me encontré con Qt's QGraphicsBlurEffect. Presentado en Qt 4.6, parece hacer exactamente lo que quieres.

+1

No tengo idea de cómo aplicar QGraphicsBlurEffect a pixmap ... – Astronavigator

+0

Los QGraphicsEffects están destinados a ser aplicados a vistas de gráficos, no pixmaps.Sin embargo, la idea general de un borrón guassiano es el camino a seguir; solo tendrá que implementar el algoritmo usted mismo en el mapa de píxeles. (Sin embargo, podría ser más rápido/más fácil de convertir a una QImage). –

+1

Todo el mundo conoce estos algoritmos. Pero para implementarlos, tengo que encontrar la forma de: 1. convertir QPixmap en 2d array 2. forma de convertir de 2d array a pixmap. Si su consejo es implementarlo yo mismo, entonces explique cómo convertir entre QPixmap y 2d array – Astronavigator

4

Salida esto:

#include <QtGui/QApplication> 
#include <QImage> 
#include <QPixmap> 
#include <QLabel> 

QImage blurred(const QImage& image, const QRect& rect, int radius, bool alphaOnly = false) 
{ 
    int tab[] = { 14, 10, 8, 6, 5, 5, 4, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2 }; 
    int alpha = (radius < 1) ? 16 : (radius > 17) ? 1 : tab[radius-1]; 

    QImage result = image.convertToFormat(QImage::Format_ARGB32_Premultiplied); 
    int r1 = rect.top(); 
    int r2 = rect.bottom(); 
    int c1 = rect.left(); 
    int c2 = rect.right(); 

    int bpl = result.bytesPerLine(); 
    int rgba[4]; 
    unsigned char* p; 

    int i1 = 0; 
    int i2 = 3; 

    if (alphaOnly) 
     i1 = i2 = (QSysInfo::ByteOrder == QSysInfo::BigEndian ? 0 : 3); 

    for (int col = c1; col <= c2; col++) { 
     p = result.scanLine(r1) + col * 4; 
     for (int i = i1; i <= i2; i++) 
      rgba[i] = p[i] << 4; 

     p += bpl; 
     for (int j = r1; j < r2; j++, p += bpl) 
      for (int i = i1; i <= i2; i++) 
       p[i] = (rgba[i] += ((p[i] << 4) - rgba[i]) * alpha/16) >> 4; 
    } 

    for (int row = r1; row <= r2; row++) { 
     p = result.scanLine(row) + c1 * 4; 
     for (int i = i1; i <= i2; i++) 
      rgba[i] = p[i] << 4; 

     p += 4; 
     for (int j = c1; j < c2; j++, p += 4) 
      for (int i = i1; i <= i2; i++) 
       p[i] = (rgba[i] += ((p[i] << 4) - rgba[i]) * alpha/16) >> 4; 
    } 

    for (int col = c1; col <= c2; col++) { 
     p = result.scanLine(r2) + col * 4; 
     for (int i = i1; i <= i2; i++) 
      rgba[i] = p[i] << 4; 

     p -= bpl; 
     for (int j = r1; j < r2; j++, p -= bpl) 
      for (int i = i1; i <= i2; i++) 
       p[i] = (rgba[i] += ((p[i] << 4) - rgba[i]) * alpha/16) >> 4; 
    } 

    for (int row = r1; row <= r2; row++) { 
     p = result.scanLine(row) + c2 * 4; 
     for (int i = i1; i <= i2; i++) 
      rgba[i] = p[i] << 4; 

     p -= 4; 
     for (int j = c1; j < c2; j++, p -= 4) 
      for (int i = i1; i <= i2; i++) 
       p[i] = (rgba[i] += ((p[i] << 4) - rgba[i]) * alpha/16) >> 4; 
    } 

    return result; 
} 

int main(int argc, char *argv[]) 
{ 
    QApplication a(argc, argv); 
    QLabel label; 
    QImage image("image.png"); 
    image = blurred(image,image.rect(),10,false); 
    label.setPixmap(QPixmap::fromImage(image)); 
    label.show(); 

    return a.exec(); 
} 
6

Método 1a: agarrar los trozos crudos y hágalo usted mismo. Tendrá que estar lo suficientemente familiarizado con mapas de bits y algoritmos borrosos para implementar el desenfoque usted mismo. Si quiere ese tipo de precisión, este es el camino a seguir.

QImage image = pixmap.toImage(); 
if (image.format() != QImage::Format_RGB32) 
    image = image.convertToFormat(QImage::Format_RGB32); 
uchar* bits = image.bits(); 
int rowBytes = image.bytesPerLine(); 
DoMyOwnBlurAlgorithm(bits, image.width(), image.height(), rowBytes); 
return QPixmap::fromImage(image); 

Método 1b: who needs raw bits? Puede usar image.pixel (x, y) y image.setPixel (x, y, color) en su lugar. Esto no será tan rápido como 1a, pero debería ser un poco más fácil de entender y codificar.

QImage image = pixmap.toImage(); 
QImage output(image.width(), image.height(), image.format()); 
for (int y=0; y<image.height(); ++y) 
    for (int x=0; x<image.width(); ++x) 
     output.setPixel(getBlurredColor(image, x, y)); 
return output; 

Método 2: utilice un QGraphicsBlurEffect, a través de un widget o escena. El código aquí usa un widget de etiqueta:

QPixmap BlurAPixmap(const QPixmap& inPixmap) 
{ 
    QLabel* label = new QLabel(); 
    label->setPixmap(inPixmap); 
    label->setGraphicsEffect(new QGraphicsBlurEffect()); 
    QPixmap output(inPixmap.width(), inPixmap.height()); 
    QPainter painter(&output); 
    label->render(&painter); 
    return output; 
} 

Modifique según sea necesario. Por ejemplo, supongo que el efecto de desenfoque de gráficos predeterminado es aceptable. Estoy usando el Método 2 en mi proyecto.

9

1º) Declarar la rutina externa QT:

QT_BEGIN_NAMESPACE 
    extern Q_WIDGETS_EXPORT void qt_blurImage(QPainter *p, QImage &blurImage, qreal radius, bool quality, bool alphaOnly, int transposed = 0); 
QT_END_NAMESPACE 

segundo) Uso:

extern QImage srcImg;//source image 
    QPixmap pxDst(srcImg.size());//blurred destination 
    pxDst.fill(Qt::transparent); 
    { 
    QPainter painter(&pxDst); 
    qt_blurImage(&painter, srcImg, 2, true, false);//blur radius: 2px 
    } 
+0

A veces me pregunto por qué se han planteado preguntas de menor calidad en lugar de las buenas. La suya es hasta ahora la mejor respuesta a esta pregunta. +1 – mhcuervo

3

Vamos a contribuir a este tema. A partir de Qt 5.3, siguiente función le ayudará mucho con la aplicación de QGraphicsEffect a QImage (y no perder la alfa)

QImage applyEffectToImage(QImage src, QGraphicsEffect *effect, int extent = 0) 
{ 
    if(src.isNull()) return QImage(); //No need to do anything else! 
    if(!effect) return src;    //No need to do anything else! 
    QGraphicsScene scene; 
    QGraphicsPixmapItem item; 
    item.setPixmap(QPixmap::fromImage(src)); 
    item.setGraphicsEffect(effect); 
    scene.addItem(&item); 
    QImage res(src.size()+QSize(extent*2, extent*2), QImage::Format_ARGB32); 
    res.fill(Qt::transparent); 
    QPainter ptr(&res); 
    scene.render(&ptr, QRectF(), QRectF(-extent, -extent, src.width()+extent*2, src.height()+extent*2)); 
    return res; 
} 

ellos, utilizando esta función para difuminar su imagen es sencillo:

QGraphicsBlurEffect *blur = new QGraphicsBlurEffect; 
blur->setBlurRadius(8); 
QImage source("://img1.png"); 
QImage result = applyEffectToImage(source, blur); 
result.save("final.png"); 

Por supuesto, no es necesario guardarlo, esto fue solo un ejemplo de utilidad. incluso Usted puede dejar una sombra:

QGraphicsDropShadowEffect *e = new QGraphicsDropShadowEffect; 
e->setColor(QColor(40,40,40,245)); 
e->setOffset(0,10); 
e->setBlurRadius(50); 
QImage p("://img3.png"); 
QImage res = applyEffectToImage(p, e, 40); 

Y tenga en cuenta el parámetro de medida, se añade extent número de píxeles a todos los lados de la imagen original, especialmente útiles para las sombras y difumina para que no se corte.