From 4f88475a962975ca45994cff9add350344fce4f9 Mon Sep 17 00:00:00 2001 From: Allan Sandfeld Jensen Date: Fri, 11 Nov 2016 13:05:13 +0100 Subject: Allow QImage with more than 2GByte of image data Changes internal data-size and pointer calculations to qssize_t. Adds new sizeInBytes() accessor to read byte size, and marks the old one deprecated. Task-number: QTBUG-50912 Change-Id: Idf0c2010542b0ec1c9abef8afd02d6db07f43e6d Reviewed-by: Thiago Macieira --- .../widgets/painting/composition/composition.cpp | 2 +- src/gui/image/qbmphandler.cpp | 4 +- src/gui/image/qimage.cpp | 43 +++++++++++++++------- src/gui/image/qimage.h | 5 ++- src/gui/image/qimage_conversions.cpp | 28 +++++++------- src/gui/image/qimage_p.h | 4 +- src/gui/image/qpixmap_blitter.cpp | 4 +- src/gui/painting/qcoregraphics.mm | 2 +- src/gui/painting/qcosmeticstroker.cpp | 2 +- src/gui/painting/qdrawhelper.cpp | 12 +++--- src/gui/painting/qdrawhelper_avx2.cpp | 2 +- src/gui/painting/qdrawhelper_p.h | 4 +- src/gui/painting/qdrawhelper_sse2.cpp | 4 +- src/gui/painting/qpaintengine_raster.cpp | 10 ++--- src/gui/painting/qpaintengine_raster_p.h | 2 + .../themes/genericunix/dbustray/qdbustraytypes.cpp | 2 +- src/plugins/imageformats/gif/qgifhandler.cpp | 4 +- .../eglfs_kms/qeglfskmsgbmcursor.cpp | 2 +- src/plugins/platforms/xcb/qxcbimage.cpp | 2 +- src/widgets/itemviews/qitemdelegate.cpp | 2 +- tests/auto/gui/image/qimage/tst_qimage.cpp | 35 ++++++++++++++++-- .../gui/image/qimagewriter/tst_qimagewriter.cpp | 2 +- .../itemviews/qitemdelegate/tst_qitemdelegate.cpp | 2 +- tests/baselineserver/shared/baselineprotocol.cpp | 2 +- 24 files changed, 115 insertions(+), 66 deletions(-) diff --git a/examples/widgets/painting/composition/composition.cpp b/examples/widgets/painting/composition/composition.cpp index d5d674fd83..0b57d3c7d3 100644 --- a/examples/widgets/painting/composition/composition.cpp +++ b/examples/widgets/painting/composition/composition.cpp @@ -464,7 +464,7 @@ void CompositionRenderer::paint(QPainter *painter) drawBase(p); } - memcpy(m_buffer.bits(), m_base_buffer.bits(), m_buffer.byteCount()); + memcpy(m_buffer.bits(), m_base_buffer.bits(), m_buffer.sizeInBytes()); { QPainter p(&m_buffer); diff --git a/src/gui/image/qbmphandler.cpp b/src/gui/image/qbmphandler.cpp index 4350a5c192..c232a84e4f 100644 --- a/src/gui/image/qbmphandler.cpp +++ b/src/gui/image/qbmphandler.cpp @@ -49,10 +49,10 @@ QT_BEGIN_NAMESPACE static void swapPixel01(QImage *image) // 1-bpp: swap 0 and 1 pixels { - int i; + qssize_t i; if (image->depth() == 1 && image->colorCount() == 2) { uint *p = (uint *)image->bits(); - int nbytes = image->byteCount(); + qssize_t nbytes = static_cast(image->sizeInBytes()); for (i=0; i> 5) << 2; // bytes per scanline (must be multiple of 4) // sanity check for potential overflows - if (INT_MAX/depth < width + if (std::numeric_limits::max()/depth < width || bytes_per_line <= 0 || height <= 0 - || INT_MAX/uint(bytes_per_line) < height - || INT_MAX/sizeof(uchar *) < uint(height)) + || std::numeric_limits::max()/uint(bytes_per_line) < height + || std::numeric_limits::max()/sizeof(uchar *) < uint(height)) return 0; QScopedPointer d(new QImageData); @@ -452,7 +452,7 @@ bool QImageData::checkForAlphaPixels() const used. For more information see the \l {QImage#Image Formats}{Image Formats} section. - The format(), bytesPerLine(), and byteCount() functions provide + The format(), bytesPerLine(), and sizeInBytes() functions provide low-level information about the data stored in the image. The cacheKey() function returns a number that uniquely @@ -1448,12 +1448,29 @@ void QImage::setDevicePixelRatio(qreal scaleFactor) /*! \since 4.6 + \obsolete Returns the number of bytes occupied by the image data. - \sa bytesPerLine(), bits(), {QImage#Image Information}{Image + Note this method should never be called on an image larger than 2 gigabytes. + Instead use sizeInBytes(). + + \sa sizeInBytes(), bytesPerLine(), bits(), {QImage#Image Information}{Image Information} */ int QImage::byteCount() const +{ + Q_ASSERT(!d || d->nbytes < std::numeric_limits::max()); + return d ? int(d->nbytes) : 0; +} + +/*! + \since 5.10 + Returns the image data size in bytes. + + \sa byteCount(), bytesPerLine(), bits(), {QImage#Image Information}{Image + Information} +*/ +qssize_t QImage::sizeInBytes() const { return d ? d->nbytes : 0; } @@ -1461,13 +1478,13 @@ int QImage::byteCount() const /*! Returns the number of bytes per image scanline. - This is equivalent to byteCount() / height(). + This is equivalent to sizeInBytes() / height() if height() is non-zero. \sa scanLine() */ int QImage::bytesPerLine() const { - return (d && d->height) ? d->nbytes / d->height : 0; + return d ? d->bytes_per_line : 0; } @@ -1594,7 +1611,7 @@ const uchar *QImage::constScanLine(int i) const data, thus ensuring that this QImage is the only one using the current return value. - \sa scanLine(), byteCount(), constBits() + \sa scanLine(), sizeInBytes(), constBits() */ uchar *QImage::bits() { @@ -4675,12 +4692,12 @@ QImage QImage::transformed(const QTransform &matrix, Qt::TransformationMode mode if (dImage.d->colortable.size() < 256) { // colors are left in the color table, so pick that one as transparent dImage.d->colortable.append(0x0); - memset(dImage.bits(), dImage.d->colortable.size() - 1, dImage.byteCount()); + memset(dImage.bits(), dImage.d->colortable.size() - 1, dImage.d->nbytes); } else { - memset(dImage.bits(), 0, dImage.byteCount()); + memset(dImage.bits(), 0, dImage.d->nbytes); } } else - memset(dImage.bits(), 0x00, dImage.byteCount()); + memset(dImage.bits(), 0x00, dImage.d->nbytes); if (target_format >= QImage::Format_RGB32) { // Prevent QPainter from applying devicePixelRatio corrections @@ -4785,7 +4802,7 @@ QDebug operator<<(QDebug dbg, const QImage &i) if (i.colorCount()) dbg << ",colorCount=" << i.colorCount(); dbg << ",devicePixelRatio=" << i.devicePixelRatio() - << ",bytesPerLine=" << i.bytesPerLine() << ",byteCount=" << i.byteCount(); + << ",bytesPerLine=" << i.bytesPerLine() << ",sizeInBytes=" << i.sizeInBytes(); } dbg << ')'; return dbg; @@ -4807,7 +4824,7 @@ QDebug operator<<(QDebug dbg, const QImage &i) Returns the number of bytes occupied by the image data. - \sa byteCount() + \sa sizeInBytes() */ /*! diff --git a/src/gui/image/qimage.h b/src/gui/image/qimage.h index 225ef3d2e8..7ad44cc33e 100644 --- a/src/gui/image/qimage.h +++ b/src/gui/image/qimage.h @@ -214,7 +214,10 @@ public: const uchar *bits() const; const uchar *constBits() const; - int byteCount() const; +#if QT_DEPRECATED_SINCE(5, 10) + QT_DEPRECATED int byteCount() const; +#endif + qssize_t sizeInBytes() const; uchar *scanLine(int); const uchar *scanLine(int) const; diff --git a/src/gui/image/qimage_conversions.cpp b/src/gui/image/qimage_conversions.cpp index aa7cfe9547..6abaa2887e 100644 --- a/src/gui/image/qimage_conversions.cpp +++ b/src/gui/image/qimage_conversions.cpp @@ -823,8 +823,8 @@ static bool convert_indexed8_to_ARGB_PM_inplace(QImageData *data, Qt::ImageConve const int depth = 32; - const int dst_bytes_per_line = ((data->width * depth + 31) >> 5) << 2; - const int nbytes = dst_bytes_per_line * data->height; + const qssize_t dst_bytes_per_line = ((data->width * depth + 31) >> 5) << 2; + const qssize_t nbytes = dst_bytes_per_line * data->height; uchar *const newData = (uchar *)realloc(data->data, nbytes); if (!newData) return false; @@ -877,8 +877,8 @@ static bool convert_indexed8_to_ARGB_inplace(QImageData *data, Qt::ImageConversi const int depth = 32; - const int dst_bytes_per_line = ((data->width * depth + 31) >> 5) << 2; - const int nbytes = dst_bytes_per_line * data->height; + const qssize_t dst_bytes_per_line = ((data->width * depth + 31) >> 5) << 2; + const qssize_t nbytes = dst_bytes_per_line * data->height; uchar *const newData = (uchar *)realloc(data->data, nbytes); if (!newData) return false; @@ -945,8 +945,8 @@ static bool convert_indexed8_to_RGB16_inplace(QImageData *data, Qt::ImageConvers const int depth = 16; - const int dst_bytes_per_line = ((data->width * depth + 31) >> 5) << 2; - const int nbytes = dst_bytes_per_line * data->height; + const qssize_t dst_bytes_per_line = ((data->width * depth + 31) >> 5) << 2; + const qssize_t nbytes = dst_bytes_per_line * data->height; uchar *const newData = (uchar *)realloc(data->data, nbytes); if (!newData) return false; @@ -1002,8 +1002,8 @@ static bool convert_RGB_to_RGB16_inplace(QImageData *data, Qt::ImageConversionFl const int depth = 16; - const int dst_bytes_per_line = ((data->width * depth + 31) >> 5) << 2; - const int src_bytes_per_line = data->bytes_per_line; + const qssize_t dst_bytes_per_line = ((data->width * depth + 31) >> 5) << 2; + const qssize_t src_bytes_per_line = data->bytes_per_line; quint32 *src_data = (quint32 *) data->data; quint16 *dst_data = (quint16 *) data->data; @@ -1257,9 +1257,9 @@ void dither_to_Mono(QImageData *dst, const QImageData *src, } uchar *dst_data = dst->data; - int dst_bpl = dst->bytes_per_line; + qssize_t dst_bpl = dst->bytes_per_line; const uchar *src_data = src->data; - int src_bpl = src->bytes_per_line; + qssize_t src_bpl = src->bytes_per_line; switch (dithermode) { case Diffuse: { @@ -1912,8 +1912,8 @@ static void convert_Indexed8_to_Alpha8(QImageData *dest, const QImageData *src, if (simpleCase) memcpy(dest->data, src->data, src->bytes_per_line * src->height); else { - int size = src->bytes_per_line * src->height; - for (int i = 0; i < size; ++i) { + qssize_t size = src->bytes_per_line * src->height; + for (qssize_t i = 0; i < size; ++i) { dest->data[i] = translate[src->data[i]]; } } @@ -1936,8 +1936,8 @@ static void convert_Indexed8_to_Grayscale8(QImageData *dest, const QImageData *s if (simpleCase) memcpy(dest->data, src->data, src->bytes_per_line * src->height); else { - int size = src->bytes_per_line * src->height; - for (int i = 0; i < size; ++i) { + qssize_t size = src->bytes_per_line * src->height; + for (qssize_t i = 0; i < size; ++i) { dest->data[i] = translate[src->data[i]]; } } diff --git a/src/gui/image/qimage_p.h b/src/gui/image/qimage_p.h index 775ab6d541..9ba4945dc5 100644 --- a/src/gui/image/qimage_p.h +++ b/src/gui/image/qimage_p.h @@ -71,12 +71,12 @@ struct Q_GUI_EXPORT QImageData { // internal image data int width; int height; int depth; - int nbytes; // number of bytes data + qssize_t nbytes; // number of bytes data qreal devicePixelRatio; QVector colortable; uchar *data; QImage::Format format; - int bytes_per_line; + qssize_t bytes_per_line; int ser_no; // serial number int detach_no; diff --git a/src/gui/image/qpixmap_blitter.cpp b/src/gui/image/qpixmap_blitter.cpp index 950695a9d7..de32327071 100644 --- a/src/gui/image/qpixmap_blitter.cpp +++ b/src/gui/image/qpixmap_blitter.cpp @@ -190,8 +190,8 @@ void QBlittablePlatformPixmap::fromImage(const QImage &image, uchar *mem = thisImg->bits(); const uchar *bits = correctFormatPic.constBits(); - int bytesCopied = 0; - while (bytesCopied < correctFormatPic.byteCount()) { + qssize_t bytesCopied = 0; + while (bytesCopied < correctFormatPic.sizeInBytes()) { memcpy(mem,bits,correctFormatPic.bytesPerLine()); mem += thisImg->bytesPerLine(); bits += correctFormatPic.bytesPerLine(); diff --git a/src/gui/painting/qcoregraphics.mm b/src/gui/painting/qcoregraphics.mm index 98fdd7f35e..9cfc94f9e8 100644 --- a/src/gui/painting/qcoregraphics.mm +++ b/src/gui/painting/qcoregraphics.mm @@ -66,7 +66,7 @@ CGImageRef qt_mac_toCGImageMask(const QImage &image) static const auto deleter = [](void *image, const void *, size_t) { delete static_cast(image); }; QCFType dataProvider = CGDataProviderCreateWithData(new QImage(image), image.bits(), - image.byteCount(), deleter); + image.sizeInBytes(), deleter); return CGImageMaskCreate(image.width(), image.height(), 8, image.depth(), image.bytesPerLine(), dataProvider, NULL, false); diff --git a/src/gui/painting/qcosmeticstroker.cpp b/src/gui/painting/qcosmeticstroker.cpp index 4965762d74..a3689a81c1 100644 --- a/src/gui/painting/qcosmeticstroker.cpp +++ b/src/gui/painting/qcosmeticstroker.cpp @@ -292,7 +292,7 @@ void QCosmeticStroker::setup() color = multiplyAlpha256(state->penData.solid.color, opacity).toArgb32(); QRasterBuffer *buffer = state->penData.rasterBuffer; pixels = (uint *)buffer->buffer(); - ppl = buffer->bytesPerLine()>>2; + ppl = buffer->stride(); } // line drawing produces different results with different clips, so diff --git a/src/gui/painting/qdrawhelper.cpp b/src/gui/painting/qdrawhelper.cpp index ca82f9a35a..67925fc69f 100644 --- a/src/gui/painting/qdrawhelper.cpp +++ b/src/gui/painting/qdrawhelper.cpp @@ -2377,7 +2377,7 @@ static void QT_FASTCALL fetchTransformedBilinearARGB32PM_fast_rotate_helper(uint __m128i v_fy = _mm_setr_epi32(fy, fy + fdy, fy + fdy + fdy, fy + fdy + fdy + fdy); const uchar *textureData = image.imageData; - const int bytesPerLine = image.bytesPerLine; + const qssize_t bytesPerLine = image.bytesPerLine; const __m128i vbpl = _mm_shufflelo_epi16(_mm_cvtsi32_si128(bytesPerLine/4), _MM_SHUFFLE(0, 0, 0, 0)); while (b < boundedEnd - 3) { @@ -4947,7 +4947,7 @@ static void blend_transformed_tiled_argb(int count, const QSpan *spans, void *us int image_width = data->texture.width; int image_height = data->texture.height; - const int scanline_offset = data->texture.bytesPerLine / 4; + const qssize_t scanline_offset = data->texture.bytesPerLine / 4; if (data->fast_matrix) { // The increment pr x in the scanline @@ -5287,7 +5287,7 @@ inline void qt_bitmapblit_template(QRasterBuffer *rasterBuffer, int mapWidth, int mapHeight, int mapStride) { DST *dest = reinterpret_cast(rasterBuffer->scanLine(y)) + x; - const int destStride = rasterBuffer->bytesPerLine() / sizeof(DST); + const int destStride = rasterBuffer->stride(); if (mapWidth > 8) { while (mapHeight--) { @@ -5601,7 +5601,7 @@ void qt_alphamapblit_quint16(QRasterBuffer *rasterBuffer, if (!clip) { quint16 *dest = reinterpret_cast(rasterBuffer->scanLine(y)) + x; - const int destStride = rasterBuffer->bytesPerLine() / sizeof(quint16); + const int destStride = rasterBuffer->stride(); while (mapHeight--) { for (int i = 0; i < mapWidth; ++i) alphamapblend_quint16(map[i], dest, i, c); @@ -5676,7 +5676,7 @@ static void qt_alphamapblit_argb32(QRasterBuffer *rasterBuffer, const QClipData *clip, bool useGammaCorrection) { const quint32 c = color.toArgb32(); - const int destStride = rasterBuffer->bytesPerLine() / sizeof(quint32); + const int destStride = rasterBuffer->stride(); if (color.isTransparent()) return; @@ -5872,7 +5872,7 @@ static void qt_alphargbblit_argb32(QRasterBuffer *rasterBuffer, if (!clip) { quint32 *dst = reinterpret_cast(rasterBuffer->scanLine(y)) + x; - const int destStride = rasterBuffer->bytesPerLine() / sizeof(quint32); + const int destStride = rasterBuffer->stride(); while (mapHeight--) { for (int i = 0; i < mapWidth; ++i) { const uint coverage = src[i]; diff --git a/src/gui/painting/qdrawhelper_avx2.cpp b/src/gui/painting/qdrawhelper_avx2.cpp index a7e03a7bb3..a378fca749 100644 --- a/src/gui/painting/qdrawhelper_avx2.cpp +++ b/src/gui/painting/qdrawhelper_avx2.cpp @@ -682,7 +682,7 @@ void QT_FASTCALL fetchTransformedBilinearARGB32PM_fast_rotate_helper_avx2(uint * v_fy = _mm256_add_epi32(v_fy, _mm256_mullo_epi32(_mm256_set1_epi32(fdy), v_index)); const uchar *textureData = image.imageData; - const int bytesPerLine = image.bytesPerLine; + const qssize_t bytesPerLine = image.bytesPerLine; const __m256i vbpl = _mm256_set1_epi16(bytesPerLine/4); while (b < boundedEnd - 7) { diff --git a/src/gui/painting/qdrawhelper_p.h b/src/gui/painting/qdrawhelper_p.h index 1f97621171..91f3bc368d 100644 --- a/src/gui/painting/qdrawhelper_p.h +++ b/src/gui/painting/qdrawhelper_p.h @@ -293,7 +293,7 @@ struct QTextureData int y1; int x2; int y2; - int bytesPerLine; + qssize_t bytesPerLine; QImage::Format format; const QVector *colorTable; bool hasAlpha; @@ -847,7 +847,7 @@ inline void qt_memfill(T *dest, T value, int count) template Q_STATIC_TEMPLATE_FUNCTION inline void qt_rectfill(T *dest, T value, - int x, int y, int width, int height, int stride) + int x, int y, int width, int height, qssize_t stride) { char *d = reinterpret_cast(dest + x) + y * stride; if (uint(stride) == (width * sizeof(T))) { diff --git a/src/gui/painting/qdrawhelper_sse2.cpp b/src/gui/painting/qdrawhelper_sse2.cpp index 3013d2cf3e..bfe2080298 100644 --- a/src/gui/painting/qdrawhelper_sse2.cpp +++ b/src/gui/painting/qdrawhelper_sse2.cpp @@ -341,7 +341,7 @@ void qt_bitmapblit32_sse2_base(QRasterBuffer *rasterBuffer, int x, int y, const uchar *src, int width, int height, int stride) { quint32 *dest = reinterpret_cast(rasterBuffer->scanLine(y)) + x; - const int destStride = rasterBuffer->bytesPerLine() / sizeof(quint32); + const int destStride = rasterBuffer->stride(); const __m128i c128 = _mm_set1_epi32(color); const __m128i maskmask1 = _mm_set_epi32(0x10101010, 0x20202020, @@ -407,7 +407,7 @@ void qt_bitmapblit16_sse2(QRasterBuffer *rasterBuffer, int x, int y, { const quint16 c = qConvertRgb32To16(color.toArgb32()); quint16 *dest = reinterpret_cast(rasterBuffer->scanLine(y)) + x; - const int destStride = rasterBuffer->bytesPerLine() / sizeof(quint16); + const int destStride = rasterBuffer->stride(); const __m128i c128 = _mm_set1_epi16(c); QT_WARNING_DISABLE_MSVC(4309) // truncation of constant value diff --git a/src/gui/painting/qpaintengine_raster.cpp b/src/gui/painting/qpaintengine_raster.cpp index eb43453ddb..1241193332 100644 --- a/src/gui/painting/qpaintengine_raster.cpp +++ b/src/gui/painting/qpaintengine_raster.cpp @@ -993,7 +993,7 @@ void QRasterPaintEnginePrivate::drawImage(const QPointF &pt, Q_ASSERT(img.depth() >= 8); - int srcBPL = img.bytesPerLine(); + qssize_t srcBPL = img.bytesPerLine(); const uchar *srcBits = img.bits(); int srcSize = img.depth() >> 3; // This is the part that is incompatible with lower than 8-bit.. int iw = img.width(); @@ -1042,7 +1042,7 @@ void QRasterPaintEnginePrivate::drawImage(const QPointF &pt, // call the blend function... int dstSize = rasterBuffer->bytesPerPixel(); - int dstBPL = rasterBuffer->bytesPerLine(); + qssize_t dstBPL = rasterBuffer->bytesPerLine(); func(rasterBuffer->buffer() + x * dstSize + y * dstBPL, dstBPL, srcBits, srcBPL, iw, ih, @@ -2317,8 +2317,8 @@ void QRasterPaintEngine::drawImage(const QRectF &r, const QImage &img, const QRe clippedSourceRect = clippedSourceRect.intersected(img.rect()); - uint dbpl = d->rasterBuffer->bytesPerLine(); - uint sbpl = img.bytesPerLine(); + const qssize_t dbpl = d->rasterBuffer->bytesPerLine(); + const qssize_t sbpl = img.bytesPerLine(); uchar *dst = d->rasterBuffer->buffer(); uint bpp = img.depth() >> 3; @@ -2827,7 +2827,7 @@ bool QRasterPaintEngine::drawCachedGlyphs(int numGlyphs, const glyph_t *glyphs, cache->fillInPendingGlyphs(); const QImage &image = cache->image(); - int bpl = image.bytesPerLine(); + qssize_t bpl = image.bytesPerLine(); int depth = image.depth(); int rightShift = 0; diff --git a/src/gui/painting/qpaintengine_raster_p.h b/src/gui/painting/qpaintengine_raster_p.h index d0b82b3a93..e2e0f821e3 100644 --- a/src/gui/painting/qpaintengine_raster_p.h +++ b/src/gui/painting/qpaintengine_raster_p.h @@ -457,6 +457,8 @@ public: int height() const { return m_height; } int bytesPerLine() const { return bytes_per_line; } int bytesPerPixel() const { return bytes_per_pixel; } + template + int stride() { return bytes_per_line / sizeof(T); } uchar *buffer() const { return m_buffer; } diff --git a/src/platformsupport/themes/genericunix/dbustray/qdbustraytypes.cpp b/src/platformsupport/themes/genericunix/dbustray/qdbustraytypes.cpp index fc0fa00655..fc49fcbea9 100644 --- a/src/platformsupport/themes/genericunix/dbustray/qdbustraytypes.cpp +++ b/src/platformsupport/themes/genericunix/dbustray/qdbustraytypes.cpp @@ -104,7 +104,7 @@ QXdgDBusImageVector iconToQXdgDBusImageVector(const QIcon &icon) } // copy and endian-convert QXdgDBusImageStruct kim(im.width(), im.height()); - const uchar *end = im.constBits() + im.byteCount(); + const uchar *end = im.constBits() + im.sizeInBytes(); uchar *dest = reinterpret_cast(kim.data.data()); for (const uchar *src = im.constBits(); src < end; src += 4, dest += 4) qToUnaligned(qToBigEndian(qFromUnaligned(src)), dest); diff --git a/src/plugins/imageformats/gif/qgifhandler.cpp b/src/plugins/imageformats/gif/qgifhandler.cpp index bae74bf9a1..e0f7f44701 100644 --- a/src/plugins/imageformats/gif/qgifhandler.cpp +++ b/src/plugins/imageformats/gif/qgifhandler.cpp @@ -354,7 +354,7 @@ int QGIFFormat::decode(QImage *image, const uchar *buffer, int length, (*image) = QImage(swidth, sheight, format); bpl = image->bytesPerLine(); bits = image->bits(); - memset(bits, 0, image->byteCount()); + memset(bits, 0, image->sizeInBytes()); } // Check if the previous attempt to create the image failed. If it @@ -415,7 +415,7 @@ int QGIFFormat::decode(QImage *image, const uchar *buffer, int length, backingstore = QImage(qMax(backingstore.width(), w), qMax(backingstore.height(), h), QImage::Format_RGB32); - memset(backingstore.bits(), 0, backingstore.byteCount()); + memset(backingstore.bits(), 0, backingstore.sizeInBytes()); } const int dest_bpl = backingstore.bytesPerLine(); unsigned char *dest_data = backingstore.bits(); diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmcursor.cpp b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmcursor.cpp index 5b779d6732..a3868fdb1d 100644 --- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmcursor.cpp +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmcursor.cpp @@ -204,7 +204,7 @@ void QEglFSKmsGbmCursor::changeCursor(QCursor *windowCursor, QWindow *window) painter.drawImage(0, 0, *m_cursorImage.image()); painter.end(); - gbm_bo_write(m_bo, cursorImage.constBits(), cursorImage.byteCount()); + gbm_bo_write(m_bo, cursorImage.constBits(), cursorImage.sizeInBytes()); uint32_t handle = gbm_bo_get_handle(m_bo).u32; diff --git a/src/plugins/platforms/xcb/qxcbimage.cpp b/src/plugins/platforms/xcb/qxcbimage.cpp index f3dfa1916b..8635a03dcb 100644 --- a/src/plugins/platforms/xcb/qxcbimage.cpp +++ b/src/plugins/platforms/xcb/qxcbimage.cpp @@ -225,7 +225,7 @@ xcb_cursor_t qt_xcb_createCursorXRender(QXcbScreen *screen, const QImage &image, xcb_image_destroy(xi); return XCB_NONE; } - memcpy(xi->data, img.constBits(), img.byteCount()); + memcpy(xi->data, img.constBits(), img.sizeInBytes()); xcb_pixmap_t pix = xcb_generate_id(conn); xcb_create_pixmap(conn, 32, pix, screen->root(), w, h); diff --git a/src/widgets/itemviews/qitemdelegate.cpp b/src/widgets/itemviews/qitemdelegate.cpp index 6a6220cd0a..86deea75b7 100644 --- a/src/widgets/itemviews/qitemdelegate.cpp +++ b/src/widgets/itemviews/qitemdelegate.cpp @@ -989,7 +989,7 @@ QPixmap *QItemDelegate::selected(const QPixmap &pixmap, const QPalette &palette, painter.end(); QPixmap selected = QPixmap(QPixmap::fromImage(img)); - int n = (img.byteCount() >> 10) + 1; + int n = (img.sizeInBytes() >> 10) + 1; if (QPixmapCache::cacheLimit() < n) QPixmapCache::setCacheLimit(n); diff --git a/tests/auto/gui/image/qimage/tst_qimage.cpp b/tests/auto/gui/image/qimage/tst_qimage.cpp index af769403bf..09263550b2 100644 --- a/tests/auto/gui/image/qimage/tst_qimage.cpp +++ b/tests/auto/gui/image/qimage/tst_qimage.cpp @@ -218,6 +218,8 @@ private slots: void toCGImage(); #endif + void hugeQImage(); + private: const QString m_prefix; }; @@ -314,8 +316,7 @@ void tst_QImage::create() { bool cr = true; QT_TRY { - //QImage image(7000000, 7000000, 8, 256, QImage::IgnoreEndian); - QImage image(7000000, 7000000, QImage::Format_Indexed8); + QImage image(700000000, 70000000, QImage::Format_Indexed8); image.setColorCount(256); cr = !image.isNull(); } QT_CATCH (...) { @@ -2366,7 +2367,7 @@ void tst_QImage::rgbSwapped() QCOMPARE(image, imageSwappedTwice); - QCOMPARE(memcmp(image.constBits(), imageSwappedTwice.constBits(), image.byteCount()), 0); + QCOMPARE(memcmp(image.constBits(), imageSwappedTwice.constBits(), image.sizeInBytes()), 0); } void tst_QImage::mirrored_data() @@ -2478,7 +2479,7 @@ void tst_QImage::mirrored() QCOMPARE(image, imageMirroredTwice); if (format != QImage::Format_Mono && format != QImage::Format_MonoLSB) - QCOMPARE(memcmp(image.constBits(), imageMirroredTwice.constBits(), image.byteCount()), 0); + QCOMPARE(memcmp(image.constBits(), imageMirroredTwice.constBits(), image.sizeInBytes()), 0); else { for (int i = 0; i < image.height(); ++i) for (int j = 0; j < image.width(); ++j) @@ -3416,6 +3417,32 @@ void tst_QImage::toCGImage() #endif +void tst_QImage::hugeQImage() +{ +#if Q_PROCESSOR_WORDSIZE < 8 + QSKIP("Test only makes sense on 64-bit machines"); +#else + QImage image(25000, 25000, QImage::Format_RGB32); + + QVERIFY(!image.isNull()); + QCOMPARE(image.height(), 25000); + QCOMPARE(image.width(), 25000); + QCOMPARE(image.sizeInBytes(), qssize_t(25000)*25000*4); + QCOMPARE(image.bytesPerLine(), 25000 * 4); + + QCOMPARE(image.constScanLine(24990), image.constBits() + qssize_t(25000)*24990*4); + + image.setPixel(20000, 24990, 0xffaabbcc); + QCOMPARE(image.pixel(20000, 24990), 0xffaabbcc); + QCOMPARE((reinterpret_cast(image.constScanLine(24990)))[20000], 0xffaabbcc); + + QImage canvas(100, 100, QImage::Format_RGB32); + QPainter painter(&canvas); + painter.drawImage(0,0, image, 19950, 24900, 100, 100); + painter.end(); + QCOMPARE(reinterpret_cast(canvas.constScanLine(90))[50], 0xffaabbcc); +#endif +} QTEST_GUILESS_MAIN(tst_QImage) #include "tst_qimage.moc" diff --git a/tests/auto/gui/image/qimagewriter/tst_qimagewriter.cpp b/tests/auto/gui/image/qimagewriter/tst_qimagewriter.cpp index 2381fd9246..a53c2ddb5b 100644 --- a/tests/auto/gui/image/qimagewriter/tst_qimagewriter.cpp +++ b/tests/auto/gui/image/qimagewriter/tst_qimagewriter.cpp @@ -466,7 +466,7 @@ void tst_QImageWriter::saveWithNoFormat() SKIP_IF_UNSUPPORTED(format); QImage niceImage(64, 64, QImage::Format_ARGB32); - memset(niceImage.bits(), 0, niceImage.byteCount()); + memset(niceImage.bits(), 0, niceImage.sizeInBytes()); QImageWriter writer(fileName /* , 0 - no format! */); if (error != 0) { diff --git a/tests/auto/widgets/itemviews/qitemdelegate/tst_qitemdelegate.cpp b/tests/auto/widgets/itemviews/qitemdelegate/tst_qitemdelegate.cpp index 5b353bb2ae..2a5895583d 100644 --- a/tests/auto/widgets/itemviews/qitemdelegate/tst_qitemdelegate.cpp +++ b/tests/auto/widgets/itemviews/qitemdelegate/tst_qitemdelegate.cpp @@ -1021,7 +1021,7 @@ void tst_QItemDelegate::decoration() } case QVariant::Image: { QImage img(size, QImage::Format_Mono); - memset(img.bits(), 0, img.byteCount()); + memset(img.bits(), 0, img.sizeInBytes()); value = img; break; } diff --git a/tests/baselineserver/shared/baselineprotocol.cpp b/tests/baselineserver/shared/baselineprotocol.cpp index 1e4d8846c8..80e269ee2a 100644 --- a/tests/baselineserver/shared/baselineprotocol.cpp +++ b/tests/baselineserver/shared/baselineprotocol.cpp @@ -235,7 +235,7 @@ quint64 ImageItem::computeChecksum(const QImage &image) quint32 h1 = 0xfeedbacc; quint32 h2 = 0x21604894; - hashword2((const quint32 *)img.constBits(), img.byteCount()/4, &h1, &h2); + hashword2((const quint32 *)img.constBits(), img.sizeInBytes()/4, &h1, &h2); return (quint64(h1) << 32) | h2; } -- cgit v1.2.3