rebaseline_server: merge identical results (across multiple builders/configs) into a single row
BUG=skia:2534 R=jcgregorio@google.com Author: epoger@google.com Review URL: https://codereview.chromium.org/326013002
This commit is contained in:
parent
66c9582d1b
commit
6b28120e4c
@ -74,5 +74,8 @@ module.constant('constants', (function() {
|
|||||||
KEY__EDITS__MODIFICATIONS: 'modifications',
|
KEY__EDITS__MODIFICATIONS: 'modifications',
|
||||||
KEY__EDITS__OLD_RESULTS_HASH: 'oldResultsHash',
|
KEY__EDITS__OLD_RESULTS_HASH: 'oldResultsHash',
|
||||||
KEY__EDITS__OLD_RESULTS_TYPE: 'oldResultsType',
|
KEY__EDITS__OLD_RESULTS_TYPE: 'oldResultsType',
|
||||||
|
|
||||||
|
// These are just used on the client side, no need to sync with server code.
|
||||||
|
KEY__IMAGEPAIRS__ROWSPAN: 'rowspan',
|
||||||
}
|
}
|
||||||
})())
|
})())
|
||||||
|
@ -56,6 +56,65 @@ Loader.filter(
|
|||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Limit the input imagePairs to some max number, and merge identical rows
|
||||||
|
* (adjacent rows which have the same (imageA, imageB) pair).
|
||||||
|
*
|
||||||
|
* @param unfilteredImagePairs imagePairs to filter
|
||||||
|
* @param maxPairs maximum number of pairs to output, or <0 for no limit
|
||||||
|
* @param mergeIdenticalRows if true, merge identical rows by setting
|
||||||
|
* ROWSPAN>1 on the first merged row, and ROWSPAN=0 for the rest
|
||||||
|
*/
|
||||||
|
Loader.filter(
|
||||||
|
'mergeAndLimit',
|
||||||
|
function(constants) {
|
||||||
|
return function(unfilteredImagePairs, maxPairs, mergeIdenticalRows) {
|
||||||
|
var numPairs = unfilteredImagePairs.length;
|
||||||
|
if ((maxPairs > 0) && (maxPairs < numPairs)) {
|
||||||
|
numPairs = maxPairs;
|
||||||
|
}
|
||||||
|
var filteredImagePairs = [];
|
||||||
|
if (!mergeIdenticalRows || (numPairs == 1)) {
|
||||||
|
// Take a shortcut if we're not merging identical rows.
|
||||||
|
// We still need to set ROWSPAN to 1 for each row, for the HTML viewer.
|
||||||
|
for (var i = numPairs-1; i >= 0; i--) {
|
||||||
|
var imagePair = unfilteredImagePairs[i];
|
||||||
|
imagePair[constants.KEY__IMAGEPAIRS__ROWSPAN] = 1;
|
||||||
|
filteredImagePairs[i] = imagePair;
|
||||||
|
}
|
||||||
|
} else if (numPairs > 1) {
|
||||||
|
// General case--there are at least 2 rows, so we may need to merge some.
|
||||||
|
// Work from the bottom up, so we can keep a running total of how many
|
||||||
|
// rows should be merged, and set ROWSPAN of the top row accordingly.
|
||||||
|
var imagePair = unfilteredImagePairs[numPairs-1];
|
||||||
|
var nextRowImageAUrl = imagePair[constants.KEY__IMAGEPAIRS__IMAGE_A_URL];
|
||||||
|
var nextRowImageBUrl = imagePair[constants.KEY__IMAGEPAIRS__IMAGE_B_URL];
|
||||||
|
imagePair[constants.KEY__IMAGEPAIRS__ROWSPAN] = 1;
|
||||||
|
filteredImagePairs[numPairs-1] = imagePair;
|
||||||
|
for (var i = numPairs-2; i >= 0; i--) {
|
||||||
|
imagePair = unfilteredImagePairs[i];
|
||||||
|
var thisRowImageAUrl = imagePair[constants.KEY__IMAGEPAIRS__IMAGE_A_URL];
|
||||||
|
var thisRowImageBUrl = imagePair[constants.KEY__IMAGEPAIRS__IMAGE_B_URL];
|
||||||
|
if ((thisRowImageAUrl == nextRowImageAUrl) &&
|
||||||
|
(thisRowImageBUrl == nextRowImageBUrl)) {
|
||||||
|
imagePair[constants.KEY__IMAGEPAIRS__ROWSPAN] =
|
||||||
|
filteredImagePairs[i+1][constants.KEY__IMAGEPAIRS__ROWSPAN] + 1;
|
||||||
|
filteredImagePairs[i+1][constants.KEY__IMAGEPAIRS__ROWSPAN] = 0;
|
||||||
|
} else {
|
||||||
|
imagePair[constants.KEY__IMAGEPAIRS__ROWSPAN] = 1;
|
||||||
|
nextRowImageAUrl = thisRowImageAUrl;
|
||||||
|
nextRowImageBUrl = thisRowImageBUrl;
|
||||||
|
}
|
||||||
|
filteredImagePairs[i] = imagePair;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// No results.
|
||||||
|
}
|
||||||
|
return filteredImagePairs;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
Loader.controller(
|
Loader.controller(
|
||||||
'Loader.Controller',
|
'Loader.Controller',
|
||||||
@ -234,6 +293,21 @@ Loader.controller(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Toggle selection state of a subset of the currently showing tests.
|
||||||
|
*
|
||||||
|
* @param startIndex index within $scope.limitedImagePairs of the first
|
||||||
|
* test to toggle selection state of
|
||||||
|
* @param num number of tests (in a contiguous block) to toggle
|
||||||
|
*/
|
||||||
|
$scope.toggleSomeImagePairs = function(startIndex, num) {
|
||||||
|
var numImagePairsShowing = $scope.limitedImagePairs.length;
|
||||||
|
for (var i = startIndex; i < startIndex + num; i++) {
|
||||||
|
var index = $scope.limitedImagePairs[i].index;
|
||||||
|
$scope.toggleValueInArray(index, $scope.selectedImagePairs);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// Tab operations.
|
// Tab operations.
|
||||||
@ -335,6 +409,7 @@ Loader.controller(
|
|||||||
'resultsToLoad': $scope.queryParameters.copiers.simple,
|
'resultsToLoad': $scope.queryParameters.copiers.simple,
|
||||||
'displayLimitPending': $scope.queryParameters.copiers.simple,
|
'displayLimitPending': $scope.queryParameters.copiers.simple,
|
||||||
'showThumbnailsPending': $scope.queryParameters.copiers.simple,
|
'showThumbnailsPending': $scope.queryParameters.copiers.simple,
|
||||||
|
'mergeIdenticalRowsPending': $scope.queryParameters.copiers.simple,
|
||||||
'imageSizePending': $scope.queryParameters.copiers.simple,
|
'imageSizePending': $scope.queryParameters.copiers.simple,
|
||||||
'sortColumnSubdict': $scope.queryParameters.copiers.simple,
|
'sortColumnSubdict': $scope.queryParameters.copiers.simple,
|
||||||
'sortColumnKey': $scope.queryParameters.copiers.simple,
|
'sortColumnKey': $scope.queryParameters.copiers.simple,
|
||||||
@ -400,6 +475,7 @@ Loader.controller(
|
|||||||
$scope.renderStartTime = window.performance.now();
|
$scope.renderStartTime = window.performance.now();
|
||||||
$log.debug("renderStartTime: " + $scope.renderStartTime);
|
$log.debug("renderStartTime: " + $scope.renderStartTime);
|
||||||
$scope.displayLimit = $scope.displayLimitPending;
|
$scope.displayLimit = $scope.displayLimitPending;
|
||||||
|
$scope.mergeIdenticalRows = $scope.mergeIdenticalRowsPending;
|
||||||
// TODO(epoger): Every time we apply a filter, AngularJS creates
|
// TODO(epoger): Every time we apply a filter, AngularJS creates
|
||||||
// another copy of the array. Is there a way we can filter out
|
// another copy of the array. Is there a way we can filter out
|
||||||
// the imagePairs as they are displayed, rather than storing multiple
|
// the imagePairs as they are displayed, rather than storing multiple
|
||||||
@ -425,9 +501,10 @@ Loader.controller(
|
|||||||
$scope.categoryValueMatch.test,
|
$scope.categoryValueMatch.test,
|
||||||
$scope.viewingTab
|
$scope.viewingTab
|
||||||
),
|
),
|
||||||
$scope.getSortColumnValue, doReverse);
|
[$scope.getSortColumnValue, $scope.getSecondOrderSortValue],
|
||||||
$scope.limitedImagePairs = $filter("limitTo")(
|
doReverse);
|
||||||
$scope.filteredImagePairs, $scope.displayLimit);
|
$scope.limitedImagePairs = $filter("mergeAndLimit")(
|
||||||
|
$scope.filteredImagePairs, $scope.displayLimit, $scope.mergeIdenticalRows);
|
||||||
} else {
|
} else {
|
||||||
$scope.filteredImagePairs =
|
$scope.filteredImagePairs =
|
||||||
$filter("orderBy")(
|
$filter("orderBy")(
|
||||||
@ -436,8 +513,9 @@ Loader.controller(
|
|||||||
{tab: $scope.viewingTab},
|
{tab: $scope.viewingTab},
|
||||||
true
|
true
|
||||||
),
|
),
|
||||||
$scope.getSortColumnValue);
|
[$scope.getSortColumnValue, $scope.getSecondOrderSortValue]);
|
||||||
$scope.limitedImagePairs = $scope.filteredImagePairs;
|
$scope.limitedImagePairs = $filter("mergeAndLimit")(
|
||||||
|
$scope.filteredImagePairs, -1, $scope.mergeIdenticalRows);
|
||||||
}
|
}
|
||||||
$scope.showThumbnails = $scope.showThumbnailsPending;
|
$scope.showThumbnails = $scope.showThumbnailsPending;
|
||||||
$scope.imageSize = $scope.imageSizePending;
|
$scope.imageSize = $scope.imageSizePending;
|
||||||
@ -458,7 +536,8 @@ Loader.controller(
|
|||||||
* Re-sort the displayed results.
|
* Re-sort the displayed results.
|
||||||
*
|
*
|
||||||
* @param subdict (string): which KEY__IMAGEPAIRS__* subdictionary
|
* @param subdict (string): which KEY__IMAGEPAIRS__* subdictionary
|
||||||
* the sort column key is within
|
* the sort column key is within, or 'none' if the sort column
|
||||||
|
* key is one of KEY__IMAGEPAIRS__*
|
||||||
* @param key (string): sort by value associated with this key in subdict
|
* @param key (string): sort by value associated with this key in subdict
|
||||||
*/
|
*/
|
||||||
$scope.sortResultsBy = function(subdict, key) {
|
$scope.sortResultsBy = function(subdict, key) {
|
||||||
@ -477,11 +556,28 @@ Loader.controller(
|
|||||||
$scope.getSortColumnValue = function(imagePair) {
|
$scope.getSortColumnValue = function(imagePair) {
|
||||||
if ($scope.sortColumnSubdict in imagePair) {
|
if ($scope.sortColumnSubdict in imagePair) {
|
||||||
return imagePair[$scope.sortColumnSubdict][$scope.sortColumnKey];
|
return imagePair[$scope.sortColumnSubdict][$scope.sortColumnKey];
|
||||||
|
} else if ($scope.sortColumnKey in imagePair) {
|
||||||
|
return imagePair[$scope.sortColumnKey];
|
||||||
} else {
|
} else {
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* For a particular ImagePair, return the value we use for the
|
||||||
|
* second-order sort (tiebreaker when multiple rows have
|
||||||
|
* the same getSortColumnValue()).
|
||||||
|
*
|
||||||
|
* We join the imageA and imageB urls for this value, so that we merge
|
||||||
|
* adjacent rows as much as possible.
|
||||||
|
*
|
||||||
|
* @param imagePair: imagePair to get a column value out of.
|
||||||
|
*/
|
||||||
|
$scope.getSecondOrderSortValue = function(imagePair) {
|
||||||
|
return imagePair[constants.KEY__IMAGEPAIRS__IMAGE_A_URL] + "-vs-" +
|
||||||
|
imagePair[constants.KEY__IMAGEPAIRS__IMAGE_B_URL];
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set $scope.categoryValueMatch[name] = value, and update results.
|
* Set $scope.categoryValueMatch[name] = value, and update results.
|
||||||
*
|
*
|
||||||
|
@ -50,6 +50,14 @@
|
|||||||
font-size: 30px;
|
font-size: 30px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Odd and even lines within results display. */
|
||||||
|
.results-odd {
|
||||||
|
background-color: #ddffdd;
|
||||||
|
}
|
||||||
|
.results-even {
|
||||||
|
background-color: #ddddff;
|
||||||
|
}
|
||||||
|
|
||||||
.show-only-button {
|
.show-only-button {
|
||||||
font-size: 8px;
|
font-size: 8px;
|
||||||
}
|
}
|
||||||
|
@ -125,6 +125,12 @@
|
|||||||
ng-change="areUpdatesPending = true"/>
|
ng-change="areUpdatesPending = true"/>
|
||||||
Show thumbnails
|
Show thumbnails
|
||||||
</td></tr>
|
</td></tr>
|
||||||
|
<tr><td>
|
||||||
|
<input type="checkbox" ng-model="mergeIdenticalRowsPending"
|
||||||
|
ng-init="mergeIdenticalRowsPending = true"
|
||||||
|
ng-change="areUpdatesPending = true"/>
|
||||||
|
Merge identical rows
|
||||||
|
</td></tr>
|
||||||
<tr><td>
|
<tr><td>
|
||||||
Image width
|
Image width
|
||||||
<input type="text" ng-model="imageSizePending"
|
<input type="text" ng-model="imageSizePending"
|
||||||
@ -248,9 +254,19 @@
|
|||||||
bugs
|
bugs
|
||||||
</th>
|
</th>
|
||||||
<th width="{{imageSize}}">
|
<th width="{{imageSize}}">
|
||||||
|
<input type="radio"
|
||||||
|
name="sortColumnRadio"
|
||||||
|
value="imageA"
|
||||||
|
ng-checked="(sortColumnKey == constants.KEY__IMAGEPAIRS__IMAGE_A_URL)"
|
||||||
|
ng-click="sortResultsBy('none', constants.KEY__IMAGEPAIRS__IMAGE_A_URL)">
|
||||||
{{imageSets[constants.KEY__IMAGESETS__SET__IMAGE_A][constants.KEY__IMAGESETS__FIELD__DESCRIPTION]}}
|
{{imageSets[constants.KEY__IMAGESETS__SET__IMAGE_A][constants.KEY__IMAGESETS__FIELD__DESCRIPTION]}}
|
||||||
</th>
|
</th>
|
||||||
<th width="{{imageSize}}">
|
<th width="{{imageSize}}">
|
||||||
|
<input type="radio"
|
||||||
|
name="sortColumnRadio"
|
||||||
|
value="imageB"
|
||||||
|
ng-checked="(sortColumnKey == constants.KEY__IMAGEPAIRS__IMAGE_B_URL)"
|
||||||
|
ng-click="sortResultsBy('none', constants.KEY__IMAGEPAIRS__IMAGE_B_URL)">
|
||||||
{{imageSets[constants.KEY__IMAGESETS__SET__IMAGE_B][constants.KEY__IMAGESETS__FIELD__DESCRIPTION]}}
|
{{imageSets[constants.KEY__IMAGESETS__SET__IMAGE_B][constants.KEY__IMAGESETS__FIELD__DESCRIPTION]}}
|
||||||
</th>
|
</th>
|
||||||
<th width="{{imageSize}}">
|
<th width="{{imageSize}}">
|
||||||
@ -280,7 +296,9 @@
|
|||||||
</th>
|
</th>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
<tr ng-repeat="imagePair in limitedImagePairs" results-updated-callback-directive>
|
<tr ng-repeat="imagePair in limitedImagePairs" valign="top"
|
||||||
|
ng-class-odd="'results-odd'" ng-class-even="'results-even'"
|
||||||
|
results-updated-callback-directive>
|
||||||
<td>
|
<td>
|
||||||
{{imagePair[constants.KEY__IMAGEPAIRS__EXTRACOLUMNS][constants.KEY__EXTRACOLUMNS__RESULT_TYPE]}}
|
{{imagePair[constants.KEY__IMAGEPAIRS__EXTRACOLUMNS][constants.KEY__EXTRACOLUMNS__RESULT_TYPE]}}
|
||||||
<br>
|
<br>
|
||||||
@ -345,7 +363,7 @@
|
|||||||
</td>
|
</td>
|
||||||
|
|
||||||
<!-- image A -->
|
<!-- image A -->
|
||||||
<td valign="bottom" width="{{imageSize}}">
|
<td width="{{imageSize}}" ng-if="imagePair[constants.KEY__IMAGEPAIRS__ROWSPAN] > 0" rowspan="{{imagePair[constants.KEY__IMAGEPAIRS__ROWSPAN]}}">
|
||||||
<div ng-if="imagePair[constants.KEY__IMAGEPAIRS__IMAGE_A_URL] != null">
|
<div ng-if="imagePair[constants.KEY__IMAGEPAIRS__IMAGE_A_URL] != null">
|
||||||
<a href="{{imageSets[constants.KEY__IMAGESETS__SET__IMAGE_A][constants.KEY__IMAGESETS__FIELD__BASE_URL]}}/{{imagePair[constants.KEY__IMAGEPAIRS__IMAGE_A_URL]}}" target="_blank">View Image</a><br/>
|
<a href="{{imageSets[constants.KEY__IMAGESETS__SET__IMAGE_A][constants.KEY__IMAGESETS__FIELD__BASE_URL]}}/{{imagePair[constants.KEY__IMAGEPAIRS__IMAGE_A_URL]}}" target="_blank">View Image</a><br/>
|
||||||
<img ng-if="showThumbnails"
|
<img ng-if="showThumbnails"
|
||||||
@ -359,7 +377,7 @@
|
|||||||
</td>
|
</td>
|
||||||
|
|
||||||
<!-- image B -->
|
<!-- image B -->
|
||||||
<td valign="bottom" width="{{imageSize}}">
|
<td width="{{imageSize}}" ng-if="imagePair[constants.KEY__IMAGEPAIRS__ROWSPAN] > 0" rowspan="{{imagePair[constants.KEY__IMAGEPAIRS__ROWSPAN]}}">
|
||||||
<div ng-if="imagePair[constants.KEY__IMAGEPAIRS__IMAGE_B_URL] != null">
|
<div ng-if="imagePair[constants.KEY__IMAGEPAIRS__IMAGE_B_URL] != null">
|
||||||
<a href="{{imageSets[constants.KEY__IMAGESETS__SET__IMAGE_B][constants.KEY__IMAGESETS__FIELD__BASE_URL]}}/{{imagePair[constants.KEY__IMAGEPAIRS__IMAGE_B_URL]}}" target="_blank">View Image</a><br/>
|
<a href="{{imageSets[constants.KEY__IMAGESETS__SET__IMAGE_B][constants.KEY__IMAGESETS__FIELD__BASE_URL]}}/{{imagePair[constants.KEY__IMAGEPAIRS__IMAGE_B_URL]}}" target="_blank">View Image</a><br/>
|
||||||
<img ng-if="showThumbnails"
|
<img ng-if="showThumbnails"
|
||||||
@ -373,17 +391,17 @@
|
|||||||
</td>
|
</td>
|
||||||
|
|
||||||
<!-- whitediffs: every differing pixel shown in white -->
|
<!-- whitediffs: every differing pixel shown in white -->
|
||||||
<td valign="bottom" width="{{imageSize}}">
|
<td width="{{imageSize}}" ng-if="imagePair[constants.KEY__IMAGEPAIRS__ROWSPAN] > 0" rowspan="{{imagePair[constants.KEY__IMAGEPAIRS__ROWSPAN]}}">
|
||||||
<div ng-if="imagePair[constants.KEY__IMAGEPAIRS__IS_DIFFERENT]"
|
<div ng-if="imagePair[constants.KEY__IMAGEPAIRS__IS_DIFFERENT]"
|
||||||
title="{{imagePair[constants.KEY__IMAGEPAIRS__DIFFERENCES][constants.KEY__DIFFERENCES__NUM_DIFF_PIXELS] | number:0}} of {{(100 * imagePair[constants.KEY__IMAGEPAIRS__DIFFERENCES][constants.KEY__DIFFERENCES__NUM_DIFF_PIXELS] / imagePair[constants.KEY__IMAGEPAIRS__DIFFERENCES][constants.KEY__DIFFERENCES__PERCENT_DIFF_PIXELS]) | number:0}} pixels ({{imagePair[constants.KEY__IMAGEPAIRS__DIFFERENCES][constants.KEY__DIFFERENCES__PERCENT_DIFF_PIXELS].toFixed(4)}}%) differ from expectation.">
|
title="{{imagePair[constants.KEY__IMAGEPAIRS__DIFFERENCES][constants.KEY__DIFFERENCES__NUM_DIFF_PIXELS] | number:0}} of {{(100 * imagePair[constants.KEY__IMAGEPAIRS__DIFFERENCES][constants.KEY__DIFFERENCES__NUM_DIFF_PIXELS] / imagePair[constants.KEY__IMAGEPAIRS__DIFFERENCES][constants.KEY__DIFFERENCES__PERCENT_DIFF_PIXELS]) | number:0}} pixels ({{imagePair[constants.KEY__IMAGEPAIRS__DIFFERENCES][constants.KEY__DIFFERENCES__PERCENT_DIFF_PIXELS].toFixed(4)}}%) differ from expectation.">
|
||||||
|
|
||||||
{{imagePair[constants.KEY__IMAGEPAIRS__DIFFERENCES][constants.KEY__DIFFERENCES__PERCENT_DIFF_PIXELS].toFixed(4)}}%
|
|
||||||
({{imagePair[constants.KEY__IMAGEPAIRS__DIFFERENCES][constants.KEY__DIFFERENCES__NUM_DIFF_PIXELS]}})
|
|
||||||
<br/>
|
|
||||||
<a href="{{imageSets[constants.KEY__IMAGESETS__SET__WHITEDIFFS][constants.KEY__IMAGESETS__FIELD__BASE_URL]}}/{{getImageDiffRelativeUrl(imagePair)}}" target="_blank">View Image</a><br/>
|
<a href="{{imageSets[constants.KEY__IMAGESETS__SET__WHITEDIFFS][constants.KEY__IMAGESETS__FIELD__BASE_URL]}}/{{getImageDiffRelativeUrl(imagePair)}}" target="_blank">View Image</a><br/>
|
||||||
<img ng-if="showThumbnails"
|
<img ng-if="showThumbnails"
|
||||||
width="{{imageSize}}"
|
width="{{imageSize}}"
|
||||||
ng-src="{{imageSets[constants.KEY__IMAGESETS__SET__WHITEDIFFS][constants.KEY__IMAGESETS__FIELD__BASE_URL]}}/{{getImageDiffRelativeUrl(imagePair)}}" />
|
ng-src="{{imageSets[constants.KEY__IMAGESETS__SET__WHITEDIFFS][constants.KEY__IMAGESETS__FIELD__BASE_URL]}}/{{getImageDiffRelativeUrl(imagePair)}}" />
|
||||||
|
<br/>
|
||||||
|
{{imagePair[constants.KEY__IMAGEPAIRS__DIFFERENCES][constants.KEY__DIFFERENCES__PERCENT_DIFF_PIXELS].toFixed(4)}}%
|
||||||
|
({{imagePair[constants.KEY__IMAGEPAIRS__DIFFERENCES][constants.KEY__DIFFERENCES__NUM_DIFF_PIXELS]}})
|
||||||
</div>
|
</div>
|
||||||
<div ng-show="!imagePair[constants.KEY__IMAGEPAIRS__IS_DIFFERENT]"
|
<div ng-show="!imagePair[constants.KEY__IMAGEPAIRS__IS_DIFFERENT]"
|
||||||
style="text-align:center">
|
style="text-align:center">
|
||||||
@ -392,18 +410,18 @@
|
|||||||
</td>
|
</td>
|
||||||
|
|
||||||
<!-- diffs: per-channel RGB deltas -->
|
<!-- diffs: per-channel RGB deltas -->
|
||||||
<td valign="bottom" width="{{imageSize}}">
|
<td width="{{imageSize}}" ng-if="imagePair[constants.KEY__IMAGEPAIRS__ROWSPAN] > 0" rowspan="{{imagePair[constants.KEY__IMAGEPAIRS__ROWSPAN]}}">
|
||||||
<div ng-if="imagePair[constants.KEY__IMAGEPAIRS__IS_DIFFERENT]"
|
<div ng-if="imagePair[constants.KEY__IMAGEPAIRS__IS_DIFFERENT]"
|
||||||
title="Perceptual difference measure is {{imagePair[constants.KEY__IMAGEPAIRS__DIFFERENCES][constants.KEY__DIFFERENCES__PERCEPTUAL_DIFF].toFixed(4)}}%. Maximum difference per channel: R={{imagePair[constants.KEY__IMAGEPAIRS__DIFFERENCES][constants.KEY__DIFFERENCES__MAX_DIFF_PER_CHANNEL][0]}}, G={{imagePair[constants.KEY__IMAGEPAIRS__DIFFERENCES][constants.KEY__DIFFERENCES__MAX_DIFF_PER_CHANNEL][1]}}, B={{imagePair[constants.KEY__IMAGEPAIRS__DIFFERENCES][constants.KEY__DIFFERENCES__MAX_DIFF_PER_CHANNEL][2]}}">
|
title="Perceptual difference measure is {{imagePair[constants.KEY__IMAGEPAIRS__DIFFERENCES][constants.KEY__DIFFERENCES__PERCEPTUAL_DIFF].toFixed(4)}}%. Maximum difference per channel: R={{imagePair[constants.KEY__IMAGEPAIRS__DIFFERENCES][constants.KEY__DIFFERENCES__MAX_DIFF_PER_CHANNEL][0]}}, G={{imagePair[constants.KEY__IMAGEPAIRS__DIFFERENCES][constants.KEY__DIFFERENCES__MAX_DIFF_PER_CHANNEL][1]}}, B={{imagePair[constants.KEY__IMAGEPAIRS__DIFFERENCES][constants.KEY__DIFFERENCES__MAX_DIFF_PER_CHANNEL][2]}}">
|
||||||
|
|
||||||
{{imagePair[constants.KEY__IMAGEPAIRS__DIFFERENCES][constants.KEY__DIFFERENCES__PERCEPTUAL_DIFF].toFixed(4)}}%
|
|
||||||
{{imagePair[constants.KEY__IMAGEPAIRS__DIFFERENCES][constants.KEY__DIFFERENCES__MAX_DIFF_PER_CHANNEL]}}
|
|
||||||
<br/>
|
|
||||||
<a href="{{imageSets[constants.KEY__IMAGESETS__SET__DIFFS][constants.KEY__IMAGESETS__FIELD__BASE_URL]}}/{{getImageDiffRelativeUrl(imagePair)}}" target="_blank">View Image</a><br/>
|
<a href="{{imageSets[constants.KEY__IMAGESETS__SET__DIFFS][constants.KEY__IMAGESETS__FIELD__BASE_URL]}}/{{getImageDiffRelativeUrl(imagePair)}}" target="_blank">View Image</a><br/>
|
||||||
<img ng-if="showThumbnails"
|
<img ng-if="showThumbnails"
|
||||||
ng-style="{backgroundColor: pixelDiffBgColor}"
|
ng-style="{backgroundColor: pixelDiffBgColor}"
|
||||||
width="{{imageSize}}"
|
width="{{imageSize}}"
|
||||||
ng-src="{{imageSets[constants.KEY__IMAGESETS__SET__DIFFS][constants.KEY__IMAGESETS__FIELD__BASE_URL]}}/{{getImageDiffRelativeUrl(imagePair)}}" />
|
ng-src="{{imageSets[constants.KEY__IMAGESETS__SET__DIFFS][constants.KEY__IMAGESETS__FIELD__BASE_URL]}}/{{getImageDiffRelativeUrl(imagePair)}}" />
|
||||||
|
<br/>
|
||||||
|
{{imagePair[constants.KEY__IMAGEPAIRS__DIFFERENCES][constants.KEY__DIFFERENCES__PERCEPTUAL_DIFF].toFixed(4)}}%
|
||||||
|
{{imagePair[constants.KEY__IMAGEPAIRS__DIFFERENCES][constants.KEY__DIFFERENCES__MAX_DIFF_PER_CHANNEL]}}
|
||||||
</div>
|
</div>
|
||||||
<div ng-show="!imagePair[constants.KEY__IMAGEPAIRS__IS_DIFFERENT]"
|
<div ng-show="!imagePair[constants.KEY__IMAGEPAIRS__IS_DIFFERENT]"
|
||||||
style="text-align:center">
|
style="text-align:center">
|
||||||
@ -411,12 +429,13 @@
|
|||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
<td>
|
<td ng-if="imagePair[constants.KEY__IMAGEPAIRS__ROWSPAN] > 0" rowspan="{{imagePair[constants.KEY__IMAGEPAIRS__ROWSPAN]}}">
|
||||||
|
<br/>
|
||||||
<input type="checkbox"
|
<input type="checkbox"
|
||||||
name="rowSelect"
|
name="rowSelect"
|
||||||
value="{{imagePair.index}}"
|
value="{{imagePair.index}}"
|
||||||
ng-checked="isValueInArray(imagePair.index, selectedImagePairs)"
|
ng-checked="isValueInArray(imagePair.index, selectedImagePairs)"
|
||||||
ng-click="toggleValueInArray(imagePair.index, selectedImagePairs)">
|
ng-click="toggleSomeImagePairs($index, imagePair[constants.KEY__IMAGEPAIRS__ROWSPAN])">
|
||||||
</tr>
|
</tr>
|
||||||
</table> <!-- imagePairs -->
|
</table> <!-- imagePairs -->
|
||||||
</td></tr></table> <!-- table holding results header + imagePairs table -->
|
</td></tr></table> <!-- table holding results header + imagePairs table -->
|
||||||
|
Loading…
Reference in New Issue
Block a user