tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

tcuBilinearImageCompare.js (11774B)


      1 /*-------------------------------------------------------------------------
      2 * drawElements Quality Program OpenGL ES Utilities
      3 * ------------------------------------------------
      4 *
      5 * Copyright 2014 The Android Open Source Project
      6 *
      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
     10 *
     11 *      http://www.apache.org/licenses/LICENSE-2.0
     12 *
     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.
     18 *
     19 */
     20 
     21 'use strict';
     22 goog.provide('framework.common.tcuBilinearImageCompare');
     23 goog.require('framework.common.tcuRGBA');
     24 goog.require('framework.common.tcuTexture');
     25 goog.require('framework.delibs.debase.deMath');
     26 
     27 goog.scope(function() {
     28 
     29    var tcuBilinearImageCompare = framework.common.tcuBilinearImageCompare;
     30    var deMath = framework.delibs.debase.deMath;
     31    var tcuTexture = framework.common.tcuTexture;
     32    var tcuRGBA = framework.common.tcuRGBA;
     33 
     34    var DE_ASSERT = function(x) {
     35        if (!x)
     36            throw new Error('Assert failed');
     37    };
     38 
     39    // for bilinear interpolation
     40    /** @const {number} */ tcuBilinearImageCompare.NUM_SUBPIXEL_BITS = 8;
     41 
     42    // Algorithm assumes that colors are packed to 32-bit values as dictated by
     43    // tcu::RGBA::*_SHIFT values.
     44 
     45    function UintRGBA8_R(color) {
     46        return (color >> 24) & 0xff;
     47    }
     48    function UintRGBA8_G(color) {
     49        return (color >> 16) & 0xff;
     50    }
     51    function UintRGBA8_B(color) {
     52        return (color >> 8) & 0xff;
     53    }
     54    function UintRGBA8_A(color) {
     55        return color & 0xff;
     56    }
     57 
     58    /**
     59    * @param {number} fx1 deUint32
     60    * @param {number} fy1 deUint32
     61    * @param {number} p00 deUint8
     62    * @param {number} p01 deUint8
     63    * @param {number} p10 deUint8
     64    * @param {number} p11 deUint8
     65    * @return {number} deUint8
     66    */
     67    tcuBilinearImageCompare.interpolateChannel = function(fx1, fy1, p00, p01, p10, p11) {
     68        /** @const {number} */ var fx0 = (1 << tcuBilinearImageCompare.NUM_SUBPIXEL_BITS) - fx1;
     69        /** @const {number} */ var fy0 = (1 << tcuBilinearImageCompare.NUM_SUBPIXEL_BITS) - fy1;
     70        /** @const {number} */
     71        var half = 1 << (tcuBilinearImageCompare.NUM_SUBPIXEL_BITS * 2 - 1);
     72        /** @const {number} */ var sum =
     73            (fx0 * fy0 * p00) +
     74            (fx1 * fy0 * p10) +
     75            (fx0 * fy1 * p01) +
     76            (fx1 * fy1 * p11);
     77        /** @const {number} */
     78        var rounded = (sum + half) >> (tcuBilinearImageCompare.NUM_SUBPIXEL_BITS * 2);
     79 
     80        DE_ASSERT(deMath.deInRange32(rounded, 0, 0xff));
     81        return rounded;
     82    };
     83 
     84    tcuBilinearImageCompare.compareUintRGBA8Threshold = function(a, b, thr) {
     85        if (a == b)
     86            return true;
     87 
     88        return (Math.abs(UintRGBA8_R(a) - UintRGBA8_R(b)) <= thr.getRed() &&
     89            Math.abs(UintRGBA8_G(a) - UintRGBA8_G(b)) <= thr.getGreen() &&
     90            Math.abs(UintRGBA8_B(a) - UintRGBA8_B(b)) <= thr.getBlue() &&
     91            Math.abs(UintRGBA8_A(a) - UintRGBA8_A(b)) <= thr.getAlpha());
     92    };
     93 
     94    /**
     95     * @param {tcuTexture.RGBA8View} view
     96     * @param {number} u
     97     * @param {number} v
     98     * @return {number}
     99     */
    100    tcuBilinearImageCompare.bilinearSampleUintRGBA8 = function(view, u, v) {
    101        /** @type {number} */ var x0 = u >> tcuBilinearImageCompare.NUM_SUBPIXEL_BITS;
    102        /** @type {number} */ var y0 = v >> tcuBilinearImageCompare.NUM_SUBPIXEL_BITS;
    103        /** @type {number} */ var x1 = x0 + 1;
    104        /** @type {number} */ var y1 = y0 + 1;
    105 
    106        DE_ASSERT(x1 < view.getWidth());
    107        DE_ASSERT(y1 < view.getHeight());
    108 
    109        /** @type {number} */ var fx1 = u - (x0 << tcuBilinearImageCompare.NUM_SUBPIXEL_BITS);
    110        /** @type {number} */ var fy1 = v - (y0 << tcuBilinearImageCompare.NUM_SUBPIXEL_BITS);
    111 
    112        /** @type {Array<number>} */ var channelsP00 = view.readUintRGBA8(x0, y0);
    113        /** @type {Array<number>} */ var channelsP10 = view.readUintRGBA8(x1, y0);
    114        /** @type {Array<number>} */ var channelsP01 = view.readUintRGBA8(x0, y1);
    115        /** @type {Array<number>} */ var channelsP11 = view.readUintRGBA8(x1, y1);
    116 
    117        /** @type {number} */ var res = 0;
    118 
    119        res = (tcuBilinearImageCompare.interpolateChannel(fx1, fy1, UintRGBA8_R(channelsP00),
    120            UintRGBA8_R(channelsP01), UintRGBA8_R(channelsP10), UintRGBA8_R(channelsP11)) & 0xff) << 24;
    121        res += (tcuBilinearImageCompare.interpolateChannel(fx1, fy1, UintRGBA8_G(channelsP00),
    122            UintRGBA8_G(channelsP01), UintRGBA8_G(channelsP10), UintRGBA8_G(channelsP11)) & 0xff) << 16;
    123        res += (tcuBilinearImageCompare.interpolateChannel(fx1, fy1, UintRGBA8_B(channelsP00),
    124            UintRGBA8_B(channelsP01), UintRGBA8_B(channelsP10), UintRGBA8_B(channelsP11)) & 0xff) << 8;
    125        res += tcuBilinearImageCompare.interpolateChannel(fx1, fy1, UintRGBA8_A(channelsP00),
    126            UintRGBA8_A(channelsP01), UintRGBA8_A(channelsP10), UintRGBA8_A(channelsP11)) & 0xff;
    127 
    128        return res;
    129    };
    130 
    131    /**
    132     * @param {tcuTexture.RGBA8View} reference
    133     * @param {tcuTexture.RGBA8View} result
    134     * @param {tcuRGBA.RGBA} threshold
    135     * @param {number} x
    136     * @param {number} y
    137     * @return {boolean}
    138     */
    139    tcuBilinearImageCompare.comparePixelRGBA8 = function(reference, result, threshold, x, y) {
    140        /** @const {tcuRGBA.RGBA} */ var resPix = result.readUintRGBA8(x, y);
    141 
    142        // Step 1: Compare result pixel to 3x3 neighborhood pixels in reference.
    143        /** @const {number} */ var x0 = Math.max(x - 1, 0);
    144        /** @const {number} */ var x1 = x;
    145        /** @const {number} */
    146        var x2 = Math.min(x + 1, reference.getWidth() - 1);
    147        /** @const {number} */ var y0 = Math.max(y - 1, 0);
    148        /** @const {number} */ var y1 = y;
    149        /** @const {number} */
    150        var y2 = Math.min(y + 1, reference.getHeight() - 1);
    151 
    152        //tcuBilinearImageCompare.readRGBA8List (reference, x0, y0, x2, y2);
    153 
    154        if (tcuBilinearImageCompare.compareUintRGBA8Threshold(resPix, reference.readUintRGBA8(x1, y1), threshold) ||
    155            tcuBilinearImageCompare.compareUintRGBA8Threshold(resPix, reference.readUintRGBA8(x0, y1), threshold) ||
    156            tcuBilinearImageCompare.compareUintRGBA8Threshold(resPix, reference.readUintRGBA8(x2, y1), threshold) ||
    157            tcuBilinearImageCompare.compareUintRGBA8Threshold(resPix, reference.readUintRGBA8(x0, y0), threshold) ||
    158            tcuBilinearImageCompare.compareUintRGBA8Threshold(resPix, reference.readUintRGBA8(x1, y0), threshold) ||
    159            tcuBilinearImageCompare.compareUintRGBA8Threshold(resPix, reference.readUintRGBA8(x2, y0), threshold) ||
    160            tcuBilinearImageCompare.compareUintRGBA8Threshold(resPix, reference.readUintRGBA8(x0, y2), threshold) ||
    161            tcuBilinearImageCompare.compareUintRGBA8Threshold(resPix, reference.readUintRGBA8(x1, y2), threshold) ||
    162            tcuBilinearImageCompare.compareUintRGBA8Threshold(resPix, reference.readUintRGBA8(x2, y2), threshold))
    163            return true;
    164 
    165        // Step 2: Compare using bilinear sampling.
    166        // \todo [pyry] Optimize sample positions!
    167        /** @const {Array<Array<number>>} */ var s_offsets = [
    168            [226, 186],
    169            [335, 235],
    170            [279, 334],
    171            [178, 272],
    172            [112, 202],
    173            [306, 117],
    174            [396, 299],
    175            [206, 382],
    176            [146, 96],
    177            [423, 155],
    178            [361, 412],
    179            [84, 339],
    180            [48, 130],
    181            [367, 43],
    182            [455, 367],
    183            [105, 439],
    184            [83, 46],
    185            [217, 24],
    186            [461, 71],
    187            [450, 459],
    188            [239, 469],
    189            [67, 267],
    190            [459, 255],
    191            [13, 416],
    192            [10, 192],
    193            [141, 502],
    194            [503, 304],
    195            [380, 506]
    196        ];
    197 
    198        for (var sampleNdx = 0; sampleNdx < s_offsets.length; sampleNdx++) {
    199            /** @const {number} */
    200            var u = ((x - 1) << tcuBilinearImageCompare.NUM_SUBPIXEL_BITS) + s_offsets[sampleNdx][0];
    201            /** @const {number} */
    202            var v = ((y - 1) << tcuBilinearImageCompare.NUM_SUBPIXEL_BITS) + s_offsets[sampleNdx][1];
    203 
    204            if (!deMath.deInBounds32(u, 0, (reference.getWidth() - 1) << tcuBilinearImageCompare.NUM_SUBPIXEL_BITS) ||
    205                !deMath.deInBounds32(v, 0, (reference.getHeight() - 1) << tcuBilinearImageCompare.NUM_SUBPIXEL_BITS))
    206                continue;
    207 
    208            if (tcuBilinearImageCompare.compareUintRGBA8Threshold(resPix, tcuBilinearImageCompare.bilinearSampleUintRGBA8(reference, u, v), threshold))
    209                return true;
    210        }
    211 
    212        return false;
    213    };
    214 
    215    /**
    216     * @param {tcuTexture.RGBA8View} reference
    217     * @param {tcuTexture.RGBA8View} result
    218     * @param {tcuTexture.PixelBufferAccess} errorMask
    219     * @param {tcuRGBA.RGBA} threshold
    220     * @return {boolean}
    221     */
    222    tcuBilinearImageCompare.bilinearCompareRGBA8 = function(reference, result, errorMask, threshold) {
    223        DE_ASSERT(reference.getFormat().isEqual(new tcuTexture.TextureFormat(
    224            tcuTexture.ChannelOrder.RGBA, tcuTexture.ChannelType.UNORM_INT8)));
    225        DE_ASSERT(result.getFormat().isEqual(new tcuTexture.TextureFormat(
    226            tcuTexture.ChannelOrder.RGBA, tcuTexture.ChannelType.UNORM_INT8)));
    227 
    228        // Clear error mask first to green (faster this way).
    229        errorMask.clear([0.0, 1.0, 0.0, 1.0]);
    230 
    231        /** @type {boolean} */ var allOk = true;
    232 
    233        for (var y = 0; y < reference.getHeight(); y++) {
    234            for (var x = 0; x < reference.getWidth(); x++) {
    235                if (!tcuBilinearImageCompare.comparePixelRGBA8(reference, result, threshold, x, y) &&
    236                    !tcuBilinearImageCompare.comparePixelRGBA8(result, reference, threshold, x, y)) {
    237                    allOk = false;
    238                    errorMask.setPixel([1.0, 0.0, 0.0, 1.0], x, y);
    239                }
    240            }
    241        }
    242 
    243        return allOk;
    244    };
    245 
    246    /**
    247     * @param {tcuTexture.ConstPixelBufferAccess} reference
    248     * @param {tcuTexture.ConstPixelBufferAccess} result
    249     * @param {tcuTexture.PixelBufferAccess} errorMask
    250     * @param {tcuRGBA.RGBA} threshold
    251     * @return {boolean}
    252     */
    253    tcuBilinearImageCompare.bilinearCompare = function(reference, result, errorMask, threshold) {
    254        assertMsgOptions(result.getWidth() == reference.getWidth() && result.getHeight() == reference.getHeight() && result.getDepth() == reference.getDepth(),
    255            'Reference and result images have different dimensions', false, true);
    256 
    257        assertMsgOptions(errorMask.getWidth() == reference.getWidth() && errorMask.getHeight() == reference.getHeight() && errorMask.getDepth() == reference.getDepth(),
    258            'Reference and error mask images have different dimensions', false, true);
    259 
    260        /** @type {boolean} */ var isEqual = reference.getFormat().isEqual(
    261            new tcuTexture.TextureFormat(
    262                tcuTexture.ChannelOrder.RGBA,
    263                tcuTexture.ChannelType.UNORM_INT8));
    264        if (isEqual) {
    265            /** @type {tcuTexture.RGBA8View} */ var refView = new tcuTexture.RGBA8View(reference);
    266            /** @type {tcuTexture.RGBA8View} */ var resView = new tcuTexture.RGBA8View(result);
    267            return tcuBilinearImageCompare.bilinearCompareRGBA8(refView, resView, errorMask, threshold);
    268        } else
    269            throw new Error('Unsupported format for bilinear comparison');
    270    };
    271 
    272 });