首页 > 其他分享 >Flutter图片上传与曝光度、饱和度、对比度调节(优化UI)

Flutter图片上传与曝光度、饱和度、对比度调节(优化UI)

时间:2024-11-14 17:18:24浏览次数:3  
标签:saturation return double 40 UI 对比度 Flutter contrast exposure

前言:

相较于前一版https://blog.csdn.net/m0_73231884/article/details/143768951?spm=1001.2014.3001.5501

在这个版本中我将三个参数的按钮整合在了一起,并使用底部弹框的方式展现


 

其中,我修改了Slider组件的值,最小值为-40,最大值为40 。

 源码如下:

import 'dart:io';

import 'package:flutter/material.dart';
import 'package:image_picker/image_picker.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: ImageUploadScreen(),
    );
  }
}

class ImageUploadScreen extends StatefulWidget {
  @override
  _ImageUploadScreenState createState() => _ImageUploadScreenState();
}

class _ImageUploadScreenState extends State<ImageUploadScreen> {
  File? _image;
  double _exposure = 0.0; // 初始曝光度
  double _contrast = 0.0; // 初始对比度
  double _saturation = 0.0; // 初始饱和度

  String _currentAdjustment = '曝光度'; // 当前选择的调整类型

  Future<void> _pickImage() async {
    final picker = ImagePicker();
    final pickedFile = await picker.pickImage(source: ImageSource.gallery);

    if (pickedFile != null) {
      setState(() {
        _image = File(pickedFile.path);
        _exposure = 0.0;
        _contrast = 0.0;
        _saturation = 0.0;
        _currentAdjustment = '曝光度';
      });
    }
  }

  List<double> _calculateColorMatrix() {
    double invSat = 1 - (_saturation / 40 + 1);
    double R = 0.213 * invSat;
    double G = 0.715 * invSat;
    double B = 0.072 * invSat;

    double contrast = _contrast / 40 + 1;
    double exposure = _exposure / 40 + 1;

    return <double>[
      contrast * (R + (_saturation / 40 + 1)) * exposure,
      contrast * G * exposure,
      contrast * B * exposure, 0, 0, // Red
      contrast * R * exposure,
      contrast * (G + (_saturation / 40 + 1)) * exposure,
      contrast * B * exposure, 0, 0, // Green
      contrast * R * exposure, contrast * G * exposure,
      contrast * (B + (_saturation / 40 + 1)) * exposure, 0, 0, // Blue
      0, 0, 0, 1, 0, // Alpha
    ];
  }

  void _showAdjustmentModal() {
    showModalBottomSheet(
      context: context,
      builder: (BuildContext context) {
        return StatefulBuilder(
          builder: (BuildContext context, StateSetter setModalState) {
            return Container(
              padding: EdgeInsets.all(16),
              child: Column(
                mainAxisSize: MainAxisSize.min,
                children: [
                  Row(
                    mainAxisAlignment: MainAxisAlignment.spaceEvenly,
                    children: [
                      _buildAdjustmentIcon(
                          '曝光度', Icons.wb_sunny, setModalState),
                      _buildAdjustmentIcon(
                          '对比度', Icons.tonality, setModalState),
                      _buildAdjustmentIcon(
                          '饱和度', Icons.color_lens, setModalState),
                    ],
                  ),
                  Slider(
                    value: _getCurrentValue(),
                    min: -40.0,
                    max: 40.0,
                    divisions: 80,
                    label: _getCurrentValue().toStringAsFixed(1),
                    onChanged: (value) {
                      setModalState(() {
                        _setCurrentValue(value);
                      });
                      setState(() {});
                    },
                  ),
                ],
              ),
            );
          },
        );
      },
    );
  }

  Widget _buildAdjustmentIcon(
      String adjustmentType, IconData icon, StateSetter setModalState) {
    final isSelected = _currentAdjustment == adjustmentType;

    return Column(
      children: [
        IconButton(
          icon: Icon(icon, color: isSelected ? Colors.blue : Colors.grey),
          onPressed: () {
            setModalState(() {
              _currentAdjustment = adjustmentType;
            });
            setState(() {});
          },
        ),
        Text(adjustmentType),
      ],
    );
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('主程序窗口'),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            _image == null
                ? Text('没有选择图片。')
                : AspectRatio(
                    aspectRatio: 1, // 你可以根据需要调整这个比例
                    child: ColorFiltered(
                      colorFilter: ColorFilter.matrix(_calculateColorMatrix()),
                      child: Image.file(
                        _image!,
                        fit: BoxFit.contain, // 适应容器
                      ),
                    ),
                  ),
            SizedBox(height: 20),
            ElevatedButton(
              onPressed: _pickImage,
              child: Text('上传图片'),
            ),
          ],
        ),
      ),
      bottomNavigationBar: BottomAppBar(
        child: IconButton(
          icon: Icon(Icons.tune), // 调节图标
          onPressed: _image != null ? _showAdjustmentModal : null,
        ),
      ),
    );
  }

  double _getCurrentValue() {
    switch (_currentAdjustment) {
      case '曝光度':
        return _exposure;
      case '对比度':
        return _contrast;
      case '饱和度':
        return _saturation;
      default:
        return 0.0;
    }
  }

  void _setCurrentValue(double value) {
    switch (_currentAdjustment) {
      case '曝光度':
        _exposure = value;
        break;
      case '对比度':
        _contrast = value;
        break;
      case '饱和度':
        _saturation = value;
        break;
    }
  }
}

 喜欢的朋友欢迎使用,小萌新勿喷,上述源码复制粘贴即可使用。
 

最后,点赞关注支持一下吧(~ ̄▽ ̄)~  

标签:saturation,return,double,40,UI,对比度,Flutter,contrast,exposure
From: https://blog.csdn.net/m0_73231884/article/details/143775382

相关文章

  • jenkins打包报错Build step 'Execute shell' marked build as failure Finished: FA
    1、jenkins打包报错  处理方式1、在步骤“Executeshell”命令最上面添加(还是报错)#!/bin/bash2、设置全局配置,添加键和值(还是报错)键:LANG值:zh.CH.UTF-83、设置全局配置,添加键和值(还是报错)键:JAVA_TOOL_OPTIONS值:-Dfile.encoding=UTF-84、cat /usr/lib/systemd/sys......
  • flutter TabBarView 动态添加删除页面
    在TabBarView动态添加页面后删除其中一个页面会导致后面的页面状态错误或删除的页面不正确。出现这种问题是由于创建子页面时没有为子页面设置唯一的key导致的。1voidaddNewPage(){2_pageCount++;3setState((){4Stringtitle="页面$_pageCount......
  • Linux HTTP代理Squid 基本配置及目标白名单方式限制转发
    LinuxHTTP代理Squid基本变更配置及目标白名单方式限制转发https://www.cnblogs.com/iAmSoScArEd/p/18546341大部分保持默认即可1、文件管理转发白名单sudotouch/etc/squid/whitelistipsudotouch/etc/squid/whitelistdomain#目的地ip地址aclwhitelistipdst"/etc/s......
  • layui-laydate时间日历控件详细示例
     layui下载地址:http://www.layui.com/此控件可使用layui或者独立版的layDate,两者初始化有些不同1.在layui模块中使用layui.code<!DOCTYPEhtml><html><head><metacharset="utf-8"><title>layDate快速使用</title><linkrel="stylesheet"......
  • buildroot --- 通过 tsocks 代理下载 package 速度快
     tsocks配置文件 /etc/tsocks.conf#Thisistheconfigurationforlibtsocks(transparentsocks)#Linesbeginningwith#andblanklinesareignored##Thebasicideaistospecify:#-Localsubnets-Networksthatcanbeaccesseddirectlywithout#......
  • Arduino语法详解_含示例详解
    Arduino的程序可以划分为三个主要部分:结构、变量(变量与常量)、函数。  结构部分 一、结构1.1setup()1.2loop()二、结构控制2.1if2.2if...else2.3for2.4switchcase2.5while2.6do...while2.7break2.8continue2.9return2.10goto三、扩展语法......
  • 第十三:BurpSuite模拟器安装Burp Suite证书(一)-重点
    一.模拟器安装BurpSuite证书抓取安卓应用(使用协议为http/https的数据包)1.下载逍遥模拟器地址:https://www.xyaz.cn/2.注意:安装程序一直下一步注意:目录(文件夹)不要出现中文(防止出现错误,无法正常安装成功)!!!3.windows+R-cmd-config//查看本机ip地址4.为模拟器......
  • 第十二:BurpSuite安装下载浏览器代理插件(一)-重点
    一.BurpSuite下载浏览器代理插件1.浏览器代理插件名:SwitchyOmega2.设置代理规则3.设置代理端口:8080设置代理ip:127.0.0.1(本地地址)......
  • 第十一:BurpSuite安装浏览器安装Burp Suite证书(一)-重点
    一.浏览器安装BurpSuite证书(BurpSuite抓取浏览器https协议需要安装BurpSuite的证书)1.浏览器设置-搜索:证书-点击:安全2.点击:管理设备的证书3.为受信任的根证书颁布机构(安装证书)3.1.为中间证书颁发机构(安装证书)注意:为什么要给两个都安装证......
  • UI自动化测试|元素操作&浏览器操作实践
    前言Selenium自动化测试是一种广泛使用的Web自动化测试工具,它允许测试人员编写自动化测试脚本来模拟用户在Web浏览器中的操作,从而实现对Web应用程序的自动化测试。这里分享元素操作&浏览器操作1.Selenium之元素操作Selenium是一种常用的自动化测试工具,它提供了一组丰富的......