src/gui/image/qpixmap_raster.cpp
changeset 33 3e2da88830cd
parent 30 5dc02b23752f
equal deleted inserted replaced
30:5dc02b23752f 33:3e2da88830cd
    45 #include "qnativeimage_p.h"
    45 #include "qnativeimage_p.h"
    46 #include "qimage_p.h"
    46 #include "qimage_p.h"
    47 
    47 
    48 #include "qbitmap.h"
    48 #include "qbitmap.h"
    49 #include "qimage.h"
    49 #include "qimage.h"
       
    50 #include <QBuffer>
       
    51 #include <QImageReader>
       
    52 #include <private/qsimd_p.h>
    50 #include <private/qwidget_p.h>
    53 #include <private/qwidget_p.h>
    51 #include <private/qdrawhelper_p.h>
    54 #include <private/qdrawhelper_p.h>
    52 
    55 
    53 QT_BEGIN_NAMESPACE
    56 QT_BEGIN_NAMESPACE
    54 
    57 
   125     }
   128     }
   126 
   129 
   127     setSerialNumber(image.serialNumber());
   130     setSerialNumber(image.serialNumber());
   128 }
   131 }
   129 
   132 
       
   133 bool QRasterPixmapData::fromData(const uchar *buffer, uint len, const char *format,
       
   134                       Qt::ImageConversionFlags flags)
       
   135 {
       
   136     QByteArray a = QByteArray::fromRawData(reinterpret_cast<const char *>(buffer), len);
       
   137     QBuffer b(&a);
       
   138     b.open(QIODevice::ReadOnly);
       
   139     QImage image = QImageReader(&b, format).read();
       
   140     if (image.isNull())
       
   141         return false;
       
   142 
       
   143     createPixmapForImage(image, flags, /* inplace = */true);
       
   144     return !isNull();
       
   145 }
       
   146 
   130 void QRasterPixmapData::fromImage(const QImage &sourceImage,
   147 void QRasterPixmapData::fromImage(const QImage &sourceImage,
   131                                   Qt::ImageConversionFlags flags)
   148                                   Qt::ImageConversionFlags flags)
   132 {
   149 {
   133     Q_UNUSED(flags);
   150     Q_UNUSED(flags);
   134 
   151     QImage image = sourceImage;
   135 #ifdef Q_WS_QWS
   152     createPixmapForImage(image, flags, /* inplace = */false);
   136     QImage::Format format;
   153 }
   137     if (pixelType() == BitmapType) {
   154 
   138         format = QImage::Format_Mono;
   155 void QRasterPixmapData::fromImageReader(QImageReader *imageReader,
   139     } else {
   156                                         Qt::ImageConversionFlags flags)
   140         format = QScreen::instance()->pixelFormat();
   157 {
   141         if (format == QImage::Format_Invalid)
   158     Q_UNUSED(flags);
   142             format = QImage::Format_ARGB32_Premultiplied;
   159     QImage image = imageReader->read();
   143         else if (format == QImage::Format_Indexed8) // currently not supported
   160     if (image.isNull())
   144             format = QImage::Format_RGB444;
   161         return;
   145     }
   162 
   146 
   163     createPixmapForImage(image, flags, /* inplace = */true);
   147     if (sourceImage.hasAlphaChannel()
       
   148         && ((flags & Qt::NoOpaqueDetection)
       
   149             || const_cast<QImage &>(sourceImage).data_ptr()->checkForAlphaPixels())) {
       
   150         switch (format) {
       
   151             case QImage::Format_RGB16:
       
   152                 format = QImage::Format_ARGB8565_Premultiplied;
       
   153                 break;
       
   154             case QImage::Format_RGB666:
       
   155                 format = QImage::Format_ARGB6666_Premultiplied;
       
   156                 break;
       
   157             case QImage::Format_RGB555:
       
   158                 format = QImage::Format_ARGB8555_Premultiplied;
       
   159                 break;
       
   160             case QImage::Format_RGB444:
       
   161                 format = QImage::Format_ARGB4444_Premultiplied;
       
   162                 break;
       
   163             default:
       
   164                 format = QImage::Format_ARGB32_Premultiplied;
       
   165                 break;
       
   166         }
       
   167     } else if (format == QImage::Format_Invalid) {
       
   168         format = QImage::Format_ARGB32_Premultiplied;
       
   169     }
       
   170 
       
   171     image = sourceImage.convertToFormat(format);
       
   172 #else
       
   173     if (pixelType() == BitmapType) {
       
   174         image = sourceImage.convertToFormat(QImage::Format_MonoLSB);
       
   175     } else {
       
   176         if (sourceImage.depth() == 1) {
       
   177             image = sourceImage.hasAlphaChannel()
       
   178                     ? sourceImage.convertToFormat(QImage::Format_ARGB32_Premultiplied)
       
   179                     : sourceImage.convertToFormat(QImage::Format_RGB32);
       
   180         } else {
       
   181 
       
   182             QImage::Format opaqueFormat = QNativeImage::systemFormat();
       
   183             QImage::Format alphaFormat = QImage::Format_ARGB32_Premultiplied;
       
   184 
       
   185 #ifndef QT_HAVE_NEON
       
   186             switch (opaqueFormat) {
       
   187             case QImage::Format_RGB16:
       
   188                 alphaFormat = QImage::Format_ARGB8565_Premultiplied;
       
   189                 break;
       
   190             default: // We don't care about the others...
       
   191                 break;
       
   192             }
       
   193 #endif
       
   194 
       
   195             if (!sourceImage.hasAlphaChannel()
       
   196                 || ((flags & Qt::NoOpaqueDetection) == 0
       
   197                     && !const_cast<QImage &>(sourceImage).data_ptr()->checkForAlphaPixels())) {
       
   198                 image = sourceImage.convertToFormat(opaqueFormat);
       
   199             } else {
       
   200                 image = sourceImage.convertToFormat(alphaFormat);
       
   201             }
       
   202         }
       
   203     }
       
   204 #endif
       
   205     if (image.d) {
       
   206         w = image.d->width;
       
   207         h = image.d->height;
       
   208         d = image.d->depth;
       
   209     } else {
       
   210         w = h = d = 0;
       
   211     }
       
   212     is_null = (w <= 0 || h <= 0);
       
   213 
       
   214     setSerialNumber(image.serialNumber());
       
   215 }
   164 }
   216 
   165 
   217 // from qwindowsurface.cpp
   166 // from qwindowsurface.cpp
   218 extern void qt_scrollRectInImage(QImage &img, const QRect &rect, const QPoint &offset);
   167 extern void qt_scrollRectInImage(QImage &img, const QRect &rect, const QPoint &offset);
       
   168 
       
   169 void QRasterPixmapData::copy(const QPixmapData *data, const QRect &rect)
       
   170 {
       
   171     fromImage(data->toImage(rect).copy(), Qt::NoOpaqueDetection);
       
   172 }
   219 
   173 
   220 bool QRasterPixmapData::scroll(int dx, int dy, const QRect &rect)
   174 bool QRasterPixmapData::scroll(int dx, int dy, const QRect &rect)
   221 {
   175 {
   222     if (!image.isNull())
   176     if (!image.isNull())
   223         qt_scrollRectInImage(image, rect, QPoint(dx, dy));
   177         qt_scrollRectInImage(image, rect, QPoint(dx, dy));
   238     } else if (image.depth() >= 15) {
   192     } else if (image.depth() >= 15) {
   239         int alpha = color.alpha();
   193         int alpha = color.alpha();
   240         if (alpha != 255) {
   194         if (alpha != 255) {
   241             if (!image.hasAlphaChannel()) {
   195             if (!image.hasAlphaChannel()) {
   242                 QImage::Format toFormat;
   196                 QImage::Format toFormat;
   243 #ifndef QT_HAVE_NEON
   197 #if !(defined(QT_HAVE_NEON) || defined(QT_ALWAYS_HAVE_SSE2))
   244                 if (image.format() == QImage::Format_RGB16)
   198                 if (image.format() == QImage::Format_RGB16)
   245                     toFormat = QImage::Format_ARGB8565_Premultiplied;
   199                     toFormat = QImage::Format_ARGB8565_Premultiplied;
   246                 else if (image.format() == QImage::Format_RGB666)
   200                 else if (image.format() == QImage::Format_RGB666)
   247                     toFormat = QImage::Format_ARGB6666_Premultiplied;
   201                     toFormat = QImage::Format_ARGB6666_Premultiplied;
   248                 else if (image.format() == QImage::Format_RGB555)
   202                 else if (image.format() == QImage::Format_RGB555)
   347 }
   301 }
   348 
   302 
   349 QImage QRasterPixmapData::toImage() const
   303 QImage QRasterPixmapData::toImage() const
   350 {
   304 {
   351     return image;
   305     return image;
       
   306 }
       
   307 
       
   308 QImage QRasterPixmapData::toImage(const QRect &rect) const
       
   309 {
       
   310     if (rect.isNull())
       
   311         return image;
       
   312 
       
   313     QRect clipped = rect.intersected(QRect(0, 0, w, h));
       
   314     if (d % 8 == 0)
       
   315         return QImage(image.scanLine(clipped.y()) + clipped.x() * (d / 8),
       
   316                       clipped.width(), clipped.height(),
       
   317                       image.bytesPerLine(), image.format());
       
   318     else
       
   319         return image.copy(clipped);
   352 }
   320 }
   353 
   321 
   354 void QRasterPixmapData::setAlphaChannel(const QPixmap &alphaChannel)
   322 void QRasterPixmapData::setAlphaChannel(const QPixmap &alphaChannel)
   355 {
   323 {
   356     image.setAlphaChannel(alphaChannel.toImage());
   324     image.setAlphaChannel(alphaChannel.toImage());
   396     }
   364     }
   397 
   365 
   398     return 0;
   366     return 0;
   399 }
   367 }
   400 
   368 
       
   369 void QRasterPixmapData::createPixmapForImage(QImage &sourceImage, Qt::ImageConversionFlags flags, bool inPlace)
       
   370 {
       
   371     QImage::Format format;
       
   372 #ifdef Q_WS_QWS
       
   373     if (pixelType() == BitmapType) {
       
   374         format = QImage::Format_Mono;
       
   375     } else {
       
   376         format = QScreen::instance()->pixelFormat();
       
   377         if (format == QImage::Format_Invalid)
       
   378             format = QImage::Format_ARGB32_Premultiplied;
       
   379         else if (format == QImage::Format_Indexed8) // currently not supported
       
   380             format = QImage::Format_RGB444;
       
   381     }
       
   382 
       
   383     if (sourceImage.hasAlphaChannel()
       
   384         && ((flags & Qt::NoOpaqueDetection)
       
   385             || const_cast<QImage &>(sourceImage).data_ptr()->checkForAlphaPixels())) {
       
   386         switch (format) {
       
   387             case QImage::Format_RGB16:
       
   388                 format = QImage::Format_ARGB8565_Premultiplied;
       
   389                 break;
       
   390             case QImage::Format_RGB666:
       
   391                 format = QImage::Format_ARGB6666_Premultiplied;
       
   392                 break;
       
   393             case QImage::Format_RGB555:
       
   394                 format = QImage::Format_ARGB8555_Premultiplied;
       
   395                 break;
       
   396             case QImage::Format_RGB444:
       
   397                 format = QImage::Format_ARGB4444_Premultiplied;
       
   398                 break;
       
   399             default:
       
   400                 format = QImage::Format_ARGB32_Premultiplied;
       
   401                 break;
       
   402         }
       
   403     } else if (format == QImage::Format_Invalid) {
       
   404         format = QImage::Format_ARGB32_Premultiplied;
       
   405     }
       
   406 #else
       
   407     if (pixelType() == BitmapType) {
       
   408         format = QImage::Format_MonoLSB;
       
   409     } else {
       
   410         if (sourceImage.depth() == 1) {
       
   411             format = sourceImage.hasAlphaChannel()
       
   412                     ? QImage::Format_ARGB32_Premultiplied
       
   413                     : QImage::Format_RGB32;
       
   414         } else {
       
   415             QImage::Format opaqueFormat = QNativeImage::systemFormat();
       
   416             QImage::Format alphaFormat = QImage::Format_ARGB32_Premultiplied;
       
   417 
       
   418 #if !defined(QT_HAVE_NEON) && !defined(QT_ALWAYS_HAVE_SSE2)
       
   419             switch (opaqueFormat) {
       
   420             case QImage::Format_RGB16:
       
   421                 alphaFormat = QImage::Format_ARGB8565_Premultiplied;
       
   422                 break;
       
   423             default: // We don't care about the others...
       
   424                 break;
       
   425             }
       
   426 #endif
       
   427 
       
   428             if (!sourceImage.hasAlphaChannel()) {
       
   429                 format = opaqueFormat;
       
   430             } else if ((flags & Qt::NoOpaqueDetection) == 0
       
   431                        && !const_cast<QImage &>(sourceImage).data_ptr()->checkForAlphaPixels())
       
   432             {
       
   433                 // image has alpha format but is really opaque, so try to do a
       
   434                 // more efficient conversion
       
   435                 if (sourceImage.format() == QImage::Format_ARGB32
       
   436                     || sourceImage.format() == QImage::Format_ARGB32_Premultiplied)
       
   437                 {
       
   438                     if (!inPlace)
       
   439                         sourceImage.detach();
       
   440                     sourceImage.d->format = QImage::Format_RGB32;
       
   441                 }
       
   442                 format = opaqueFormat;
       
   443             } else {
       
   444                 format = alphaFormat;
       
   445             }
       
   446         }
       
   447     }
       
   448 #endif
       
   449 
       
   450     if (inPlace && sourceImage.d->convertInPlace(format, flags)) {
       
   451         image = sourceImage;
       
   452     } else {
       
   453         image = sourceImage.convertToFormat(format);
       
   454     }
       
   455 
       
   456     if (image.d) {
       
   457         w = image.d->width;
       
   458         h = image.d->height;
       
   459         d = image.d->depth;
       
   460     } else {
       
   461         w = h = d = 0;
       
   462     }
       
   463     is_null = (w <= 0 || h <= 0);
       
   464 
       
   465     setSerialNumber(image.serialNumber());
       
   466 }
       
   467 
   401 QImage* QRasterPixmapData::buffer()
   468 QImage* QRasterPixmapData::buffer()
   402 {
   469 {
   403     return &image;
   470     return &image;
   404 }
   471 }
   405 
   472