diff --git a/src/gui/image/qimage.cpp b/src/gui/image/qimage.cpp
index 8373a55..b5aff87 100644
--- a/src/gui/image/qimage.cpp
+++ b/src/gui/image/qimage.cpp
@@ -265,6 +265,16 @@ bool QImageData::checkForAlphaPixels() const
             end_bits += bytes_per_line;
         }
     } break;
+    case QImage::Format_RGBA64:
+    case QImage::Format_RGBA64_Premultiplied: {
+        uchar *bits = data;
+        for (int y=0; y<height && !has_alpha_pixels; ++y) {
+            for (int x=0; x<width; ++x) {
+                has_alpha_pixels |= !(((QRgba64 *)bits)[x].isOpaque());
+            }
+            bits += bytes_per_line;
+        }
+    } break;
 
     default:
         break;
@@ -1690,6 +1700,10 @@ void QImage::fill(uint pixel)
         qt_rectfill<quint24>(reinterpret_cast<quint24*>(d->data), pixel,
                              0, 0, d->width, d->height, d->bytes_per_line);
         return;
+    } else if (d->depth == 64) {
+        qt_rectfill<quint64>(reinterpret_cast<quint64*>(d->data), QRgba64::fromArgb32(pixel),
+                             0, 0, d->width, d->height, d->bytes_per_line);
+        return;
     }
 
     if (d->format == Format_RGB32)
@@ -1968,6 +1982,26 @@ QImage::Format QImage::format() const
     \sa {Image Formats}
 */
 
+static bool highColorPrecision(QImage::Format format)
+{
+    // Formats with higher color precision than ARGB32_Premultiplied.
+    switch (format) {
+    case QImage::Format_ARGB32:
+    case QImage::Format_RGBA8888:
+    case QImage::Format_BGR30:
+    case QImage::Format_RGB30:
+    case QImage::Format_A2BGR30_Premultiplied:
+    case QImage::Format_A2RGB30_Premultiplied:
+    case QImage::Format_RGBX64:
+    case QImage::Format_RGBA64:
+    case QImage::Format_RGBA64_Premultiplied:
+        return true;
+    default:
+        break;
+    }
+    return false;
+}
+
 /*!
     \internal
 */
@@ -1980,8 +2014,18 @@ QImage QImage::convertToFormat_helper(Format format, Qt::ImageConversionFlags fl
         return QImage();
 
     Image_Converter converter = qimage_converter_map[d->format][format];
-    if (!converter && format > QImage::Format_Indexed8 && d->format > QImage::Format_Indexed8)
-        converter = convert_generic;
+    if (!converter && format > QImage::Format_Indexed8 && d->format > QImage::Format_Indexed8) {
+        if (highColorPrecision(format) && highColorPrecision(d->format)) {
+            // Convert over RGBA64_Premultiplied
+            if (format == QImage::Format_RGBA64_Premultiplied)
+                converter = convert_generic_to_rgb64;
+            else {
+                Q_ASSERT(d->format != QImage::Format_RGBA64_Premultiplied);
+                return convertToFormat(Format_RGBA64_Premultiplied, flags).convertToFormat(format, flags);
+            }
+        } else
+            converter = convert_generic;
+    }
     if (converter) {
         QImage image(d->width, d->height, format);
 
@@ -4346,6 +4390,9 @@ int QImage::bitPlaneCount() const
     case QImage::Format_RGB444:
         bpc = 12;
         break;
+    case QImage::Format_RGBX64:
+        bpc = 48;
+        break;
     default:
         bpc = qt_depthForFormat(d->format);
         break;
@@ -4422,6 +4469,14 @@ static QImage rotated90(const QImage &image) {
                         reinterpret_cast<quint8*>(out.bits()),
                         out.bytesPerLine());
         break;
+    case QImage::Format_RGBX64:
+    case QImage::Format_RGBA64:
+    case QImage::Format_RGBA64_Premultiplied:
+        qt_memrotate270(reinterpret_cast<const quint64*>(image.bits()),
+                        w, h, image.bytesPerLine(),
+                        reinterpret_cast<quint64*>(out.bits()),
+                        out.bytesPerLine());
+        break;
     default:
         for (int y=0; y<h; ++y) {
             if (image.colorCount())
@@ -4490,6 +4545,14 @@ static QImage rotated270(const QImage &image) {
                        reinterpret_cast<quint8*>(out.bits()),
                        out.bytesPerLine());
         break;
+    case QImage::Format_RGBX64:
+    case QImage::Format_RGBA64:
+    case QImage::Format_RGBA64_Premultiplied:
+        qt_memrotate90(reinterpret_cast<const quint64*>(image.bits()),
+                       w, h, image.bytesPerLine(),
+                       reinterpret_cast<quint64*>(out.bits()),
+                       out.bytesPerLine());
+        break;
     default:
         for (int y=0; y<h; ++y) {
             if (image.colorCount())
@@ -4615,6 +4678,9 @@ QImage QImage::transformed(const QTransform &matrix, Qt::TransformationMode mode
             case QImage::Format_RGB30:
                 target_format = Format_A2RGB30_Premultiplied;
                 break;
+            case QImage::Format_RGBX64:
+                target_format = Format_RGBA64_Premultiplied;
+                break;
             default:
                 target_format = Format_ARGB32_Premultiplied;
                 break;
@@ -5117,6 +5183,45 @@ static Q_CONSTEXPR QPixelFormat pixelformats[] = {
                     /*PREMULTIPLIED*/     QPixelFormat::NotPremultiplied,
                     /*INTERPRETATION*/    QPixelFormat::UnsignedByte,
                     /*BYTE ORDER*/        QPixelFormat::CurrentSystemEndian),
+        //QImage::Format_RGBX64:
+        QPixelFormat(QPixelFormat::RGB,
+                     /*RED*/                16,
+                     /*GREEN*/              16,
+                     /*BLUE*/               16,
+                     /*FOURTH*/             0,
+                     /*FIFTH*/              0,
+                     /*ALPHA*/              16,
+                     /*ALPHA USAGE*/       QPixelFormat::IgnoresAlpha,
+                     /*ALPHA POSITION*/    QPixelFormat::AtEnd,
+                     /*PREMULTIPLIED*/     QPixelFormat::NotPremultiplied,
+                     /*INTERPRETATION*/    QPixelFormat::UnsignedShort,
+                     /*BYTE ORDER*/        QPixelFormat::CurrentSystemEndian),
+        //QImage::Format_RGBA64:
+        QPixelFormat(QPixelFormat::RGB,
+                     /*RED*/                16,
+                     /*GREEN*/              16,
+                     /*BLUE*/               16,
+                     /*FOURTH*/             0,
+                     /*FIFTH*/              0,
+                     /*ALPHA*/              16,
+                     /*ALPHA USAGE*/       QPixelFormat::UsesAlpha,
+                     /*ALPHA POSITION*/    QPixelFormat::AtEnd,
+                     /*PREMULTIPLIED*/     QPixelFormat::Premultiplied,
+                     /*INTERPRETATION*/    QPixelFormat::UnsignedShort,
+                     /*BYTE ORDER*/        QPixelFormat::CurrentSystemEndian),
+         //QImage::Format_RGBA64_Premultiplied:
+         QPixelFormat(QPixelFormat::RGB,
+                     /*RED*/                16,
+                     /*GREEN*/              16,
+                     /*BLUE*/               16,
+                     /*FOURTH*/             0,
+                     /*FIFTH*/              0,
+                     /*ALPHA*/              16,
+                     /*ALPHA USAGE*/       QPixelFormat::UsesAlpha,
+                     /*ALPHA POSITION*/    QPixelFormat::AtEnd,
+                     /*PREMULTIPLIED*/     QPixelFormat::Premultiplied,
+                     /*INTERPRETATION*/    QPixelFormat::UnsignedShort,
+                     /*BYTE ORDER*/        QPixelFormat::CurrentSystemEndian),
 };
 Q_STATIC_ASSERT(sizeof(pixelformats) / sizeof(*pixelformats) == QImage::NImageFormats);
 
diff --git a/src/gui/image/qimage.h b/src/gui/image/qimage.h
index 7751bbe..953bf60 100644
--- a/src/gui/image/qimage.h
+++ b/src/gui/image/qimage.h
@@ -113,6 +113,9 @@ public:
         Format_A2RGB30_Premultiplied,
         Format_Alpha8,
         Format_Grayscale8,
+        Format_RGBX64,
+        Format_RGBA64,
+        Format_RGBA64_Premultiplied,
 #if 0
         // reserved for future use
         Format_Grayscale16,
diff --git a/src/gui/image/qimage_conversions.cpp b/src/gui/image/qimage_conversions.cpp
index 28e3a48..4c99917 100644
--- a/src/gui/image/qimage_conversions.cpp
+++ b/src/gui/image/qimage_conversions.cpp
@@ -168,6 +168,32 @@ void convert_generic(QImageData *dest, const QImageData *src, Qt::ImageConversio
     }
 }
 
+void convert_generic_to_rgb64(QImageData *dest, const QImageData *src, Qt::ImageConversionFlags)
+{
+    Q_ASSERT(dest->format == QImage::Format_RGBA64_Premultiplied);
+    Q_ASSERT(src->format > QImage::Format_Indexed8);
+    const int buffer_size = 2048;
+    quint64 buffer[buffer_size];
+    const QPixelLayout *srcLayout = &qPixelLayouts[src->format];
+    const uchar *srcData = src->data;
+    uchar *destData = dest->data;
+
+    const FetchPixelsFunc64 fetch64 = qFetchPixels64[srcLayout->bpp];
+    ConvertFunc64 convertToRGBA64PM = srcLayout->convertToRGBA64PM;
+
+    for (int y = 0; y < src->height; ++y) {
+        int x = 0;
+        while (x < src->width) {
+            int l = qMin(src->width - x, buffer_size);
+            const quint64 *ptr = fetch64(buffer, srcData, x, l);
+            convertToRGBA64PM((QRgba64*)destData + x, ptr, l, srcLayout, 0);
+            x += l;
+        }
+        srcData += src->bytes_per_line;
+        destData += dest->bytes_per_line;
+    }
+}
+
 bool convert_generic_inplace(QImageData *data, QImage::Format dst_format, Qt::ImageConversionFlags)
 {
     // Cannot be used with indexed formats or between formats with different pixel depths.
@@ -182,6 +208,8 @@ bool convert_generic_inplace(QImageData *data, QImage::Format dst_format, Qt::Im
     const QPixelLayout *destLayout = &qPixelLayouts[dst_format];
     uchar *srcData = data->data;
 
+    Q_ASSERT(srcLayout->bpp == destLayout->bpp);
+    Q_ASSERT(srcLayout->bpp != QPixelLayout::BPP64);
     const FetchPixelsFunc fetch = qFetchPixels[srcLayout->bpp];
     const StorePixelsFunc store = qStorePixels[destLayout->bpp];
     ConvertFunc convertToARGB32PM = srcLayout->convertToARGB32PM;
@@ -1009,6 +1037,270 @@ static void mask_alpha_converter_RGBx(QImageData *dest, const QImageData *src, Q
 #endif
 }
 
+template<bool RGBA>
+static void convert_RGBA64_to_ARGB32(QImageData *dest, const QImageData *src, Qt::ImageConversionFlags)
+{
+    Q_ASSERT(src->format == QImage::Format_RGBA64);
+    Q_ASSERT(RGBA || dest->format == QImage::Format_ARGB32);
+    Q_ASSERT(!RGBA || dest->format == QImage::Format_RGBA8888);
+    Q_ASSERT(src->width == dest->width);
+    Q_ASSERT(src->height == dest->height);
+
+    const uchar *srcData = src->data;
+    uchar *destData = dest->data;
+
+    for (int i = 0; i < src->height; ++i) {
+        uint *d = reinterpret_cast<uint *>(destData);
+        const QRgba64 *s = reinterpret_cast<const QRgba64 *>(srcData);
+        qt_convertRGBA64ToARGB32<RGBA>(d, s, src->width);
+        srcData += src->bytes_per_line;
+        destData += dest->bytes_per_line;
+    }
+}
+
+template<bool RGBA>
+static void convert_RGBA64PM_to_ARGB32(QImageData *dest, const QImageData *src, Qt::ImageConversionFlags)
+{
+    Q_ASSERT(src->format == QImage::Format_RGBA64_Premultiplied);
+    Q_ASSERT(RGBA || dest->format == QImage::Format_ARGB32);
+    Q_ASSERT(!RGBA || dest->format == QImage::Format_RGBA8888);
+    Q_ASSERT(src->width == dest->width);
+    Q_ASSERT(src->height == dest->height);
+
+    const int src_pad = (src->bytes_per_line >> 3) - src->width;
+    const int dest_pad = (dest->bytes_per_line >> 2) - dest->width;
+    const QRgba64 *src_data = reinterpret_cast<const QRgba64 *>(src->data);
+    uint *dest_data = reinterpret_cast<uint *>(dest->data);
+
+    for (int i = 0; i < src->height; ++i) {
+        const QRgba64 *end = src_data + src->width;
+        while (src_data < end) {
+            QRgba64 s = src_data->unpremultiplied();
+            *dest_data = RGBA ? ARGB2RGBA(s.toArgb32()) : s.toArgb32();
+            ++src_data;
+            ++dest_data;
+        }
+        src_data += src_pad;
+        dest_data += dest_pad;
+    }
+}
+
+template<bool RGBA>
+static void convert_ARGB32_to_RGBA64(QImageData *dest, const QImageData *src, Qt::ImageConversionFlags)
+{
+    Q_ASSERT(RGBA || src->format == QImage::Format_ARGB32);
+    Q_ASSERT(!RGBA || src->format == QImage::Format_RGBA8888);
+    Q_ASSERT(dest->format == QImage::Format_RGBA64);
+    Q_ASSERT(src->width == dest->width);
+    Q_ASSERT(src->height == dest->height);
+
+    const int src_pad = (src->bytes_per_line >> 2) - src->width;
+    const int dest_pad = (dest->bytes_per_line >> 3) - dest->width;
+    const uint *src_data = reinterpret_cast<const uint *>(src->data);
+    QRgba64 *dest_data = reinterpret_cast<QRgba64 *>(dest->data);
+
+    for (int i = 0; i < src->height; ++i) {
+        const uint *end = src_data + src->width;
+        while (src_data < end) {
+            if (RGBA)
+                *dest_data = QRgba64::fromArgb32(RGBA2ARGB(*src_data));
+            else
+                *dest_data = QRgba64::fromArgb32(*src_data);
+            ++src_data;
+            ++dest_data;
+        }
+        src_data += src_pad;
+        dest_data += dest_pad;
+    }
+}
+
+template<QtPixelOrder PixelOrder>
+static void convert_RGBA64PM_to_RGB30(QImageData *dest, const QImageData *src, Qt::ImageConversionFlags)
+{
+    Q_ASSERT(src->format == QImage::Format_RGBA64_Premultiplied);
+    Q_ASSERT(dest->format == QImage::Format_RGB30 || dest->format == QImage::Format_BGR30);
+    Q_ASSERT(src->width == dest->width);
+    Q_ASSERT(src->height == dest->height);
+
+    const int src_pad = (src->bytes_per_line >> 3) - src->width;
+    const int dest_pad = (dest->bytes_per_line >> 2) - dest->width;
+    const QRgba64 *src_data = reinterpret_cast<const QRgba64 *>(src->data);
+    uint *dest_data = reinterpret_cast<uint *>(dest->data);
+
+    for (int i = 0; i < src->height; ++i) {
+        const QRgba64 *end = src_data + src->width;
+        while (src_data < end) {
+            *dest_data = 0xc0000000 || qConvertRgb64ToRgb30<PixelOrder>(src_data->unpremultiplied());
+            ++src_data;
+            ++dest_data;
+        }
+        src_data += src_pad;
+        dest_data += dest_pad;
+    }
+}
+
+template<QtPixelOrder PixelOrder>
+static void convert_RGBA64PM_to_A2RGB30(QImageData *dest, const QImageData *src, Qt::ImageConversionFlags)
+{
+    Q_ASSERT(src->format == QImage::Format_RGBA64_Premultiplied);
+    Q_ASSERT(dest->format == QImage::Format_A2RGB30_Premultiplied
+          || dest->format == QImage::Format_A2BGR30_Premultiplied);
+    Q_ASSERT(src->width == dest->width);
+    Q_ASSERT(src->height == dest->height);
+
+    const int src_pad = (src->bytes_per_line >> 3) - src->width;
+    const int dest_pad = (dest->bytes_per_line >> 2) - dest->width;
+    const QRgba64 *src_data = reinterpret_cast<const QRgba64 *>(src->data);
+    uint *dest_data = reinterpret_cast<uint *>(dest->data);
+
+    for (int i = 0; i < src->height; ++i) {
+        const QRgba64 *end = src_data + src->width;
+        while (src_data < end) {
+            *dest_data = qConvertRgb64ToRgb30<PixelOrder>(*src_data);
+            ++src_data;
+            ++dest_data;
+        }
+        src_data += src_pad;
+        dest_data += dest_pad;
+    }
+}
+
+static void convert_RGBA64_to_RGBx64(QImageData *dest, const QImageData *src, Qt::ImageConversionFlags)
+{
+    Q_ASSERT(src->format == QImage::Format_RGBA64);
+    Q_ASSERT(dest->format == QImage::Format_RGBX64);
+    Q_ASSERT(src->width == dest->width);
+    Q_ASSERT(src->height == dest->height);
+
+    const int src_pad = (src->bytes_per_line >> 3) - src->width;
+    const int dest_pad = (dest->bytes_per_line >> 3) - dest->width;
+    const QRgba64 *src_data = reinterpret_cast<const QRgba64 *>(src->data);
+    QRgba64 *dest_data = reinterpret_cast<QRgba64 *>(dest->data);
+
+    for (int i = 0; i < src->height; ++i) {
+        const QRgba64 *end = src_data + src->width;
+        while (src_data < end) {
+            *dest_data = *src_data;
+            dest_data->setAlpha(65535);
+            ++src_data;
+            ++dest_data;
+        }
+        src_data += src_pad;
+        dest_data += dest_pad;
+    }
+}
+
+static bool convert_RGBA64_to_RGBx64_inplace(QImageData *data, Qt::ImageConversionFlags)
+{
+    Q_ASSERT(data->format == QImage::Format_RGBA64);
+
+    const int pad = (data->bytes_per_line >> 3) - data->width;
+    QRgba64 *rgb_data = reinterpret_cast<QRgba64 *>(data->data);
+
+    for (int i = 0; i < data->height; ++i) {
+        const QRgba64 *end = rgb_data + data->width;
+        while (rgb_data < end) {
+            rgb_data->setAlpha(65535);
+            ++rgb_data;
+        }
+        rgb_data += pad;
+    }
+    data->format = QImage::Format_RGBX64;
+    return true;
+}
+
+static void convert_RGBA64_to_RGBA64PM(QImageData *dest, const QImageData *src, Qt::ImageConversionFlags)
+{
+    Q_ASSERT(src->format == QImage::Format_RGBA64);
+    Q_ASSERT(dest->format == QImage::Format_RGBA64_Premultiplied);
+    Q_ASSERT(src->width == dest->width);
+    Q_ASSERT(src->height == dest->height);
+
+    const int src_pad = (src->bytes_per_line >> 3) - src->width;
+    const int dest_pad = (dest->bytes_per_line >> 3) - dest->width;
+    const QRgba64 *src_data = reinterpret_cast<const QRgba64 *>(src->data);
+    QRgba64 *dest_data = reinterpret_cast<QRgba64 *>(dest->data);
+
+    for (int i = 0; i < src->height; ++i) {
+        const QRgba64 *end = src_data + src->width;
+        while (src_data < end) {
+            *dest_data = src_data->premultiplied();
+            ++src_data;
+            ++dest_data;
+        }
+        src_data += src_pad;
+        dest_data += dest_pad;
+    }
+}
+
+static bool convert_RGBA64_to_RGBA64PM_inplace(QImageData *data, Qt::ImageConversionFlags)
+{
+    Q_ASSERT(data->format == QImage::Format_RGBA64);
+
+    const int pad = (data->bytes_per_line >> 3) - data->width;
+    QRgba64 *rgb_data = reinterpret_cast<QRgba64 *>(data->data);
+
+    for (int i = 0; i < data->height; ++i) {
+        const QRgba64 *end = rgb_data + data->width;
+        while (rgb_data < end) {
+            *rgb_data = rgb_data->premultiplied();
+            ++rgb_data;
+        }
+        rgb_data += pad;
+    }
+    data->format = QImage::Format_RGBA64_Premultiplied;
+    return true;
+}
+
+template<bool MaskAlpha>
+static void convert_RGBA64PM_to_RGBA64(QImageData *dest, const QImageData *src, Qt::ImageConversionFlags)
+{
+    Q_ASSERT(src->format == QImage::Format_RGBA64_Premultiplied);
+    Q_ASSERT(dest->format == QImage::Format_RGBA64 || dest->format == QImage::Format_RGBX64);
+    Q_ASSERT(src->width == dest->width);
+    Q_ASSERT(src->height == dest->height);
+
+    const int src_pad = (src->bytes_per_line >> 3) - src->width;
+    const int dest_pad = (dest->bytes_per_line >> 3) - dest->width;
+    const QRgba64 *src_data = reinterpret_cast<const QRgba64 *>(src->data);
+    QRgba64 *dest_data = reinterpret_cast<QRgba64 *>(dest->data);
+
+    for (int i = 0; i < src->height; ++i) {
+        const QRgba64 *end = src_data + src->width;
+        while (src_data < end) {
+            *dest_data = src_data->unpremultiplied();
+            if (MaskAlpha)
+                dest_data->setAlpha(65535);
+            ++src_data;
+            ++dest_data;
+        }
+        src_data += src_pad;
+        dest_data += dest_pad;
+    }
+}
+
+template<bool MaskAlpha>
+static bool convert_RGBA64PM_to_RGBA64_inplace(QImageData *data, Qt::ImageConversionFlags)
+{
+    Q_ASSERT(data->format == QImage::Format_RGBA64_Premultiplied);
+
+    const int pad = (data->bytes_per_line >> 3) - data->width;
+    QRgba64 *rgb_data = reinterpret_cast<QRgba64 *>(data->data);
+
+    for (int i = 0; i < data->height; ++i) {
+        const QRgba64 *end = rgb_data + data->width;
+        while (rgb_data < end) {
+            *rgb_data = rgb_data->unpremultiplied();
+            if (MaskAlpha)
+                rgb_data->setAlpha(65535);
+            ++rgb_data;
+        }
+        rgb_data += pad;
+    }
+    data->format = MaskAlpha ? QImage::Format_RGBX64 : QImage::Format_RGBA64;
+    return true;
+}
+
 static QVector<QRgb> fix_color_table(const QVector<QRgb> &ctbl, QImage::Format format)
 {
     QVector<QRgb> colorTable = ctbl;
@@ -1878,7 +2170,7 @@ Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImageFormat
         0,
         0,
         0,
-        0, 0, 0, 0, 0, 0, 0
+        0, 0, 0, 0, 0, 0, 0, 0, 0, 0
     }, // Format_Mono
 
     {
@@ -1900,7 +2192,7 @@ Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImageFormat
         0,
         0,
         0,
-        0, 0, 0, 0, 0, 0, 0
+        0, 0, 0, 0, 0, 0, 0, 0, 0, 0
     }, // Format_MonoLSB
 
     {
@@ -1925,6 +2217,7 @@ Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImageFormat
         0, 0, 0, 0, 0,
         convert_Indexed8_to_Alpha8,
         convert_Indexed8_to_Grayscale8,
+        0, 0, 0
     }, // Format_Indexed8
 
     {
@@ -1951,7 +2244,8 @@ Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImageFormat
         convert_RGB_to_RGB30<PixelOrderBGR>,
         convert_RGB_to_RGB30<PixelOrderRGB>,
         convert_RGB_to_RGB30<PixelOrderRGB>,
-        0, 0
+        0, 0,
+        0, 0, 0
     }, // Format_RGB32
 
     {
@@ -1978,7 +2272,10 @@ Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImageFormat
         0,
         convert_RGB_to_RGB30<PixelOrderRGB>,
         0,
-        0, 0
+        0, 0,
+        0,
+        convert_ARGB32_to_RGBA64<false>,
+        0
     }, // Format_ARGB32
 
     {
@@ -2001,11 +2298,9 @@ Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImageFormat
         0,
         0,
         convert_ARGB_to_RGBA,
-        0,
-        0,
-        0,
-        0,
-        0, 0
+        0, 0, 0, 0,
+        0, 0,
+        0, 0, 0
     },  // Format_ARGB32_Premultiplied
 
     {
@@ -2027,7 +2322,7 @@ Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImageFormat
         0,
         0,
         0,
-        0, 0, 0, 0, 0, 0, 0
+        0, 0, 0, 0, 0, 0, 0, 0, 0, 0
     }, // Format_RGB16
 
     {
@@ -2049,7 +2344,7 @@ Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImageFormat
         0,
         0,
         0,
-        0, 0, 0, 0, 0, 0, 0
+        0, 0, 0, 0, 0, 0, 0, 0, 0, 0
     }, // Format_ARGB8565_Premultiplied
 
     {
@@ -2071,7 +2366,7 @@ Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImageFormat
         0,
         0,
         0,
-        0, 0, 0, 0, 0, 0, 0
+        0, 0, 0, 0, 0, 0, 0, 0, 0, 0
     }, // Format_RGB666
 
     {
@@ -2093,7 +2388,7 @@ Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImageFormat
         0,
         0,
         0,
-        0, 0, 0, 0, 0, 0, 0
+        0, 0, 0, 0, 0, 0, 0, 0, 0, 0
     }, // Format_ARGB6666_Premultiplied
 
     {
@@ -2115,7 +2410,7 @@ Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImageFormat
         0,
         0,
         0,
-        0, 0, 0, 0, 0, 0, 0
+        0, 0, 0, 0, 0, 0, 0, 0, 0, 0
     }, // Format_RGB555
 
     {
@@ -2137,7 +2432,7 @@ Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImageFormat
         0,
         0,
         0,
-        0, 0, 0, 0, 0, 0, 0
+        0, 0, 0, 0, 0, 0, 0, 0, 0, 0
     }, // Format_ARGB8555_Premultiplied
 
     {
@@ -2160,7 +2455,7 @@ Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImageFormat
         convert_RGB888_to_RGB<true>,
         convert_RGB888_to_RGB<true>,
         convert_RGB888_to_RGB<true>,
-        0, 0, 0, 0, 0, 0
+        0, 0, 0, 0, 0, 0, 0, 0, 0
     }, // Format_RGB888
 
     {
@@ -2182,7 +2477,7 @@ Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImageFormat
         0,
         0,
         0,
-        0, 0, 0, 0, 0, 0, 0
+        0, 0, 0, 0, 0, 0, 0, 0, 0, 0
     }, // Format_RGB444
 
     {
@@ -2203,7 +2498,7 @@ Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImageFormat
         0,
         0,
         0,
-        0, 0, 0, 0, 0, 0, 0
+        0, 0, 0, 0, 0, 0, 0, 0, 0, 0
     }, // Format_ARGB4444_Premultiplied
     {
         0,
@@ -2223,9 +2518,9 @@ Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImageFormat
         0,
         0,
         0,
-        mask_alpha_converter_RGBx,
-        mask_alpha_converter_RGBx,
-        0, 0, 0, 0, 0, 0
+        convert_passthrough,
+        convert_passthrough,
+        0, 0, 0, 0, 0, 0, 0, 0, 0
     }, // Format_RGBX8888
     {
         0,
@@ -2252,7 +2547,10 @@ Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImageFormat
         0,
         0,
 #endif
-        0, 0, 0, 0, 0, 0
+        0, 0, 0, 0, 0, 0,
+        0,
+        convert_ARGB32_to_RGBA64<true>,
+        0
     }, // Format_RGBA8888
 
     {
@@ -2274,7 +2572,7 @@ Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImageFormat
         0,
         0,
         0,
-        0, 0, 0, 0, 0, 0
+        0, 0, 0, 0, 0, 0, 0, 0, 0
     }, // Format_RGBA8888_Premultiplied
 
     {
@@ -2301,7 +2599,8 @@ Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImageFormat
         convert_passthrough,
         convert_BGR30_to_RGB30,
         convert_BGR30_to_RGB30,
-        0, 0
+        0, 0,
+        0, 0, 0
     }, // Format_BGR30
     {
         0,
@@ -2327,7 +2626,8 @@ Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImageFormat
         0,
         0,
         convert_BGR30_to_RGB30,
-        0, 0
+        0, 0,
+        0, 0, 0
     }, // Format_BGR30A2_Premultiplied
     {
         0,
@@ -2353,7 +2653,7 @@ Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImageFormat
         0,
         0,
         convert_passthrough,
-        0, 0
+        0, 0, 0, 0, 0
     }, // Format_RGB30
     {
         0,
@@ -2379,8 +2679,8 @@ Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImageFormat
         convert_BGR30_to_RGB30,
         convert_A2RGB30_PM_to_RGB30,
         0,
-        0,
-        0,
+        0, 0,
+        0, 0, 0
     }, // Format_RGB30A2_Premultiplied
     {
         0,
@@ -2400,7 +2700,7 @@ Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImageFormat
         0,
         0,
         0,
-        0, 0, 0, 0, 0, 0, 0
+        0, 0, 0, 0, 0, 0, 0, 0, 0, 0
     }, // Format_Alpha8
     {
         0,
@@ -2420,20 +2720,98 @@ Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImageFormat
         0,
         0,
         0,
-        0, 0, 0, 0, 0, 0, 0
-    } // Format_Grayscale8
+        0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+    }, // Format_Grayscale8
+    {
+        0,
+        0,
+        0,
+        0,
+        0,
+        0,
+        0,
+        0,
+        0,
+        0,
+        0,
+        0,
+        0,
+        0,
+        0,
+        0,
+        0,
+        0,
+        0, 0, 0, 0,
+        0, 0,
+        0, // self
+        convert_passthrough,
+        convert_passthrough
+    }, // Format_RGBX64
+    {
+        0,
+        0,
+        0,
+        0,
+        0,
+        convert_RGBA64_to_ARGB32<false>,
+        0,
+        0,
+        0,
+        0,
+        0,
+        0,
+        0,
+        0,
+        0,
+        0,
+        convert_RGBA64_to_ARGB32<true>,
+        0,
+        0, 0, 0, 0,
+        0, 0,
+        convert_RGBA64_to_RGBx64,
+        0, // self
+        convert_RGBA64_to_RGBA64PM
+    }, // Format_RGBA64
+    {
+        0,
+        0,
+        0,
+        0,
+        0,
+        convert_RGBA64PM_to_ARGB32<false>,
+        0,
+        0,
+        0,
+        0,
+        0,
+        0,
+        0,
+        0,
+        0,
+        0,
+        convert_RGBA64PM_to_ARGB32<true>,
+        0,
+        convert_RGBA64PM_to_RGB30<PixelOrderBGR>,
+        convert_RGBA64PM_to_A2RGB30<PixelOrderBGR>,
+        convert_RGBA64PM_to_RGB30<PixelOrderRGB>,
+        convert_RGBA64PM_to_A2RGB30<PixelOrderRGB>,
+        0, 0,
+        convert_RGBA64PM_to_RGBA64<true>,
+        convert_RGBA64PM_to_RGBA64<false>,
+        0 // self
+    } // Format_RGBA64_Premultiplied
 };
 
 InPlace_Image_Converter qimage_inplace_converter_map[QImage::NImageFormats][QImage::NImageFormats] =
 {
     {
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
     },
     {
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
     }, // Format_Mono
     {
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
     }, // Format_MonoLSB
     {
         0,
@@ -2457,6 +2835,7 @@ InPlace_Image_Converter qimage_inplace_converter_map[QImage::NImageFormats][QIma
         0, 0, 0, 0, 0,
         convert_Indexed8_to_Alpha8_inplace,
         convert_Indexed8_to_Grayscale8_inplace,
+        0, 0, 0
     }, // Format_Indexed8
     {
         0,
@@ -2478,7 +2857,7 @@ InPlace_Image_Converter qimage_inplace_converter_map[QImage::NImageFormats][QIma
         0,
         0,
         0,
-        0, 0, 0, 0, 0, 0
+        0, 0, 0, 0, 0, 0, 0, 0, 0
     }, // Format_RGB32
     {
         0,
@@ -2504,7 +2883,7 @@ InPlace_Image_Converter qimage_inplace_converter_map[QImage::NImageFormats][QIma
         0,
         convert_ARGB_to_RGBA_inplace,
         0,
-        0, 0, 0, 0, 0, 0
+        0, 0, 0, 0, 0, 0, 0, 0, 0
     }, // Format_ARGB32
     {
         0,
@@ -2526,34 +2905,34 @@ InPlace_Image_Converter qimage_inplace_converter_map[QImage::NImageFormats][QIma
         0,
         0,
         convert_ARGB_to_RGBA_inplace,
-        0, 0, 0, 0, 0, 0
+        0, 0, 0, 0, 0, 0, 0, 0, 0
     },  // Format_ARGB32_Premultiplied
     {
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
     }, // Format_RGB16
     {
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
     }, // Format_ARGB8565_Premultiplied
     {
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
     }, // Format_RGB666
     {
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
     }, // Format_ARGB6666_Premultiplied
     {
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
     }, // Format_RGB555
     {
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
     }, // Format_ARGB8555_Premultiplied
     {
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
     }, // Format_RGB888
     {
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
     }, // Format_RGB444
     {
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
     }, // Format_ARGB4444_Premultiplied
     {
         0,
@@ -2575,7 +2954,7 @@ InPlace_Image_Converter qimage_inplace_converter_map[QImage::NImageFormats][QIma
         0,
         convert_passthrough_inplace<QImage::Format_RGBA8888>,
         convert_passthrough_inplace<QImage::Format_RGBA8888_Premultiplied>,
-        0, 0, 0, 0, 0, 0
+        0, 0, 0, 0, 0, 0, 0, 0, 0
     }, // Format_RGBX8888
     {
         0,
@@ -2602,7 +2981,7 @@ InPlace_Image_Converter qimage_inplace_converter_map[QImage::NImageFormats][QIma
         0,
         0,
 #endif
-        0, 0, 0, 0, 0, 0
+        0, 0, 0, 0, 0, 0, 0, 0, 0
     }, // Format_RGBA8888
     {
         0,
@@ -2624,7 +3003,7 @@ InPlace_Image_Converter qimage_inplace_converter_map[QImage::NImageFormats][QIma
         0,
         0,
         0,
-        0, 0, 0, 0, 0, 0
+        0, 0, 0, 0, 0, 0, 0, 0, 0
     }, // Format_RGBA8888_Premultiplied
     {
         0,
@@ -2650,7 +3029,7 @@ InPlace_Image_Converter qimage_inplace_converter_map[QImage::NImageFormats][QIma
         convert_passthrough_inplace<QImage::Format_A2BGR30_Premultiplied>,
         convert_BGR30_to_RGB30_inplace,
         convert_BGR30_to_RGB30_inplace,
-        0, 0
+        0, 0, 0, 0, 0
     }, // Format_BGR30
     {
         0,
@@ -2676,7 +3055,7 @@ InPlace_Image_Converter qimage_inplace_converter_map[QImage::NImageFormats][QIma
         0,
         0,
         convert_BGR30_to_RGB30_inplace,
-        0, 0
+        0, 0, 0, 0, 0
     }, // Format_BGR30A2_Premultiplied
     {
         0,
@@ -2702,7 +3081,7 @@ InPlace_Image_Converter qimage_inplace_converter_map[QImage::NImageFormats][QIma
         convert_BGR30_to_RGB30_inplace,
         0,
         convert_passthrough_inplace<QImage::Format_A2RGB30_Premultiplied>,
-        0, 0
+        0, 0, 0, 0, 0
     }, // Format_RGB30
     {
         0,
@@ -2728,7 +3107,7 @@ InPlace_Image_Converter qimage_inplace_converter_map[QImage::NImageFormats][QIma
         convert_BGR30_to_RGB30_inplace,
         convert_A2RGB30_PM_to_RGB30_inplace,
         0,
-        0, 0
+        0, 0, 0, 0, 0
     }, // Format_RGB30A2_Premultiplied
     {
         0,
@@ -2754,7 +3133,7 @@ InPlace_Image_Converter qimage_inplace_converter_map[QImage::NImageFormats][QIma
         0,
         0,
         0,
-        0, 0
+        0, 0, 0, 0, 0
     }, // Format_Alpha8
     {
         0,
@@ -2780,8 +3159,26 @@ InPlace_Image_Converter qimage_inplace_converter_map[QImage::NImageFormats][QIma
         0,
         0,
         0,
-        0, 0
-    }  // Format_Grayscale8
+        0, 0, 0, 0, 0
+    }, // Format_Grayscale8
+    {
+        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        0, // self
+        convert_passthrough_inplace<QImage::Format_RGBA64>,
+        convert_passthrough_inplace<QImage::Format_RGBA64_Premultiplied>,
+    }, // Format_RGBX64
+    {
+        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        convert_RGBA64_to_RGBx64_inplace,
+        0, // self
+        convert_RGBA64_to_RGBA64PM_inplace
+    }, // Format_RGBA64
+    {
+        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        convert_RGBA64PM_to_RGBA64_inplace<true>,
+        convert_RGBA64PM_to_RGBA64_inplace<false>,
+        0 // self
+    }  // Format_RGBA64_Premultiplied
 };
 
 void qInitImageConversions()
diff --git a/src/gui/image/qimage_p.h b/src/gui/image/qimage_p.h
index 7eb5719..8755d5b 100644
--- a/src/gui/image/qimage_p.h
+++ b/src/gui/image/qimage_p.h
@@ -107,6 +107,7 @@ extern Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImag
 extern InPlace_Image_Converter qimage_inplace_converter_map[QImage::NImageFormats][QImage::NImageFormats];
 
 void convert_generic(QImageData *dest, const QImageData *src, Qt::ImageConversionFlags);
+void convert_generic_to_rgb64(QImageData *dest, const QImageData *src, Qt::ImageConversionFlags);
 bool convert_generic_inplace(QImageData *data, QImage::Format dst_format, Qt::ImageConversionFlags);
 
 void dither_to_Mono(QImageData *dst, const QImageData *src, Qt::ImageConversionFlags flags, bool fromalpha);
@@ -160,6 +161,11 @@ inline int qt_depthForFormat(QImage::Format format)
     case QImage::Format_RGB888:
         depth = 24;
         break;
+    case QImage::Format_RGBX64:
+    case QImage::Format_RGBA64:
+    case QImage::Format_RGBA64_Premultiplied:
+        depth = 64;
+        break;
     }
     return depth;
 }
diff --git a/src/gui/image/qpixmap_raster.cpp b/src/gui/image/qpixmap_raster.cpp
index 9c8835a..7a76bb2 100644
--- a/src/gui/image/qpixmap_raster.cpp
+++ b/src/gui/image/qpixmap_raster.cpp
@@ -188,8 +188,17 @@ void QRasterPlatformPixmap::fill(const QColor &color)
                     toFormat = QImage::Format_ARGB8555_Premultiplied;
                 else if (image.format() == QImage::Format_RGB444)
                     toFormat = QImage::Format_ARGB4444_Premultiplied;
+                else if (image.format() == QImage::Format_RGBX8888)
+                    toFormat = QImage::Format_RGBA8888_Premultiplied;
                 else
 #endif
+                if (image.format() == QImage::Format_BGR30)
+                    toFormat = QImage::Format_A2BGR30_Premultiplied;
+                else if (image.format() == QImage::Format_RGB30)
+                    toFormat = QImage::Format_A2RGB30_Premultiplied;
+                else if (image.format() == QImage::Format_RGBX64)
+                    toFormat = QImage::Format_RGBA64_Premultiplied;
+                else
                     toFormat = QImage::Format_ARGB32_Premultiplied;
 
                 if (!image.isNull() && qt_depthForFormat(image.format()) == qt_depthForFormat(toFormat)) {
@@ -312,7 +321,12 @@ void QRasterPlatformPixmap::createPixmapForImage(QImage &sourceImage, Qt::ImageC
         } else {
             QImage::Format opaqueFormat = QNativeImage::systemFormat();
             QImage::Format alphaFormat = QImage::Format_ARGB32_Premultiplied;
-
+#if defined(__SSE2__)
+            if (sourceImage.bitPlaneCount() > 32) {
+                opaqueFormat = QImage::Format_RGBX64;
+                alphaFormat = QImage::Format_RGBA64_Premultiplied;
+            }
+#endif
 #if !defined(__ARM_NEON__) && !defined(__SSE2__)
             switch (opaqueFormat) {
             case QImage::Format_RGB16:
diff --git a/src/gui/image/qpnghandler.cpp b/src/gui/image/qpnghandler.cpp
index 3c88d2e..0bf6c97 100644
--- a/src/gui/image/qpnghandler.cpp
+++ b/src/gui/image/qpnghandler.cpp
@@ -42,6 +42,7 @@
 #include <qtextcodec.h>
 #include <qvariant.h>
 #include <qvector.h>
+#include <qdebug.h>
 
 #ifdef QT_USE_BUNDLED_LIBPNG
 #include <../../3rdparty/libpng/png.h>
@@ -363,6 +364,24 @@ void setup_qt(QImage& image, png_structp png_ptr, png_infop info_ptr, QSize scal
            );
             i++;
         }
+        // Qt==ARGB==Big(ARGB)==Little(BGRA)
+        if (QSysInfo::ByteOrder == QSysInfo::LittleEndian) {
+            png_set_bgr(png_ptr);
+        }
+    } else if (bit_depth == 16 && (color_type & PNG_COLOR_MASK_COLOR)) {
+        QImage::Format format = QImage::Format_RGBA64;
+        if (!(color_type & PNG_COLOR_MASK_ALPHA) && !png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) {
+            png_set_filler(png_ptr, 0xffff, PNG_FILLER_AFTER);
+            format = QImage::Format_RGBX64;
+        }
+        if (image.size() != QSize(width, height) || image.format() != format) {
+            image = QImage(width, height, format);
+            if (image.isNull())
+                return;
+        }
+//         if (QSysInfo::ByteOrder == QSysInfo::LittleEndian)
+//             png_set_swap(png_ptr);
+        png_read_update_info(png_ptr, info_ptr);
     } else {
         // 32-bit
         if (bit_depth == 16)
@@ -399,12 +418,12 @@ void setup_qt(QImage& image, png_structp png_ptr, png_infop info_ptr, QSize scal
         if (QSysInfo::ByteOrder == QSysInfo::BigEndian)
             png_set_swap_alpha(png_ptr);
 
-        png_read_update_info(png_ptr, info_ptr);
-    }
+        // Qt==ARGB==Big(ARGB)==Little(BGRA)
+        if (QSysInfo::ByteOrder == QSysInfo::LittleEndian) {
+            png_set_bgr(png_ptr);
+        }
 
-    // Qt==ARGB==Big(ARGB)==Little(BGRA)
-    if (QSysInfo::ByteOrder == QSysInfo::LittleEndian) {
-        png_set_bgr(png_ptr);
+        png_read_update_info(png_ptr, info_ptr);
     }
 }
 
@@ -681,6 +700,10 @@ QImage::Format QPngHandlerPrivate::readImageFormat()
             png_read_update_info(png_ptr, info_ptr);
             png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, 0, 0, 0);
             format = bit_depth == 1 ? QImage::Format_Mono : QImage::Format_Indexed8;
+        } else if (bit_depth == 16 && (color_type & PNG_COLOR_MASK_COLOR)) {
+            format = QImage::Format_RGBA64;
+            if (!(color_type & PNG_COLOR_MASK_ALPHA) && !png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS))
+                format = QImage::Format_RGBX64;
         } else {
             // 32-bit
             if (bit_depth == 16)
@@ -815,6 +838,7 @@ bool QPNGImageWriter::writeImage(const QImage& image, int off_x, int off_y)
 bool Q_INTERNAL_WIN_NO_THROW QPNGImageWriter::writeImage(const QImage& image, volatile int quality_in, const QString &description,
                                  int off_x_in, int off_y_in)
 {
+    qDebug() << Q_FUNC_INFO;
     QPoint offset = image.offset();
     int off_x = off_x_in + offset.x();
     int off_y = off_y_in + offset.y();
@@ -866,8 +890,25 @@ bool Q_INTERNAL_WIN_NO_THROW QPNGImageWriter::writeImage(const QImage& image, vo
     else
         color_type = PNG_COLOR_TYPE_RGB;
 
+    int bpc = 0;
+    switch (image.format()) {
+    case QImage::Format_Mono:
+    case QImage::Format_MonoLSB:
+        bpc = 1;
+        break;
+    case QImage::Format_RGBX64:
+    case QImage::Format_RGBA64:
+    case QImage::Format_RGBA64_Premultiplied:
+        bpc = 16;
+        break;
+    default:
+        bpc = 8;
+        break;
+    }
+    qDebug() << Q_FUNC_INFO << bpc;
+
     png_set_IHDR(png_ptr, info_ptr, image.width(), image.height(),
-                 image.depth() == 1 ? 1 : 8, // per channel
+                 bpc, // per channel
                  color_type, 0, 0, 0);       // sets #channels
 
     if (gamma != 0.0) {
@@ -903,13 +944,33 @@ bool Q_INTERNAL_WIN_NO_THROW QPNGImageWriter::writeImage(const QImage& image, vo
     // Swap ARGB to RGBA (normal PNG format) before saving on
     // BigEndian machines
     if (QSysInfo::ByteOrder == QSysInfo::BigEndian) {
-        png_set_swap_alpha(png_ptr);
+        switch (image.format()) {
+        case QImage::Format_RGBX8888:
+        case QImage::Format_RGBA8888:
+        case QImage::Format_RGBX64:
+        case QImage::Format_RGBA64:
+        case QImage::Format_RGBA64_Premultiplied:
+            break;
+        default:
+            png_set_swap_alpha(png_ptr);
+        }
     }
 
     // Qt==ARGB==Big(ARGB)==Little(BGRA). But RGB888 is RGB regardless
-    if (QSysInfo::ByteOrder == QSysInfo::LittleEndian
-        && image.format() != QImage::Format_RGB888) {
-        png_set_bgr(png_ptr);
+    if (QSysInfo::ByteOrder == QSysInfo::LittleEndian) {
+        switch (image.format()) {
+        case QImage::Format_RGB888:
+        case QImage::Format_RGBX8888:
+        case QImage::Format_RGBA8888:
+            break;
+        case QImage::Format_RGBX64:
+        case QImage::Format_RGBA64:
+        case QImage::Format_RGBA64_Premultiplied:
+            png_set_swap(png_ptr);
+            break;
+        default:
+            png_set_bgr(png_ptr);
+        }
     }
 
     if (off_x || off_y) {
@@ -932,10 +993,20 @@ bool Q_INTERNAL_WIN_NO_THROW QPNGImageWriter::writeImage(const QImage& image, vo
     if (image.depth() != 1)
         png_set_packing(png_ptr);
 
-    if (color_type == PNG_COLOR_TYPE_RGB && image.format() != QImage::Format_RGB888)
-        png_set_filler(png_ptr, 0,
-            QSysInfo::ByteOrder == QSysInfo::BigEndian ?
-                PNG_FILLER_BEFORE : PNG_FILLER_AFTER);
+    if (color_type == PNG_COLOR_TYPE_RGB) {
+        switch (image.format()) {
+        case QImage::Format_RGB888:
+            break;
+        case QImage::Format_RGBX8888:
+        case QImage::Format_RGBX64:
+            png_set_filler(png_ptr, 0, PNG_FILLER_AFTER);
+            break;
+        default:
+            png_set_filler(png_ptr, 0,
+                QSysInfo::ByteOrder == QSysInfo::BigEndian ?
+                    PNG_FILLER_BEFORE : PNG_FILLER_AFTER);
+        }
+    }
 
     if (looping >= 0 && frames_written == 0) {
         uchar data[13] = "NETSCAPE2.0";
@@ -963,12 +1034,38 @@ bool Q_INTERNAL_WIN_NO_THROW QPNGImageWriter::writeImage(const QImage& image, vo
     case QImage::Format_RGB32:
     case QImage::Format_ARGB32:
     case QImage::Format_RGB888:
+    case QImage::Format_RGBX8888:
+    case QImage::Format_RGBA8888: {
+        png_bytep* row_pointers = new png_bytep[height];
+        for (int y=0; y<height; y++)
+            row_pointers[y] = const_cast<png_bytep>(image.constScanLine(y));
+        png_write_image(png_ptr, row_pointers);
+        delete [] row_pointers;
+        break;
+    }
+    case QImage::Format_RGBX64:
+    case QImage::Format_RGBA64://  {
+//        png_bytep* row_pointers = new png_bytep[height];
+//        for (int y=0; y<height; y++)
+//            row_pointers[y] = const_cast<png_bytep>(image.constScanLine(y));
+//        png_write_image(png_ptr, row_pointers);
+//        delete [] row_pointers;
+//        break;
+//    }
+    case QImage::Format_RGBA64_Premultiplied:
         {
-            png_bytep* row_pointers = new png_bytep[height];
-            for (int y=0; y<height; y++)
-                row_pointers[y] = const_cast<png_bytep>(image.constScanLine(y));
-            png_write_image(png_ptr, row_pointers);
-            delete [] row_pointers;
+            QImage row;
+            png_bytep row_pointers[1];
+            for (int y=0; y<height; y++) {
+                row = image.copy(0, y, width, 1).convertToFormat(QImage::Format_RGBA64);
+                // set_swap doesn't work so we need to fix 16bit endian ourselves
+                ushort* scanline = (ushort*)row.scanLine(0);
+                for(int x=0; x<width*4; x++) {
+                    scanline[x] = (scanline[x] >> 8) | (scanline[x] << 8);
+                }
+                row_pointers[0] = reinterpret_cast<png_bytep>(scanline);
+                png_write_rows(png_ptr, row_pointers, 1);
+            }
         }
         break;
     default:
diff --git a/src/gui/image/qppmhandler.cpp b/src/gui/image/qppmhandler.cpp
index 0f4256b..91ddaa7 100644
--- a/src/gui/image/qppmhandler.cpp
+++ b/src/gui/image/qppmhandler.cpp
@@ -259,6 +259,7 @@ static bool write_pbm_image(QIODevice *out, const QImage &sourceImage, const QBy
         switch (image.format()) {
         case QImage::Format_Mono:
         case QImage::Format_MonoLSB:
+        case QImage::Format_Grayscale8:
             image = image.convertToFormat(QImage::Format_Indexed8);
             break;
         case QImage::Format_Indexed8:
diff --git a/src/gui/painting/qdrawhelper.cpp b/src/gui/painting/qdrawhelper.cpp
index e46e997..76a5dfb 100644
--- a/src/gui/painting/qdrawhelper.cpp
+++ b/src/gui/painting/qdrawhelper.cpp
@@ -185,7 +185,7 @@ static const uint *QT_FASTCALL convertToRGB32(uint *buffer, const uint *src, int
 }
 
 template<QImage::Format Format>
-static const QRgba64 *QT_FASTCALL convertToRGB64(QRgba64 *buffer, const uint *src, int count,
+static const QRgba64 *QT_FASTCALL convertToRGB64(QRgba64 *buffer, const quint64 *src, int count,
                                                  const QPixelLayout *, const QRgb *)
 {
     Q_CONSTEXPR uint redMask = ((1 << redWidth<Format>()) - 1);
@@ -250,7 +250,7 @@ static const uint *QT_FASTCALL convertARGBPMToARGB32PM(uint *buffer, const uint
 }
 
 template<QImage::Format Format>
-static const QRgba64 *QT_FASTCALL convertARGBPMToARGB64PM(QRgba64 *buffer, const uint *src, int count,
+static const QRgba64 *QT_FASTCALL convertARGBPMToRGBA64PM(QRgba64 *buffer, const quint64 *src, int count,
                                                           const QPixelLayout *, const QRgb *)
 {
     Q_CONSTEXPR uint alphaMask = ((1 << alphaWidth<Format>()) - 1);
@@ -402,7 +402,7 @@ template<QImage::Format Format> Q_DECL_CONSTEXPR static inline QPixelLayout pixe
         convertARGBPMToARGB32PM<Format>,
         convertARGBPMFromARGB32PM<Format>,
         convertARGBPMFromRGB32<Format>,
-        convertARGBPMToARGB64PM<Format>
+        convertARGBPMToRGBA64PM<Format>
     };
 }
 
@@ -417,7 +417,7 @@ static const uint *QT_FASTCALL convertIndexedToARGB32PM(uint *buffer, const uint
     return buffer;
 }
 
-static const QRgba64 *QT_FASTCALL convertIndexedToARGB64PM(QRgba64 *buffer, const uint *src, int count,
+static const QRgba64 *QT_FASTCALL convertIndexedToARGB64PM(QRgba64 *buffer, const quint64 *src, int count,
                                                            const QPixelLayout *, const QRgb *clut)
 {
     for (int i = 0; i < count; ++i)
@@ -467,7 +467,7 @@ static const uint *QT_FASTCALL convertGrayscale8ToRGB32(uint *buffer, const uint
     return buffer;
 }
 
-static const QRgba64 *QT_FASTCALL convertAlpha8ToRGB64(QRgba64 *buffer, const uint *src, int count,
+static const QRgba64 *QT_FASTCALL convertAlpha8ToRGB64(QRgba64 *buffer, const quint64 *src, int count,
                                                        const QPixelLayout *, const QRgb *)
 {
     for (int i = 0; i < count; ++i)
@@ -475,7 +475,7 @@ static const QRgba64 *QT_FASTCALL convertAlpha8ToRGB64(QRgba64 *buffer, const ui
     return buffer;
 }
 
-static const QRgba64 *QT_FASTCALL convertGrayscale8ToRGB64(QRgba64 *buffer, const uint *src, int count,
+static const QRgba64 *QT_FASTCALL convertGrayscale8ToRGB64(QRgba64 *buffer, const quint64 *src, int count,
                                                            const QPixelLayout *, const QRgb *)
 {
     for (int i = 0; i < count; ++i)
@@ -501,7 +501,7 @@ static const uint *QT_FASTCALL convertRGBA8888PMFromARGB32PM(uint *buffer, const
 
 #ifdef __SSE2__
 template<bool RGBA, bool maskAlpha>
-static inline void qConvertARGB32PMToARGB64PM_sse2(QRgba64 *buffer, const uint *src, int count)
+static inline void qConvertARGB32PMToRGBA64PM_sse2(QRgba64 *buffer, const quint64 *src, int count)
 {
     const __m128i amask = _mm_set1_epi32(0xff000000);
     int i = 0;
@@ -513,7 +513,9 @@ static inline void qConvertARGB32PMToARGB64PM_sse2(QRgba64 *buffer, const uint *
         i++;
     }
     for (; i < count-3; i += 4) {
-        __m128i vs = _mm_loadu_si128((const __m128i*)src);
+        __m128 vs1 = _mm_loadu_ps((const float*)src);
+        __m128 vs2 = _mm_loadu_ps((const float*)(src + 2));
+        __m128i vs = _mm_castps_si128(_mm_shuffle_ps(vs1, vs2, _MM_SHUFFLE(2, 0, 2, 0)));
         if (maskAlpha)
             vs = _mm_or_si128(vs, amask);
         src += 4;
@@ -540,11 +542,11 @@ static inline void qConvertARGB32PMToARGB64PM_sse2(QRgba64 *buffer, const uint *
 }
 #endif
 
-static const QRgba64 *QT_FASTCALL convertRGB32ToRGB64(QRgba64 *buffer, const uint *src, int count,
+static const QRgba64 *QT_FASTCALL convertRGB32ToRGB64(QRgba64 *buffer, const quint64 *src, int count,
                                                       const QPixelLayout *, const QRgb *)
 {
 #ifdef __SSE2__
-    qConvertARGB32PMToARGB64PM_sse2<false, true>(buffer, src, count);
+    qConvertARGB32PMToRGBA64PM_sse2<false, true>(buffer, src, count);
 #else
     for (int i = 0; i < count; ++i)
         buffer[i] = QRgba64::fromArgb32(0xff000000 | src[i]);
@@ -552,11 +554,17 @@ static const QRgba64 *QT_FASTCALL convertRGB32ToRGB64(QRgba64 *buffer, const uin
     return buffer;
 }
 
-static const QRgba64 *QT_FASTCALL convertARGB32ToARGB64PM(QRgba64 *buffer, const uint *src, int count,
+static const QRgba64 *QT_FASTCALL convertRGB64ToRGB64(QRgba64 *, const quint64 *src, int,
+                                                      const QPixelLayout *, const QRgb *)
+{
+    return reinterpret_cast<const QRgba64*>(src);
+}
+
+static const QRgba64 *QT_FASTCALL convertARGB32ToRGBA64PM(QRgba64 *buffer, const quint64 *src, int count,
                                                           const QPixelLayout *, const QRgb *)
 {
 #ifdef __SSE2__
-    qConvertARGB32PMToARGB64PM_sse2<false, false>(buffer, src, count);
+    qConvertARGB32PMToRGBA64PM_sse2<false, false>(buffer, src, count);
     for (int i = 0; i < count; ++i)
         buffer[i] = buffer[i].premultiplied();
 #else
@@ -566,11 +574,19 @@ static const QRgba64 *QT_FASTCALL convertARGB32ToARGB64PM(QRgba64 *buffer, const
     return buffer;
 }
 
-static const QRgba64 *QT_FASTCALL convertARGB32PMToARGB64PM(QRgba64 *buffer, const uint *src, int count,
+static const QRgba64 *QT_FASTCALL convertRGBA64ToRGBA64PM(QRgba64 *buffer, const quint64 *src, int count,
+                                                          const QPixelLayout *, const QRgb *)
+{
+    for (int i = 0; i < count; ++i)
+        buffer[i] = QRgba64::fromRgba64(src[i]).premultiplied();
+    return buffer;
+}
+
+static const QRgba64 *QT_FASTCALL convertARGB32PMToRGBA64PM(QRgba64 *buffer, const quint64 *src, int count,
                                                             const QPixelLayout *, const QRgb *)
 {
 #ifdef __SSE2__
-    qConvertARGB32PMToARGB64PM_sse2<false, false>(buffer, src, count);
+    qConvertARGB32PMToRGBA64PM_sse2<false, false>(buffer, src, count);
 #else
     for (int i = 0; i < count; ++i)
         buffer[i] = QRgba64::fromArgb32(src[i]);
@@ -578,11 +594,11 @@ static const QRgba64 *QT_FASTCALL convertARGB32PMToARGB64PM(QRgba64 *buffer, con
     return buffer;
 }
 
-static const QRgba64 *QT_FASTCALL convertRGBA8888ToARGB64PM(QRgba64 *buffer, const uint *src, int count,
+static const QRgba64 *QT_FASTCALL convertRGBA8888ToRGBA64PM(QRgba64 *buffer, const quint64 *src, int count,
                                                             const QPixelLayout *, const QRgb *)
 {
 #ifdef __SSE2__
-    qConvertARGB32PMToARGB64PM_sse2<true, false>(buffer, src, count);
+    qConvertARGB32PMToRGBA64PM_sse2<true, false>(buffer, src, count);
     for (int i = 0; i < count; ++i)
         buffer[i] = buffer[i].premultiplied();
 #else
@@ -592,11 +608,11 @@ static const QRgba64 *QT_FASTCALL convertRGBA8888ToARGB64PM(QRgba64 *buffer, con
     return buffer;
 }
 
-static const QRgba64 *QT_FASTCALL convertRGBA8888PMToARGB64PM(QRgba64 *buffer, const uint *src, int count,
+static const QRgba64 *QT_FASTCALL convertRGBA8888PMToRGBA64PM(QRgba64 *buffer, const quint64 *src, int count,
                                                              const QPixelLayout *, const QRgb *)
 {
 #ifdef __SSE2__
-    qConvertARGB32PMToARGB64PM_sse2<true, false>(buffer, src, count);
+    qConvertARGB32PMToRGBA64PM_sse2<true, false>(buffer, src, count);
 #else
     for (int i = 0; i < count; ++i)
         buffer[i] = QRgba64::fromArgb32(RGBA2ARGB(src[i]));
@@ -639,7 +655,7 @@ static const uint *QT_FASTCALL convertA2RGB30PMToARGB32PM(uint *buffer, const ui
 
 #ifdef __SSE2__
 template<QtPixelOrder PixelOrder>
-static inline void qConvertA2RGB30PMToARGB64PM_sse2(QRgba64 *buffer, const uint *src, int count)
+static inline void qConvertA2RGB30PMToARGB64PM_sse2(QRgba64 *buffer, const quint64 *src, int count)
 {
     const __m128i rmask = _mm_set1_epi32(0x3ff00000);
     const __m128i gmask = _mm_set1_epi32(0x000ffc00);
@@ -651,7 +667,9 @@ static inline void qConvertA2RGB30PMToARGB64PM_sse2(QRgba64 *buffer, const uint
         i++;
     }
     for (; i < count-3; i += 4) {
-        __m128i vs = _mm_loadu_si128((const __m128i*)src);
+        __m128 vs1 = _mm_loadu_ps((const float*)src);
+        __m128 vs2 = _mm_loadu_ps((const float*)(src + 2));
+        __m128i vs = _mm_castps_si128(_mm_shuffle_ps(vs1, vs2, _MM_SHUFFLE(2, 0, 2, 0)));
         src += 4;
         __m128i va = _mm_srli_epi32(vs, 30);
         __m128i vr = _mm_and_si128(vs, rmask);
@@ -679,7 +697,7 @@ static inline void qConvertA2RGB30PMToARGB64PM_sse2(QRgba64 *buffer, const uint
 #endif
 
 template<QtPixelOrder PixelOrder>
-static const QRgba64 *QT_FASTCALL convertA2RGB30PMToARGB64PM(QRgba64 *buffer, const uint *src, int count,
+static const QRgba64 *QT_FASTCALL convertA2RGB30PMToARGB64PM(QRgba64 *buffer, const quint64 *src, int count,
                                                              const QPixelLayout *, const QRgb *)
 {
 #ifdef __SSE2__
@@ -781,6 +799,33 @@ inline uint QT_FASTCALL fetchPixel<QPixelLayout::BPP32>(const uchar *src, int in
     return reinterpret_cast<const uint *>(src)[index];
 }
 
+template <>
+inline uint QT_FASTCALL fetchPixel<QPixelLayout::BPP64>(const uchar *src, int index)
+{
+    // We have to do the conversion in fetch to fit into a 32bit uint
+    QRgba64 c = reinterpret_cast<const QRgba64 *>(src)[index];
+    return c.toArgb32();
+}
+
+template <QPixelLayout::BPP bpp>
+static quint64 QT_FASTCALL fetchPixel64(const uchar *src, int index)
+{
+    return fetchPixel<bpp>(src, index);
+}
+
+template <>
+quint64 QT_FASTCALL fetchPixel64<QPixelLayout::BPP64>(const uchar *src, int index)
+{
+    return reinterpret_cast<const quint64 *>(src)[index];
+}
+
+template <>
+quint64 QT_FASTCALL fetchPixel64<QPixelLayout::BPPNone>(const uchar *, int)
+{
+    Q_UNREACHABLE();
+    return 0;
+}
+
 template <QPixelLayout::BPP bpp>
 inline const uint *QT_FASTCALL fetchPixels(uint *buffer, const uchar *src, int index, int count)
 {
@@ -795,11 +840,71 @@ inline const uint *QT_FASTCALL fetchPixels<QPixelLayout::BPP32>(uint *, const uc
     return reinterpret_cast<const uint *>(src) + index;
 }
 
-template <QPixelLayout::BPP width> static
+template<bool RGBA>
+void qt_convertRGBA64ToARGB32(uint *dst, const QRgba64 *src, int count)
+{
+    int i = 0;
+#ifdef __SSE2__
+    if (((uintptr_t)dst & 0x7) && count > 0) {
+        *dst++ = (*src++).toArgb32();
+        i++;
+    }
+    const __m128i vhalf = _mm_set1_epi32(0x80);
+    const __m128i vzero = _mm_setzero_si128();
+    for (; i < count-1; i += 2) {
+        __m128i vs = _mm_loadu_si128((const __m128i*)src);
+        src += 2;
+        if (!RGBA) {
+            vs = _mm_shufflelo_epi16(vs, _MM_SHUFFLE(3, 0, 1, 2));
+            vs = _mm_shufflehi_epi16(vs, _MM_SHUFFLE(3, 0, 1, 2));
+        }
+        __m128i v1 = _mm_unpacklo_epi16(vs, vzero);
+        __m128i v2 = _mm_unpackhi_epi16(vs, vzero);
+        v1 = _mm_add_epi32(v1, vhalf);
+        v2 = _mm_add_epi32(v2, vhalf);
+        v1 = _mm_sub_epi32(v1, _mm_srli_epi32(v1, 8));
+        v2 = _mm_sub_epi32(v2, _mm_srli_epi32(v2, 8));
+        v1 = _mm_srli_epi32(v1, 8);
+        v2 = _mm_srli_epi32(v2, 8);
+        v1 = _mm_packs_epi32(v1, v2);
+        v1 = _mm_packus_epi16(v1, vzero);
+        _mm_storel_epi64((__m128i*)(dst), v1);
+        dst += 2;
+    }
+#endif
+    for (; i < count; i++)
+        *dst++ = (*src++).toArgb32();
+}
+template void qt_convertRGBA64ToARGB32<false>(uint *dst, const QRgba64 *src, int count);
+template void qt_convertRGBA64ToARGB32<true>(uint *dst, const QRgba64 *src, int count);
+
+template <>
+inline const uint *QT_FASTCALL fetchPixels<QPixelLayout::BPP64>(uint *buffer, const uchar *src, int index, int count)
+{
+    const QRgba64 *s = reinterpret_cast<const QRgba64 *>(src) + index;
+    qt_convertRGBA64ToARGB32<false>(buffer, s, count);
+    return buffer;
+}
+
+template <QPixelLayout::BPP bpp>
+const quint64 *QT_FASTCALL fetchPixels64(quint64 *buffer, const uchar *src, int index, int count)
+{
+    for (int i = 0; i < count; ++i)
+        buffer[i] = fetchPixel64<bpp>(src, index + i);
+    return buffer;
+}
+
+template <>
+const quint64 *QT_FASTCALL fetchPixels64<QPixelLayout::BPP64>(quint64 *, const uchar *src, int index, int)
+{
+    return reinterpret_cast<const quint64 *>(src) + index;
+}
+
+template <QPixelLayout::BPP width>
 void QT_FASTCALL storePixel(uchar *dest, int index, uint pixel);
 
 template <>
-inline void QT_FASTCALL storePixel<QPixelLayout::BPP1LSB>(uchar *dest, int index, uint pixel)
+void QT_FASTCALL storePixel<QPixelLayout::BPP1LSB>(uchar *dest, int index, uint pixel)
 {
     if (pixel)
         dest[index >> 3] |= 1 << (index & 7);
@@ -808,7 +913,7 @@ inline void QT_FASTCALL storePixel<QPixelLayout::BPP1LSB>(uchar *dest, int index
 }
 
 template <>
-inline void QT_FASTCALL storePixel<QPixelLayout::BPP1MSB>(uchar *dest, int index, uint pixel)
+void QT_FASTCALL storePixel<QPixelLayout::BPP1MSB>(uchar *dest, int index, uint pixel)
 {
     if (pixel)
         dest[index >> 3] |= 1 << (~index & 7);
@@ -817,23 +922,42 @@ inline void QT_FASTCALL storePixel<QPixelLayout::BPP1MSB>(uchar *dest, int index
 }
 
 template <>
-inline void QT_FASTCALL storePixel<QPixelLayout::BPP8>(uchar *dest, int index, uint pixel)
+void QT_FASTCALL storePixel<QPixelLayout::BPP8>(uchar *dest, int index, uint pixel)
 {
     dest[index] = uchar(pixel);
 }
 
 template <>
-inline void QT_FASTCALL storePixel<QPixelLayout::BPP16>(uchar *dest, int index, uint pixel)
+void QT_FASTCALL storePixel<QPixelLayout::BPP16>(uchar *dest, int index, uint pixel)
 {
     reinterpret_cast<quint16 *>(dest)[index] = quint16(pixel);
 }
 
 template <>
-inline void QT_FASTCALL storePixel<QPixelLayout::BPP24>(uchar *dest, int index, uint pixel)
+void QT_FASTCALL storePixel<QPixelLayout::BPP24>(uchar *dest, int index, uint pixel)
 {
     reinterpret_cast<quint24 *>(dest)[index] = quint24(pixel);
 }
 
+template <>
+void QT_FASTCALL storePixel<QPixelLayout::BPP32>(uchar *dest, int index, uint pixel)
+{
+    reinterpret_cast<uint *>(dest)[index] = pixel;
+}
+
+template <>
+void QT_FASTCALL storePixel<QPixelLayout::BPP64>(uchar *dest, int index, uint pixel)
+{
+    QRgba64 p = QRgba64::fromArgb32(pixel);
+    reinterpret_cast<quint64 *>(dest)[index] = p;
+}
+
+template <QPixelLayout::BPP width>
+static void QT_FASTCALL storePixel64(uchar *dest, int index, quint64 pixel)
+{
+    storePixel<width>(dest, index, pixel);
+}
+
 template <QPixelLayout::BPP width>
 inline void QT_FASTCALL storePixels(uchar *dest, const uint *src, int index, int count)
 {
@@ -847,6 +971,19 @@ inline void QT_FASTCALL storePixels<QPixelLayout::BPP32>(uchar *dest, const uint
     memcpy(reinterpret_cast<uint *>(dest) + index, src, count * sizeof(uint));
 }
 
+template <QPixelLayout::BPP width>
+static void QT_FASTCALL storePixels64(uchar *dest, const quint64 *src, int index, int count)
+{
+    for (int i = 0; i < count; ++i)
+        storePixel64<width>(dest, index + i, src[i]);
+}
+
+template <>
+void QT_FASTCALL storePixels64<QPixelLayout::BPP64>(uchar *dest, const quint64 *src, int index, int count)
+{
+    memcpy(reinterpret_cast<quint64 *>(dest) + index, src, count * sizeof(quint64));
+}
+
 // Note:
 // convertToArgb32() assumes that no color channel is less than 4 bits.
 // convertFromArgb32() assumes that no color channel is more than 8 bits.
@@ -859,8 +996,8 @@ QPixelLayout qPixelLayouts[QImage::NImageFormats] = {
     // Technically using convertPassThrough to convert from ARGB32PM to RGB32 is wrong,
     // but everywhere this generic conversion would be wrong is currently overloaded.
     { 8, 16, 8,  8, 8,  0, 0,  0, false, QPixelLayout::BPP32, convertPassThrough, convertPassThrough, convertPassThrough, convertRGB32ToRGB64 }, // Format_RGB32
-    { 8, 16, 8,  8, 8,  0, 8, 24, false, QPixelLayout::BPP32, convertARGB32ToARGB32PM, convertARGB32FromARGB32PM, convertPassThrough, convertARGB32ToARGB64PM }, // Format_ARGB32
-    { 8, 16, 8,  8, 8,  0, 8, 24,  true, QPixelLayout::BPP32, convertPassThrough, convertPassThrough, convertPassThrough, convertARGB32PMToARGB64PM }, // Format_ARGB32_Premultiplied
+    { 8, 16, 8,  8, 8,  0, 8, 24, false, QPixelLayout::BPP32, convertARGB32ToARGB32PM, convertARGB32FromARGB32PM, convertPassThrough, convertARGB32ToRGBA64PM }, // Format_ARGB32
+    { 8, 16, 8,  8, 8,  0, 8, 24,  true, QPixelLayout::BPP32, convertPassThrough, convertPassThrough, convertPassThrough, convertARGB32PMToRGBA64PM }, // Format_ARGB32_Premultiplied
 #ifdef Q_COMPILER_CONSTEXPR
     pixelLayoutRGB<QImage::Format_RGB16>(),
     pixelLayoutARGBPM<QImage::Format_ARGB8565_Premultiplied>(),
@@ -882,7 +1019,7 @@ QPixelLayout qPixelLayouts[QImage::NImageFormats] = {
       convertARGBPMToARGB32PM<QImage::Format_ARGB8565_Premultiplied>,
       convertARGBPMFromARGB32PM<QImage::Format_ARGB8565_Premultiplied>,
       convertARGBPMFromRGB32<QImage::Format_ARGB8565_Premultiplied>,
-      convertARGBPMToARGB64PM<QImage::Format_ARGB8565_Premultiplied>,
+      convertARGBPMToRGBA64PM<QImage::Format_ARGB8565_Premultiplied>,
     },
     { 6, 12, 6,  6, 6,  0, 0,  0, false, QPixelLayout::BPP24,
       convertToRGB32<QImage::Format_RGB666>,
@@ -894,7 +1031,7 @@ QPixelLayout qPixelLayouts[QImage::NImageFormats] = {
       convertARGBPMToARGB32PM<QImage::Format_ARGB6666_Premultiplied>,
       convertARGBPMFromARGB32PM<QImage::Format_ARGB6666_Premultiplied>,
       convertARGBPMFromRGB32<QImage::Format_ARGB6666_Premultiplied>,
-      convertARGBPMToARGB64PM<QImage::Format_ARGB6666_Premultiplied>,
+      convertARGBPMToRGBA64PM<QImage::Format_ARGB6666_Premultiplied>,
     },
     { 5, 10, 5,  5, 5,  0, 0,  0, false, QPixelLayout::BPP16,
       convertToRGB32<QImage::Format_RGB555>,
@@ -906,7 +1043,7 @@ QPixelLayout qPixelLayouts[QImage::NImageFormats] = {
       convertARGBPMToARGB32PM<QImage::Format_ARGB8555_Premultiplied>,
       convertARGBPMFromARGB32PM<QImage::Format_ARGB8555_Premultiplied>,
       convertARGBPMFromRGB32<QImage::Format_ARGB8555_Premultiplied>,
-      convertARGBPMToARGB64PM<QImage::Format_ARGB8555_Premultiplied>,
+      convertARGBPMToRGBA64PM<QImage::Format_ARGB8555_Premultiplied>,
     },
     { 8, 16, 8,  8, 8,  0, 0,  0, false, QPixelLayout::BPP24,
       convertToRGB32<QImage::Format_RGB888>,
@@ -924,56 +1061,96 @@ QPixelLayout qPixelLayouts[QImage::NImageFormats] = {
       convertARGBPMToARGB32PM<QImage::Format_ARGB4444_Premultiplied>,
       convertARGBPMFromARGB32PM<QImage::Format_ARGB4444_Premultiplied>,
       convertARGBPMFromRGB32<QImage::Format_ARGB4444_Premultiplied>,
-      convertARGBPMToARGB64PM<QImage::Format_ARGB4444_Premultiplied>,
+      convertARGBPMToRGBA64PM<QImage::Format_ARGB4444_Premultiplied>,
     },
 #endif
 #if Q_BYTE_ORDER == Q_BIG_ENDIAN
-    { 8, 24, 8, 16, 8,  8, 0,  0, false, QPixelLayout::BPP32, convertRGBA8888PMToARGB32PM, convertRGBXFromARGB32PM, convertRGBXFromRGB32, convertRGBA8888PMToARGB64PM }, // Format_RGBX8888
-    { 8, 24, 8, 16, 8,  8, 8,  0, false, QPixelLayout::BPP32, convertRGBA8888ToARGB32PM, convertRGBA8888FromARGB32PM, convertRGBXFromRGB32, convertRGBA8888ToARGB64PM }, // Format_RGBA8888
-    { 8, 24, 8, 16, 8,  8, 8,  0,  true, QPixelLayout::BPP32, convertRGBA8888PMToARGB32PM, convertRGBA8888PMFromARGB32PM, convertRGBXFromRGB32, convertRGBA8888PMToARGB64PM}, // Format_RGBA8888_Premultiplied
+    { 8, 24, 8, 16, 8,  8, 0,  0, false, QPixelLayout::BPP32, convertRGBA8888PMToARGB32PM, convertRGBXFromARGB32PM, convertRGBXFromRGB32, convertRGBA8888PMToRGBA64PM }, // Format_RGBX8888
+    { 8, 24, 8, 16, 8,  8, 8,  0, false, QPixelLayout::BPP32, convertRGBA8888ToARGB32PM, convertRGBA8888FromARGB32PM, convertRGBXFromRGB32, convertRGBA8888ToRGBA64PM }, // Format_RGBA8888
+    { 8, 24, 8, 16, 8,  8, 8,  0,  true, QPixelLayout::BPP32, convertRGBA8888PMToARGB32PM, convertRGBA8888PMFromARGB32PM, convertRGBXFromRGB32, convertRGBA8888PMToRGBA64PM}, // Format_RGBA8888_Premultiplied
 #else
-    { 8,  0, 8,  8, 8, 16, 0, 24, false, QPixelLayout::BPP32, convertRGBA8888PMToARGB32PM, convertRGBXFromARGB32PM, convertRGBXFromRGB32, convertRGBA8888PMToARGB64PM }, // Format_RGBX8888
-    { 8,  0, 8,  8, 8, 16, 8, 24, false, QPixelLayout::BPP32, convertRGBA8888ToARGB32PM, convertRGBA8888FromARGB32PM, convertRGBXFromRGB32, convertRGBA8888ToARGB64PM }, // Format_RGBA8888 (ABGR32)
-    { 8,  0, 8,  8, 8, 16, 8, 24,  true, QPixelLayout::BPP32, convertRGBA8888PMToARGB32PM, convertRGBA8888PMFromARGB32PM, convertRGBXFromRGB32, convertRGBA8888PMToARGB64PM },  // Format_RGBA8888_Premultiplied
+    { 8,  0, 8,  8, 8, 16, 0, 24, false, QPixelLayout::BPP32, convertRGBA8888PMToARGB32PM, convertRGBXFromARGB32PM, convertRGBXFromRGB32, convertRGBA8888PMToRGBA64PM }, // Format_RGBX8888
+    { 8,  0, 8,  8, 8, 16, 8, 24, false, QPixelLayout::BPP32, convertRGBA8888ToARGB32PM, convertRGBA8888FromARGB32PM, convertRGBXFromRGB32, convertRGBA8888ToRGBA64PM }, // Format_RGBA8888 (ABGR32)
+    { 8,  0, 8,  8, 8, 16, 8, 24,  true, QPixelLayout::BPP32, convertRGBA8888PMToARGB32PM, convertRGBA8888PMFromARGB32PM, convertRGBXFromRGB32, convertRGBA8888PMToRGBA64PM },  // Format_RGBA8888_Premultiplied
 #endif
     { 10,  20, 10,  10, 10, 0, 0, 30, false, QPixelLayout::BPP32, convertA2RGB30PMToARGB32PM<PixelOrderBGR>, convertRGB30FromARGB32PM<PixelOrderBGR>, convertRGB30FromRGB32<PixelOrderBGR>, convertA2RGB30PMToARGB64PM<PixelOrderBGR> }, // Format_BGR30
     { 10,  20, 10,  10, 10, 0, 2, 30,  true, QPixelLayout::BPP32, convertA2RGB30PMToARGB32PM<PixelOrderBGR>, convertA2RGB30PMFromARGB32PM<PixelOrderBGR>, convertRGB30FromRGB32<PixelOrderBGR>, convertA2RGB30PMToARGB64PM<PixelOrderBGR> },  // Format_A2BGR30_Premultiplied
     { 10,  0, 10,  10, 10, 20, 0, 30, false, QPixelLayout::BPP32, convertA2RGB30PMToARGB32PM<PixelOrderRGB>, convertRGB30FromARGB32PM<PixelOrderRGB>, convertRGB30FromRGB32<PixelOrderRGB>, convertA2RGB30PMToARGB64PM<PixelOrderRGB> }, // Format_RGB30
     { 10,  0, 10,  10, 10, 20, 2, 30,  true, QPixelLayout::BPP32, convertA2RGB30PMToARGB32PM<PixelOrderRGB>, convertA2RGB30PMFromARGB32PM<PixelOrderRGB>, convertRGB30FromRGB32<PixelOrderRGB>, convertA2RGB30PMToARGB64PM<PixelOrderRGB> },  // Format_A2RGB30_Premultiplied
     { 0, 0,  0, 0,  0, 0,  8, 0, false, QPixelLayout::BPP8, convertAlpha8ToRGB32, convertAlpha8FromARGB32PM, 0, convertAlpha8ToRGB64 }, // Format_Alpha8
-    { 0, 0,  0, 0,  0, 0,  0, 0, false, QPixelLayout::BPP8, convertGrayscale8ToRGB32, convertGrayscale8FromARGB32PM, convertGrayscale8FromRGB32, convertGrayscale8ToRGB64 } // Format_Grayscale8
+    { 0, 0,  0, 0,  0, 0,  0, 0, false, QPixelLayout::BPP8, convertGrayscale8ToRGB32, convertGrayscale8FromARGB32PM, convertGrayscale8FromRGB32, convertGrayscale8ToRGB64 }, // Format_Grayscale8
+    // The BPP64 formats are converted on fetch and therefore like the (A)RGB32 after fetch.
+    { 8, 16, 8, 8, 8, 0, 0, 24, false, QPixelLayout::BPP64, convertPassThrough, convertPassThrough, convertPassThrough, convertRGB64ToRGB64 }, // Format_RGBX64
+    { 8, 16, 8, 8, 8, 0, 8, 24, false, QPixelLayout::BPP64, convertARGB32ToARGB32PM, convertARGB32FromARGB32PM, convertPassThrough, convertRGBA64ToRGBA64PM }, // Format_RGBA64
+    { 8, 16, 8, 8, 8, 0, 8, 24,  true, QPixelLayout::BPP64, convertPassThrough, convertPassThrough, convertPassThrough, convertRGB64ToRGB64 } // Format_RGB64_Premultiplied
+};
+
+const FetchPixelsFunc qFetchPixels[QPixelLayout::BPPCount] = {
+    0, // BPPNone
+    fetchPixels<QPixelLayout::BPP1MSB>,
+    fetchPixels<QPixelLayout::BPP1LSB>,
+    fetchPixels<QPixelLayout::BPP8>,
+    fetchPixels<QPixelLayout::BPP16>,
+    fetchPixels<QPixelLayout::BPP24>,
+    fetchPixels<QPixelLayout::BPP32>,
+    fetchPixels<QPixelLayout::BPP64>
 };
 
-FetchPixelsFunc qFetchPixels[QPixelLayout::BPPCount] = {
+const StorePixelsFunc qStorePixels[QPixelLayout::BPPCount] = {
     0, // BPPNone
-    fetchPixels<QPixelLayout::BPP1MSB>, // BPP1MSB
-    fetchPixels<QPixelLayout::BPP1LSB>, // BPP1LSB
-    fetchPixels<QPixelLayout::BPP8>, // BPP8
-    fetchPixels<QPixelLayout::BPP16>, // BPP16
-    fetchPixels<QPixelLayout::BPP24>, // BPP24
-    fetchPixels<QPixelLayout::BPP32> // BPP32
+    storePixels<QPixelLayout::BPP1MSB>,
+    storePixels<QPixelLayout::BPP1LSB>,
+    storePixels<QPixelLayout::BPP8>,
+    storePixels<QPixelLayout::BPP16>,
+    storePixels<QPixelLayout::BPP24>,
+    storePixels<QPixelLayout::BPP32>,
+    storePixels<QPixelLayout::BPP64>
 };
 
-StorePixelsFunc qStorePixels[QPixelLayout::BPPCount] = {
+const FetchPixelsFunc64 qFetchPixels64[QPixelLayout::BPPCount] = {
     0, // BPPNone
-    storePixels<QPixelLayout::BPP1MSB>, // BPP1MSB
-    storePixels<QPixelLayout::BPP1LSB>, // BPP1LSB
-    storePixels<QPixelLayout::BPP8>, // BPP8
-    storePixels<QPixelLayout::BPP16>, // BPP16
-    storePixels<QPixelLayout::BPP24>, // BPP24
-    storePixels<QPixelLayout::BPP32> // BPP32
+    fetchPixels64<QPixelLayout::BPP1MSB>,
+    fetchPixels64<QPixelLayout::BPP1LSB>,
+    fetchPixels64<QPixelLayout::BPP8>,
+    fetchPixels64<QPixelLayout::BPP16>,
+    fetchPixels64<QPixelLayout::BPP24>,
+    fetchPixels64<QPixelLayout::BPP32>,
+    fetchPixels64<QPixelLayout::BPP64>
+};
+
+const StorePixelsFunc64 qStorePixels64[QPixelLayout::BPPCount] = {
+    0, // BPPNone
+    storePixels64<QPixelLayout::BPP1MSB>,
+    storePixels64<QPixelLayout::BPP1LSB>,
+    storePixels64<QPixelLayout::BPP8>,
+    storePixels64<QPixelLayout::BPP16>,
+    storePixels64<QPixelLayout::BPP24>,
+    storePixels64<QPixelLayout::BPP64>
 };
 
 typedef uint (QT_FASTCALL *FetchPixelFunc)(const uchar *src, int index);
+typedef quint64 (QT_FASTCALL *FetchPixelFunc64)(const uchar *src, int index);
 
-FetchPixelFunc qFetchPixel[QPixelLayout::BPPCount] = {
+const FetchPixelFunc qFetchPixel[QPixelLayout::BPPCount] = {
     0, // BPPNone
-    fetchPixel<QPixelLayout::BPP1MSB>, // BPP1MSB
-    fetchPixel<QPixelLayout::BPP1LSB>, // BPP1LSB
-    fetchPixel<QPixelLayout::BPP8>, // BPP8
-    fetchPixel<QPixelLayout::BPP16>, // BPP16
-    fetchPixel<QPixelLayout::BPP24>, // BPP24
-    fetchPixel<QPixelLayout::BPP32> // BPP32
+    fetchPixel<QPixelLayout::BPP1MSB>,
+    fetchPixel<QPixelLayout::BPP1LSB>,
+    fetchPixel<QPixelLayout::BPP8>,
+    fetchPixel<QPixelLayout::BPP16>,
+    fetchPixel<QPixelLayout::BPP24>,
+    fetchPixel<QPixelLayout::BPP32>,
+    fetchPixel<QPixelLayout::BPP64>,
+};
+
+const FetchPixelFunc64 qFetchPixel64[QPixelLayout::BPPCount] = {
+    0, // BPPNone
+    fetchPixel64<QPixelLayout::BPP1MSB>,
+    fetchPixel64<QPixelLayout::BPP1LSB>,
+    fetchPixel64<QPixelLayout::BPP8>,
+    fetchPixel64<QPixelLayout::BPP16>,
+    fetchPixel64<QPixelLayout::BPP24>,
+    fetchPixel64<QPixelLayout::BPP32>,
+    fetchPixel64<QPixelLayout::BPP64>,
 };
 
 /*
@@ -1030,16 +1207,13 @@ static uint *QT_FASTCALL destFetch(uint *buffer, QRasterBuffer *rasterBuffer, in
 static QRgba64 *QT_FASTCALL destFetch64(QRgba64 *buffer, QRasterBuffer *rasterBuffer, int x, int y, int length)
 {
     const QPixelLayout *layout = &qPixelLayouts[rasterBuffer->format];
-    uint buffer32[buffer_size];
-    const uint *ptr = qFetchPixels[layout->bpp](buffer32, rasterBuffer->scanLine(y), x, length);
-    return const_cast<QRgba64 *>(layout->convertToARGB64PM(buffer, ptr, length, layout, 0));
+    const quint64 *ptr = qFetchPixels64[layout->bpp]((quint64*)buffer, rasterBuffer->scanLine(y), x, length);
+    return const_cast<QRgba64 *>(layout->convertToRGBA64PM(buffer, ptr, length, layout, 0));
 }
 
-static QRgba64 *QT_FASTCALL destFetch64uint32(QRgba64 *buffer, QRasterBuffer *rasterBuffer, int x, int y, int length)
+static QRgba64 * QT_FASTCALL destFetchRGB64(QRgba64 *, QRasterBuffer *rasterBuffer, int x, int y, int)
 {
-    const QPixelLayout *layout = &qPixelLayouts[rasterBuffer->format];
-    const uint *src = ((const uint *)rasterBuffer->scanLine(y)) + x;
-    return const_cast<QRgba64 *>(layout->convertToARGB64PM(buffer, src, length, layout, 0));
+    return (QRgba64 *)rasterBuffer->scanLine(y) + x;
 }
 
 static DestFetchProc destFetchProc[QImage::NImageFormats] =
@@ -1069,6 +1243,9 @@ static DestFetchProc destFetchProc[QImage::NImageFormats] =
     destFetch,          // Format_A2RGB30_Premultiplied
     destFetch,          // Format_Alpha8
     destFetch,          // Format_Grayscale8
+    destFetch,          // Format_RGBX64
+    destFetch,          // Format_RGBA64
+    destFetch,          // Format_RGBA64_Premultiplied
 };
 
 static DestFetchProc64 destFetchProc64[QImage::NImageFormats] =
@@ -1077,9 +1254,9 @@ static DestFetchProc64 destFetchProc64[QImage::NImageFormats] =
     destFetch64,        // Format_Mono,
     destFetch64,        // Format_MonoLSB
     0,                  // Format_Indexed8
-    destFetch64uint32,  // Format_RGB32
-    destFetch64uint32,  // Format_ARGB32,
-    destFetch64uint32,  // Format_ARGB32_Premultiplied
+    destFetch64,        // Format_RGB32
+    destFetch64,        // Format_ARGB32,
+    destFetch64,        // Format_ARGB32_Premultiplied
     destFetch64,        // Format_RGB16
     destFetch64,        // Format_ARGB8565_Premultiplied
     destFetch64,        // Format_RGB666
@@ -1089,15 +1266,18 @@ static DestFetchProc64 destFetchProc64[QImage::NImageFormats] =
     destFetch64,        // Format_RGB888
     destFetch64,        // Format_RGB444
     destFetch64,        // Format_ARGB4444_Premultiplied
-    destFetch64uint32,  // Format_RGBX8888
-    destFetch64uint32,  // Format_RGBA8888
-    destFetch64uint32,  // Format_RGBA8888_Premultiplied
-    destFetch64uint32,  // Format_BGR30
-    destFetch64uint32,  // Format_A2BGR30_Premultiplied
-    destFetch64uint32,  // Format_RGB30
-    destFetch64uint32,  // Format_A2RGB30_Premultiplied
+    destFetch64,        // Format_RGBX8888
+    destFetch64,        // Format_RGBA8888
+    destFetch64,        // Format_RGBA8888_Premultiplied
+    destFetch64,        // Format_BGR30
+    destFetch64,        // Format_A2BGR30_Premultiplied
+    destFetch64,        // Format_RGB30
+    destFetch64,        // Format_A2RGB30_Premultiplied
     destFetch64,        // Format_Alpha8
     destFetch64,        // Format_Grayscale8
+    destFetchRGB64,     // Format_RGBX64
+    destFetch64,        // Format_RGBA64
+    destFetchRGB64,     // Format_RGBA64_Premultiplied
 };
 
 /*
@@ -1216,13 +1396,6 @@ static void QT_FASTCALL destStore(QRasterBuffer *rasterBuffer, int x, int y, con
     }
 }
 
-static void QT_FASTCALL convertFromRgb64(uint *dest, const QRgba64 *src, int length)
-{
-    for (int i = 0; i < length; ++i) {
-        dest[i] = src[i].toArgb32();
-    }
-}
-
 static void QT_FASTCALL destStore64(QRasterBuffer *rasterBuffer, int x, int y, const QRgba64 *buffer, int length)
 {
     uint buf[buffer_size];
@@ -1232,7 +1405,7 @@ static void QT_FASTCALL destStore64(QRasterBuffer *rasterBuffer, int x, int y, c
     while (length) {
         int l = qMin(length, buffer_size);
         const uint *ptr = 0;
-        convertFromRgb64(buf, buffer, l);
+        qt_convertRGBA64ToARGB32<false>(buf, buffer, length);
         if (!layout->premultiplied && !layout->alphaWidth)
             ptr = layout->convertFromRGB32(buf, buf, l, layout, 0);
         else
@@ -1307,6 +1480,14 @@ static void QT_FASTCALL destStore64RGB30(QRasterBuffer *rasterBuffer, int x, int
 #endif
 }
 
+static void QT_FASTCALL destStore64RGBA64(QRasterBuffer *rasterBuffer, int x, int y, const QRgba64 *buffer, int length)
+{
+    QRgba64 *dest = reinterpret_cast<QRgba64*>(rasterBuffer->scanLine(y)) + x;
+    for (int i = 0; i < length; ++i) {
+        dest[i] = buffer[i].unpremultiplied();
+    }
+}
+
 static DestStoreProc destStoreProc[QImage::NImageFormats] =
 {
     0,                  // Format_Invalid
@@ -1334,6 +1515,9 @@ static DestStoreProc destStoreProc[QImage::NImageFormats] =
     destStore,          // Format_A2RGB30_Premultiplied
     destStore,          // Format_Alpha8
     destStore,          // Format_Grayscale8
+    destStore,          // Format_RGBX64
+    destStore,          // Format_RGBA64
+    destStore,          // Format_RGBA64_Premultiplied
 };
 
 static DestStoreProc64 destStoreProc64[QImage::NImageFormats] =
@@ -1363,6 +1547,9 @@ static DestStoreProc64 destStoreProc64[QImage::NImageFormats] =
     destStore64RGB30<PixelOrderRGB>,        // Format_A2RGB30_Premultiplied
     destStore64,        // Format_Alpha8
     destStore64,        // Format_Grayscale8
+    0,                  // Format_RGBX64
+    destStore64RGBA64,  // Format_RGBA64
+    0                   // Format_RGBA64_Premultiplied
 };
 
 /*
@@ -1425,14 +1612,15 @@ static const QRgba64 *QT_FASTCALL fetchUntransformed64(QRgba64 *buffer, const Op
 {
     const QPixelLayout *layout = &qPixelLayouts[data->texture.format];
     const QRgb *clut = data->texture.colorTable ? data->texture.colorTable->constData() : 0;
-    if (layout->bpp != QPixelLayout::BPP32) {
-        uint buffer32[buffer_size];
-        const uint *ptr = qFetchPixels[layout->bpp](buffer32, data->texture.scanLine(y), x, length);
-        return layout->convertToARGB64PM(buffer, ptr, length, layout, clut);
-    } else {
-        const uint *src = (const uint *)data->texture.scanLine(y) + x;
-        return layout->convertToARGB64PM(buffer, src, length, layout, clut);
-    }
+    const quint64 *ptr = qFetchPixels64[layout->bpp](reinterpret_cast<quint64*>(buffer), data->texture.scanLine(y), x, length);
+    return layout->convertToRGBA64PM(buffer, ptr, length, layout, clut);
+}
+
+static const QRgba64 *QT_FASTCALL fetchUntransformedRGBA64PM(QRgba64 *, const Operator *,
+                                                             const QSpanData *data, int y, int x, int)
+{
+    const uchar *scanLine = data->texture.scanLine(y);
+    return ((const QRgba64 *)scanLine) + x;
 }
 
 // blendType is either BlendTransformed or BlendTransformedTiled
@@ -1613,10 +1801,9 @@ static const QRgba64 *QT_FASTCALL fetchTransformed64(QRgba64 *buffer, const Oper
     const qreal cy = y + qreal(0.5);
 
     const QPixelLayout *layout = &qPixelLayouts[data->texture.format];
-    FetchPixelFunc fetch = qFetchPixel[layout->bpp];
+    FetchPixelFunc64 fetch = qFetchPixel64[layout->bpp];
     const QRgb *clut = data->texture.colorTable ? data->texture.colorTable->constData() : 0;
 
-    uint buffer32[buffer_size];
     QRgba64 *b = buffer;
     if (data->fast_matrix) {
         // The increment pr x in the scanline
@@ -1631,7 +1818,7 @@ static const QRgba64 *QT_FASTCALL fetchTransformed64(QRgba64 *buffer, const Oper
         int i = 0,  j = 0;
         while (i < length) {
             if (j == buffer_size) {
-                layout->convertToARGB64PM(b, buffer32, buffer_size, layout, clut);
+                layout->convertToRGBA64PM(b, (const quint64*)b, buffer_size, layout, clut);
                 b += buffer_size;
                 j = 0;
             }
@@ -1647,14 +1834,14 @@ static const QRgba64 *QT_FASTCALL fetchTransformed64(QRgba64 *buffer, const Oper
                 px = qBound(0, px, image_width - 1);
                 py = qBound(0, py, image_height - 1);
             }
-            buffer32[j] = fetch(data->texture.scanLine(py), px);
+            b[j] = fetch(data->texture.scanLine(py), px);
 
             fx += fdx;
             fy += fdy;
             ++i; ++j;
         }
         if (j > 0) {
-            layout->convertToARGB64PM(b, buffer32, j, layout, clut);
+            layout->convertToRGBA64PM(b, (const quint64*)b, j, layout, clut);
             b += j;
         }
     } else {
@@ -1669,7 +1856,7 @@ static const QRgba64 *QT_FASTCALL fetchTransformed64(QRgba64 *buffer, const Oper
         int i = 0,  j = 0;
         while (i < length) {
             if (j == buffer_size) {
-                layout->convertToARGB64PM(b, buffer32, buffer_size, layout, clut);
+                layout->convertToRGBA64PM(b, (const quint64*)b, buffer_size, layout, clut);
                 b += buffer_size;
                 j = 0;
             }
@@ -1688,7 +1875,7 @@ static const QRgba64 *QT_FASTCALL fetchTransformed64(QRgba64 *buffer, const Oper
                 px = qBound(0, px, image_width - 1);
                 py = qBound(0, py, image_height - 1);
             }
-            buffer32[j] = fetch(data->texture.scanLine(py), px);
+            b[j] = fetch(data->texture.scanLine(py), px);
 
             fx += fdx;
             fy += fdy;
@@ -1700,7 +1887,7 @@ static const QRgba64 *QT_FASTCALL fetchTransformed64(QRgba64 *buffer, const Oper
             ++i; ++j;
         }
         if (j > 0) {
-            layout->convertToARGB64PM(b, buffer32, j, layout, clut);
+            layout->convertToRGBA64PM(b, (const quint64*)b, j, layout, clut);
             b += j;
         }
     }
@@ -1798,7 +1985,7 @@ static inline uint interpolate_4_pixels_16(uint tl, uint tr, uint bl, uint br, i
 #endif
 
 #if defined(__SSE2__)
-static inline QRgba64 interpolate_4_pixels_rgb64(QRgba64 t[], QRgba64 b[], uint distx, uint disty)
+static inline QRgba64 interpolate_4_pixels_rgb64(const QRgba64 t[], const QRgba64 b[], uint distx, uint disty)
 {
     const __m128i vdistx = _mm_shufflelo_epi16(_mm_cvtsi32_si128(distx), _MM_SHUFFLE(0, 0, 0, 0));
     const __m128i vidistx = _mm_shufflelo_epi16(_mm_cvtsi32_si128(0x10000 - distx), _MM_SHUFFLE(0, 0, 0, 0));
@@ -1821,7 +2008,7 @@ static inline QRgba64 interpolate_4_pixels_rgb64(QRgba64 t[], QRgba64 b[], uint
 #endif
 }
 #else
-static inline QRgba64 interpolate_4_pixels_rgb64(QRgba64 t[], QRgba64 b[], uint distx, uint disty)
+static inline QRgba64 interpolate_4_pixels_rgb64(const QRgba64 t[], const QRgba64 b[], uint distx, uint disty)
 {
     const uint dx = distx>>8;
     const uint dy = disty>>8;
@@ -2718,32 +2905,39 @@ static const uint *QT_FASTCALL fetchTransformedBilinear(uint *buffer, const Oper
     return buffer;
 }
 
-template<TextureBlendType blendType>
-static const QRgba64 *QT_FASTCALL fetchTransformedBilinear64(QRgba64 *buffer, const Operator *,
-                                                             const QSpanData *data, int y, int x, int length)
+template<TextureBlendType blendType, QPixelLayout::BPP BPP>
+static const QRgba64 *QT_FASTCALL fetchTransformedBilinear64_template(QRgba64 *buffer, const QSpanData *data,
+                                                                      int y, int x, int length)
 {
-    const QPixelLayout *layout = &qPixelLayouts[data->texture.format];
-    const QRgb *clut = data->texture.colorTable ? data->texture.colorTable->constData() : 0;
+    const QTextureData &texture = data->texture;
+    const QPixelLayout *layout = &qPixelLayouts[texture.format];
+    const QRgb *clut = texture.colorTable ? texture.colorTable->constData() : 0;
 
-    int image_width = data->texture.width;
-    int image_height = data->texture.height;
+    const int image_width = data->texture.width;
+    const int image_height = data->texture.height;
 
-    int image_x1 = data->texture.x1;
-    int image_y1 = data->texture.y1;
-    int image_x2 = data->texture.x2 - 1;
-    int image_y2 = data->texture.y2 - 1;
+    const int image_x1 = texture.x1;
+    const int image_y1 = texture.y1;
+    const int image_x2 = texture.x2 - 1;
+    const int image_y2 = texture.y2 - 1;
 
     const qreal cx = x + qreal(0.5);
     const qreal cy = y + qreal(0.5);
 
-    const qreal fdx = data->m11;
-    const qreal fdy = data->m12;
-    const qreal fdw = data->m13;
+    const FetchPixelFunc64 fetch = (BPP == QPixelLayout::BPPNone) ? qFetchPixel64[layout->bpp] : fetchPixel64<BPP>;
+
+    QRgba64 buf1[buffer_size];
+    QRgba64 buf2[buffer_size];
+    quint64 *sbuf1 = reinterpret_cast<quint64*>(buf1);
+    quint64 *sbuf2 = reinterpret_cast<quint64*>(buf2);
+
+    QRgba64 *end = buffer + length;
+    QRgba64 *b = buffer;
 
     if (data->fast_matrix) {
         // The increment pr x in the scanline
-        int fdx = (int)(data->m11 * fixed_scale);
-        int fdy = (int)(data->m12 * fixed_scale);
+        const int fdx = (int)(data->m11 * fixed_scale);
+        const int fdy = (int)(data->m12 * fixed_scale);
 
         int fx = int((data->m21 * cy + data->m11 * cx + data->dx) * fixed_scale);
         int fy = int((data->m22 * cy + data->m12 * cx + data->dy) * fixed_scale);
@@ -2755,16 +2949,10 @@ static const QRgba64 *QT_FASTCALL fetchTransformedBilinear64(QRgba64 *buffer, co
             int y1 = (fy >> 16);
             int y2;
             fetchTransformedBilinear_pixelBounds<blendType>(image_height, image_y1, image_y2, y1, y2);
-            const uchar *s1 = data->texture.scanLine(y1);
-            const uchar *s2 = data->texture.scanLine(y2);
+            const uchar *s1 = texture.scanLine(y1);
+            const uchar *s2 = texture.scanLine(y2);
 
-            FetchPixelFunc fetch = qFetchPixel[layout->bpp];
-            uint sbuf1[buffer_size];
-            uint sbuf2[buffer_size];
-            QRgba64 buf1[buffer_size];
-            QRgba64 buf2[buffer_size];
-            QRgba64 *b = buffer;
-            while (length) {
+            while (b < end) {
                 int len = qMin(length, buffer_size / 2);
                 int fracX = fx;
                 int i = 0;
@@ -2772,17 +2960,17 @@ static const QRgba64 *QT_FASTCALL fetchTransformedBilinear64(QRgba64 *buffer, co
 #if defined(__SSE2__)
                 const __m128i vdy = _mm_set1_epi16(disty);
                 const __m128i vidy = _mm_set1_epi16(0x10000 - disty);
-                if (blendType != BlendTransformedBilinearTiled && layout->bpp == QPixelLayout::BPP32) {
+                if (blendType != BlendTransformedBilinearTiled) {
                     for (; i < len; ++i) {
                         int x1 = (fx >> 16);
                         int x2;
                         fetchTransformedBilinear_pixelBounds<blendType>(image_width, image_x1, image_x2, x1, x2);
                         if (x1 != x2)
                             break;
-                        sbuf1[i * 2 + 0] = ((const uint*)s1)[x1];
-                        sbuf1[i * 2 + 1] = ((const uint*)s1)[x2];
-                        sbuf2[i * 2 + 0] = ((const uint*)s2)[x1];
-                        sbuf2[i * 2 + 1] = ((const uint*)s2)[x2];
+                        sbuf1[i * 2 + 0] = fetch(s1, x1);
+                        sbuf1[i * 2 + 1] = fetch(s1, x2);
+                        sbuf2[i * 2 + 0] = fetch(s2, x1);
+                        sbuf2[i * 2 + 1] = fetch(s2, x2);
                         fx += fdx;
                     }
 
@@ -2790,25 +2978,25 @@ static const QRgba64 *QT_FASTCALL fetchTransformedBilinear64(QRgba64 *buffer, co
                     __m128i v_fx = _mm_setr_epi32(fx, fx + fdx, fx + fdx + fdx, fx + fdx + fdx + fdx);
                     for (; i < len-3; i+=4) {
                         int offset = _mm_extract_epi16(v_fx, 1);
-                        sbuf1[i * 2 + 0] = ((const uint*)s1)[offset];
-                        sbuf1[i * 2 + 1] = ((const uint*)s1)[offset + 1];
-                        sbuf2[i * 2 + 0] = ((const uint*)s2)[offset];
-                        sbuf2[i * 2 + 1] = ((const uint*)s2)[offset + 1];
+                        sbuf1[i * 2 + 0] = fetch(s1, offset);
+                        sbuf1[i * 2 + 1] = fetch(s1, offset + 1);
+                        sbuf2[i * 2 + 0] = fetch(s2, offset);
+                        sbuf2[i * 2 + 1] = fetch(s2, offset + 1);
                         offset = _mm_extract_epi16(v_fx, 3);
-                        sbuf1[i * 2 + 2] = ((const uint*)s1)[offset];
-                        sbuf1[i * 2 + 3] = ((const uint*)s1)[offset + 1];
-                        sbuf2[i * 2 + 2] = ((const uint*)s2)[offset];
-                        sbuf2[i * 2 + 3] = ((const uint*)s2)[offset + 1];
+                        sbuf1[i * 2 + 2] = fetch(s1, offset);
+                        sbuf1[i * 2 + 3] = fetch(s1, offset + 1);
+                        sbuf2[i * 2 + 2] = fetch(s2, offset);
+                        sbuf2[i * 2 + 3] = fetch(s2, offset + 1);
                         offset = _mm_extract_epi16(v_fx, 5);
-                        sbuf1[i * 2 + 4] = ((const uint*)s1)[offset];
-                        sbuf1[i * 2 + 5] = ((const uint*)s1)[offset + 1];
-                        sbuf2[i * 2 + 4] = ((const uint*)s2)[offset];
-                        sbuf2[i * 2 + 5] = ((const uint*)s2)[offset + 1];
+                        sbuf1[i * 2 + 4] = fetch(s1, offset);
+                        sbuf1[i * 2 + 5] = fetch(s1, offset + 1);
+                        sbuf2[i * 2 + 4] = fetch(s2, offset);
+                        sbuf2[i * 2 + 5] = fetch(s2, offset + 1);
                         offset = _mm_extract_epi16(v_fx, 7);
-                        sbuf1[i * 2 + 6] = ((const uint*)s1)[offset];
-                        sbuf1[i * 2 + 7] = ((const uint*)s1)[offset + 1];
-                        sbuf2[i * 2 + 6] = ((const uint*)s2)[offset];
-                        sbuf2[i * 2 + 7] = ((const uint*)s2)[offset + 1];
+                        sbuf1[i * 2 + 6] = fetch(s1, offset);
+                        sbuf1[i * 2 + 7] = fetch(s1, offset + 1);
+                        sbuf2[i * 2 + 6] = fetch(s2, offset);
+                        sbuf2[i * 2 + 7] = fetch(s2, offset + 1);
                         v_fx = _mm_add_epi32(v_fx, v_fdx);
                     }
                     fx = _mm_cvtsi128_si32(v_fx);
@@ -2819,24 +3007,16 @@ static const QRgba64 *QT_FASTCALL fetchTransformedBilinear64(QRgba64 *buffer, co
                     int x2;
                     fetchTransformedBilinear_pixelBounds<blendType>(image_width, image_x1, image_x2, x1, x2);
 
-                    if (layout->bpp == QPixelLayout::BPP32) {
-                        sbuf1[i * 2 + 0] = ((const uint*)s1)[x1];
-                        sbuf1[i * 2 + 1] = ((const uint*)s1)[x2];
-                        sbuf2[i * 2 + 0] = ((const uint*)s2)[x1];
-                        sbuf2[i * 2 + 1] = ((const uint*)s2)[x2];
-
-                    } else {
-                        sbuf1[i * 2 + 0] = fetch(s1, x1);
-                        sbuf1[i * 2 + 1] = fetch(s1, x2);
-                        sbuf2[i * 2 + 0] = fetch(s2, x1);
-                        sbuf2[i * 2 + 1] = fetch(s2, x2);
-                    }
+                    sbuf1[i * 2 + 0] = fetch(s1, x1);
+                    sbuf1[i * 2 + 1] = fetch(s1, x2);
+                    sbuf2[i * 2 + 0] = fetch(s2, x1);
+                    sbuf2[i * 2 + 1] = fetch(s2, x2);
 
                     fx += fdx;
                 }
-                layout->convertToARGB64PM(buf1, sbuf1, len * 2, layout, clut);
+                layout->convertToRGBA64PM(buf1, sbuf1, len * 2, layout, clut);
                 if (disty)
-                    layout->convertToARGB64PM(buf2, sbuf2, len * 2, layout, clut);
+                    layout->convertToRGBA64PM(buf2, sbuf2, len * 2, layout, clut);
 
                 for (int i = 0; i < len; ++i) {
                     int distx = (fracX & 0x0000ffff);
@@ -2862,21 +3042,13 @@ static const QRgba64 *QT_FASTCALL fetchTransformedBilinear64(QRgba64 *buffer, co
                 b += len;
             }
         } else { //rotation
-            FetchPixelFunc fetch = qFetchPixel[layout->bpp];
-            uint sbuf1[buffer_size];
-            uint sbuf2[buffer_size];
-            QRgba64 buf1[buffer_size];
-            QRgba64 buf2[buffer_size];
-            QRgba64 *end = buffer + length;
-            QRgba64 *b = buffer;
-
             while (b < end) {
                 int len = qMin(length, buffer_size / 2);
                 int fracX = fx;
                 int fracY = fy;
                 int i = 0;
 #if defined(__SSE2__)
-                if (blendType != BlendTransformedBilinearTiled && layout->bpp == QPixelLayout::BPP32) {
+                if (blendType != BlendTransformedBilinearTiled && BPP >= QPixelLayout::BPP32) {
                     for (; i < len; ++i) {
                         int x1 = (fx >> 16);
                         int x2;
@@ -2886,12 +3058,12 @@ static const QRgba64 *QT_FASTCALL fetchTransformedBilinear64(QRgba64 *buffer, co
                         fetchTransformedBilinear_pixelBounds<blendType>(image_height, image_y1, image_y2, y1, y2);
                         if (x1 != x2 && y1 != y2)
                             break;
-                        const uchar *s1 = data->texture.scanLine(y1);
-                        const uchar *s2 = data->texture.scanLine(y2);
-                        sbuf1[i * 2 + 0] = ((const uint*)s1)[x1];
-                        sbuf1[i * 2 + 1] = ((const uint*)s1)[x2];
-                        sbuf2[i * 2 + 0] = ((const uint*)s2)[x1];
-                        sbuf2[i * 2 + 1] = ((const uint*)s2)[x2];
+                        const uchar *s1 = texture.scanLine(y1);
+                        const uchar *s2 = texture.scanLine(y2);
+                        sbuf1[i * 2 + 0] = fetch(s1, x1);
+                        sbuf1[i * 2 + 1] = fetch(s1, x2);
+                        sbuf2[i * 2 + 0] = fetch(s2, x1);
+                        sbuf2[i * 2 + 1] = fetch(s2, x2);
                         fx += fdx;
                         fy += fdy;
                     }
@@ -2900,10 +3072,11 @@ static const QRgba64 *QT_FASTCALL fetchTransformedBilinear64(QRgba64 *buffer, co
                     const __m128i v_fdy = _mm_set1_epi32(fdy*4);
                     __m128i v_fx = _mm_setr_epi32(fx, fx + fdx, fx + fdx + fdx, fx + fdx + fdx + fdx);
                     __m128i v_fy = _mm_setr_epi32(fy, fy + fdy, fy + fdy + fdy, fy + fdy + fdy + fdy);
-                    const int bytesPerLine = data->texture.bytesPerLine;
-                    const uchar *s1 = data->texture.imageData;
+                    const int bytesPerLine = texture.bytesPerLine;
+                    const uchar *s1 = texture.imageData;
                     const uchar *s2 = s1 + bytesPerLine;
-                    const __m128i vbpl = _mm_shufflelo_epi16(_mm_cvtsi32_si128(bytesPerLine/4), _MM_SHUFFLE(0, 0, 0, 0));
+                    const int pbl = BPP == QPixelLayout::BPP32 ? bytesPerLine/4 : bytesPerLine/8;
+                    const __m128i vbpl = _mm_shufflelo_epi16(_mm_cvtsi32_si128(pbl), _MM_SHUFFLE(0, 0, 0, 0));
                     for (; i < len-3; i+=4) {
                         if (fdx > 0 && (short)_mm_extract_epi16(v_fx, 7) >= image_x2)
                             break;
@@ -2918,26 +3091,25 @@ static const QRgba64 *QT_FASTCALL fetchTransformedBilinear64(QRgba64 *buffer, co
                         voffset = _mm_add_epi32(voffset, _mm_srli_epi32(v_fx, 16));
 
                         int offset = _mm_cvtsi128_si32(voffset); voffset = _mm_srli_si128(voffset, 4);
-                        sbuf1[i * 2 + 0] = ((const uint*)s1)[offset];
-                        sbuf1[i * 2 + 1] = ((const uint*)s1)[offset + 1];
-                        sbuf2[i * 2 + 0] = ((const uint*)s2)[offset];
-                        sbuf2[i * 2 + 1] = ((const uint*)s2)[offset + 1];
+                        sbuf1[i * 2 + 0] = fetch(s1, offset);
+                        sbuf1[i * 2 + 1] = fetch(s1, offset + 1);
+                        sbuf2[i * 2 + 0] = fetch(s2, offset);
+                        sbuf2[i * 2 + 1] = fetch(s2, offset + 1);
                         offset = _mm_cvtsi128_si32(voffset); voffset = _mm_srli_si128(voffset, 4);
-                        sbuf1[i * 2 + 2] = ((const uint*)s1)[offset];
-                        sbuf1[i * 2 + 3] = ((const uint*)s1)[offset + 1];
-                        sbuf2[i * 2 + 2] = ((const uint*)s2)[offset];
-                        sbuf2[i * 2 + 3] = ((const uint*)s2)[offset + 1];
+                        sbuf1[i * 2 + 2] = fetch(s1, offset);
+                        sbuf1[i * 2 + 3] = fetch(s1, offset + 1);
+                        sbuf2[i * 2 + 2] = fetch(s2, offset);
+                        sbuf2[i * 2 + 3] = fetch(s2, offset + 1);
                         offset = _mm_cvtsi128_si32(voffset); voffset = _mm_srli_si128(voffset, 4);
-                        sbuf1[i * 2 + 4] = ((const uint*)s1)[offset];
-                        sbuf1[i * 2 + 5] = ((const uint*)s1)[offset + 1];
-                        sbuf2[i * 2 + 4] = ((const uint*)s2)[offset];
-                        sbuf2[i * 2 + 5] = ((const uint*)s2)[offset + 1];
+                        sbuf1[i * 2 + 4] = fetch(s1, offset);
+                        sbuf1[i * 2 + 5] = fetch(s1, offset + 1);
+                        sbuf2[i * 2 + 4] = fetch(s2, offset);
+                        sbuf2[i * 2 + 5] = fetch(s2, offset + 1);
                         offset = _mm_cvtsi128_si32(voffset);
-                        sbuf1[i * 2 + 6] = ((const uint*)s1)[offset];
-                        sbuf1[i * 2 + 7] = ((const uint*)s1)[offset + 1];
-                        sbuf2[i * 2 + 6] = ((const uint*)s2)[offset];
-                        sbuf2[i * 2 + 7] = ((const uint*)s2)[offset + 1];
-
+                        sbuf1[i * 2 + 6] = fetch(s1, offset);
+                        sbuf1[i * 2 + 7] = fetch(s1, offset + 1);
+                        sbuf2[i * 2 + 6] = fetch(s2, offset);
+                        sbuf2[i * 2 + 7] = fetch(s2, offset + 1);
                         v_fx = _mm_add_epi32(v_fx, v_fdx);
                         v_fy = _mm_add_epi32(v_fy, v_fdy);
                     }
@@ -2953,27 +3125,19 @@ static const QRgba64 *QT_FASTCALL fetchTransformedBilinear64(QRgba64 *buffer, co
                     fetchTransformedBilinear_pixelBounds<blendType>(image_width, image_x1, image_x2, x1, x2);
                     fetchTransformedBilinear_pixelBounds<blendType>(image_height, image_y1, image_y2, y1, y2);
 
-                    const uchar *s1 = data->texture.scanLine(y1);
-                    const uchar *s2 = data->texture.scanLine(y2);
+                    const uchar *s1 = texture.scanLine(y1);
+                    const uchar *s2 = texture.scanLine(y2);
 
-                    if (layout->bpp == QPixelLayout::BPP32) {
-                        sbuf1[i * 2 + 0] = ((const uint*)s1)[x1];
-                        sbuf1[i * 2 + 1] = ((const uint*)s1)[x2];
-                        sbuf2[i * 2 + 0] = ((const uint*)s2)[x1];
-                        sbuf2[i * 2 + 1] = ((const uint*)s2)[x2];
-
-                    } else {
-                        sbuf1[i * 2 + 0] = fetch(s1, x1);
-                        sbuf1[i * 2 + 1] = fetch(s1, x2);
-                        sbuf2[i * 2 + 0] = fetch(s2, x1);
-                        sbuf2[i * 2 + 1] = fetch(s2, x2);
-                    }
+                    sbuf1[i * 2 + 0] = fetch(s1, x1);
+                    sbuf1[i * 2 + 1] = fetch(s1, x2);
+                    sbuf2[i * 2 + 0] = fetch(s2, x1);
+                    sbuf2[i * 2 + 1] = fetch(s2, x2);
 
                     fx += fdx;
                     fy += fdy;
                 }
-                layout->convertToARGB64PM(buf1, sbuf1, len * 2, layout, clut);
-                layout->convertToARGB64PM(buf2, sbuf2, len * 2, layout, clut);
+                layout->convertToRGBA64PM(buf1, sbuf1, len * 2, layout, clut);
+                layout->convertToRGBA64PM(buf2, sbuf2, len * 2, layout, clut);
 
                 for (int i = 0; i < len; ++i) {
                     int distx = (fracX & 0x0000ffff);
@@ -2987,22 +3151,18 @@ static const QRgba64 *QT_FASTCALL fetchTransformedBilinear64(QRgba64 *buffer, co
                 b += len;
             }
         }
-    } else {
+    } else { // !(data->fast_matrix)
+        const qreal fdx = data->m11;
+        const qreal fdy = data->m12;
+        const qreal fdw = data->m13;
         qreal fx = data->m21 * cy + data->m11 * cx + data->dx;
         qreal fy = data->m22 * cy + data->m12 * cx + data->dy;
         qreal fw = data->m23 * cy + data->m13 * cx + data->m33;
 
-        FetchPixelFunc fetch = qFetchPixel[layout->bpp];
-        uint sbuf1[buffer_size];
-        uint sbuf2[buffer_size];
-        QRgba64 buf1[buffer_size];
-        QRgba64 buf2[buffer_size];
-        QRgba64 *b = buffer;
-
         int distxs[buffer_size / 2];
         int distys[buffer_size / 2];
 
-        while (length) {
+        while (b < end) {
             int len = qMin(length, buffer_size / 2);
             for (int i = 0; i < len; ++i) {
                 const qreal iw = fw == 0 ? 1 : 1 / fw;
@@ -3020,21 +3180,13 @@ static const QRgba64 *QT_FASTCALL fetchTransformedBilinear64(QRgba64 *buffer, co
                 fetchTransformedBilinear_pixelBounds<blendType>(image_width, image_x1, image_x2, x1, x2);
                 fetchTransformedBilinear_pixelBounds<blendType>(image_height, image_y1, image_y2, y1, y2);
 
-                const uchar *s1 = data->texture.scanLine(y1);
-                const uchar *s2 = data->texture.scanLine(y2);
+                const uchar *s1 = texture.scanLine(y1);
+                const uchar *s2 = texture.scanLine(y2);
 
-                if (layout->bpp == QPixelLayout::BPP32) {
-                    sbuf1[i * 2 + 0] = ((const uint*)s1)[x1];
-                    sbuf1[i * 2 + 1] = ((const uint*)s1)[x2];
-                    sbuf2[i * 2 + 0] = ((const uint*)s2)[x1];
-                    sbuf2[i * 2 + 1] = ((const uint*)s2)[x2];
-
-                } else {
-                    sbuf1[i * 2 + 0] = fetch(s1, x1);
-                    sbuf1[i * 2 + 1] = fetch(s1, x2);
-                    sbuf2[i * 2 + 0] = fetch(s2, x1);
-                    sbuf2[i * 2 + 1] = fetch(s2, x2);
-                }
+                sbuf1[i * 2 + 0] = fetch(s1, x1);
+                sbuf1[i * 2 + 1] = fetch(s1, x2);
+                sbuf2[i * 2 + 0] = fetch(s2, x1);
+                sbuf2[i * 2 + 1] = fetch(s2, x2);
 
                 fx += fdx;
                 fy += fdy;
@@ -3044,8 +3196,8 @@ static const QRgba64 *QT_FASTCALL fetchTransformedBilinear64(QRgba64 *buffer, co
                     fw += fdw;
             }
 
-            layout->convertToARGB64PM(buf1, sbuf1, len * 2, layout, clut);
-            layout->convertToARGB64PM(buf2, sbuf2, len * 2, layout, clut);
+            layout->convertToRGBA64PM(buf1, sbuf1, len * 2, layout, clut);
+            layout->convertToRGBA64PM(buf2, sbuf2, len * 2, layout, clut);
 
             for (int i = 0; i < len; ++i) {
                 int distx = distxs[i];
@@ -3057,10 +3209,26 @@ static const QRgba64 *QT_FASTCALL fetchTransformedBilinear64(QRgba64 *buffer, co
             b += len;
         }
     }
-
     return buffer;
 }
 
+template<TextureBlendType blendType>
+static const QRgba64 *QT_FASTCALL fetchTransformedBilinear64(QRgba64 *buffer, const Operator *,
+                                                             const QSpanData *data, int y, int x, int length)
+{
+    // This trick makes it possible for the compiler to inline fetchPixel
+    switch (qPixelLayouts[data->texture.format].bpp) {
+    case QPixelLayout::BPP32:
+        return fetchTransformedBilinear64_template<blendType, QPixelLayout::BPP32>(buffer, data, y, x, length);
+    case QPixelLayout::BPP64:
+        return fetchTransformedBilinear64_template<blendType, QPixelLayout::BPP64>(buffer, data, y, x, length);
+    default:
+        break;
+    }
+    // Use a generic fallback so we don't generate too many specialized versions.
+    return fetchTransformedBilinear64_template<blendType, QPixelLayout::BPPNone>(buffer, data, y, x, length);
+}
+
 static SourceFetchProc sourceFetch[NBlendTypes][QImage::NImageFormats] = {
     // Untransformed
     {
@@ -3089,6 +3257,9 @@ static SourceFetchProc sourceFetch[NBlendTypes][QImage::NImageFormats] = {
         fetchUntransformed,         // Format_A2RGB30_Premultiplied
         fetchUntransformed,         // Alpha8
         fetchUntransformed,         // Grayscale8
+        fetchUntransformed,
+        fetchUntransformed,
+        fetchUntransformed,
     },
     // Tiled
     {
@@ -3117,6 +3288,9 @@ static SourceFetchProc sourceFetch[NBlendTypes][QImage::NImageFormats] = {
         fetchUntransformed,         // A2RGB30_Premultiplied
         fetchUntransformed,         // Alpha8
         fetchUntransformed,         // Grayscale8
+        fetchUntransformed,
+        fetchUntransformed,
+        fetchUntransformed,
     },
     // Transformed
     {
@@ -3145,6 +3319,9 @@ static SourceFetchProc sourceFetch[NBlendTypes][QImage::NImageFormats] = {
         fetchTransformed<BlendTransformed>,         // A2RGB30_Premultiplied
         fetchTransformed<BlendTransformed>,         // Alpah8
         fetchTransformed<BlendTransformed>,         // Grayscale8
+        fetchTransformed<BlendTransformed>,         // RGBX64
+        fetchTransformed<BlendTransformed>,         // RGBA64
+        fetchTransformed<BlendTransformed>,         // RGBA64_Premultiplied
     },
     {
         0, // TransformedTiled
@@ -3172,6 +3349,9 @@ static SourceFetchProc sourceFetch[NBlendTypes][QImage::NImageFormats] = {
         fetchTransformed<BlendTransformedTiled>,            // A2RGB30_Premultiplied
         fetchTransformed<BlendTransformedTiled>,            // Alpha8
         fetchTransformed<BlendTransformedTiled>,            // Grayscale8
+        fetchTransformed<BlendTransformedTiled>,            // RGBX64
+        fetchTransformed<BlendTransformedTiled>,            // RGBA64
+        fetchTransformed<BlendTransformedTiled>,            // RGBA64_Premultiplied
     },
     {
         0, // Bilinear
@@ -3199,6 +3379,9 @@ static SourceFetchProc sourceFetch[NBlendTypes][QImage::NImageFormats] = {
         fetchTransformedBilinear<BlendTransformedBilinear>,         // A2RGB30_Premultiplied
         fetchTransformedBilinear<BlendTransformedBilinear>,         // Alpha8
         fetchTransformedBilinear<BlendTransformedBilinear>,         // Grayscale8
+        fetchTransformedBilinear<BlendTransformedBilinear>,         // RGBX64
+        fetchTransformedBilinear<BlendTransformedBilinear>,         // RGBA64
+        fetchTransformedBilinear<BlendTransformedBilinear>,         // RGBA64_Premultiplied
     },
     {
         0, // BilinearTiled
@@ -3226,6 +3409,9 @@ static SourceFetchProc sourceFetch[NBlendTypes][QImage::NImageFormats] = {
         fetchTransformedBilinear<BlendTransformedBilinearTiled>,            // A2RGB30_Premultiplied
         fetchTransformedBilinear<BlendTransformedBilinearTiled>,            // Alpha8
         fetchTransformedBilinear<BlendTransformedBilinearTiled>,            // Grayscale8
+        fetchTransformedBilinear<BlendTransformedBilinearTiled>,            // RGBX64
+        fetchTransformedBilinear<BlendTransformedBilinearTiled>,            // RGBA64
+        fetchTransformedBilinear<BlendTransformedBilinearTiled>,            // RGBA64_Premultiplied
     },
 };
 
@@ -3257,6 +3443,9 @@ static SourceFetchProc64 sourceFetch64[NBlendTypes][QImage::NImageFormats] = {
         fetchUntransformed64,         // Format_A2RGB30_Premultiplied
         fetchUntransformed64,         // Alpha8
         fetchUntransformed64,         // Grayscale8
+        fetchUntransformedRGBA64PM,   // RGBX64
+        fetchUntransformed64,         // RGBA64
+        fetchUntransformedRGBA64PM,   // RGBA64_Premultiplied
     },
     // Tiled
     {
@@ -3285,6 +3474,9 @@ static SourceFetchProc64 sourceFetch64[NBlendTypes][QImage::NImageFormats] = {
         fetchUntransformed64,         // A2RGB30_Premultiplied
         fetchUntransformed64,         // Alpha8
         fetchUntransformed64,         // Grayscale8
+        fetchUntransformedRGBA64PM,   // RGBX64
+        fetchUntransformed64,         // RGBA64
+        fetchUntransformedRGBA64PM,   // RGBA64_Premultiplied
     },
     // Transformed
     {
@@ -3313,6 +3505,9 @@ static SourceFetchProc64 sourceFetch64[NBlendTypes][QImage::NImageFormats] = {
         fetchTransformed64<BlendTransformed>,         // A2RGB30_Premultiplied
         fetchTransformed64<BlendTransformed>,         // Alpah8
         fetchTransformed64<BlendTransformed>,         // Grayscale8
+        fetchTransformed64<BlendTransformed>,
+        fetchTransformed64<BlendTransformed>,
+        fetchTransformed64<BlendTransformed>,
     },
     {
         0, // TransformedTiled
@@ -3340,6 +3535,9 @@ static SourceFetchProc64 sourceFetch64[NBlendTypes][QImage::NImageFormats] = {
         fetchTransformed64<BlendTransformedTiled>,            // A2RGB30_Premultiplied
         fetchTransformed64<BlendTransformedTiled>,            // Alpha8
         fetchTransformed64<BlendTransformedTiled>,            // Grayscale8
+        fetchTransformed64<BlendTransformedTiled>,
+        fetchTransformed64<BlendTransformedTiled>,
+        fetchTransformed64<BlendTransformedTiled>,
     },
     {
         0, // Bilinear
@@ -3367,6 +3565,9 @@ static SourceFetchProc64 sourceFetch64[NBlendTypes][QImage::NImageFormats] = {
         fetchTransformedBilinear64<BlendTransformedBilinear>,         // A2RGB30_Premultiplied
         fetchTransformedBilinear64<BlendTransformedBilinear>,         // Alpha8
         fetchTransformedBilinear64<BlendTransformedBilinear>,         // Grayscale8
+        fetchTransformedBilinear64<BlendTransformedBilinear>,
+        fetchTransformedBilinear64<BlendTransformedBilinear>,
+        fetchTransformedBilinear64<BlendTransformedBilinear>,
     },
     {
         0, // BilinearTiled
@@ -3394,6 +3595,9 @@ static SourceFetchProc64 sourceFetch64[NBlendTypes][QImage::NImageFormats] = {
         fetchTransformedBilinear64<BlendTransformedBilinearTiled>,            // A2RGB30_Premultiplied
         fetchTransformedBilinear64<BlendTransformedBilinearTiled>,            // Alpha8
         fetchTransformedBilinear64<BlendTransformedBilinearTiled>,            // Grayscale8
+        fetchTransformedBilinear64<BlendTransformedBilinearTiled>,
+        fetchTransformedBilinear64<BlendTransformedBilinearTiled>,
+        fetchTransformedBilinear64<BlendTransformedBilinearTiled>,
     },
 };
 
@@ -3866,7 +4070,8 @@ void blend_color_generic_rgb64(int count, const QSpan *spans, void *userData)
             int l = qMin(buffer_size, length);
             QRgba64 *dest = op.destFetch64(buffer, data->rasterBuffer, x, spans->y, l);
             op.funcSolid64(dest, l, color, spans->coverage);
-            op.destStore64(data->rasterBuffer, x, spans->y, dest, l);
+            if (op.destStore64)
+                op.destStore64(data->rasterBuffer, x, spans->y, dest, l);
             length -= l;
             x += l;
         }
@@ -4055,7 +4260,7 @@ public:
 
     bool isSupported() const
     {
-        return op.func64 && op.destFetch64 && op.destStore64;
+        return op.func64 && op.destFetch64;
     }
 
     const QRgba64 *fetch(int x, int y, int len)
@@ -4071,7 +4276,8 @@ public:
 
     void store(int x, int y, int len)
     {
-        op.destStore64(data->rasterBuffer, x, y, dest, len);
+        if (op.destStore64)
+            op.destStore64(data->rasterBuffer, x, y, dest, len);
     }
 };
 
@@ -4178,7 +4384,8 @@ static void blend_untransformed_generic_rgb64(int count, const QSpan *spans, voi
                     const QRgba64 *src = op.srcFetch64(src_buffer, &op, data, sy, sx, l);
                     QRgba64 *dest = op.destFetch64(buffer, data->rasterBuffer, x, spans->y, l);
                     op.func64(dest, src, l, coverage);
-                    op.destStore64(data->rasterBuffer, x, spans->y, dest, l);
+                    if (op.destStore64)
+                        op.destStore64(data->rasterBuffer, x, spans->y, dest, l);
                     x += l;
                     sx += l;
                     length -= l;
@@ -4422,7 +4629,8 @@ static void blend_tiled_generic_rgb64(int count, const QSpan *spans, void *userD
             const QRgba64 *src = op.srcFetch64(src_buffer, &op, data, sy, sx, l);
             QRgba64 *dest = op.destFetch64(buffer, data->rasterBuffer, x, spans->y, l);
             op.func64(dest, src, l, coverage);
-            op.destStore64(data->rasterBuffer, x, spans->y, dest, l);
+            if (op.destStore64)
+                op.destStore64(data->rasterBuffer, x, spans->y, dest, l);
             x += l;
             sx += l;
             length -= l;
@@ -5309,6 +5517,9 @@ static const ProcessSpans processTextureSpans[NBlendTypes][QImage::NImageFormats
         blend_untransformed_generic_rgb64,
         blend_untransformed_generic,
         blend_untransformed_generic,
+        blend_untransformed_generic_rgb64,
+        blend_untransformed_generic_rgb64,
+        blend_untransformed_generic_rgb64,
     },
     // Tiled
     {
@@ -5337,6 +5548,9 @@ static const ProcessSpans processTextureSpans[NBlendTypes][QImage::NImageFormats
         blend_tiled_generic_rgb64,
         blend_tiled_generic,
         blend_tiled_generic,
+        blend_tiled_generic_rgb64,
+        blend_tiled_generic_rgb64,
+        blend_tiled_generic_rgb64,
     },
     // Transformed
     {
@@ -5365,6 +5579,9 @@ static const ProcessSpans processTextureSpans[NBlendTypes][QImage::NImageFormats
         blend_src_generic_rgb64,
         blend_src_generic,
         blend_src_generic,
+        blend_src_generic_rgb64,
+        blend_src_generic_rgb64,
+        blend_src_generic_rgb64,
     },
      // TransformedTiled
     {
@@ -5392,6 +5609,9 @@ static const ProcessSpans processTextureSpans[NBlendTypes][QImage::NImageFormats
         blend_src_generic_rgb64,
         blend_src_generic,
         blend_src_generic,
+        blend_src_generic_rgb64,
+        blend_src_generic_rgb64,
+        blend_src_generic_rgb64,
     },
     // Bilinear
     {
@@ -5420,6 +5640,9 @@ static const ProcessSpans processTextureSpans[NBlendTypes][QImage::NImageFormats
         blend_src_generic_rgb64,
         blend_src_generic,
         blend_src_generic,
+        blend_src_generic_rgb64,
+        blend_src_generic_rgb64,
+        blend_src_generic_rgb64,
     },
     // BilinearTiled
     {
@@ -5448,6 +5671,9 @@ static const ProcessSpans processTextureSpans[NBlendTypes][QImage::NImageFormats
         blend_src_generic_rgb64, // A2RGB30_Premultiplied
         blend_src_generic, // Alpha8
         blend_src_generic, // Grayscale8
+        blend_src_generic_rgb64, // RGBX64
+        blend_src_generic_rgb64, // RGBA64
+        blend_src_generic_rgb64, // RGBA64_Premultiplied
     }
 };
 
@@ -6014,6 +6240,14 @@ static void qt_rectfill_gray(QRasterBuffer *rasterBuffer,
                          qGray(color.toArgb32()), x, y, width, height, rasterBuffer->bytesPerLine());
 }
 
+static void qt_rectfill_rgb64(QRasterBuffer *rasterBuffer,
+                              int x, int y, int width, int height,
+                              const QRgba64 &color)
+{
+    qt_rectfill<quint64>(reinterpret_cast<quint64 *>(rasterBuffer->buffer()),
+                         color, x, y, width, height, rasterBuffer->bytesPerLine());
+}
+
 // Map table for destination image format. Contains function pointers
 // for blends of various types unto the destination
 
@@ -6212,6 +6446,26 @@ DrawHelper qDrawHelper[QImage::NImageFormats] =
         0, 0, 0,
         qt_rectfill_gray
     },
+    // Format_RGBX64
+    {
+        blend_color_generic_rgb64,
+        blend_src_generic_rgb64,
+        0, 0, 0,
+        qt_rectfill_rgb64
+    },
+    // Format_RGBA64
+    {
+        blend_color_generic_rgb64,
+        blend_src_generic_rgb64,
+        0, 0, 0, 0
+    },
+    // Format_RGBA64_Premultiplied
+    {
+        blend_color_generic_rgb64,
+        blend_src_generic_rgb64,
+        0, 0, 0,
+        qt_rectfill_rgb64
+    },
 };
 
 #if defined(Q_CC_MSVC) && !defined(_MIPS_)
diff --git a/src/gui/painting/qdrawhelper_p.h b/src/gui/painting/qdrawhelper_p.h
index f8865a6..fb9498e 100644
--- a/src/gui/painting/qdrawhelper_p.h
+++ b/src/gui/painting/qdrawhelper_p.h
@@ -1025,8 +1025,14 @@ inline int qBlue565(quint16 rgb) {
 
 static Q_ALWAYS_INLINE const uint *qt_convertARGB32ToARGB32PM(uint *buffer, const uint *src, int count)
 {
-    for (int i = 0; i < count; ++i)
-        buffer[i] = qPremultiply(src[i]);
+    // We explicitly split the aliased case to force the compiler to make optimized code paths for each case.
+    if (buffer == src) {
+        for (int i = 0; i < count; ++i)
+            buffer[i] = qPremultiply(buffer[i]);
+    } else {
+        for (int i = 0; i < count; ++i)
+            buffer[i] = qPremultiply(src[i]);
+    }
     return buffer;
 }
 
@@ -1037,6 +1043,7 @@ static Q_ALWAYS_INLINE const uint *qt_convertRGBA8888ToARGB32PM(uint *buffer, co
     return buffer;
 }
 
+template<bool RGBA> void qt_convertRGBA64ToARGB32(uint *dst, const QRgba64 *src, int count);
 
 const uint qt_bayer_matrix[16][16] = {
     { 0x1, 0xc0, 0x30, 0xf0, 0xc, 0xcc, 0x3c, 0xfc,
@@ -1104,7 +1111,7 @@ inline int comp_func_Plus_one_pixel(uint d, const uint s)
 struct QPixelLayout;
 typedef const uint *(QT_FASTCALL *ConvertFunc)(uint *buffer, const uint *src, int count,
                                                const QPixelLayout *layout, const QRgb *clut);
-typedef const QRgba64 *(QT_FASTCALL *ConvertFunc64)(QRgba64 *buffer, const uint *src, int count,
+typedef const QRgba64 *(QT_FASTCALL *ConvertFunc64)(QRgba64 *buffer, const quint64 *src, int count,
                                                     const QPixelLayout *layout, const QRgb *clut);
 
 struct QPixelLayout
@@ -1118,6 +1125,7 @@ struct QPixelLayout
         BPP16,
         BPP24,
         BPP32,
+        BPP64,
         BPPCount
     };
 
@@ -1135,17 +1143,20 @@ struct QPixelLayout
     ConvertFunc convertToARGB32PM;
     ConvertFunc convertFromARGB32PM;
     ConvertFunc convertFromRGB32;
-    ConvertFunc64 convertToARGB64PM;
+    ConvertFunc64 convertToRGBA64PM;
 };
 
 typedef const uint *(QT_FASTCALL *FetchPixelsFunc)(uint *buffer, const uchar *src, int index, int count);
 typedef void (QT_FASTCALL *StorePixelsFunc)(uchar *dest, const uint *src, int index, int count);
 
-extern QPixelLayout qPixelLayouts[QImage::NImageFormats];
-extern FetchPixelsFunc qFetchPixels[QPixelLayout::BPPCount];
-extern StorePixelsFunc qStorePixels[QPixelLayout::BPPCount];
-
+typedef const quint64 *(QT_FASTCALL *FetchPixelsFunc64)(quint64 *buffer, const uchar *src, int index, int count);
+typedef void (QT_FASTCALL *StorePixelsFunc64)(uchar *dest, const quint64 *src, int index, int count);
 
+extern QPixelLayout qPixelLayouts[QImage::NImageFormats];
+extern const FetchPixelsFunc qFetchPixels[QPixelLayout::BPPCount];
+extern const StorePixelsFunc qStorePixels[QPixelLayout::BPPCount];
+extern const FetchPixelsFunc64 qFetchPixels64[QPixelLayout::BPPCount];
+extern const StorePixelsFunc64 qStorePixels64[QPixelLayout::BPPCount];
 
 QT_END_NAMESPACE
 
diff --git a/src/gui/painting/qmemrotate.cpp b/src/gui/painting/qmemrotate.cpp
index f205cb1..105bc2a 100644
--- a/src/gui/painting/qmemrotate.cpp
+++ b/src/gui/painting/qmemrotate.cpp
@@ -465,9 +465,7 @@ Q_GUI_EXPORT void qt_memrotate270(const type *src, int w, int h, int sstride, \
     qt_memrotate270_tiled_unpacked<type>(src, w, h, sstride, dest, dstride); \
 }
 
-
-
-
+QT_IMPL_MEMROTATE(quint64)
 QT_IMPL_MEMROTATE(quint32)
 QT_IMPL_MEMROTATE(quint16)
 QT_IMPL_MEMROTATE(quint24)
@@ -518,6 +516,21 @@ void qt_memrotate270_32(const uchar *srcPixels, int w, int h, int sbpl, uchar *d
     qt_memrotate270((const uint *)srcPixels, w, h, sbpl, (uint *)destPixels, dbpl);
 }
 
+void qt_memrotate90_64(const uchar *srcPixels, int w, int h, int sbpl, uchar *destPixels, int dbpl)
+{
+    qt_memrotate90((const quint64 *)srcPixels, w, h, sbpl, (quint64 *)destPixels, dbpl);
+}
+
+void qt_memrotate180_64(const uchar *srcPixels, int w, int h, int sbpl, uchar *destPixels, int dbpl)
+{
+    qt_memrotate180((const quint64 *)srcPixels, w, h, sbpl, (quint64 *)destPixels, dbpl);
+}
+
+void qt_memrotate270_64(const uchar *srcPixels, int w, int h, int sbpl, uchar *destPixels, int dbpl)
+{
+    qt_memrotate270((const quint64 *)srcPixels, w, h, sbpl, (quint64 *)destPixels, dbpl);
+}
+
 MemRotateFunc qMemRotateFunctions[QImage::NImageFormats][3] =
 // 90, 180, 270
 {
@@ -546,6 +559,9 @@ MemRotateFunc qMemRotateFunctions[QImage::NImageFormats][3] =
     { qt_memrotate90_32, qt_memrotate180_32, qt_memrotate270_32 },      // Format_A2RGB30_Premultiplied,
     { qt_memrotate90_8, qt_memrotate180_8, qt_memrotate270_8 },         // Format_Alpha8,
     { qt_memrotate90_8, qt_memrotate180_8, qt_memrotate270_8 },         // Format_Grayscale8,
+    { qt_memrotate90_64, qt_memrotate180_64, qt_memrotate270_64 },      // Format_RGBX64
+    { qt_memrotate90_64, qt_memrotate180_64, qt_memrotate270_64 },      // Format_RGBA64
+    { qt_memrotate90_64, qt_memrotate180_64, qt_memrotate270_64 },      // Format_RGBA64_Premultiplied
 };
 
 QT_END_NAMESPACE
diff --git a/src/gui/painting/qmemrotate_p.h b/src/gui/painting/qmemrotate_p.h
index ece6e94..3d209e3 100644
--- a/src/gui/painting/qmemrotate_p.h
+++ b/src/gui/painting/qmemrotate_p.h
@@ -71,6 +71,7 @@ QT_DECL_MEMROTATE(quint32);
 QT_DECL_MEMROTATE(quint16);
 QT_DECL_MEMROTATE(quint24);
 QT_DECL_MEMROTATE(quint8);
+QT_DECL_MEMROTATE(quint64);
 
 #undef QT_DECL_MEMROTATE
 
diff --git a/tests/auto/gui/image/qimage/tst_qimage.cpp b/tests/auto/gui/image/qimage/tst_qimage.cpp
index 5691a65..511963e 100644
--- a/tests/auto/gui/image/qimage/tst_qimage.cpp
+++ b/tests/auto/gui/image/qimage/tst_qimage.cpp
@@ -184,6 +184,10 @@ private slots:
 
     void devicePixelRatio();
 
+    void metadataPassthrough();
+
+    void myTests();
+
 private:
     const QString m_prefix;
 };
@@ -2800,6 +2804,35 @@ void tst_QImage::cleanupFunctions()
 
 }
 
+void tst_QImage::myTests()
+{
+    
+    QImage image(900, 100, QImage::Format_RGBX64);
+    QPainter painter(&image);
+    QLinearGradient g(0, 0, 900, 0);
+    g.setColorAt(0, QColor("#FFCC22"));
+    g.setColorAt(1, QColor("#EE0033"));
+    QBrush brush(g);
+    painter.fillRect(QRect(0, 0, 900, 100), brush);
+    painter.end();
+    image.save("test64x.png");
+
+    QImage image2(900, 100, QImage::Format_RGB32);
+    QPainter painter2(&image2);
+    painter2.fillRect(QRect(0, 0, 900, 100), brush);
+    painter2.end();
+    image2.save("test32.png");
+    
+    QImage image3(900, 100, QImage::Format_RGB30);
+    QPainter painter3(&image3);
+    painter3.fillRect(QRect(0, 0, 900, 100), brush);
+    painter3.end();
+    image3.save("test30.png");
+
+    image3.convertToFormat(QImage::Format_RGBX64).save("test30x64.png");
+}
+
+
 // test image devicePixelRatio setting and detaching
 void tst_QImage::devicePixelRatio()
 {
@@ -2827,5 +2860,39 @@ void tst_QImage::devicePixelRatio()
     QCOMPARE(b.devicePixelRatio(), qreal(1.0));
 }
 
+void tst_QImage::metadataPassthrough()
+{
+    QImage a(64, 64, QImage::Format_ARGB32);
+    a.fill(Qt::white);
+    a.setText(QStringLiteral("Test"), QStringLiteral("Text"));
+    a.setDotsPerMeterX(100);
+    a.setDotsPerMeterY(80);
+    a.setDevicePixelRatio(2.0);
+
+    QImage scaled = a.scaled(QSize(32, 32), Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
+    QCOMPARE(scaled.text(QStringLiteral("Test")), a.text(QStringLiteral("Test")));
+    QCOMPARE(scaled.dotsPerMeterX(), a.dotsPerMeterX());
+    QCOMPARE(scaled.dotsPerMeterY(), a.dotsPerMeterY());
+    QCOMPARE(scaled.devicePixelRatio(), a.devicePixelRatio());
+
+    scaled = a.scaled(QSize(128, 128), Qt::IgnoreAspectRatio, Qt::FastTransformation);
+    QCOMPARE(scaled.text(QStringLiteral("Test")), a.text(QStringLiteral("Test")));
+    QCOMPARE(scaled.dotsPerMeterX(), a.dotsPerMeterX());
+    QCOMPARE(scaled.dotsPerMeterY(), a.dotsPerMeterY());
+    QCOMPARE(scaled.devicePixelRatio(), a.devicePixelRatio());
+
+    QImage mirrored = a.mirrored();
+    QCOMPARE(mirrored.text(QStringLiteral("Test")), a.text(QStringLiteral("Test")));
+    QCOMPARE(mirrored.dotsPerMeterX(), a.dotsPerMeterX());
+    QCOMPARE(mirrored.dotsPerMeterY(), a.dotsPerMeterY());
+    QCOMPARE(mirrored.devicePixelRatio(), a.devicePixelRatio());
+
+    QImage swapped = a.rgbSwapped();
+    QCOMPARE(swapped.text(QStringLiteral("Test")), a.text(QStringLiteral("Test")));
+    QCOMPARE(swapped.dotsPerMeterX(), a.dotsPerMeterX());
+    QCOMPARE(swapped.dotsPerMeterY(), a.dotsPerMeterY());
+    QCOMPARE(swapped.devicePixelRatio(), a.devicePixelRatio());
+}
+
 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 4f04e50..ecbab60 100644
--- a/tests/auto/gui/image/qimagewriter/tst_qimagewriter.cpp
+++ b/tests/auto/gui/image/qimagewriter/tst_qimagewriter.cpp
@@ -266,18 +266,16 @@ void tst_QImageWriter::writeImage2_data()
     QImage image0(70, 70, QImage::Format_ARGB32);
     image0.fill(QColor(Qt::red).rgb());
 
-    QImage::Format imgFormat = QImage::Format_Mono;
-    while (imgFormat != QImage::NImageFormats) {
-        QImage image = image0.convertToFormat(imgFormat);
+    for (int i = QImage::Format_Mono; i < QImage::NImageFormats; ++i) {
+        QImage image = image0.convertToFormat(QImage::Format(i));
         initializePadding(&image);
         foreach (const QString format, formats) {
-            const QString fileName = QString("solidcolor_%1.%2").arg(imgFormat)
+            const QString fileName = QString("solidcolor_%1.%2").arg(i)
                                      .arg(format);
             QTest::newRow(fileName.toLatin1()) << fileName
                                                << format.toLatin1()
                                                << image;
         }
-        imgFormat = QImage::Format(int(imgFormat) + 1);
     }
 }
 
