-
-
Notifications
You must be signed in to change notification settings - Fork 14
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Initial work on renderer tests and integration tests.
- Loading branch information
Showing
22 changed files
with
309 additions
and
8 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,3 @@ | ||
#!/bin/sh | ||
export CLOSURE_LATEST="https://repo1.maven.org/maven2/com/google/javascript/closure-compiler/v20231112/closure-compiler-v20231112.jar" #"http://dl.google.com/closure-compiler/compiler-latest.tar.gz" | ||
export NPM_PACKAGES="source-map@latest prettier@latest pretty-quick@latest eslint@latest eslint-config-prettier@latest lint-staged@latest jest@latest jsdom@latest jest-environment-jsdom@latest jsdoc-to-markdown@latest http-server@latest" | ||
export NPM_PACKAGE_JSON='{"devDependencies":{"eslint":"latest","eslint-config-prettier":"latest","http-server":"latest","jest":"latest","jest-environment-jsdom":"latest","jsdoc-to-markdown":"latest","libass-wasm":"latest","lint-staged":"latest","mime":"latest","prettier":"latest","pretty-quick":"latest","source-map":"latest","ssim.js":"latest","node-canvas-webgl":"latest"},"overrides":{"gl@<8.0.2":"8.0.2"}}' |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,154 @@ | ||
{ | ||
const { mockDOM } = require('node-canvas-webgl'); | ||
mockDOM(window); | ||
} | ||
global = globalThis; | ||
require('../util.js') | ||
require('../global-constants.js') | ||
require('../color.js'); | ||
require('../style.js'); | ||
require('../lib/codepage.js'); | ||
require('../text-server.js'); | ||
require('../style-override.js'); | ||
require('../subtitle-event.js'); | ||
require("../subtitle-tags.js"); | ||
require("../subtitle-parser.js"); | ||
require("../scheduler.js"); | ||
require("../shader.js"); | ||
require("../font-server.js"); | ||
require("../canvas-2d-text-renderer.js"); | ||
require("../canvas-2d-shape-renderer.js"); | ||
require("../lib/BSpline.js"); | ||
require("../lib/earcut.js"); | ||
require("../renderer-main.js"); | ||
|
||
sabre.getScriptPath = function(){ | ||
return __dirname+"/../"; | ||
}; | ||
|
||
const opentype = require("./test-modules/opentype.compat.min.js"); | ||
|
||
const loadFile = (function(){ | ||
const { readFileSync } = require('fs'); | ||
return function(file){ | ||
return readFileSync(__dirname+"/testfiles/" + file,null); | ||
} | ||
})(); | ||
|
||
const loadFileAsDataURI = (function(file,mime){ | ||
const data = loadFile(file); | ||
return "data:"+mime+";base64,"+data.toString('base64'); | ||
}); | ||
|
||
const compareImages = (function(){ | ||
const compare = require("./test-utils/image-comparison.utils.js"); | ||
return (function(){ | ||
function canvasToImageData(inputCanvas){ | ||
const wantedColorSpace = (window.matchMedia && window.matchMedia("(color-gamut: p3)").matches ? "display-p3" : "srgb"); | ||
if(inputCanvas.width > 0 && inputCanvas.height > 0){ | ||
ctx = inputCanvas.getContext("2d"); | ||
const imageData = ctx.getImageData(0,0,inputCanvas.width,inputCanvas.height,{colorSpace:wantedColorSpace}); | ||
return imageData; | ||
}else{ | ||
throw new Error("Canvas too small to compare."); | ||
} | ||
} | ||
return function(canvas1,canvas2){ | ||
const imageData1 = canvasToImageData(canvas1); | ||
const imageData2 = canvasToImageData(canvas2); | ||
return compare(imageData1,imageData2); | ||
} | ||
})(); | ||
})(); | ||
|
||
describe("Subtitle Renderer", () => { | ||
|
||
describe("Canvas2DTextRenderer", () => { | ||
|
||
}); | ||
|
||
describe("Canvas2DShapeRenderer", () => { | ||
|
||
}); | ||
|
||
describe("Integration Tests", () => { | ||
|
||
const SubtitlesOctopus = require("libass-wasm"); | ||
|
||
const octopus_options_template = Object.freeze({ | ||
workerUrl: require.resolve('libass-wasm/dist/js/subtitles-octopus-worker.js'), | ||
legacyWorkerUrl: require.resolve('libass-wasm/dist/js/subtitles-octopus-worker-legacy.js'), | ||
}); | ||
|
||
let canvas; | ||
let octopus_canvas; | ||
|
||
const fontsList = [ | ||
"fonts/OpenSans-Light.ttf", | ||
"fonts/OpenSans-Regular.ttf", | ||
"fonts/OpenSans-Medium.ttf", | ||
"fonts/OpenSans-SemiBold.ttf", | ||
"fonts/OpenSans-Bold.ttf", | ||
"fonts/OpenSans-ExtraBold.ttf", | ||
"fonts/OpenSans-LightItalic.ttf", | ||
"fonts/OpenSans-Italic.ttf", | ||
"fonts/OpenSans-MediumItalic.ttf", | ||
"fonts/OpenSans-SemiBoldItalic.ttf", | ||
"fonts/OpenSans-BoldItalic.ttf", | ||
"fonts/OpenSans-ExtraBoldItalic.ttf", | ||
"fonts/Rosario-Regular.otf" | ||
]; | ||
const fontUrls = fontsList.map(font => loadFileAsDataURI(font,(font.endsWith(".otf") ? "font/otf" : "font/ttf"))); | ||
const fonts = fontsList.map(font => opentype.parse(loadFile(font))); | ||
|
||
beforeEach(() => { | ||
canvas = document.createElement('canvas'); | ||
canvas.width = 640; | ||
canvas.height = 480; | ||
|
||
octopus_canvas = document.createElement('canvas'); | ||
octopus_canvas.width = 640; | ||
octopus_canvas.height = 480; | ||
}); | ||
|
||
describe("Basic Tests", () => { | ||
test("Can we initialize the renderer?", () => { | ||
const renderer = external.SABRERenderer({ | ||
fonts: fonts, | ||
subtitles: loadFile("tag_tests.ass"), | ||
colorSpace:external.VideoColorSpaces.AUTOMATIC, | ||
resolution:[640,480], | ||
nativeResolution:[640,480] | ||
}); | ||
expect(renderer.checkReadyToRender()).toBe(true); | ||
}); | ||
}); | ||
/* | ||
describe("Comparison Tests", () => { | ||
let testBuffer; | ||
let testUri; | ||
let sabre, octopus; | ||
beforeEach(() => { | ||
const octopus_options = Object.freeze(Object.assign({ | ||
subUrl: testUri | ||
},octopus_options_template)); | ||
octopus = new SubtitlesOctopus(octopus_options); | ||
}); | ||
afterEach(() => { | ||
octopus.dispose(); | ||
}); | ||
describe("Tag Tests", () => { | ||
beforeAll(() => { | ||
testBuffer = loadFile("./testfiles/tag_tests.ass"); | ||
testUri = loadFile("./testfiles/tag_tests.ass"); | ||
}); | ||
}); | ||
}); | ||
*/ | ||
}); | ||
}); |
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,129 @@ | ||
const ssim = require('ssim.js'); | ||
|
||
function multiplyMatrixByVector(matrix, vector) { | ||
let result = [0, 0, 0]; | ||
for (let i = 0; i < 3; i++) { | ||
for (let j = 0; j < 3; j++) { | ||
result[i] += matrix[i * 3 + j] * vector[j]; | ||
} | ||
} | ||
return result; | ||
} | ||
|
||
function sRGBtoRGB(sR,sG,sB){ | ||
const color = [sR,sG,sB]; | ||
for(let i = 0; i < 3; i++){ | ||
if(color[i] <= 0.04045){ | ||
color[i] /= 12.92; | ||
}else{ | ||
color[i] = Math.pow((color[i]+0.055)/1.055,2.4); | ||
} | ||
} | ||
return color; | ||
} | ||
|
||
const DP3toLinearDP3 = sRGBtoRGB; | ||
|
||
function sRGBtoXYZ(sR,sG,sB){ | ||
const RGBtoXYZMatrix = [0.4360413,0.3851129,0.1430458,0.2224845,0.7169051,0.0606104,0.0139202,0.0970672,0.7139126]; | ||
const RGB = sRGBtoRGB(sR,sG,sB); | ||
return multiplyMatrixByVector(RGBtoXYZMatrix,RGB); | ||
} | ||
|
||
function DP3toXYZ(wR,wG,wB){ | ||
const LinearDP3toXYZMatrix = [0.5151187,0.2919778,0.1571035,0.2411892,0.6922441,0.0665668,-0.0010505,0.0418791,0.7840713]; | ||
const LinearDP3 = DP3toLinearDP3(wR,wG,wB) | ||
return multiplyMatrixByVector(LinearDP3toXYZMatrix,LinearDP3) | ||
} | ||
|
||
function imageDataToXYZ(d){ | ||
const data = d.data; | ||
const colorSpace = d.colorSpace || "srgb"; | ||
const length = d.width*d.height*3; | ||
const output = new Array(length); | ||
let j = 0; | ||
for(let i = 0; i < d.width*d.height*4; i+=4){ | ||
let XYZ; | ||
switch(colorSpace){ | ||
default: | ||
console.warn("Unrecognized color space '"+colorSpace+"' assuming srgb, colors may be wrong."); | ||
case "srgb": | ||
XYZ = sRGBtoXYZ(data[i]/255,data[i+1]/255,data[i+2]/255); | ||
break; | ||
case "display-p3": | ||
XYZ = DP3toXYZ(data[i]/255,data[i+1]/255,data[i+2]/255); | ||
break; | ||
} | ||
output[j] = XYZ[0]; | ||
output[j+1] = XYZ[1]; | ||
output[j+2] = XYZ[2]; | ||
j+=3; | ||
} | ||
return output; | ||
} | ||
|
||
function diffArray(a,b){ | ||
const maxLength = Math.min(a.length, b.length); | ||
const output = new Array(maxLength); | ||
for(let i = 0; i < maxLength; i++){ | ||
output[i] = (a[i]??0)-(b[i]??0); | ||
} | ||
return output; | ||
} | ||
|
||
function selectArrayFromArray(a,n,x){ | ||
const offset = typeof(x) === "number" ? x : 0; | ||
const length = Math.trunc(a.length/n); | ||
const output = new Array(length); | ||
for(let i = 0; i < length; i++){ | ||
output[i] = a[(i*n)+offset]; | ||
} | ||
return output; | ||
} | ||
|
||
function psnr(image1,image2) { | ||
const image1xyz = imageDataToXYZ(image1); | ||
const image2xyz = imageDataToXYZ(image2); | ||
|
||
let mse; | ||
{ | ||
const xyzDiffSquared = diffArray(image1xyz,image2xyz).map((value) => Math.pow(value,2)); | ||
const mseComponentLength = Math.trunc(xyzDiffSquared.length/3); | ||
// Calculate the mean squared error for each channel | ||
const mseX = selectArrayFromArray(xyzDiffSquared,3).reduce((sum,value) => sum+value,0)/mseComponentLength; | ||
const mseY = selectArrayFromArray(xyzDiffSquared,3,1).reduce((sum,value) => sum+value,0)/mseComponentLength; | ||
const mseZ = selectArrayFromArray(xyzDiffSquared,3,2).reduce((sum,value) => sum+value,0)/mseComponentLength; | ||
// Calculate the mean squared error across all channels | ||
mse = (mseX + mseY + mseZ) / 3; | ||
} | ||
|
||
// Maximum possible pixel value (we are using floating point values) | ||
const maxPixelValue = 1.0; | ||
|
||
// Return PSNR value. | ||
return 20 * Math.log10(maxPixelValue / Math.sqrt(mse)); | ||
} | ||
|
||
function xyzssim (image1, image2) { | ||
const image1xyz = imageDataToXYZ(image1); | ||
const image2xyz = imageDataToXYZ(image2); | ||
const image1_x_channel = selectArrayFromArray(image1xyz,3); | ||
const image1_y_channel = selectArrayFromArray(image1xyz,3,1); | ||
const image1_z_channel = selectArrayFromArray(image1xyz,3,2); | ||
const image2_x_channel = selectArrayFromArray(image2xyz,3); | ||
const image2_y_channel = selectArrayFromArray(image2xyz,3,1); | ||
const image2_z_channel = selectArrayFromArray(image2xyz,3,2); | ||
const ssim_x = ssim.ssim({width:image1.width,height:image1.height,data:image1_x_channel}, {width:image2.width,height:image2.height,data:image2_x_channel}).mssim; | ||
const ssim_y = ssim.ssim({width:image1.width,height:image1.height,data:image1_y_channel}, {width:image2.width,height:image2.height,data:image2_y_channel}).mssim; | ||
const ssim_z = ssim.ssim({width:image1.width,height:image1.height,data:image1_z_channel}, {width:image2.width,height:image2.height,data:image2_z_channel}).mssim; | ||
return (ssim_x + ssim_y + ssim_z) / 3; | ||
} | ||
|
||
function compare(a,b){ | ||
if(a && b){ | ||
return {psnr: psnr(a,b), ssim: xyzssim(a,b)}; | ||
} | ||
throw new Error("No images to compare."); | ||
} | ||
|
||
module.exports = compare; |
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters