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)
131 lines • 5.34 kB
JavaScript
import { InputBuffer } from '../../common/input-buffer.js';
export class WebPFilters {
static predictLine(src, pred, dst, length, inverse) {
if (inverse) {
for (let i = 0; i < length; ++i)
dst.set(i, src.get(i) + pred.get(i));
}
else {
for (let i = 0; i < length; ++i)
dst.set(i, src.get(i) - pred.get(i));
}
}
static doHorizontalFilter(src, width, _height, stride, row, numRows, inverse, _out) {
let _row = row;
const startOffset = _row * stride;
const lastRow = _row + numRows;
const s = new InputBuffer({ buffer: src, offset: startOffset });
const o = new InputBuffer({ buffer: src, offset: startOffset });
const preds = InputBuffer.from(inverse ? o : s);
if (_row === 0) {
o.set(0, s.get(0));
this.predictLine(InputBuffer.from(s, 1), preds, InputBuffer.from(o, 1), width - 1, inverse);
_row = 1;
preds.offset += stride;
s.offset += stride;
o.offset += stride;
}
while (_row < lastRow) {
this.predictLine(s, InputBuffer.from(preds, -stride), o, 1, inverse);
this.predictLine(InputBuffer.from(s, 1), preds, InputBuffer.from(o, 1), width - 1, inverse);
++_row;
preds.offset += stride;
s.offset += stride;
o.offset += stride;
}
}
static doVerticalFilter(src, width, _height, stride, row, numRows, inverse, out) {
let _row = row;
const startOffset = _row * stride;
const lastRow = _row + numRows;
const s = new InputBuffer({ buffer: src, offset: startOffset });
const o = new InputBuffer({ buffer: out, offset: startOffset });
const preds = InputBuffer.from(inverse ? o : s);
if (_row === 0) {
o.set(0, s.get(0));
this.predictLine(InputBuffer.from(s, 1), preds, InputBuffer.from(o, 1), width - 1, inverse);
_row = 1;
s.offset += stride;
o.offset += stride;
}
else {
preds.offset -= stride;
}
while (_row < lastRow) {
this.predictLine(s, preds, o, width, inverse);
++_row;
preds.offset += stride;
s.offset += stride;
o.offset += stride;
}
}
static gradientPredictor(a, b, c) {
const g = a + b - c;
return (g & ~0xff) === 0 ? g : g < 0 ? 0 : 255;
}
static doGradientFilter(src, width, _height, stride, row, numRows, inverse, out) {
let _row = row;
const startOffset = _row * stride;
const lastRow = _row + numRows;
const s = new InputBuffer({ buffer: src, offset: startOffset });
const o = new InputBuffer({ buffer: out, offset: startOffset });
const preds = InputBuffer.from(inverse ? o : s);
if (_row === 0) {
o.set(0, s.get(0));
this.predictLine(InputBuffer.from(s, 1), preds, InputBuffer.from(o, 1), width - 1, inverse);
_row = 1;
preds.offset += stride;
s.offset += stride;
o.offset += stride;
}
while (_row < lastRow) {
this.predictLine(s, InputBuffer.from(preds, -stride), o, 1, inverse);
for (let w = 1; w < width; ++w) {
const pred = this.gradientPredictor(preds.get(w - 1), preds.get(w - stride), preds.get(w - stride - 1));
o.set(w, s.get(w) + (inverse ? pred : -pred));
}
++_row;
preds.offset += stride;
s.offset += stride;
o.offset += stride;
}
}
static horizontalFilter(data, width, height, stride, filteredData) {
WebPFilters.doHorizontalFilter(data, width, height, stride, 0, height, false, filteredData);
}
static horizontalUnfilter(width, height, stride, row, numRows, data) {
WebPFilters.doHorizontalFilter(data, width, height, stride, row, numRows, true, data);
}
static verticalFilter(data, width, height, stride, filteredData) {
WebPFilters.doVerticalFilter(data, width, height, stride, 0, height, false, filteredData);
}
static verticalUnfilter(width, height, stride, row, numRows, data) {
WebPFilters.doVerticalFilter(data, width, height, stride, row, numRows, true, data);
}
static gradientFilter(data, width, height, stride, filteredData) {
WebPFilters.doGradientFilter(data, width, height, stride, 0, height, false, filteredData);
}
static gradientUnfilter(width, height, stride, row, numRows, data) {
WebPFilters.doGradientFilter(data, width, height, stride, row, numRows, true, data);
}
}
WebPFilters.filterNone = 0;
WebPFilters.filterHorizontal = 1;
WebPFilters.filterVertical = 2;
WebPFilters.filterGradient = 3;
WebPFilters.filterLast = WebPFilters.filterGradient + 1;
WebPFilters.filterBest = 5;
WebPFilters.filterFast = 6;
WebPFilters.filters = [
undefined,
WebPFilters.horizontalFilter,
WebPFilters.verticalFilter,
WebPFilters.gradientFilter,
];
WebPFilters.unfilters = [
undefined,
WebPFilters.horizontalUnfilter,
WebPFilters.verticalUnfilter,
WebPFilters.gradientUnfilter,
];
//# sourceMappingURL=webp-filters.js.map