image-in-browser
Version:
Package for encoding / decoding images, transforming images, applying filters, drawing primitives on images on the client side (no need for server Node.js)
300 lines • 8.2 kB
JavaScript
import { Channel } from '../color/channel.js';
import { ColorUtils } from '../color/color-utils.js';
import { Format } from '../color/format.js';
import { ArrayUtils } from '../common/array-utils.js';
import { MathUtils } from '../common/math-utils.js';
import { MemoryImageDataUint1 } from './image-data-uint1.js';
export class PixelUint1 {
get image() {
return this._image;
}
get x() {
return this._x;
}
get y() {
return this._y;
}
get xNormalized() {
return this.width > 1 ? this._x / (this.width - 1) : 0;
}
get yNormalized() {
return this.height > 1 ? this._y / (this.height - 1) : 0;
}
get index() {
return this.getChannelInternal(0);
}
set index(i) {
this.setChannel(0, i);
}
get data() {
return this._image.data;
}
get isValid() {
return (this._x >= 0 &&
this._x < this._image.width - 1 &&
this._y >= 0 &&
this._y < this._image.height - 1);
}
get width() {
return this._image.width;
}
get height() {
return this._image.height;
}
get length() {
var _a, _b;
return (_b = (_a = this.palette) === null || _a === void 0 ? void 0 : _a.numChannels) !== null && _b !== void 0 ? _b : this._image.numChannels;
}
get numChannels() {
return this._image.numChannels;
}
get maxChannelValue() {
return this._image.maxChannelValue;
}
get maxIndexValue() {
return this._image.maxIndexValue;
}
get format() {
return Format.uint1;
}
get isLdrFormat() {
return this._image.isLdrFormat;
}
get isHdrFormat() {
return this._image.isLdrFormat;
}
get hasPalette() {
return this._image.hasPalette;
}
get palette() {
return this._image.palette;
}
get r() {
return this.getChannel(0);
}
set r(r) {
this.setChannel(0, r);
}
get g() {
return this.getChannel(1);
}
set g(g) {
this.setChannel(1, g);
}
get b() {
return this.getChannel(2);
}
set b(b) {
this.setChannel(2, b);
}
get a() {
return this.getChannel(3);
}
set a(a) {
this.setChannel(3, a);
}
get rNormalized() {
return this.r / this.maxChannelValue;
}
set rNormalized(v) {
this.r = v * this.maxChannelValue;
}
get gNormalized() {
return this.g / this.maxChannelValue;
}
set gNormalized(v) {
this.g = v * this.maxChannelValue;
}
get bNormalized() {
return this.b / this.maxChannelValue;
}
set bNormalized(v) {
this.b = v * this.maxChannelValue;
}
get aNormalized() {
return this.a / this.maxChannelValue;
}
set aNormalized(v) {
this.a = v * this.maxChannelValue;
}
get luminance() {
return ColorUtils.getLuminance(this);
}
get luminanceNormalized() {
return ColorUtils.getLuminanceNormalized(this);
}
get imageLength() {
return this._image.length;
}
constructor(x, y, index, bitIndex, rowOffset, image) {
this._image = image;
this._index = index;
this._bitIndex = bitIndex;
this._rowOffset = rowOffset;
this._x = x;
this._y = y;
}
static imageData(image) {
return new PixelUint1(-1, 0, 0, -1, 0, image);
}
static image(image) {
return new PixelUint1(-1, 0, 0, -1, 0, image.data instanceof MemoryImageDataUint1
? image.data
: new MemoryImageDataUint1(0, 0, 0));
}
static from(other) {
return new PixelUint1(other.x, other.y, other._index, other._bitIndex, other._rowOffset, other.image);
}
getChannelInternal(channel) {
let i = this._index;
let bi = 7 - (this._bitIndex + channel);
if (bi < 0) {
bi += 8;
i++;
}
if (i >= this._image.data.length) {
return 0;
}
return (this._image.data[i] >>> bi) & 0x1;
}
next() {
this._x++;
if (this._x === this.width) {
this._x = 0;
this._y++;
this._bitIndex = 0;
this._index++;
this._rowOffset += this.image.rowStride;
return {
done: this._y >= this.height,
value: this,
};
}
const nc = this.numChannels;
if (this.palette !== undefined || nc === 1) {
this._bitIndex++;
if (this._bitIndex > 7) {
this._bitIndex = 0;
this._index++;
}
}
else {
const bpp = this.image.numChannels;
this._bitIndex = (this._x * bpp) & 0x7;
this._index = this._rowOffset + ((this._x * bpp) >>> 3);
}
return {
done: this._index >= this.imageLength,
value: this,
};
}
setPosition(x, y) {
this._x = x;
this._y = y;
const bpp = this._image.numChannels;
this._rowOffset = this._y * this._image.rowStride;
this._index = this._rowOffset + ((this._x * bpp) >>> 3);
this._bitIndex = (this._x * bpp) & 0x7;
}
setPositionNormalized(x, y) {
return this.setPosition(Math.floor(x * (this.width - 1)), Math.floor(y * (this.height - 1)));
}
getChannel(channel) {
if (this.palette !== undefined) {
return this.palette.get(this.getChannelInternal(0), channel);
}
else {
if (channel === Channel.luminance) {
return this.luminance;
}
else {
return channel < this.numChannels
? this.getChannelInternal(channel)
: 0;
}
}
}
getChannelNormalized(channel) {
return this.getChannel(channel) / this.maxChannelValue;
}
setChannel(channel, value) {
if (channel >= this.numChannels) {
return;
}
let i = this._index;
let bi = 7 - (this._bitIndex + channel);
if (bi < 0) {
bi += 8;
i++;
}
let v = this.data[i];
const vi = MathUtils.clampInt(value, 0, 1);
const msk = [0xfe, 0xfd, 0xfb, 0xf7, 0xef, 0xdf, 0xbf, 0x7f];
const mask = msk[bi];
v = (v & mask) | (vi << bi);
this.data[i] = v;
}
set(color) {
this.r = color.r;
this.g = color.g;
this.b = color.b;
this.a = color.a;
}
setRgb(r, g, b) {
const nc = this.image.numChannels;
if (nc > 0) {
this.setChannel(0, r);
if (nc > 1) {
this.setChannel(1, g);
if (nc > 2) {
this.setChannel(2, b);
}
}
}
}
setRgba(r, g, b, a) {
const nc = this.numChannels;
if (nc > 0) {
this.setChannel(0, r);
if (nc > 1) {
this.setChannel(1, g);
if (nc > 2) {
this.setChannel(2, b);
if (nc > 3) {
this.setChannel(3, a);
}
}
}
}
}
toArray() {
return ArrayUtils.generate(this.length, (i) => this.getChannel(i));
}
equals(other) {
if (other instanceof PixelUint1) {
return ArrayUtils.equals(this.toArray(), other.toArray());
}
if (Array.isArray(other)) {
return ArrayUtils.equals(this.toArray(), other);
}
return false;
}
clone() {
return PixelUint1.from(this);
}
convert(opt) {
return ColorUtils.convertColor({
from: this,
format: opt.format,
numChannels: opt.numChannels,
alpha: opt.alpha,
});
}
toString() {
return `${this.constructor.name} (${this.toArray()})`;
}
[Symbol.iterator]() {
return this;
}
}
//# sourceMappingURL=pixel-uint1.js.map