Title: [141886] trunk/Source/WebCore
Revision
141886
Author
[email protected]
Date
2013-02-05 04:57:01 -0800 (Tue, 05 Feb 2013)

Log Message

[Qt] RGB -> BGR is wrong on big endian
https://bugs.webkit.org/show_bug.cgi?id=107560

Reviewed by Jocelyn Turcotte.

Replace the conversion to methods that make it clearer what is going on.
The routines are also optimized compared to the existing by avoiding going
over slow Color constructor.

Tested by existing tests in canvas and fast/canvas.

* platform/graphics/Color.cpp:
(WebCore::colorFromPremultipliedARGB):
    Cleanup.
(WebCore::premultipliedARGBFromColor):
    Cleanup and correct for alpha = 0.
* platform/graphics/Color.h:
(WebCore):
* platform/graphics/qt/ImageBufferQt.cpp:
(WebCore::copyColorToRGBA):
(WebCore::copyRGBAToColor):
(WebCore::getImageData):
(WebCore::ImageBuffer::putByteArray):

Modified Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (141885 => 141886)


--- trunk/Source/WebCore/ChangeLog	2013-02-05 12:41:17 UTC (rev 141885)
+++ trunk/Source/WebCore/ChangeLog	2013-02-05 12:57:01 UTC (rev 141886)
@@ -1,3 +1,29 @@
+2013-02-05  Allan Sandfeld Jensen  <[email protected]>
+
+        [Qt] RGB -> BGR is wrong on big endian
+        https://bugs.webkit.org/show_bug.cgi?id=107560
+
+        Reviewed by Jocelyn Turcotte.
+
+        Replace the conversion to methods that make it clearer what is going on.
+        The routines are also optimized compared to the existing by avoiding going
+        over slow Color constructor.
+
+        Tested by existing tests in canvas and fast/canvas.
+
+        * platform/graphics/Color.cpp:
+        (WebCore::colorFromPremultipliedARGB):
+            Cleanup.
+        (WebCore::premultipliedARGBFromColor):
+            Cleanup and correct for alpha = 0.
+        * platform/graphics/Color.h:
+        (WebCore):
+        * platform/graphics/qt/ImageBufferQt.cpp:
+        (WebCore::copyColorToRGBA):
+        (WebCore::copyRGBAToColor):
+        (WebCore::getImageData):
+        (WebCore::ImageBuffer::putByteArray):
+
 2013-02-05  JungJik Lee  <[email protected]>
 
         [TexMap] Use visible as initial value of backface-visibility-property.

Modified: trunk/Source/WebCore/platform/graphics/Color.cpp (141885 => 141886)


--- trunk/Source/WebCore/platform/graphics/Color.cpp	2013-02-05 12:41:17 UTC (rev 141885)
+++ trunk/Source/WebCore/platform/graphics/Color.cpp	2013-02-05 12:57:01 UTC (rev 141886)
@@ -414,31 +414,30 @@
         saturation = ((max - min) / (2.0 - (max + min)));
 }
 
-Color colorFromPremultipliedARGB(unsigned pixelColor)
+Color colorFromPremultipliedARGB(RGBA32 pixelColor)
 {
-    Color color;
-
-    if (unsigned alpha = (pixelColor & 0xFF000000) >> 24) {
-        color = Color::createUnchecked(
-                        ((pixelColor & 0x00FF0000) >> 16) * 255 / alpha,
-                        ((pixelColor & 0x0000FF00) >> 8) * 255 / alpha,
-                         (pixelColor & 0x000000FF) * 255 / alpha,
-                          alpha);
+    int alpha = alphaChannel(pixelColor);
+    if (alpha && alpha < 255) {
+        return Color::createUnchecked(
+            redChannel(pixelColor) * 255 / alpha,
+            greenChannel(pixelColor) * 255 / alpha,
+            blueChannel(pixelColor) * 255 / alpha,
+            alpha);
     } else
-        color = Color(pixelColor);
-
-    return color;
+        return Color(pixelColor);
 }
 
-unsigned premultipliedARGBFromColor(const Color& color)
+RGBA32 premultipliedARGBFromColor(const Color& color)
 {
     unsigned pixelColor;
 
-    if (unsigned alpha = color.alpha()) {
-        pixelColor = alpha << 24 |
-             ((color.red() * alpha  + 254) / 255) << 16 | 
-             ((color.green() * alpha  + 254) / 255) << 8 | 
-             ((color.blue() * alpha  + 254) / 255);
+    unsigned alpha = color.alpha();
+    if (alpha < 255) {
+        pixelColor = Color::createUnchecked(
+            (color.red() * alpha  + 254) / 255,
+            (color.green() * alpha  + 254) / 255,
+            (color.blue() * alpha  + 254) / 255,
+            alpha).rgb();
     } else
          pixelColor = color.rgb();
 

Modified: trunk/Source/WebCore/platform/graphics/Color.h (141885 => 141886)


--- trunk/Source/WebCore/platform/graphics/Color.h	2013-02-05 12:41:17 UTC (rev 141885)
+++ trunk/Source/WebCore/platform/graphics/Color.h	2013-02-05 12:57:01 UTC (rev 141886)
@@ -182,8 +182,8 @@
     return !(a == b);
 }
 
-Color colorFromPremultipliedARGB(unsigned);
-unsigned premultipliedARGBFromColor(const Color&);
+Color colorFromPremultipliedARGB(RGBA32);
+RGBA32 premultipliedARGBFromColor(const Color&);
 
 inline Color blend(const Color& from, const Color& to, double progress, bool blendPremultiplied = true)
 {

Modified: trunk/Source/WebCore/platform/graphics/qt/ImageBufferQt.cpp (141885 => 141886)


--- trunk/Source/WebCore/platform/graphics/qt/ImageBufferQt.cpp	2013-02-05 12:41:17 UTC (rev 141885)
+++ trunk/Source/WebCore/platform/graphics/qt/ImageBufferQt.cpp	2013-02-05 12:57:01 UTC (rev 141886)
@@ -193,14 +193,19 @@
         m_data.m_painter->begin(&m_data.m_pixmap);
 }
 
-static inline quint32 convertABGRToARGB(quint32 pixel)
+static inline void copyColorToRGBA(Color& from, uchar* to)
 {
-    return ((pixel << 16) & 0xff0000) | ((pixel >> 16) & 0xff) | (pixel & 0xff00ff00);
+    // Copy from endian dependent 32bit ARGB to endian independent RGBA8888.
+    to[0] = from.red();
+    to[1] = from.green();
+    to[2] = from.blue();
+    to[3] = from.alpha();
 }
 
-static inline quint32 convertARGBToABGR(quint32 pixel)
+static inline void copyRGBAToColor(const uchar* from, Color& to)
 {
-    return convertABGRToARGB(pixel);
+    // Copy from endian independent RGBA8888 to endian dependent 32bit ARGB.
+    to = Color::createUnchecked(from[0], from[1], from[2], from[3]);
 }
 
 template <Multiply multiplied>
@@ -211,7 +216,7 @@
         return 0;
 
     RefPtr<Uint8ClampedArray> result = Uint8ClampedArray::createUninitialized(rect.width() * rect.height() * 4);
-    unsigned char* data = ""
+    uchar* resultData = result->data();
 
     if (rect.x() < 0 || rect.y() < 0 || rect.maxX() > size.width() || rect.maxY() > size.height())
         result->zeroFill();
@@ -238,27 +243,26 @@
         endy = size.height();
     int numRows = endy - originy;
 
+    const unsigned destBytesPerRow = 4 * rect.width();
+
     // NOTE: For unmultiplied data, we undo the premultiplication below.
     QImage image = imageData.toQImage().convertToFormat(QImage::Format_ARGB32_Premultiplied);
 
     ASSERT(!image.isNull());
 
-    const int bytesPerLine = image.bytesPerLine();
-    const uchar* bits = image.constBits();
-
-    quint32* destRows = reinterpret_cast_ptr<quint32*>(&data[desty * rect.width() * 4 + destx * 4]);
+    // The Canvas 2D Context expects RGBA order, while Qt uses 32bit QRgb (ARGB/BGRA).
     for (int y = 0; y < numRows; ++y) {
-        const quint32* scanLine = reinterpret_cast_ptr<const quint32*>(bits + (y + originy) * bytesPerLine);
-        for (int x = 0; x < numColumns; x++) {
-            QRgb pixel = scanLine[x + originx];
+        // This cast and the calls below relies on both QRgb and WebCore::RGBA32 being 32bit ARGB.
+        const unsigned* srcRow = reinterpret_cast<const unsigned*>(image.constScanLine(originy + y)) + originx;
+        uchar* destRow = resultData + (desty + y) * destBytesPerRow + destx * 4;
+        for (int x = 0; x < numColumns; x++, srcRow++, destRow += 4) {
             Color pixelColor;
             if (multiplied == Unmultiplied)
-                pixelColor = colorFromPremultipliedARGB(Color(qRed(pixel), qGreen(pixel), qBlue(pixel), qAlpha(pixel)).rgb());
+                pixelColor = colorFromPremultipliedARGB(*srcRow);
             else
-                pixelColor = Color(qRed(pixel), qGreen(pixel), qBlue(pixel), qAlpha(pixel));
-            destRows[x] = convertARGBToABGR(pixelColor.rgb());
+                pixelColor = Color(*srcRow);
+            copyColorToRGBA(pixelColor, destRow);
         }
-        destRows += rect.width();
     }
 
     return result.release();
@@ -302,25 +306,26 @@
     ASSERT(endy <= m_size.height());
     int numRows = endy - desty;
 
-    unsigned srcBytesPerRow = 4 * sourceSize.width();
+    const unsigned srcBytesPerRow = 4 * sourceSize.width();
 
     // NOTE: For unmultiplied input data, we do the premultiplication below.
     QImage image(numColumns, numRows, QImage::Format_ARGB32_Premultiplied);
-    uchar* bits = image.bits();
-    const int bytesPerLine = image.bytesPerLine();
 
-    const quint32* srcScanLine = reinterpret_cast_ptr<const quint32*>(source->data() + originy * srcBytesPerRow + originx * 4);
+    unsigned* destData = reinterpret_cast<unsigned*>(image.bits());
+    const uchar* srcData = source->data();
 
     for (int y = 0; y < numRows; ++y) {
-        quint32* destScanLine = reinterpret_cast_ptr<quint32*>(bits + y * bytesPerLine);
-        for (int x = 0; x < numColumns; x++) {
-            quint32 pixel = convertABGRToARGB(srcScanLine[x]);
+        const uchar* srcRow = srcData + (originy + y) * srcBytesPerRow + originx * 4;
+        // This cast and the calls below relies on both QRgb and WebCore::RGBA32 being 32bit ARGB.
+        unsigned* destRow = destData + y * numColumns;
+        for (int x = 0; x < numColumns; x++, srcRow += 4, destRow++) {
+            Color pixelColor;
+            copyRGBAToColor(srcRow, pixelColor);
             if (multiplied == Unmultiplied)
-                destScanLine[x] = premultipliedARGBFromColor(Color(pixel));
+                *destRow = premultipliedARGBFromColor(pixelColor);
             else
-                destScanLine[x] = pixel;
+                *destRow = pixelColor.rgb();
         }
-        srcScanLine += sourceSize.width();
     }
 
     bool isPainting = m_data.m_painter->isActive();
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to