filmout_manager supports selecting and using color negative timings

This commit is contained in:
Matt McWilliams 2026-06-06 16:32:52 -04:00
parent 7ba696a9a8
commit 9338e19296
8 changed files with 222 additions and 7 deletions

View File

@ -330,7 +330,7 @@ class Client {
if (typeof state.mode !== 'undefined') {
(document.getElementById(`imageMode-${state.mode}`) as HTMLInputElement).checked = true;
const exposureCtrl : HTMLElement = document.getElementById('exposureCtrl');
if (state.mode === 'rgb' || state.mode === 'irgb') {
if (state.mode === 'rgb' || state.mode === 'irgb' || state.mode === 'colornegative') {
if (exposureCtrl.classList.contains('single')) {
exposureCtrl.classList.replace('single', 'multiple');
}

View File

@ -57,5 +57,6 @@ export declare class Sequence {
updateScale(scale: number): void;
private frameRecord;
private frameRecordRGB;
private frameRecordColorNegative;
}
export {};

103
dist/sequence/index.js vendored
View File

@ -16,6 +16,7 @@ var ImageMode;
ImageMode["Inverted"] = "inverted";
ImageMode["RGB"] = "rgb";
ImageMode["IRGB"] = "irgb";
ImageMode["CN"] = "colornegative";
})(ImageMode || (ImageMode = {}));
class Statistics {
constructor(exposure, frames) {
@ -148,6 +149,14 @@ class Sequence {
this.log.error(`Error recording frame`, err);
}
}
else if (this.mode === ImageMode.CN) {
try {
await this.frameRecordColorNegative();
}
catch (err) {
this.log.error(`Error recording frame`, err);
}
}
this.frameAdvance();
}
//complete running
@ -568,6 +577,100 @@ class Sequence {
total = Date.now() - start;
this.stats.add(load, open, exposureElapsed, exposureReported, close, total);
}
async frameRecordColorNegative() {
const start = Date.now();
let load;
let open;
let exposureElapsed = 0;
let exposureReported = 0;
let close;
let total;
let result;
let channels;
const img = this.images[this.frame];
const dimensions = this.display.getOutgoingPosition();
this.log.info(`CN: ${img.name} ${this.frame} / ${this.images.length}`);
try {
channels = await this.image.colorNegative(img.path);
}
catch (err) {
this.log.error(`Error getting temp files for channels`, err);
}
try {
await this.camera.open();
}
catch (err) {
this.log.error(`Error opening camera`, err);
}
open = Date.now() - start - load;
try {
await this.fd.load(channels.red, dimensions.x, dimensions.y, dimensions.w, dimensions.h);
}
catch (err) {
this.log.error(`Error loading cyan/red channel for display`, err);
}
load = Date.now() - start;
try {
await this.camera.open();
}
catch (err) {
this.log.error(`Error opening camera`, err);
}
this.log.info(`Displaying cyan/red channel for ${img.name}`);
try {
result = await this.fd.display(channels.red, [this.exposures[0]]);
}
catch (err) {
this.log.error(`Error displaying cyan/red channel`, err);
}
exposureReported += result.reported;
try {
await this.fd.load(channels.green, dimensions.x, dimensions.y, dimensions.w, dimensions.h);
}
catch (err) {
this.log.error(`Error loading green/magenta channel`, err);
}
this.log.info(`Displaying green/magenta channel for ${img.name}`);
try {
result = await this.fd.display(channels.green, [this.exposures[1]]);
}
catch (err) {
this.log.error(`Error displaying green channel`, err);
}
exposureReported += result.reported;
try {
await this.fd.load(channels.blue, dimensions.x, dimensions.y, dimensions.w, dimensions.h);
}
catch (err) {
this.log.error(`Error loading blue/yellow channel`, err);
}
this.log.info(`Displaying blue/yellow channel for ${img.name}`);
try {
result = await this.fd.display(channels.blue, [this.exposures[2]]);
}
catch (err) {
this.log.error(`Error displaying blue/yellow channel`, err);
}
exposureReported += result.reported;
try {
await (0, promises_1.unlink)(channels.red);
await (0, promises_1.unlink)(channels.green);
await (0, promises_1.unlink)(channels.blue);
}
catch (err) {
this.log.error(`Error cleaning up temp channel files`, err);
}
exposureElapsed = Date.now() - start - load - open;
try {
await this.camera.close();
}
catch (err) {
this.log.error(`Error closing camera`, err);
}
close = Date.now() - start - load - open - exposureElapsed;
total = Date.now() - start;
this.stats.add(load, open, exposureElapsed, exposureReported, close, total);
}
}
exports.Sequence = Sequence;
//# sourceMappingURL=index.js.map

File diff suppressed because one or more lines are too long

View File

@ -20,7 +20,8 @@ enum ImageMode {
Default = '8bit',
Inverted = 'inverted',
RGB = 'rgb',
IRGB = 'irgb'
IRGB = 'irgb',
CN = 'colornegative'
}
class Statistics {
@ -190,6 +191,12 @@ export class Sequence {
} catch (err) {
this.log.error(`Error recording frame`, err);
}
} else if (this.mode === ImageMode.CN) {
try {
await this.frameRecordColorNegative();
} catch (err) {
this.log.error(`Error recording frame`, err);
}
}
this.frameAdvance();
@ -651,4 +658,108 @@ export class Sequence {
total = Date.now() - start;
this.stats.add(load, open, exposureElapsed, exposureReported, close, total);
}
private async frameRecordColorNegative () {
const start : number = Date.now();
let load : number;
let open : number;
let exposureElapsed : number = 0;
let exposureReported : number = 0;
let close : number;
let total : number;
let result : fdResult;
let channels : Channels
const img : ImageObject = this.images[this.frame];
const dimensions : fdOutgoingPosition = this.display.getOutgoingPosition();
this.log.info(`CN: ${img.name} ${this.frame} / ${this.images.length}`);
try {
channels = await this.image.colorNegative(img.path);
} catch (err) {
this.log.error(`Error getting temp files for channels`, err);
}
try {
await this.camera.open();
} catch (err) {
this.log.error(`Error opening camera`, err);
}
open = Date.now() - start - load;
try {
await this.fd.load(channels.red, dimensions.x, dimensions.y, dimensions.w, dimensions.h);
} catch (err) {
this.log.error(`Error loading cyan/red channel for display`, err);
}
load = Date.now() - start;
try {
await this.camera.open();
} catch (err) {
this.log.error(`Error opening camera`, err);
}
this.log.info(`Displaying cyan/red channel for ${img.name}`);
try {
result = await this.fd.display(channels.red, [ this.exposures[0] ] );
} catch (err) {
this.log.error(`Error displaying cyan/red channel`, err);
}
exposureReported += result.reported;
try {
await this.fd.load(channels.green, dimensions.x, dimensions.y, dimensions.w, dimensions.h);
} catch (err) {
this.log.error(`Error loading green/magenta channel`, err);
}
this.log.info(`Displaying green/magenta channel for ${img.name}`);
try {
result = await this.fd.display(channels.green, [ this.exposures[1] ] );
} catch (err) {
this.log.error(`Error displaying green channel`, err);
}
exposureReported += result.reported;
try {
await this.fd.load(channels.blue, dimensions.x, dimensions.y, dimensions.w, dimensions.h);
} catch (err) {
this.log.error(`Error loading blue/yellow channel`, err);
}
this.log.info(`Displaying blue/yellow channel for ${img.name}`);
try {
result = await this.fd.display(channels.blue, [ this.exposures[2] ] );
} catch (err) {
this.log.error(`Error displaying blue/yellow channel`, err);
}
exposureReported += result.reported;
try {
await unlink(channels.red);
await unlink(channels.green);
await unlink(channels.blue);
} catch (err) {
this.log.error(`Error cleaning up temp channel files`, err);
}
exposureElapsed = Date.now() - start - load - open;
try {
await this.camera.close();
} catch (err) {
this.log.error(`Error closing camera`, err);
}
close = Date.now() - start - load - open - exposureElapsed;
total = Date.now() - start;
this.stats.add(load, open, exposureElapsed, exposureReported, close, total);
}
}

View File

@ -269,7 +269,7 @@ class Client {
if (typeof state.mode !== 'undefined') {
document.getElementById(`imageMode-${state.mode}`).checked = true;
const exposureCtrl = document.getElementById('exposureCtrl');
if (state.mode === 'rgb' || state.mode === 'irgb') {
if (state.mode === 'rgb' || state.mode === 'irgb' || state.mode === 'colornegative') {
if (exposureCtrl.classList.contains('single')) {
exposureCtrl.classList.replace('single', 'multiple');
}

File diff suppressed because one or more lines are too long

View File

@ -214,8 +214,8 @@
<label for="imageMode-rgb">Positive RGB</label>
</div>
<div class="check">
<input type="radio" name="imageMode" id="imageMode-irgb" value="irgb" onclick="client.sendImageMode();" />
<label for="imageMode-irgb">Negative RGB</label>
<input type="radio" name="imageMode" id="imageMode-colornegative" value="colornegative" onclick="client.sendImageMode();" />
<label for="imageMode-colornegative">Color Negative</label>
</div>
</span>
</form>