pixelmatch

temporary lib: pixelmatch@5.2.0

此脚本不应直接安装。它是供其他脚本使用的外部库,要使用该库请加入元指令 // @require https://update.gf.qytechs.cn/scripts/401377/970885/pixelmatch.js

  1. (function webpackUniversalModuleDefinition(root, factory) {
  2. if(typeof exports === 'object' && typeof module === 'object')
  3. module.exports = factory();
  4. else if(typeof define === 'function' && define.amd)
  5. define([], factory);
  6. else if(typeof exports === 'object')
  7. exports["pixelmatch"] = factory();
  8. else
  9. root["pixelmatch"] = factory();
  10. })(self, function() {
  11. return /******/ (() => { // webpackBootstrap
  12. /******/ var __webpack_modules__ = ({
  13.  
  14. /***/ 148:
  15. /***/ ((module) => {
  16.  
  17. "use strict";
  18.  
  19.  
  20. module.exports = pixelmatch;
  21.  
  22. const defaultOptions = {
  23. threshold: 0.1, // matching threshold (0 to 1); smaller is more sensitive
  24. includeAA: false, // whether to skip anti-aliasing detection
  25. alpha: 0.1, // opacity of original image in diff ouput
  26. aaColor: [255, 255, 0], // color of anti-aliased pixels in diff output
  27. diffColor: [255, 0, 0], // color of different pixels in diff output
  28. diffColorAlt: null, // whether to detect dark on light differences between img1 and img2 and set an alternative color to differentiate between the two
  29. diffMask: false // draw the diff over a transparent background (a mask)
  30. };
  31.  
  32. function pixelmatch(img1, img2, output, width, height, options) {
  33.  
  34. if (!isPixelData(img1) || !isPixelData(img2) || (output && !isPixelData(output)))
  35. throw new Error('Image data: Uint8Array, Uint8ClampedArray or Buffer expected.');
  36.  
  37. if (img1.length !== img2.length || (output && output.length !== img1.length))
  38. throw new Error('Image sizes do not match.');
  39.  
  40. if (img1.length !== width * height * 4) throw new Error('Image data size does not match width/height.');
  41.  
  42. options = Object.assign({}, defaultOptions, options);
  43.  
  44. // check if images are identical
  45. const len = width * height;
  46. const a32 = new Uint32Array(img1.buffer, img1.byteOffset, len);
  47. const b32 = new Uint32Array(img2.buffer, img2.byteOffset, len);
  48. let identical = true;
  49.  
  50. for (let i = 0; i < len; i++) {
  51. if (a32[i] !== b32[i]) { identical = false; break; }
  52. }
  53. if (identical) { // fast path if identical
  54. if (output && !options.diffMask) {
  55. for (let i = 0; i < len; i++) drawGrayPixel(img1, 4 * i, options.alpha, output);
  56. }
  57. return 0;
  58. }
  59.  
  60. // maximum acceptable square distance between two colors;
  61. // 35215 is the maximum possible value for the YIQ difference metric
  62. const maxDelta = 35215 * options.threshold * options.threshold;
  63. let diff = 0;
  64.  
  65. // compare each pixel of one image against the other one
  66. for (let y = 0; y < height; y++) {
  67. for (let x = 0; x < width; x++) {
  68.  
  69. const pos = (y * width + x) * 4;
  70.  
  71. // squared YUV distance between colors at this pixel position, negative if the img2 pixel is darker
  72. const delta = colorDelta(img1, img2, pos, pos);
  73.  
  74. // the color difference is above the threshold
  75. if (Math.abs(delta) > maxDelta) {
  76. // check it's a real rendering difference or just anti-aliasing
  77. if (!options.includeAA && (antialiased(img1, x, y, width, height, img2) ||
  78. antialiased(img2, x, y, width, height, img1))) {
  79. // one of the pixels is anti-aliasing; draw as yellow and do not count as difference
  80. // note that we do not include such pixels in a mask
  81. if (output && !options.diffMask) drawPixel(output, pos, ...options.aaColor);
  82.  
  83. } else {
  84. // found substantial difference not caused by anti-aliasing; draw it as such
  85. if (output) {
  86. drawPixel(output, pos, ...(delta < 0 && options.diffColorAlt || options.diffColor));
  87. }
  88. diff++;
  89. }
  90.  
  91. } else if (output) {
  92. // pixels are similar; draw background as grayscale image blended with white
  93. if (!options.diffMask) drawGrayPixel(img1, pos, options.alpha, output);
  94. }
  95. }
  96. }
  97.  
  98. // return the number of different pixels
  99. return diff;
  100. }
  101.  
  102. function isPixelData(arr) {
  103. // work around instanceof Uint8Array not working properly in some Jest environments
  104. return ArrayBuffer.isView(arr) && arr.constructor.BYTES_PER_ELEMENT === 1;
  105. }
  106.  
  107. // check if a pixel is likely a part of anti-aliasing;
  108. // based on "Anti-aliased Pixel and Intensity Slope Detector" paper by V. Vysniauskas, 2009
  109.  
  110. function antialiased(img, x1, y1, width, height, img2) {
  111. const x0 = Math.max(x1 - 1, 0);
  112. const y0 = Math.max(y1 - 1, 0);
  113. const x2 = Math.min(x1 + 1, width - 1);
  114. const y2 = Math.min(y1 + 1, height - 1);
  115. const pos = (y1 * width + x1) * 4;
  116. let zeroes = x1 === x0 || x1 === x2 || y1 === y0 || y1 === y2 ? 1 : 0;
  117. let min = 0;
  118. let max = 0;
  119. let minX, minY, maxX, maxY;
  120.  
  121. // go through 8 adjacent pixels
  122. for (let x = x0; x <= x2; x++) {
  123. for (let y = y0; y <= y2; y++) {
  124. if (x === x1 && y === y1) continue;
  125.  
  126. // brightness delta between the center pixel and adjacent one
  127. const delta = colorDelta(img, img, pos, (y * width + x) * 4, true);
  128.  
  129. // count the number of equal, darker and brighter adjacent pixels
  130. if (delta === 0) {
  131. zeroes++;
  132. // if found more than 2 equal siblings, it's definitely not anti-aliasing
  133. if (zeroes > 2) return false;
  134.  
  135. // remember the darkest pixel
  136. } else if (delta < min) {
  137. min = delta;
  138. minX = x;
  139. minY = y;
  140.  
  141. // remember the brightest pixel
  142. } else if (delta > max) {
  143. max = delta;
  144. maxX = x;
  145. maxY = y;
  146. }
  147. }
  148. }
  149.  
  150. // if there are no both darker and brighter pixels among siblings, it's not anti-aliasing
  151. if (min === 0 || max === 0) return false;
  152.  
  153. // if either the darkest or the brightest pixel has 3+ equal siblings in both images
  154. // (definitely not anti-aliased), this pixel is anti-aliased
  155. return (hasManySiblings(img, minX, minY, width, height) && hasManySiblings(img2, minX, minY, width, height)) ||
  156. (hasManySiblings(img, maxX, maxY, width, height) && hasManySiblings(img2, maxX, maxY, width, height));
  157. }
  158.  
  159. // check if a pixel has 3+ adjacent pixels of the same color.
  160. function hasManySiblings(img, x1, y1, width, height) {
  161. const x0 = Math.max(x1 - 1, 0);
  162. const y0 = Math.max(y1 - 1, 0);
  163. const x2 = Math.min(x1 + 1, width - 1);
  164. const y2 = Math.min(y1 + 1, height - 1);
  165. const pos = (y1 * width + x1) * 4;
  166. let zeroes = x1 === x0 || x1 === x2 || y1 === y0 || y1 === y2 ? 1 : 0;
  167.  
  168. // go through 8 adjacent pixels
  169. for (let x = x0; x <= x2; x++) {
  170. for (let y = y0; y <= y2; y++) {
  171. if (x === x1 && y === y1) continue;
  172.  
  173. const pos2 = (y * width + x) * 4;
  174. if (img[pos] === img[pos2] &&
  175. img[pos + 1] === img[pos2 + 1] &&
  176. img[pos + 2] === img[pos2 + 2] &&
  177. img[pos + 3] === img[pos2 + 3]) zeroes++;
  178.  
  179. if (zeroes > 2) return true;
  180. }
  181. }
  182.  
  183. return false;
  184. }
  185.  
  186. // calculate color difference according to the paper "Measuring perceived color difference
  187. // using YIQ NTSC transmission color space in mobile applications" by Y. Kotsarenko and F. Ramos
  188.  
  189. function colorDelta(img1, img2, k, m, yOnly) {
  190. let r1 = img1[k + 0];
  191. let g1 = img1[k + 1];
  192. let b1 = img1[k + 2];
  193. let a1 = img1[k + 3];
  194.  
  195. let r2 = img2[m + 0];
  196. let g2 = img2[m + 1];
  197. let b2 = img2[m + 2];
  198. let a2 = img2[m + 3];
  199.  
  200. if (a1 === a2 && r1 === r2 && g1 === g2 && b1 === b2) return 0;
  201.  
  202. if (a1 < 255) {
  203. a1 /= 255;
  204. r1 = blend(r1, a1);
  205. g1 = blend(g1, a1);
  206. b1 = blend(b1, a1);
  207. }
  208.  
  209. if (a2 < 255) {
  210. a2 /= 255;
  211. r2 = blend(r2, a2);
  212. g2 = blend(g2, a2);
  213. b2 = blend(b2, a2);
  214. }
  215.  
  216. const y1 = rgb2y(r1, g1, b1);
  217. const y2 = rgb2y(r2, g2, b2);
  218. const y = y1 - y2;
  219.  
  220. if (yOnly) return y; // brightness difference only
  221.  
  222. const i = rgb2i(r1, g1, b1) - rgb2i(r2, g2, b2);
  223. const q = rgb2q(r1, g1, b1) - rgb2q(r2, g2, b2);
  224.  
  225. const delta = 0.5053 * y * y + 0.299 * i * i + 0.1957 * q * q;
  226.  
  227. // encode whether the pixel lightens or darkens in the sign
  228. return y1 > y2 ? -delta : delta;
  229. }
  230.  
  231. function rgb2y(r, g, b) { return r * 0.29889531 + g * 0.58662247 + b * 0.11448223; }
  232. function rgb2i(r, g, b) { return r * 0.59597799 - g * 0.27417610 - b * 0.32180189; }
  233. function rgb2q(r, g, b) { return r * 0.21147017 - g * 0.52261711 + b * 0.31114694; }
  234.  
  235. // blend semi-transparent color with white
  236. function blend(c, a) {
  237. return 255 + (c - 255) * a;
  238. }
  239.  
  240. function drawPixel(output, pos, r, g, b) {
  241. output[pos + 0] = r;
  242. output[pos + 1] = g;
  243. output[pos + 2] = b;
  244. output[pos + 3] = 255;
  245. }
  246.  
  247. function drawGrayPixel(img, i, alpha, output) {
  248. const r = img[i + 0];
  249. const g = img[i + 1];
  250. const b = img[i + 2];
  251. const val = blend(rgb2y(r, g, b), alpha * img[i + 3] / 255);
  252. drawPixel(output, i, val, val, val);
  253. }
  254.  
  255.  
  256. /***/ }),
  257.  
  258. /***/ 138:
  259. /***/ ((module, __unused_webpack_exports, __webpack_require__) => {
  260.  
  261. const pixelmatch = __webpack_require__(148);
  262. module.exports = pixelmatch;
  263.  
  264.  
  265. /***/ })
  266.  
  267. /******/ });
  268. /************************************************************************/
  269. /******/ // The module cache
  270. /******/ var __webpack_module_cache__ = {};
  271. /******/
  272. /******/ // The require function
  273. /******/ function __webpack_require__(moduleId) {
  274. /******/ // Check if module is in cache
  275. /******/ var cachedModule = __webpack_module_cache__[moduleId];
  276. /******/ if (cachedModule !== undefined) {
  277. /******/ return cachedModule.exports;
  278. /******/ }
  279. /******/ // Create a new module (and put it into the cache)
  280. /******/ var module = __webpack_module_cache__[moduleId] = {
  281. /******/ // no module.id needed
  282. /******/ // no module.loaded needed
  283. /******/ exports: {}
  284. /******/ };
  285. /******/
  286. /******/ // Execute the module function
  287. /******/ __webpack_modules__[moduleId](module, module.exports, __webpack_require__);
  288. /******/
  289. /******/ // Return the exports of the module
  290. /******/ return module.exports;
  291. /******/ }
  292. /******/
  293. /************************************************************************/
  294. /******/
  295. /******/ // startup
  296. /******/ // Load entry module and return exports
  297. /******/ // This entry module is referenced by other modules so it can't be inlined
  298. /******/ var __webpack_exports__ = __webpack_require__(138);
  299. /******/
  300. /******/ return __webpack_exports__;
  301. /******/ })()
  302. ;
  303. });

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址