WebKitTools/DumpRenderTree/qt/ImageDiff.cpp
changeset 2 303757a437d3
parent 0 4f2f89ce4247
equal deleted inserted replaced
0:4f2f89ce4247 2:303757a437d3
     1 /*
       
     2     Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies)
       
     3 
       
     4     This library is free software; you can redistribute it and/or
       
     5     modify it under the terms of the GNU Library General Public
       
     6     License as published by the Free Software Foundation; either
       
     7     version 2 of the License, or (at your option) any later version.
       
     8 
       
     9     This library is distributed in the hope that it will be useful,
       
    10     but WITHOUT ANY WARRANTY; without even the implied warranty of
       
    11     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
       
    12     Library General Public License for more details.
       
    13 
       
    14     You should have received a copy of the GNU Library General Public License
       
    15     along with this library; see the file COPYING.LIB.  If not, write to
       
    16     the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
       
    17     Boston, MA 02110-1301, USA.
       
    18 */
       
    19 
       
    20 #include <QtCore/qmath.h>
       
    21 
       
    22 #include <QApplication>
       
    23 #include <QBuffer>
       
    24 #include <QByteArray>
       
    25 #include <QImage>
       
    26 #include <QStringList>
       
    27 
       
    28 #include <stdio.h>
       
    29 
       
    30 int main(int argc, char* argv[])
       
    31 {
       
    32     QCoreApplication app(argc, argv);
       
    33 
       
    34     qreal tolerance = 0;
       
    35 
       
    36     QStringList args = app.arguments();
       
    37     for (int i = 0; i < argc; ++i)
       
    38         if (args[i] == "-t" || args[i] == "--tolerance")
       
    39             tolerance = args[i + 1].toDouble();
       
    40 
       
    41     char buffer[2048];
       
    42     QImage actualImage;
       
    43     QImage baselineImage;
       
    44 
       
    45     while (fgets(buffer, sizeof(buffer), stdin)) {
       
    46         // remove the CR
       
    47         char* newLineCharacter = strchr(buffer, '\n');
       
    48         if (newLineCharacter)
       
    49             *newLineCharacter = '\0';
       
    50 
       
    51         if (!strncmp("Content-Length: ", buffer, 16)) {
       
    52             strtok(buffer, " ");
       
    53             int imageSize = strtol(strtok(0, " "), 0, 10);
       
    54 
       
    55             if (imageSize <= 0) {
       
    56                 fputs("error, image size must be specified.\n", stdout);
       
    57             } else {
       
    58                 unsigned char buffer[2048];
       
    59                 QBuffer data;
       
    60 
       
    61                 // Read all the incoming chunks
       
    62                 data.open(QBuffer::WriteOnly);
       
    63                 while (imageSize > 0) {
       
    64                     size_t bytesToRead = qMin(imageSize, 2048);
       
    65                     size_t bytesRead = fread(buffer, 1, bytesToRead, stdin);
       
    66                     data.write(reinterpret_cast<const char*>(buffer), bytesRead);
       
    67                     imageSize -= static_cast<int>(bytesRead);
       
    68                 }
       
    69 
       
    70                 // Convert into QImage
       
    71                 QImage decodedImage;
       
    72                 decodedImage.loadFromData(data.data(), "PNG");
       
    73                 decodedImage.convertToFormat(QImage::Format_ARGB32);
       
    74 
       
    75                 // Place it in the right place
       
    76                 if (actualImage.isNull())
       
    77                     actualImage = decodedImage;
       
    78                 else
       
    79                     baselineImage = decodedImage;
       
    80             }
       
    81         }
       
    82 
       
    83         if (!actualImage.isNull() && !baselineImage.isNull()) {
       
    84 
       
    85             if (actualImage.size() != baselineImage.size()) {
       
    86                 fprintf(stderr, "error, test and reference image have different properties.\n");
       
    87                 fflush(stderr);
       
    88             } else {
       
    89 
       
    90                 int w = actualImage.width();
       
    91                 int h = actualImage.height();
       
    92                 QImage diffImage(w, h, QImage::Format_ARGB32);
       
    93 
       
    94                 int count = 0;
       
    95                 qreal sum = 0;
       
    96                 qreal maxDistance = 0;
       
    97 
       
    98                 for (int x = 0; x < w; ++x)
       
    99                     for (int y = 0; y < h; ++y) {
       
   100                         QRgb pixel = actualImage.pixel(x, y);
       
   101                         QRgb basePixel = baselineImage.pixel(x, y);
       
   102                         qreal red = (qRed(pixel) - qRed(basePixel)) / static_cast<float>(qMax(255 - qRed(basePixel), qRed(basePixel)));
       
   103                         qreal green = (qGreen(pixel) - qGreen(basePixel)) / static_cast<float>(qMax(255 - qGreen(basePixel), qGreen(basePixel)));
       
   104                         qreal blue = (qBlue(pixel) - qBlue(basePixel)) / static_cast<float>(qMax(255 - qBlue(basePixel), qBlue(basePixel)));
       
   105                         qreal alpha = (qAlpha(pixel) - qAlpha(basePixel)) / static_cast<float>(qMax(255 - qAlpha(basePixel), qAlpha(basePixel)));
       
   106                         qreal distance = qSqrt(red * red + green * green + blue * blue + alpha * alpha) / 2.0f;
       
   107                         int gray = distance * qreal(255);
       
   108                         diffImage.setPixel(x, y, qRgb(gray, gray, gray));
       
   109                         if (distance >= 1 / qreal(255)) {
       
   110                             count++;
       
   111                             sum += distance;
       
   112                             maxDistance = qMax(maxDistance, distance);
       
   113                         }
       
   114                 }
       
   115 
       
   116                 qreal difference = 0;
       
   117                 if (count)
       
   118                     difference = 100 * sum / static_cast<qreal>(w * h);
       
   119                 if (difference <= tolerance) {
       
   120                     difference = 0;
       
   121                 } else {
       
   122                     difference = qRound(difference * 100) / 100;
       
   123                     difference = qMax(difference, qreal(0.01));
       
   124                 }
       
   125 
       
   126                 if (!count) {
       
   127                     fprintf(stdout, "diff: %01.2f%% passed\n", difference);
       
   128                 } else {
       
   129                     QBuffer buffer;
       
   130                     buffer.open(QBuffer::WriteOnly);
       
   131                     diffImage.save(&buffer, "PNG");
       
   132                     buffer.close();
       
   133                     const QByteArray &data = buffer.data();
       
   134                     printf("Content-Length: %lu\n", static_cast<unsigned long>(data.length()));
       
   135                     fwrite(data.constData(), 1, data.length(), stdout);
       
   136 
       
   137                     fprintf(stdout, "diff: %01.2f%% failed\n", difference);
       
   138                 }
       
   139 
       
   140                 fflush(stdout);
       
   141             }
       
   142         }
       
   143     }
       
   144 
       
   145     return 0;
       
   146 }