parent
7e70d91582
commit
0eba96af08
@ -10,6 +10,7 @@ var Debug = {
|
|||||||
keyboard: true,
|
keyboard: true,
|
||||||
debugResizer: true,
|
debugResizer: true,
|
||||||
debugArDetect: true,
|
debugArDetect: true,
|
||||||
|
scaler: true,
|
||||||
// debugStorage: false,
|
// debugStorage: false,
|
||||||
// debugStorage: true,
|
// debugStorage: true,
|
||||||
// comms: false,
|
// comms: false,
|
||||||
|
@ -45,7 +45,7 @@ var ExtensionConf = {
|
|||||||
|
|
||||||
// samplingInterval: 10, // we sample at columns at (width/this) * [ 1 .. this - 1]
|
// samplingInterval: 10, // we sample at columns at (width/this) * [ 1 .. this - 1]
|
||||||
blackframe: {
|
blackframe: {
|
||||||
sufficientColorVariance: 0.09, // calculate difference between average intensity and pixel, for every pixel for every color
|
sufficientColorVariance: 0.10, // calculate difference between average intensity and pixel, for every pixel for every color
|
||||||
// component. Average intensity is normalized to where 0 is black and 1 is biggest value for
|
// component. Average intensity is normalized to where 0 is black and 1 is biggest value for
|
||||||
// that component. If sum of differences between normalized average intensity and normalized
|
// that component. If sum of differences between normalized average intensity and normalized
|
||||||
// component varies more than this % between color components, we can afford to use less strict
|
// component varies more than this % between color components, we can afford to use less strict
|
||||||
|
@ -284,9 +284,6 @@ class ArDetector {
|
|||||||
// set initial timestamps so frame check will trigger the first time we run the loop
|
// set initial timestamps so frame check will trigger the first time we run the loop
|
||||||
let lastFrameCheckStartTime = Date.now() - (this.settings.active.arDetect.timers.playing << 1);
|
let lastFrameCheckStartTime = Date.now() - (this.settings.active.arDetect.timers.playing << 1);
|
||||||
|
|
||||||
//
|
|
||||||
console.log("MAIN: BLACKFRAME CONTEXT:", this.blackframeContext)
|
|
||||||
|
|
||||||
const frameCheckTimes = new Array(10).fill(-1);
|
const frameCheckTimes = new Array(10).fill(-1);
|
||||||
let frameCheckBufferIndex = 0;
|
let frameCheckBufferIndex = 0;
|
||||||
let fcstart, fctime;
|
let fcstart, fctime;
|
||||||
@ -302,7 +299,13 @@ class ArDetector {
|
|||||||
lastFrameCheckStartTime = Date.now();
|
lastFrameCheckStartTime = Date.now();
|
||||||
fcstart = performance.now();
|
fcstart = performance.now();
|
||||||
|
|
||||||
this.frameCheck();
|
try {
|
||||||
|
this.frameCheck();
|
||||||
|
} catch (e) {
|
||||||
|
if (Debug.debug) {
|
||||||
|
console.log("%c[ArDetector::main] Frame check failed:", "color: #000, background: #f00", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (Debug.performanceMetrics) {
|
if (Debug.performanceMetrics) {
|
||||||
fctime = performance.now() - fcstart;
|
fctime = performance.now() - fcstart;
|
||||||
@ -428,14 +431,37 @@ class ArDetector {
|
|||||||
if(edges.top === undefined){
|
if(edges.top === undefined){
|
||||||
edges.top = 0;
|
edges.top = 0;
|
||||||
edges.bottom = 0;
|
edges.bottom = 0;
|
||||||
edge.left = 0;
|
edges.left = 0; // RESERVED FOR FUTURE — CURRENTLY UNUSED
|
||||||
edges.right = 0;
|
edges.right = 0; // THIS FUNCTION CAN PRESENTLY ONLY HANDLE LETTERBOX
|
||||||
}
|
}
|
||||||
|
|
||||||
let zoomFactor = 1;
|
const letterbox = edges.top + edges.bottom;
|
||||||
var letterbox = edges.top + edges.bottom;
|
|
||||||
|
|
||||||
|
if (! this.fallbackMode) {
|
||||||
|
// Since video is stretched to fit the canvas, we need to take that into account when calculating target
|
||||||
|
// aspect ratio and correct our calculations to account for that
|
||||||
|
|
||||||
|
const fileAr = this.video.videoWidth / this.video.videoHeight;
|
||||||
|
const canvasAr = this.canvas.width / this.canvas.height;
|
||||||
|
let widthCorrected;
|
||||||
|
|
||||||
|
if (edges.top && edges.bottom) {
|
||||||
|
// in case of letterbox, we take canvas height as canon and assume width got stretched or squished
|
||||||
|
|
||||||
|
if (fileAr != canvasAr) {
|
||||||
|
widthCorrected = this.canvas.height * fileAr;
|
||||||
|
} else {
|
||||||
|
widthCorrected = this.canvas.width;
|
||||||
|
}
|
||||||
|
|
||||||
|
return widthCorrected / (this.canvas.height - letterbox);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// fallback mode behaves a wee bit differently
|
||||||
|
|
||||||
|
let zoomFactor = 1;
|
||||||
|
|
||||||
if (this.fallbackMode) {
|
|
||||||
// there's stuff missing from the canvas. We need to assume canvas' actual height is bigger by a factor x, where
|
// there's stuff missing from the canvas. We need to assume canvas' actual height is bigger by a factor x, where
|
||||||
// x = [video.zoomedHeight] / [video.unzoomedHeight]
|
// x = [video.zoomedHeight] / [video.unzoomedHeight]
|
||||||
//
|
//
|
||||||
@ -446,11 +472,9 @@ class ArDetector {
|
|||||||
|
|
||||||
zoomFactor = vbr.height / this.video.clientHeight;
|
zoomFactor = vbr.height / this.video.clientHeight;
|
||||||
letterbox += vbr.height - this.video.clientHeight;
|
letterbox += vbr.height - this.video.clientHeight;
|
||||||
}
|
|
||||||
|
|
||||||
var trueHeight = this.canvas.height * zoomFactor - letterbox;
|
var trueHeight = this.canvas.height * zoomFactor - letterbox;
|
||||||
|
|
||||||
if(this.fallbackMode){
|
|
||||||
if(edges.top > 1 && edges.top <= this.settings.active.arDetect.fallbackMode.noTriggerZonePx ){
|
if(edges.top > 1 && edges.top <= this.settings.active.arDetect.fallbackMode.noTriggerZonePx ){
|
||||||
if(Debug.debug && Debug.debugArDetect) {
|
if(Debug.debug && Debug.debugArDetect) {
|
||||||
console.log("Edge is in the no-trigger zone. Aspect ratio change is not triggered.")
|
console.log("Edge is in the no-trigger zone. Aspect ratio change is not triggered.")
|
||||||
@ -463,10 +487,9 @@ class ArDetector {
|
|||||||
// safety border so we can detect aspect ratio narrowing (21:9 -> 16:9).
|
// safety border so we can detect aspect ratio narrowing (21:9 -> 16:9).
|
||||||
// x2 because safetyBorderPx is for one side.
|
// x2 because safetyBorderPx is for one side.
|
||||||
trueHeight += (this.settings.active.arDetect.fallbackMode.safetyBorderPx << 1);
|
trueHeight += (this.settings.active.arDetect.fallbackMode.safetyBorderPx << 1);
|
||||||
|
|
||||||
|
return this.canvas.width * zoomFactor / trueHeight;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
return this.canvas.width * zoomFactor / trueHeight;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
processAr(trueAr){
|
processAr(trueAr){
|
||||||
@ -476,7 +499,7 @@ class ArDetector {
|
|||||||
// poglejmo, če se je razmerje stranic spremenilo
|
// poglejmo, če se je razmerje stranic spremenilo
|
||||||
// check if aspect ratio is changed:
|
// check if aspect ratio is changed:
|
||||||
var lastAr = this.conf.resizer.getLastAr();
|
var lastAr = this.conf.resizer.getLastAr();
|
||||||
if( lastAr.type === AspectRatio.Automatic && lastAr.ratio !== null){
|
if (lastAr.type === AspectRatio.Automatic && lastAr.ratio !== null){
|
||||||
// spremembo lahko zavrnemo samo, če uporabljamo avtomatski način delovanja in če smo razmerje stranic
|
// spremembo lahko zavrnemo samo, če uporabljamo avtomatski način delovanja in če smo razmerje stranic
|
||||||
// že nastavili.
|
// že nastavili.
|
||||||
//
|
//
|
||||||
|
@ -30,25 +30,33 @@ class EdgeDetect{
|
|||||||
findBars(image, sampleCols, direction = EdgeDetectPrimaryDirection.VERTICAL, quality = EdgeDetectQuality.IMPROVED, guardLineOut, blackFrameAnalysis){
|
findBars(image, sampleCols, direction = EdgeDetectPrimaryDirection.VERTICAL, quality = EdgeDetectQuality.IMPROVED, guardLineOut, blackFrameAnalysis){
|
||||||
let fastCandidates, edgeCandidates, bars;
|
let fastCandidates, edgeCandidates, bars;
|
||||||
if (direction == EdgeDetectPrimaryDirection.VERTICAL) {
|
if (direction == EdgeDetectPrimaryDirection.VERTICAL) {
|
||||||
fastCandidates = this.findCandidates(image, sampleCols, guardLineOut);
|
try {
|
||||||
|
fastCandidates = this.findCandidates(image, sampleCols, guardLineOut);
|
||||||
if (! this.isValidSample(fastCandidates)) {
|
|
||||||
return {status: EdgeStatus.AR_UNKNOWN};
|
if (! this.isValidSample(fastCandidates)) {
|
||||||
}
|
return {status: EdgeStatus.AR_UNKNOWN};
|
||||||
// if(quality == EdgeDetectQuality.FAST){
|
}
|
||||||
// edges = fastCandidates; // todo: processing
|
// if(quality == EdgeDetectQuality.FAST){
|
||||||
// } else {
|
// edges = fastCandidates; // todo: processing
|
||||||
edgeCandidates = this.edgeDetect(image, fastCandidates);
|
// } else {
|
||||||
console.log("edge candidates:", edgeCandidates)
|
edgeCandidates = this.edgeDetect(image, fastCandidates);
|
||||||
bars = this.edgePostprocess(edgeCandidates, this.conf.canvas.height);
|
console.log("edge candidates:", edgeCandidates)
|
||||||
console.log("bars:", bars)
|
bars = this.edgePostprocess(edgeCandidates, this.conf.canvas.height);
|
||||||
|
console.log("bars:", bars)
|
||||||
|
|
||||||
// }
|
// }
|
||||||
|
} catch (e) {
|
||||||
|
if (Debug.debug) {
|
||||||
|
console.log("%c[EdgeDetect::findBars] find bars failed.", "background: #f00, color: #000", e);
|
||||||
|
}
|
||||||
|
return {status: EdgeStatus.AR_UNKNOWN}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
bars = this.pillarTest(image) ? {status: EdgeStatus.AR_KNOWN} : {status: EdgeStatus.AR_UNKNOWN};
|
bars = this.pillarTest(image) ? {status: EdgeStatus.AR_KNOWN} : {status: EdgeStatus.AR_UNKNOWN};
|
||||||
}
|
}
|
||||||
|
|
||||||
return bars;
|
return bars;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
findCandidates(image, sampleCols, guardLineOut){
|
findCandidates(image, sampleCols, guardLineOut){
|
||||||
|
@ -13,13 +13,15 @@ class Scaler {
|
|||||||
this.conf = videoData;
|
this.conf = videoData;
|
||||||
}
|
}
|
||||||
|
|
||||||
modeToAr(ar){
|
|
||||||
|
// Skrbi za "stare" možnosti, kot na primer "na širino zaslona", "na višino zaslona" in "ponastavi".
|
||||||
|
// Približevanje opuščeno.
|
||||||
|
// handles "legacy" options, such as 'fit to widht', 'fit to height' and AspectRatio.Reset. No zoom tho
|
||||||
|
modeToAr (ar) {
|
||||||
if (ar.ratio) {
|
if (ar.ratio) {
|
||||||
return ar.ratio;
|
return ar.ratio;
|
||||||
}
|
}
|
||||||
// Skrbi za "stare" možnosti, kot na primer "na širino zaslona", "na višino zaslona" in "ponastavi".
|
|
||||||
// Približevanje opuščeno.
|
|
||||||
// handles "legacy" options, such as 'fit to widht', 'fit to height' and AspectRatio.Reset. No zoom tho
|
|
||||||
var ratioOut;
|
var ratioOut;
|
||||||
|
|
||||||
if (!this.conf.video) {
|
if (!this.conf.video) {
|
||||||
@ -69,8 +71,9 @@ class Scaler {
|
|||||||
|
|
||||||
calculateCrop(ar) {
|
calculateCrop(ar) {
|
||||||
if(!this.conf.video || this.conf.video.videoWidth == 0 || this.conf.video.videoHeight == 0){
|
if(!this.conf.video || this.conf.video.videoWidth == 0 || this.conf.video.videoHeight == 0){
|
||||||
if(Debug.debug)
|
if (Debug.debug) {
|
||||||
console.log("[Scaler::calculateCrop] ERROR — no video detected.");
|
console.log("[Scaler::calculateCrop] ERROR — no video detected.");
|
||||||
|
}
|
||||||
|
|
||||||
this.conf.destroy();
|
this.conf.destroy();
|
||||||
return {error: "no_video"};
|
return {error: "no_video"};
|
||||||
@ -81,18 +84,21 @@ class Scaler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// handle fuckie-wuckies
|
// handle fuckie-wuckies
|
||||||
if (! ar.ratio){
|
if (!ar.ratio){
|
||||||
if(Debug.debug)
|
if (Debug.debug && Debug.scaler) {
|
||||||
console.log("[Scaler::calculateCrop] no ar?", ar.ratio, " -- we were given this mode:", ar);
|
console.log("[Scaler::calculateCrop] no ar?", ar.ratio, " -- we were given this mode:", ar);
|
||||||
|
}
|
||||||
return {error: "no_ar", ratio: ar.ratio};
|
return {error: "no_ar", ratio: ar.ratio};
|
||||||
}
|
}
|
||||||
|
|
||||||
if(Debug.debug)
|
if (Debug.debug && Debug.scaler) {
|
||||||
console.log("[Scaler::calculateCrop] trying to set ar. args are: ar->",ar.ratio,"; this.conf.player.dimensions->",this.conf.player.dimensions.width, "×", this.conf.player.dimensions.height, "| obj:", this.conf.player.dimensions);
|
console.log("[Scaler::calculateCrop] trying to set ar. args are: ar->",ar.ratio,"; this.conf.player.dimensions->",this.conf.player.dimensions.width, "×", this.conf.player.dimensions.height, "| obj:", this.conf.player.dimensions);
|
||||||
|
}
|
||||||
|
|
||||||
if( (! this.conf.player.dimensions) || this.conf.player.dimensions.width === 0 || this.conf.player.dimensions.height === 0 ){
|
if( (! this.conf.player.dimensions) || this.conf.player.dimensions.width === 0 || this.conf.player.dimensions.height === 0 ){
|
||||||
if(Debug.debug)
|
if (Debug.debug && Debug.scaler) {
|
||||||
console.log("[Scaler::calculateCrop] ERROR — no (or invalid) this.conf.player.dimensions:",this.conf.player.dimensions);
|
console.log("[Scaler::calculateCrop] ERROR — no (or invalid) this.conf.player.dimensions:",this.conf.player.dimensions);
|
||||||
|
}
|
||||||
return {error: "this.conf.player.dimensions_error"};
|
return {error: "this.conf.player.dimensions_error"};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -104,12 +110,14 @@ class Scaler {
|
|||||||
var fileAr = this.conf.video.videoWidth / this.conf.video.videoHeight;
|
var fileAr = this.conf.video.videoWidth / this.conf.video.videoHeight;
|
||||||
var playerAr = this.conf.player.dimensions.width / this.conf.player.dimensions.height;
|
var playerAr = this.conf.player.dimensions.width / this.conf.player.dimensions.height;
|
||||||
|
|
||||||
if(ar.type === AspectRatio.Initial || !ar.ratio)
|
if (ar.type === AspectRatio.Initial || !ar.ratio) {
|
||||||
ar.ratio = fileAr;
|
ar.ratio = fileAr;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
if(Debug.debug)
|
if (Debug.debug && Debug.scaler) {
|
||||||
console.log("[Scaler::calculateCrop] ar is " ,ar.ratio, ", file ar is", fileAr, ", this.conf.player.dimensions are ", this.conf.player.dimensions.width, "×", this.conf.player.dimensions.height, "| obj:", this.conf.player.dimensions);
|
console.log("[Scaler::calculateCrop] ar is " ,ar.ratio, ", file ar is", fileAr, ", this.conf.player.dimensions are ", this.conf.player.dimensions.width, "×", this.conf.player.dimensions.height, "| obj:", this.conf.player.dimensions);
|
||||||
|
}
|
||||||
|
|
||||||
var videoDimensions = {
|
var videoDimensions = {
|
||||||
xFactor: 1,
|
xFactor: 1,
|
||||||
@ -122,14 +130,15 @@ class Scaler {
|
|||||||
// console.log("[Scaler::calculateCrop] Player dimensions?", this.conf.player.dimensions.width, "×", this.conf.player.dimensions.height, "| obj:", this.conf.player.dimensions);
|
// console.log("[Scaler::calculateCrop] Player dimensions?", this.conf.player.dimensions.width, "×", this.conf.player.dimensions.height, "| obj:", this.conf.player.dimensions);
|
||||||
// }
|
// }
|
||||||
|
|
||||||
if( fileAr < ar.ratio ){
|
if (fileAr < ar.ratio){
|
||||||
// imamo letterbox zgoraj in spodaj -> spremenimo velikost videa (a nikoli širše od ekrana)
|
// imamo letterbox zgoraj in spodaj -> spremenimo velikost videa (a nikoli širše od ekrana)
|
||||||
// letterbox -> change video size (but never to wider than monitor width)
|
// letterbox -> change video size (but never to wider than monitor width)
|
||||||
|
// if (Debug.debug && Debug.scaler) {
|
||||||
|
// console.log(`%c[Scaler::calculateCrop] Trying to determine scaling factors. Aspect ratios:\n file: ${fileAr.toFixed(3)}\n player: ${playerAr.toFixed(3)}\n target: ${ar.ratio.toFixed(3)}\n-----------------------`, "color: #2ba");
|
||||||
|
// }
|
||||||
videoDimensions.xFactor = Math.min(ar.ratio, playerAr) / fileAr;
|
videoDimensions.xFactor = Math.min(ar.ratio, playerAr) / fileAr;
|
||||||
videoDimensions.yFactor = videoDimensions.xFactor;
|
videoDimensions.yFactor = videoDimensions.xFactor;
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
videoDimensions.xFactor = fileAr / Math.min(ar.ratio, playerAr);
|
videoDimensions.xFactor = fileAr / Math.min(ar.ratio, playerAr);
|
||||||
videoDimensions.yFactor = videoDimensions.xFactor;
|
videoDimensions.yFactor = videoDimensions.xFactor;
|
||||||
}
|
}
|
||||||
|
@ -34,19 +34,24 @@ https://www.youtube.com/watch?v=NaTGwlfRB_c (dark, triggers minor corrections)
|
|||||||
|
|
||||||
https://www.youtube.com/watch?v=tXTFdDrd7pA
|
https://www.youtube.com/watch?v=tXTFdDrd7pA
|
||||||
|
|
||||||
|
|
||||||
### HARD MODE
|
### HARD MODE
|
||||||
|
|
||||||
For situations that would be _really_ hard to fix (if fix is even possible)
|
For situations that would be _really_ hard to fix (if fix is even possible)
|
||||||
|
|
||||||
#### Gradient incorrectly triggers aspect ratio correction
|
#### Gradient incorrectly triggers aspect ratio correction
|
||||||
|
|
||||||
IGN: Hollow Knight Review | https://www.youtube.com/watch?v=hg25ONutphA
|
IGN: Hollow Knight Review | https://www.youtube.com/watch?v=hg25ONutphA (Should be mostly fixed as of 4.0.0)
|
||||||
|
|
||||||
|
#### Text triggers autodetection
|
||||||
|
|
||||||
|
If detected edge is text, extension shouldn't crop.
|
||||||
|
|
||||||
|
https://www.reddit.com/r/videos/comments/a137pj/daily_reminder_that_shelly_miscavige_wife_of/
|
||||||
|
|
||||||
### Bugs
|
### Bugs
|
||||||
|
|
||||||
#### Incorrect crops
|
#### Incorrect crops
|
||||||
|
|
||||||
Incorrect crop when fixing vertical videos with letterbox: https://www.youtube.com/watch?v=9DP0TbOQcOw — [Issue 48](https://github.com/xternal7/ultrawidify/issues/48)
|
~~Incorrect crop when fixing vertical videos with letterbox: https://www.youtube.com/watch?v=9DP0TbOQcOw — [Issue 48](https://github.com/xternal7/ultrawidify/issues/48)~~
|
||||||
|
|
||||||
Incorrect crop on 4:3 in certain circumstances: https://www.reddit.com/r/videos/comments/a137pj/daily_reminder_that_shelly_miscavige_wife_of/ (embedded) — [Issue 54](https://github.com/xternal7/ultrawidify/issues/54)
|
~~Incorrect crop on 4:3 in certain circumstances: https://www.reddit.com/r/videos/comments/a137pj/daily_reminder_that_shelly_miscavige_wife_of/ (embedded) — [Issue 54](https://github.com/xternal7/ultrawidify/issues/54)~~
|
Loading…
Reference in New Issue
Block a user