Home | History | Annotate | Download | only in skpdiff
      1 /*
      2  * Copyright 2013 Google Inc.
      3  *
      4  * Use of this source code is governed by a BSD-style license that can be
      5  * found in the LICENSE file.
      6  */
      7 
      8 #include <cstring>
      9 
     10 #include "SkBitmap.h"
     11 
     12 #include "SkDifferentPixelsMetric.h"
     13 #include "skpdiff_util.h"
     14 
     15 struct SkDifferentPixelsMetric::QueuedDiff {
     16     bool finished;
     17     double result;
     18     SkTDArray<SkIPoint>* poi;
     19 };
     20 
     21 const char* SkDifferentPixelsMetric::getName() {
     22     return "different_pixels";
     23 }
     24 
     25 int SkDifferentPixelsMetric::queueDiff(SkBitmap* baseline, SkBitmap* test) {
     26     double startTime = get_seconds();
     27     int diffID = fQueuedDiffs.count();
     28     QueuedDiff* diff = fQueuedDiffs.push();
     29     SkTDArray<SkIPoint>* poi = diff->poi = new SkTDArray<SkIPoint>();
     30 
     31     // If we never end up running the kernel, include some safe defaults in the result.
     32     diff->finished = false;
     33     diff->result = -1;
     34 
     35     // Ensure the images are comparable
     36     if (baseline->width() != test->width() || baseline->height() != test->height() ||
     37         baseline->width() <= 0 || baseline->height() <= 0 ||
     38         baseline->config() != test->config()) {
     39         diff->finished = true;
     40         return diffID;
     41     }
     42 
     43     int width = baseline->width();
     44     int height = baseline->height();
     45     int differentPixelsCount = 0;
     46 
     47     // Prepare the pixels for comparison
     48     baseline->lockPixels();
     49     test->lockPixels();
     50     for (int y = 0; y < height; y++) {
     51         // Grab a row from each image for easy comparison
     52         unsigned char* baselineRow = (unsigned char*)baseline->getAddr(0, y);
     53         unsigned char* testRow = (unsigned char*)test->getAddr(0, y);
     54         for (int x = 0; x < width; x++) {
     55             // Compare one pixel at a time so each differing pixel can be noted
     56             if (std::memcmp(&baselineRow[x * 4], &testRow[x * 4], 4) != 0) {
     57                 poi->push()->set(x, y);
     58                 differentPixelsCount++;
     59             }
     60         }
     61     }
     62     test->unlockPixels();
     63     baseline->unlockPixels();
     64 
     65     // Calculates the percentage of identical pixels
     66     diff->result = 1.0 - ((double)differentPixelsCount / (width * height));
     67 
     68     SkDebugf("Time: %f\n", (get_seconds() - startTime));
     69 
     70     return diffID;
     71 }
     72 
     73 void SkDifferentPixelsMetric::deleteDiff(int id) {
     74     if (NULL != fQueuedDiffs[id].poi)
     75     {
     76         delete fQueuedDiffs[id].poi;
     77         fQueuedDiffs[id].poi = NULL;
     78     }
     79 }
     80 
     81 bool SkDifferentPixelsMetric::isFinished(int id) {
     82     return fQueuedDiffs[id].finished;
     83 }
     84 
     85 double SkDifferentPixelsMetric::getResult(int id) {
     86     return fQueuedDiffs[id].result;
     87 }
     88 
     89 int SkDifferentPixelsMetric::getPointsOfInterestCount(int id) {
     90     return fQueuedDiffs[id].poi->count();
     91 }
     92 
     93 SkIPoint* SkDifferentPixelsMetric::getPointsOfInterest(int id) {
     94     return fQueuedDiffs[id].poi->begin();
     95 }
     96