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 |