Add position adjustment logic and size adjustment logic. Still need to complete scale and fix an issue with letterboxed images just discovered with a 4:3 monitor

This commit is contained in:
Matt McWilliams 2024-10-22 15:04:25 -04:00
parent 58b9310128
commit 582a95202e
18 changed files with 374 additions and 36 deletions

View File

@ -57,6 +57,11 @@ interface State {
interface Message { interface Message {
cmd? : string; cmd? : string;
state? : State; state? : State;
x? : number;
y? : number;
width? : number;
height? : number;
scale? : number;
} }
declare function humanizeDuration(a : any, b : any) : string; declare function humanizeDuration(a : any, b : any) : string;

View File

@ -57,17 +57,17 @@ class Display {
this.canvasScale = window.devicePixelRatio; this.canvasScale = window.devicePixelRatio;
this.canvasWidth = this.parentElement.clientWidth - 12; this.canvasWidth = this.parentElement.clientWidth - 12;
this.canvasHeight = this.parentElement.clientHeight - 12; this.canvasHeight = this.parentElement.clientHeight - 12;
console.log(`${this.canvasWidth},${this.canvasHeight}`); //console.log(`${this.canvasWidth},${this.canvasHeight}`);
this.canvas.width = this.canvasWidth; this.canvas.width = this.canvasWidth;
this.canvas.height = this.canvasHeight; this.canvas.height = this.canvasHeight;
} }
private clear () { public clear () {
this.ctx.fillStyle = 'rgb(0, 0, 0)'; this.ctx.fillStyle = 'rgb(0, 0, 0)';
this.ctx.fillRect(0, 0, this.canvasWidth, this.canvasHeight); this.ctx.fillRect(0, 0, this.canvasWidth, this.canvasHeight);
} }
private updateScreen () { public updateScreen () {
const clientRatio : number = this.canvasWidth / this.canvasHeight; const clientRatio : number = this.canvasWidth / this.canvasHeight;
const screenRatio : number = this.screen.width / this.screen.height; const screenRatio : number = this.screen.width / this.screen.height;
@ -91,7 +91,7 @@ class Display {
if (!this.sequence) { if (!this.sequence) {
return; return;
} }
console.log(this.sequence) //console.log(this.sequence);
const screenScaleX : number = this.screenWidth / this.screen.width; const screenScaleX : number = this.screenWidth / this.screen.width;
const screenScaleY : number = this.screenHeight / this.screen.height; const screenScaleY : number = this.screenHeight / this.screen.height;
this.displayWidth = Math.round(this.width * screenScaleX); this.displayWidth = Math.round(this.width * screenScaleX);
@ -101,7 +101,7 @@ class Display {
this.ctx.fillStyle = 'rgb(0, 0, 0)'; this.ctx.fillStyle = 'rgb(0, 0, 0)';
this.ctx.fillRect(this.displayOffsetX, this.displayOffsetY, this.displayWidth, this.displayHeight); this.ctx.fillRect(this.displayOffsetX, this.displayOffsetY, this.displayWidth, this.displayHeight);
console.log(`${this.displayOffsetX}, ${this.displayOffsetY}, ${this.displayWidth}, ${this.displayHeight}`); //console.log(`${this.displayOffsetX}, ${this.displayOffsetY}, ${this.displayWidth}, ${this.displayHeight}`);
this.updateImage(); this.updateImage();
} }
@ -257,6 +257,8 @@ class Client {
if (typeof state.display !== 'undefined') { if (typeof state.display !== 'undefined') {
this.set('displayWidth', state.display.width.toString()); this.set('displayWidth', state.display.width.toString());
this.set('displayHeight', state.display.height.toString()); this.set('displayHeight', state.display.height.toString());
this.set('offsetLeft', state.offset.x.toString());
this.set('offsetTop', state.offset.y.toString());
this.set('sourceWidth', state.source.width.toString()); this.set('sourceWidth', state.source.width.toString());
this.set('sourceHeight', state.source.height.toString()); this.set('sourceHeight', state.source.height.toString());
@ -322,6 +324,9 @@ class Client {
case 'focus' : case 'focus' :
this.receiveFocus(msg); this.receiveFocus(msg);
break; break;
case 'display' :
this.receiveDisplay(msg);
break;
default: default:
console.warn(`No command "${msg.cmd}"`); console.warn(`No command "${msg.cmd}"`);
break; break;
@ -441,6 +446,12 @@ class Client {
this.setUpdate(msg.state); this.setUpdate(msg.state);
} }
private receiveDisplay (msg: Message) {
this.display.clear();
this.display.updateScreen();
this.setDisplay(msg.state);
}
public sendFocus () { public sendFocus () {
console.log('send focus'); console.log('send focus');
//this.disableClass('manualCtrl'); //this.disableClass('manualCtrl');
@ -451,6 +462,18 @@ class Client {
this.display.updateImage(); this.display.updateImage();
} }
public sendOffset (x : number, y : number) {
this.client.send(JSON.stringify({ cmd : 'offset', x, y }));
}
public sendSize (width : number, height : number) {
this.client.send(JSON.stringify({ cmd : 'size', width, height }));
}
public sendScale (scale : number) {
this.client.send(JSON.stringify({ cmd : 'scale', scale }));
}
/** /**
* HELPERS * HELPERS
**/ **/

View File

@ -5,6 +5,10 @@ export declare class Dimensions {
constructor(width: number, height: number); constructor(width: number, height: number);
getRatio(): number; getRatio(): number;
} }
interface Offset {
x: number;
y: number;
}
export declare class Display { export declare class Display {
private screen; private screen;
private source; private source;
@ -13,8 +17,13 @@ export declare class Display {
constructor(width: number, height: number); constructor(width: number, height: number);
setOffsetX(x: number): void; setOffsetX(x: number): void;
setOffsetY(y: number): void; setOffsetY(y: number): void;
setWidth(width: number): void;
setHeight(height: number): void;
setSource(width: number, height: number): void; setSource(width: number, height: number): void;
getDimensions(): fdOutgoingPosition; getOutgoingPosition(): fdOutgoingPosition;
getDimensions(): Dimensions;
getOffset(): Offset;
getScreen(): Dimensions; getScreen(): Dimensions;
getSource(): Dimensions; getSource(): Dimensions;
} }
export type { Offset };

14
dist/display/index.js vendored
View File

@ -22,6 +22,12 @@ class Display {
setOffsetY(y) { setOffsetY(y) {
this.offset.y = y; this.offset.y = y;
} }
setWidth(width) {
this.display.width = width;
}
setHeight(height) {
this.display.height = height;
}
setSource(width, height) { setSource(width, height) {
let offset; let offset;
this.source = new Dimensions(width, height); this.source = new Dimensions(width, height);
@ -36,7 +42,7 @@ class Display {
this.offset = { x: Math.round(offset / 2), y: 0 }; this.offset = { x: Math.round(offset / 2), y: 0 };
} }
} }
getDimensions() { getOutgoingPosition() {
return { return {
w: this.display.width, w: this.display.width,
h: this.display.height, h: this.display.height,
@ -44,6 +50,12 @@ class Display {
y: this.offset.y y: this.offset.y
}; };
} }
getDimensions() {
return this.display;
}
getOffset() {
return this.offset;
}
getScreen() { getScreen() {
return this.screen; return this.screen;
} }

View File

@ -1 +1 @@
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/display/index.ts"],"names":[],"mappings":";;;AAEA,MAAa,UAAU;IAItB,YAAa,KAAc,EAAE,MAAe;QAC3C,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;QACnB,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;IACtB,CAAC;IAEM,QAAQ;QACd,OAAO,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,MAAM,CAAC;IACjC,CAAC;CACD;AAZD,gCAYC;AAOD,MAAa,OAAO;IAQnB,YAAa,KAAc,EAAE,MAAe;QAC3C,IAAI,CAAC,MAAM,GAAG,IAAI,UAAU,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;QAC5C,IAAI,CAAC,MAAM,GAAG,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAG,CAAC,EAAE,CAAA;IAC9B,CAAC;IAEM,UAAU,CAAE,CAAU;QAC5B,IAAI,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,CAAC;IACnB,CAAC;IAEM,UAAU,CAAE,CAAU;QAC5B,IAAI,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,CAAC;IACnB,CAAC;IAEM,SAAS,CAAE,KAAc,EAAE,MAAe;QAChD,IAAI,MAAe,CAAC;QACpB,IAAI,CAAC,MAAM,GAAG,IAAI,UAAU,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;QAC5C,IAAI,IAAI,CAAC,MAAM,CAAC,QAAQ,EAAE,GAAG,IAAI,CAAC,MAAM,CAAC,QAAQ,EAAE,EAAE,CAAC;YACrD,IAAI,CAAC,OAAO,GAAG,IAAI,UAAU,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,GAAG,IAAI,CAAC,MAAM,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC;YACzG,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC;YAClD,IAAI,CAAC,MAAM,GAAG,EAAE,CAAC,EAAE,CAAC,EAAG,CAAC,EAAG,IAAI,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,EAAE,CAAC;QACrD,CAAC;aAAM,CAAC;YACP,IAAI,CAAC,OAAO,GAAG,IAAI,UAAU,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,EAAE,GAAG,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;YAC3G,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,KAAK,GAAG,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC;YAChD,IAAI,CAAC,MAAM,GAAG,EAAE,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,EAAG,CAAC,EAAG,CAAC,EAAE,CAAC;QACrD,CAAC;IACF,CAAC;IAEM,aAAa;QACnB,OAAO;YACN,CAAC,EAAG,IAAI,CAAC,OAAO,CAAC,KAAK;YACtB,CAAC,EAAG,IAAI,CAAC,OAAO,CAAC,MAAM;YACvB,CAAC,EAAG,IAAI,CAAC,MAAM,CAAC,CAAC;YACjB,CAAC,EAAG,IAAI,CAAC,MAAM,CAAC,CAAC;SACjB,CAAA;IACF,CAAC;IAEM,SAAS;QACf,OAAO,IAAI,CAAC,MAAM,CAAC;IACpB,CAAC;IAEM,SAAS;QACf,OAAO,IAAI,CAAC,MAAM,CAAC;IACpB,CAAC;CACD;AAnDD,0BAmDC;AAED,MAAM,CAAC,OAAO,GAAG,EAAE,OAAO,EAAG,UAAU,EAAE,CAAC"} {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/display/index.ts"],"names":[],"mappings":"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"}

31
dist/index.js vendored
View File

@ -238,6 +238,15 @@ async function cmd(msg) {
case 'focus': case 'focus':
await focus(); await focus();
break; break;
case 'offset':
offset(msg);
break;
case 'size':
size(msg);
break;
case 'scale':
scale(msg);
break;
default: default:
log.warn(`No matching command: ${msg.cmd}`); log.warn(`No matching command: ${msg.cmd}`);
} }
@ -319,6 +328,24 @@ async function focus() {
focusImage = await testimage_1.TestImage.Focus(pos.w, pos.h); focusImage = await testimage_1.TestImage.Focus(pos.w, pos.h);
send({ cmd: 'focus' }); send({ cmd: 'focus' });
} }
function offset(msg) {
let current = sequence.getCurrent();
if (current !== null) {
sequence.updateOffset(msg.x, msg.y);
}
}
function size(msg) {
let current = sequence.getCurrent();
if (current !== null) {
sequence.updateSize(msg.width, msg.height);
}
}
function scale(msg) {
let current = sequence.getCurrent();
if (current !== null) {
sequence.updateScale(msg.scale);
}
}
app.get('/', async (req, res, next) => { app.get('/', async (req, res, next) => {
const sequencesArr = await files_1.Files.enumerateSequences(sequences); const sequencesArr = await files_1.Files.enumerateSequences(sequences);
//const videosArr : VideoObject[] = await Files.enumerateVideos(videos); //const videosArr : VideoObject[] = await Files.enumerateVideos(videos);
@ -336,7 +363,7 @@ app.get('/:width/:height/image.jpg', async (req, res, next) => {
log.info(`Image: ${current.path} - ${width},${height}`); log.info(`Image: ${current.path} - ${width},${height}`);
} }
catch (err) { catch (err) {
log.error('Error getting thumbnail of ${current}', err); log.error(`Error getting thumbnail of ${current}`, err);
return next(new Error('Error getting thumbnail')); return next(new Error('Error getting thumbnail'));
} }
} }
@ -346,7 +373,7 @@ app.get('/:width/:height/image.jpg', async (req, res, next) => {
log.info(`Image: ${current.path} - ${width},${height}`); log.info(`Image: ${current.path} - ${width},${height}`);
} }
catch (err) { catch (err) {
log.error('Error getting thumbnail of ${current}', err); log.error(`Error getting thumbnail of ${current}`, err);
return next(new Error('Error getting thumbnail')); return next(new Error('Error getting thumbnail'));
} }
} }

2
dist/index.js.map vendored

File diff suppressed because one or more lines are too long

View File

@ -34,6 +34,7 @@ export declare class Sequence {
load(seq: SequenceObject): Promise<void>; load(seq: SequenceObject): Promise<void>;
updateClientsOnLoad(): void; updateClientsOnLoad(): void;
updateClientsOnState(): void; updateClientsOnState(): void;
updateClientsOnDisplay(): void;
private enumerate; private enumerate;
unload(): void; unload(): void;
getState(): State; getState(): State;
@ -45,6 +46,9 @@ export declare class Sequence {
frameAdvance(frames?: number): void; frameAdvance(frames?: number): void;
frameRewind(frames?: number): void; frameRewind(frames?: number): void;
frameSet(frame: number): void; frameSet(frame: number): void;
updateOffset(x: number, y: number): void;
updateSize(width: number, height: number): void;
updateScale(scale: number): void;
private frameRecord; private frameRecord;
} }
export {}; export {};

View File

@ -149,6 +149,11 @@ class Sequence {
this.send({ cmd: 'update', state: this.getState() }); this.send({ cmd: 'update', state: this.getState() });
} }
} }
updateClientsOnDisplay() {
if (this.current !== null) {
this.send({ cmd: 'display', state: this.getState() });
}
}
async enumerate() { async enumerate() {
let screen; let screen;
if (this.current === null) { if (this.current === null) {
@ -172,7 +177,7 @@ class Sequence {
this.display.setSource(this.info.width, this.info.height); this.display.setSource(this.info.width, this.info.height);
this.log.info(`Screen : ${screen.width},${screen.height}`); this.log.info(`Screen : ${screen.width},${screen.height}`);
this.log.info(`Sequence : ${this.info.width},${this.info.height}`); this.log.info(`Sequence : ${this.info.width},${this.info.height}`);
this.log.info(`Display : ${JSON.stringify(this.display.getDimensions())}`); this.log.info(`Display : ${JSON.stringify(this.display.getOutgoingPosition())}`);
} }
} }
unload() { unload() {
@ -181,7 +186,7 @@ class Sequence {
this.images = []; this.images = [];
} }
getState() { getState() {
const dimensions = this.display.getDimensions(); const dimensions = this.display.getOutgoingPosition();
const source = this.display.getSource(); const source = this.display.getSource();
const screen = this.display.getScreen(); const screen = this.display.getScreen();
return { return {
@ -281,6 +286,76 @@ class Sequence {
this.progress = this.frame > 0 ? this.frame / (this.images.length - 1) : 0; this.progress = this.frame > 0 ? this.frame / (this.images.length - 1) : 0;
this.updateClientsOnState(); this.updateClientsOnState();
} }
updateOffset(x, y) {
const current = this.display.getOutgoingPosition();
const screen = this.display.getScreen();
let totalX;
let totalY;
let updated = false;
if (x !== 0) {
if (current.x + x < 0) {
return;
}
totalX = current.x + current.w + x;
if (totalX > screen.width) {
return;
}
this.display.setOffsetX(current.x + x);
updated = true;
}
if (y !== 0) {
if (current.y + y < 0) {
return;
}
totalY = current.y + current.h + y;
if (totalY > screen.height) {
return;
}
this.display.setOffsetY(current.y + y);
updated = true;
}
if (updated) {
this.updateClientsOnDisplay();
}
}
updateSize(width, height) {
const current = this.display.getOutgoingPosition();
const screen = this.display.getScreen();
let totalX;
let totalY;
let updated = false;
if (width !== 0) {
if (current.w + width < 1) {
return;
}
totalX = current.x + current.w + width;
if (totalX > screen.width) {
return;
}
this.display.setWidth(current.w + width);
updated = true;
}
if (height !== 0) {
if (current.h + height < 1) {
return;
}
totalY = current.y + current.h + height;
if (totalY > screen.height) {
return;
}
this.display.setHeight(current.h + height);
updated = true;
}
if (updated) {
this.updateClientsOnDisplay();
}
}
updateScale(scale) {
const current = this.display.getDimensions();
const offset = this.display.getOffset();
const screen = this.display.getScreen();
console.dir(scale);
}
async frameRecord() { async frameRecord() {
const start = Date.now(); const start = Date.now();
let load; let load;
@ -291,7 +366,7 @@ class Sequence {
let total; let total;
let result; let result;
const img = this.images[this.frame]; const img = this.images[this.frame];
const dimensions = this.display.getDimensions(); const dimensions = this.display.getOutgoingPosition();
this.log.info(`Frame: ${this.frame} / ${this.images.length}`); this.log.info(`Frame: ${this.frame} / ${this.images.length}`);
await this.fd.load(img.path, dimensions.x, dimensions.y, dimensions.w, dimensions.h); await this.fd.load(img.path, dimensions.x, dimensions.y, dimensions.w, dimensions.h);
load = Date.now() - start; load = Date.now() - start;

File diff suppressed because one or more lines are too long

View File

@ -40,6 +40,14 @@ export class Display {
this.offset.y = y; this.offset.y = y;
} }
public setWidth (width : number) {
this.display.width = width;
}
public setHeight (height : number) {
this.display.height = height;
}
public setSource (width : number, height : number) { public setSource (width : number, height : number) {
let offset : number; let offset : number;
this.source = new Dimensions(width, height); this.source = new Dimensions(width, height);
@ -54,7 +62,7 @@ export class Display {
} }
} }
public getDimensions () : fdOutgoingPosition { public getOutgoingPosition () : fdOutgoingPosition {
return { return {
w : this.display.width, w : this.display.width,
h : this.display.height, h : this.display.height,
@ -63,6 +71,14 @@ export class Display {
} }
} }
public getDimensions () : Dimensions {
return this.display;
}
public getOffset () : Offset {
return this.offset;
}
public getScreen () : Dimensions { public getScreen () : Dimensions {
return this.screen; return this.screen;
} }
@ -73,3 +89,4 @@ export class Display {
} }
module.exports = { Display, Dimensions }; module.exports = { Display, Dimensions };
export type { Offset };

5
src/globals.d.ts vendored
View File

@ -57,6 +57,11 @@ interface State {
interface Message { interface Message {
cmd? : string; cmd? : string;
state? : State; state? : State;
x? : number;
y? : number;
width? : number;
height? : number;
scale? : number;
} }
declare function humanizeDuration(a : any, b : any) : string; declare function humanizeDuration(a : any, b : any) : string;

View File

@ -226,6 +226,15 @@ async function cmd (msg : Message) {
case 'focus' : case 'focus' :
await focus(); await focus();
break; break;
case 'offset' :
offset(msg);
break;
case 'size' :
size(msg);
break;
case 'scale' :
scale(msg);
break;
default : default :
log.warn(`No matching command: ${msg.cmd}`); log.warn(`No matching command: ${msg.cmd}`);
} }
@ -319,6 +328,27 @@ async function focus () {
send({ cmd : 'focus' }); send({ cmd : 'focus' });
} }
function offset (msg : Message) {
let current : ImageObject = sequence.getCurrent();
if (current !== null) {
sequence.updateOffset(msg.x, msg.y);
}
}
function size (msg : Message) {
let current : ImageObject = sequence.getCurrent();
if (current !== null) {
sequence.updateSize(msg.width, msg.height);
}
}
function scale (msg : Message) {
let current : ImageObject = sequence.getCurrent();
if (current !== null) {
sequence.updateScale(msg.scale);
}
}
app.get('/', async (req : Request, res : Response, next : NextFunction) => { app.get('/', async (req : Request, res : Response, next : NextFunction) => {
const sequencesArr : SequenceObject[] = await Files.enumerateSequences(sequences); const sequencesArr : SequenceObject[] = await Files.enumerateSequences(sequences);
//const videosArr : VideoObject[] = await Files.enumerateVideos(videos); //const videosArr : VideoObject[] = await Files.enumerateVideos(videos);

View File

@ -5,7 +5,7 @@ import type { Logger } from 'winston';
import type { SequenceObject, ImageObject } from '../files'; import type { SequenceObject, ImageObject } from '../files';
import type { FD, fdOutgoingPosition, fdResult } from '../fd'; import type { FD, fdOutgoingPosition, fdResult } from '../fd';
import type { Camera } from '../camera'; import type { Camera } from '../camera';
import type { Display, Dimensions } from '../display'; import type { Display, Dimensions, Offset } from '../display';
import type { FFPROBE, VideoInfo } from '../ffprobe'; import type { FFPROBE, VideoInfo } from '../ffprobe';
enum SequenceStatus { enum SequenceStatus {
@ -196,6 +196,12 @@ export class Sequence {
} }
} }
public updateClientsOnDisplay () {
if (this.current !== null) {
this.send({ cmd : 'display', state : this.getState() });
}
}
private async enumerate () { private async enumerate () {
let screen : Dimensions; let screen : Dimensions;
@ -223,7 +229,7 @@ export class Sequence {
this.display.setSource(this.info.width, this.info.height); this.display.setSource(this.info.width, this.info.height);
this.log.info(`Screen : ${screen.width},${screen.height}`); this.log.info(`Screen : ${screen.width},${screen.height}`);
this.log.info(`Sequence : ${this.info.width},${this.info.height}`); this.log.info(`Sequence : ${this.info.width},${this.info.height}`);
this.log.info(`Display : ${JSON.stringify(this.display.getDimensions())}`) this.log.info(`Display : ${JSON.stringify(this.display.getOutgoingPosition())}`)
} }
} }
@ -234,7 +240,7 @@ export class Sequence {
} }
public getState () : State { public getState () : State {
const dimensions : fdOutgoingPosition = this.display.getDimensions(); const dimensions : fdOutgoingPosition = this.display.getOutgoingPosition();
const source : Dimensions = this.display.getSource(); const source : Dimensions = this.display.getSource();
const screen : Dimensions = this.display.getScreen(); const screen : Dimensions = this.display.getScreen();
return { return {
@ -341,6 +347,79 @@ export class Sequence {
this.updateClientsOnState(); this.updateClientsOnState();
} }
public updateOffset (x : number, y : number) {
const current : fdOutgoingPosition = this.display.getOutgoingPosition();
const screen : Dimensions = this.display.getScreen();
let totalX : number;
let totalY : number;
let updated : boolean = false;
if (x !== 0) {
if (current.x + x < 0) {
return;
}
totalX = current.x + current.w + x;
if (totalX > screen.width) {
return;
}
this.display.setOffsetX(current.x + x);
updated = true;
}
if (y !== 0) {
if (current.y + y < 0) {
return;
}
totalY = current.y + current.h + y;
if (totalY > screen.height) {
return;
}
this.display.setOffsetY(current.y + y);
updated = true;
}
if (updated) {
this.updateClientsOnDisplay();
}
}
public updateSize (width : number, height : number) {
const current : fdOutgoingPosition = this.display.getOutgoingPosition();
const screen : Dimensions = this.display.getScreen();
let totalX : number;
let totalY : number;
let updated : boolean = false;
if (width !== 0) {
if (current.w + width < 1) {
return;
}
totalX = current.x + current.w + width;
if (totalX > screen.width) {
return;
}
this.display.setWidth(current.w + width);
updated = true;
}
if (height !== 0) {
if (current.h + height < 1) {
return;
}
totalY = current.y + current.h + height;
if (totalY > screen.height) {
return;
}
this.display.setHeight(current.h + height);
updated = true;
}
if (updated) {
this.updateClientsOnDisplay();
}
}
public updateScale (scale : number) {
const current : Dimensions = this.display.getDimensions();
const offset : Offset = this.display.getOffset();
const screen : Dimensions = this.display.getScreen();
console.dir(scale);
}
private async frameRecord () { private async frameRecord () {
const start : number = Date.now(); const start : number = Date.now();
let load : number; let load : number;
@ -351,7 +430,7 @@ export class Sequence {
let total : number; let total : number;
let result : fdResult; let result : fdResult;
const img : ImageObject = this.images[this.frame]; const img : ImageObject = this.images[this.frame];
const dimensions : fdOutgoingPosition = this.display.getDimensions(); const dimensions : fdOutgoingPosition = this.display.getOutgoingPosition();
this.log.info(`Frame: ${this.frame} / ${this.images.length}`); this.log.info(`Frame: ${this.frame} / ${this.images.length}`);
await this.fd.load(img.path, dimensions.x, dimensions.y, dimensions.w, dimensions.h); await this.fd.load(img.path, dimensions.x, dimensions.y, dimensions.w, dimensions.h);
load = Date.now() - start; load = Date.now() - start;

View File

@ -30,8 +30,8 @@ declare class Display {
constructor(); constructor();
private create; private create;
private updateSize; private updateSize;
private clear; clear(): void;
private updateScreen; updateScreen(): void;
updateDisplay(): void; updateDisplay(): void;
updateImage(): void; updateImage(): void;
update(msg: Message): void; update(msg: Message): void;
@ -79,8 +79,12 @@ declare class Client {
sendStop(): void; sendStop(): void;
sendExposure(): void; sendExposure(): void;
private receiveUpdate; private receiveUpdate;
private receiveDisplay;
sendFocus(): void; sendFocus(): void;
private receiveFocus; private receiveFocus;
sendOffset(x: number, y: number): void;
sendSize(width: number, height: number): void;
sendScale(scale: number): void;
fullscreen(): void; fullscreen(): void;
exitFullscreen(): void; exitFullscreen(): void;
private active; private active;

View File

@ -45,7 +45,6 @@ class Display {
this.canvasScale = window.devicePixelRatio; this.canvasScale = window.devicePixelRatio;
this.canvasWidth = this.parentElement.clientWidth - 12; this.canvasWidth = this.parentElement.clientWidth - 12;
this.canvasHeight = this.parentElement.clientHeight - 12; this.canvasHeight = this.parentElement.clientHeight - 12;
console.log(`${this.canvasWidth},${this.canvasHeight}`);
this.canvas.width = this.canvasWidth; this.canvas.width = this.canvasWidth;
this.canvas.height = this.canvasHeight; this.canvas.height = this.canvasHeight;
} }
@ -76,7 +75,6 @@ class Display {
if (!this.sequence) { if (!this.sequence) {
return; return;
} }
console.log(this.sequence);
const screenScaleX = this.screenWidth / this.screen.width; const screenScaleX = this.screenWidth / this.screen.width;
const screenScaleY = this.screenHeight / this.screen.height; const screenScaleY = this.screenHeight / this.screen.height;
this.displayWidth = Math.round(this.width * screenScaleX); this.displayWidth = Math.round(this.width * screenScaleX);
@ -85,7 +83,6 @@ class Display {
this.displayOffsetY = this.screenOffsetY + Math.round(this.offsetY * screenScaleY); this.displayOffsetY = this.screenOffsetY + Math.round(this.offsetY * screenScaleY);
this.ctx.fillStyle = 'rgb(0, 0, 0)'; this.ctx.fillStyle = 'rgb(0, 0, 0)';
this.ctx.fillRect(this.displayOffsetX, this.displayOffsetY, this.displayWidth, this.displayHeight); this.ctx.fillRect(this.displayOffsetX, this.displayOffsetY, this.displayWidth, this.displayHeight);
console.log(`${this.displayOffsetX}, ${this.displayOffsetY}, ${this.displayWidth}, ${this.displayHeight}`);
this.updateImage(); this.updateImage();
} }
updateImage() { updateImage() {
@ -215,6 +212,8 @@ class Client {
if (typeof state.display !== 'undefined') { if (typeof state.display !== 'undefined') {
this.set('displayWidth', state.display.width.toString()); this.set('displayWidth', state.display.width.toString());
this.set('displayHeight', state.display.height.toString()); this.set('displayHeight', state.display.height.toString());
this.set('offsetLeft', state.offset.x.toString());
this.set('offsetTop', state.offset.y.toString());
this.set('sourceWidth', state.source.width.toString()); this.set('sourceWidth', state.source.width.toString());
this.set('sourceHeight', state.source.height.toString()); this.set('sourceHeight', state.source.height.toString());
this.display.set(state); this.display.set(state);
@ -266,6 +265,9 @@ class Client {
case 'focus': case 'focus':
this.receiveFocus(msg); this.receiveFocus(msg);
break; break;
case 'display':
this.receiveDisplay(msg);
break;
default: default:
console.warn(`No command "${msg.cmd}"`); console.warn(`No command "${msg.cmd}"`);
break; break;
@ -366,6 +368,11 @@ class Client {
receiveUpdate(msg) { receiveUpdate(msg) {
this.setUpdate(msg.state); this.setUpdate(msg.state);
} }
receiveDisplay(msg) {
this.display.clear();
this.display.updateScreen();
this.setDisplay(msg.state);
}
sendFocus() { sendFocus() {
console.log('send focus'); console.log('send focus');
this.client.send(JSON.stringify({ cmd: 'focus' })); this.client.send(JSON.stringify({ cmd: 'focus' }));
@ -373,6 +380,15 @@ class Client {
receiveFocus(msg) { receiveFocus(msg) {
this.display.updateImage(); this.display.updateImage();
} }
sendOffset(x, y) {
this.client.send(JSON.stringify({ cmd: 'offset', x, y }));
}
sendSize(width, height) {
this.client.send(JSON.stringify({ cmd: 'size', width, height }));
}
sendScale(scale) {
this.client.send(JSON.stringify({ cmd: 'scale', scale }));
}
fullscreen() { fullscreen() {
if (!document.fullscreenElement) { if (!document.fullscreenElement) {
document.documentElement.requestFullscreen(); document.documentElement.requestFullscreen();

File diff suppressed because one or more lines are too long

View File

@ -61,7 +61,7 @@
<input id="offsetLeft" type="text" value="0" readonly /> <input id="offsetLeft" type="text" value="0" readonly />
</span> </span>
<span class="field-row"> <span class="field-row">
<label for="offsetTop">Height</label> <label for="offsetTop">Top</label>
<input id="offsetTop" type="text" value="0" readonly /> <input id="offsetTop" type="text" value="0" readonly />
</span> </span>
</fieldset> </fieldset>
@ -132,33 +132,65 @@
<span> <span>
<div></div> <div></div>
<div> <div>
<button class="small manualCtrl" id="offsetXMinus" disabled><</button> <button class="small manualCtrl" id="offsetXMinus" onclick="client.sendOffset(-1, 0);" disabled>←</button>
</div> </div>
<div></div> <div></div>
</span> </span>
<span> <span>
<div> <div>
<button class="small manualCtrl" id="offsetYPlus" disabled>^</button> <button class="small manualCtrl" id="offsetYPlus" onclick="client.sendOffset(0, -1);" disabled>↑</button>
</div> </div>
<div> <div>
Position Position
</div> </div>
<div> <div>
<button class="small manualCtrl" id="offsetYMinus" disabled>Y -</button> <button class="small manualCtrl" id="offsetYMinus" onclick="client.sendOffset(0, 1);" disabled>↓</button>
</div> </div>
</span> </span>
<span> <span>
<div></div> <div></div>
<div> <div>
<button class="small manualCtrl" id="offsetXPlus" disabled>></button> <button class="small manualCtrl" id="offsetXPlus" onclick="client.sendOffset(1, 0);" disabled>→</button>
</div> </div>
<div></div> <div></div>
</span> </span>
<span> <span>
<button class="small manualCtrl" id="widthPlus" disabled>W +</button> <div style="width: 30px;">&nbsp;</div>
<button class="small manualCtrl" id="widthMinus" disabled>W -</button> </span>
<button class="small manualCtrl" id="heightPlus" disabled>H +</button> <span>
<button class="small manualCtrl" id="heightMinus" disabled>H -</button> <div></div>
<div>
<button class="small manualCtrl" id="widthMinus" onclick="client.sendSize(-1, 0);" disabled>W -</button>
</div>
<div></div>
</span>
<span>
<div>
<button class="small manualCtrl" id="heightPlus" onclick="client.sendSize(0, 1);" disabled>H +</button>
</div>
<div>Size</div>
<div>
<button class="small manualCtrl" id="heightMinus" onclick="client.sendSize(0, -1);" disabled>H -</button>
</div>
</span>
<span>
<div></div>
<div>
<button class="small manualCtrl" id="widthPlus" onclick="client.sendSize(1, 0);" disabled>W +</button>
</div>
<div></div>
</span>
<span>
<div style="width: 30px;">&nbsp;</div>
</span>
<span>
<div>
<button class="small manualCtrl" id="scalePlus" onclick="client.sendScale(2);" disabled>S +</button>
</div>
<div>Scale</div>
<div>
<button class="small manualCtrl" id="scaleMinus" onclick="client.sendScale(-2);" disabled>S -</button>
</div>
</span> </span>
</form> </form>
</fieldset> </fieldset>