Save ColorFiltered image to disk

Viewed 144

In Flutter, if we use the ColorFilter widget, it takes a ColorFilter.matrix and an Image, on which it applies the ColorFilter.matrix.

const ColorFilter sepia = ColorFilter.matrix(<double>[
  0.393, 0.769, 0.189, 0, 0,
  0.349, 0.686, 0.168, 0, 0,
  0.272, 0.534, 0.131, 0, 0,
  0,     0,     0,     1, 0,
]);

Container _buildFilterThumbnail(int index, Size size) {
final Image image = Image.file(
  widget.imageFile,
  width: size.width,
  fit: BoxFit.cover,
);

return Container(
  padding: const EdgeInsets.all(4.0),
  decoration: BoxDecoration(
    border: Border.all(color: _selectedIndex == index ? Colors.blue : Theme.of(context).primaryColor, width: 4.0),
  ),
  child: ColorFiltered(
    colorFilter: ColorFilter.matrix(filters[index].matrixValues),
    child: Container(
      height: 80,
      width: 80,
      child: image,
    ),
  ),
);
}

How can we get the underlying image (in pixels/bytes) so that it can be saved on disk. I don't want to save the rendered ColorFiltered area on the screen.

Curretly am forced to use the photofilters library from pub.dev, which does the pixel manipulation to apply the custom filters. However, its not very efficient and essentially applies the pixel level manipulation for every thumbnail, making it very slow. On the other hand, ColorFiltered widget is lightening fast!

Below is internal working of photofilters library

int clampPixel(int x) => x.clamp(0, 255);

// ColorOverlay - add a slight color overlay.
void colorOverlay(Uint8List bytes, num red, num green, num blue, num scale) {
  for (int i = 0; i < bytes.length; i += 4) {
    bytes[i] = clampPixel((bytes[i] - (bytes[i] - red) * scale).round());
    bytes[i + 1] =
        clampPixel((bytes[i + 1] - (bytes[i + 1] - green) * scale).round());
    bytes[i + 2] =
        clampPixel((bytes[i + 2] - (bytes[i + 2] - blue) * scale).round());
  }
}

// RGB Scale
void rgbScale(Uint8List bytes, num red, num green, num blue) {
  for (int i = 0; i < bytes.length; i += 4) {
    bytes[i] = clampPixel((bytes[i] * red).round());
    bytes[i + 1] = clampPixel((bytes[i + 1] * green).round());
    bytes[i + 2] = clampPixel((bytes[i + 2] * blue).round());
  }
}

Any pointers appreciated.

0 Answers
Related