Skip to content

Commit 2bfae04

Browse files
committed
[Refactor] #183 - 주고받는 데이터 data -> CGImage로 변경
1 parent eb09b42 commit 2bfae04

4 files changed

Lines changed: 16 additions & 54 deletions

File tree

Neki-iOS/Core/Sources/ImageTransform/Data/DefaultImageTransformRepository.swift

Lines changed: 5 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,9 @@
66
//
77

88
import Foundation
9-
import CoreML
109
import Vision
11-
import UniformTypeIdentifiers
1210
import ComposableArchitecture
1311
import CoreImage
14-
import os
1512

1613
public final class DefaultImageTransformRepository: ImageTransformRepository {
1714

@@ -28,17 +25,17 @@ public final class DefaultImageTransformRepository: ImageTransformRepository {
2825
}
2926
}
3027

31-
public func transform(data inputData: Data) async throws -> Data {
28+
public func transform(image inputImage: CGImage) async throws -> CGImage {
3229
let visionModel = try await modelTask.value
3330

3431
return try await Task(priority: .userInitiated) {
3532
let request = VNCoreMLRequest(model: visionModel)
3633
request.imageCropAndScaleOption = .scaleFit
3734

38-
let handler = VNImageRequestHandler(data: inputData)
35+
let handler = VNImageRequestHandler(cgImage: inputImage)
3936
try handler.perform([request])
4037

41-
return try self.extractData(from: request.results)
38+
return try self.extractCGImage(from: request.results)
4239
}.value
4340
}
4441
}
@@ -47,48 +44,18 @@ public final class DefaultImageTransformRepository: ImageTransformRepository {
4744
// MARK: - DefaultImageTransformRepository Private Helpers
4845

4946
private extension DefaultImageTransformRepository {
50-
51-
/// Vision 결과물을 추출하여 최종 PNG Data로 변환하는 로직
52-
func extractData(from results: [VNObservation]?) throws -> Data {
53-
// Vision 결과물(CVPixelBuffer)
47+
func extractCGImage(from results: [VNObservation]?) throws -> CGImage {
5448
guard let observations = results as? [VNPixelBufferObservation],
5549
let pixelBuffer = observations.first?.pixelBuffer else {
5650
throw ImageTransformRepositoryError.renderingFailed
5751
}
5852

59-
// 픽셀 데이터를 이미지(CIImage -> CGImage)로 렌더링
6053
let ciImage = CIImage(cvPixelBuffer: pixelBuffer)
6154
guard let outputCGImage = self.ciContext.createCGImage(ciImage, from: ciImage.extent) else {
6255
throw ImageTransformRepositoryError.renderingFailed
6356
}
6457

65-
// 렌더링된 이미지를 PNG 형식의 Data로 압축
66-
return try compressToPNG(cgImage: outputCGImage)
67-
}
68-
69-
/// CGImage를 PNG Data로 압축하는 메서드 (너무 어렵다...)
70-
/// UIImage(cgImage:).pngData() 이거 쓰면 딸깍이긴 하지만 Data 레이어에 UIKit 의존성이 생겨버림..
71-
func compressToPNG(cgImage: CGImage) throws -> Data {
72-
guard let cfMutableData = CFDataCreateMutable(kCFAllocatorDefault, 0) else {
73-
throw ImageTransformRepositoryError.destinationCreationFailed
74-
}
75-
76-
guard let destination = CGImageDestinationCreateWithData(
77-
cfMutableData,
78-
UTType.png.identifier as CFString,
79-
1,
80-
nil
81-
) else {
82-
throw ImageTransformRepositoryError.destinationCreationFailed
83-
}
84-
85-
CGImageDestinationAddImage(destination, cgImage, nil)
86-
87-
if CGImageDestinationFinalize(destination) {
88-
return cfMutableData as Data
89-
} else {
90-
throw ImageTransformRepositoryError.dataCompressionFailed
91-
}
58+
return outputCGImage
9259
}
9360
}
9461

Neki-iOS/Core/Sources/ImageTransform/Domain/ImageTransformClient.swift

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,18 +7,19 @@
77

88
import Foundation
99
import ComposableArchitecture
10+
import CoreGraphics
1011

1112
public struct ImageTransformClient {
12-
public var transformImage: @Sendable (_ image: Data) async throws -> Data
13+
public var transformImage: @Sendable (_ image: CGImage) async throws -> CGImage
1314
}
1415

1516
extension ImageTransformClient: DependencyKey {
1617
public static let liveValue: ImageTransformClient = {
1718
@Dependency(\.imageTransformRepository) var repository
1819

1920
return ImageTransformClient(
20-
transformImage: { inputData in
21-
return try await repository.transform(data: inputData)
21+
transformImage: { inputImage in
22+
return try await repository.transform(image: inputImage)
2223
}
2324
)
2425
}()
@@ -33,8 +34,8 @@ extension DependencyValues {
3334

3435
extension ImageTransformClient: TestDependencyKey {
3536
public static let testValue = ImageTransformClient(
36-
transformImage: { inputData in
37-
return inputData
37+
transformImage: { inputImage in
38+
return inputImage
3839
}
3940
)
4041
}

Neki-iOS/Core/Sources/ImageTransform/Domain/ImageTransformRepository.swift

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,22 +6,19 @@
66
//
77

88
import Foundation
9+
import CoreGraphics
910

1011
public protocol ImageTransformRepository: Sendable {
11-
func transform(data: Data) async throws -> Data
12+
func transform(image: CGImage) async throws -> CGImage
1213
}
1314

1415
public enum ImageTransformRepositoryError: LocalizedError {
1516
case modelLoadFailed
16-
case destinationCreationFailed
17-
case dataCompressionFailed
1817
case renderingFailed
1918

2019
public var errorDescription: String? {
2120
switch self {
2221
case .modelLoadFailed: return "AI 모델을 불러오는데 실패했습니다."
23-
case .destinationCreationFailed: return "데이터 저장소를 생성할 수 없습니다."
24-
case .dataCompressionFailed: return "이미지 압축에 실패했습니다."
2522
case .renderingFailed: return "이미지 렌더링에 실패했습니다."
2623
}
2724
}

Neki-iOS/Core/Sources/ImageTransform/Presentation/ImageTransformFeature.swift

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -55,15 +55,12 @@ public struct ImageTransformFeature {
5555
let originalRatio = inputImage.size.width / inputImage.size.height
5656

5757
guard let squaredImage = self.prepareSquareForCoreML(image: inputImage, targetSize: 512),
58-
let inputData = squaredImage.pngData() else {
58+
let inputCGImage = squaredImage.cgImage else {
5959
throw ImageTransformError.processingFailed
6060
}
6161

62-
let resultData = try await imageTransformClient.transformImage(inputData)
63-
64-
guard let resultSquareImage = UIImage(data: resultData) else {
65-
throw ImageTransformError.resultDataReadFailed
66-
}
62+
let resultCGImage = try await imageTransformClient.transformImage(inputCGImage)
63+
let resultSquareImage = UIImage(cgImage: resultCGImage)
6764

6865
if let finalCroppedImage = self.cropToOriginalRatio(image: resultSquareImage, originalRatio: originalRatio) {
6966
await send(.transformCompleted(finalCroppedImage))

0 commit comments

Comments
 (0)