Ignore:
Timestamp:
May 5, 2011, 5:36:53 AM (14 years ago)
Author:
Dmitry A. Kuminov
Message:

trunk: Merged in qt 4.7.2 sources from branches/vendor/nokia/qt.

Location:
trunk
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk

  • trunk/src/gui/image/qimage.cpp

    r769 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    5959#include <private/qpixmapdata_p.h>
    6060#include <private/qimagescale_p.h>
     61#include <private/qsimd_p.h>
    6162
    6263#include <qhash.h>
     
    210211    }
    211212
    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)
    213214
    214215    // sanity check for potential overflows
     
    273274    switch (format) {
    274275
     276    case QImage::Format_Mono:
     277    case QImage::Format_MonoLSB:
    275278    case QImage::Format_Indexed8:
    276279        has_alpha_pixels = has_alpha_clut;
     
    481484    \o Low-level information
    482485    \o
     486
    483487    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.
    486492
    487493    The format(), bytesPerLine(), and byteCount() functions provide
     
    708714
    709715    \value Format_Indexed8  The image is stored using 8-bit indexes
    710                             into a colormap. 
     716                            into a colormap.
    711717
    712718    \value Format_RGB32     The image is stored using a 32-bit RGB format (0xffRRGGBB).
     
    11161122    : QPaintDevice()
    11171123{
    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    }
    11211132}
    11221133
     
    13151326QImage &QImage::operator=(const QImage &image)
    13161327{
    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    }
    13221337    return *this;
    13231338}
     
    15811596    Returns the depth of the image.
    15821597
    1583     The image depth is the number of bits used to encode a single
     1598    The image depth is the number of bits used to store a single
    15841599    pixel, also called bits per pixel (bpp).
    15851600
    15861601    The supported depths are 1, 8, 16, 24 and 32.
    15871602
    1588     \sa convertToFormat(), {QImage#Image Formats}{Image Formats},
     1603    \sa bitPlaneCount(), convertToFormat(), {QImage#Image Formats}{Image Formats},
    15891604    {QImage#Image Information}{Image Information}
    15901605
     
    18361851
    18371852    \sa bytesPerLine(), bits(), {QImage#Pixel Manipulation}{Pixel
    1838     Manipulation}
     1853    Manipulation}, constScanLine()
    18391854*/
    18401855uchar *QImage::scanLine(int i)
     
    18641879}
    18651880
     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*/
     1895const 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}
    18661903
    18671904/*!
     
    18741911    current return value.
    18751912
    1876     \sa scanLine(), byteCount()
     1913    \sa scanLine(), byteCount(), constBits()
    18771914*/
    18781915uchar *QImage::bits()
     
    19021939
    19031940
     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*/
     1951const uchar *QImage::constBits() const
     1952{
     1953    return d ? d->data : 0;
     1954}
    19041955
    19051956/*!
     
    22342285typedef void (*Image_Converter)(QImageData *dest, const QImageData *src, Qt::ImageConversionFlags);
    22352286
     2287typedef bool (*InPlace_Image_Converter)(QImageData *data, Qt::ImageConversionFlags);
     2288
    22362289static void convert_ARGB_to_ARGB_PM(QImageData *dest, const QImageData *src, Qt::ImageConversionFlags)
    22372290{
     
    22552308        src_data += src_pad;
    22562309        dest_data += dest_pad;
     2310    }
     2311}
     2312
     2313static 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
     2332static 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
     2384static 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
     2433static 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
     2488static 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;
    22572513    }
    22582514}
     
    29503206        for (int i=0; i<256; ++i)
    29513207            colorTable[i] = qRgb(i, i, i);
    2952 
    29533208    }
    29543209
     
    29563211    const uchar *src_data = src->data;
    29573212    uchar *dest_data = dest->data;
     3213    int tableSize = colorTable.size() - 1;
    29583214    for (int y = 0; y < src->height; y++) {
    29593215        uint *p = (uint *)dest_data;
     
    29623218
    29633219        while (p < end)
    2964             *p++ = colorTable.at(*b++);
     3220            *p++ = colorTable.at(qMin<int>(tableSize, *b++));
    29653221
    29663222        src_data += src->bytes_per_line;
     
    31083364
    31093365// first index source, second dest
    3110 static const Image_Converter converter_map[QImage::NImageFormats][QImage::NImageFormats] =
     3366static Image_Converter converter_map[QImage::NImageFormats][QImage::NImageFormats] =
    31113367{
    31123368    {
     
    34063662    } // Format_ARGB4444_Premultiplied
    34073663};
     3664
     3665static 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
     3762void 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}
    34083790
    34093791/*!
     
    37594141        break;
    37604142    case Format_Indexed8:
    3761         if (index_or_rgb > (uint)d->colortable.size()) {
     4143        if (index_or_rgb >= (uint)d->colortable.size()) {
    37624144            qWarning("QImage::setPixel: Index %d out of range", index_or_rgb);
    37634145            return;
     
    41704552    int h = height();
    41714553    QImage m(w, h, Format_MonoLSB);
     4554    QIMAGE_SANITYCHECK_MEMORY(m);
    41724555    m.setColorCount(2);
    41734556    m.setColor(0, QColor(Qt::color0).rgba());
     
    42624645        return QImage();
    42634646    QImage maskImage(size(), QImage::Format_MonoLSB);
     4647    QIMAGE_SANITYCHECK_MEMORY(maskImage);
    42644648    maskImage.fill(0);
    42654649    uchar *s = maskImage.bits();
     
    43224706    // Create result image, copy colormap
    43234707    QImage result(d->width, d->height, d->format);
     4708    QIMAGE_SANITYCHECK_MEMORY(result);
    43244709
    43254710    // check if we ran out of of memory..
     
    44594844    case Format_ARGB32_Premultiplied:
    44604845        res = QImage(d->width, d->height, d->format);
     4846        QIMAGE_SANITYCHECK_MEMORY(res);
    44614847        for (int i = 0; i < d->height; i++) {
    44624848            uint *q = (uint*)res.scanLine(i);
    4463             uint *p = (uint*)scanLine(i);
     4849            uint *p = (uint*)constScanLine(i);
    44644850            uint *end = p + d->width;
    44654851            while (p < end) {
     
    44724858    case Format_RGB16:
    44734859        res = QImage(d->width, d->height, d->format);
     4860        QIMAGE_SANITYCHECK_MEMORY(res);
    44744861        for (int i = 0; i < d->height; i++) {
    44754862            ushort *q = (ushort*)res.scanLine(i);
    4476             const ushort *p = (const ushort*)scanLine(i);
     4863            const ushort *p = (const ushort*)constScanLine(i);
    44774864            const ushort *end = p + d->width;
    44784865            while (p < end) {
     
    44854872    case Format_ARGB8565_Premultiplied:
    44864873        res = QImage(d->width, d->height, d->format);
     4874        QIMAGE_SANITYCHECK_MEMORY(res);
    44874875        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);
    44894878            const quint8 *end = p + d->width * sizeof(qargb8565);
    44904879            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);
    44934883                p += sizeof(qargb8565);
     4884                q += sizeof(qargb8565);
    44944885            }
    44954886        }
     
    44974888    case Format_RGB666:
    44984889        res = QImage(d->width, d->height, d->format);
     4890        QIMAGE_SANITYCHECK_MEMORY(res);
    44994891        for (int i = 0; i < d->height; i++) {
    45004892            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));
    45024894            const qrgb666 *end = p + d->width;
    45034895            while (p < end) {
     
    45094901    case Format_ARGB6666_Premultiplied:
    45104902        res = QImage(d->width, d->height, d->format);
     4903        QIMAGE_SANITYCHECK_MEMORY(res);
    45114904        for (int i = 0; i < d->height; i++) {
    4512             qargb6666 *q = reinterpret_cast<qargb6666*>(res.scanLine(i));
    4513             const qargb6666 *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);
    45154908            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);
    45184914            }
    45194915        }
     
    45214917    case Format_RGB555:
    45224918        res = QImage(d->width, d->height, d->format);
     4919        QIMAGE_SANITYCHECK_MEMORY(res);
    45234920        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;
    45274924            while (p < end) {
    4528                 *q = ((*p << 10) & 0x7800) | ((*p >> 10) & 0x1f) | (*p & 0x83e0);
     4925                *q = ((*p << 10) & 0x7c00) | ((*p >> 10) & 0x1f) | (*p & 0x3e0);
    45294926                p++;
    45304927                q++;
     
    45344931    case Format_ARGB8555_Premultiplied:
    45354932        res = QImage(d->width, d->height, d->format);
     4933        QIMAGE_SANITYCHECK_MEMORY(res);
    45364934        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);
    45384937            const quint8 *end = p + d->width * sizeof(qargb8555);
    45394938            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);
    45424942                p += sizeof(qargb8555);
     4943                q += sizeof(qargb8555);
    45434944            }
    45444945        }
     
    45464947    case Format_RGB888:
    45474948        res = QImage(d->width, d->height, d->format);
     4949        QIMAGE_SANITYCHECK_MEMORY(res);
    45484950        for (int i = 0; i < d->height; i++) {
    4549             quint8 *q = reinterpret_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);
    45514953            const quint8 *end = p + d->width * sizeof(qrgb888);
    45524954            while (p < end) {
     
    45604962        break;
    45614963    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;
    45754964    case Format_ARGB4444_Premultiplied:
    45764965        res = QImage(d->width, d->height, d->format);
     4966        QIMAGE_SANITYCHECK_MEMORY(res);
    45774967        for (int i = 0; i < d->height; i++) {
    4578             quint8 *q = reinterpret_cast<quint8*>(res.scanLine(i));
    4579             const quint8 *p = reinterpret_cast<const quint8*>(scanLine(i));
    4580             const quint8 *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;
    45814971            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++;
    45864975            }
    45874976        }
     
    47745163    the stream to a file will not produce a valid image file.
    47755164
    4776     \sa QImage::save(), {Format of the QDataStream Operators}
     5165    \sa QImage::save(), {Serializing Qt Data Types}
    47775166*/
    47785167
     
    48005189    \a image.
    48015190
    4802     \sa QImage::load(), {Format of the QDataStream Operators}
     5191    \sa QImage::load(), {Serializing Qt Data Types}
    48035192*/
    48045193
     
    56666055    }
    56676056
    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();
    56736059    else
     6060        *this = convertToFormat(QImage::Format_ARGB32_Premultiplied);
     6061
     6062    if (isNull())
    56746063        return;
    56756064
     
    58146203                                           || d->format == Format_Mono
    58156204                                           || 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*/
     6219int 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;
    58166247}
    58176248
     
    61816612}
    61826613
     6614bool 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}
    61836630
    61846631/*!
Note: See TracChangeset for help on using the changeset viewer.