pixelBufferToPng function
Implementation
Future<Uint8List> pixelBufferToPng(Uint8List pixelBuffer, int width, int height,
{bool hasAlpha = true,
bool isFloat = false,
bool linearToSrgb = false,
bool invertAces = false,
bool flipY = false}) async {
final image = img.Image(width: width, height: height);
Float32List? floatData;
if (isFloat) {
floatData = pixelBuffer.buffer.asFloat32List(
pixelBuffer.offsetInBytes, width * height * (hasAlpha ? 4 : 3));
}
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
late int pixelIndex;
if (flipY) {
pixelIndex = ((height - 1 - y) * width + x) * (hasAlpha ? 4 : 3);
} else {
pixelIndex = (y * width + x) * (hasAlpha ? 4 : 3);
}
double r, g, b, a;
if (isFloat) {
r = floatData![pixelIndex];
g = floatData[pixelIndex + 1];
b = floatData[pixelIndex + 2];
a = hasAlpha ? floatData[pixelIndex + 3] : 1.0;
} else {
r = pixelBuffer[pixelIndex] / 255.0;
g = pixelBuffer[pixelIndex + 1] / 255.0;
b = pixelBuffer[pixelIndex + 2] / 255.0;
a = hasAlpha ? pixelBuffer[pixelIndex + 3] / 255.0 : 1.0;
}
r = r.clamp(0, 1);
g = g.clamp(0, 1);
b = b.clamp(0, 1);
a = a.clamp(0, 1);
// Apply inverse ACES tone mapping
if (invertAces) {
r = _inverseACESToneMapping(r);
g = _inverseACESToneMapping(g);
b = _inverseACESToneMapping(b);
}
if (linearToSrgb) {
// Convert from linear to sRGB
image.setPixel(
x,
y,
img.ColorUint8(4)
..setRgba(
_linearToSRGB(r), _linearToSRGB(g), _linearToSRGB(b), a));
} else {
image.setPixel(
x,
y,
img.ColorUint8(4)
..setRgba((r * 255).toInt(), (g * 255).toInt(), (b * 255).toInt(),
(a * 255).toInt()));
}
}
}
return img.encodePng(image);
}