pixelBufferToPng function

Future<Uint8List> pixelBufferToPng(
  1. Uint8List pixelBuffer,
  2. int width,
  3. int height, {
  4. bool hasAlpha = true,
  5. bool isFloat = false,
  6. bool linearToSrgb = false,
  7. bool invertAces = false,
  8. bool flipY = false,
})

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);
}