src/gui/image/qimage.cpp
changeset 33 3e2da88830cd
parent 30 5dc02b23752f
child 37 758a864f9613
equal deleted inserted replaced
30:5dc02b23752f 33:3e2da88830cd
    56 #include <math.h>
    56 #include <math.h>
    57 #include <private/qdrawhelper_p.h>
    57 #include <private/qdrawhelper_p.h>
    58 #include <private/qmemrotate_p.h>
    58 #include <private/qmemrotate_p.h>
    59 #include <private/qpixmapdata_p.h>
    59 #include <private/qpixmapdata_p.h>
    60 #include <private/qimagescale_p.h>
    60 #include <private/qimagescale_p.h>
       
    61 #include <private/qsimd_p.h>
    61 
    62 
    62 #include <qhash.h>
    63 #include <qhash.h>
    63 
    64 
    64 #include <private/qpaintengine_raster_p.h>
    65 #include <private/qpaintengine_raster_p.h>
    65 
    66 
   207     default:
   208     default:
   208         numColors = 0;
   209         numColors = 0;
   209         break;
   210         break;
   210     }
   211     }
   211 
   212 
   212     const int bytes_per_line = ((width * depth + 31) >> 5) << 2; // bytes per scanline (must be multiple of 8)
   213     const int bytes_per_line = ((width * depth + 31) >> 5) << 2; // bytes per scanline (must be multiple of 4)
   213 
   214 
   214     // sanity check for potential overflows
   215     // sanity check for potential overflows
   215     if (INT_MAX/depth < width
   216     if (INT_MAX/depth < width
   216         || bytes_per_line <= 0
   217         || bytes_per_line <= 0
   217         || height <= 0
   218         || height <= 0
   270 {
   271 {
   271     bool has_alpha_pixels = false;
   272     bool has_alpha_pixels = false;
   272 
   273 
   273     switch (format) {
   274     switch (format) {
   274 
   275 
       
   276     case QImage::Format_Mono:
       
   277     case QImage::Format_MonoLSB:
   275     case QImage::Format_Indexed8:
   278     case QImage::Format_Indexed8:
   276         has_alpha_pixels = has_alpha_clut;
   279         has_alpha_pixels = has_alpha_clut;
   277         break;
   280         break;
   278 
   281 
   279     case QImage::Format_ARGB32:
   282     case QImage::Format_ARGB32:
  2270   Internal routines for converting image depth.
  2273   Internal routines for converting image depth.
  2271  *****************************************************************************/
  2274  *****************************************************************************/
  2272 
  2275 
  2273 typedef void (*Image_Converter)(QImageData *dest, const QImageData *src, Qt::ImageConversionFlags);
  2276 typedef void (*Image_Converter)(QImageData *dest, const QImageData *src, Qt::ImageConversionFlags);
  2274 
  2277 
       
  2278 typedef bool (*InPlace_Image_Converter)(QImageData *data, Qt::ImageConversionFlags);
       
  2279 
  2275 static void convert_ARGB_to_ARGB_PM(QImageData *dest, const QImageData *src, Qt::ImageConversionFlags)
  2280 static void convert_ARGB_to_ARGB_PM(QImageData *dest, const QImageData *src, Qt::ImageConversionFlags)
  2276 {
  2281 {
  2277     Q_ASSERT(src->format == QImage::Format_ARGB32);
  2282     Q_ASSERT(src->format == QImage::Format_ARGB32);
  2278     Q_ASSERT(dest->format == QImage::Format_ARGB32_Premultiplied);
  2283     Q_ASSERT(dest->format == QImage::Format_ARGB32_Premultiplied);
  2279     Q_ASSERT(src->width == dest->width);
  2284     Q_ASSERT(src->width == dest->width);
  2291             ++src_data;
  2296             ++src_data;
  2292             ++dest_data;
  2297             ++dest_data;
  2293         }
  2298         }
  2294         src_data += src_pad;
  2299         src_data += src_pad;
  2295         dest_data += dest_pad;
  2300         dest_data += dest_pad;
       
  2301     }
       
  2302 }
       
  2303 
       
  2304 static bool convert_ARGB_to_ARGB_PM_inplace(QImageData *data, Qt::ImageConversionFlags)
       
  2305 {
       
  2306     Q_ASSERT(data->format == QImage::Format_ARGB32);
       
  2307 
       
  2308     const int pad = (data->bytes_per_line >> 2) - data->width;
       
  2309     QRgb *rgb_data = (QRgb *) data->data;
       
  2310 
       
  2311     for (int i = 0; i < data->height; ++i) {
       
  2312         const QRgb *end = rgb_data + data->width;
       
  2313         while (rgb_data < end) {
       
  2314             *rgb_data = PREMUL(*rgb_data);
       
  2315             ++rgb_data;
       
  2316         }
       
  2317         rgb_data += pad;
       
  2318     }
       
  2319     data->format = QImage::Format_ARGB32_Premultiplied;
       
  2320     return true;
       
  2321 }
       
  2322 
       
  2323 static bool convert_indexed8_to_ARGB_PM_inplace(QImageData *data, Qt::ImageConversionFlags)
       
  2324 {
       
  2325     Q_ASSERT(data->format == QImage::Format_Indexed8);
       
  2326     const int depth = 32;
       
  2327 
       
  2328     const int dst_bytes_per_line = ((data->width * depth + 31) >> 5) << 2;
       
  2329     const int nbytes = dst_bytes_per_line * data->height;
       
  2330     uchar *const newData = (uchar *)realloc(data->data, nbytes);
       
  2331     if (!newData)
       
  2332         return false;
       
  2333 
       
  2334     data->data = newData;
       
  2335 
       
  2336     // start converting from the end because the end image is bigger than the source
       
  2337     uchar *src_data = newData + data->nbytes; // end of src
       
  2338     quint32 *dest_data = (quint32 *) (newData + nbytes); // end of dest > end of src
       
  2339     const int width = data->width;
       
  2340     const int src_pad = data->bytes_per_line - width;
       
  2341     const int dest_pad = (dst_bytes_per_line >> 2) - width;
       
  2342     if (data->colortable.size() == 0) {
       
  2343         data->colortable.resize(256);
       
  2344         for (int i = 0; i < 256; ++i)
       
  2345             data->colortable[i] = qRgb(i, i, i);
       
  2346     } else {
       
  2347         for (int i = 0; i < data->colortable.size(); ++i)
       
  2348             data->colortable[i] = PREMUL(data->colortable.at(i));
       
  2349 
       
  2350         // Fill the rest of the table in case src_data > colortable.size()
       
  2351         const int oldSize = data->colortable.size();
       
  2352         const QRgb lastColor = data->colortable.at(oldSize - 1);
       
  2353         data->colortable.insert(oldSize, 256 - oldSize, lastColor);
       
  2354     }
       
  2355 
       
  2356     for (int i = 0; i < data->height; ++i) {
       
  2357         src_data -= src_pad;
       
  2358         dest_data -= dest_pad;
       
  2359         for (int pixI = 0; pixI < width; ++pixI) {
       
  2360             --src_data;
       
  2361             --dest_data;
       
  2362             *dest_data = data->colortable.at(*src_data);
       
  2363         }
       
  2364     }
       
  2365 
       
  2366     data->colortable = QVector<QRgb>();
       
  2367     data->format = QImage::Format_ARGB32_Premultiplied;
       
  2368     data->bytes_per_line = dst_bytes_per_line;
       
  2369     data->depth = depth;
       
  2370     data->nbytes = nbytes;
       
  2371 
       
  2372     return true;
       
  2373 }
       
  2374 
       
  2375 static bool convert_indexed8_to_RGB_inplace(QImageData *data, Qt::ImageConversionFlags)
       
  2376 {
       
  2377     Q_ASSERT(data->format == QImage::Format_Indexed8);
       
  2378     const int depth = 32;
       
  2379 
       
  2380     const int dst_bytes_per_line = ((data->width * depth + 31) >> 5) << 2;
       
  2381     const int nbytes = dst_bytes_per_line * data->height;
       
  2382     uchar *const newData = (uchar *)realloc(data->data, nbytes);
       
  2383     if (!newData)
       
  2384         return false;
       
  2385 
       
  2386     data->data = newData;
       
  2387 
       
  2388     // start converting from the end because the end image is bigger than the source
       
  2389     uchar *src_data = newData + data->nbytes;
       
  2390     quint32 *dest_data = (quint32 *) (newData + nbytes);
       
  2391     const int width = data->width;
       
  2392     const int src_pad = data->bytes_per_line - width;
       
  2393     const int dest_pad = (dst_bytes_per_line >> 2) - width;
       
  2394     if (data->colortable.size() == 0) {
       
  2395         data->colortable.resize(256);
       
  2396         for (int i = 0; i < 256; ++i)
       
  2397             data->colortable[i] = qRgb(i, i, i);
       
  2398     } else {
       
  2399         // Fill the rest of the table in case src_data > colortable.size()
       
  2400         const int oldSize = data->colortable.size();
       
  2401         const QRgb lastColor = data->colortable.at(oldSize - 1);
       
  2402         data->colortable.insert(oldSize, 256 - oldSize, lastColor);
       
  2403     }
       
  2404 
       
  2405     for (int i = 0; i < data->height; ++i) {
       
  2406         src_data -= src_pad;
       
  2407         dest_data -= dest_pad;
       
  2408         for (int pixI = 0; pixI < width; ++pixI) {
       
  2409             --src_data;
       
  2410             --dest_data;
       
  2411             *dest_data = (quint32) data->colortable.at(*src_data);
       
  2412         }
       
  2413     }
       
  2414 
       
  2415     data->colortable = QVector<QRgb>();
       
  2416     data->format = QImage::Format_RGB32;
       
  2417     data->bytes_per_line = dst_bytes_per_line;
       
  2418     data->depth = depth;
       
  2419     data->nbytes = nbytes;
       
  2420 
       
  2421     return true;
       
  2422 }
       
  2423 
       
  2424 static bool convert_indexed8_to_RGB16_inplace(QImageData *data, Qt::ImageConversionFlags)
       
  2425 {
       
  2426     Q_ASSERT(data->format == QImage::Format_Indexed8);
       
  2427     const int depth = 16;
       
  2428 
       
  2429     const int dst_bytes_per_line = ((data->width * depth + 31) >> 5) << 2;
       
  2430     const int nbytes = dst_bytes_per_line * data->height;
       
  2431     uchar *const newData = (uchar *)realloc(data->data, nbytes);
       
  2432     if (!newData)
       
  2433         return false;
       
  2434 
       
  2435     data->data = newData;
       
  2436 
       
  2437     // start converting from the end because the end image is bigger than the source
       
  2438     uchar *src_data = newData + data->nbytes;
       
  2439     quint16 *dest_data = (quint16 *) (newData + nbytes);
       
  2440     const int width = data->width;
       
  2441     const int src_pad = data->bytes_per_line - width;
       
  2442     const int dest_pad = (dst_bytes_per_line >> 1) - width;
       
  2443 
       
  2444     quint16 colorTableRGB16[256];
       
  2445     if (data->colortable.isEmpty()) {
       
  2446         for (int i = 0; i < 256; ++i)
       
  2447             colorTableRGB16[i] = qt_colorConvert<quint16, quint32>(qRgb(i, i, i), 0);
       
  2448     } else {
       
  2449         // 1) convert the existing colors to RGB16
       
  2450         const int tableSize = data->colortable.size();
       
  2451         for (int i = 0; i < tableSize; ++i)
       
  2452             colorTableRGB16[i] = qt_colorConvert<quint16, quint32>(data->colortable.at(i), 0);
       
  2453         data->colortable = QVector<QRgb>();
       
  2454 
       
  2455         // 2) fill the rest of the table in case src_data > colortable.size()
       
  2456         const quint16 lastColor = colorTableRGB16[tableSize - 1];
       
  2457         for (int i = tableSize; i < 256; ++i)
       
  2458             colorTableRGB16[i] = lastColor;
       
  2459     }
       
  2460 
       
  2461     for (int i = 0; i < data->height; ++i) {
       
  2462         src_data -= src_pad;
       
  2463         dest_data -= dest_pad;
       
  2464         for (int pixI = 0; pixI < width; ++pixI) {
       
  2465             --src_data;
       
  2466             --dest_data;
       
  2467             *dest_data = colorTableRGB16[*src_data];
       
  2468         }
       
  2469     }
       
  2470 
       
  2471     data->format = QImage::Format_RGB16;
       
  2472     data->bytes_per_line = dst_bytes_per_line;
       
  2473     data->depth = depth;
       
  2474     data->nbytes = nbytes;
       
  2475 
       
  2476     return true;
       
  2477 }
       
  2478 
       
  2479 static bool convert_RGB_to_RGB16_inplace(QImageData *data, Qt::ImageConversionFlags)
       
  2480 {
       
  2481     Q_ASSERT(data->format == QImage::Format_RGB32);
       
  2482     const int depth = 16;
       
  2483 
       
  2484     const int dst_bytes_per_line = ((data->width * depth + 31) >> 5) << 2;
       
  2485     const int src_bytes_per_line = data->bytes_per_line;
       
  2486     quint32 *src_data = (quint32 *) data->data;
       
  2487     quint16 *dst_data = (quint16 *) data->data;
       
  2488 
       
  2489     for (int i = 0; i < data->height; ++i) {
       
  2490         qt_memconvert(dst_data, src_data, data->width);
       
  2491         src_data = (quint32 *) (((char*)src_data) + src_bytes_per_line);
       
  2492         dst_data = (quint16 *) (((char*)dst_data) + dst_bytes_per_line);
       
  2493     }
       
  2494     data->format = QImage::Format_RGB16;
       
  2495     data->bytes_per_line = dst_bytes_per_line;
       
  2496     data->depth = depth;
       
  2497     data->nbytes = dst_bytes_per_line * data->height;
       
  2498     uchar *const newData = (uchar *)realloc(data->data, data->nbytes);
       
  2499     if (newData) {
       
  2500         data->data = newData;
       
  2501         return true;
       
  2502     } else {
       
  2503         return false;
  2296     }
  2504     }
  2297 }
  2505 }
  2298 
  2506 
  2299 static void convert_ARGB_PM_to_ARGB(QImageData *dest, const QImageData *src, Qt::ImageConversionFlags)
  2507 static void convert_ARGB_PM_to_ARGB(QImageData *dest, const QImageData *src, Qt::ImageConversionFlags)
  2300 {
  2508 {
  3443         0,
  3651         0,
  3444         0
  3652         0
  3445     } // Format_ARGB4444_Premultiplied
  3653     } // Format_ARGB4444_Premultiplied
  3446 };
  3654 };
  3447 
  3655 
       
  3656 static InPlace_Image_Converter inplace_converter_map[QImage::NImageFormats][QImage::NImageFormats] =
       
  3657 {
       
  3658     {
       
  3659         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
       
  3660     },
       
  3661     {
       
  3662         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
       
  3663     }, // Format_Mono
       
  3664     {
       
  3665        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
       
  3666     }, // Format_MonoLSB
       
  3667     {
       
  3668         0,
       
  3669         0,
       
  3670         0,
       
  3671         0,
       
  3672         0,
       
  3673         convert_indexed8_to_RGB_inplace,
       
  3674         convert_indexed8_to_ARGB_PM_inplace,
       
  3675         convert_indexed8_to_RGB16_inplace,
       
  3676         0,
       
  3677         0,
       
  3678         0,
       
  3679         0,
       
  3680         0,
       
  3681         0,
       
  3682         0,
       
  3683         0,
       
  3684     }, // Format_Indexed8
       
  3685     {
       
  3686         0,
       
  3687         0,
       
  3688         0,
       
  3689         0,
       
  3690         0,
       
  3691         0,
       
  3692         0,
       
  3693         convert_RGB_to_RGB16_inplace,
       
  3694         0,
       
  3695         0,
       
  3696         0,
       
  3697         0,
       
  3698         0,
       
  3699         0,
       
  3700         0,
       
  3701         0,
       
  3702     }, // Format_ARGB32
       
  3703     {
       
  3704         0,
       
  3705         0,
       
  3706         0,
       
  3707         0,
       
  3708         0,
       
  3709         0,
       
  3710         convert_ARGB_to_ARGB_PM_inplace,
       
  3711         0,
       
  3712         0,
       
  3713         0,
       
  3714         0,
       
  3715         0,
       
  3716         0,
       
  3717         0,
       
  3718         0,
       
  3719         0,
       
  3720     }, // Format_ARGB32
       
  3721     {
       
  3722         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
       
  3723     },  // Format_ARGB32_Premultiplied
       
  3724     {
       
  3725         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
       
  3726     }, // Format_RGB16
       
  3727     {
       
  3728         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
       
  3729     }, // Format_ARGB8565_Premultiplied
       
  3730     {
       
  3731         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
       
  3732     }, // Format_RGB666
       
  3733     {
       
  3734         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
       
  3735     }, // Format_ARGB6666_Premultiplied
       
  3736     {
       
  3737         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
       
  3738     }, // Format_RGB555
       
  3739     {
       
  3740         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
       
  3741     }, // Format_ARGB8555_Premultiplied
       
  3742     {
       
  3743         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
       
  3744     }, // Format_RGB888
       
  3745     {
       
  3746         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
       
  3747     }, // Format_RGB444
       
  3748     {
       
  3749         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
       
  3750     } // Format_ARGB4444_Premultiplied
       
  3751 };
       
  3752 
       
  3753 void qInitImageConversions()
       
  3754 {
       
  3755     const uint features = qDetectCPUFeatures();
       
  3756     Q_UNUSED(features);
       
  3757 
       
  3758 #ifdef QT_HAVE_SSE2
       
  3759     if (features & SSE2) {
       
  3760         extern bool convert_ARGB_to_ARGB_PM_inplace_sse2(QImageData *data, Qt::ImageConversionFlags);
       
  3761         inplace_converter_map[QImage::Format_ARGB32][QImage::Format_ARGB32_Premultiplied] = convert_ARGB_to_ARGB_PM_inplace_sse2;
       
  3762     }
       
  3763 #endif
       
  3764 }
       
  3765 
  3448 /*!
  3766 /*!
  3449     Returns a copy of the image in the given \a format.
  3767     Returns a copy of the image in the given \a format.
  3450 
  3768 
  3451     The specified image conversion \a flags control how the image data
  3769     The specified image conversion \a flags control how the image data
  3452     is handled during the conversion process.
  3770     is handled during the conversion process.
  3795             else
  4113             else
  3796                 *(s + (x >> 3)) |= (1 << (7-(x & 7)));
  4114                 *(s + (x >> 3)) |= (1 << (7-(x & 7)));
  3797         }
  4115         }
  3798         break;
  4116         break;
  3799     case Format_Indexed8:
  4117     case Format_Indexed8:
  3800         if (index_or_rgb > (uint)d->colortable.size()) {
  4118         if (index_or_rgb >= (uint)d->colortable.size()) {
  3801             qWarning("QImage::setPixel: Index %d out of range", index_or_rgb);
  4119             qWarning("QImage::setPixel: Index %d out of range", index_or_rgb);
  3802             return;
  4120             return;
  3803         }
  4121         }
  3804         s[x] = index_or_rgb;
  4122         s[x] = index_or_rgb;
  3805         break;
  4123         break;
  4206 #define PIX(x,y)  (*((QRgb*)scanLine(y)+x) & 0x00ffffff)
  4524 #define PIX(x,y)  (*((QRgb*)scanLine(y)+x) & 0x00ffffff)
  4207 
  4525 
  4208     int w = width();
  4526     int w = width();
  4209     int h = height();
  4527     int h = height();
  4210     QImage m(w, h, Format_MonoLSB);
  4528     QImage m(w, h, Format_MonoLSB);
       
  4529     QIMAGE_SANITYCHECK_MEMORY(m);
  4211     m.setColorCount(2);
  4530     m.setColorCount(2);
  4212     m.setColor(0, QColor(Qt::color0).rgba());
  4531     m.setColor(0, QColor(Qt::color0).rgba());
  4213     m.setColor(1, QColor(Qt::color1).rgba());
  4532     m.setColor(1, QColor(Qt::color1).rgba());
  4214     m.fill(0xff);
  4533     m.fill(0xff);
  4215 
  4534 
  4298 QImage QImage::createMaskFromColor(QRgb color, Qt::MaskMode mode) const
  4617 QImage QImage::createMaskFromColor(QRgb color, Qt::MaskMode mode) const
  4299 {
  4618 {
  4300     if (!d)
  4619     if (!d)
  4301         return QImage();
  4620         return QImage();
  4302     QImage maskImage(size(), QImage::Format_MonoLSB);
  4621     QImage maskImage(size(), QImage::Format_MonoLSB);
       
  4622     QIMAGE_SANITYCHECK_MEMORY(maskImage);
  4303     maskImage.fill(0);
  4623     maskImage.fill(0);
  4304     uchar *s = maskImage.bits();
  4624     uchar *s = maskImage.bits();
  4305 
  4625 
  4306     if (depth() == 32) {
  4626     if (depth() == 32) {
  4307         for (int h = 0; h < d->height; h++) {
  4627         for (int h = 0; h < d->height; h++) {
  4358 
  4678 
  4359     int w = d->width;
  4679     int w = d->width;
  4360     int h = d->height;
  4680     int h = d->height;
  4361     // Create result image, copy colormap
  4681     // Create result image, copy colormap
  4362     QImage result(d->width, d->height, d->format);
  4682     QImage result(d->width, d->height, d->format);
       
  4683     QIMAGE_SANITYCHECK_MEMORY(result);
  4363 
  4684 
  4364     // check if we ran out of of memory..
  4685     // check if we ran out of of memory..
  4365     if (!result.d)
  4686     if (!result.d)
  4366         return QImage();
  4687         return QImage();
  4367 
  4688 
  4495         break;
  4816         break;
  4496     case Format_RGB32:
  4817     case Format_RGB32:
  4497     case Format_ARGB32:
  4818     case Format_ARGB32:
  4498     case Format_ARGB32_Premultiplied:
  4819     case Format_ARGB32_Premultiplied:
  4499         res = QImage(d->width, d->height, d->format);
  4820         res = QImage(d->width, d->height, d->format);
       
  4821         QIMAGE_SANITYCHECK_MEMORY(res);
  4500         for (int i = 0; i < d->height; i++) {
  4822         for (int i = 0; i < d->height; i++) {
  4501             uint *q = (uint*)res.scanLine(i);
  4823             uint *q = (uint*)res.scanLine(i);
  4502             uint *p = (uint*)scanLine(i);
  4824             uint *p = (uint*)scanLine(i);
  4503             uint *end = p + d->width;
  4825             uint *end = p + d->width;
  4504             while (p < end) {
  4826             while (p < end) {
  4508             }
  4830             }
  4509         }
  4831         }
  4510         break;
  4832         break;
  4511     case Format_RGB16:
  4833     case Format_RGB16:
  4512         res = QImage(d->width, d->height, d->format);
  4834         res = QImage(d->width, d->height, d->format);
       
  4835         QIMAGE_SANITYCHECK_MEMORY(res);
  4513         for (int i = 0; i < d->height; i++) {
  4836         for (int i = 0; i < d->height; i++) {
  4514             ushort *q = (ushort*)res.scanLine(i);
  4837             ushort *q = (ushort*)res.scanLine(i);
  4515             const ushort *p = (const ushort*)scanLine(i);
  4838             const ushort *p = (const ushort*)scanLine(i);
  4516             const ushort *end = p + d->width;
  4839             const ushort *end = p + d->width;
  4517             while (p < end) {
  4840             while (p < end) {
  4521             }
  4844             }
  4522         }
  4845         }
  4523         break;
  4846         break;
  4524     case Format_ARGB8565_Premultiplied:
  4847     case Format_ARGB8565_Premultiplied:
  4525         res = QImage(d->width, d->height, d->format);
  4848         res = QImage(d->width, d->height, d->format);
       
  4849         QIMAGE_SANITYCHECK_MEMORY(res);
  4526         for (int i = 0; i < d->height; i++) {
  4850         for (int i = 0; i < d->height; i++) {
  4527             quint8 *p = (quint8*)scanLine(i);
  4851             quint8 *p = (quint8*)scanLine(i);
  4528             const quint8 *end = p + d->width * sizeof(qargb8565);
  4852             const quint8 *end = p + d->width * sizeof(qargb8565);
  4529             while (p < end) {
  4853             while (p < end) {
  4530                 quint16 *q = reinterpret_cast<quint16*>(p + 1);
  4854                 quint16 *q = reinterpret_cast<quint16*>(p + 1);
  4533             }
  4857             }
  4534         }
  4858         }
  4535         break;
  4859         break;
  4536     case Format_RGB666:
  4860     case Format_RGB666:
  4537         res = QImage(d->width, d->height, d->format);
  4861         res = QImage(d->width, d->height, d->format);
       
  4862         QIMAGE_SANITYCHECK_MEMORY(res);
  4538         for (int i = 0; i < d->height; i++) {
  4863         for (int i = 0; i < d->height; i++) {
  4539             qrgb666 *q = reinterpret_cast<qrgb666*>(res.scanLine(i));
  4864             qrgb666 *q = reinterpret_cast<qrgb666*>(res.scanLine(i));
  4540             const qrgb666 *p = reinterpret_cast<const qrgb666*>(scanLine(i));
  4865             const qrgb666 *p = reinterpret_cast<const qrgb666*>(scanLine(i));
  4541             const qrgb666 *end = p + d->width;
  4866             const qrgb666 *end = p + d->width;
  4542             while (p < end) {
  4867             while (p < end) {
  4545             }
  4870             }
  4546         }
  4871         }
  4547         break;
  4872         break;
  4548     case Format_ARGB6666_Premultiplied:
  4873     case Format_ARGB6666_Premultiplied:
  4549         res = QImage(d->width, d->height, d->format);
  4874         res = QImage(d->width, d->height, d->format);
       
  4875         QIMAGE_SANITYCHECK_MEMORY(res);
  4550         for (int i = 0; i < d->height; i++) {
  4876         for (int i = 0; i < d->height; i++) {
  4551             qargb6666 *q = reinterpret_cast<qargb6666*>(res.scanLine(i));
  4877             qargb6666 *q = reinterpret_cast<qargb6666*>(res.scanLine(i));
  4552             const qargb6666 *p = reinterpret_cast<const qargb6666*>(scanLine(i));
  4878             const qargb6666 *p = reinterpret_cast<const qargb6666*>(scanLine(i));
  4553             const qargb6666 *end = p + d->width;
  4879             const qargb6666 *end = p + d->width;
  4554             while (p < end) {
  4880             while (p < end) {
  4557             }
  4883             }
  4558         }
  4884         }
  4559         break;
  4885         break;
  4560     case Format_RGB555:
  4886     case Format_RGB555:
  4561         res = QImage(d->width, d->height, d->format);
  4887         res = QImage(d->width, d->height, d->format);
       
  4888         QIMAGE_SANITYCHECK_MEMORY(res);
  4562         for (int i = 0; i < d->height; i++) {
  4889         for (int i = 0; i < d->height; i++) {
  4563             ushort *q = (ushort*)res.scanLine(i);
  4890             ushort *q = (ushort*)res.scanLine(i);
  4564             const ushort *p = (const ushort*)scanLine(i);
  4891             const ushort *p = (const ushort*)scanLine(i);
  4565             const ushort *end = p + d->width;
  4892             const ushort *end = p + d->width;
  4566             while (p < end) {
  4893             while (p < end) {
  4570             }
  4897             }
  4571         }
  4898         }
  4572         break;
  4899         break;
  4573     case Format_ARGB8555_Premultiplied:
  4900     case Format_ARGB8555_Premultiplied:
  4574         res = QImage(d->width, d->height, d->format);
  4901         res = QImage(d->width, d->height, d->format);
       
  4902         QIMAGE_SANITYCHECK_MEMORY(res);
  4575         for (int i = 0; i < d->height; i++) {
  4903         for (int i = 0; i < d->height; i++) {
  4576             quint8 *p = (quint8*)scanLine(i);
  4904             quint8 *p = (quint8*)scanLine(i);
  4577             const quint8 *end = p + d->width * sizeof(qargb8555);
  4905             const quint8 *end = p + d->width * sizeof(qargb8555);
  4578             while (p < end) {
  4906             while (p < end) {
  4579                 quint16 *q = reinterpret_cast<quint16*>(p + 1);
  4907                 quint16 *q = reinterpret_cast<quint16*>(p + 1);
  4582             }
  4910             }
  4583         }
  4911         }
  4584         break;
  4912         break;
  4585     case Format_RGB888:
  4913     case Format_RGB888:
  4586         res = QImage(d->width, d->height, d->format);
  4914         res = QImage(d->width, d->height, d->format);
       
  4915         QIMAGE_SANITYCHECK_MEMORY(res);
  4587         for (int i = 0; i < d->height; i++) {
  4916         for (int i = 0; i < d->height; i++) {
  4588             quint8 *q = reinterpret_cast<quint8*>(res.scanLine(i));
  4917             quint8 *q = reinterpret_cast<quint8*>(res.scanLine(i));
  4589             const quint8 *p = reinterpret_cast<const quint8*>(scanLine(i));
  4918             const quint8 *p = reinterpret_cast<const quint8*>(scanLine(i));
  4590             const quint8 *end = p + d->width * sizeof(qrgb888);
  4919             const quint8 *end = p + d->width * sizeof(qrgb888);
  4591             while (p < end) {
  4920             while (p < end) {
  4597             }
  4926             }
  4598         }
  4927         }
  4599         break;
  4928         break;
  4600     case Format_RGB444:
  4929     case Format_RGB444:
  4601         res = QImage(d->width, d->height, d->format);
  4930         res = QImage(d->width, d->height, d->format);
       
  4931         QIMAGE_SANITYCHECK_MEMORY(res);
  4602         for (int i = 0; i < d->height; i++) {
  4932         for (int i = 0; i < d->height; i++) {
  4603             quint8 *q = reinterpret_cast<quint8*>(res.scanLine(i));
  4933             quint8 *q = reinterpret_cast<quint8*>(res.scanLine(i));
  4604             const quint8 *p = reinterpret_cast<const quint8*>(scanLine(i));
  4934             const quint8 *p = reinterpret_cast<const quint8*>(scanLine(i));
  4605             const quint8 *end = p + d->width * sizeof(qrgb444);
  4935             const quint8 *end = p + d->width * sizeof(qrgb444);
  4606             while (p < end) {
  4936             while (p < end) {
  4611             }
  4941             }
  4612         }
  4942         }
  4613         break;
  4943         break;
  4614     case Format_ARGB4444_Premultiplied:
  4944     case Format_ARGB4444_Premultiplied:
  4615         res = QImage(d->width, d->height, d->format);
  4945         res = QImage(d->width, d->height, d->format);
       
  4946         QIMAGE_SANITYCHECK_MEMORY(res);
  4616         for (int i = 0; i < d->height; i++) {
  4947         for (int i = 0; i < d->height; i++) {
  4617             quint8 *q = reinterpret_cast<quint8*>(res.scanLine(i));
  4948             quint8 *q = reinterpret_cast<quint8*>(res.scanLine(i));
  4618             const quint8 *p = reinterpret_cast<const quint8*>(scanLine(i));
  4949             const quint8 *p = reinterpret_cast<const quint8*>(scanLine(i));
  4619             const quint8 *end = p + d->width * sizeof(qargb4444);
  4950             const quint8 *end = p + d->width * sizeof(qargb4444);
  4620             while (p < end) {
  4951             while (p < end) {
  4810 
  5141 
  4811     Writes the given \a image to the given \a stream as a PNG image,
  5142     Writes the given \a image to the given \a stream as a PNG image,
  4812     or as a BMP image if the stream's version is 1. Note that writing
  5143     or as a BMP image if the stream's version is 1. Note that writing
  4813     the stream to a file will not produce a valid image file.
  5144     the stream to a file will not produce a valid image file.
  4814 
  5145 
  4815     \sa QImage::save(), {Format of the QDataStream Operators}
  5146     \sa QImage::save(), {Serializing Qt Data Types}
  4816 */
  5147 */
  4817 
  5148 
  4818 QDataStream &operator<<(QDataStream &s, const QImage &image)
  5149 QDataStream &operator<<(QDataStream &s, const QImage &image)
  4819 {
  5150 {
  4820     if (s.version() >= 5) {
  5151     if (s.version() >= 5) {
  4836     \relates QImage
  5167     \relates QImage
  4837 
  5168 
  4838     Reads an image from the given \a stream and stores it in the given
  5169     Reads an image from the given \a stream and stores it in the given
  4839     \a image.
  5170     \a image.
  4840 
  5171 
  4841     \sa QImage::load(), {Format of the QDataStream Operators}
  5172     \sa QImage::load(), {Serializing Qt Data Types}
  4842 */
  5173 */
  4843 
  5174 
  4844 QDataStream &operator>>(QDataStream &s, QImage &image)
  5175 QDataStream &operator>>(QDataStream &s, QImage &image)
  4845 {
  5176 {
  4846     if (s.version() >= 5) {
  5177     if (s.version() >= 5) {
  6259     const QRect mapped = matrix.mapRect(rect).toAlignedRect();
  6590     const QRect mapped = matrix.mapRect(rect).toAlignedRect();
  6260     const QPoint delta = mapped.topLeft();
  6591     const QPoint delta = mapped.topLeft();
  6261     return matrix * QTransform().translate(-delta.x(), -delta.y());
  6592     return matrix * QTransform().translate(-delta.x(), -delta.y());
  6262 }
  6593 }
  6263 
  6594 
       
  6595 bool QImageData::convertInPlace(QImage::Format newFormat, Qt::ImageConversionFlags flags)
       
  6596 {
       
  6597     if (format == newFormat)
       
  6598         return true;
       
  6599 
       
  6600     const InPlace_Image_Converter *const converterPtr = &inplace_converter_map[format][newFormat];
       
  6601     InPlace_Image_Converter converter = *converterPtr;
       
  6602     if (converter)
       
  6603         return converter(this, flags);
       
  6604     else
       
  6605         return false;
       
  6606 }
  6264 
  6607 
  6265 /*!
  6608 /*!
  6266     \typedef QImage::DataPtr
  6609     \typedef QImage::DataPtr
  6267     \internal
  6610     \internal
  6268 */
  6611 */