495 lines
17 KiB
Dart
495 lines
17 KiB
Dart
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;
|
||
}
|
||
}
|