1 /*-------------------------------------------------------------------------
2 * drawElements Quality Program OpenGL ES Utilities
3 * ------------------------------------------------
5 * Copyright 2014 The Android Open Source Project
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
11 * http://www.apache.org/licenses/LICENSE-2.0
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
22 goog
.provide('framework.common.tcuImageCompare');
23 goog
.require('framework.common.tcuBilinearImageCompare');
24 goog
.require('framework.common.tcuFloat');
25 goog
.require('framework.common.tcuFuzzyImageCompare');
26 goog
.require('framework.common.tcuLogImage');
27 goog
.require('framework.common.tcuRGBA');
28 goog
.require('framework.common.tcuSurface');
29 goog
.require('framework.common.tcuTexture');
30 goog
.require('framework.common.tcuTextureUtil');
31 goog
.require('framework.delibs.debase.deMath');
33 goog
.scope(function() {
35 var tcuImageCompare
= framework
.common
.tcuImageCompare
;
36 var tcuSurface
= framework
.common
.tcuSurface
;
37 var deMath
= framework
.delibs
.debase
.deMath
;
38 var tcuTexture
= framework
.common
.tcuTexture
;
39 var tcuTextureUtil
= framework
.common
.tcuTextureUtil
;
40 var tcuFloat
= framework
.common
.tcuFloat
;
41 var tcuFuzzyImageCompare
= framework
.common
.tcuFuzzyImageCompare
;
42 var tcuBilinearImageCompare
= framework
.common
.tcuBilinearImageCompare
;
43 var tcuRGBA
= framework
.common
.tcuRGBA
;
44 var tcuLogImage
= framework
.common
.tcuLogImage
;
49 tcuImageCompare
.CompareLogMode
= {
56 * @param {framework.common.tcuTexture.ConstPixelBufferAccess} result
57 * @param {framework.common.tcuTexture.ConstPixelBufferAccess} reference
58 * @param {framework.common.tcuTexture.ConstPixelBufferAccess=} diff
60 tcuImageCompare
.displayImages = function(result
, reference
, diff
) {
61 var limits
= tcuImageCompare
.computeScaleAndBias(reference
, result
);
62 tcuLogImage
.logImage('Result', '', result
, limits
.scale
, limits
.bias
);
63 tcuLogImage
.logImage('Reference', '', reference
, limits
.scale
, limits
.bias
);
65 tcuLogImage
.logImage('Error', 'error mask', diff
);
69 * @param {tcuTexture.ConstPixelBufferAccess} reference
70 * @param {tcuTexture.ConstPixelBufferAccess} result
71 * @return {{scale: Array<number>, bias: Array<number>}}
73 tcuImageCompare
.computeScaleAndBias = function(reference
, result
) {
80 var referenceRange
= tcuTextureUtil
.estimatePixelValueRange(reference
);
81 var resultRange
= tcuTextureUtil
.estimatePixelValueRange(result
);
83 minVal
[0] = Math
.min(referenceRange
[0][0], resultRange
[0][0]);
84 minVal
[1] = Math
.min(referenceRange
[0][1], resultRange
[0][1]);
85 minVal
[2] = Math
.min(referenceRange
[0][2], resultRange
[0][2]);
86 minVal
[3] = Math
.min(referenceRange
[0][3], resultRange
[0][3]);
88 maxVal
[0] = Math
.max(referenceRange
[1][0], resultRange
[1][0]);
89 maxVal
[1] = Math
.max(referenceRange
[1][1], resultRange
[1][1]);
90 maxVal
[2] = Math
.max(referenceRange
[1][2], resultRange
[1][2]);
91 maxVal
[3] = Math
.max(referenceRange
[1][3], resultRange
[1][3]);
93 for (var c
= 0; c
< 4; c
++) {
94 if (maxVal
[c
] - minVal
[c
] < eps
) {
95 scale
[c
] = (maxVal
[c
] < eps
) ? 1 : (1 / maxVal
[c
]);
96 bias
[c
] = (c
== 3) ? (1 - maxVal
[c
] * scale
[c
]) : (0 - minVal
[c
] * scale
[c
]);
98 scale
[c
] = 1 / (maxVal
[c
] - minVal
[c
]);
99 bias
[c
] = 0 - minVal
[c
] * scale
[c
];
109 * \brief Per-pixel threshold-based comparison
111 * This compare computes per-pixel differences between result and reference
112 * image. Comparison fails if any pixels exceed the given threshold value.
114 * This comparison can be used for integer- and fixed-point texture formats.
115 * Difference is computed in integer space.
117 * On failure error image is generated that shows where the failing pixels
120 * @param {string} imageSetName Name for image set when logging results
121 * @param {string} imageSetDesc Description for image set
122 * @param {tcuTexture.ConstPixelBufferAccess} reference Reference image
123 * @param {tcuTexture.ConstPixelBufferAccess} result Result image
124 * @param {Array<number>} threshold Maximum allowed difference
125 * @param {tcuImageCompare.CompareLogMode=} logMode
126 * @param {Array< Array<number> >} skipPixels pixels that are skipped comparison
127 * @return {boolean} true if comparison passes, false otherwise
129 tcuImageCompare
.intThresholdCompare = function(imageSetName
, imageSetDesc
, reference
, result
, threshold
, logMode
, skipPixels
) {
130 var width
= reference
.getWidth();
131 var height
= reference
.getHeight();
132 var depth
= reference
.getDepth();
133 var errorMask
= new tcuSurface
.Surface(width
, height
);
135 var maxDiff
= [0, 0, 0, 0];
136 // var pixelBias = [0, 0, 0, 0]; // Vec4 // TODO: check, only used in computeScaleAndBias, which is not included
137 // var pixelScale = [1, 1, 1, 1]; // Vec4 // TODO: check, only used in computeScaleAndBias
139 assertMsgOptions(result
.getWidth() == width
&& result
.getHeight() == height
&& result
.getDepth() == depth
,
140 'Reference and result images have different dimensions', false, true);
142 for (var z
= 0; z
< depth
; z
++) {
143 for (var y
= 0; y
< height
; y
++) {
144 for (var x
= 0; x
< width
; x
++) {
145 if (skipPixels
&& skipPixels
.length
> 0) {
147 for (var ii
= 0; ii
< skipPixels
.length
; ++ii
) {
148 var refZ
= (skipPixels
[ii
].length
> 2 ? skipPixels
[ii
][2] : 0);
149 if (x
== skipPixels
[ii
][0] && y
== skipPixels
[ii
][1] && z
== refZ
) {
157 var refPix
= reference
.getPixelInt(x
, y
, z
);
158 var cmpPix
= result
.getPixelInt(x
, y
, z
);
160 var diff
= deMath
.absDiff(refPix
, cmpPix
);
161 var isOk
= deMath
.boolAll(deMath
.lessThanEqual(diff
, threshold
));
163 maxDiff
= deMath
.max(maxDiff
, diff
);
164 var color
= [0, 255, 0, 255];
166 color
= [255, 0, 0, 255];
167 errorMask
.setPixel(x
, y
, color
);
172 var compareOk
= deMath
.boolAll(deMath
.lessThanEqual(maxDiff
, threshold
));
175 debug('Image comparison failed: max difference = ' + maxDiff
+ ', threshold = ' + threshold
);
176 tcuImageCompare
.displayImages(result
, reference
, errorMask
.getAccess());
183 * \brief Per-pixel threshold-based deviation-ignoring comparison
185 * This compare computes per-pixel differences between result and reference
186 * image. Pixel fails the test if there is no pixel matching the given
187 * threshold value in the search volume. Comparison fails if the number of
188 * failing pixels exceeds the given limit.
190 * If the search volume contains out-of-bounds pixels, comparison can be set
191 * to either ignore these pixels in search or to accept any pixel that has
192 * out-of-bounds pixels in its search volume.
194 * This comparison can be used for integer- and fixed-point texture formats.
195 * Difference is computed in integer space.
197 * On failure error image is generated that shows where the failing pixels
200 * @param {string} imageSetName Name for image set when logging results
201 * @param {string} imageSetDesc Description for image set
202 * @param {tcuTexture.ConstPixelBufferAccess} reference Reference image
203 * @param {tcuTexture.ConstPixelBufferAccess} result Result image
204 * @param {Array<number>} threshold Maximum allowed difference
205 * @param {Array<number>} maxPositionDeviation Maximum allowed distance in the search volume.
206 * @param {boolean} acceptOutOfBoundsAsAnyValue Accept any pixel in the boundary region
207 * @param {number} maxAllowedFailingPixels Maximum number of failing pixels
208 * @return {boolean} true if comparison passes, false otherwise
210 tcuImageCompare
.intThresholdPositionDeviationErrorThresholdCompare = function(
211 imageSetName
, imageSetDesc
, reference
, result
, threshold
, maxPositionDeviation
, acceptOutOfBoundsAsAnyValue
, maxAllowedFailingPixels
) {
212 /** @type {number} */ var width
= reference
.getWidth();
213 /** @type {number} */ var height
= reference
.getHeight();
214 /** @type {number} */ var depth
= reference
.getDepth();
215 /** @type {tcuSurface.Surface} */ var errorMask
= new tcuSurface
.Surface(width
, height
);
216 /** @type {number} */ var numFailingPixels
= tcuImageCompare
.findNumPositionDeviationFailingPixels(errorMask
.getAccess(), reference
, result
, threshold
, maxPositionDeviation
, acceptOutOfBoundsAsAnyValue
);
217 var compareOk
= numFailingPixels
<= maxAllowedFailingPixels
;
218 /** @type {Array<number>} */ var pixelBias
= [0.0, 0.0, 0.0, 0.0];
219 /** @type {Array<number>} */ var pixelScale
= [1.0, 1.0, 1.0, 1.0];
222 debug('Position deviation error threshold image comparison failed: failed pixels = ' + numFailingPixels
+ ', threshold = ' + threshold
);
223 tcuImageCompare
.displayImages(result
, reference
, errorMask
.getAccess());
225 tcuLogImage
.logImage('Result', '', result
);
228 // All formats except normalized unsigned fixed point ones need remapping in order to fit into unorm channels in logged images.
229 if (tcuTexture.getTextureChannelClass(reference.getFormat().type) != tcuTexture.TextureChannelClass.UNSIGNED_FIXED_POINT ||
230 tcuTexture.getTextureChannelClass(result.getFormat().type) != tcuTexture.TextureChannelClass.UNSIGNED_FIXED_POINT) {
231 computeScaleAndBias(reference, result, pixelScale, pixelBias);
232 log << TestLog::Message << "Result and reference images are normalized with formula p * " << pixelScale << " + " << pixelBias << TestLog::EndMessage;
236 log << TestLog::Message
237 << "Image comparison failed:\n"
238 << "\tallowed position deviation = " << maxPositionDeviation << "\n"
239 << "\tcolor threshold = " << threshold
240 << TestLog::EndMessage;
241 log << TestLog::Message << "Number of failing pixels = " << numFailingPixels << ", max allowed = " << maxAllowedFailingPixels << TestLog::EndMessage;
243 log << TestLog::ImageSet(imageSetName, imageSetDesc)
244 << TestLog::Image("Result", "Result", result, pixelScale, pixelBias)
245 << TestLog::Image("Reference", "Reference", reference, pixelScale, pixelBias)
246 << TestLog::Image("ErrorMask", "Error mask", errorMask)
247 << TestLog::EndImageSet;
248 } else if (logMode == COMPARE_LOG_RESULT) {
249 if (result.getFormat() != TextureFormat(TextureFormat::RGBA, TextureFormat::UNORM_INT8))
250 computePixelScaleBias(result, pixelScale, pixelBias);
252 log << TestLog::ImageSet(imageSetName, imageSetDesc)
253 << TestLog::Image("Result", "Result", result, pixelScale, pixelBias)
254 << TestLog::EndImageSet;
261 * tcuImageCompare.floatUlpThresholdCompare
262 * @param {string} imageSetName
263 * @param {string} imageSetDesc
264 * @param {tcuTexture.ConstPixelBufferAccess} reference
265 * @param {tcuTexture.ConstPixelBufferAccess} result
266 * @param {Array<number>} threshold - previously used as an Uint32Array
269 tcuImageCompare
.floatUlpThresholdCompare = function(imageSetName
, imageSetDesc
, reference
, result
, threshold
) {
270 /** @type {number} */ var width
= reference
.getWidth();
271 /** @type {number} */ var height
= reference
.getHeight();
272 /** @type {number} */ var depth
= reference
.getDepth();
273 /** @type {tcuSurface.Surface} */ var errorMask
= new tcuSurface
.Surface(width
, height
);
275 /** @type {Array<number>} */ var maxDiff
= [0, 0, 0, 0]; // UVec4
276 // var pixelBias = [0, 0, 0, 0]; // Vec4
277 // var pixelScale = [1, 1, 1, 1]; // Vec4
279 assertMsgOptions(result
.getWidth() == width
&& result
.getHeight() == height
&& result
.getDepth() == depth
,
280 'Reference and result images have different dimensions', false, true);
282 for (var z
= 0; z
< depth
; z
++) {
283 for (var y
= 0; y
< height
; y
++) {
284 for (var x
= 0; x
< width
; x
++) {
285 /** @type {ArrayBuffer} */ var arrayBufferRef
= new ArrayBuffer(4 * 4);
286 /** @type {ArrayBuffer} */ var arrayBufferCmp
= new ArrayBuffer(4 * 4);
288 /** @type {Array<number>} */ var refPix
= reference
.getPixel(x
, y
, z
); // getPixel returns a Vec4 pixel color
290 /** @type {Array<number>} */ var cmpPix
= result
.getPixel(x
, y
, z
); // getPixel returns a Vec4 pixel color
292 /** @type {Uint32Array} */ var refBits
= new Uint32Array(arrayBufferRef
); // UVec4
293 /** @type {Uint32Array} */ var cmpBits
= new Uint32Array(arrayBufferCmp
); // UVec4
295 // Instead of memcpy(), which is the way to do float->uint32 reinterpretation in C++
296 for (var i
= 0; i
< refPix
.length
; i
++) {
297 refBits
[i
] = tcuFloat
.convertFloat32Inline(refPix
[i
], tcuFloat
.description32
);
298 cmpBits
[i
] = tcuFloat
.convertFloat32Inline(cmpPix
[i
], tcuFloat
.description32
);
301 /** @type {Array<number>} */ var diff
= deMath
.absDiff(refBits
, cmpBits
); // UVec4
302 /** @type {boolean} */ var isOk
= deMath
.boolAll(deMath
.lessThanEqual(diff
, threshold
));
304 maxDiff
= deMath
.max(maxDiff
, diff
);
306 errorMask
.setPixel(x
, y
, isOk
? [0, 255, 0, 255] : [255, 0, 0, 255]);
311 /** @type {boolean} */ var compareOk
= deMath
.boolAll(deMath
.lessThanEqual(maxDiff
, threshold
));
314 debug('Image comparison failed: max difference = ' + maxDiff
+ ', threshold = ' + threshold
);
315 tcuImageCompare
.displayImages(result
, reference
, errorMask
.getAccess());
318 /*if (!compareOk || logMode == COMPARE_LOG_EVERYTHING) {
319 // All formats except normalized unsigned fixed point ones need remapping in order to fit into unorm channels in logged images.
320 if (tcu::getTextureChannelClass(reference.getFormat().type) != tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT ||
321 tcu::getTextureChannelClass(result.getFormat().type) != tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT) {
322 computeScaleAndBias(reference, result, pixelScale, pixelBias);
323 log << TestLog::Message << "Result and reference images are normalized with formula p * " << pixelScale << " + " << pixelBias << TestLog::EndMessage;
327 log << TestLog::Message << "Image comparison failed: max difference = " << maxDiff << ", threshold = " << threshold << TestLog::EndMessage;
329 log << TestLog::ImageSet(imageSetName, imageSetDesc)
330 << TestLog::Image("Result", "Result", result, pixelScale, pixelBias)
331 << TestLog::Image("Reference", "Reference", reference, pixelScale, pixelBias)
332 << TestLog::Image("ErrorMask", "Error mask", errorMask)
333 << TestLog::EndImageSet;
334 } else if (logMode == COMPARE_LOG_RESULT) {
335 if (result.getFormat() != TextureFormat(TextureFormat::RGBA, TextureFormat::UNORM_INT8))
336 computePixelScaleBias(result, pixelScale, pixelBias);
338 log << TestLog::ImageSet(imageSetName, imageSetDesc)
339 << TestLog::Image("Result", "Result", result, pixelScale, pixelBias)
340 << TestLog::EndImageSet;
347 * tcuImageCompare.floatThresholdCompare
348 * @param {string} imageSetName
349 * @param {string} imageSetDesc
350 * @param {tcuTexture.ConstPixelBufferAccess} reference
351 * @param {tcuTexture.ConstPixelBufferAccess} result
352 * @param {Array<number>} threshold
355 tcuImageCompare
.floatThresholdCompare = function(imageSetName
, imageSetDesc
, reference
, result
, threshold
) {
356 /** @type {number} */ var width
= reference
.getWidth();
357 /** @type {number} */ var height
= reference
.getHeight();
358 /** @type {number} */ var depth
= reference
.getDepth();
359 /** @type {tcuSurface.Surface} */ var errorMask
= new tcuSurface
.Surface(width
, height
);
361 /** @type {Array<number>} */ var maxDiff
= [0, 0, 0, 0]; // Vec4
362 // var pixelBias = [0, 0, 0, 0]; // Vec4
363 // var pixelScale = [1, 1, 1, 1]; // Vec4
365 assertMsgOptions(result
.getWidth() == width
&& result
.getHeight() == height
&& result
.getDepth() == depth
,
366 'Reference and result images have different dimensions', false, true);
368 for (var z
= 0; z
< depth
; z
++) {
369 for (var y
= 0; y
< height
; y
++) {
370 for (var x
= 0; x
< width
; x
++) {
371 var refPix
= reference
.getPixel(x
, y
, z
); // Vec4
372 var cmpPix
= result
.getPixel(x
, y
, z
); // Vec4
374 /** @type {Array<number>} */ var diff
= deMath
.absDiff(refPix
, cmpPix
); // Vec4
375 /** @type {boolean} */ var isOk
= deMath
.boolAll(deMath
.lessThanEqual(diff
, threshold
));
377 maxDiff
= deMath
.max(maxDiff
, diff
);
379 errorMask
.setPixel(x
, y
, isOk
? [0, 255, 0, 255] : [255, 0, 0, 255]);
384 /** @type {boolean} */ var compareOk
= deMath
.boolAll(deMath
.lessThanEqual(maxDiff
, threshold
));
387 debug('Image comparison failed: max difference = ' + maxDiff
+ ', threshold = ' + threshold
);
388 tcuImageCompare
.displayImages(result
, reference
, errorMask
.getAccess());
391 /*if (!compareOk || logMode == COMPARE_LOG_EVERYTHING) {
392 // All formats except normalized unsigned fixed point ones need remapping in order to fit into unorm channels in logged images.
393 if (tcu::getTextureChannelClass(reference.getFormat().type) != tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT ||
394 tcu::getTextureChannelClass(result.getFormat().type) != tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT) {
395 computeScaleAndBias(reference, result, pixelScale, pixelBias);
396 log << TestLog::Message << "Result and reference images are normalized with formula p * " << pixelScale << " + " << pixelBias << TestLog::EndMessage;
400 log << TestLog::Message << "Image comparison failed: max difference = " << maxDiff << ", threshold = " << threshold << TestLog::EndMessage;
402 log << TestLog::ImageSet(imageSetName, imageSetDesc)
403 << TestLog::Image("Result", "Result", result, pixelScale, pixelBias)
404 << TestLog::Image("Reference", "Reference", reference, pixelScale, pixelBias)
405 << TestLog::Image("ErrorMask", "Error mask", errorMask)
406 << TestLog::EndImageSet;
407 } else if (logMode == COMPARE_LOG_RESULT) {
408 if (result.getFormat() != TextureFormat(TextureFormat::RGBA, TextureFormat::UNORM_INT8))
409 computePixelScaleBias(result, pixelScale, pixelBias);
411 log << TestLog::ImageSet(imageSetName, imageSetDesc)
412 << TestLog::Image("Result", "Result", result, pixelScale, pixelBias)
413 << TestLog::EndImageSet;
420 * \brief Per-pixel threshold-based comparison
422 * This compare computes per-pixel differences between result and reference
423 * image. Comparison fails if any pixels exceed the given threshold value.
425 * On failure error image is generated that shows where the failing pixels
428 * @param {string} imageSetName Name for image set when logging results
429 * @param {string} imageSetDesc Description for image set
430 * @param {tcuSurface.Surface} reference Reference image
431 * @param {tcuSurface.Surface} result Result image
432 * @param {Array<number>} threshold Maximum allowed difference
433 * @param {tcuImageCompare.CompareLogMode=} logMode
434 * @param {Array< Array<number> >} skipPixels pixels that are skipped comparison
435 * @return {boolean} true if comparison passes, false otherwise
437 tcuImageCompare
.pixelThresholdCompare = function(imageSetName
, imageSetDesc
, reference
, result
, threshold
, logMode
, skipPixels
) {
438 return tcuImageCompare
.intThresholdCompare(imageSetName
, imageSetDesc
, reference
.getAccess(), result
.getAccess(), threshold
, logMode
, skipPixels
);
442 * @param {tcuTexture.PixelBufferAccess} errorMask
443 * @param {tcuTexture.ConstPixelBufferAccess} reference
444 * @param {tcuTexture.ConstPixelBufferAccess} result
445 * @param {Array<number>} threshold
446 * @param {Array<number>} maxPositionDeviation
447 * @param {boolean} acceptOutOfBoundsAsAnyValue
450 tcuImageCompare
.findNumPositionDeviationFailingPixels = function(errorMask
, reference
, result
, threshold
, maxPositionDeviation
, acceptOutOfBoundsAsAnyValue
) {
451 /** @type {number} */ var width
= reference
.getWidth();
452 /** @type {number} */ var height
= reference
.getHeight();
453 /** @type {number} */ var depth
= reference
.getDepth();
454 /** @type {number} */ var numFailingPixels
= 0;
456 checkMessage(result
.getWidth() == width
&& result
.getHeight() == height
&& result
.getDepth() == depth
, 'Surfaces have different dimensions');
458 for (var z
= 0; z
< depth
; z
++) {
459 for (var y
= 0; y
< height
; y
++) {
460 for (var x
= 0; x
< width
; x
++) {
461 /** @type {Array<number>} */ var refPix
= reference
.getPixelInt(x
, y
, z
);
462 /** @type {Array<number>} */ var cmpPix
= result
.getPixelInt(x
, y
, z
);
465 /** @type {Array<number>} */ var diff
= deMath
.absDiff(refPix
, cmpPix
);
466 /** @type {boolean} */ var isOk
= deMath
.boolAll(deMath
.lessThanEqual(diff
, threshold
));
469 errorMask
.setPixel([0, 0xff, 0, 0xff], x
, y
, z
);
473 // Accept over the image bounds pixels since they could be anything
475 if (acceptOutOfBoundsAsAnyValue
&&
476 (x
< maxPositionDeviation
[0] || x
+ maxPositionDeviation
[0] >= width
||
477 y
< maxPositionDeviation
[1] || y
+ maxPositionDeviation
[1] >= height
||
478 z
< maxPositionDeviation
[2] || z
+ maxPositionDeviation
[2] >= depth
)) {
479 errorMask
.setPixel([0, 0xff, 0, 0xff], x
, y
, z
);
483 // Find matching pixels for both result and reference pixel
485 var pixelFoundForReference
= false;
486 var pixelFoundForResult
= false;
488 // Find deviated result pixel for reference
490 for (var sz
= Math
.max(0, z
- maxPositionDeviation
[2]); sz
<= Math
.min(depth
- 1, z
+ maxPositionDeviation
[2]) && !pixelFoundForReference
; ++sz
)
491 for (var sy
= Math
.max(0, y
- maxPositionDeviation
[1]); sy
<= Math
.min(height
- 1, y
+ maxPositionDeviation
[1]) && !pixelFoundForReference
; ++sy
)
492 for (var sx
= Math
.max(0, x
- maxPositionDeviation
[0]); sx
<= Math
.min(width
- 1, x
+ maxPositionDeviation
[0]) && !pixelFoundForReference
; ++sx
) {
493 /** @type {Array<number>} */ var deviatedCmpPix
= result
.getPixelInt(sx
, sy
, sz
);
494 diff
= deMath
.absDiff(refPix
, deviatedCmpPix
);
495 isOk
= deMath
.boolAll(deMath
.lessThanEqual(diff
, threshold
));
497 pixelFoundForReference
|= isOk
;
500 // Find deviated reference pixel for result
502 for (var sz
= Math
.max(0, z
- maxPositionDeviation
[2]); sz
<= Math
.min(depth
- 1, z
+ maxPositionDeviation
[2]) && !pixelFoundForResult
; ++sz
)
503 for (var sy
= Math
.max(0, y
- maxPositionDeviation
[1]); sy
<= Math
.min(height
- 1, y
+ maxPositionDeviation
[1]) && !pixelFoundForResult
; ++sy
)
504 for (var sx
= Math
.max(0, x
- maxPositionDeviation
[0]); sx
<= Math
.min(width
- 1, x
+ maxPositionDeviation
[0]) && !pixelFoundForResult
; ++sx
) {
505 /** @type {Array<number>} */ var deviatedRefPix
= reference
.getPixelInt(sx
, sy
, sz
);
506 diff
= deMath
.absDiff(cmpPix
, deviatedRefPix
);
507 isOk
= deMath
.boolAll(deMath
.lessThanEqual(diff
, threshold
));
509 pixelFoundForResult
|= isOk
;
512 if (pixelFoundForReference
&& pixelFoundForResult
)
513 errorMask
.setPixel([0, 0xff, 0, 0xff], x
, y
, z
);
515 errorMask
.setPixel([0xff, 0, 0, 0xff], x
, y
, z
);
522 return numFailingPixels
;
526 * tcuImageCompare.fuzzyCompare
527 * @param {string} imageSetName
528 * @param {string} imageSetDesc
529 * @param {tcuTexture.ConstPixelBufferAccess} reference
530 * @param {tcuTexture.ConstPixelBufferAccess} result
531 * @param {number} threshold
532 * @param {tcuImageCompare.CompareLogMode=} logMode
535 tcuImageCompare
.fuzzyCompare = function(imageSetName
, imageSetDesc
, reference
, result
, threshold
, logMode
) {
536 /** @type {tcuFuzzyImageCompare.FuzzyCompareParams} */ var params
= new tcuFuzzyImageCompare
.FuzzyCompareParams(); // Use defaults.
537 /** @type {tcuTexture.TextureLevel} */ var errorMask
= new tcuTexture
.TextureLevel(
538 new tcuTexture
.TextureFormat(tcuTexture
.ChannelOrder
.RGB
,
539 tcuTexture
.ChannelType
.UNORM_INT8
),
540 reference
.getWidth(),
541 reference
.getHeight()
543 /** @type {number} */ var difference
= tcuFuzzyImageCompare
.fuzzyCompare(
547 tcuTexture
.PixelBufferAccess
.newFromTextureLevel(errorMask
)
549 /** @type {boolean} */ var isOk
= difference
<= threshold
;
550 /** @type {Array<number>} */ var pixelBias
= [0.0, 0.0, 0.0, 0.0];
551 /** @type {Array<number>} */ var pixelScale
= [1.0, 1.0, 1.0, 1.0];
554 debug('Fuzzy image comparison failed: difference = ' + difference
+ ', threshold = ' + threshold
);
555 tcuImageCompare
.displayImages(result
, reference
, errorMask
.getAccess());
559 if (!isOk || logMode == COMPARE_LOG_EVERYTHING) {
560 // Generate more accurate error mask.
561 params.maxSampleSkip = 0;
562 tcuImageCompare.fuzzyCompare(params, reference, result, errorMask.getAccess());
564 if (result.getFormat() != TextureFormat(TextureFormat::RGBA, TextureFormat::UNORM_INT8) && reference.getFormat() != TextureFormat(TextureFormat::RGBA, TextureFormat::UNORM_INT8))
565 computeScaleAndBias(reference, result, pixelScale, pixelBias);
568 log << TestLog::Message << "Image comparison failed: difference = " << difference << ", threshold = " << threshold << TestLog::EndMessage;
570 log << TestLog::ImageSet(imageSetName, imageSetDesc)
571 << TestLog::Image("Result", "Result", result, pixelScale, pixelBias)
572 << TestLog::Image("Reference", "Reference", reference, pixelScale, pixelBias)
573 << TestLog::Image("ErrorMask", "Error mask", errorMask)
574 << TestLog::EndImageSet;
575 } else if (logMode == COMPARE_LOG_RESULT) {
576 if (result.getFormat() != TextureFormat(TextureFormat::RGBA, TextureFormat::UNORM_INT8))
577 computePixelScaleBias(result, pixelScale, pixelBias);
579 log << TestLog::ImageSet(imageSetName, imageSetDesc)
580 << TestLog::Image("Result", "Result", result, pixelScale, pixelBias)
581 << TestLog::EndImageSet;
587 tcuImageCompare
.unitTest = function() {
591 var weirdLevel
= new tcuTexture
.TextureLevel(new tcuTexture
.TextureFormat(tcuTexture
.ChannelOrder
.RG
, tcuTexture
.ChannelType
.SNORM_INT32
), width
, height
);
592 var access
= weirdLevel
.getAccess();
593 access
.clear([0.1, 0.5, 0, 0]);
594 access
.clear([0.11, 0.52, 0, 0], [0, width
], [0, height
/ 2]);
595 access
.clear([0.12, 0.52, 0, 0], [0, width
], [height
/ 2, height
/ 2 + height
/ 8]);
596 var limits
= tcuTextureUtil
.computePixelScaleBias(access
);
597 debug('Scale: ' + limits
.scale
);
598 debug('Bias: ' + limits
.bias
);
599 tcuLogImage
.logImage('Weird', 'weird format without scaling', access
);
600 tcuLogImage
.logImage('Weird', 'weird format', access
, limits
.scale
, limits
.bias
);
602 var srcLevel
= new tcuTexture
.TextureLevel(new tcuTexture
.TextureFormat(tcuTexture
.ChannelOrder
.RGBA
, tcuTexture
.ChannelType
.UNORM_INT8
), width
, height
);
603 var dstLevel
= new tcuTexture
.TextureLevel(new tcuTexture
.TextureFormat(tcuTexture
.ChannelOrder
.RGBA
, tcuTexture
.ChannelType
.UNORM_INT8
), width
, height
);
604 var src
= srcLevel
.getAccess();
605 var dst
= dstLevel
.getAccess();
610 for (var i
= 0; i
< width
- 1; i
++) {
611 for (var j
= 0; j
< height
- 1; j
++) {
612 src
.setPixelInt([i
, j
, 90, 255], i
, j
);
613 dst
.setPixelInt([i
, j
, 90, 255], i
+ 1, j
+ 1);
617 debug('Src format: ' + src
.getFormat());
618 debug('Destination: ' + dst
);
620 tcuLogImage
.logImage('Source', 'Source image', src
);
622 if (!tcuImageCompare
.fuzzyCompare('compare', 'compare similar images', src
, dst
, 0.05))
623 throw new Error('Compare should return true');
628 for (var i
= 0; i
< width
- 2; i
++) {
629 for (var j
= 0; j
< height
- 2; j
++) {
630 src
.setPixelInt([i
, j
, 90, 255], i
, j
);
631 dst
.setPixelInt([i
, j
, 90, 255], i
+ 2, j
+ 2);
635 if (tcuImageCompare
.fuzzyCompare('compare', 'compare different images', src
, dst
, 0.05))
636 throw new Error('Compare should return false');
641 tcuImageCompare
.unitTest2 = function() {
644 var srcLevel
= new tcuTexture
.TextureLevel(new tcuTexture
.TextureFormat(tcuTexture
.ChannelOrder
.RGBA
, tcuTexture
.ChannelType
.UNORM_INT8
), width
, height
);
645 var dstLevel
= new tcuTexture
.TextureLevel(new tcuTexture
.TextureFormat(tcuTexture
.ChannelOrder
.RGBA
, tcuTexture
.ChannelType
.UNORM_INT8
), width
, height
);
646 var src
= srcLevel
.getAccess();
647 var dst
= dstLevel
.getAccess();
648 var threshold
= tcuRGBA
.newRGBAComponents(1, 1, 1, 1);
649 debug('Threshold: ' + threshold
);
654 for (var i
= 0; i
< width
- 1; i
++) {
655 for (var j
= 0; j
< height
- 1; j
++) {
656 src
.setPixelInt([i
, j
, 90, 255], i
, j
);
657 dst
.setPixelInt([i
, j
, 90, 255], i
, j
);
660 if (!tcuImageCompare
.bilinearCompare('compare', 'compare similar images', src
, dst
, threshold
))
661 throw new Error('Compare should return true');
662 debug('bilinear compare the same images passed');
667 for (var i
= 0; i
< width
- 1; i
++) {
668 for (var j
= 0; j
< height
- 1; j
++) {
669 src
.setPixelInt([i
, j
, 90, 255], i
, j
);
670 dst
.setPixelInt([i
, j
+ 1, 90, 255], i
, j
+ 1);
673 if (!tcuImageCompare
.bilinearCompare('compare', 'compare similar images', src
, dst
, threshold
))
674 throw new Error('Compare should return true');
675 debug('bilinear compare very similar images passed');
680 for (var i
= 0; i
< width
- 2; i
++) {
681 for (var j
= 0; j
< height
- 2; j
++) {
682 src
.setPixelInt([i
, j
, 90, 255], i
, j
);
683 // dst.setPixelInt([i, j, 90, 255], i + 2, j + 2);
687 if (tcuImageCompare
.bilinearCompare('compare', 'compare different images', src
, dst
, threshold
))
688 throw new Error('Compare should return false');
690 debug('bilinear compare very different images passed');
694 * Bilinear image comparison
695 * On failure error image is generated that shows where the failing pixels
697 * Currently supports only RGBA, UNORM_INT8 formats
699 * @param {string} imageSetName Name for image set when logging results
700 * @param {string} imageSetDesc Description for image set
701 * @param {tcuTexture.ConstPixelBufferAccess} reference Reference image
702 * @param {tcuTexture.ConstPixelBufferAccess} result Result image
703 * @param {tcuRGBA.RGBA} threshold Maximum local difference
704 * @param {tcuImageCompare.CompareLogMode=} logMode Logging mode
705 * @return {boolean} if comparison passes, false otherwise
707 tcuImageCompare
.bilinearCompare = function(imageSetName
, imageSetDesc
, reference
, result
, threshold
, logMode
) {
708 /** @type {tcuTexture.TextureLevel} */
709 var errorMask
= new tcuTexture
.TextureLevel(
710 new tcuTexture
.TextureFormat(
711 tcuTexture
.ChannelOrder
.RGB
,
712 tcuTexture
.ChannelType
.UNORM_INT8
),
713 reference
.getWidth(),
714 reference
.getHeight());
716 /** @type {boolean} */
717 var isOk
= tcuBilinearImageCompare
.bilinearCompare(
720 tcuTexture
.PixelBufferAccess
.newFromTextureLevel(errorMask
),
724 debug('Image comparison failed: threshold = ' + threshold
);
725 tcuImageCompare
.displayImages(result
, reference
, errorMask
.getAccess());
728 // /* @type {Array<number>} */ var pixelBias = [0.0, 0.0, 0.0, 0.0];
729 // /* @type {Array<number>} */ var pixelScale = [1.0, 1.0, 1.0, 1.0];
730 // if (!isOk || logMode == COMPARE_LOG_EVERYTHING)
732 // if (result.getFormat() != TextureFormat(TextureFormat::RGBA, TextureFormat::UNORM_INT8) && reference.getFormat() != TextureFormat(TextureFormat::RGBA, TextureFormat::UNORM_INT8))
733 // computeScaleAndBias(reference, result, pixelScale, pixelBias);
736 // log << TestLog::Message << "Image comparison failed, threshold = " << threshold << TestLog::EndMessage;
738 // log << TestLog::ImageSet(imageSetName, imageSetDesc)
739 // << TestLog::Image("Result", "Result", result, pixelScale, pixelBias)
740 // << TestLog::Image("Reference", "Reference", reference, pixelScale, pixelBias)
741 // << TestLog::Image("ErrorMask", "Error mask", errorMask)
742 // << TestLog::EndImageSet;
744 // else if (logMode == COMPARE_LOG_RESULT)
746 // if (result.getFormat() != TextureFormat(TextureFormat::RGBA, TextureFormat::UNORM_INT8))
747 // computePixelScaleBias(result, pixelScale, pixelBias);
749 // log << TestLog::ImageSet(imageSetName, imageSetDesc)
750 // << TestLog::Image("Result", "Result", result, pixelScale, pixelBias)
751 // << TestLog::EndImageSet;