fluttercandies / flutter_image_editor

Flutter plugin, support android/ios.Support crop, flip, rotate, color martix, mix image, add text. merge multi images.
Apache License 2.0
407 stars 124 forks source link

fixes ColorOption.contrast (issue #105) #107

Closed ramtinq closed 1 year ago

ramtinq commented 1 year ago

The current matrix for contrast is identical to the brightness matrix. The modification is based on the following guide:

https://docs.rainmeter.net/tips/colormatrix-guide/

and tested, too.

AlexV525 commented 1 year ago

https://docs.rainmeter.net/tips/colormatrix-guide/

This looks robust. Can you add it as a comment to the factory constructor? Such as:

/// The contrast translate follows the guide at
/// https://docs.rainmeter.net/tips/colormatrix-guide.

Also, to make sure the value will be translated correctly and to avoid regressions, can you add a simple test to make sure the matrix is produced correctly through this option?

ramtinq commented 1 year ago

I added the reference to the guide.

By 'add a simple test' I didn't know if you mean a programatic test or a simple test app. I didn't find any already written tests in the package's files, only examples, so I concluded you mean a simple example test app. Here it is:

import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:image_editor/image_editor.dart' hide ImageSource;

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 const MaterialApp(
        title: 'Image Editor Test', home: ExtendedImageExample());
  }
}

class ExtendedImageExample extends StatefulWidget {
  const ExtendedImageExample({super.key});
  @override
  ExtendedImageExampleState createState() => ExtendedImageExampleState();
}

class ExtendedImageExampleState extends State<ExtendedImageExample> {
  late Uint8List originalImage;
  Uint8List? image;

  double _contrast = 1;

  Future<void> initImage() async {
    originalImage = (await NetworkAssetBundle(Uri.parse(
                'https://is3-ssl.mzstatic.com/image/thumb/xlPg0CL5sqh8OCq8mFNnJg/2638x1484.webp'))
            .load(
                'https://is3-ssl.mzstatic.com/image/thumb/xlPg0CL5sqh8OCq8mFNnJg/2638x1484.webp'))
        .buffer
        .asUint8List();
    setState(() {
      print('image loaded');
      image = Uint8List.fromList(originalImage);
    });
  }

  @override
  void initState() {
    initImage();
    super.initState();
  }

  Future<void> updateImage() async {
    final ImageEditorOption option = ImageEditorOption()
      ..addOption(ColorOption.contrast(_contrast));

    final Uint8List? result = await ImageEditor.editImage(
      image: originalImage,
      imageEditorOption: option,
    );

    if (result != null) {
      setState(() {
        image = result;
      });
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Test new contrast matrix'),
      ),
      body: SizedBox(
        height: double.infinity,
        child: Column(
          children: <Widget>[
            AspectRatio(
              aspectRatio: 1,
              child: image == null
                  ? const Center(
                      child: CircularProgressIndicator(),
                    )
                  : Image.memory(
                      image!,
                      gaplessPlayback: true,
                    ),
            ),
            const SizedBox(
              height: 16,
            ),
            Expanded(
              child: SliderTheme(
                data: const SliderThemeData(
                  showValueIndicator: ShowValueIndicator.always,
                ),
                child: Slider(
                  value: _contrast,
                  min: 0,
                  max: 2,
                  label: 'cont : ${_contrast.toStringAsFixed(2)}',
                  onChanged: (double value) {
                    setState(() {
                      _contrast = value;
                    });
                  },
                  onChangeEnd: (_) async => updateImage(),
                ),
              ),
            ),
          ],
        ),
      ),
    );
  }
}
AlexV525 commented 1 year ago

By 'add a simple test' I didn't know if you mean a programatic test or a simple test app. I didn't find any already written tests in the package's files, only examples, so I concluded you mean a simple example test app. Here it is:

Well here I mean a simple unit test to use the factory and check expectations.