Commit bbc7d200 authored by netyouli's avatar netyouli

添加图生图功能

parent 0618b3ec
......@@ -30,7 +30,7 @@ class AIDrawImageResultController extends GetxController {
var styleName = "".obs;
var text = "".obs;
var enText = "";
var imageUrl = "".obs;
var resultImageUrl = "".obs;
var progress = 0.obs;
var showProgressView = false.obs;
var loseTime = "0.0s".obs;
......@@ -171,7 +171,13 @@ class AIDrawImageResultController extends GetxController {
makeDrawImage() async {
progress.value = 0;
final question = '$enText --ar $ratio$s';
final imageUrl = imageUrls.first;
var question = "";
if (imageUrl.isNotEmpty) {
question = '$imageUrl $enText --iw 2 --ar $ratio$s';
} else {
question = '$enText --ar $ratio$s';
}
Logger.debugPrint("question = $question");
EasyLoading.show(status: "AI正在生成中...");
try {
......@@ -230,17 +236,17 @@ class AIDrawImageResultController extends GetxController {
}
final progressBase64 = model.progressBase64?.replaceAll("data:image/png;base64,", "") ?? "";
if (model.response?.imageUrl != null) {
imageUrl.value = model.response?.imageUrl ?? "" ;
resultImageUrl.value = model.response?.imageUrl ?? "" ;
} else if (model.progressImageUrl != null) {
imageUrl.value = model.progressImageUrl ?? "";
resultImageUrl.value = model.progressImageUrl ?? "";
}
if (progressBase64.isNotEmpty) {
final decode = base64Decode(progressBase64.replaceAll('\n', ''));
placehoderImageData = imageData.value ?? decode;
imageData.value = decode;
} else {
if (imageUrl.value.isNotEmpty) {
loadImage(imageUrl.value, model.progress ?? 0);
if (resultImageUrl.value.isNotEmpty) {
loadImage(resultImageUrl.value, model.progress ?? 0);
}
}
// final first = model.response?.buttons?.first ?? "";
......
......@@ -192,7 +192,7 @@ class AIDrawImageResultPage extends GetView<AIDrawImageResultController> {
children: [
InkWell(
onTap: () {
controller.saveNetworkImage(controller.imageUrl.value);
controller.saveNetworkImage(controller.resultImageUrl.value);
},
child: Container(
width: 150,
......
......@@ -6,6 +6,7 @@ import 'package:chart/common/apis/apis.dart';
import 'package:chart/common/utils/utils.dart';
import 'package:flutter/material.dart';
import 'package:flutter_easyloading/flutter_easyloading.dart';
import 'package:flutter_keyboard_visibility/flutter_keyboard_visibility.dart';
import 'package:flutter_vibrate/flutter_vibrate.dart';
import 'package:get/get.dart';
import 'package:loading_animation_widget/loading_animation_widget.dart';
......@@ -19,6 +20,7 @@ import 'model.dart';
class AIDrawImageController extends GetxController {
late TabController tabController;
late TabController categoryController;
ScrollController textToImageController = ScrollController(initialScrollOffset: 0);
var model = AIDrawTextToImageModel();
var ratio = "9:16".obs;
var descriptionText = "".obs;
......@@ -28,7 +30,8 @@ class AIDrawImageController extends GetxController {
TextEditingController textController = TextEditingController(text: "");
Offset startPoint = const Offset(0, 0);
RxList<AIDrawDescriptiveItem> randomDescriptionItems = RxList<AIDrawDescriptiveItem>();
RxList<XFile> assets = RxList<XFile>();
RxList<XFile> blendAssets = RxList<XFile>();
RxList<XFile> textAssets = RxList<XFile>();
var sizePictures = [
AIDrawSizePictrue(name: "手机壁纸", ratio: "9:16", imageUrl: "assets/images/v_iphone.png"),
AIDrawSizePictrue(name: "电脑壁纸", ratio: "16:9", imageUrl: "assets/images/h_iphone.png"),
......@@ -59,7 +62,8 @@ class AIDrawImageController extends GetxController {
];
var textCount = 0.obs;
var uploadImageUrls = List.generate(0, (index) => "");
var uploadBlendImageUrls = List<String>.generate(0, (index) => "");
var uploadTextImageUrls = List<String>.generate(0, (index) => "");
@override
void onInit() {
......@@ -73,6 +77,16 @@ class AIDrawImageController extends GetxController {
descriptionText.value = textController.text;
}
});
KeyboardVisibilityController().onChange.listen((bool visible) {
if (tabController.index == 0) {
if (visible) {
textToImageController.animateTo(140, duration: const Duration(milliseconds: 100), curve: Curves.linear);
} else {
textToImageController.animateTo(0, duration: const Duration(milliseconds: 100), curve: Curves.linear);
}
}
});
}
@override
......@@ -95,12 +109,17 @@ class AIDrawImageController extends GetxController {
textController.setText(model.descriptives[randomIndex].description);
}
clearSelectedImage() {
assets.value = [];
uploadImageUrls.clear();
clearBlendSelectedImage() {
blendAssets.value = [];
uploadBlendImageUrls.clear();
}
clearTextSelectedImage() {
textAssets.clear();
uploadTextImageUrls.clear();
}
selectImageUpload(ImageSource source) async {
selectBlendImageUpload(ImageSource source) async {
List<XFile>? images;
if (source == ImageSource.camera) {
final image = await ImagePicker().pickImage(source: ImageSource.camera);
......@@ -115,7 +134,7 @@ class AIDrawImageController extends GetxController {
EasyLoading.showError("请选择1-5张图片");
} else {
for (var image in images) {
assets.add(image);
blendAssets.add(image);
}
}
EasyLoading.show(
......@@ -140,14 +159,46 @@ class AIDrawImageController extends GetxController {
if (i == count - 1) {
EasyLoading.dismiss();
}
uploadImageUrls.add(res.data ?? "");
uploadBlendImageUrls.add(res.data ?? "");
}
}
}
}
selectTextImageUpload(ImageSource source) async {
XFile? image;
if (source == ImageSource.camera) {
image = await ImagePicker().pickImage(source: ImageSource.camera);
} else {
image = await ImagePicker().pickImage(source: ImageSource.gallery);
}
if (image == null) return null;
textAssets.add(image);
EasyLoading.show(
status: "正在上传,请稍后",
dismissOnTap: false,
maskType: EasyLoadingMaskType.none,
indicator: LoadingAnimationWidget.staggeredDotsWave(
color: Colors.white,
size: 30,
));
final res = await NewsAPI.uploadFile([File(image.path)]);
if (res.status == 401) {
EasyLoading.showInfo('您还未登录,请登录后体验功能。');
Get.toNamed(AppRoutes.SIGN_IN);
// state.isLoading = false;
} else {
if (res.data == null) {
EasyLoading.showToast(res.message ?? "未知错误");
} else {
EasyLoading.dismiss();
uploadTextImageUrls.add(res.data ?? "");
}
}
}
toImageMarkDrawImage() async {
if (uploadImageUrls.length < 2 || uploadImageUrls.length > 5) {
if (uploadBlendImageUrls.length < 2 || uploadBlendImageUrls.length > 5) {
EasyLoading.showError("请选择2-5张图片");
return;
}
......@@ -170,12 +221,12 @@ class AIDrawImageController extends GetxController {
arguments: {
"opearter": "imageToImage",
"conversionId": conversionId,
"imageUrls": List<String>.from(uploadImageUrls),
"imageUrls": List<String>.from(uploadBlendImageUrls),
"ratio": ratio.value,
"s": s,
"styleName": styleName.value
});
clearSelectedImage();
clearBlendSelectedImage();
}
}
......@@ -204,12 +255,14 @@ class AIDrawImageController extends GetxController {
arguments: {
"opearter": "textToImage",
"conversionId": conversionId,
"imageUrls": List<String>.from(uploadTextImageUrls),
"enText": transformModel.transResult?.first.dst ?? textController.text,
"text": textController.text,
"ratio": ratio.value,
"s": s,
"styleName": styleName.value
});
clearTextSelectedImage();
}
}
......
......@@ -25,7 +25,7 @@ import 'controller.dart';
children: [
InkWell(
onTap: () {
controller.selectImageUpload(ImageSource.camera);
controller.selectBlendImageUpload(ImageSource.camera);
Get.back();
},
child: Container(
......@@ -42,7 +42,7 @@ import 'controller.dart';
SizedBox(height: 10,),
InkWell(
onTap: () {
controller.selectImageUpload(ImageSource.gallery);
controller.selectBlendImageUpload(ImageSource.gallery);
Get.back();
},
child: Container(
......@@ -65,10 +65,10 @@ import 'controller.dart';
Widget makeShowAssetImageView(double width) {
final controller = Get.find<AIDrawImageController>();
final count = controller.assets.length < 5 ? controller.assets.length + 1 : controller.assets.length;
final count = controller.blendAssets.length < 5 ? controller.blendAssets.length + 1 : controller.blendAssets.length;
final children = List<Widget>.generate(count, (index) {
if (index < controller.assets.length) {
final element = controller.assets[index];
if (index < controller.blendAssets.length) {
final element = controller.blendAssets[index];
return Image.file(File(element.path), width: (width - 20) / 5.0, height: 160, fit: BoxFit.contain,);
}
return Container(
......@@ -121,13 +121,13 @@ import 'controller.dart';
return Stack(
children: [
Obx(() => Visibility(
visible: controller.assets.isNotEmpty,
visible: controller.blendAssets.isNotEmpty,
child: Positioned(
right: 0,
top: 0,
child: InkWell(
onTap: () {
controller.clearSelectedImage();
controller.clearBlendSelectedImage();
},
child: Image.asset("assets/images/清空图片.png", width: 30, height: 30,),
)
......@@ -149,7 +149,7 @@ import 'controller.dart';
child: Obx(() => Stack(
children: [
Visibility(
visible: controller.assets.isEmpty,
visible: controller.blendAssets.isEmpty,
child: InkWell(
onTap: () {
showSheetAlert();
......@@ -173,7 +173,7 @@ import 'controller.dart';
)
),
Visibility(
visible: controller.assets.isNotEmpty,
visible: controller.blendAssets.isNotEmpty,
child: makeShowAssetImageView(constraints.maxWidth - 20)
)
],
......
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:image_picker/image_picker.dart';
import 'package:pinput/pinput.dart';
import '../../common/routers/names.dart';
import '../../common/style/color.dart';
......@@ -22,6 +25,161 @@ Widget makeSectionTitleView(String index, String name) {
);
}
showSheetAlert() {
final controller = Get.find<AIDrawImageController>();
Get.bottomSheet(
SafeArea(
child: Container(
decoration: const BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.all(Radius.circular(20))
),
padding: const EdgeInsets.fromLTRB(20, 20, 20, 20),
height: 138,
child: Column(
children: [
InkWell(
onTap: () {
controller.selectTextImageUpload(ImageSource.camera);
Get.back();
},
child: Container(
height: 44,
width: Get.width - 40,
alignment: Alignment.center,
decoration: BoxDecoration(
color: AppColor.primary,
borderRadius: BorderRadius.circular(22)
),
child: Text("拍照"),
),
),
SizedBox(height: 10,),
InkWell(
onTap: () {
controller.selectTextImageUpload(ImageSource.gallery);
Get.back();
},
child: Container(
height: 44,
width: Get.width - 40,
alignment: Alignment.center,
decoration: BoxDecoration(
color: AppColor.primary,
borderRadius: BorderRadius.circular(22)
),
child: Text("相册"),
),
)
],
),
)
), persistent: false
);
}
Widget makeShowAssetImageView(double width) {
final controller = Get.find<AIDrawImageController>();
final count = controller.textAssets.length;
final children = List<Widget>.generate(count, (index) {
final element = controller.textAssets[index];
return Image.file(File(element.path), width: (width - 20) / 5.0, height: 160, fit: BoxFit.contain,);
});
return Container(
child: Stack(
children: [
Row(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: children,
),
],
),
);
}
Widget makeInsertPictureView() {
final controller = Get.find<AIDrawImageController>();
// 插入图片
return Container(
height: 220,
padding: EdgeInsets.fromLTRB(10, 10, 10, 10),
decoration: BoxDecoration(
color: AppColor.gray3,
borderRadius: BorderRadius.circular(20)
),
child: LayoutBuilder(builder: (context, constraints) {
return Stack(
children: [
Obx(() => Visibility(
visible: controller.textAssets.isNotEmpty,
child: Positioned(
right: 0,
top: 0,
child: InkWell(
onTap: () {
controller.clearTextSelectedImage();
},
child: Image.asset("assets/images/清空图片.png", width: 30, height: 30,),
)
),
)
),
Column(
children: [
makeSectionTitleView("01.", "插入图片"),
SizedBox(height: 10,),
Container(
height: 160,
width: constraints.maxWidth - 20,
padding: EdgeInsets.fromLTRB(10, 0, 10, 0),
decoration: BoxDecoration(
color: AppColor.black1,
borderRadius: BorderRadius.circular(10)
),
child: Obx(() => Stack(
children: [
Visibility(
visible: controller.textAssets.isEmpty,
child: InkWell(
onTap: () {
showSheetAlert();
},
child: Container(
height: 160,
width: constraints.maxWidth - 20,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Image(image: AssetImage("assets/images/添加图片.png", ), width: 40, height: 40,),
SizedBox(height: 20,),
Text("支持图片格式:JPG/PNG,低于10M",
style: TextStyle(
fontSize: 12
),
),
]
),
),
)
),
Visibility(
visible: controller.textAssets.isNotEmpty,
child: makeShowAssetImageView(constraints.maxWidth - 20)
)
],
),
)
),
],
)
],
);
},)
);
}
Widget makeImageRandomItem(int index) {
final controller = Get.find<AIDrawImageController>();
final item = controller.randomDescriptionItems[index];
......@@ -135,7 +293,7 @@ Widget makeSectionTitleView(String index, String name) {
),
child: Column(
children: [
makeSectionTitleView("01.", "输入描述词"),
makeSectionTitleView("02.", "输入描述词"),
SizedBox(height: 10,),
Container(
height: 160,
......@@ -296,7 +454,7 @@ Widget makeSectionTitleView(String index, String name) {
),
child: Column(
children: [
makeSectionTitleView("02.", "选择风格"),
makeSectionTitleView("03.", "选择风格"),
SizedBox(height: 10,),
Divider(
color: AppColor.black1,
......@@ -381,7 +539,7 @@ Widget makeSectionTitleView(String index, String name) {
),
child: Column(
children: [
makeSectionTitleView("03.", "选择画幅"),
makeSectionTitleView("04.", "选择画幅"),
SizedBox(height: 10,),
Divider(
color: AppColor.black1,
......@@ -415,6 +573,7 @@ Widget makeSectionTitleView(String index, String name) {
return Stack(
children: [
SingleChildScrollView(
controller: controller.textToImageController,
scrollDirection: Axis.vertical,
padding: EdgeInsets.fromLTRB(10, 10, 10, 70),
child: Container(
......@@ -440,6 +599,8 @@ Widget makeSectionTitleView(String index, String name) {
),
),
SizedBox(height: 20,),
makeInsertPictureView(),
SizedBox(height: 20,),
makeEnterDescriptiveWordsView(),
SizedBox(height: 20,),
makeStyleSelectionView(),
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment