Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Firefox/dom/canvas/test/   (Browser von der Mozilla Stiftung Version 136.0.1©)  Datei vom 10.2.2025 mit Größe 9 kB image not shown  

Quelle  captureStream_common.js   Sprache: JAVA

 
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */


"use strict";

/*
 * Util base class to help test a captured canvas element. Initializes the
 * output canvas (used for testing the color of video elements), and optionally
 * overrides the default `createAndAppendElement` element |width| and |height|.
 */

function CaptureStreamTestHelper(width, height) {
  if (width) {
    this.elemWidth = width;
  }
  if (height) {
    this.elemHeight = height;
  }

  /* cout is used for `getPixel`; only needs to be big enough for one pixel */
  this.cout = document.createElement("canvas");
  this.cout.width = 1;
  this.cout.height = 1;
}

CaptureStreamTestHelper.prototype = {
  /* Predefined colors for use in the methods below. */
  black: { data: [0, 0, 0, 255], name: "black" },
  blackTransparent: { data: [0, 0, 0, 0], name: "blackTransparent" },
  white: { data: [255, 255, 255, 255], name: "white" },
  green: { data: [0, 255, 0, 255], name: "green" },
  red: { data: [255, 0, 0, 255], name: "red" },
  blue: { data: [0, 0, 255, 255], name: "blue" },
  grey: { data: [128, 128, 128, 255], name: "grey" },

  /* Default element size for createAndAppendElement() */
  elemWidth: 100,
  elemHeight: 100,

  /*
   * Perform the drawing operation on each animation frame until stop is called
   * on the returned object.
   */

  startDrawing(f) {
    var stop = false;
    var draw = () => {
      if (stop) {
        return;
      }
      f();
      window.requestAnimationFrame(draw);
    };
    draw();
    return { stop: () => (stop = true) };
  },

  /* Request a frame from the stream played by |video|. */
  requestFrame(video) {
    info("Requesting frame from " + video.id);
    video.srcObject.requestFrame();
  },

  /*
   * Returns the pixel at (|offsetX|, |offsetY|) (from top left corner) of
   * |video| as an array of the pixel's color channels: [R,G,B,A].
   */

  getPixel(video, offsetX = 0, offsetY = 0) {
    // Avoids old values in case of a transparent image.
    CaptureStreamTestHelper2D.prototype.clear.call(thisthis.cout);

    var ctxout = this.cout.getContext("2d");
    ctxout.drawImage(
      video,
      offsetX, // source x coordinate
      offsetY, // source y coordinate
      1, // source width
      1, // source height
      0, // destination x coordinate
      0, // destination y coordinate
      1, // destination width
      1
    ); // destination height
    return ctxout.getImageData(0, 0, 1, 1).data;
  },

  /*
   * Returns true if px lies within the per-channel |threshold| of the
   * referenced color for all channels. px is on the form of an array of color
   * channels, [R,G,B,A]. Each channel is in the range [0, 255].
   *
   * Threshold defaults to 0 which is an exact match.
   */

  isPixel(px, refColor, threshold = 0) {
    return px.every((ch, i) => Math.abs(ch - refColor.data[i]) <= threshold);
  },

  /*
   * Returns true if px lies further away than |threshold| of the
   * referenced color for any channel. px is on the form of an array of color
   * channels, [R,G,B,A]. Each channel is in the range [0, 255].
   *
   * Threshold defaults to 127 which should be far enough for most cases.
   */

  isPixelNot(px, refColor, threshold = 127) {
    return px.some((ch, i) => Math.abs(ch - refColor.data[i]) > threshold);
  },

  /*
   * Behaves like isPixelNot but ignores the alpha channel.
   */

  isOpaquePixelNot(px, refColor, threshold) {
    px[3] = refColor.data[3];
    return this.isPixelNot(px, refColor, threshold);
  },

  /*
   * Returns a promise that resolves when the provided function |test|
   * returns true, or rejects when the optional `cancel` promise resolves.
   */

  async waitForPixel(
    video,
    test,
    {
      offsetX = 0,
      offsetY = 0,
      width = 0,
      height = 0,
      cancel = new Promise(() => {}),
    } = {}
  ) {
    let aborted = false;
    cancel.then(e => (aborted = true));

    while (true) {
      await Promise.race([
        new Promise(resolve =>
          video.addEventListener("timeupdate", resolve, { once: true })
        ),
        cancel,
      ]);
      if (aborted) {
        throw await cancel;
      }
      if (test(this.getPixel(video, offsetX, offsetY, width, height))) {
        return;
      }
    }
  },

  /*
   * Returns a promise that resolves when the top left pixel of |video| matches
   * on all channels. Use |threshold| for fuzzy matching the color on each
   * channel, in the range [0,255]. 0 means exact match, 255 accepts anything.
   */

  async pixelMustBecome(
    video,
    refColor,
    { threshold = 0, infoString = "n/a", cancel = new Promise(() => {}) } = {}
  ) {
    info(
      "Waiting for video " +
        video.id +
        " to match [" +
        refColor.data.join(",") +
        "] - " +
        refColor.name +
        " (" +
        infoString +
        ")"
    );
    var paintedFrames = video.mozPaintedFrames - 1;
    await this.waitForPixel(
      video,
      px => {
        if (paintedFrames != video.mozPaintedFrames) {
          info(
            "Frame: " +
              video.mozPaintedFrames +
              " IsPixel ref=" +
              refColor.data +
              " threshold=" +
              threshold +
              " value=" +
              px
          );
          paintedFrames = video.mozPaintedFrames;
        }
        return this.isPixel(px, refColor, threshold);
      },
      {
        offsetX: 0,
        offsetY: 0,
        width: 0,
        height: 0,
        cancel,
      }
    );
    ok(true, video.id + " " + infoString);
  },

  /*
   * Returns a promise that resolves after |time| ms of playback or when the
   * top left pixel of |video| becomes |refColor|. The test is failed if the
   * time is not reached, or if the cancel promise resolves.
   */

  async pixelMustNotBecome(
    video,
    refColor,
    { threshold = 0, time = 5000, infoString = "n/a" } = {}
  ) {
    info(
      "Waiting for " +
        video.id +
        " to time out after " +
        time +
        "ms against [" +
        refColor.data.join(",") +
        "] - " +
        refColor.name
    );
    let timeout = new Promise(resolve => setTimeout(resolve, time));
    let analysis = async () => {
      await this.waitForPixel(
        video,
        px => this.isPixel(px, refColor, threshold),
        {
          offsetX: 0,
          offsetY: 0,
          width: 0,
          height: 0,
        }
      );
      throw new Error("Got color " + refColor.name + ". " + infoString);
    };
    await Promise.race([timeout, analysis()]);
    ok(true, video.id + " " + infoString);
  },

  /* Create an element of type |type| with id |id| and append it to the body. */
  createAndAppendElement(type, id) {
    var e = document.createElement(type);
    e.id = id;
    e.width = this.elemWidth;
    e.height = this.elemHeight;
    if (type === "video") {
      e.autoplay = true;
    }
    document.body.appendChild(e);
    return e;
  },
};

/* Sub class holding 2D-Canvas specific helpers. */
function CaptureStreamTestHelper2D(width, height) {
  CaptureStreamTestHelper.call(this, width, height);
}

CaptureStreamTestHelper2D.prototype = Object.create(
  CaptureStreamTestHelper.prototype
);
CaptureStreamTestHelper2D.prototype.constructor = CaptureStreamTestHelper2D;

/* Clear all drawn content on |canvas|. */
CaptureStreamTestHelper2D.prototype.clear = function (canvas) {
  var ctx = canvas.getContext("2d");
  ctx.clearRect(0, 0, canvas.width, canvas.height);
};

/* Draw the color |color| to the source canvas |canvas|. Format [R,G,B,A]. */
CaptureStreamTestHelper2D.prototype.drawColor = function (
  canvas,
  color,
  {
    offsetX = 0,
    offsetY = 0,
    width = canvas.width / 2,
    height = canvas.height / 2,
  } = {}
) {
  var ctx = canvas.getContext("2d");
  var rgba = color.data.slice(); // Copy to not overwrite the original array
  rgba[3] = rgba[3] / 255.0; // Convert opacity to double in range [0,1]
  info("Drawing color " + rgba.join(","));
  ctx.fillStyle = "rgba(" + rgba.join(",") + ")";

  // Only fill top left corner to test that output is not flipped or rotated.
  ctx.fillRect(offsetX, offsetY, width, height);
};

/* Test that the given 2d canvas is NOT origin-clean. */
CaptureStreamTestHelper2D.prototype.testNotClean = function (canvas) {
  var ctx = canvas.getContext("2d");
  var error = "OK";
  try {
    var data = ctx.getImageData(0, 0, 1, 1);
  } catch (e) {
    error = e.name;
  }
  is(
    error,
    "SecurityError",
    "Canvas '" + canvas.id + "' should not be origin-clean"
  );
};

/* Sub class holding WebGL specific helpers. */
function CaptureStreamTestHelperWebGL(width, height) {
  CaptureStreamTestHelper.call(this, width, height);
}

CaptureStreamTestHelperWebGL.prototype = Object.create(
  CaptureStreamTestHelper.prototype
);
CaptureStreamTestHelperWebGL.prototype.constructor =
  CaptureStreamTestHelperWebGL;

/* Set the (uniform) color location for future draw calls. */
CaptureStreamTestHelperWebGL.prototype.setFragmentColorLocation = function (
  colorLocation
) {
  this.colorLocation = colorLocation;
};

/* Clear the given WebGL context with |color|. */
CaptureStreamTestHelperWebGL.prototype.clearColor = function (canvas, color) {
  info("WebGL: clearColor(" + color.name + ")");
  var gl = canvas.getContext("webgl");
  var conv = color.data.map(i => i / 255.0);
  gl.clearColor(conv[0], conv[1], conv[2], conv[3]);
  gl.clear(gl.COLOR_BUFFER_BIT);
};

/* Set an already setFragmentColorLocation() to |color| and drawArrays() */
CaptureStreamTestHelperWebGL.prototype.drawColor = function (canvas, color) {
  info("WebGL: drawArrays(" + color.name + ")");
  var gl = canvas.getContext("webgl");
  var conv = color.data.map(i => i / 255.0);
  gl.uniform4f(this.colorLocation, conv[0], conv[1], conv[2], conv[3]);
  gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
};

Messung V0.5
C=98 H=100 G=98

¤ Dauer der Verarbeitung: 0.4 Sekunden  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.