Changeset 846 for trunk/src/gui/image/qimage.cpp
- Timestamp:
- May 5, 2011, 5:36:53 AM (14 years ago)
- Location:
- trunk
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk
- Property svn:mergeinfo changed
/branches/vendor/nokia/qt/4.7.2 (added) merged: 845 /branches/vendor/nokia/qt/current merged: 844 /branches/vendor/nokia/qt/4.6.3 removed
- Property svn:mergeinfo changed
-
trunk/src/gui/image/qimage.cpp
r769 r846 1 1 /**************************************************************************** 2 2 ** 3 ** Copyright (C) 201 0Nokia Corporation and/or its subsidiary(-ies).3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). 4 4 ** All rights reserved. 5 5 ** Contact: Nokia Corporation (qt-info@nokia.com) … … 59 59 #include <private/qpixmapdata_p.h> 60 60 #include <private/qimagescale_p.h> 61 #include <private/qsimd_p.h> 61 62 62 63 #include <qhash.h> … … 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 215 // sanity check for potential overflows … … 273 274 switch (format) { 274 275 276 case QImage::Format_Mono: 277 case QImage::Format_MonoLSB: 275 278 case QImage::Format_Indexed8: 276 279 has_alpha_pixels = has_alpha_clut; … … 481 484 \o Low-level information 482 485 \o 486 483 487 The depth() function returns the depth of the image. The supported 484 depths are 1 (monochrome), 8 and 32 (for more information see the 485 \l {QImage#Image Formats}{Image Formats} section). 488 depths are 1 (monochrome), 8, 16, 24 and 32 bits. The 489 bitPlaneCount() function tells how many of those bits that are 490 used. For more information see the 491 \l {QImage#Image Formats}{Image Formats} section. 486 492 487 493 The format(), bytesPerLine(), and byteCount() functions provide … … 708 714 709 715 \value Format_Indexed8 The image is stored using 8-bit indexes 710 into a colormap. 716 into a colormap. 711 717 712 718 \value Format_RGB32 The image is stored using a 32-bit RGB format (0xffRRGGBB). … … 1116 1122 : QPaintDevice() 1117 1123 { 1118 d = image.d; 1119 if (d) 1120 d->ref.ref(); 1124 if (image.paintingActive()) { 1125 d = 0; 1126 operator=(image.copy()); 1127 } else { 1128 d = image.d; 1129 if (d) 1130 d->ref.ref(); 1131 } 1121 1132 } 1122 1133 … … 1315 1326 QImage &QImage::operator=(const QImage &image) 1316 1327 { 1317 if (image.d) 1318 image.d->ref.ref(); 1319 if (d && !d->ref.deref()) 1320 delete d; 1321 d = image.d; 1328 if (image.paintingActive()) { 1329 operator=(image.copy()); 1330 } else { 1331 if (image.d) 1332 image.d->ref.ref(); 1333 if (d && !d->ref.deref()) 1334 delete d; 1335 d = image.d; 1336 } 1322 1337 return *this; 1323 1338 } … … 1581 1596 Returns the depth of the image. 1582 1597 1583 The image depth is the number of bits used to encode a single1598 The image depth is the number of bits used to store a single 1584 1599 pixel, also called bits per pixel (bpp). 1585 1600 1586 1601 The supported depths are 1, 8, 16, 24 and 32. 1587 1602 1588 \sa convertToFormat(), {QImage#Image Formats}{Image Formats},1603 \sa bitPlaneCount(), convertToFormat(), {QImage#Image Formats}{Image Formats}, 1589 1604 {QImage#Image Information}{Image Information} 1590 1605 … … 1836 1851 1837 1852 \sa bytesPerLine(), bits(), {QImage#Pixel Manipulation}{Pixel 1838 Manipulation} 1853 Manipulation}, constScanLine() 1839 1854 */ 1840 1855 uchar *QImage::scanLine(int i) … … 1864 1879 } 1865 1880 1881 1882 /*! 1883 Returns a pointer to the pixel data at the scanline with index \a 1884 i. The first scanline is at index 0. 1885 1886 The scanline data is aligned on a 32-bit boundary. 1887 1888 Note that QImage uses \l{Implicit Data Sharing} {implicit data 1889 sharing}, but this function does \e not perform a deep copy of the 1890 shared pixel data, because the returned data is const. 1891 1892 \sa scanLine(), constBits() 1893 \since 4.7 1894 */ 1895 const uchar *QImage::constScanLine(int i) const 1896 { 1897 if (!d) 1898 return 0; 1899 1900 Q_ASSERT(i >= 0 && i < height()); 1901 return d->data + i * d->bytes_per_line; 1902 } 1866 1903 1867 1904 /*! … … 1874 1911 current return value. 1875 1912 1876 \sa scanLine(), byteCount() 1913 \sa scanLine(), byteCount(), constBits() 1877 1914 */ 1878 1915 uchar *QImage::bits() … … 1902 1939 1903 1940 1941 /*! 1942 Returns a pointer to the first pixel data. 1943 1944 Note that QImage uses \l{Implicit Data Sharing} {implicit data 1945 sharing}, but this function does \e not perform a deep copy of the 1946 shared pixel data, because the returned data is const. 1947 1948 \sa bits(), constScanLine() 1949 \since 4.7 1950 */ 1951 const uchar *QImage::constBits() const 1952 { 1953 return d ? d->data : 0; 1954 } 1904 1955 1905 1956 /*! … … 2234 2285 typedef void (*Image_Converter)(QImageData *dest, const QImageData *src, Qt::ImageConversionFlags); 2235 2286 2287 typedef bool (*InPlace_Image_Converter)(QImageData *data, Qt::ImageConversionFlags); 2288 2236 2289 static void convert_ARGB_to_ARGB_PM(QImageData *dest, const QImageData *src, Qt::ImageConversionFlags) 2237 2290 { … … 2255 2308 src_data += src_pad; 2256 2309 dest_data += dest_pad; 2310 } 2311 } 2312 2313 static bool convert_ARGB_to_ARGB_PM_inplace(QImageData *data, Qt::ImageConversionFlags) 2314 { 2315 Q_ASSERT(data->format == QImage::Format_ARGB32); 2316 2317 const int pad = (data->bytes_per_line >> 2) - data->width; 2318 QRgb *rgb_data = (QRgb *) data->data; 2319 2320 for (int i = 0; i < data->height; ++i) { 2321 const QRgb *end = rgb_data + data->width; 2322 while (rgb_data < end) { 2323 *rgb_data = PREMUL(*rgb_data); 2324 ++rgb_data; 2325 } 2326 rgb_data += pad; 2327 } 2328 data->format = QImage::Format_ARGB32_Premultiplied; 2329 return true; 2330 } 2331 2332 static bool convert_indexed8_to_ARGB_PM_inplace(QImageData *data, Qt::ImageConversionFlags) 2333 { 2334 Q_ASSERT(data->format == QImage::Format_Indexed8); 2335 const int depth = 32; 2336 2337 const int dst_bytes_per_line = ((data->width * depth + 31) >> 5) << 2; 2338 const int nbytes = dst_bytes_per_line * data->height; 2339 uchar *const newData = (uchar *)realloc(data->data, nbytes); 2340 if (!newData) 2341 return false; 2342 2343 data->data = newData; 2344 2345 // start converting from the end because the end image is bigger than the source 2346 uchar *src_data = newData + data->nbytes; // end of src 2347 quint32 *dest_data = (quint32 *) (newData + nbytes); // end of dest > end of src 2348 const int width = data->width; 2349 const int src_pad = data->bytes_per_line - width; 2350 const int dest_pad = (dst_bytes_per_line >> 2) - width; 2351 if (data->colortable.size() == 0) { 2352 data->colortable.resize(256); 2353 for (int i = 0; i < 256; ++i) 2354 data->colortable[i] = qRgb(i, i, i); 2355 } else { 2356 for (int i = 0; i < data->colortable.size(); ++i) 2357 data->colortable[i] = PREMUL(data->colortable.at(i)); 2358 2359 // Fill the rest of the table in case src_data > colortable.size() 2360 const int oldSize = data->colortable.size(); 2361 const QRgb lastColor = data->colortable.at(oldSize - 1); 2362 data->colortable.insert(oldSize, 256 - oldSize, lastColor); 2363 } 2364 2365 for (int i = 0; i < data->height; ++i) { 2366 src_data -= src_pad; 2367 dest_data -= dest_pad; 2368 for (int pixI = 0; pixI < width; ++pixI) { 2369 --src_data; 2370 --dest_data; 2371 *dest_data = data->colortable.at(*src_data); 2372 } 2373 } 2374 2375 data->colortable = QVector<QRgb>(); 2376 data->format = QImage::Format_ARGB32_Premultiplied; 2377 data->bytes_per_line = dst_bytes_per_line; 2378 data->depth = depth; 2379 data->nbytes = nbytes; 2380 2381 return true; 2382 } 2383 2384 static bool convert_indexed8_to_RGB_inplace(QImageData *data, Qt::ImageConversionFlags) 2385 { 2386 Q_ASSERT(data->format == QImage::Format_Indexed8); 2387 const int depth = 32; 2388 2389 const int dst_bytes_per_line = ((data->width * depth + 31) >> 5) << 2; 2390 const int nbytes = dst_bytes_per_line * data->height; 2391 uchar *const newData = (uchar *)realloc(data->data, nbytes); 2392 if (!newData) 2393 return false; 2394 2395 data->data = newData; 2396 2397 // start converting from the end because the end image is bigger than the source 2398 uchar *src_data = newData + data->nbytes; 2399 quint32 *dest_data = (quint32 *) (newData + nbytes); 2400 const int width = data->width; 2401 const int src_pad = data->bytes_per_line - width; 2402 const int dest_pad = (dst_bytes_per_line >> 2) - width; 2403 if (data->colortable.size() == 0) { 2404 data->colortable.resize(256); 2405 for (int i = 0; i < 256; ++i) 2406 data->colortable[i] = qRgb(i, i, i); 2407 } else { 2408 // Fill the rest of the table in case src_data > colortable.size() 2409 const int oldSize = data->colortable.size(); 2410 const QRgb lastColor = data->colortable.at(oldSize - 1); 2411 data->colortable.insert(oldSize, 256 - oldSize, lastColor); 2412 } 2413 2414 for (int i = 0; i < data->height; ++i) { 2415 src_data -= src_pad; 2416 dest_data -= dest_pad; 2417 for (int pixI = 0; pixI < width; ++pixI) { 2418 --src_data; 2419 --dest_data; 2420 *dest_data = (quint32) data->colortable.at(*src_data); 2421 } 2422 } 2423 2424 data->colortable = QVector<QRgb>(); 2425 data->format = QImage::Format_RGB32; 2426 data->bytes_per_line = dst_bytes_per_line; 2427 data->depth = depth; 2428 data->nbytes = nbytes; 2429 2430 return true; 2431 } 2432 2433 static bool convert_indexed8_to_RGB16_inplace(QImageData *data, Qt::ImageConversionFlags) 2434 { 2435 Q_ASSERT(data->format == QImage::Format_Indexed8); 2436 const int depth = 16; 2437 2438 const int dst_bytes_per_line = ((data->width * depth + 31) >> 5) << 2; 2439 const int nbytes = dst_bytes_per_line * data->height; 2440 uchar *const newData = (uchar *)realloc(data->data, nbytes); 2441 if (!newData) 2442 return false; 2443 2444 data->data = newData; 2445 2446 // start converting from the end because the end image is bigger than the source 2447 uchar *src_data = newData + data->nbytes; 2448 quint16 *dest_data = (quint16 *) (newData + nbytes); 2449 const int width = data->width; 2450 const int src_pad = data->bytes_per_line - width; 2451 const int dest_pad = (dst_bytes_per_line >> 1) - width; 2452 2453 quint16 colorTableRGB16[256]; 2454 if (data->colortable.isEmpty()) { 2455 for (int i = 0; i < 256; ++i) 2456 colorTableRGB16[i] = qt_colorConvert<quint16, quint32>(qRgb(i, i, i), 0); 2457 } else { 2458 // 1) convert the existing colors to RGB16 2459 const int tableSize = data->colortable.size(); 2460 for (int i = 0; i < tableSize; ++i) 2461 colorTableRGB16[i] = qt_colorConvert<quint16, quint32>(data->colortable.at(i), 0); 2462 data->colortable = QVector<QRgb>(); 2463 2464 // 2) fill the rest of the table in case src_data > colortable.size() 2465 const quint16 lastColor = colorTableRGB16[tableSize - 1]; 2466 for (int i = tableSize; i < 256; ++i) 2467 colorTableRGB16[i] = lastColor; 2468 } 2469 2470 for (int i = 0; i < data->height; ++i) { 2471 src_data -= src_pad; 2472 dest_data -= dest_pad; 2473 for (int pixI = 0; pixI < width; ++pixI) { 2474 --src_data; 2475 --dest_data; 2476 *dest_data = colorTableRGB16[*src_data]; 2477 } 2478 } 2479 2480 data->format = QImage::Format_RGB16; 2481 data->bytes_per_line = dst_bytes_per_line; 2482 data->depth = depth; 2483 data->nbytes = nbytes; 2484 2485 return true; 2486 } 2487 2488 static bool convert_RGB_to_RGB16_inplace(QImageData *data, Qt::ImageConversionFlags) 2489 { 2490 Q_ASSERT(data->format == QImage::Format_RGB32); 2491 const int depth = 16; 2492 2493 const int dst_bytes_per_line = ((data->width * depth + 31) >> 5) << 2; 2494 const int src_bytes_per_line = data->bytes_per_line; 2495 quint32 *src_data = (quint32 *) data->data; 2496 quint16 *dst_data = (quint16 *) data->data; 2497 2498 for (int i = 0; i < data->height; ++i) { 2499 qt_memconvert(dst_data, src_data, data->width); 2500 src_data = (quint32 *) (((char*)src_data) + src_bytes_per_line); 2501 dst_data = (quint16 *) (((char*)dst_data) + dst_bytes_per_line); 2502 } 2503 data->format = QImage::Format_RGB16; 2504 data->bytes_per_line = dst_bytes_per_line; 2505 data->depth = depth; 2506 data->nbytes = dst_bytes_per_line * data->height; 2507 uchar *const newData = (uchar *)realloc(data->data, data->nbytes); 2508 if (newData) { 2509 data->data = newData; 2510 return true; 2511 } else { 2512 return false; 2257 2513 } 2258 2514 } … … 2950 3206 for (int i=0; i<256; ++i) 2951 3207 colorTable[i] = qRgb(i, i, i); 2952 2953 3208 } 2954 3209 … … 2956 3211 const uchar *src_data = src->data; 2957 3212 uchar *dest_data = dest->data; 3213 int tableSize = colorTable.size() - 1; 2958 3214 for (int y = 0; y < src->height; y++) { 2959 3215 uint *p = (uint *)dest_data; … … 2962 3218 2963 3219 while (p < end) 2964 *p++ = colorTable.at( *b++);3220 *p++ = colorTable.at(qMin<int>(tableSize, *b++)); 2965 3221 2966 3222 src_data += src->bytes_per_line; … … 3108 3364 3109 3365 // first index source, second dest 3110 static constImage_Converter converter_map[QImage::NImageFormats][QImage::NImageFormats] =3366 static Image_Converter converter_map[QImage::NImageFormats][QImage::NImageFormats] = 3111 3367 { 3112 3368 { … … 3406 3662 } // Format_ARGB4444_Premultiplied 3407 3663 }; 3664 3665 static InPlace_Image_Converter inplace_converter_map[QImage::NImageFormats][QImage::NImageFormats] = 3666 { 3667 { 3668 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 3669 }, 3670 { 3671 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 3672 }, // Format_Mono 3673 { 3674 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 3675 }, // Format_MonoLSB 3676 { 3677 0, 3678 0, 3679 0, 3680 0, 3681 0, 3682 convert_indexed8_to_RGB_inplace, 3683 convert_indexed8_to_ARGB_PM_inplace, 3684 convert_indexed8_to_RGB16_inplace, 3685 0, 3686 0, 3687 0, 3688 0, 3689 0, 3690 0, 3691 0, 3692 0, 3693 }, // Format_Indexed8 3694 { 3695 0, 3696 0, 3697 0, 3698 0, 3699 0, 3700 0, 3701 0, 3702 convert_RGB_to_RGB16_inplace, 3703 0, 3704 0, 3705 0, 3706 0, 3707 0, 3708 0, 3709 0, 3710 0, 3711 }, // Format_ARGB32 3712 { 3713 0, 3714 0, 3715 0, 3716 0, 3717 0, 3718 0, 3719 convert_ARGB_to_ARGB_PM_inplace, 3720 0, 3721 0, 3722 0, 3723 0, 3724 0, 3725 0, 3726 0, 3727 0, 3728 0, 3729 }, // Format_ARGB32 3730 { 3731 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 3732 }, // Format_ARGB32_Premultiplied 3733 { 3734 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 3735 }, // Format_RGB16 3736 { 3737 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 3738 }, // Format_ARGB8565_Premultiplied 3739 { 3740 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 3741 }, // Format_RGB666 3742 { 3743 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 3744 }, // Format_ARGB6666_Premultiplied 3745 { 3746 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 3747 }, // Format_RGB555 3748 { 3749 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 3750 }, // Format_ARGB8555_Premultiplied 3751 { 3752 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 3753 }, // Format_RGB888 3754 { 3755 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 3756 }, // Format_RGB444 3757 { 3758 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 3759 } // Format_ARGB4444_Premultiplied 3760 }; 3761 3762 void qInitImageConversions() 3763 { 3764 const uint features = qDetectCPUFeatures(); 3765 Q_UNUSED(features); 3766 3767 #ifdef QT_HAVE_SSE2 3768 if (features & SSE2) { 3769 extern bool convert_ARGB_to_ARGB_PM_inplace_sse2(QImageData *data, Qt::ImageConversionFlags); 3770 inplace_converter_map[QImage::Format_ARGB32][QImage::Format_ARGB32_Premultiplied] = convert_ARGB_to_ARGB_PM_inplace_sse2; 3771 } 3772 #endif 3773 #ifdef QT_HAVE_SSSE3 3774 if (features & SSSE3) { 3775 extern void convert_RGB888_to_RGB32_ssse3(QImageData *dest, const QImageData *src, Qt::ImageConversionFlags); 3776 converter_map[QImage::Format_RGB888][QImage::Format_RGB32] = convert_RGB888_to_RGB32_ssse3; 3777 converter_map[QImage::Format_RGB888][QImage::Format_ARGB32] = convert_RGB888_to_RGB32_ssse3; 3778 converter_map[QImage::Format_RGB888][QImage::Format_ARGB32_Premultiplied] = convert_RGB888_to_RGB32_ssse3; 3779 } 3780 #endif 3781 #ifdef QT_HAVE_NEON 3782 if (features & NEON) { 3783 extern void convert_RGB888_to_RGB32_neon(QImageData *dest, const QImageData *src, Qt::ImageConversionFlags); 3784 converter_map[QImage::Format_RGB888][QImage::Format_RGB32] = convert_RGB888_to_RGB32_neon; 3785 converter_map[QImage::Format_RGB888][QImage::Format_ARGB32] = convert_RGB888_to_RGB32_neon; 3786 converter_map[QImage::Format_RGB888][QImage::Format_ARGB32_Premultiplied] = convert_RGB888_to_RGB32_neon; 3787 } 3788 #endif 3789 } 3408 3790 3409 3791 /*! … … 3759 4141 break; 3760 4142 case Format_Indexed8: 3761 if (index_or_rgb > (uint)d->colortable.size()) {4143 if (index_or_rgb >= (uint)d->colortable.size()) { 3762 4144 qWarning("QImage::setPixel: Index %d out of range", index_or_rgb); 3763 4145 return; … … 4170 4552 int h = height(); 4171 4553 QImage m(w, h, Format_MonoLSB); 4554 QIMAGE_SANITYCHECK_MEMORY(m); 4172 4555 m.setColorCount(2); 4173 4556 m.setColor(0, QColor(Qt::color0).rgba()); … … 4262 4645 return QImage(); 4263 4646 QImage maskImage(size(), QImage::Format_MonoLSB); 4647 QIMAGE_SANITYCHECK_MEMORY(maskImage); 4264 4648 maskImage.fill(0); 4265 4649 uchar *s = maskImage.bits(); … … 4322 4706 // Create result image, copy colormap 4323 4707 QImage result(d->width, d->height, d->format); 4708 QIMAGE_SANITYCHECK_MEMORY(result); 4324 4709 4325 4710 // check if we ran out of of memory.. … … 4459 4844 case Format_ARGB32_Premultiplied: 4460 4845 res = QImage(d->width, d->height, d->format); 4846 QIMAGE_SANITYCHECK_MEMORY(res); 4461 4847 for (int i = 0; i < d->height; i++) { 4462 4848 uint *q = (uint*)res.scanLine(i); 4463 uint *p = (uint*) scanLine(i);4849 uint *p = (uint*)constScanLine(i); 4464 4850 uint *end = p + d->width; 4465 4851 while (p < end) { … … 4472 4858 case Format_RGB16: 4473 4859 res = QImage(d->width, d->height, d->format); 4860 QIMAGE_SANITYCHECK_MEMORY(res); 4474 4861 for (int i = 0; i < d->height; i++) { 4475 4862 ushort *q = (ushort*)res.scanLine(i); 4476 const ushort *p = (const ushort*) scanLine(i);4863 const ushort *p = (const ushort*)constScanLine(i); 4477 4864 const ushort *end = p + d->width; 4478 4865 while (p < end) { … … 4485 4872 case Format_ARGB8565_Premultiplied: 4486 4873 res = QImage(d->width, d->height, d->format); 4874 QIMAGE_SANITYCHECK_MEMORY(res); 4487 4875 for (int i = 0; i < d->height; i++) { 4488 quint8 *p = (quint8*)scanLine(i); 4876 const quint8 *p = constScanLine(i); 4877 quint8 *q = res.scanLine(i); 4489 4878 const quint8 *end = p + d->width * sizeof(qargb8565); 4490 4879 while (p < end) { 4491 quint16 *q = reinterpret_cast<quint16*>(p + 1); 4492 *q = ((*q << 11) & 0xf800) | ((*q >> 11) & 0x1f) | (*q & 0x07e0); 4880 q[0] = p[0]; 4881 q[1] = (p[1] & 0xe0) | (p[2] >> 3); 4882 q[2] = (p[2] & 0x07) | (p[1] << 3); 4493 4883 p += sizeof(qargb8565); 4884 q += sizeof(qargb8565); 4494 4885 } 4495 4886 } … … 4497 4888 case Format_RGB666: 4498 4889 res = QImage(d->width, d->height, d->format); 4890 QIMAGE_SANITYCHECK_MEMORY(res); 4499 4891 for (int i = 0; i < d->height; i++) { 4500 4892 qrgb666 *q = reinterpret_cast<qrgb666*>(res.scanLine(i)); 4501 const qrgb666 *p = reinterpret_cast<const qrgb666*>( scanLine(i));4893 const qrgb666 *p = reinterpret_cast<const qrgb666*>(constScanLine(i)); 4502 4894 const qrgb666 *end = p + d->width; 4503 4895 while (p < end) { … … 4509 4901 case Format_ARGB6666_Premultiplied: 4510 4902 res = QImage(d->width, d->height, d->format); 4903 QIMAGE_SANITYCHECK_MEMORY(res); 4511 4904 for (int i = 0; i < d->height; i++) { 4512 qargb6666 *q = reinterpret_cast<qargb6666*>(res.scanLine(i));4513 const q argb6666 *p = reinterpret_cast<const qargb6666*>(scanLine(i));4514 const qargb6666 *end = p + d->width;4905 const quint8 *p = constScanLine(i); 4906 const quint8 *end = p + d->width * sizeof(qargb6666); 4907 quint8 *q = res.scanLine(i); 4515 4908 while (p < end) { 4516 const QRgb rgb = quint32(*p++); 4517 *q++ = qRgba(qBlue(rgb), qGreen(rgb), qRed(rgb), qAlpha(rgb)); 4909 q[0] = (p[1] >> 4) | ((p[2] & 0x3) << 4) | (p[0] & 0xc0); 4910 q[1] = (p[1] & 0xf) | (p[0] << 4); 4911 q[2] = (p[2] & 0xfc) | ((p[0] >> 4) & 0x3); 4912 p += sizeof(qargb6666); 4913 q += sizeof(qargb6666); 4518 4914 } 4519 4915 } … … 4521 4917 case Format_RGB555: 4522 4918 res = QImage(d->width, d->height, d->format); 4919 QIMAGE_SANITYCHECK_MEMORY(res); 4523 4920 for (int i = 0; i < d->height; i++) { 4524 ushort *q = (ushort*)res.scanLine(i);4525 const ushort *p = (const ushort*)scanLine(i);4526 const ushort*end = p + d->width;4921 quint16 *q = (quint16*)res.scanLine(i); 4922 const quint16 *p = (const quint16*)constScanLine(i); 4923 const quint16 *end = p + d->width; 4527 4924 while (p < end) { 4528 *q = ((*p << 10) & 0x7 800) | ((*p >> 10) & 0x1f) | (*p & 0x83e0);4925 *q = ((*p << 10) & 0x7c00) | ((*p >> 10) & 0x1f) | (*p & 0x3e0); 4529 4926 p++; 4530 4927 q++; … … 4534 4931 case Format_ARGB8555_Premultiplied: 4535 4932 res = QImage(d->width, d->height, d->format); 4933 QIMAGE_SANITYCHECK_MEMORY(res); 4536 4934 for (int i = 0; i < d->height; i++) { 4537 quint8 *p = (quint8*)scanLine(i); 4935 const quint8 *p = constScanLine(i); 4936 quint8 *q = res.scanLine(i); 4538 4937 const quint8 *end = p + d->width * sizeof(qargb8555); 4539 4938 while (p < end) { 4540 quint16 *q = reinterpret_cast<quint16*>(p + 1); 4541 *q = ((*q << 10) & 0x7800) | ((*q >> 10) & 0x1f) | (*q & 0x83e0); 4939 q[0] = p[0]; 4940 q[1] = (p[1] & 0xe0) | (p[2] >> 2); 4941 q[2] = (p[2] & 0x03) | ((p[1] << 2) & 0x7f); 4542 4942 p += sizeof(qargb8555); 4943 q += sizeof(qargb8555); 4543 4944 } 4544 4945 } … … 4546 4947 case Format_RGB888: 4547 4948 res = QImage(d->width, d->height, d->format); 4949 QIMAGE_SANITYCHECK_MEMORY(res); 4548 4950 for (int i = 0; i < d->height; i++) { 4549 quint8 *q = re interpret_cast<quint8*>(res.scanLine(i));4550 const quint8 *p = reinterpret_cast<const quint8*>(scanLine(i));4951 quint8 *q = res.scanLine(i); 4952 const quint8 *p = constScanLine(i); 4551 4953 const quint8 *end = p + d->width * sizeof(qrgb888); 4552 4954 while (p < end) { … … 4560 4962 break; 4561 4963 case Format_RGB444: 4562 res = QImage(d->width, d->height, d->format);4563 for (int i = 0; i < d->height; i++) {4564 quint8 *q = reinterpret_cast<quint8*>(res.scanLine(i));4565 const quint8 *p = reinterpret_cast<const quint8*>(scanLine(i));4566 const quint8 *end = p + d->width * sizeof(qrgb444);4567 while (p < end) {4568 q[0] = (p[0] & 0xf0) | ((p[1] & 0x0f) << 8);4569 q[1] = ((p[0] & 0x0f) >> 8) | (p[1] & 0xf0);4570 q += sizeof(qrgb444);4571 p += sizeof(qrgb444);4572 }4573 }4574 break;4575 4964 case Format_ARGB4444_Premultiplied: 4576 4965 res = QImage(d->width, d->height, d->format); 4966 QIMAGE_SANITYCHECK_MEMORY(res); 4577 4967 for (int i = 0; i < d->height; i++) { 4578 quint 8 *q = reinterpret_cast<quint8*>(res.scanLine(i));4579 const quint 8 *p = reinterpret_cast<const quint8*>(scanLine(i));4580 const quint 8 *end = p + d->width * sizeof(qargb4444);4968 quint16 *q = reinterpret_cast<quint16*>(res.scanLine(i)); 4969 const quint16 *p = reinterpret_cast<const quint16*>(constScanLine(i)); 4970 const quint16 *end = p + d->width; 4581 4971 while (p < end) { 4582 q[0] = (p[0] & 0xf0) | ((p[1] & 0x0f) << 8); 4583 q[1] = ((p[0] & 0x0f) >> 8) | (p[1] & 0xf0); 4584 q += sizeof(qargb4444); 4585 p += sizeof(qargb4444); 4972 *q = (*p & 0xf0f0) | ((*p & 0x0f) << 8) | ((*p & 0xf00) >> 8); 4973 p++; 4974 q++; 4586 4975 } 4587 4976 } … … 4774 5163 the stream to a file will not produce a valid image file. 4775 5164 4776 \sa QImage::save(), { Format of the QDataStream Operators}5165 \sa QImage::save(), {Serializing Qt Data Types} 4777 5166 */ 4778 5167 … … 4800 5189 \a image. 4801 5190 4802 \sa QImage::load(), { Format of the QDataStream Operators}5191 \sa QImage::load(), {Serializing Qt Data Types} 4803 5192 */ 4804 5193 … … 5666 6055 } 5667 6056 5668 detach(); 5669 5670 QImage converted = convertToFormat(QImage::Format_ARGB32_Premultiplied); 5671 if (!converted.isNull()) 5672 *this = converted; 6057 if (d->format == QImage::Format_ARGB32_Premultiplied) 6058 detach(); 5673 6059 else 6060 *this = convertToFormat(QImage::Format_ARGB32_Premultiplied); 6061 6062 if (isNull()) 5674 6063 return; 5675 6064 … … 5814 6203 || d->format == Format_Mono 5815 6204 || d->format == Format_MonoLSB))); 6205 } 6206 6207 6208 /*! 6209 \since 4.7 6210 Returns the number of bit planes in the image. 6211 6212 The number of bit planes is the number of bits of color and 6213 transparency information for each pixel. This is different from 6214 (i.e. smaller than) the depth when the image format contains 6215 unused bits. 6216 6217 \sa depth(), format(), {QImage#Image Formats}{Image Formats} 6218 */ 6219 int QImage::bitPlaneCount() const 6220 { 6221 if (!d) 6222 return 0; 6223 int bpc = 0; 6224 switch (d->format) { 6225 case QImage::Format_Invalid: 6226 break; 6227 case QImage::Format_RGB32: 6228 bpc = 24; 6229 break; 6230 case QImage::Format_RGB666: 6231 bpc = 18; 6232 break; 6233 case QImage::Format_RGB555: 6234 bpc = 15; 6235 break; 6236 case QImage::Format_ARGB8555_Premultiplied: 6237 bpc = 23; 6238 break; 6239 case QImage::Format_RGB444: 6240 bpc = 12; 6241 break; 6242 default: 6243 bpc = depthForFormat(d->format); 6244 break; 6245 } 6246 return bpc; 5816 6247 } 5817 6248 … … 6181 6612 } 6182 6613 6614 bool QImageData::convertInPlace(QImage::Format newFormat, Qt::ImageConversionFlags flags) 6615 { 6616 if (format == newFormat) 6617 return true; 6618 6619 // No in-place conversion if we have to detach 6620 if (ref > 1) 6621 return false; 6622 6623 const InPlace_Image_Converter *const converterPtr = &inplace_converter_map[format][newFormat]; 6624 InPlace_Image_Converter converter = *converterPtr; 6625 if (converter) 6626 return converter(this, flags); 6627 else 6628 return false; 6629 } 6183 6630 6184 6631 /*!
Note:
See TracChangeset
for help on using the changeset viewer.