OLD | NEW |
1 #include <cmath> | 1 #include <cmath> |
2 | 2 |
3 #include "SkBitmap.h" | 3 #include "SkBitmap.h" |
4 #include "skpdiff_util.h" | 4 #include "skpdiff_util.h" |
5 #include "SkPMetric.h" | 5 #include "SkPMetric.h" |
6 #include "SkPMetricUtil_generated.h" | 6 #include "SkPMetricUtil_generated.h" |
7 | 7 |
8 struct RGB { | 8 struct RGB { |
9 float r, g, b; | 9 float r, g, b; |
10 }; | 10 }; |
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
116 } else { | 116 } else { |
117 f[i] = 7.787f * f[i] + 4.0f / 29.0f; | 117 f[i] = 7.787f * f[i] + 4.0f / 29.0f; |
118 } | 118 } |
119 } | 119 } |
120 lab->l = 116.0f * f[1] - 16.0f; | 120 lab->l = 116.0f * f[1] - 16.0f; |
121 lab->a = 500.0f * (f[0] - f[1]); | 121 lab->a = 500.0f * (f[0] - f[1]); |
122 lab->b = 200.0f * (f[1] - f[2]); | 122 lab->b = 200.0f * (f[1] - f[2]); |
123 } | 123 } |
124 | 124 |
125 /// Converts a 8888 bitmap to LAB color space and puts it into the output | 125 /// Converts a 8888 bitmap to LAB color space and puts it into the output |
126 static void bitmap_to_cielab(const SkBitmap* bitmap, ImageLAB* outImageLAB) { | 126 static bool bitmap_to_cielab(const SkBitmap* bitmap, ImageLAB* outImageLAB) { |
127 SkASSERT(bitmap->config() == SkBitmap::kARGB_8888_Config); | 127 SkBitmap bm8888; |
| 128 if (bitmap->config() != SkBitmap::kARGB_8888_Config) { |
| 129 if (!bitmap->copyTo(&bm8888, SkBitmap::kARGB_8888_Config)) { |
| 130 return false; |
| 131 } |
| 132 bitmap = &bm8888; |
| 133 } |
128 | 134 |
129 int width = bitmap->width(); | 135 int width = bitmap->width(); |
130 int height = bitmap->height(); | 136 int height = bitmap->height(); |
131 SkASSERT(outImageLAB->width == width); | 137 SkASSERT(outImageLAB->width == width); |
132 SkASSERT(outImageLAB->height == height); | 138 SkASSERT(outImageLAB->height == height); |
133 | 139 |
134 bitmap->lockPixels(); | 140 bitmap->lockPixels(); |
135 RGB rgb; | 141 RGB rgb; |
136 LAB lab; | 142 LAB lab; |
137 for (int y = 0; y < height; y++) { | 143 for (int y = 0; y < height; y++) { |
138 unsigned char* row = (unsigned char*)bitmap->getAddr(0, y); | 144 unsigned char* row = (unsigned char*)bitmap->getAddr(0, y); |
139 for (int x = 0; x < width; x++) { | 145 for (int x = 0; x < width; x++) { |
140 // Perform gamma correction which is assumed to be 2.2 | 146 // Perform gamma correction which is assumed to be 2.2 |
141 rgb.r = SkPMetricUtil::get_gamma(row[x * 4 + 2]); | 147 rgb.r = SkPMetricUtil::get_gamma(row[x * 4 + 2]); |
142 rgb.g = SkPMetricUtil::get_gamma(row[x * 4 + 1]); | 148 rgb.g = SkPMetricUtil::get_gamma(row[x * 4 + 1]); |
143 rgb.b = SkPMetricUtil::get_gamma(row[x * 4 + 0]); | 149 rgb.b = SkPMetricUtil::get_gamma(row[x * 4 + 0]); |
144 adobergb_to_cielab(rgb.r, rgb.g, rgb.b, &lab); | 150 adobergb_to_cielab(rgb.r, rgb.g, rgb.b, &lab); |
145 outImageLAB->writePixel(x, y, lab); | 151 outImageLAB->writePixel(x, y, lab); |
146 } | 152 } |
147 } | 153 } |
148 bitmap->unlockPixels(); | 154 bitmap->unlockPixels(); |
| 155 return true; |
149 } | 156 } |
150 | 157 |
151 // From Barten SPIE 1989 | 158 // From Barten SPIE 1989 |
152 static float contrast_sensitivity(float cyclesPerDegree, float luminance) { | 159 static float contrast_sensitivity(float cyclesPerDegree, float luminance) { |
153 float a = 440.0f * powf(1.0f + 0.7f / luminance, -0.2f); | 160 float a = 440.0f * powf(1.0f + 0.7f / luminance, -0.2f); |
154 float b = 0.3f * powf(1.0f + 100.0f / luminance, 0.15f); | 161 float b = 0.3f * powf(1.0f + 100.0f / luminance, 0.15f); |
155 return a * | 162 return a * |
156 cyclesPerDegree * | 163 cyclesPerDegree * |
157 expf(-b * cyclesPerDegree) * | 164 expf(-b * cyclesPerDegree) * |
158 sqrtf(1.0f + 0.06f * expf(b * cyclesPerDegree)); | 165 sqrtf(1.0f + 0.06f * expf(b * cyclesPerDegree)); |
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
262 int width = baselineLAB->width; | 269 int width = baselineLAB->width; |
263 int height = baselineLAB->height; | 270 int height = baselineLAB->height; |
264 int maxLevels = 0; | 271 int maxLevels = 0; |
265 | 272 |
266 // Calculates how many levels to make by how many times the image can be div
ided in two | 273 // Calculates how many levels to make by how many times the image can be div
ided in two |
267 int smallerDimension = width < height ? width : height; | 274 int smallerDimension = width < height ? width : height; |
268 for ( ; smallerDimension > 1; smallerDimension /= 2) { | 275 for ( ; smallerDimension > 1; smallerDimension /= 2) { |
269 maxLevels++; | 276 maxLevels++; |
270 } | 277 } |
271 | 278 |
| 279 // We'll be creating new arrays with maxLevels - 2, and ImageL3D requires ma
xLevels > 0, |
| 280 // so just return failure if we're less than 3. |
| 281 if (maxLevels <= 2) { |
| 282 return 0.0; |
| 283 } |
| 284 |
272 const float fov = SK_ScalarPI / 180.0f * 45.0f; | 285 const float fov = SK_ScalarPI / 180.0f * 45.0f; |
273 float contrastSensitivityMax = contrast_sensitivity(3.248f, 100.0f); | 286 float contrastSensitivityMax = contrast_sensitivity(3.248f, 100.0f); |
274 float pixelsPerDegree = width / (2.0f * tanf(fov * 0.5f) * 180.0f / SK_Scala
rPI); | 287 float pixelsPerDegree = width / (2.0f * tanf(fov * 0.5f) * 180.0f / SK_Scala
rPI); |
275 | 288 |
276 ImageL3D baselineL(width, height, maxLevels); | 289 ImageL3D baselineL(width, height, maxLevels); |
277 ImageL3D testL(width, height, maxLevels); | 290 ImageL3D testL(width, height, maxLevels); |
278 ImageL scratchImageL(width, height); | 291 ImageL scratchImageL(width, height); |
279 float* cyclesPerDegree = SkNEW_ARRAY(float, maxLevels); | 292 float* cyclesPerDegree = SkNEW_ARRAY(float, maxLevels); |
280 float* thresholdFactorFrequency = SkNEW_ARRAY(float, maxLevels - 2); | 293 float* thresholdFactorFrequency = SkNEW_ARRAY(float, maxLevels - 2); |
281 float* contrast = SkNEW_ARRAY(float, maxLevels - 2); | 294 float* contrast = SkNEW_ARRAY(float, maxLevels - 2); |
(...skipping 161 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
443 // Ensure the images are comparable | 456 // Ensure the images are comparable |
444 if (baseline->width() != test->width() || baseline->height() != test->height
() || | 457 if (baseline->width() != test->width() || baseline->height() != test->height
() || |
445 baseline->width() <= 0 || baseline->height() <= 0) { | 458 baseline->width() <= 0 || baseline->height() <= 0) { |
446 diff.finished = true; | 459 diff.finished = true; |
447 return diffID; | 460 return diffID; |
448 } | 461 } |
449 | 462 |
450 ImageLAB baselineLAB(baseline->width(), baseline->height()); | 463 ImageLAB baselineLAB(baseline->width(), baseline->height()); |
451 ImageLAB testLAB(baseline->width(), baseline->height()); | 464 ImageLAB testLAB(baseline->width(), baseline->height()); |
452 | 465 |
453 bitmap_to_cielab(baseline, &baselineLAB); | 466 if (!bitmap_to_cielab(baseline, &baselineLAB) || !bitmap_to_cielab(test, &te
stLAB)) { |
454 bitmap_to_cielab(test, &testLAB); | 467 return diffID; |
| 468 } |
455 | 469 |
456 diff.result = pmetric(&baselineLAB, &testLAB, &diff.poi); | 470 diff.result = pmetric(&baselineLAB, &testLAB, &diff.poi); |
457 | 471 |
458 SkDebugf("Time: %f\n", (get_seconds() - startTime)); | 472 SkDebugf("Time: %f\n", (get_seconds() - startTime)); |
459 | 473 |
460 return diffID; | 474 return diffID; |
461 } | 475 } |
462 | 476 |
463 | 477 |
464 void SkPMetric::deleteDiff(int id) { | 478 void SkPMetric::deleteDiff(int id) { |
465 // clean up the POI array to save space | 479 // clean up the POI array to save space |
466 return fQueuedDiffs[id].poi.reset(); | 480 return fQueuedDiffs[id].poi.reset(); |
467 } | 481 } |
468 | 482 |
469 bool SkPMetric::isFinished(int id) { | 483 bool SkPMetric::isFinished(int id) { |
470 return fQueuedDiffs[id].finished; | 484 return fQueuedDiffs[id].finished; |
471 } | 485 } |
472 | 486 |
473 double SkPMetric::getResult(int id) { | 487 double SkPMetric::getResult(int id) { |
474 return fQueuedDiffs[id].result; | 488 return fQueuedDiffs[id].result; |
475 } | 489 } |
476 | 490 |
477 int SkPMetric::getPointsOfInterestCount(int id) { | 491 int SkPMetric::getPointsOfInterestCount(int id) { |
478 return fQueuedDiffs[id].poi.count(); | 492 return fQueuedDiffs[id].poi.count(); |
479 } | 493 } |
480 | 494 |
481 SkIPoint* SkPMetric::getPointsOfInterest(int id) { | 495 SkIPoint* SkPMetric::getPointsOfInterest(int id) { |
482 return fQueuedDiffs[id].poi.begin(); | 496 return fQueuedDiffs[id].poi.begin(); |
483 } | 497 } |
OLD | NEW |