speedy-vision
Version:
GPU-accelerated Computer Vision for JavaScript
137 lines (122 loc) • 3.98 kB
JavaScript
/*
* speedy-vision.js
* GPU-accelerated Computer Vision for JavaScript
* Copyright 2020-2022 Alexandre Martins <alemartf(at)gmail.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* mixer.js
* Image Mixer
*/
import { SpeedyPipelineNode } from '../../pipeline-node';
import { SpeedyPipelineMessageType, SpeedyPipelineMessageWithImage } from '../../pipeline-message';
import { InputPort, OutputPort } from '../../pipeline-portbuilder';
import { SpeedyGPU } from '../../../../gpu/speedy-gpu';
import { SpeedyTexture } from '../../../../gpu/speedy-texture';
import { Utils } from '../../../../utils/utils';
import { ImageFormat } from '../../../../utils/types';
import { SpeedyPromise } from '../../../speedy-promise';
import { NotSupportedError } from '../../../../utils/errors';
/**
* Image Mixer
*/
export class SpeedyPipelineNodeImageMixer extends SpeedyPipelineNode
{
/**
* Constructor
* @param {string} [name] name of the node
*/
constructor(name = undefined)
{
super(name, 1, [
InputPort('in0').expects(SpeedyPipelineMessageType.Image),
InputPort('in1').expects(SpeedyPipelineMessageType.Image),
OutputPort().expects(SpeedyPipelineMessageType.Image),
]);
/** @type {number} alpha coefficient (applied to image0) */
this._alpha = 0.5;
/** @type {number} beta coefficient (applied to image1) */
this._beta = 0.5;
/** @type {number} gamma coefficient (brightness control) */
this._gamma = 0.0;
}
/**
* Alpha coefficient (applied to image0)
* @returns {number}
*/
get alpha()
{
return this._alpha;
}
/**
* Alpha coefficient (applied to image0)
* @param {number} value
*/
set alpha(value)
{
this._alpha = +value;
}
/**
* Beta coefficient (applied to image1)
* @returns {number}
*/
get beta()
{
return this._beta;
}
/**
* Beta coefficient (applied to image1)
* @param {number} value
*/
set beta(value)
{
this._beta = +value;
}
/**
* Gamma coefficient (brightness control)
* @returns {number}
*/
get gamma()
{
return this._gamma;
}
/**
* Gamma coefficient (brightness control)
* @param {number} value
*/
set gamma(value)
{
this._gamma = +value;
}
/**
* Run the specific task of this node
* @param {SpeedyGPU} gpu
* @returns {void|SpeedyPromise<void>}
*/
_run(gpu)
{
const in0 = /** @type {SpeedyPipelineMessageWithImage} */ ( this.input('in0').read() );
const in1 = /** @type {SpeedyPipelineMessageWithImage} */ ( this.input('in1').read() );
const image0 = in0.image, image1 = in1.image;
const format0 = in0.format, format1 = in1.format;
const width = Math.max(image0.width, image1.width);
const height = Math.max(image0.height, image1.height);
const alpha = this._alpha, beta = this._beta, gamma = this._gamma;
const outputTexture = this._tex[0];
if(format0 != format1)
throw new NotSupportedError(`Can't mix images of different formats`);
gpu.programs.transforms.additiveMix.outputs(width, height, outputTexture);
gpu.programs.transforms.additiveMix(image0, image1, alpha, beta, gamma);
this.output().swrite(outputTexture, format0);
}
}