Skip to content

Commit

Permalink
Add image adapters and tests
Browse files Browse the repository at this point in the history
  • Loading branch information
morganchen12 committed Jan 3, 2024
1 parent fead303 commit ec5ab77
Show file tree
Hide file tree
Showing 3 changed files with 93 additions and 0 deletions.
40 changes: 40 additions & 0 deletions Sources/GoogleAI/PartsRepresentable.swift
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
// limitations under the License.

import Foundation
import UniformTypeIdentifiers
#if canImport(UIKit)
import UIKit // For UIImage extensions.
#elseif canImport(AppKit)
Expand Down Expand Up @@ -77,3 +78,42 @@ extension [any PartsRepresentable]: PartsRepresentable {
}
}
#endif

extension CGImage: PartsRepresentable {
public var partsValue: [ModelContent.Part] {
let output = NSMutableData()
guard let imageDestination = CGImageDestinationCreateWithData(
output, UTType.jpeg.identifier as CFString, 1, nil
) else {
Logging.default.error("[GoogleGenerativeAI] Couldn't create JPEG from CGImage.")
return []
}
CGImageDestinationAddImage(imageDestination, self, nil)
CGImageDestinationSetProperties(imageDestination, [
kCGImageDestinationLossyCompressionQuality: 0.8,
] as CFDictionary)
if CGImageDestinationFinalize(imageDestination) {
return [.data(mimetype: "image/jpeg", output as Data)]
}
Logging.default.error("[GoogleGenerativeAI] Couldn't create JPEG from CGImage.")
return []
}
}

extension CIImage: PartsRepresentable {
public var partsValue: [ModelContent.Part] {
let context = CIContext()
let jpegData = (colorSpace ?? CGColorSpace(name: CGColorSpace.sRGB))
.flatMap {
// The docs specify kCGImageDestinationLossyCompressionQuality as a supported option, but
// Swift's type system does not allow this.
// [kCGImageDestinationLossyCompressionQuality: 0.8]
context.jpegRepresentation(of: self, colorSpace: $0, options: [:])
}
if let jpegData = jpegData {
return [.data(mimetype: "image/jpeg", jpegData)]
}
Logging.default.error("[GoogleGenerativeAI] Couldn't create JPEG from CIImage.")
return []
}
}
53 changes: 53 additions & 0 deletions Tests/GoogleAITests/PartsRepresentableTests.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
// Copyright 2024 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

import XCTest

final class PartsRepresentableTests: XCTestCase {
let imageURL = Bundle.main.url(forResource: "logo", withExtension: "png")!

func testModelContentFromCGImageIsNotEmpty() throws {
guard let dataProvider = CGDataProvider(url: imageURL as CFURL) else {
XCTFail("Could not find data for url: \(imageURL)")
return
}
guard let image = CGImage(pngDataProviderSource: dataProvider,
decode: nil,
shouldInterpolate: false,
intent: .defaultIntent) else {
XCTFail("Could not construct CGImage from URL: \(imageURL)")
return
}
let modelContent = image.partsValue
XCTAssert(modelContent.count > 0, "Expected non-empty model content for CGImage: \(image)")
}

func testModelContentFromCIImageIsNotEmpty() throws {
guard let image = CIImage(contentsOf: imageURL) else {
XCTFail("Could not construct CIImage from URL: \(imageURL)")
return
}
let modelContent = image.partsValue
XCTAssert(modelContent.count > 0, "Expected non-empty model content for CGImage: \(image)")
}

func testModelContentFromUIImageIsNotEmpty() throws {
guard let image = UIImage(named: "logo.png") else {
XCTFail("Could not find image named logo.png.")
return
}
let modelContent = image.partsValue
XCTAssert(modelContent.count > 0, "Expected non-empty model content for UIImage: \(image)")
}
}
Binary file added Tests/GoogleAITests/logo.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit ec5ab77

Please sign in to comment.