blob: 1b8bd5d33ce27e1b6f65f2e7b8cb5d111dadff0f [file] [log] [blame]
import 'dart:math';
import 'dart:typed_data';
import 'hdr_image.dart';
/// Applies an HDR bloom filter to the image, in-place.
HdrImage hdrBloom(HdrImage hdr, {double radius = 0.01, double weight = 0.1}) {
double _lerp(double t, double a, double b) => (1.0 - t) * a + t * b;
//int nPix = xResolution * yResolution;
// Possibly apply bloom effect to image
if (radius > 0.0 && weight > 0.0) {
// Compute image-space extent of bloom effect
int bloomSupport = (radius * max(hdr.width, hdr.height)).ceil();
int bloomWidth = bloomSupport ~/ 2;
// Initialize bloom filter table
Float32List bloomFilter = Float32List(bloomWidth * bloomWidth);
for (int i = 0; i < bloomWidth * bloomWidth; ++i) {
double dist = sqrt(i / bloomWidth);
bloomFilter[i] = pow(max(0.0, 1.0 - dist), 4.0).toDouble();
}
// Apply bloom filter to image pixels
Float32List bloomImage = Float32List(3 * hdr.width * hdr.height);
for (int y = 0, offset = 0; y < hdr.height; ++y) {
for (int x = 0; x < hdr.width; ++x, ++offset) {
// Compute bloom for pixel _(x,y)_
// Compute extent of pixels contributing bloom
int x0 = max(0, x - bloomWidth);
int x1 = min(x + bloomWidth, hdr.width - 1);
int y0 = max(0, y - bloomWidth);
int y1 = min(y + bloomWidth, hdr.height - 1);
double sumWt = 0.0;
for (int by = y0; by <= y1; ++by) {
for (int bx = x0; bx <= x1; ++bx) {
// Accumulate bloom from pixel $(bx,by)$
int dx = x - bx;
int dy = y - by;
if (dx == 0 && dy == 0) {
continue;
}
int dist2 = dx * dx + dy * dy;
if (dist2 < bloomWidth * bloomWidth) {
//int bloomOffset = bx + by * hdr.width;
double wt = bloomFilter[dist2];
sumWt += wt;
bloomImage[3 * offset] += wt * hdr.getRed(bx, by);
bloomImage[3 * offset + 1] += wt * hdr.getGreen(bx, by);
bloomImage[3 * offset + 2] += wt * hdr.getBlue(bx, by);
}
}
}
bloomImage[3 * offset] /= sumWt;
bloomImage[3 * offset + 1] /= sumWt;
bloomImage[3 * offset + 2] /= sumWt;
}
}
// Mix bloom effect into each pixel
for (int y = 0, offset = 0; y < hdr.height; ++y) {
for (int x = 0; x < hdr.width; ++x, offset += 3) {
hdr.setRed(x, y, _lerp(weight, hdr.getRed(x, y), bloomImage[offset]));
hdr.setGreen(
x, y, _lerp(weight, hdr.getGreen(x, y), bloomImage[offset + 1]));
hdr.setBlue(
x, y, _lerp(weight, hdr.getBlue(x, y), bloomImage[offset + 2]));
}
}
}
return hdr;
}