123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345 |
- //
- // DrawViewController.swift
- // AIPaint
- //
- // Created by Fengyu He on 2022/11/29.
- //
- import UIKit
- import Photos
- import SnapKit
- import SwiftyJSON
- import SwiftUI
- import CoreData
- class DrawViewController: UIViewController {
-
- lazy var generateView: UIView = {
- let view = UIView()
- view.backgroundColor = .clear
- view.layer.borderWidth = 1
- view.layer.borderColor = UIColor.black.cgColor
- return view
- }()
-
- lazy var promptTextField: UITextField = {
- let textField = UITextField()
- textField.placeholder = "请输入你的作品的组成元素,以空格分割。"
- textField.layer.borderWidth = 1
- textField.layer.borderColor = UIColor.black.cgColor
- return textField
- }()
-
- lazy var negativePromptTextField: UITextField = {
- let textField = UITextField()
- textField.placeholder = "请输入你不想在作品中看到的元素,以空格分割。"
- textField.layer.borderWidth = 1
- textField.layer.borderColor = UIColor.black.cgColor
- return textField
- }()
-
- lazy var generateButton: UIButton = {
- let button = UIButton()
- button.layer.backgroundColor = UIColor.blue.cgColor
- button.addTarget(self, action: #selector(generateAction), for: .touchUpInside)
- button.setTitle("生成图片", for: .normal)
- button.isUserInteractionEnabled = true
- return button
- }()
-
- var longPress: UILongPressGestureRecognizer?
-
- lazy var generateImage: UIImageView = {
- let imageView = UIImageView()
- imageView.layer.borderWidth = 1
- imageView.layer.borderColor = UIColor.black.cgColor
- imageView.isUserInteractionEnabled = true
- return imageView
- }()
-
- lazy var remindText: UILabel = {
- var label = UILabel()
- label.text = "长按图片进行保存"
- label.textColor = .systemGray5
- label.textAlignment = .center
- return label
- }()
-
- var prompt = ""
- var tranPrompt = ""
- var negativePrompt = ""
- var tranNegativePrompt = ""
- var sessionHash = ""
- var delegate: AppDelegate?
- var context: NSManagedObjectContext?
- var painting: Painting?
- let alertController = UIAlertController(title: "保存成功!", message: nil, preferredStyle: .alert)
-
- override func viewDidLoad() {
- super.viewDidLoad()
-
- if UITraitCollection.current.userInterfaceStyle == .dark {
- view.backgroundColor = .black
- } else {
- view.backgroundColor = .white
- }
-
- self.title = "AI Paint"
- delegate = UIApplication.shared.delegate as? AppDelegate
- view.addSubview(generateView)
- generateView.addSubview(promptTextField)
- generateView.addSubview(negativePromptTextField)
- generateView.addSubview(generateButton)
- view.addSubview(remindText)
-
- view.addSubview(generateImage)
- longPress = UILongPressGestureRecognizer(target: self, action: #selector(saveImageToPhotos))
- generateImage.addGestureRecognizer(longPress!)
-
- generateView.snp.makeConstraints { (make) in
- make.top.equalTo(view.safeAreaLayoutGuide.snp.top)
- make.width.equalTo(view.safeAreaLayoutGuide.snp.width)
- make.height.equalTo(view.safeAreaLayoutGuide.snp.height).multipliedBy(0.35)
- make.centerX.equalTo(view.safeAreaLayoutGuide.snp.centerX)
- }
-
- promptTextField.snp.makeConstraints { (make) in
- make.top.equalTo(generateView.snp.top).offset(5)
- make.width.equalTo(generateView.snp.width).multipliedBy(0.95)
- make.height.equalTo(generateView.snp.height).multipliedBy(0.35)
- make.centerX.equalTo(generateView.snp.centerX)
- }
-
- negativePromptTextField.snp.makeConstraints { (make) in
- make.top.equalTo(promptTextField.snp.bottom).offset(5)
- make.width.equalTo(generateView.snp.width).multipliedBy(0.95)
- make.height.equalTo(generateView.snp.height).multipliedBy(0.35)
- make.centerX.equalTo(generateView.snp.centerX)
- }
-
- generateButton.snp.makeConstraints { (make) in
- make.top.equalTo(negativePromptTextField.snp.bottom).offset(5)
- make.width.equalTo(generateView.snp.width).multipliedBy(0.95)
- make.height.equalTo(generateView.snp.height).multipliedBy(0.2)
- make.centerX.equalTo(generateView.snp.centerX)
- }
-
- generateImage.snp.makeConstraints { (make) in
- make.top.equalTo(generateView.snp.bottom).offset(10)
- make.width.equalTo(view.safeAreaLayoutGuide.snp.width)
- make.height.equalTo(view.safeAreaLayoutGuide.snp.height).multipliedBy(0.60)
- make.centerX.equalTo(view.safeAreaLayoutGuide.snp.centerX)
- }
-
- remindText.snp.makeConstraints { (make) in
- make.top.equalTo(generateImage.snp.top).offset(2)
- make.width.equalTo(generateImage.snp.width)
- make.height.equalTo(generateImage.snp.height).multipliedBy(0.40)
- make.centerX.equalTo(generateImage.snp.centerX)
- }
- }
-
- func translatePrompt(prompt: String, negativePrompt: String, completion: @escaping (_ tranPrompt: String, _ tranNegativePrompt: String) -> Void) {
- let APP_KEY = "3bb96f14d2af67ec"
- let APP_SECRET = "SRQF1jGwAMuYciFK33KfyRGKa7B1x38u"
- let q = prompt + "|" + negativePrompt
- let salt = UUID().uuidString
- let curtime = Int(Date().timeIntervalSince1970)
- let inputQ = q.count <= 20 ? q : String(q.prefix(10)) + String(q.count) + String(q.suffix(10))
- let signStr = APP_KEY + inputQ + salt + String(curtime) + APP_SECRET
- let cryptoSign = signStr.sha256
- let paramDic = ["q": q, "from": "auto", "to": "en", "appKey": APP_KEY, "salt": salt, "sign": cryptoSign, "signType": "v3", "curtime": String(curtime)]
- let list = NSMutableArray()
- for subDic in paramDic {
- let tmpStr = "\(subDic.0)=\(subDic.1)"
- list.add(tmpStr)
- }
- let paramStr = list.componentsJoined(by: "&")
- let paramData = "https://openapi.youdao.com/api?" + paramStr
- print(paramData)
- guard let addr = paramData.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed) else {
- print("error")
- return
- }
- guard let url = URL(string: addr) else {
- print("error")
- return
- }
- var request = URLRequest(url: url)
- request.httpMethod = "GET"
-
- var promptValue = ""
- var negativePromotValue = ""
-
- let task = URLSession.shared.dataTask(with: request) { (data, response, error) in
- do {
- guard let unwrapedData = data else {
- print("error")
- return
- }
- let jsonData = try JSON(data: unwrapedData)
- let promptData = jsonData["translation"][0].stringValue
- print(promptData)
- if String(promptData.first ?? String.Element("")) == "|" {
- if #available(iOS 16.0, *) {
- let subStringArr = promptData.split(separator: "|")
- negativePromotValue = String(subStringArr[0])
- } else {
- // Fallback on earlier versions
- let subStringArr = promptData.components(separatedBy: "|")
- negativePromotValue = String(subStringArr[0])
- }
-
- } else if String(promptData.last ?? String.Element("")) == "|" {
- if #available(iOS 16.0, *) {
- let subStringArr = promptData.split(separator: " |")
- promptValue = String(subStringArr[0])
- } else {
- // Fallback on earlier versions
- let subStringArr = promptData.components(separatedBy: "|")
- promptValue = String(subStringArr[0])
- }
- } else if promptData == "|"{
- // do nothing
- } else {
- if #available(iOS 16.0, *) {
- let subStringArr = promptData.split(separator: "|")
- promptValue = String(subStringArr[0])
- negativePromotValue = String(subStringArr[1])
- } else {
- // Fallback on earlier versions
- let subStringArr = promptData.components(separatedBy: "|")
- promptValue = String(subStringArr[0])
- negativePromotValue = String(subStringArr[1])
- }
-
- }
- } catch {}
- completion(promptValue, negativePromotValue)
- }
- task.resume()
- }
-
- @objc func generateAction() {
- let promptText = promptTextField.text ?? ""
- let negativePromptText = negativePromptTextField.text ?? ""
- translatePrompt(prompt: promptTextField.text!, negativePrompt: negativePromptTextField.text!) { [self] promptValue, negativePromotValue in
-
- prompt = "masterpiece, best quality, " + promptValue
- negativePrompt = "lowres, bad anatomy, bad hands, text, error, missing fingers, extra digits, fewer digits, cropped, worst quality, low quality, normal quality, jpeg artifacts, signature, watermark, username, blurry, bad feet, " + negativePromotValue
- sessionHash = UUID().uuidString
- guard let unwrapedDelegate = delegate else {
- return
- }
- context = unwrapedDelegate.persistentContainer.viewContext
- painting = NSEntityDescription.insertNewObject(forEntityName: "Painting", into: context!) as? Painting
- painting?.prompt = promptText
- painting?.negative_prompt = negativePromptText
- painting?.session_hash = sessionHash
- painting?.create_time = Date()
- guard let url = URL(string: "https://aipaint.hefengyu.org/api/predict/") else {
- print("error")
- return
- }
- var request = URLRequest(url: url)
- request.httpMethod = "POST"
- let postData: [String: Any] = ["fn_index":50, "data":[prompt,negativePrompt,"None","None",20,"Euler a",false,false,1,1,7,-1,-1,0,0,0,false,512,512,false,0.7,0,0,"None",false,false,false,"","Seed","","Nothing","",true,false,false,"null","",""], "session_hash":sessionHash]
- let jsonData = try? JSONSerialization.data(withJSONObject: postData, options: [])
- request.setValue("application/json", forHTTPHeaderField: "Content-Type")
- request.httpBody = jsonData
- let dataTask = URLSession.shared.dataTask(with: request) { (data, request, error) in
- do {
- guard let data = data else {
- return
- }
- guard let json = try? JSON(data: data) else {
- return
- }
- let imageAddr = json["data"][0][0]["name"].stringValue
- let addrProcess = imageAddr.replacingOccurrences(of: "\\", with: "/")
- let imageStr = "https://aipaint.hefengyu.org/file=\(addrProcess)"
- guard let imageUrl = URL(string: imageStr) else {
- return
- }
- guard let imageData = try? Data(contentsOf: imageUrl) else {
- return
- }
- DispatchQueue.main.async { [self] in
- painting?.image = imageData
- self.generateImage.image = UIImage(data: imageData)
- self.generateButton.backgroundColor = .blue
- self.generateButton.isUserInteractionEnabled = true
- saveContext()
- }
- }
- }
- dataTask.resume()
- }
- generateButton.backgroundColor = .gray
- generateButton.isUserInteractionEnabled = false
- }
-
- @objc func saveImageToPhotos() {
- if (longPress!.state == .began) {
- guard let img = generateImage.image else {
- print("error")
- return
- }
- switch PHPhotoLibrary.authorizationStatus() {
- case .authorized:
- saveImg(image: img)
- case .notDetermined:
- PHPhotoLibrary.requestAuthorization { (status) in
- if status == .authorized {
- self.saveImg(image: img)
- } else {
- print("用户拒绝访问")
- }
- }
- case .restricted, .denied:
- if let url = URL.init(string: UIApplication.openSettingsURLString) {
- if UIApplication.shared.canOpenURL(url) {
- UIApplication.shared.open(url)
- }
- }
- case .limited:
- return
- @unknown default:
- return
- }
- }else if (longPress!.state == .ended){
- return
- }
- }
-
- func saveContext() {
- if context!.hasChanges {
- do {
- try context?.save()
- print("save success.")
- } catch {}
- }
- }
-
- func saveImg(image: UIImage) {
- PHPhotoLibrary.shared().performChanges({
- PHAssetChangeRequest.creationRequestForAsset(from: image)
- }, completionHandler: { (isSuccess, error) in
- DispatchQueue.main.async {
- if isSuccess{
- self.present(self.alertController, animated: true, completion: nil)
- DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 2) {
- self.alertController.dismiss(animated: false)
- }
- }
- }
- })
- }
-
- override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
- promptTextField.resignFirstResponder()
- negativePromptTextField.resignFirstResponder()
- }
- }
|