ChatApp/lib/tools/upload/upload_page.dart
2024-07-05 10:00:00 +08:00

495 lines
17 KiB
Dart
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import 'dart:async';
import 'dart:convert';
import 'dart:io';
import 'package:dio/dio.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_easyloading/flutter_easyloading.dart';
import 'package:flutter_native_image/flutter_native_image.dart';
import 'package:image_cropper/image_cropper.dart';
import 'package:image_picker/image_picker.dart';
import 'package:web_socket_channel/web_socket_channel.dart';
import '../../common/app_util.dart';
import '../../network/NetworkConfig.dart';
import '../home/HomeModel.dart';
import 'CropperDialog.dart';
///上传
class UploadPage extends StatefulWidget {
const UploadPage({Key? key}) : super(key: key);
@override
State<UploadPage> createState() => _MePageState();
}
class _MePageState extends State<UploadPage>
with SingleTickerProviderStateMixin {
StreamSubscription? subscription;
final HomeModel viewModel = HomeModel();
CroppedFile? selectImage; //选择的相册图
int currentSizeIndex = 0; //当前尺寸下标
String initImg = ""; //参考图
var imageValue = false;
String outputImg = "";
Future<void> _createPic() async {
EasyLoading.show(status: 'loading...');
String fileName = 'image.png';
FormData formData = FormData.fromMap({
'image': MultipartFile.fromBytes(_imageBytes!, filename: fileName),
});
viewModel.uploadImg(formData);
}
late WebSocketChannel channel;
bool isConnected = false;
void connectToWebSocket(String serverAddress, String clientId) async {
final url = 'ws://$serverAddress/ws?clientId=$clientId';
Uri uri = Uri.parse(url); // 注意这里我们没有添加查询参数
WebSocketChannel channel = WebSocketChannel.connect(uri);
channel.stream.listen((message) {
Map<String, dynamic> responseData = jsonDecode(message);
// 处理接收到的消息
if (responseData["type"] != 'crystools.monitor') {
print('Received: $message');
if (responseData["type"] == 'executed' &&
responseData["data"]['node'] == '384') {
print("responseData: " +
responseData["data"]['output']['images'][0]['filename']);
outputImg = "http://192.168.1.103:8188/view?filename=" +
responseData["data"]['output']['images'][0]['filename'] +
"&type=output";
setState(() {
EasyLoading.dismiss();
});
}
}
// 如果我们还没有标记为已连接,现在标记为已连接
}, onError: (error) {
// 处理错误
print('WebSocket error: $error');
isConnected = false; // 连接已关闭或出错
}, onDone: () {
// 连接关闭时的处理
print('WebSocket closed');
isConnected = false; // 连接已关闭
}, cancelOnError: true);
}
// 发送 clientId 的函数
/*void sendClientId(WebSocketChannel channel, String clientId) {
if (isConnected) {
// 如果 sink 已经被取消(例如,由于连接关闭),则不发送消息
return;
}
String jsonMessage = jsonEncode({'client_id': clientId});
channel.sink.add(utf8.encode(jsonMessage)); // 使用 utf8 编码发送字符串
}*/
@override
void initState() {
// TODO: implement initState
super.initState();
String serverAddress = '101.43.19.200:82'; // 假设这是你的服务器地址
String clientId = 'zhangzhan8228'; // 假设这是你的客户端 ID
connectToWebSocket(serverAddress, clientId);
//_channel = WebSocketChannel.connect(Uri.parse('ws://your-comfyui-url'));
}
@override
void dispose() {
// TODO: implement dispose
subscription?.cancel();
super.dispose();
}
//裁剪
cropImage(String path, int index) async {
CroppedFile? croppedFile = await ImageCropper().cropImage(
sourcePath: path,
// aspectRatioPresets: [
// CropAspectRatioPreset.square, //1:1
// ],
//aspectRatio: CropAspectRatio(ratioX: x, ratioY: y),
uiSettings: [
IOSUiSettings(
title: 'Cropper',
aspectRatioLockEnabled: true,
resetAspectRatioEnabled: false,
),
AndroidUiSettings(
toolbarTitle: 'Cropper',
toolbarColor: Color(0xFFBE6FDF),
toolbarWidgetColor: Colors.white,
activeControlsWidgetColor: Color(0xFFBE6FDF),
initAspectRatio: CropAspectRatioPreset.square,
lockAspectRatio: true,
),
WebUiSettings(
context: context,
viewwMode: WebViewMode.mode_1,
cropBoxMovable: false,
customDialogBuilder: (cropper, initCropper, crop, rotate, scale) {
return CropperDialog(
cropper: cropper,
initCropper: initCropper,
crop: crop,
rotate: rotate,
scale: scale,
);
},
),
],
);
return croppedFile;
}
Uint8List? _imageBytes;
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.white,
body: Stack(
children: [
const Image(
width: double.infinity,
fit: BoxFit.fitWidth,
image: AssetImage('assets/images/upbg.webp'),
),
Column(
children: [
GestureDetector(
onTap: () async {
XFile img = await AppUtil.getImages();
selectImage = await cropImage(img.path, currentSizeIndex);
final Response<List<int>> response =
await Dio().get<List<int>>(
selectImage!.path,
options: Options(
responseType: ResponseType.bytes), // 指定响应类型为字节
);
_imageBytes = Uint8List.fromList(response.data!);
setState(() {
//_imageBytes = selectImage!.readAsBytes() as Uint8List?;
});
},
child: Container(
width: 300,
height: 300,
margin:
const EdgeInsets.only(top: 100, left: 60, right: 60),
child: selectImage != null
? SizedBox(
width: 300.0, // 设置宽度
height: 300,
child: Image.network(outputImg != ""
? outputImg
: selectImage!
.path) /*Image.file(
File(selectImage!.path),
fit: BoxFit.cover, // 使用 BoxFit.cover 以适应容器的大小
)*/
)
: const Image(
fit: BoxFit.fitWidth,
image: AssetImage('assets/images/kuang.png'),
),
)),
Container(
margin: const EdgeInsets.only(top: 20, left: 20, right: 20),
child: Text(
'开始图生图',
style:
const TextStyle(color: Color(0xFF000000), fontSize: 14),
),
),
GestureDetector(
onTap: () async {
_generateImages();
},
child: Container(
height: 50,
margin: const EdgeInsets.only(top: 20, left: 50, right: 50),
width: double.infinity,
alignment: Alignment.center,
decoration: const BoxDecoration(
gradient: LinearGradient(
begin: Alignment.centerLeft, //渐变开始于上面的中间开始
end: Alignment.centerRight, //渐变结束于下面的中间
colors: [Color(0xFF808EEF), Color(0xFFBE6FDF)]),
borderRadius: BorderRadius.all(Radius.circular(25))),
child: Text(
'确认提交',
style: const TextStyle(
color: Color(0xFFFFFFFF), fontSize: 18),
),
))
],
),
],
),
);
}
///生成图片
_generateImages() async {
//if (NetworkConfig.userId != "") {
if (selectImage != null) {
//处理图片
//initImg = await _compressPictures();
// File file = File(selectImage!.path);
// ByteData data = await rootBundle.load(file.path);
// Uint8List imageBytes = data.buffer.asUint8List();
// initImg = base64Encode(imageBytes);
//initImg = await AppUtil.uploadImage2(file);
// final Response<List<int>> response = await Dio().get<List<int>>(
// selectImage!.path,
// options: Options(responseType: ResponseType.bytes), // 指定响应类型为字节
// );
// Uint8List imageBytes = Uint8List.fromList(response.data!);
//initImg = base64Encode(imageBytes);
///图生图
_createPic();
}
/*} else {
showLoginDialog();
}*/
}
//处理图片
_compressPictures() async {
String img = "";
//1取方向判断原图方向横竖
// 2同方向取宽高中最大值匹配已选择的画面比例宽高值。反方向小值
//1:1 512*512 3:4 512*704 4:3 704*512 9:16 512*910 16:9 910*512
File file = File(selectImage!.path);
File? compressedFile;
// ImageProperties properties =
// await FlutterNativeImage.getImageProperties(file.path);
//判断当前方向
/*int isDirection = 0; //0 正方形 1 横向长方形 2 纵向长方形
if (properties.width == properties.height) {
isDirection = 0;
} else if (properties.width! > properties.height!) {
isDirection = 1;
} else if (properties.width! < properties.height!) {
isDirection = 2;
}
//下标选择方向
if (currentSizeIndex == 0) {
if (isDirection == 0) {
//如果大于512的正方形直接换比例成512否则使用原图
if (properties.width! > 512) {
compressedFile = await FlutterNativeImage.compressImage(file.path,
quality: 100, targetWidth: 512, targetHeight: 512);
} else {
compressedFile = file;
}
} else if (isDirection == 1) {
if (properties.width! > 512) {
compressedFile = await FlutterNativeImage.compressImage(file.path,
quality: 100,
targetWidth: 512,
targetHeight:
(properties.height! * 512 / properties.width!).round());
} else {
compressedFile = file;
}
} else if (isDirection == 2) {
if (properties.height! > 512) {
compressedFile = await FlutterNativeImage.compressImage(file.path,
quality: 100,
targetWidth:
(properties.width! * 512 / properties.height!).round(),
targetHeight: 512);
} else {
compressedFile = file;
}
}
} else if (currentSizeIndex == 1) {
//下标方向为纵向
if (isDirection == 0) {
//如果大于512的正方形直接换比例成512否则使用原图
if (properties.width! > 512) {
compressedFile = await FlutterNativeImage.compressImage(file.path,
quality: 100, targetWidth: 512, targetHeight: 512);
} else {
compressedFile = file;
}
} else if (isDirection == 1) {
//横向
if (properties.width! > 512) {
compressedFile = await FlutterNativeImage.compressImage(file.path,
quality: 100,
targetWidth: 512,
targetHeight:
(properties.height! * 512 / properties.width!).round());
} else {
compressedFile = file;
}
} else if (isDirection == 2) {
//纵向
if (properties.height! > 704) {
compressedFile = await FlutterNativeImage.compressImage(file.path,
quality: 100,
targetWidth:
(properties.width! * 704 / properties.height!).round(),
targetHeight: 704);
} else {
compressedFile = file;
}
}
} else if (currentSizeIndex == 2) {
//下标方向为横向
if (isDirection == 0) {
//如果大于512的正方形直接换比例成512否则使用原图
if (properties.height! > 512) {
compressedFile = await FlutterNativeImage.compressImage(file.path,
quality: 100, targetWidth: 512, targetHeight: 512);
} else {
compressedFile = file;
}
} else if (isDirection == 1) {
//横向
if (properties.width! > 704) {
compressedFile = await FlutterNativeImage.compressImage(file.path,
quality: 100,
targetWidth: 704,
targetHeight:
(properties.height! * 704 / properties.width!).round());
} else {
compressedFile = file;
}
} else if (isDirection == 2) {
//纵向
if (properties.height! > 512) {
compressedFile = await FlutterNativeImage.compressImage(file.path,
quality: 100,
targetWidth:
(properties.width! * 512 / properties.height!).round(),
targetHeight: 512);
} else {
compressedFile = file;
}
}
} else if (currentSizeIndex == 3) {
//下标方向为纵向
if (isDirection == 0) {
//如果大于512的正方形直接换比例成512否则使用原图
if (properties.width! > 512) {
compressedFile = await FlutterNativeImage.compressImage(file.path,
quality: 100, targetWidth: 512, targetHeight: 512);
} else {
compressedFile = file;
}
} else if (isDirection == 1) {
//横向
if (properties.width! > 512) {
compressedFile = await FlutterNativeImage.compressImage(file.path,
quality: 100,
targetWidth: 512,
targetHeight:
(properties.height! * 512 / properties.width!).round());
} else {
compressedFile = file;
}
} else if (isDirection == 2) {
//纵向
if (properties.height! > 910) {
compressedFile = await FlutterNativeImage.compressImage(file.path,
quality: 100,
targetWidth:
(properties.width! * 910 / properties.height!).round(),
targetHeight: 910);
} else {
compressedFile = file;
}
}
} else if (currentSizeIndex == 4) {
//下标方向为横向
if (isDirection == 0) {
//如果大于512的正方形直接换比例成512否则使用原图
if (properties.height! > 512) {
compressedFile = await FlutterNativeImage.compressImage(file.path,
quality: 100, targetWidth: 512, targetHeight: 512);
} else {
compressedFile = file;
}
} else if (isDirection == 1) {
//横向
if (properties.width! > 910) {
compressedFile = await FlutterNativeImage.compressImage(file.path,
quality: 100,
targetWidth: 910,
targetHeight:
(properties.height! * 910 / properties.width!).round());
} else {
compressedFile = file;
}
} else if (isDirection == 2) {
//纵向
if (properties.height! > 512) {
compressedFile = await FlutterNativeImage.compressImage(file.path,
quality: 100,
targetWidth:
(properties.width! * 512 / properties.height!).round(),
targetHeight: 512);
} else {
compressedFile = file;
}
}
}*/
ImageProperties properties2 =
await FlutterNativeImage.getImageProperties(compressedFile!.path);
// print("ImageProperties===" +
// properties2.width.toString() +
// "*" +
// properties2.height.toString());
///判断图片大小
// double size = AppUtil.getFileSizeDouble(bytes: compressedFile.lengthSync());
//取整 大于10m直接抛弃
//var s = size.ceil();
// if (s > 10) {
// EasyLoading.showToast('图片过大');
// } else {
// //取整 大于1m直接压缩小于1m使用原图
// if (s > 1) {
// //图片压缩,压缩算法为 (10-s)*10,m越大调整后百分比越小
// int percentage = (10 - s) * 10;
// File compressedFile2 = await FlutterNativeImage.compressImage(
// compressedFile.path,
// quality: 80,
// percentage: percentage);
// //AppUtil.getFileSizeDouble(bytes: compressedFile2.lengthSync());
// img = await AppUtil.uploadImage2(compressedFile2);
// } else {
// //不压
//img = await AppUtil.uploadImage2(compressedFile2);
// }
// }
return img;
}
}