pixelmatch@5.3.0

https://www.npmjs.com/package/pixelmatch

目前为 2024-06-26 提交的版本。查看 最新版本

此脚本不应直接安装,它是一个供其他脚本使用的外部库。如果您需要使用该库,请在脚本元属性加入:// @require https://update.gf.qytechs.cn/scripts/498926/1400611/pixelmatch%40530.js

  1. window.pixelmatch = (() => {
  2. var __getOwnPropNames = Object.getOwnPropertyNames;
  3. var __commonJS = (cb, mod) => function __require() {
  4. return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
  5. };
  6.  
  7. // entry.js
  8. var require_entry = __commonJS({
  9. "entry.js"(exports, module) {
  10. module.exports = pixelmatch;
  11. var defaultOptions = {
  12. threshold: 0.1,
  13. // matching threshold (0 to 1); smaller is more sensitive
  14. includeAA: false,
  15. // whether to skip anti-aliasing detection
  16. alpha: 0.1,
  17. // opacity of original image in diff output
  18. aaColor: [255, 255, 0],
  19. // color of anti-aliased pixels in diff output
  20. diffColor: [255, 0, 0],
  21. // color of different pixels in diff output
  22. diffColorAlt: null,
  23. // whether to detect dark on light differences between img1 and img2 and set an alternative color to differentiate between the two
  24. diffMask: false
  25. // draw the diff over a transparent background (a mask)
  26. };
  27. function pixelmatch(img1, img2, output, width, height, options) {
  28. if (!isPixelData(img1) || !isPixelData(img2) || output && !isPixelData(output))
  29. throw new Error("Image data: Uint8Array, Uint8ClampedArray or Buffer expected.");
  30. if (img1.length !== img2.length || output && output.length !== img1.length)
  31. throw new Error("Image sizes do not match.");
  32. if (img1.length !== width * height * 4) throw new Error("Image data size does not match width/height.");
  33. options = Object.assign({}, defaultOptions, options);
  34. const len = width * height;
  35. const a32 = new Uint32Array(img1.buffer, img1.byteOffset, len);
  36. const b32 = new Uint32Array(img2.buffer, img2.byteOffset, len);
  37. let identical = true;
  38. for (let i = 0; i < len; i++) {
  39. if (a32[i] !== b32[i]) {
  40. identical = false;
  41. break;
  42. }
  43. }
  44. if (identical) {
  45. if (output && !options.diffMask) {
  46. for (let i = 0; i < len; i++) drawGrayPixel(img1, 4 * i, options.alpha, output);
  47. }
  48. return 0;
  49. }
  50. const maxDelta = 35215 * options.threshold * options.threshold;
  51. let diff = 0;
  52. for (let y = 0; y < height; y++) {
  53. for (let x = 0; x < width; x++) {
  54. const pos = (y * width + x) * 4;
  55. const delta = colorDelta(img1, img2, pos, pos);
  56. if (Math.abs(delta) > maxDelta) {
  57. if (!options.includeAA && (antialiased(img1, x, y, width, height, img2) || antialiased(img2, x, y, width, height, img1))) {
  58. if (output && !options.diffMask) drawPixel(output, pos, ...options.aaColor);
  59. } else {
  60. if (output) {
  61. drawPixel(output, pos, ...delta < 0 && options.diffColorAlt || options.diffColor);
  62. }
  63. diff++;
  64. }
  65. } else if (output) {
  66. if (!options.diffMask) drawGrayPixel(img1, pos, options.alpha, output);
  67. }
  68. }
  69. }
  70. return diff;
  71. }
  72. function isPixelData(arr) {
  73. return ArrayBuffer.isView(arr) && arr.constructor.BYTES_PER_ELEMENT === 1;
  74. }
  75. function antialiased(img, x1, y1, width, height, img2) {
  76. const x0 = Math.max(x1 - 1, 0);
  77. const y0 = Math.max(y1 - 1, 0);
  78. const x2 = Math.min(x1 + 1, width - 1);
  79. const y2 = Math.min(y1 + 1, height - 1);
  80. const pos = (y1 * width + x1) * 4;
  81. let zeroes = x1 === x0 || x1 === x2 || y1 === y0 || y1 === y2 ? 1 : 0;
  82. let min = 0;
  83. let max = 0;
  84. let minX, minY, maxX, maxY;
  85. for (let x = x0; x <= x2; x++) {
  86. for (let y = y0; y <= y2; y++) {
  87. if (x === x1 && y === y1) continue;
  88. const delta = colorDelta(img, img, pos, (y * width + x) * 4, true);
  89. if (delta === 0) {
  90. zeroes++;
  91. if (zeroes > 2) return false;
  92. } else if (delta < min) {
  93. min = delta;
  94. minX = x;
  95. minY = y;
  96. } else if (delta > max) {
  97. max = delta;
  98. maxX = x;
  99. maxY = y;
  100. }
  101. }
  102. }
  103. if (min === 0 || max === 0) return false;
  104. return hasManySiblings(img, minX, minY, width, height) && hasManySiblings(img2, minX, minY, width, height) || hasManySiblings(img, maxX, maxY, width, height) && hasManySiblings(img2, maxX, maxY, width, height);
  105. }
  106. function hasManySiblings(img, x1, y1, width, height) {
  107. const x0 = Math.max(x1 - 1, 0);
  108. const y0 = Math.max(y1 - 1, 0);
  109. const x2 = Math.min(x1 + 1, width - 1);
  110. const y2 = Math.min(y1 + 1, height - 1);
  111. const pos = (y1 * width + x1) * 4;
  112. let zeroes = x1 === x0 || x1 === x2 || y1 === y0 || y1 === y2 ? 1 : 0;
  113. for (let x = x0; x <= x2; x++) {
  114. for (let y = y0; y <= y2; y++) {
  115. if (x === x1 && y === y1) continue;
  116. const pos2 = (y * width + x) * 4;
  117. if (img[pos] === img[pos2] && img[pos + 1] === img[pos2 + 1] && img[pos + 2] === img[pos2 + 2] && img[pos + 3] === img[pos2 + 3]) zeroes++;
  118. if (zeroes > 2) return true;
  119. }
  120. }
  121. return false;
  122. }
  123. function colorDelta(img1, img2, k, m, yOnly) {
  124. let r1 = img1[k + 0];
  125. let g1 = img1[k + 1];
  126. let b1 = img1[k + 2];
  127. let a1 = img1[k + 3];
  128. let r2 = img2[m + 0];
  129. let g2 = img2[m + 1];
  130. let b2 = img2[m + 2];
  131. let a2 = img2[m + 3];
  132. if (a1 === a2 && r1 === r2 && g1 === g2 && b1 === b2) return 0;
  133. if (a1 < 255) {
  134. a1 /= 255;
  135. r1 = blend(r1, a1);
  136. g1 = blend(g1, a1);
  137. b1 = blend(b1, a1);
  138. }
  139. if (a2 < 255) {
  140. a2 /= 255;
  141. r2 = blend(r2, a2);
  142. g2 = blend(g2, a2);
  143. b2 = blend(b2, a2);
  144. }
  145. const y1 = rgb2y(r1, g1, b1);
  146. const y2 = rgb2y(r2, g2, b2);
  147. const y = y1 - y2;
  148. if (yOnly) return y;
  149. const i = rgb2i(r1, g1, b1) - rgb2i(r2, g2, b2);
  150. const q = rgb2q(r1, g1, b1) - rgb2q(r2, g2, b2);
  151. const delta = 0.5053 * y * y + 0.299 * i * i + 0.1957 * q * q;
  152. return y1 > y2 ? -delta : delta;
  153. }
  154. function rgb2y(r, g, b) {
  155. return r * 0.29889531 + g * 0.58662247 + b * 0.11448223;
  156. }
  157. function rgb2i(r, g, b) {
  158. return r * 0.59597799 - g * 0.2741761 - b * 0.32180189;
  159. }
  160. function rgb2q(r, g, b) {
  161. return r * 0.21147017 - g * 0.52261711 + b * 0.31114694;
  162. }
  163. function blend(c, a) {
  164. return 255 + (c - 255) * a;
  165. }
  166. function drawPixel(output, pos, r, g, b) {
  167. output[pos + 0] = r;
  168. output[pos + 1] = g;
  169. output[pos + 2] = b;
  170. output[pos + 3] = 255;
  171. }
  172. function drawGrayPixel(img, i, alpha, output) {
  173. const r = img[i + 0];
  174. const g = img[i + 1];
  175. const b = img[i + 2];
  176. const val = blend(rgb2y(r, g, b), alpha * img[i + 3] / 255);
  177. drawPixel(output, i, val, val, val);
  178. }
  179. }
  180. });
  181. return require_entry();
  182. })();

QingJ © 2025

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