BitmapFilter abstract class
abstract class BitmapFilter {
BitmapFilter clone();
Rectangle get overlap;
void apply(BitmapData bitmapData, [Rectangle rectangle]);
//-----------------------------------------------------------------------------------------------
static var _buffer = new List<int>.filled(1024, 0);
//-----------------------------------------------------------------------------------------------
_premultiplyAlpha(List<int> data) {
if (_isLittleEndianSystem) {
for(int i = 0; i <= data.length - 4; i += 4) {
int alpha = data[i + 3];
data[i + 0] = (data[i + 0] * alpha) ~/ 255;
data[i + 1] = (data[i + 1] * alpha) ~/ 255;
data[i + 2] = (data[i + 2] * alpha) ~/ 255;
}
} else {
for(int i = 0; i <= data.length - 4; i += 4) {
int alpha = data[i + 0];
data[i + 1] = (data[i + 1] * alpha) ~/ 255;
data[i + 2] = (data[i + 2] * alpha) ~/ 255;
data[i + 3] = (data[i + 3] * alpha) ~/ 255;
}
}
}
//-----------------------------------------------------------------------------------------------
_unpremultiplyAlpha(List<int> data) {
if (_isLittleEndianSystem) {
for(int i = 0; i <= data.length - 4; i += 4) {
int alpha = data[i + 3];
if (alpha > 0) {
data[i + 0] = (data[i + 0] * 255) ~/ alpha;
data[i + 1] = (data[i + 1] * 255) ~/ alpha;
data[i + 2] = (data[i + 2] * 255) ~/ alpha;
}
}
} else {
for(int i = 0; i <= data.length - 4; i += 4) {
int alpha = data[i + 0];
if (alpha > 0) {
data[i + 1] = (data[i + 1] * 255) ~/ alpha;
data[i + 2] = (data[i + 2] * 255) ~/ alpha;
data[i + 3] = (data[i + 3] * 255) ~/ alpha;
}
}
}
}
//-----------------------------------------------------------------------------------------------
_clearChannel(List<int> data, int offset, int length) {
int offsetStart = offset;
int offsetEnd = offset + length * 4 - 4;
if (offsetStart < 0) throw new RangeError(offsetStart);
if (offsetEnd >= data.length) throw new RangeError(offsetEnd);
for(int i = offsetStart; i <= offsetEnd; i += 4) {
data[i] = 0;
}
}
//-----------------------------------------------------------------------------------------------
_shiftChannel(List<int> data, int channel, int width, int height, int shiftX, int shiftY) {
if (channel < 0) throw new ArgumentError();
if (channel > 3) throw new ArgumentError();
if (shiftX == 0 && shiftY == 0) return;
if (shiftX.abs() >= width || shiftY.abs() >= height) {
_clearChannel(data, channel, width * height);
return;
}
if (shiftX + width * shiftY < 0) {
int dst = channel;
int src = channel - 4 * (shiftX + width * shiftY);
for(; src < data.length; src += 4, dst += 4) data[dst] = data[src];
} else {
int dst = data.length + channel - 4;
int src = data.length + channel - 4 * (shiftX + width * shiftY);
for(; src >= 0; src -= 4, dst -= 4) data[dst] = data[src];
}
for(int y = 0; y < height; y++) {
if (y < shiftY || y >= height + shiftY) {
_clearChannel(data, (y * width) * 4 + channel, width);
} else if (shiftX > 0) {
_clearChannel(data, (y * width) * 4 + channel, shiftX);
} else if (shiftX < 0) {
_clearChannel(data, (y * width + width + shiftX) * 4 + channel, 0 - shiftX);
}
}
}
//-----------------------------------------------------------------------------------------------
_blur2(List<int> data, int offset, int length, int stride, int radius) {
int weight = radius * radius;
int weightInv = (1 << 22) ~/ weight;
int sum = weight ~/ 2;
int dif = 0;
int offsetSource = offset;
int offsetDestination = offset;
int radius1 = radius * 1;
int radius2 = radius * 2;
List<int> buffer = _buffer;
for (int i = 0; i < length + radius1; i++) {
if (i >= radius1) {
data[offsetDestination] = ((sum * weightInv) | 0) >> 22;
offsetDestination += stride;
if (i >= radius2) {
dif -= 2 * buffer[i & 1023] - buffer[(i - radius1) & 1023];
} else {
dif -= 2 * buffer[i & 1023];
}
}
if (i < length) {
int value = data[offsetSource];
offsetSource += stride;
buffer[(i + radius1) & 1023] = value;
sum += dif += value;
} else {
buffer[(i + radius1) & 1023] = 0;
sum += dif;
}
}
}
//-----------------------------------------------------------------------------------------------
_setColor(List<int> data, int color, num alpha) {
int rColor = _colorGetR(color);
int gColor = _colorGetG(color);
int bColor = _colorGetB(color);
int alpha256 = (alpha * 256).toInt();
if (_isLittleEndianSystem) {
for(var i = 0; i <= data.length - 4; i += 4) {
data[i + 0] = rColor;
data[i + 1] = gColor;
data[i + 2] = bColor;
data[i + 3] = (data[i + 3] * alpha256 | 0) >> 8;
}
} else {
for(var i = 0; i <= data.length - 4; i += 4) {
data[i + 0] = (data[i + 0] * alpha256 | 0) >> 8;
data[i + 1] = bColor;
data[i + 2] = gColor;
data[i + 3] = rColor;
}
}
}
//-----------------------------------------------------------------------------------------------
_blend(List<int> dstData, List<int> srcData) {
if (dstData.length != srcData.length) return;
if (_isLittleEndianSystem) {
for(int i = 0; i <= dstData.length - 4; i += 4) {
int srcA = srcData[i + 3];
int dstA = dstData[i + 3];
int srcAX = srcA * 255;
int dstAX = dstA * (255 - srcA);
int outAX = srcAX + dstAX;
if (outAX > 0) {
dstData[i + 0] = (srcData[i + 0] * srcAX + dstData[i + 0] * dstAX) ~/ outAX;
dstData[i + 1] = (srcData[i + 1] * srcAX + dstData[i + 1] * dstAX) ~/ outAX;
dstData[i + 2] = (srcData[i + 2] * srcAX + dstData[i + 2] * dstAX) ~/ outAX;
dstData[i + 3] = outAX ~/ 255;
}
}
} else {
for(int i = 0; i <= dstData.length - 4; i += 4) {
int srcA = srcData[i + 0];
int dstA = dstData[i + 0];
int srcAX = srcA * 255;
int dstAX = dstA * (255 - srcA);
int outAX = srcAX + dstAX;
if (outAX > 0) {
dstData[i + 0] = outAX ~/ 255;
dstData[i + 1] = (srcData[i + 1] * srcAX + dstData[i + 1] * dstAX) ~/ outAX;
dstData[i + 2] = (srcData[i + 2] * srcAX + dstData[i + 2] * dstAX) ~/ outAX;
dstData[i + 3] = (srcData[i + 3] * srcAX + dstData[i + 3] * dstAX) ~/ outAX;
}
}
}
}
//-----------------------------------------------------------------------------------------------
_knockout(List<int> dstData, List<int> srcData) {
if (dstData.length != srcData.length) return;
if (_isLittleEndianSystem) {
for(int i = 0; i <= dstData.length - 4; i += 4) {
dstData[i + 3] = dstData[i + 3] * (255 - srcData[i + 3]) ~/ 255;
}
} else {
for(int i = 0; i <= dstData.length - 4; i += 4) {
dstData[i + 0] = dstData[i + 0] * (255 - srcData[i + 0]) ~/ 255;
}
}
}
//-----------------------------------------------------------------------------------------------
_setColorBlend(List<int> dstData, int color, num alpha, List<int> srcData) {
// optimized version for:
// _setColor(data, this.color, this.alpha);
// _blend(data, sourceImageData.data);
if (dstData.length != srcData.length) return;
int rColor = _colorGetR(color);
int gColor = _colorGetG(color);
int bColor = _colorGetB(color);
int alpha256 = (alpha * 256).toInt();
if (_isLittleEndianSystem) {
for(int i = 0; i <= dstData.length - 4; i += 4) {
int srcA = srcData[i + 3];
int dstA = dstData[i + 3];
int srcAX = (srcA * 255);
int dstAX = (dstA * (255 - srcA) * alpha256 | 0) >> 8;
int outAX = (srcAX + dstAX);
if (outAX > 0) {
dstData[i + 0] = (srcData[i + 0] * srcAX + rColor * dstAX) ~/ outAX;
dstData[i + 1] = (srcData[i + 1] * srcAX + gColor * dstAX) ~/ outAX;
dstData[i + 2] = (srcData[i + 2] * srcAX + bColor * dstAX) ~/ outAX;
dstData[i + 3] = outAX ~/ 255;
} else {
dstData[i + 3] = 0;
}
}
} else {
for(int i = 0; i <= dstData.length - 4; i += 4) {
int srcA = srcData[i + 0];
int dstA = dstData[i + 0];
int srcAX = (srcA * 255);
int dstAX = (dstA * (255 - srcA) * alpha256 | 0) >> 8;
int outAX = (srcAX + dstAX);
if (outAX > 0) {
dstData[i + 0] = outAX ~/ 255;
dstData[i + 1] = (srcData[i + 1] * srcAX + bColor * dstAX) ~/ outAX;
dstData[i + 2] = (srcData[i + 2] * srcAX + gColor * dstAX) ~/ outAX;
dstData[i + 3] = (srcData[i + 3] * srcAX + rColor * dstAX) ~/ outAX;
} else {
dstData[i + 0] = 0;
}
}
}
}
//-----------------------------------------------------------------------------------------------
_setColorKnockout(List<int> dstData, int color, num alpha, List<int> srcData) {
// optimized version for:
// _setColor(data, this.color, this.alpha);
// _knockout(data, sourceImageData.data);
if (dstData.length != srcData.length) return;
int rColor = _colorGetR(color);
int gColor = _colorGetG(color);
int bColor = _colorGetB(color);
int alpha256 = (alpha * 256).toInt();
if (_isLittleEndianSystem) {
for(var i = 0; i <= dstData.length - 4; i += 4) {
dstData[i + 0] = rColor;
dstData[i + 1] = gColor;
dstData[i + 2] = bColor;
dstData[i + 3] = (alpha256 * dstData[i + 3] * (255 - srcData[i + 3]) | 0) ~/ (255 * 256);
}
} else {
for(var i = 0; i <= dstData.length - 4; i += 4) {
dstData[i + 0] = (alpha256 * dstData[i + 0] * (255 - srcData[i + 0]) | 0) ~/ (255 * 256);
dstData[i + 1] = bColor;
dstData[i + 2] = gColor;
dstData[i + 3] = rColor;
}
}
}
}
Subclasses
AlphaMaskFilter, BlurFilter, ColorMatrixFilter, DropShadowFilter, GlowFilter