commit 833f73add5da694e79918e557e5c3b0036ca9879
Author: Allan Sandfeld Jensen <allan.jensen@theqtcompany.com>
Date:   Tue Apr 28 12:38:49 2015 +0200

    WIP: 16bpc image formats
    
    Change-Id: Icd28bd5868a6efcf65cb5bd56031d42941e04099

diff --git a/examples/widgets/widgets/scribble/scribblearea.cpp b/examples/widgets/widgets/scribble/scribblearea.cpp
index 23ff92c..cd59ab0 100644
--- a/examples/widgets/widgets/scribble/scribblearea.cpp
+++ b/examples/widgets/widgets/scribble/scribblearea.cpp
@@ -189,7 +189,7 @@ void ScribbleArea::resizeImage(QImage *image, const QSize &newSize)
     if (image->size() == newSize)
         return;
 
-    QImage newImage(newSize, QImage::Format_RGB32);
+    QImage newImage(newSize, QImage::Format_RGBX64);
     newImage.fill(qRgb(255, 255, 255));
     QPainter painter(&newImage);
     painter.drawImage(QPoint(0, 0), *image);
diff --git a/src/gui/image/qimage.cpp b/src/gui/image/qimage.cpp
index cac3d26..6ad7bdd 100644
--- a/src/gui/image/qimage.cpp
+++ b/src/gui/image/qimage.cpp
@@ -265,6 +265,15 @@ bool QImageData::checkForAlphaPixels() const
             end_bits += bytes_per_line;
         }
     } break;
+    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 +1699,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)
@@ -2469,6 +2482,7 @@ bool QImage::allGray() const
     case Format_Alpha8:
         return false;
     case Format_Grayscale8:
+    case Format_Grayscale16:
         return true;
     case Format_RGB32:
     case Format_ARGB32:
@@ -2537,7 +2551,7 @@ bool QImage::isGrayscale() const
     if (d->format == QImage::Format_Alpha8)
         return false;
 
-    if (d->format == QImage::Format_Grayscale8)
+    if (d->format == QImage::Format_Grayscale8 || d->format == QImage::Format_Grayscale16)
         return true;
 
     switch (depth()) {
@@ -4338,6 +4352,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;
@@ -4401,6 +4418,7 @@ static QImage rotated90(const QImage &image) {
     case QImage::Format_RGB555:
     case QImage::Format_RGB16:
     case QImage::Format_ARGB4444_Premultiplied:
+    case QImage::Format_Grayscale16:
         qt_memrotate270(reinterpret_cast<const quint16*>(image.bits()),
                         w, h, image.bytesPerLine(),
                         reinterpret_cast<quint16*>(out.bits()),
@@ -4414,6 +4432,13 @@ static QImage rotated90(const QImage &image) {
                         reinterpret_cast<quint8*>(out.bits()),
                         out.bytesPerLine());
         break;
+    case QImage::Format_RGBX64:
+    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())
@@ -4469,6 +4494,7 @@ static QImage rotated270(const QImage &image) {
     case QImage::Format_RGB555:
     case QImage::Format_RGB16:
     case QImage::Format_ARGB4444_Premultiplied:
+    case QImage::Format_Grayscale16:
        qt_memrotate90(reinterpret_cast<const quint16*>(image.bits()),
                        w, h, image.bytesPerLine(),
                        reinterpret_cast<quint16*>(out.bits()),
@@ -4482,6 +4508,13 @@ static QImage rotated270(const QImage &image) {
                        reinterpret_cast<quint8*>(out.bits()),
                        out.bytesPerLine());
         break;
+    case QImage::Format_RGBX64:
+    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())
@@ -5109,6 +5142,45 @@ static Q_CONSTEXPR QPixelFormat pixelformats[] = {
                     /*PREMULTIPLIED*/     QPixelFormat::NotPremultiplied,
                     /*INTERPRETATION*/    QPixelFormat::UnsignedByte,
                     /*BYTE ORDER*/        QPixelFormat::CurrentSystemEndian),
+        //QImage::Format_Grayscale16:
+        QPixelFormat(QPixelFormat::Grayscale,
+                    /*GRAY*/               16,
+                    /*SECOND*/             0,
+                    /*THIRD*/              0,
+                    /*FOURTH*/             0,
+                    /*FIFTH*/              0,
+                    /*ALPHA*/              0,
+                    /*ALPHA USAGE*/       QPixelFormat::IgnoresAlpha,
+                    /*ALPHA POSITION*/    QPixelFormat::AtBeginning,
+                    /*PREMULTIPLIED*/     QPixelFormat::NotPremultiplied,
+                    /*INTERPRETATION*/    QPixelFormat::UnsignedByte,
+                    /*BYTE ORDER*/        QPixelFormat::CurrentSystemEndian),
+        //QImage::Format_RGB48:
+        QPixelFormat(QPixelFormat::RGB,
+                     /*RED*/                16,
+                     /*GREEN*/              16,
+                     /*BLUE*/               16,
+                     /*FOURTH*/             0,
+                     /*FIFTH*/              0,
+                     /*ALPHA*/              0,
+                     /*ALPHA USAGE*/       QPixelFormat::IgnoresAlpha,
+                     /*ALPHA POSITION*/    QPixelFormat::AtEnd,
+                     /*PREMULTIPLIED*/     QPixelFormat::NotPremultiplied,
+                     /*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*/              86,
+                     /*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..307eff4 100644
--- a/src/gui/image/qimage.h
+++ b/src/gui/image/qimage.h
@@ -113,10 +113,9 @@ public:
         Format_A2RGB30_Premultiplied,
         Format_Alpha8,
         Format_Grayscale8,
-#if 0
-        // reserved for future use
         Format_Grayscale16,
-#endif
+        Format_RGBX64,
+        Format_RGBA64_Premultiplied,
 #ifndef Q_QDOC
         NImageFormats
 #endif
diff --git a/src/gui/image/qimage_conversions.cpp b/src/gui/image/qimage_conversions.cpp
index 8cb886e..93127b7 100644
--- a/src/gui/image/qimage_conversions.cpp
+++ b/src/gui/image/qimage_conversions.cpp
@@ -133,6 +133,7 @@ void convert_generic(QImageData *dest, const QImageData *src, Qt::ImageConversio
     const uchar *srcData = src->data;
     uchar *destData = dest->data;
 
+    // FIXME: Handle BPP48 and BPP64
     const FetchPixelsFunc fetch = qFetchPixels[srcLayout->bpp];
     const StorePixelsFunc store = qStorePixels[destLayout->bpp];
     ConvertFunc convertToARGB32PM = srcLayout->convertToARGB32PM;
@@ -182,6 +183,7 @@ bool convert_generic_inplace(QImageData *data, QImage::Format dst_format, Qt::Im
     const QPixelLayout *destLayout = &qPixelLayouts[dst_format];
     uchar *srcData = data->data;
 
+    // FIXME: Handle BPP48 and BPP64
     const FetchPixelsFunc fetch = qFetchPixels[srcLayout->bpp];
     const StorePixelsFunc store = qStorePixels[destLayout->bpp];
     ConvertFunc convertToARGB32PM = srcLayout->convertToARGB32PM;
@@ -1878,7 +1880,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 +1902,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 +1927,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 +1954,7 @@ 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 +1981,7 @@ Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImageFormat
         0,
         convert_RGB_to_RGB30<PixelOrderRGB>,
         0,
-        0, 0
+        0, 0, 0, 0, 0
     }, // Format_ARGB32
 
     {
@@ -2005,7 +2008,7 @@ Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImageFormat
         0,
         0,
         0,
-        0, 0
+        0, 0, 0, 0, 0
     },  // Format_ARGB32_Premultiplied
 
     {
@@ -2027,7 +2030,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 +2052,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 +2074,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 +2096,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 +2118,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 +2140,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 +2163,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 +2185,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 +2206,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,
@@ -2225,7 +2228,7 @@ Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImageFormat
         0,
         mask_alpha_converter_RGBx,
         mask_alpha_converter_RGBx,
-        0, 0, 0, 0, 0, 0
+        0, 0, 0, 0, 0, 0, 0, 0, 0
     }, // Format_RGBX8888
     {
         0,
@@ -2252,7 +2255,7 @@ 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, 0, 0
     }, // Format_RGBA8888
 
     {
@@ -2274,7 +2277,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 +2304,7 @@ 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 +2330,7 @@ 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 +2356,7 @@ Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImageFormat
         0,
         0,
         convert_passthrough,
-        0, 0
+        0, 0, 0, 0, 0
     }, // Format_RGB30
     {
         0,
@@ -2380,7 +2383,7 @@ Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImageFormat
         convert_A2RGB30_PM_to_RGB30,
         0,
         0,
-        0,
+        0, 0, 0, 0
     }, // Format_RGB30A2_Premultiplied
     {
         0,
@@ -2400,7 +2403,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 +2423,80 @@ 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, 0, 0
+    }, // Format_Grayscale16
+    {
+        0,
+        0,
+        0,
+        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_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, 0, 0
+    } // Format_RGBA64
 };
 
 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 +2520,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 +2542,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 +2568,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 +2590,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 +2639,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 +2666,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 +2688,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 +2714,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 +2740,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 +2766,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 +2792,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 +2818,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 +2844,17 @@ 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, 0, 0
+    }, // Format_Grayscale16
+    {
+        0, 0, 0, 0, 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_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, 0, 0, 0
+    }  // Format_RGBA64
 };
 
 void qInitImageConversions()
diff --git a/src/gui/image/qimage_p.h b/src/gui/image/qimage_p.h
index 7eb5719..6679e5a 100644
--- a/src/gui/image/qimage_p.h
+++ b/src/gui/image/qimage_p.h
@@ -151,6 +151,7 @@ inline int qt_depthForFormat(QImage::Format format)
     case QImage::Format_RGB16:
     case QImage::Format_RGB444:
     case QImage::Format_ARGB4444_Premultiplied:
+    case QImage::Format_Grayscale16:
         depth = 16;
         break;
     case QImage::Format_RGB666:
@@ -160,6 +161,10 @@ inline int qt_depthForFormat(QImage::Format format)
     case QImage::Format_RGB888:
         depth = 24;
         break;
+    case QImage::Format_RGBX64:
+    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..d882979 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,6 +321,10 @@ void QRasterPlatformPixmap::createPixmapForImage(QImage &sourceImage, Qt::ImageC
         } else {
             QImage::Format opaqueFormat = QNativeImage::systemFormat();
             QImage::Format alphaFormat = QImage::Format_ARGB32_Premultiplied;
+            if (sourceImage.bitPlaneCount() > 32) {
+                opaqueFormat = QImage::Format_RGBX64;
+                alphaFormat = QImage::Format_RGBA64_Premultiplied;
+            }
 
 #if !defined(__ARM_NEON__) && !defined(__SSE2__)
             switch (opaqueFormat) {
diff --git a/src/gui/image/qpnghandler.cpp b/src/gui/image/qpnghandler.cpp
index 3c88d2e..5934332 100644
--- a/src/gui/image/qpnghandler.cpp
+++ b/src/gui/image/qpnghandler.cpp
@@ -299,6 +299,15 @@ void setup_qt(QImage& image, png_structp png_ptr, png_infop info_ptr, QSize scal
             }
 
             png_read_update_info(png_ptr, info_ptr);
+        } else if (bit_depth == 16 && !png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) {
+            if (image.size() != QSize(width, height) || image.format() != QImage::Format_Grayscale16) {
+                image = QImage(width, height, QImage::Format_Grayscale16);
+                if (image.isNull())
+                    return;
+            }
+            if (QSysInfo::ByteOrder == QSysInfo::LittleEndian)
+                png_set_swap(png_ptr);
+            png_read_update_info(png_ptr, info_ptr);
         } else {
             if (bit_depth == 16)
                 png_set_strip_16(png_ptr);
@@ -363,6 +372,20 @@ 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 (color_type == PNG_COLOR_TYPE_RGB && bit_depth == 16 && !png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) {
+        if (image.size() != QSize(width, height) || image.format() != QImage::Format_RGBX64) {
+            image = QImage(width, height, QImage::Format_RGBX64);
+            if (image.isNull())
+                return;
+        }
+        png_set_filler(png_ptr, 0xffff, PNG_FILLER_AFTER);
+        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 +422,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);
     }
 }
 
@@ -668,6 +691,8 @@ QImage::Format QPngHandlerPrivate::readImageFormat()
                 format = QImage::Format_ARGB32;
             } else if (bit_depth == 8 && !png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) {
                 format = QImage::Format_Grayscale8;
+            } else if (bit_depth == 16) {
+                format = QImage::Format_Grayscale16;
             } else {
                 format = QImage::Format_Indexed8;
             }
@@ -681,6 +706,9 @@ 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 (color_type == PNG_COLOR_TYPE_RGB && bit_depth == 16 && !png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) {
+            // FIXME: Check for PNG_INFO_tRNS?
+            format = QImage::Format_RGBX64;
         } else {
             // 32-bit
             if (bit_depth == 16)
@@ -859,15 +887,30 @@ bool Q_INTERNAL_WIN_NO_THROW QPNGImageWriter::writeImage(const QImage& image, vo
         else
             color_type = PNG_COLOR_TYPE_PALETTE;
     }
-    else if (image.format() == QImage::Format_Grayscale8)
+    else if (image.format() == QImage::Format_Grayscale8 || image.format() == QImage::Format_Grayscale16)
         color_type = PNG_COLOR_TYPE_GRAY;
     else if (image.hasAlphaChannel())
         color_type = PNG_COLOR_TYPE_RGB_ALPHA;
     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_Grayscale16:
+    case QImage::Format_RGBX64:
+        bpc = 16;
+        break;
+    default:
+        bpc = 8;
+        break;
+    }
+
     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 +946,34 @@ 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_RGBA8888_Premultiplied:
+        case QImage::Format_RGBX64:
+//        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:
+//        case QImage::Format_RGBA8888_Premultiplied:
+            break;
+        case QImage::Format_Grayscale16:
+        case QImage::Format_RGBX64:
+//        case QImage::Format_RGBA64_Premultiplied:
+            png_set_swap(png_ptr);
+            break;
+        default:
+            png_set_bgr(png_ptr);
+        }
     }
 
     if (off_x || off_y) {
@@ -932,10 +996,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";
@@ -960,9 +1034,13 @@ bool Q_INTERNAL_WIN_NO_THROW QPNGImageWriter::writeImage(const QImage& image, vo
     case QImage::Format_MonoLSB:
     case QImage::Format_Indexed8:
     case QImage::Format_Grayscale8:
+    case QImage::Format_Grayscale16:
     case QImage::Format_RGB32:
     case QImage::Format_ARGB32:
     case QImage::Format_RGB888:
+    case QImage::Format_RGBX8888:
+    case QImage::Format_RGBA8888:
+    case QImage::Format_RGBX64:
         {
             png_bytep* row_pointers = new png_bytep[height];
             for (int y=0; y<height; y++)
@@ -971,6 +1049,8 @@ bool Q_INTERNAL_WIN_NO_THROW QPNGImageWriter::writeImage(const QImage& image, vo
             delete [] row_pointers;
         }
         break;
+    case QImage::Format_RGBA64_Premultiplied:
+        // FIXME: Handle
     default:
         {
             QImage::Format fmt = image.hasAlphaChannel() ? QImage::Format_ARGB32 : QImage::Format_RGB32;
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 b3f9fd9..2399acf 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 convertARGBPMToARGB64PM(QRgba64 *buffer, const quint64 *src, int count,
                                                           const QPixelLayout *, const QRgb *)
 {
     Q_CONSTEXPR uint alphaMask = ((1 << alphaWidth<Format>()) - 1);
@@ -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)
@@ -483,6 +483,30 @@ static const QRgba64 *QT_FASTCALL convertGrayscale8ToRGB64(QRgba64 *buffer, cons
     return buffer;
 }
 
+static Q_DECL_CONSTEXPR uint qt_div_257_floor(uint x) { return  (x - (x >> 8)) >> 8; }
+static Q_DECL_CONSTEXPR uint qt_div_257(uint x) { return qt_div_257_floor(x + 128); }
+
+static const uint *QT_FASTCALL convertGrayscale16ToRGB32(uint *buffer, const uint *src, int count,
+                                                         const QPixelLayout *, const QRgb *)
+{
+    // FIXME: Verify what the fuck I am doing here.
+    for (int i = 0; i < count; ++i) {
+        int green = qt_div_257(src[i]);
+        int red = green; // std::min(std::max(green + (int)((src[i] >> 6) & 3) - 2, 255), 0);
+        int blue = green; // std::min(std::max(green + (int)((src[i] >> 4) & 7) - 4, 255), 0);
+        buffer[i] = qRgb(red, green, blue);
+    }
+    return buffer;
+}
+
+static const QRgba64 *QT_FASTCALL convertGrayscale16ToRGB64(QRgba64 *buffer, const quint64 *src, int count,
+                                                            const QPixelLayout *, const QRgb *)
+{
+    for (int i = 0; i < count; ++i)
+        buffer[i] = QRgba64::fromRgba64(src[i], src[i], src[i], 65535);
+    return buffer;
+}
+
 static const uint *QT_FASTCALL convertARGB32FromARGB32PM(uint *buffer, const uint *src, int count,
                                                          const QPixelLayout *, const QRgb *)
 {
@@ -501,7 +525,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 qConvertARGB32PMToARGB64PM_sse2(QRgba64 *buffer, const quint64 *src, int count)
 {
     const __m128i amask = _mm_set1_epi32(0xff000000);
     int i = 0;
@@ -513,7 +537,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,7 +566,7 @@ 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__
@@ -552,7 +578,13 @@ 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 convertARGB32ToARGB64PM(QRgba64 *buffer, const quint64 *src, int count,
                                                           const QPixelLayout *, const QRgb *)
 {
 #ifdef __SSE2__
@@ -566,7 +598,7 @@ 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 convertARGB32PMToARGB64PM(QRgba64 *buffer, const quint64 *src, int count,
                                                             const QPixelLayout *, const QRgb *)
 {
 #ifdef __SSE2__
@@ -578,7 +610,7 @@ 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 convertRGBA8888ToARGB64PM(QRgba64 *buffer, const quint64 *src, int count,
                                                             const QPixelLayout *, const QRgb *)
 {
 #ifdef __SSE2__
@@ -592,7 +624,7 @@ 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 convertRGBA8888PMToARGB64PM(QRgba64 *buffer, const quint64 *src, int count,
                                                              const QPixelLayout *, const QRgb *)
 {
 #ifdef __SSE2__
@@ -639,7 +671,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 +683,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 +713,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__
@@ -742,6 +776,24 @@ static const uint *QT_FASTCALL convertGrayscale8FromARGB32PM(uint *buffer, const
     return buffer;
 }
 
+static const uint *QT_FASTCALL convertGrayscale16FromRGB32(uint *buffer, const uint *src, int count,
+                                                           const QPixelLayout *, const QRgb *)
+{
+    for (int i = 0; i < count; ++i)
+        buffer[i] = qGray(src[i]) * 257;
+//        buffer[i] = qGray16(src[i]);
+    return buffer;
+}
+
+static const uint *QT_FASTCALL convertGrayscale16FromARGB32PM(uint *buffer, const uint *src, int count,
+                                                              const QPixelLayout *, const QRgb *)
+{
+    for (int i = 0; i < count; ++i)
+        buffer[i] = qGray(qUnpremultiply(src[i])) * 257;
+//        buffer[i] = qGray16(qUnpremultiply(src[i]));
+    return buffer;
+}
+
 template <QPixelLayout::BPP bpp> static
 uint QT_FASTCALL fetchPixel(const uchar *src, int index);
 
@@ -781,6 +833,26 @@ 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 <QPixelLayout::BPP bpp>
 inline const uint *QT_FASTCALL fetchPixels(uint *buffer, const uchar *src, int index, int count)
 {
@@ -795,11 +867,65 @@ inline const uint *QT_FASTCALL fetchPixels<QPixelLayout::BPP32>(uint *, const uc
     return reinterpret_cast<const uint *>(src) + index;
 }
 
-template <QPixelLayout::BPP width> static
+static inline void qConvertRGBA64ToARGB32(uint *buffer, const QRgba64 *src, int count)
+{
+    int i = 0;
+#ifdef __SSE2__
+    if (((uintptr_t)buffer & 0x7) && count > 0) {
+        *buffer++ = (*src++).toArgb32();
+        i++;
+    }
+    const __m128i vhalf = _mm_set1_epi32(0x80);
+    for (; i < count-1; i += 2) {
+        __m128i vs = _mm_loadu_si128((const __m128i*)src);
+        src += 2;
+        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, _mm_setzero_si128());
+        __m128i v2 = _mm_unpackhi_epi16(vs, _mm_setzero_si128());
+        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, v1);
+        _mm_storel_epi64((__m128i*)(buffer), v1);
+        buffer += 2;
+    }
+#endif
+    for (; i < count; ++i)
+        *buffer++ = (*src++).toArgb32();
+}
+
+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;
+    qConvertRGBA64ToARGB32(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 +934,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 +943,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 +992,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.
@@ -941,39 +1099,83 @@ QPixelLayout qPixelLayouts[QImage::NImageFormats] = {
     { 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
+    { 0, 0,  0, 0,  0, 0,  0, 0, false, QPixelLayout::BPP16, convertGrayscale16ToRGB32, convertGrayscale16FromARGB32PM, convertGrayscale16FromRGB32, convertGrayscale16ToRGB64 }, // Format_Grayscale16
+#if Q_BYTE_ORDER == Q_BIG_ENDIAN
+    { 16, 48, 16, 32, 16, 16, 0,  0, false, QPixelLayout::BPP64, convertPassThrough, convertPassThrough, convertPassThrough, convertRGB64ToRGB64 }, // Format_RGBX64
+    { 16, 48, 16, 32, 16, 16, 16, 0,  true, QPixelLayout::BPP64, convertPassThrough, convertPassThrough, convertPassThrough, convertRGB64ToRGB64 } // Format_RGB64_Premultiplied
+#else
+    { 16, 0, 16, 16, 16, 32, 0,  48, false, QPixelLayout::BPP64, convertPassThrough, convertPassThrough, convertPassThrough, convertRGB64ToRGB64 }, // Format_RGBX64
+    { 16, 0, 16, 16, 16, 32, 16, 48,  true, QPixelLayout::BPP64, convertPassThrough, convertPassThrough, convertPassThrough, convertRGB64ToRGB64 } // Format_RGB64_Premultiplied
+#endif
 };
 
 FetchPixelsFunc qFetchPixels[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
+    fetchPixels<QPixelLayout::BPP1MSB>,
+    fetchPixels<QPixelLayout::BPP1LSB>,
+    fetchPixels<QPixelLayout::BPP8>,
+    fetchPixels<QPixelLayout::BPP16>,
+    fetchPixels<QPixelLayout::BPP24>,
+    fetchPixels<QPixelLayout::BPP32>,
+    fetchPixels<QPixelLayout::BPP64>
 };
 
 StorePixelsFunc qStorePixels[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
+    storePixels<QPixelLayout::BPP1MSB>,
+    storePixels<QPixelLayout::BPP1LSB>,
+    storePixels<QPixelLayout::BPP8>,
+    storePixels<QPixelLayout::BPP16>,
+    storePixels<QPixelLayout::BPP24>,
+    storePixels<QPixelLayout::BPP32>,
+    storePixels<QPixelLayout::BPP64>
+};
+
+FetchPixelsFunc64 qFetchPixels64[QPixelLayout::BPPCount] = {
+    0, // BPPNone
+    fetchPixels64<QPixelLayout::BPP1MSB>,
+    fetchPixels64<QPixelLayout::BPP1LSB>,
+    fetchPixels64<QPixelLayout::BPP8>,
+    fetchPixels64<QPixelLayout::BPP16>,
+    fetchPixels64<QPixelLayout::BPP24>,
+    fetchPixels64<QPixelLayout::BPP32>,
+    fetchPixels64<QPixelLayout::BPP64>
+};
+
+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] = {
     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>,
+};
+
+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 +1232,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);
+    const quint64 *ptr = qFetchPixels64[layout->bpp]((quint64*)buffer, rasterBuffer->scanLine(y), x, length);
     return const_cast<QRgba64 *>(layout->convertToARGB64PM(buffer, ptr, length, layout, 0));
 }
 
-static QRgba64 *QT_FASTCALL destFetch64uint32(QRgba64 *buffer, QRasterBuffer *rasterBuffer, int x, int y, int length)
+static QRgba64 * QT_FASTCALL destFetchRGBA64P(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 +1268,9 @@ static DestFetchProc destFetchProc[QImage::NImageFormats] =
     destFetch,          // Format_A2RGB30_Premultiplied
     destFetch,          // Format_Alpha8
     destFetch,          // Format_Grayscale8
+    destFetch,          // Format_Grayscale16
+    destFetch,          // Format_RGBX64
+    destFetch,          // Format_RGBA64_Premultiplied
 };
 
 static DestFetchProc64 destFetchProc64[QImage::NImageFormats] =
@@ -1077,9 +1279,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 +1291,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
+    destFetch64,        // Format_Grayscale16
+    destFetchRGBA64P,   // Format_RGBX64
+    destFetchRGBA64P,   // Format_RGBA64_Premultiplied
 };
 
 /*
@@ -1216,13 +1421,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 +1430,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);
+        qConvertRGBA64ToARGB32(buf, buffer, length);
         if (!layout->premultiplied && !layout->alphaWidth)
             ptr = layout->convertFromRGB32(buf, buf, l, layout, 0);
         else
@@ -1307,6 +1505,26 @@ static void QT_FASTCALL destStore64RGB30(QRasterBuffer *rasterBuffer, int x, int
 #endif
 }
 
+static void QT_FASTCALL destStore64Gray16(QRasterBuffer *rasterBuffer, int x, int y, const QRgba64 *buffer, int length)
+{
+    quint16 *dest = (quint16*)rasterBuffer->scanLine(y) + x;
+    for (int i = 0; i < length; ++i) {
+        QRgba64 v = buffer[i].unpremultiplied();
+        // FIXME: Wrong gray conversion:
+        dest[i] = qGray(v.red(), v.green(), v.blue());
+    }
+}
+
+static void QT_FASTCALL destStore64RGB64(QRasterBuffer *rasterBuffer, int x, int y, const QRgba64 *buffer, int length)
+{
+    QRgba64 *dest = (QRgba64*)rasterBuffer->scanLine(y) + x;
+    if (dest == buffer)
+        return;
+    for (int i = 0; i < length; ++i) {
+        dest[i] = buffer[i];
+    }
+}
+
 static DestStoreProc destStoreProc[QImage::NImageFormats] =
 {
     0,                  // Format_Invalid
@@ -1334,6 +1552,9 @@ static DestStoreProc destStoreProc[QImage::NImageFormats] =
     destStore,          // Format_A2RGB30_Premultiplied
     destStore,          // Format_Alpha8
     destStore,          // Format_Grayscale8
+    destStore,          // Format_Grayscale16
+    destStore,          // Format_RGBX64
+    destStore,          // Format_RGBA64_Premultiplied
 };
 
 static DestStoreProc64 destStoreProc64[QImage::NImageFormats] =
@@ -1363,6 +1584,9 @@ static DestStoreProc64 destStoreProc64[QImage::NImageFormats] =
     destStore64RGB30<PixelOrderRGB>,        // Format_A2RGB30_Premultiplied
     destStore64,        // Format_Alpha8
     destStore64,        // Format_Grayscale8
+    destStore64Gray16,  // Format_Grayscale16
+    destStore64RGB64,   // Format_RGBX64
+    destStore64RGB64    // Format_RGBA64_Premultiplied
 };
 
 /*
@@ -1425,14 +1649,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->convertToARGB64PM(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 +1838,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 +1855,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->convertToARGB64PM(b, (const quint64*)b, buffer_size, layout, clut);
                 b += buffer_size;
                 j = 0;
             }
@@ -1647,14 +1871,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->convertToARGB64PM(b, (const quint64*)b, j, layout, clut);
             b += j;
         }
     } else {
@@ -1669,7 +1893,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->convertToARGB64PM(b, (const quint64*)b, buffer_size, layout, clut);
                 b += buffer_size;
                 j = 0;
             }
@@ -1688,7 +1912,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 +1924,7 @@ static const QRgba64 *QT_FASTCALL fetchTransformed64(QRgba64 *buffer, const Oper
             ++i; ++j;
         }
         if (j > 0) {
-            layout->convertToARGB64PM(b, buffer32, j, layout, clut);
+            layout->convertToARGB64PM(b, (const quint64*)b, j, layout, clut);
             b += j;
         }
     }
@@ -1798,7 +2022,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 +2045,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;
@@ -2758,11 +2982,11 @@ static const QRgba64 *QT_FASTCALL fetchTransformedBilinear64(QRgba64 *buffer, co
             const uchar *s1 = data->texture.scanLine(y1);
             const uchar *s2 = data->texture.scanLine(y2);
 
-            FetchPixelFunc fetch = qFetchPixel[layout->bpp];
-            uint sbuf1[buffer_size];
-            uint sbuf2[buffer_size];
+            FetchPixelFunc64 fetch = qFetchPixel64[layout->bpp];
             QRgba64 buf1[buffer_size];
             QRgba64 buf2[buffer_size];
+            quint64 *sbuf1 = reinterpret_cast<quint64*>(buf1);
+            quint64 *sbuf2 = reinterpret_cast<quint64*>(buf2);
             QRgba64 *b = buffer;
             while (length) {
                 int len = qMin(length, buffer_size / 2);
@@ -2772,44 +2996,78 @@ 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
+                    && (layout->bpp == QPixelLayout::BPP32 || layout->bpp == QPixelLayout::BPP64)) {
                     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];
+                        if (layout->bpp == QPixelLayout::BPP64) {
+                            sbuf1[i * 2 + 0] = ((const quint64*)s1)[x1];
+                            sbuf1[i * 2 + 1] = ((const quint64*)s1)[x2];
+                            sbuf2[i * 2 + 0] = ((const quint64*)s2)[x1];
+                            sbuf2[i * 2 + 1] = ((const quint64*)s2)[x2];
+                        } else {
+                            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];
+                        }
                         fx += fdx;
                     }
 
                     const __m128i v_fdx = _mm_set1_epi32(fdx*4);
                     __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];
-                        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];
-                        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];
-                        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];
-                        v_fx = _mm_add_epi32(v_fx, v_fdx);
+                    if (layout->bpp == QPixelLayout::BPP64) {
+                        for (; i < len-3; i+=4) {
+                            int offset = _mm_extract_epi16(v_fx, 1);
+                            sbuf1[i * 2 + 0] = ((const quint64*)s1)[offset];
+                            sbuf1[i * 2 + 1] = ((const quint64*)s1)[offset + 1];
+                            sbuf2[i * 2 + 0] = ((const quint64*)s2)[offset];
+                            sbuf2[i * 2 + 1] = ((const quint64*)s2)[offset + 1];
+                            offset = _mm_extract_epi16(v_fx, 3);
+                            sbuf1[i * 2 + 2] = ((const quint64*)s1)[offset];
+                            sbuf1[i * 2 + 3] = ((const quint64*)s1)[offset + 1];
+                            sbuf2[i * 2 + 2] = ((const quint64*)s2)[offset];
+                            sbuf2[i * 2 + 3] = ((const quint64*)s2)[offset + 1];
+                            offset = _mm_extract_epi16(v_fx, 5);
+                            sbuf1[i * 2 + 4] = ((const quint64*)s1)[offset];
+                            sbuf1[i * 2 + 5] = ((const quint64*)s1)[offset + 1];
+                            sbuf2[i * 2 + 4] = ((const quint64*)s2)[offset];
+                            sbuf2[i * 2 + 5] = ((const quint64*)s2)[offset + 1];
+                            offset = _mm_extract_epi16(v_fx, 7);
+                            sbuf1[i * 2 + 6] = ((const quint64*)s1)[offset];
+                            sbuf1[i * 2 + 7] = ((const quint64*)s1)[offset + 1];
+                            sbuf2[i * 2 + 6] = ((const quint64*)s2)[offset];
+                            sbuf2[i * 2 + 7] = ((const quint64*)s2)[offset + 1];
+                            v_fx = _mm_add_epi32(v_fx, v_fdx);
+                        }
+                    } else {
+                        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];
+                            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];
+                            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];
+                            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];
+                            v_fx = _mm_add_epi32(v_fx, v_fdx);
+                        }
                     }
                     fx = _mm_cvtsi128_si32(v_fx);
                 }
@@ -2819,12 +3077,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) {
+                    if (layout->bpp == QPixelLayout::BPP64) {
+                        sbuf1[i * 2 + 0] = ((const quint64*)s1)[x1];
+                        sbuf1[i * 2 + 1] = ((const quint64*)s1)[x2];
+                        sbuf2[i * 2 + 0] = ((const quint64*)s2)[x1];
+                        sbuf2[i * 2 + 1] = ((const quint64*)s2)[x2];
+                    } else 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);
@@ -2862,11 +3124,11 @@ 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];
+            FetchPixelFunc64 fetch = qFetchPixel64[layout->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;
 
@@ -2876,7 +3138,8 @@ static const QRgba64 *QT_FASTCALL fetchTransformedBilinear64(QRgba64 *buffer, co
                 int fracY = fy;
                 int i = 0;
 #if defined(__SSE2__)
-                if (blendType != BlendTransformedBilinearTiled && layout->bpp == QPixelLayout::BPP32) {
+                if (blendType != BlendTransformedBilinearTiled
+                    && (layout->bpp == QPixelLayout::BPP32 || layout->bpp == QPixelLayout::BPP64)) {
                     for (; i < len; ++i) {
                         int x1 = (fx >> 16);
                         int x2;
@@ -2888,10 +3151,17 @@ static const QRgba64 *QT_FASTCALL fetchTransformedBilinear64(QRgba64 *buffer, co
                             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];
+                        if (layout->bpp == QPixelLayout::BPP64) {
+                            sbuf1[i * 2 + 0] = ((const quint64*)s1)[x1];
+                            sbuf1[i * 2 + 1] = ((const quint64*)s1)[x2];
+                            sbuf2[i * 2 + 0] = ((const quint64*)s2)[x1];
+                            sbuf2[i * 2 + 1] = ((const quint64*)s2)[x2];
+                        } else {
+                            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];
+                        }
                         fx += fdx;
                         fy += fdy;
                     }
@@ -2903,7 +3173,8 @@ static const QRgba64 *QT_FASTCALL fetchTransformedBilinear64(QRgba64 *buffer, co
                     const int bytesPerLine = data->texture.bytesPerLine;
                     const uchar *s1 = data->texture.imageData;
                     const uchar *s2 = s1 + bytesPerLine;
-                    const __m128i vbpl = _mm_shufflelo_epi16(_mm_cvtsi32_si128(bytesPerLine/4), _MM_SHUFFLE(0, 0, 0, 0));
+                    int pbl = (layout->bpp == QPixelLayout::BPP64) ? bytesPerLine/8 : bytesPerLine/4;
+                    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 +3189,47 @@ 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];
-                        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];
-                        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];
-                        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];
-
+                        if (layout->bpp == QPixelLayout::BPP64) {
+                            sbuf1[i * 2 + 0] = ((const quint64*)s1)[offset];
+                            sbuf1[i * 2 + 1] = ((const quint64*)s1)[offset + 1];
+                            sbuf2[i * 2 + 0] = ((const quint64*)s2)[offset];
+                            sbuf2[i * 2 + 1] = ((const quint64*)s2)[offset + 1];
+                            offset = _mm_cvtsi128_si32(voffset); voffset = _mm_srli_si128(voffset, 4);
+                            sbuf1[i * 2 + 2] = ((const quint64*)s1)[offset];
+                            sbuf1[i * 2 + 3] = ((const quint64*)s1)[offset + 1];
+                            sbuf2[i * 2 + 2] = ((const quint64*)s2)[offset];
+                            sbuf2[i * 2 + 3] = ((const quint64*)s2)[offset + 1];
+                            offset = _mm_cvtsi128_si32(voffset); voffset = _mm_srli_si128(voffset, 4);
+                            sbuf1[i * 2 + 4] = ((const quint64*)s1)[offset];
+                            sbuf1[i * 2 + 5] = ((const quint64*)s1)[offset + 1];
+                            sbuf2[i * 2 + 4] = ((const quint64*)s2)[offset];
+                            sbuf2[i * 2 + 5] = ((const quint64*)s2)[offset + 1];
+                            offset = _mm_cvtsi128_si32(voffset);
+                            sbuf1[i * 2 + 6] = ((const quint64*)s1)[offset];
+                            sbuf1[i * 2 + 7] = ((const quint64*)s1)[offset + 1];
+                            sbuf2[i * 2 + 6] = ((const quint64*)s2)[offset];
+                            sbuf2[i * 2 + 7] = ((const quint64*)s2)[offset + 1];
+                        } else {
+                            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];
+                            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];
+                            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];
+                            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];
+                        }
                         v_fx = _mm_add_epi32(v_fx, v_fdx);
                         v_fy = _mm_add_epi32(v_fy, v_fdy);
                     }
@@ -2956,12 +3248,16 @@ static const QRgba64 *QT_FASTCALL fetchTransformedBilinear64(QRgba64 *buffer, co
                     const uchar *s1 = data->texture.scanLine(y1);
                     const uchar *s2 = data->texture.scanLine(y2);
 
-                    if (layout->bpp == QPixelLayout::BPP32) {
+                    if (layout->bpp == QPixelLayout::BPP64) {
+                        sbuf1[i * 2 + 0] = ((const quint64*)s1)[x1];
+                        sbuf1[i * 2 + 1] = ((const quint64*)s1)[x2];
+                        sbuf2[i * 2 + 0] = ((const quint64*)s2)[x1];
+                        sbuf2[i * 2 + 1] = ((const quint64*)s2)[x2];
+                    } else 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);
@@ -2992,11 +3288,11 @@ static const QRgba64 *QT_FASTCALL fetchTransformedBilinear64(QRgba64 *buffer, co
         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];
+        FetchPixelFunc64 fetch = qFetchPixel64[layout->bpp];
         QRgba64 buf1[buffer_size];
         QRgba64 buf2[buffer_size];
+        quint64 *sbuf1 = reinterpret_cast<quint64*>(buf1);
+        quint64 *sbuf2 = reinterpret_cast<quint64*>(buf2);
         QRgba64 *b = buffer;
 
         int distxs[buffer_size / 2];
@@ -3023,12 +3319,16 @@ static const QRgba64 *QT_FASTCALL fetchTransformedBilinear64(QRgba64 *buffer, co
                 const uchar *s1 = data->texture.scanLine(y1);
                 const uchar *s2 = data->texture.scanLine(y2);
 
-                if (layout->bpp == QPixelLayout::BPP32) {
+                if (layout->bpp == QPixelLayout::BPP64) {
+                    sbuf1[i * 2 + 0] = ((const quint64*)s1)[x1];
+                    sbuf1[i * 2 + 1] = ((const quint64*)s1)[x2];
+                    sbuf2[i * 2 + 0] = ((const quint64*)s2)[x1];
+                    sbuf2[i * 2 + 1] = ((const quint64*)s2)[x2];
+                } else 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);
@@ -3089,6 +3389,9 @@ static SourceFetchProc sourceFetch[NBlendTypes][QImage::NImageFormats] = {
         fetchUntransformed,         // Format_A2RGB30_Premultiplied
         fetchUntransformed,         // Alpha8
         fetchUntransformed,         // Grayscale8
+        fetchUntransformed,
+        fetchUntransformed,
+        fetchUntransformed,
     },
     // Tiled
     {
@@ -3117,6 +3420,9 @@ static SourceFetchProc sourceFetch[NBlendTypes][QImage::NImageFormats] = {
         fetchUntransformed,         // A2RGB30_Premultiplied
         fetchUntransformed,         // Alpha8
         fetchUntransformed,         // Grayscale8
+        fetchUntransformed,
+        fetchUntransformed,
+        fetchUntransformed,
     },
     // Transformed
     {
@@ -3145,6 +3451,9 @@ static SourceFetchProc sourceFetch[NBlendTypes][QImage::NImageFormats] = {
         fetchTransformed<BlendTransformed>,         // A2RGB30_Premultiplied
         fetchTransformed<BlendTransformed>,         // Alpah8
         fetchTransformed<BlendTransformed>,         // Grayscale8
+        fetchTransformed<BlendTransformed>,         // Grayscale16
+        fetchTransformed<BlendTransformed>,         // RGB48
+        fetchTransformed<BlendTransformed>,         // RGBA64_Premultiplied
     },
     {
         0, // TransformedTiled
@@ -3172,6 +3481,9 @@ static SourceFetchProc sourceFetch[NBlendTypes][QImage::NImageFormats] = {
         fetchTransformed<BlendTransformedTiled>,            // A2RGB30_Premultiplied
         fetchTransformed<BlendTransformedTiled>,            // Alpha8
         fetchTransformed<BlendTransformedTiled>,            // Grayscale8
+        fetchTransformed<BlendTransformedTiled>,            // Grayscale16
+        fetchTransformed<BlendTransformedTiled>,            // RGB48
+        fetchTransformed<BlendTransformedTiled>,            // RGBA64_Premultiplied
     },
     {
         0, // Bilinear
@@ -3199,6 +3511,9 @@ static SourceFetchProc sourceFetch[NBlendTypes][QImage::NImageFormats] = {
         fetchTransformedBilinear<BlendTransformedBilinear>,         // A2RGB30_Premultiplied
         fetchTransformedBilinear<BlendTransformedBilinear>,         // Alpha8
         fetchTransformedBilinear<BlendTransformedBilinear>,         // Grayscale8
+        fetchTransformedBilinear<BlendTransformedBilinear>,         // Grayscale16
+        fetchTransformedBilinear<BlendTransformedBilinear>,         // RGB48
+        fetchTransformedBilinear<BlendTransformedBilinear>,         // RGBA64_Premultiplied
     },
     {
         0, // BilinearTiled
@@ -3226,6 +3541,9 @@ static SourceFetchProc sourceFetch[NBlendTypes][QImage::NImageFormats] = {
         fetchTransformedBilinear<BlendTransformedBilinearTiled>,            // A2RGB30_Premultiplied
         fetchTransformedBilinear<BlendTransformedBilinearTiled>,            // Alpha8
         fetchTransformedBilinear<BlendTransformedBilinearTiled>,            // Grayscale8
+        fetchTransformedBilinear<BlendTransformedBilinearTiled>,            // Grayscale16
+        fetchTransformedBilinear<BlendTransformedBilinearTiled>,            // RGB48
+        fetchTransformedBilinear<BlendTransformedBilinearTiled>,            // RGBA64_Premultiplied
     },
 };
 
@@ -3257,6 +3575,9 @@ static SourceFetchProc64 sourceFetch64[NBlendTypes][QImage::NImageFormats] = {
         fetchUntransformed64,         // Format_A2RGB30_Premultiplied
         fetchUntransformed64,         // Alpha8
         fetchUntransformed64,         // Grayscale8
+        fetchUntransformed64,         // Grayscale16
+        fetchUntransformedRGBA64PM,   // RGBX64
+        fetchUntransformedRGBA64PM,   // RGBA64_Premultiplied
     },
     // Tiled
     {
@@ -3285,6 +3606,9 @@ static SourceFetchProc64 sourceFetch64[NBlendTypes][QImage::NImageFormats] = {
         fetchUntransformed64,         // A2RGB30_Premultiplied
         fetchUntransformed64,         // Alpha8
         fetchUntransformed64,         // Grayscale8
+        fetchUntransformed64,         // Grayscale16
+        fetchUntransformedRGBA64PM,   // RGBX64
+        fetchUntransformedRGBA64PM,   // RGBA64_Premultiplied
     },
     // Transformed
     {
@@ -3313,6 +3637,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 +3667,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 +3697,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 +3727,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 +4202,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 +4392,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 +4408,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 +4516,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 +4761,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 +5649,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
     {
@@ -5365,6 +5708,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 +5738,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 +5769,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 +5800,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, // Grayscale16
+        blend_src_generic_rgb64, // RGB48
+        blend_src_generic_rgb64, // RGBA64_Premultiplied
     }
 };
 
@@ -6014,6 +6369,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 +6575,26 @@ DrawHelper qDrawHelper[QImage::NImageFormats] =
         0, 0, 0,
         qt_rectfill_gray
     },
+    // Format_Grayscale16
+    {
+        blend_color_generic_rgb64,
+        blend_src_generic_rgb64,
+        0, 0, 0, 0
+    },
+    // Format_RGBX64
+    {
+        blend_color_generic_rgb64,
+        blend_src_generic_rgb64,
+        0, 0, 0,
+        qt_rectfill_rgb64
+    },
+    // 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..4271a18 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;
 }
 
@@ -1104,7 +1110,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 +1124,7 @@ struct QPixelLayout
         BPP16,
         BPP24,
         BPP32,
+        BPP64,
         BPPCount
     };
 
@@ -1141,11 +1148,14 @@ struct QPixelLayout
 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);
 
+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 FetchPixelsFunc qFetchPixels[QPixelLayout::BPPCount];
 extern StorePixelsFunc qStorePixels[QPixelLayout::BPPCount];
-
-
+extern FetchPixelsFunc64 qFetchPixels64[QPixelLayout::BPPCount];
+extern StorePixelsFunc64 qStorePixels64[QPixelLayout::BPPCount];
 
 QT_END_NAMESPACE
 
diff --git a/src/gui/painting/qmemrotate.cpp b/src/gui/painting/qmemrotate.cpp
index f205cb1..9b8958a 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_16, qt_memrotate180_16, qt_memrotate270_16 },      // Format_Grayscale16,
+    { qt_memrotate90_64, qt_memrotate180_64, qt_memrotate270_64 },      // Format_RGBX64
+    { 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/src/gui/painting/qrgb.h b/src/gui/painting/qrgb.h
index 05b3a76..7acbdb3 100644
--- a/src/gui/painting/qrgb.h
+++ b/src/gui/painting/qrgb.h
@@ -68,12 +68,19 @@ inline Q_DECL_CONSTEXPR QRgb qRgb(int r, int g, int b)// set RGB value
 inline Q_DECL_CONSTEXPR QRgb qRgba(int r, int g, int b, int a)// set RGBA value
 { return ((a & 0xff) << 24) | ((r & 0xff) << 16) | ((g & 0xff) << 8) | (b & 0xff); }
 
-inline Q_DECL_CONSTEXPR int qGray(int r, int g, int b)// convert R,G,B to gray 0..255
+inline Q_DECL_CONSTEXPR int qGray(int r, int g, int b)      // convert R,G,B to gray 0..255
 { return (r*11+g*16+b*5)/32; }
 
-inline Q_DECL_CONSTEXPR int qGray(QRgb rgb)                // convert RGB to gray 0..255
+inline Q_DECL_CONSTEXPR int qGray16(int r, int g, int b)    // convert R,G,B to gray 0..65535
+{ return (r*110+g*366+b*38)/2; }
+//{ return (r*299+g*587+b*138+2)/4; }
+
+inline Q_DECL_CONSTEXPR int qGray(QRgb rgb)                 // convert RGB to gray 0..255
 { return qGray(qRed(rgb), qGreen(rgb), qBlue(rgb)); }
 
+inline Q_DECL_CONSTEXPR int qGray16(QRgb rgb)               // convert RGB to gray 0..65535
+{ return qGray16(qRed(rgb), qGreen(rgb), qBlue(rgb)); }
+
 inline Q_DECL_CONSTEXPR bool qIsGray(QRgb rgb)
 { return qRed(rgb) == qGreen(rgb) && qRed(rgb) == qBlue(rgb); }
 
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);
     }
 }
 
