| 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 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 83 SkASSERT(z < slices); | 83 SkASSERT(z < slices); |
| 84 return image[z]; | 84 return image[z]; |
| 85 } | 85 } |
| 86 }; | 86 }; |
| 87 | 87 |
| 88 typedef ImageArray<float> ImageL3D; | 88 typedef ImageArray<float> ImageL3D; |
| 89 | 89 |
| 90 | 90 |
| 91 #define MAT_ROW_MULT(rc,gc,bc) r*rc + g*gc + b*bc | 91 #define MAT_ROW_MULT(rc,gc,bc) r*rc + g*gc + b*bc |
| 92 | 92 |
| 93 | 93 static void adobergb_to_cielab(float r, float g, float b, LAB* lab) { |
| 94 void adobergb_to_cielab(float r, float g, float b, LAB* lab) { | |
| 95 // Conversion of Adobe RGB to XYZ taken from from "Adobe RGB (1998) ColorIma
ge Encoding" | 94 // Conversion of Adobe RGB to XYZ taken from from "Adobe RGB (1998) ColorIma
ge Encoding" |
| 96 // URL:http://www.adobe.com/digitalimag/pdfs/AdobeRGB1998.pdf | 95 // URL:http://www.adobe.com/digitalimag/pdfs/AdobeRGB1998.pdf |
| 97 // Section: 4.3.5.3 | 96 // Section: 4.3.5.3 |
| 98 // See Also: http://en.wikipedia.org/wiki/Adobe_rgb | 97 // See Also: http://en.wikipedia.org/wiki/Adobe_rgb |
| 99 float x = MAT_ROW_MULT(0.57667f, 0.18556f, 0.18823f); | 98 float x = MAT_ROW_MULT(0.57667f, 0.18556f, 0.18823f); |
| 100 float y = MAT_ROW_MULT(0.29734f, 0.62736f, 0.07529f); | 99 float y = MAT_ROW_MULT(0.29734f, 0.62736f, 0.07529f); |
| 101 float z = MAT_ROW_MULT(0.02703f, 0.07069f, 0.99134f); | 100 float z = MAT_ROW_MULT(0.02703f, 0.07069f, 0.99134f); |
| 102 | 101 |
| 103 // The following is the white point in XYZ, so it's simply the row wise addi
tion of the above | 102 // The following is the white point in XYZ, so it's simply the row wise addi
tion of the above |
| 104 // matrix. | 103 // matrix. |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 145 adobergb_to_cielab(rgb.r, rgb.g, rgb.b, &lab); | 144 adobergb_to_cielab(rgb.r, rgb.g, rgb.b, &lab); |
| 146 outImageLAB->writePixel(x, y, lab); | 145 outImageLAB->writePixel(x, y, lab); |
| 147 } | 146 } |
| 148 } | 147 } |
| 149 bitmap->unlockPixels(); | 148 bitmap->unlockPixels(); |
| 150 } | 149 } |
| 151 | 150 |
| 152 // From Barten SPIE 1989 | 151 // From Barten SPIE 1989 |
| 153 static float contrast_sensitivity(float cyclesPerDegree, float luminance) { | 152 static float contrast_sensitivity(float cyclesPerDegree, float luminance) { |
| 154 float a = 440.0f * powf(1.0f + 0.7f / luminance, -0.2f); | 153 float a = 440.0f * powf(1.0f + 0.7f / luminance, -0.2f); |
| 155 float b = 0.3f * powf(1 + 100.0 / luminance, 0.15f); | 154 float b = 0.3f * powf(1.0f + 100.0f / luminance, 0.15f); |
| 156 return a * | 155 return a * |
| 157 cyclesPerDegree * | 156 cyclesPerDegree * |
| 158 expf(-b * cyclesPerDegree) * | 157 expf(-b * cyclesPerDegree) * |
| 159 sqrtf(1.0f + 0.06f * expf(b * cyclesPerDegree)); | 158 sqrtf(1.0f + 0.06f * expf(b * cyclesPerDegree)); |
| 160 } | 159 } |
| 161 | 160 |
| 162 #if 0 | 161 #if 0 |
| 163 // We're keeping these around for reference and in case the lookup tables are no
longer desired. | 162 // We're keeping these around for reference and in case the lookup tables are no
longer desired. |
| 164 // They are no longer called by any code in this file. | 163 // They are no longer called by any code in this file. |
| 165 | 164 |
| (...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 252 // As we move down, scroll the row pointers down with us | 251 // As we move down, scroll the row pointers down with us |
| 253 for (int y = 0; y < matrixCount - 1; y++) | 252 for (int y = 0; y < matrixCount - 1; y++) |
| 254 { | 253 { |
| 255 rowPtrs[y] = rowPtrs[y + 1]; | 254 rowPtrs[y] = rowPtrs[y + 1]; |
| 256 } | 255 } |
| 257 rowPtrs[matrixCount - 1] += imageL->width; | 256 rowPtrs[matrixCount - 1] += imageL->width; |
| 258 writeRow += imageL->width; | 257 writeRow += imageL->width; |
| 259 } | 258 } |
| 260 } | 259 } |
| 261 | 260 |
| 262 float pmetric(const ImageLAB* baselineLAB, const ImageLAB* testLAB, SkTDArray<Sk
IPoint>* poi) { | 261 static double pmetric(const ImageLAB* baselineLAB, const ImageLAB* testLAB, SkTD
Array<SkIPoint>* poi) { |
| 263 int width = baselineLAB->width; | 262 int width = baselineLAB->width; |
| 264 int height = baselineLAB->height; | 263 int height = baselineLAB->height; |
| 265 int maxLevels = (int)log2(width < height ? width : height); | 264 int maxLevels = 0; |
| 266 | 265 |
| 267 const float fov = M_PI / 180.0f * 45.0f; | 266 // 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; |
| 268 for ( ; smallerDimension > 1; smallerDimension /= 2) { |
| 269 maxLevels++; |
| 270 } |
| 271 |
| 272 const float fov = SK_ScalarPI / 180.0f * 45.0f; |
| 268 float contrastSensitivityMax = contrast_sensitivity(3.248f, 100.0f); | 273 float contrastSensitivityMax = contrast_sensitivity(3.248f, 100.0f); |
| 269 float pixelsPerDegree = width / (2.0f * tanf(fov * 0.5f) * 180.0f / M_PI); | 274 float pixelsPerDegree = width / (2.0f * tanf(fov * 0.5f) * 180.0f / SK_Scala
rPI); |
| 270 | 275 |
| 271 ImageL3D baselineL(width, height, maxLevels); | 276 ImageL3D baselineL(width, height, maxLevels); |
| 272 ImageL3D testL(width, height, maxLevels); | 277 ImageL3D testL(width, height, maxLevels); |
| 273 ImageL scratchImageL(width, height); | 278 ImageL scratchImageL(width, height); |
| 274 float* cyclesPerDegree = SkNEW_ARRAY(float, maxLevels); | 279 float* cyclesPerDegree = SkNEW_ARRAY(float, maxLevels); |
| 275 float* thresholdFactorFrequency = SkNEW_ARRAY(float, maxLevels - 2); | 280 float* thresholdFactorFrequency = SkNEW_ARRAY(float, maxLevels - 2); |
| 276 float* contrast = SkNEW_ARRAY(float, maxLevels - 2); | 281 float* contrast = SkNEW_ARRAY(float, maxLevels - 2); |
| 277 | 282 |
| 278 lab_to_l(baselineLAB, baselineL.getLayer(0)); | 283 lab_to_l(baselineLAB, baselineL.getLayer(0)); |
| 279 lab_to_l(testLAB, testL.getLayer(0)); | 284 lab_to_l(testLAB, testL.getLayer(0)); |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 319 float lTest; | 324 float lTest; |
| 320 baselineL.getLayer(0)->readPixel(x, y, &lBaseline); | 325 baselineL.getLayer(0)->readPixel(x, y, &lBaseline); |
| 321 testL.getLayer(0)->readPixel(x, y, &lTest); | 326 testL.getLayer(0)->readPixel(x, y, &lTest); |
| 322 | 327 |
| 323 float avgLBaseline; | 328 float avgLBaseline; |
| 324 float avgLTest; | 329 float avgLTest; |
| 325 baselineL.getLayer(maxLevels - 1)->readPixel(x, y, &avgLBaseline); | 330 baselineL.getLayer(maxLevels - 1)->readPixel(x, y, &avgLBaseline); |
| 326 testL.getLayer(maxLevels - 1)->readPixel(x, y, &avgLTest); | 331 testL.getLayer(maxLevels - 1)->readPixel(x, y, &avgLTest); |
| 327 | 332 |
| 328 float lAdapt = 0.5f * (avgLBaseline + avgLTest); | 333 float lAdapt = 0.5f * (avgLBaseline + avgLTest); |
| 329 if (lAdapt < 1e-5) { | 334 if (lAdapt < 1e-5f) { |
| 330 lAdapt = 1e-5; | 335 lAdapt = 1e-5f; |
| 331 } | 336 } |
| 332 | 337 |
| 333 float contrastSum = 0.0f; | 338 float contrastSum = 0.0f; |
| 334 for (int levelIndex = 0; levelIndex < maxLevels - 2; levelIndex++) { | 339 for (int levelIndex = 0; levelIndex < maxLevels - 2; levelIndex++) { |
| 335 float baselineL0, baselineL1, baselineL2; | 340 float baselineL0, baselineL1, baselineL2; |
| 336 float testL0, testL1, testL2; | 341 float testL0, testL1, testL2; |
| 337 baselineL.getLayer(levelIndex + 0)->readPixel(x, y, &baselineL0)
; | 342 baselineL.getLayer(levelIndex + 0)->readPixel(x, y, &baselineL0)
; |
| 338 testL. getLayer(levelIndex + 0)->readPixel(x, y, &testL0); | 343 testL. getLayer(levelIndex + 0)->readPixel(x, y, &testL0); |
| 339 baselineL.getLayer(levelIndex + 1)->readPixel(x, y, &baselineL1)
; | 344 baselineL.getLayer(levelIndex + 1)->readPixel(x, y, &baselineL1)
; |
| 340 testL. getLayer(levelIndex + 1)->readPixel(x, y, &testL1); | 345 testL. getLayer(levelIndex + 1)->readPixel(x, y, &testL1); |
| 341 baselineL.getLayer(levelIndex + 2)->readPixel(x, y, &baselineL2)
; | 346 baselineL.getLayer(levelIndex + 2)->readPixel(x, y, &baselineL2)
; |
| 342 testL. getLayer(levelIndex + 2)->readPixel(x, y, &testL2); | 347 testL. getLayer(levelIndex + 2)->readPixel(x, y, &testL2); |
| 343 | 348 |
| 344 float baselineContrast1 = fabsf(baselineL0 - baselineL1); | 349 float baselineContrast1 = fabsf(baselineL0 - baselineL1); |
| 345 float testContrast1 = fabsf(testL0 - testL1); | 350 float testContrast1 = fabsf(testL0 - testL1); |
| 346 float numerator = (baselineContrast1 > testContrast1) ? | 351 float numerator = (baselineContrast1 > testContrast1) ? |
| 347 baselineContrast1 : testContrast1; | 352 baselineContrast1 : testContrast1; |
| 348 | 353 |
| 349 float baselineContrast2 = fabsf(baselineL2); | 354 float baselineContrast2 = fabsf(baselineL2); |
| 350 float testContrast2 = fabsf(testL2); | 355 float testContrast2 = fabsf(testL2); |
| 351 float denominator = (baselineContrast2 > testContrast2) ? | 356 float denominator = (baselineContrast2 > testContrast2) ? |
| 352 baselineContrast2 : testContrast2; | 357 baselineContrast2 : testContrast2; |
| 353 | 358 |
| 354 // Avoid divides by close to zero | 359 // Avoid divides by close to zero |
| 355 if (denominator < 1e-5) { | 360 if (denominator < 1e-5f) { |
| 356 denominator = 1e-5; | 361 denominator = 1e-5f; |
| 357 } | 362 } |
| 358 contrast[levelIndex] = numerator / denominator; | 363 contrast[levelIndex] = numerator / denominator; |
| 359 contrastSum += contrast[levelIndex]; | 364 contrastSum += contrast[levelIndex]; |
| 360 } | 365 } |
| 361 | 366 |
| 362 if (contrastSum < 1e-5) { | 367 if (contrastSum < 1e-5f) { |
| 363 contrastSum = 1e-5; | 368 contrastSum = 1e-5f; |
| 364 } | 369 } |
| 365 | 370 |
| 366 float F = 0.0f; | 371 float F = 0.0f; |
| 367 for (int levelIndex = 0; levelIndex < maxLevels - 2; levelIndex++) { | 372 for (int levelIndex = 0; levelIndex < maxLevels - 2; levelIndex++) { |
| 368 float contrastSensitivity = contrastSensitivityTable[levelIndex
* 1000 + | 373 float contrastSensitivity = contrastSensitivityTable[levelIndex
* 1000 + |
| 369 (int)(lAdap
t * 10.0)]; | 374 (int)(lAdap
t * 10.0)]; |
| 370 float mask = SkPMetricUtil::get_visual_mask(contrast[levelIndex]
* | 375 float mask = SkPMetricUtil::get_visual_mask(contrast[levelIndex]
* |
| 371 contrastSensitivity)
; | 376 contrastSensitivity)
; |
| 372 | 377 |
| 373 F += contrast[levelIndex] + | 378 F += contrast[levelIndex] + |
| (...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 462 return fQueuedDiffs[id].result; | 467 return fQueuedDiffs[id].result; |
| 463 } | 468 } |
| 464 | 469 |
| 465 int SkPMetric::getPointsOfInterestCount(int id) { | 470 int SkPMetric::getPointsOfInterestCount(int id) { |
| 466 return fQueuedDiffs[id].poi.count(); | 471 return fQueuedDiffs[id].poi.count(); |
| 467 } | 472 } |
| 468 | 473 |
| 469 SkIPoint* SkPMetric::getPointsOfInterest(int id) { | 474 SkIPoint* SkPMetric::getPointsOfInterest(int id) { |
| 470 return fQueuedDiffs[id].poi.begin(); | 475 return fQueuedDiffs[id].poi.begin(); |
| 471 } | 476 } |
| OLD | NEW |