DrawViewController.swift 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280
  1. //
  2. // DrawViewController.swift
  3. // AIPaint
  4. //
  5. // Created by Fengyu He on 2022/11/29.
  6. //
  7. import UIKit
  8. import Photos
  9. import SnapKit
  10. import SwiftyJSON
  11. import SwiftUI
  12. import CoreData
  13. class DrawViewController: UIViewController {
  14. lazy var generateView: UIView = {
  15. let view = UIView()
  16. view.backgroundColor = .clear
  17. view.layer.borderWidth = 1
  18. view.layer.borderColor = UIColor.black.cgColor
  19. return view
  20. }()
  21. lazy var promptTextField: UITextField = {
  22. let textField = UITextField()
  23. textField.placeholder = "请输入你的作品的组成元素,以空格分割。"
  24. textField.layer.borderWidth = 1
  25. textField.layer.borderColor = UIColor.black.cgColor
  26. return textField
  27. }()
  28. lazy var negativePromptTextField: UITextField = {
  29. let textField = UITextField()
  30. textField.placeholder = "请输入你不想在作品中看到的元素,以空格分割。"
  31. textField.layer.borderWidth = 1
  32. textField.layer.borderColor = UIColor.black.cgColor
  33. return textField
  34. }()
  35. lazy var generateButton: UIButton = {
  36. let button = UIButton()
  37. button.layer.backgroundColor = UIColor.blue.cgColor
  38. button.addTarget(self, action: #selector(generateAction), for: .touchUpInside)
  39. button.setTitle("生成图片", for: .normal)
  40. button.isUserInteractionEnabled = true
  41. return button
  42. }()
  43. var longPress: UILongPressGestureRecognizer?
  44. lazy var generateImage: UIImageView = {
  45. let imageView = UIImageView()
  46. imageView.layer.borderWidth = 1
  47. imageView.layer.borderColor = UIColor.black.cgColor
  48. imageView.isUserInteractionEnabled = true
  49. return imageView
  50. }()
  51. var prompt = ""
  52. var tranPrompt = ""
  53. var negativePrompt = ""
  54. var tranNegativePrompt = ""
  55. var sessionHash = ""
  56. var delegate: AppDelegate?
  57. var context: NSManagedObjectContext?
  58. var painting: Painting?
  59. let alertController = UIAlertController(title: "保存成功!", message: nil, preferredStyle: .alert)
  60. override func viewDidLoad() {
  61. super.viewDidLoad()
  62. view.backgroundColor = .white
  63. self.title = "AI Paint"
  64. delegate = UIApplication.shared.delegate as? AppDelegate
  65. context = delegate!.persistentContainer.viewContext
  66. painting = NSEntityDescription.insertNewObject(forEntityName: "Painting", into: context!) as? Painting
  67. view.addSubview(generateView)
  68. generateView.addSubview(promptTextField)
  69. generateView.addSubview(negativePromptTextField)
  70. generateView.addSubview(generateButton)
  71. view.addSubview(generateImage)
  72. longPress = UILongPressGestureRecognizer(target: self, action: #selector(saveImageToPhotos))
  73. generateImage.addGestureRecognizer(longPress!)
  74. generateView.snp.makeConstraints { (make) in
  75. make.top.equalTo(view.safeAreaLayoutGuide.snp.top)
  76. make.width.equalTo(view.safeAreaLayoutGuide.snp.width)
  77. make.height.equalTo(view.safeAreaLayoutGuide.snp.height).multipliedBy(0.35)
  78. make.centerX.equalTo(view.safeAreaLayoutGuide.snp.centerX)
  79. }
  80. promptTextField.snp.makeConstraints { (make) in
  81. make.top.equalTo(generateView.snp.top).offset(5)
  82. make.width.equalTo(generateView.snp.width).multipliedBy(0.95)
  83. make.height.equalTo(generateView.snp.height).multipliedBy(0.35)
  84. make.centerX.equalTo(generateView.snp.centerX)
  85. }
  86. negativePromptTextField.snp.makeConstraints { (make) in
  87. make.top.equalTo(promptTextField.snp.bottom).offset(5)
  88. make.width.equalTo(generateView.snp.width).multipliedBy(0.95)
  89. make.height.equalTo(generateView.snp.height).multipliedBy(0.35)
  90. make.centerX.equalTo(generateView.snp.centerX)
  91. }
  92. generateButton.snp.makeConstraints { (make) in
  93. make.top.equalTo(negativePromptTextField.snp.bottom).offset(5)
  94. make.width.equalTo(generateView.snp.width).multipliedBy(0.95)
  95. make.height.equalTo(generateView.snp.height).multipliedBy(0.2)
  96. make.centerX.equalTo(generateView.snp.centerX)
  97. }
  98. generateImage.snp.makeConstraints { (make) in
  99. make.top.equalTo(generateView.snp.bottom).offset(10)
  100. make.width.equalTo(view.safeAreaLayoutGuide.snp.width)
  101. make.height.equalTo(view.safeAreaLayoutGuide.snp.height).multipliedBy(0.60)
  102. make.centerX.equalTo(view.safeAreaLayoutGuide.snp.centerX)
  103. }
  104. }
  105. func translatePrompt(prompt: String, negativePrompt: String) -> (tranPrompt: String, tranNegativePrompt: String){
  106. let APP_KEY = "3bb96f14d2af67ec"
  107. let APP_SECRET = "SRQF1jGwAMuYciFK33KfyRGKa7B1x38u"
  108. let q = prompt + "|" + negativePrompt
  109. let salt = UUID().uuidString
  110. let curtime = Int(Date().timeIntervalSince1970)
  111. print(curtime)
  112. let signStr = APP_KEY + q + salt + String(curtime) + APP_SECRET
  113. let cryptoSign = signStr.sha256
  114. let paramDic = ["q": q, "from": "auto", "to": "en", "appKey": APP_KEY, "salt": salt, "sign": cryptoSign, "signType": "v3", "curtime": String(curtime)]
  115. let list = NSMutableArray()
  116. for subDic in paramDic {
  117. let tmpStr = "\(subDic.0)=\(subDic.1)"
  118. list.add(tmpStr)
  119. }
  120. let paramStr = list.componentsJoined(by: "&")
  121. let paramData = "https://openapi.youdao.com/api?" + paramStr
  122. var addr = paramData.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed)
  123. let url = URL(string: addr!)
  124. var request = URLRequest(url: url!)
  125. request.httpMethod = "GET"
  126. var promptValue = ""
  127. var negativePromotValue = ""
  128. let task = URLSession.shared.dataTask(with: request) { (data, response, error) in
  129. do {
  130. let jsonData = try JSON(data: data!)
  131. let promptData = jsonData["translation"][0].stringValue
  132. print(promptData)
  133. if String(promptData.first!) == "|" {
  134. let subStringArr = promptData.split(separator: "| ")
  135. negativePromotValue = String(subStringArr[0])
  136. } else if String(promptData.last!) == "|" {
  137. let subStringArr = promptData.split(separator: " |")
  138. promptValue = String(subStringArr[0])
  139. } else {
  140. let subStringArr = promptData.split(separator: " | ")
  141. promptValue = String(subStringArr[0])
  142. negativePromotValue = String(subStringArr[1])
  143. }
  144. } catch {}
  145. }
  146. task.resume()
  147. return (promptValue, negativePromotValue)
  148. }
  149. @objc func generateAction() {
  150. let translation = translatePrompt(prompt: promptTextField.text!, negativePrompt: negativePromptTextField.text!)
  151. generateButton.backgroundColor = .gray
  152. generateButton.isUserInteractionEnabled = false
  153. print("translation", translation)
  154. var promptValue = translation.tranPrompt
  155. var negativePromotValue = translation.tranNegativePrompt
  156. print("Generation: \(promptValue) + \(negativePromotValue)")
  157. prompt = "masterpiece, best quality, " + promptValue
  158. 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
  159. sessionHash = UUID().uuidString
  160. painting?.prompt = promptTextField.text!
  161. painting?.negative_prompt = negativePromptTextField.text!
  162. painting?.session_hash = sessionHash
  163. painting?.create_time = Date()
  164. let url = URL(string: "https://aipaint.hefengyu.org/api/predict/")
  165. var request = URLRequest(url: url!)
  166. request.httpMethod = "POST"
  167. 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]
  168. let jsonData = try? JSONSerialization.data(withJSONObject: postData, options: [])
  169. request.setValue("application/json", forHTTPHeaderField: "Content-Type")
  170. request.httpBody = jsonData
  171. var imageData: Data?
  172. let dataTask = URLSession.shared.dataTask(with: request) { (data, request, error) in
  173. do {
  174. let json = try? JSON(data: data!)
  175. let imageAddr = json!["data"][0][0]["name"].stringValue
  176. let addrProcess = imageAddr.replacingOccurrences(of: "\\", with: "/")
  177. let imageStr = "https://aipaint.hefengyu.org/file=\(addrProcess)"
  178. let imageUrl = URL(string: imageStr)
  179. imageData = try? Data(contentsOf: imageUrl!)
  180. DispatchQueue.main.async { [self] in
  181. painting?.image = imageData!
  182. self.generateImage.image = UIImage(data: imageData!)
  183. self.generateButton.backgroundColor = .blue
  184. self.generateButton.isUserInteractionEnabled = true
  185. if context!.hasChanges {
  186. do {
  187. try context?.save()
  188. print("save success.")
  189. } catch {}
  190. }
  191. }
  192. }
  193. }
  194. // let processURL = URL(string: "https://aipaint.hefengyu.org/api/predict/")
  195. // let processTask = URLSession.shared.dataTask(with: <#T##URLRequest#>)
  196. dataTask.resume()
  197. }
  198. @objc func saveImageToPhotos() {
  199. if (longPress!.state == .began) {
  200. // do something
  201. print("nice")
  202. guard let img = generateImage.image else {
  203. return
  204. }
  205. switch PHPhotoLibrary.authorizationStatus() {
  206. case .authorized:
  207. saveImg(image: img)
  208. case .notDetermined:
  209. PHPhotoLibrary.requestAuthorization { (status) in
  210. if status == .authorized {
  211. self.saveImg(image: img)
  212. } else {
  213. print("用户拒绝访问")
  214. }
  215. }
  216. case .restricted, .denied:
  217. if let url = URL.init(string: UIApplication.openSettingsURLString) {
  218. if UIApplication.shared.canOpenURL(url) {
  219. UIApplication.shared.open(url)
  220. }
  221. }
  222. case .limited:
  223. return
  224. @unknown default:
  225. return
  226. }
  227. }else if (longPress!.state == .ended){
  228. return
  229. }
  230. }
  231. func saveImg(image: UIImage) {
  232. PHPhotoLibrary.shared().performChanges({
  233. PHAssetChangeRequest.creationRequestForAsset(from: image)
  234. }, completionHandler: { (isSuccess, error) in
  235. DispatchQueue.main.async {
  236. if isSuccess{
  237. self.present(self.alertController, animated: true, completion: nil)
  238. DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 2) {
  239. self.alertController.dismiss(animated: false)
  240. }
  241. }
  242. }
  243. })
  244. }
  245. override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
  246. promptTextField.resignFirstResponder()
  247. negativePromptTextField.resignFirstResponder()
  248. }
  249. }