bitmap 0.3.0 copy "bitmap: ^0.3.0" to clipboard
bitmap: ^0.3.0 copied to clipboard

Bitmap is a fast and minimalistic lib that helps you to manipulate images in.

example/lib/main.dart

import 'dart:async';

import 'package:bitmap/bitmap_flutter.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';

void main() => runApp(const MyApp());

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Image',
      theme: ThemeData(
        primarySwatch: Colors.orange,
      ),
      home: const MyHomePage(
        title: 'Pans',
      ),
    );
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({
    super.key,
    required this.title,
  });

  final String title;

  @override
  void debugFillProperties(DiagnosticPropertiesBuilder properties) {
    super.debugFillProperties(properties);
    properties.add(StringProperty('title', title));
  }

  @override
  MyHomePageState createState() => MyHomePageState();
}

class MyHomePageState extends State<MyHomePage> {
  ImageValueNotifier imageValueNotifier = ImageValueNotifier();

  @override
  void initState() {
    super.initState();
    imageValueNotifier.loadImage();
  }

  void flipHImage() {
    if (imageValueNotifier.value != null) {
      imageValueNotifier.flipHImage();
    }
  }

  void flipVImage() {
    if (imageValueNotifier.value != null) {
      imageValueNotifier.flipVImage();
    }
  }

  void rotateClockwiseImage() {
    if (imageValueNotifier.value != null) {
      imageValueNotifier.rotateClockwiseImage();
    }
  }

  void rotateCounterClockwiseImage() {
    if (imageValueNotifier.value != null) {
      imageValueNotifier.rotateCounterClockwiseImage();
    }
  }

  void rotate180Image() {
    if (imageValueNotifier.value != null) {
      imageValueNotifier.rotate180Image();
    }
  }

  void contrastImage() {
    if (imageValueNotifier.value != null) {
      imageValueNotifier.contrastImage();
    }
  }

  void brightnessImage() {
    if (imageValueNotifier.value != null) {
      imageValueNotifier.brightnessImage();
    }
  }

  void adjustColorImage() {
    if (imageValueNotifier.value != null) {
      imageValueNotifier.adjustColorImage();
    }
  }

  void batchOperations() {
    if (imageValueNotifier.value != null) {
      imageValueNotifier.batchOperations();
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: GestureDetector(
        onTap: () {
          imageValueNotifier.reset();
        },
        child: Center(
          child: ValueListenableBuilder<Bitmap?>(
            valueListenable: imageValueNotifier,
            builder: (BuildContext context, Bitmap? bitmap, Widget? child) {
              if (bitmap == null) {
                return const CircularProgressIndicator();
              }
              return Column(
                children: <Widget>[
                  SafeArea(
                    child: Image.memory(
                      bitmap.buildHeaded(),
                    ),
                  ),
                  const Text('Tap image to reset'),
                  Text('ImageSize ${bitmap.width}'),
                ],
              );
            },
          ),
        ),
      ),
      floatingActionButton: Buttons(
        flipHImage: flipHImage,
        flipVImage: flipVImage,
        rotateClockwiseImage: rotateClockwiseImage,
        rotateCounterClockwiseImage: rotateCounterClockwiseImage,
        rotate180Image: rotate180Image,
        contrastImage: contrastImage,
        brightnessImage: brightnessImage,
        adjustColorImage: adjustColorImage,
        batchOperations: batchOperations,
      ), // This trailing comma makes auto-formatting nicer for build methods.
    );
  }

  @override
  void debugFillProperties(DiagnosticPropertiesBuilder properties) {
    super.debugFillProperties(properties);
    properties.add(
      DiagnosticsProperty<ImageValueNotifier>(
        'imageValueNotifier',
        imageValueNotifier,
      ),
    );
  }
}

class Buttons extends StatelessWidget {
  const Buttons({
    super.key,
    required this.flipHImage,
    required this.flipVImage,
    required this.rotateClockwiseImage,
    required this.rotateCounterClockwiseImage,
    required this.rotate180Image,
    required this.contrastImage,
    required this.brightnessImage,
    required this.adjustColorImage,
    required this.batchOperations,
  });

  final VoidCallback flipHImage;
  final VoidCallback flipVImage;
  final VoidCallback rotateClockwiseImage;
  final VoidCallback rotateCounterClockwiseImage;
  final VoidCallback rotate180Image;
  final VoidCallback contrastImage;
  final VoidCallback brightnessImage;
  final VoidCallback adjustColorImage;
  final VoidCallback batchOperations;

  @override
  Widget build(BuildContext context) {
    return Container(
      padding: const EdgeInsets.symmetric(horizontal: 20),
      child: Column(
        mainAxisAlignment: MainAxisAlignment.end,
        children: <Widget>[
          Row(
            children: <Widget>[
              TextButton(
                onPressed: flipHImage,
                child: const Text(
                  'Flip horizontal',
                  style: TextStyle(fontSize: 10),
                ),
              ),
              TextButton(
                onPressed: flipVImage,
                child: const Text(
                  'Flip vertical',
                  style: TextStyle(fontSize: 10),
                ),
              ),
              TextButton(
                onPressed: contrastImage,
                child: const Text(
                  'Contrast +',
                  style: TextStyle(fontSize: 10),
                ),
              ),
            ],
          ),
          Row(
            children: <Widget>[
              TextButton(
                onPressed: brightnessImage,
                child: const Text(
                  'Brightness +',
                  style: TextStyle(fontSize: 10),
                ),
              ),
              TextButton(
                onPressed: adjustColorImage,
                child: const Text(
                  'AdjustColor +',
                  style: TextStyle(fontSize: 10),
                ),
              ),
            ],
          ),
          Row(
            children: <Widget>[
              TextButton(
                onPressed: rotateClockwiseImage,
                child: const Text(
                  'Rotate Clock +',
                  style: TextStyle(fontSize: 10),
                ),
              ),
              TextButton(
                onPressed: rotateCounterClockwiseImage,
                child: const Text(
                  'Rotate Clock -',
                  style: TextStyle(fontSize: 10),
                ),
              ),
              TextButton(
                onPressed: rotate180Image,
                child: const Text(
                  'Rotate 180',
                  style: TextStyle(fontSize: 10),
                ),
              ),
            ],
          ),
          Row(
            children: <Widget>[
              TextButton(
                onPressed: batchOperations,
                child: const Text(
                  'Batch operations (saturation + crop)',
                  style: TextStyle(fontSize: 10),
                ),
              ),
            ],
          ),
        ],
      ),
    );
  }

  @override
  void debugFillProperties(DiagnosticPropertiesBuilder properties) {
    super.debugFillProperties(properties);
    properties
        ..add(ObjectFlagProperty<VoidCallback>.has('flipHImage', flipHImage))
    
        ..add(ObjectFlagProperty<VoidCallback>.has('flipVImage', flipVImage))
    ..add(
      ObjectFlagProperty<VoidCallback>.has(
        'rotateClockwiseImage',
        rotateClockwiseImage,
      ),
    )
    ..add(
      ObjectFlagProperty<VoidCallback>.has(
        'rotateCounterClockwiseImage',
        rotateCounterClockwiseImage,
      ),
    )
      ..add(
      ObjectFlagProperty<VoidCallback>.has('rotate180Image', rotate180Image),
    )
    ..add(
      ObjectFlagProperty<VoidCallback>.has('contrastImage', contrastImage),
    )
    ..add(
      ObjectFlagProperty<VoidCallback>.has(
        'brightnessImage',
        brightnessImage,
      ),
    )
    ..add(
      ObjectFlagProperty<VoidCallback>.has(
        'adjustColorImage',
        adjustColorImage,
      ),
    )
    ..add(
      ObjectFlagProperty<VoidCallback>.has(
        'batchOperations',
        batchOperations,
      ),
    );
  }
}

// stores headless contents
class ImageValueNotifier extends ValueNotifier<Bitmap?> {
  ImageValueNotifier() : super(null);

  late Bitmap initial;

  void reset() {
    value = initial;
  }

  Future<void> loadImage() async {
    const ImageProvider imageProvider = AssetImage('assets/street.jpg');

    value = await Bitmap.fromProvider(imageProvider);
    initial = value!;
  }

  Future<void> flipHImage() async {
    final temp = value!;
    value = null;

    final converted = await compute(
      flipHImageIsolate,
      [temp.content, temp.width, temp.height],
    );

    value = Bitmap.fromHeadless(temp.width, temp.height, converted);
  }

  Future<void> flipVImage() async {
    final temp = value!;
    value = null;

    final converted = await compute(
      flipVImageIsolate,
      [temp.content, temp.width, temp.height],
    );

    value = Bitmap.fromHeadless(temp.width, temp.height, converted);
  }

  Future<void> rotateClockwiseImage() async {
    final temp = value!;
    value = null;

    final converted = await compute(
      rotateClockwiseImageIsolate,
      [temp.content, temp.width, temp.height],
    );

    value = Bitmap.fromHeadless(temp.height, temp.width, converted);
  }

  Future<void> rotateCounterClockwiseImage() async {
    final temp = value!;
    value = null;

    final converted = await compute(
      rotateCounterClockwiseImageIsolate,
      [temp.content, temp.width, temp.height],
    );

    value = Bitmap.fromHeadless(temp.height, temp.width, converted);
  }

  Future<void> rotate180Image() async {
    final temp = value!;
    value = null;

    final converted = await compute(
      rotate180ImageIsolate,
      [temp.content, temp.width, temp.height],
    );

    value = Bitmap.fromHeadless(temp.width, temp.height, converted);
  }

  Future<void> contrastImage() async {
    final temp = value!;
    value = null;

    final converted = await compute(
      contrastImageIsolate,
      [temp.content, temp.width, temp.height],
    );

    value = Bitmap.fromHeadless(temp.width, temp.height, converted);
  }

  Future<void> brightnessImage() async {
    final temp = value!;
    value = null;

    final converted = await compute(
      brightnessImageIsolate,
      [temp.content, temp.width, temp.height],
    );

    value = Bitmap.fromHeadless(temp.width, temp.height, converted);
  }

  Future<void> adjustColorImage() async {
    final temp = value!;
    value = null;

    final converted = await compute(
      adjustColorsImageIsolate,
      [temp.content, temp.width, temp.height],
    );

    value = Bitmap.fromHeadless(temp.width, temp.height, converted);
  }

  Future<void> batchOperations() async {
    final temp = value!;
    value = null;

    final converted = await compute(
      batchOperationsImageIsolate,
      [temp.content, temp.width, temp.height],
    );

    value = Bitmap.fromHeadless(temp.width - 20, temp.height - 20, converted);
  }
}

Future<Uint8List> flipHImageIsolate(List<dynamic> imageData) async {
  final byteData = imageData[0] as Uint8List;
  final width = imageData[1] as int;
  final height = imageData[2] as int;

  final bigBitmap = Bitmap.fromHeadless(width, height, byteData);
  final returnBitmap = bigBitmap.apply(BitmapFlip.horizontal());

  return returnBitmap.content;
}

Future<Uint8List> flipVImageIsolate(List<dynamic> imageData) async {
  final byteData = imageData[0] as Uint8List;
  final width = imageData[1] as int;
  final height = imageData[2] as int;

  final bigBitmap = Bitmap.fromHeadless(width, height, byteData);

  final returnBitmap = bigBitmap.apply(BitmapFlip.vertical());

  return returnBitmap.content;
}

Future<Uint8List> rotateClockwiseImageIsolate(List<dynamic> imageData) async {
  final byteData = imageData[0] as Uint8List;
  final width = imageData[1] as int;
  final height = imageData[2] as int;

  final bigBitmap = Bitmap.fromHeadless(width, height, byteData);

  final returnBitmap = bigBitmap.apply(BitmapRotate.rotateClockwise());

  return returnBitmap.content;
}

Future<Uint8List> rotateCounterClockwiseImageIsolate(
  List<dynamic> imageData,
) async {
  final byteData = imageData[0] as Uint8List;
  final width = imageData[1] as int;
  final height = imageData[2] as int;

  final bigBitmap = Bitmap.fromHeadless(width, height, byteData);

  final returnBitmap = bigBitmap.apply(BitmapRotate.rotateCounterClockwise());

  return returnBitmap.content;
}

Future<Uint8List> rotate180ImageIsolate(List<dynamic> imageData) async {
  final byteData = imageData[0] as Uint8List;
  final width = imageData[1] as int;
  final height = imageData[2] as int;

  final bigBitmap = Bitmap.fromHeadless(width, height, byteData);

  final returnBitmap = bigBitmap.apply(BitmapRotate.rotate180());

  return returnBitmap.content;
}

Future<Uint8List> contrastImageIsolate(List<dynamic> imageData) async {
  final byteData = imageData[0] as Uint8List;
  final width = imageData[1] as int;
  final height = imageData[2] as int;

  final bigBitmap = Bitmap.fromHeadless(width, height, byteData);

  final returnBitmap = bigBitmap.apply(BitmapContrast(1.2));

  return returnBitmap.content;
}

Future<Uint8List> brightnessImageIsolate(List<dynamic> imageData) async {
  final byteData = imageData[0] as Uint8List;
  final width = imageData[1] as int;
  final height = imageData[2] as int;

  final bigBitmap = Bitmap.fromHeadless(width, height, byteData);

  final returnBitmap = bigBitmap.apply(BitmapBrightness(0.1));

  return returnBitmap.content;
}

Future<Uint8List> adjustColorsImageIsolate(List<dynamic> imageData) async {
  final byteData = imageData[0] as Uint8List;
  final width = imageData[1] as int;
  final height = imageData[2] as int;

  final bigBitmap = Bitmap.fromHeadless(width, height, byteData);

  final returnBitmap = bigBitmap.apply(
    BitmapAdjustColor(
      blacks: 0x00000000,
      saturation: 1.9, // 0 and 5 mid 1.0
    ),
  );

  return returnBitmap.content;
}

Future<Uint8List> batchOperationsImageIsolate(List<dynamic> imageData) async {
  final byteData = imageData[0] as Uint8List;
  final width = imageData[1] as int;
  final height = imageData[2] as int;

  final bigBitmap = Bitmap.fromHeadless(width, height, byteData);

  final returnBitmap = bigBitmap.applyBatch([
    BitmapAdjustColor(
      saturation: 1.9,
    ),
    BitmapCrop.fromLTWH(
      left: 10,
      top: 10,
      width: width - 20,
      height: height - 20,
    ),
  ]);

  return returnBitmap.content;
}
101
likes
150
points
414
downloads

Publisher

verified publisherblue-fire.xyz

Weekly Downloads

Bitmap is a fast and minimalistic lib that helps you to manipulate images in.

Repository (GitHub)
View/report issues

Topics

#image #image-processing #ffi

Documentation

API reference

License

MIT (license)

Dependencies

equatable, ffi, flutter

More

Packages that depend on bitmap

Packages that implement bitmap