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 | 6 |
7 struct RGB { | 7 struct RGB { |
8 float r, g, b; | 8 float r, g, b; |
9 }; | 9 }; |
10 | 10 |
(...skipping 20 matching lines...) Expand all Loading... | |
31 } | 31 } |
32 | 32 |
33 void readPixel(int x, int y, T* pixel) const { | 33 void readPixel(int x, int y, T* pixel) const { |
34 SkASSERT(x >= 0); | 34 SkASSERT(x >= 0); |
35 SkASSERT(y >= 0); | 35 SkASSERT(y >= 0); |
36 SkASSERT(x < width); | 36 SkASSERT(x < width); |
37 SkASSERT(y < height); | 37 SkASSERT(y < height); |
38 *pixel = image[y * width + x]; | 38 *pixel = image[y * width + x]; |
39 } | 39 } |
40 | 40 |
41 T* getRow(int y) const { | |
42 return &image[y * width]; | |
43 } | |
44 | |
41 void writePixel(int x, int y, const T& pixel) { | 45 void writePixel(int x, int y, const T& pixel) { |
42 SkASSERT(x >= 0); | 46 SkASSERT(x >= 0); |
43 SkASSERT(y >= 0); | 47 SkASSERT(y >= 0); |
44 SkASSERT(x < width); | 48 SkASSERT(x < width); |
45 SkASSERT(y < height); | 49 SkASSERT(y < height); |
46 image[y * width + x] = pixel; | 50 image[y * width + x] = pixel; |
47 } | 51 } |
48 }; | 52 }; |
49 | 53 |
50 typedef Image2D<float> ImageL; | 54 typedef Image2D<float> ImageL; |
(...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
184 for (int y = 0; y < imageLAB->height; y++) { | 188 for (int y = 0; y < imageLAB->height; y++) { |
185 for (int x = 0; x < imageLAB->width; x++) { | 189 for (int x = 0; x < imageLAB->width; x++) { |
186 LAB lab; | 190 LAB lab; |
187 imageLAB->readPixel(x, y, &lab); | 191 imageLAB->readPixel(x, y, &lab); |
188 outImageL->writePixel(x, y, lab.l); | 192 outImageL->writePixel(x, y, lab.l); |
189 } | 193 } |
190 } | 194 } |
191 } | 195 } |
192 | 196 |
193 /// Convolves an image with the given filter in one direction and saves it to th e output image | 197 /// Convolves an image with the given filter in one direction and saves it to th e output image |
194 static void convolve(const ImageL* imageL, | 198 static void convolve(const ImageL* imageL, bool vertical, ImageL* outImageL) { |
195 bool vertical, const float* matrix, int radius, | |
196 ImageL* outImageL) { | |
197 SkASSERT(imageL->width == outImageL->width); | 199 SkASSERT(imageL->width == outImageL->width); |
198 SkASSERT(imageL->height == outImageL->height); | 200 SkASSERT(imageL->height == outImageL->height); |
201 | |
202 const float matrix[] = { 0.05f, 0.25f, 0.4f, 0.25f, 0.05f }; | |
203 const int matrixCount = sizeof(matrix) / sizeof(float); | |
tfarina
2013/07/16 13:07:26
SK_ARRAY_COUNT?
| |
204 const int radius = matrixCount / 2; | |
205 | |
206 // Keep track of what rows are being operated on for quick access. | |
207 float* rowPtrs[matrixCount]; // Because matrixCount is constant, this won't create a VLA | |
208 for (int y = radius; y < matrixCount; y++) { | |
209 rowPtrs[y] = imageL->getRow(y - radius); | |
210 } | |
211 float* writeRow = outImageL->getRow(0); | |
212 | |
213 | |
199 for (int y = 0; y < imageL->height; y++) { | 214 for (int y = 0; y < imageL->height; y++) { |
200 for (int x = 0; x < imageL->width; x++) { | 215 for (int x = 0; x < imageL->width; x++) { |
201 float lSum = 0.0f; | 216 float lSum = 0.0f; |
202 float l; | |
203 for (int xx = -radius; xx <= radius; xx++) { | 217 for (int xx = -radius; xx <= radius; xx++) { |
204 int nx = x; | 218 int nx = x; |
205 int ny = y; | 219 int ny = y; |
206 | 220 |
207 // We mirror at edges so that edge pixels that the filter weight ing still makes | 221 // We mirror at edges so that edge pixels that the filter weight ing still makes |
208 // sense. | 222 // sense. |
209 if (vertical) { | 223 if (vertical) { |
210 ny += xx; | 224 ny += xx; |
211 if (ny < 0) { | 225 if (ny < 0) { |
212 ny = -ny; | 226 ny = -ny; |
213 } | 227 } |
214 if (ny >= imageL->height) { | 228 if (ny >= imageL->height) { |
215 ny = imageL->height + (imageL->height - ny - 1); | 229 ny = imageL->height + (imageL->height - ny - 1); |
216 } | 230 } |
217 } else { | 231 } else { |
218 nx += xx; | 232 nx += xx; |
219 if (nx < 0) { | 233 if (nx < 0) { |
220 nx = -nx; | 234 nx = -nx; |
221 } | 235 } |
222 if (nx >= imageL->width) { | 236 if (nx >= imageL->width) { |
223 nx = imageL->width + (imageL->width - nx - 1); | 237 nx = imageL->width + (imageL->width - nx - 1); |
224 } | 238 } |
225 } | 239 } |
226 | 240 |
227 imageL->readPixel(nx, ny, &l); | |
228 float weight = matrix[xx + radius]; | 241 float weight = matrix[xx + radius]; |
229 lSum += l * weight; | 242 lSum += rowPtrs[ny - y + radius][nx] * weight; |
230 } | 243 } |
231 outImageL->writePixel(x, y, lSum); | 244 writeRow[x] = lSum; |
232 } | 245 } |
246 // As we move down, scroll the row pointers down with us | |
247 for (int y = 0; y < matrixCount - 1; y++) | |
248 { | |
249 rowPtrs[y] = rowPtrs[y + 1]; | |
250 } | |
251 rowPtrs[matrixCount - 1] += imageL->width; | |
252 writeRow += imageL->width; | |
233 } | 253 } |
234 } | 254 } |
235 | 255 |
236 float pmetric(const ImageLAB* baselineLAB, const ImageLAB* testLAB, SkTDArray<Sk IPoint>* poi) { | 256 float pmetric(const ImageLAB* baselineLAB, const ImageLAB* testLAB, SkTDArray<Sk IPoint>* poi) { |
237 int width = baselineLAB->width; | 257 int width = baselineLAB->width; |
238 int height = baselineLAB->height; | 258 int height = baselineLAB->height; |
239 int maxLevels = (int)log2(width < height ? width : height); | 259 int maxLevels = (int)log2(width < height ? width : height); |
240 | 260 |
241 const float fov = M_PI / 180.0f * 45.0f; | 261 const float fov = M_PI / 180.0f * 45.0f; |
242 float contrastSensitivityMax = contrast_sensitivity(3.248f, 100.0f); | 262 float contrastSensitivityMax = contrast_sensitivity(3.248f, 100.0f); |
243 float pixelsPerDegree = width / (2.0f * tanf(fov * 0.5f) * 180.0f / M_PI); | 263 float pixelsPerDegree = width / (2.0f * tanf(fov * 0.5f) * 180.0f / M_PI); |
244 | 264 |
245 ImageL3D baselineL(width, height, maxLevels); | 265 ImageL3D baselineL(width, height, maxLevels); |
246 ImageL3D testL(width, height, maxLevels); | 266 ImageL3D testL(width, height, maxLevels); |
247 ImageL scratchImageL(width, height); | 267 ImageL scratchImageL(width, height); |
248 float* cyclesPerDegree = SkNEW_ARRAY(float, maxLevels); | 268 float* cyclesPerDegree = SkNEW_ARRAY(float, maxLevels); |
249 float* thresholdFactorFrequency = SkNEW_ARRAY(float, maxLevels - 2); | 269 float* thresholdFactorFrequency = SkNEW_ARRAY(float, maxLevels - 2); |
250 float* contrast = SkNEW_ARRAY(float, maxLevels - 2); | 270 float* contrast = SkNEW_ARRAY(float, maxLevels - 2); |
251 | 271 |
252 lab_to_l(baselineLAB, baselineL.getLayer(0)); | 272 lab_to_l(baselineLAB, baselineL.getLayer(0)); |
253 lab_to_l(testLAB, testL.getLayer(0)); | 273 lab_to_l(testLAB, testL.getLayer(0)); |
254 | 274 |
255 // Compute cpd - Cycles per degree on the pyramid | 275 // Compute cpd - Cycles per degree on the pyramid |
256 cyclesPerDegree[0] = 0.5f * pixelsPerDegree; | 276 cyclesPerDegree[0] = 0.5f * pixelsPerDegree; |
257 for (int levelIndex = 1; levelIndex < maxLevels; levelIndex++) { | 277 for (int levelIndex = 1; levelIndex < maxLevels; levelIndex++) { |
258 cyclesPerDegree[levelIndex] = cyclesPerDegree[levelIndex - 1] * 0.5f; | 278 cyclesPerDegree[levelIndex] = cyclesPerDegree[levelIndex - 1] * 0.5f; |
259 } | 279 } |
260 | 280 |
261 const float filterMatrix[] = { 0.05f, 0.25f, 0.4f, 0.25f, 0.05f }; | |
262 // Compute G - The convolved lum for the baseline | 281 // Compute G - The convolved lum for the baseline |
263 for (int levelIndex = 1; levelIndex < maxLevels; levelIndex++) { | 282 for (int levelIndex = 1; levelIndex < maxLevels; levelIndex++) { |
264 convolve(baselineL.getLayer(levelIndex - 1), false, filterMatrix, 2, &sc ratchImageL); | 283 convolve(baselineL.getLayer(levelIndex - 1), false, &scratchImageL); |
265 convolve(&scratchImageL, true, filterMatrix, 2, baselineL.getLayer(level Index)); | 284 convolve(&scratchImageL, true, baselineL.getLayer(levelIndex)); |
266 } | 285 } |
267 for (int levelIndex = 1; levelIndex < maxLevels; levelIndex++) { | 286 for (int levelIndex = 1; levelIndex < maxLevels; levelIndex++) { |
268 convolve(testL.getLayer(levelIndex - 1), false, filterMatrix, 2, &scratc hImageL); | 287 convolve(testL.getLayer(levelIndex - 1), false, &scratchImageL); |
269 convolve(&scratchImageL, true, filterMatrix, 2, testL.getLayer(levelInde x)); | 288 convolve(&scratchImageL, true, testL.getLayer(levelIndex)); |
270 } | 289 } |
271 | 290 |
272 // Compute F_freq - The elevation f | 291 // Compute F_freq - The elevation f |
273 for (int levelIndex = 0; levelIndex < maxLevels - 2; levelIndex++) { | 292 for (int levelIndex = 0; levelIndex < maxLevels - 2; levelIndex++) { |
274 float cpd = cyclesPerDegree[levelIndex]; | 293 float cpd = cyclesPerDegree[levelIndex]; |
275 thresholdFactorFrequency[levelIndex] = contrastSensitivityMax / | 294 thresholdFactorFrequency[levelIndex] = contrastSensitivityMax / |
276 contrast_sensitivity(cpd, 100.0f) ; | 295 contrast_sensitivity(cpd, 100.0f) ; |
277 } | 296 } |
278 | 297 |
279 int failures = 0; | 298 int failures = 0; |
(...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
425 return fQueuedDiffs[id].result; | 444 return fQueuedDiffs[id].result; |
426 } | 445 } |
427 | 446 |
428 int SkPMetric::getPointsOfInterestCount(int id) { | 447 int SkPMetric::getPointsOfInterestCount(int id) { |
429 return fQueuedDiffs[id].poi.count(); | 448 return fQueuedDiffs[id].poi.count(); |
430 } | 449 } |
431 | 450 |
432 SkIPoint* SkPMetric::getPointsOfInterest(int id) { | 451 SkIPoint* SkPMetric::getPointsOfInterest(int id) { |
433 return fQueuedDiffs[id].poi.begin(); | 452 return fQueuedDiffs[id].poi.begin(); |
434 } | 453 } |
OLD | NEW |