LoginSignup
5
2

はじめに

だいぶ暑くなってきましたね。
これから夏本番ということで、今回は、Swiftを使ってホラーテイストな画像を生成するiOSアプリを作ってみました👻

要件

  • iOS 14.0以降
  • Xcode 12.0以降
  • OpenAI APIキー

環境構築

  1. Xcodeで新規プロジェクトを作成

    • プロジェクト名: HorrorImageConverter
    • インターフェース: SwiftUI
    • 言語: Swift
  2. OpenAI APIキーを取得

OpenAI API (https://openai.com/index/openai-api/) でアカウントを作成し、APIキーを取得してください。

要件

  • 作りたい画像のイメージを入力できる
  • 画像生成ボタンをタップすると、ホラー画像が生成される

実装

ContentView.swift
import SwiftUI

struct ContentView: View {
    @State private var inputText = ""
    @State private var outputImage: UIImage?
    @State private var showAlert = false
    @State private var isLoading = false // ローディング状態を管理する状態変数

    var body: some View {
        VStack {
            // 入力フィールド
            TextField("イメージを入力してください...", text: $inputText)
                .padding()
                .border(Color.gray, width: 1)

            // 画像生成ボタン
            Button("画像生成") {
                self.outputImage = nil // 画像を非表示にする
                isLoading = true // ボタンが押されたらローディング開始
                generateImage(from: inputText)
            }
            .padding()
            .border(Color.gray, width: 1)
            .disabled(isLoading) // ローディング中はボタンを無効化

            // ローディングアイコン
            if isLoading {
                ProgressView()
                    .progressViewStyle(CircularProgressViewStyle())
            }

            // 生成された画像を表示
            if let outputImage = outputImage {
                Image(uiImage: outputImage)
                    .resizable()
                    .scaledToFit()
                    .frame(maxHeight: 300)
            }
        }
        .padding()
        .alert(isPresented: $showAlert) {
            Alert(title: Text("エラー"), message: Text("画像の生成に失敗しました。"), dismissButton: .default(Text("OK")))
        }
    }

    func generateImage(from text: String) {
        let apiKey = "sk-proj-xxxxx"
        let url = URL(string: "https://api.openai.com/v1/images/generations")!

        // ホラーテイストを必ず入れるためのプロンプト調整
        let horrorPrompt = "An eerie and unsettling scene with \(text), in the style of a horror movie poster, dark and gruesome, high quality, digital art."

        let parameters: [String: Any] = [
            "model": "dall-e-3", // dall-e-3に指定
            "prompt": horrorPrompt,
            "n": 1,
            "size": "1024x1024" // 画像サイズ
        ]

        var request = URLRequest(url: url)
        request.httpMethod = "POST"
        request.addValue("Bearer \(apiKey)", forHTTPHeaderField: "Authorization")
        request.addValue("application/json", forHTTPHeaderField: "Content-Type")
        request.httpBody = try? JSONSerialization.data(withJSONObject: parameters)

        URLSession.shared.dataTask(with: request) { data, response, error in
            // エラー処理
            if let error = error {
                print("エラー: \(error)")
                DispatchQueue.main.async {
                    self.showAlert = true
                }
                return
            }

            guard let data = data else {
                print("データがありません")
                DispatchQueue.main.async {
                    self.showAlert = true
                }
                return
            }

            do {
                if let json = try JSONSerialization.jsonObject(with: data, options: []) as? [String: Any],
                   let dataArray = json["data"] as? [[String: Any]],
                   let firstImageData = dataArray.first,
                   let imageUrlString = firstImageData["url"] as? String,
                   let imageUrl = URL(string: imageUrlString) {
                   
                    // 画像の取得
                    if let imageData = try? Data(contentsOf: imageUrl), let image = UIImage(data: imageData) {
                        DispatchQueue.main.async {
                            self.outputImage = image
                            self.isLoading = false
                        }
                    } else {
                        print("画像の取得またはデコードエラー")
                        DispatchQueue.main.async {
                            self.showAlert = true
                        }
                    }
                } else {
                    print("画像URLの解析エラー")
                    DispatchQueue.main.async {
                        self.showAlert = true
                    }
                }

            } catch {
                print("JSON解析エラー: \(error)")
                DispatchQueue.main.async {
                    self.showAlert = true
                }
            }
        }.resume()
    }
}

※今回はローカルで動かすための簡易実装です。
※APIキーの取り扱いには、十分にご注意ください。

動作確認

女の子

チューリップ

笑顔

お花畑

どれも怖いですね、、、👻

まとめ

今回は、OpenAI APIを使ってホラー画像を生成するiOSアプリを開発しました。画像生成AIの技術は日々進化しており、アイデア次第で様々なアプリ開発に活用できます。

ぜひ、自分だけのオリジナルアプリ開発に挑戦してみてください!

5
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
2