UNPKG

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)

297 lines 8.18 kB
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 { MemoryImageDataUint2 } from './image-data-uint2.js'; export class PixelUint2 { 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.uint2; } 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 bitsPerPixel() { return this._image.palette !== undefined ? 2 : this._image.numChannels << 1; } 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 PixelUint2(-1, 0, 0, -2, 0, image); } static image(image) { return new PixelUint2(-1, 0, 0, -2, 0, image.data instanceof MemoryImageDataUint2 ? image.data : new MemoryImageDataUint2(0, 0, 0)); } static from(other) { return new PixelUint2(other.x, other.y, other._index, other._bitIndex, other._rowOffset, other.image); } getChannelInternal(channel) { let i = this._index; let bi = 6 - (this._bitIndex + (channel << 1)); if (bi < 0) { bi += 8; i++; } return (this._image.data[i] >>> bi) & 0x3; } 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 += 2; if (this._bitIndex > 7) { this._bitIndex = 0; this._index++; } } else { const bpp = this.bitsPerPixel; this._bitIndex = (this._x * bpp) & 0x7; this._index = this._rowOffset + ((this._x * bpp) >>> 3); } return { done: this._index >= this.image.data.length, value: this, }; } setPosition(x, y) { this._x = x; this._y = y; const bpp = this.bitsPerPixel; 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.image.numChannels) { return; } let i = this._index; let bi = 6 - (this._bitIndex + (channel << 1)); if (bi < 0) { bi += 8; i++; } let v = this.data[i]; const vi = MathUtils.clampInt(value, 0, 3); const msk = [0xfc, 0xf3, 0xcf, 0x3f]; const mask = msk[bi >>> 1]; 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.image.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); } } } } } equals(other) { if (other instanceof PixelUint2) { return ArrayUtils.equals(this.toArray(), other.toArray()); } if (Array.isArray(other)) { return ArrayUtils.equals(this.toArray(), other); } return false; } toArray() { return ArrayUtils.generate(this.length, (i) => this.getChannel(i)); } clone() { return PixelUint2.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-uint2.js.map