다음과 같은 에러때문에 어떻게 해결하는지 이틀동안 삽질만 하면서 계속 헤매다가 결국 방법을 찾았습니다..
You uploaded an unsupported image. Please make sure your image is below 20 MB in size and is of one the following formats: ['png', 'jpeg', 'gif', 'webp'].
결국 해당 패키지 Discussions 에 글을 올리게 되었는데 Github를 사용하면서 처음 사용해본 기능이였습니다.
하지만 뻘쭘하게 글을 올리고 몇시간 뒤에 문제를 해결하게 되었으며 글 아래에서 어떻게 해결하였는지 정리해보겠습니다.
GPT에 사진 전송하기
사진을 전송하기 위해서는 앨범에 존재하는 사진을 선택하거나 카메라로 사진을 찍어서 해당 사진을 전송해야 했습니다.
앨범에서 선택한 사진을 gpt에 전송하는 것은 별 문제없이 성공하였으나 카메라로 찍은 사진을 전송하는데 있어서 문제가 발생하였습니다.
SwiftUI를 사용하기 때문에 사진을 찍기 위해서는 UIViewControllerRepresentable 를 사용하여 UIKit에 있는 카메라뷰를 사용했습니다.
struct AccessCameraView: UIViewControllerRepresentable {
@Binding var isPresented: Bool
@Binding var selectedImage: UIImage?
func makeUIViewController(context: Context) -> UIImagePickerController {
let imagePicker = UIImagePickerController()
imagePicker.delegate = context.coordinator
imagePicker.sourceType = .camera
return imagePicker
}
func updateUIViewController(_ uiViewController: UIImagePickerController, context: Context) {
}
func makeCoordinator() -> Coordinator {
return Coordinator(isPresented: $isPresented, selectedImage: $selectedImage)
}
}
class Coordinator: NSObject, UINavigationControllerDelegate, UIImagePickerControllerDelegate {
@Binding var isPresented: Bool
@Binding var selectedImage: UIImage?
init(isPresented: Binding<Bool>, selectedImage: Binding<UIImage?>) {
_isPresented = isPresented
_selectedImage = selectedImage
}
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
if let uiImage = info[.originalImage] as? UIImage {
selectedImage = uiImage
}
isPresented = false
}
}
카메라를 통해 사진을 찍고 확인버튼을 누르게 된다면 didFinishPickingMediaWithInfo 콜백함수가 실행되어 클로저 내부에 있는 내용들이 실행됩니다.
시도한 것들
이후 다음 코드를 사용하여 UIImage 를 jpeg 데이터로 변환하였지만 위와 같은 에러가 발생한 것입니다..
jpeg, png, encoding64 모두 사용해보았지만 같은 에러를 출력하면서 문제가 해결되지 않았습니다.
guard let jpegData = selectedImage?.jpegData(compressionQuality: 0.1) else { return }
추가로 다음 코드를 사용하여 image 의 jpeg 데이터의 크기가 20 MB 이하인 것도 확인하였습니다.
let bcf = ByteCountFormatter()
bcf.allowedUnits = [.useMB]
bcf.countStyle = .file
let string = bcf.string(fromByteCount: Int64(jpegData.count))
print("formatted result: \(string)")
해결방법
그러면 어떻게 해결했느냐 물론 Discussions에 글을 올리는 과정도 있었지만 결국에는 사진의 크기가 문제였습니다.
사진 파일의 확장자도 파일의 크기도 조건에 적합했지만 UIGraphicsImageRenderer를 사용하여 이미지의 크기를 조절하는 것이 정답이였습니다. 왜 그런지는 잘 모르겠지만 카메라로 찍은 메모리에 저장된 UIImage와 앨범처럼 디스크에 저장된 UIImage는 다른것 같다고 생각이 듭니다. (메라로 찍은 사진은 불안정한 이미지고 앨범에 저장된 사진은 안정된 이미지라서.?? 추측)
extension UIImage {
func scaleToFit(targetSize: CGSize = .init(width: 512, height: 512)) -> UIImage {
let widthRatio = targetSize.width / size.width
let heightRatio = targetSize.height / size.height
let scaleFactor = min(widthRatio, heightRatio)
let scaledImageSize = CGSize(
width: size.width * scaleFactor,
height: size.height * scaleFactor
)
let renderer = UIGraphicsImageRenderer(size: targetSize)
let scaledImage = renderer.image { _ in
self.draw(in: .init(
origin: .init(
x: (targetSize.width - scaledImageSize.width) / 2.0,
y: (targetSize.height - scaledImageSize.height) / 2.0),
size: scaledImageSize))
}
return scaledImage
}
func scaledJPGData(compressionQuality: CGFloat = 0.5) -> Data {
let targetSize = CGSize(
width: size.width / UIScreen.main.scale,
height: size.height / UIScreen.main.scale)
let renderer = UIGraphicsImageRenderer(size: targetSize)
let resized = renderer.image { _ in
self.draw(in: .init(origin: .zero, size: targetSize))
}
return resized.jpegData(compressionQuality: compressionQuality)!
}
}
이후 위에서 만든 메서드들을 사용하여 문제를 해결할 수 있었습니다.
let imageData: Data
imageData = (selectedImage?.scaleToFit().scaledJPGData())!
let imageParam = ChatQuery.ChatCompletionMessageParam.ChatCompletionUserMessageParam.init(
content:
.vision([
.chatCompletionContentPartImageParam(.init(imageUrl: .init(url: imageData, detail: .auto)))
])
)
얻은 교훈
사진을 다룰 때는 카메라로 찍은 사진과 앨범에 저장된 사진은 서버에 전송할 때 에러가 발생할 수 있으므로 UIGraphicsImageRenderer를 사용하여 이미지를 다시 스케일링해보는 것도 방법인 것 같습니다. 추후 공부 필요.
'SwiftUI > 에러해결' 카테고리의 다른 글
SwiftUI - Global functions are not supported in this predicate (SwiftData 에러) (0) | 2024.09.01 |
---|---|
SwiftUI - Observable 여러 뷰에서 데이터 업데이트 안됨 (0) | 2024.08.21 |
PhotosPicker 사진 회전되어 출력되는 현상 해결 (0) | 2024.07.10 |
SwiftData Fatal Error in ModelContainer.swift 에러 (0) | 2024.06.22 |
JSONDecoder로 Decode할 때 에러 (0) | 2024.05.08 |