From 1b51316ab6a54a14dd0578feef3e1fe46c094aa6 Mon Sep 17 00:00:00 2001 From: Wilhelm Oks Date: Fri, 13 Dec 2024 14:41:26 +0100 Subject: [PATCH] AuthToken, ImageDataConversion --- Sources/SwiftDevRant/AuthToken.swift | 10 +++ .../SwiftDevRant/ImageDataConversion.swift | 87 +++++++++++++++++++ 2 files changed, 97 insertions(+) create mode 100644 Sources/SwiftDevRant/AuthToken.swift create mode 100644 Sources/SwiftDevRant/ImageDataConversion.swift diff --git a/Sources/SwiftDevRant/AuthToken.swift b/Sources/SwiftDevRant/AuthToken.swift new file mode 100644 index 0000000..793cf65 --- /dev/null +++ b/Sources/SwiftDevRant/AuthToken.swift @@ -0,0 +1,10 @@ +public struct AuthToken: Codable, Hashable { + public struct Container: Codable { + public let auth_token: AuthToken + } + + public let id: Int + public let key: String + public let expire_time: Int + public let user_id: Int +} diff --git a/Sources/SwiftDevRant/ImageDataConversion.swift b/Sources/SwiftDevRant/ImageDataConversion.swift new file mode 100644 index 0000000..bd51d26 --- /dev/null +++ b/Sources/SwiftDevRant/ImageDataConversion.swift @@ -0,0 +1,87 @@ +#if os(iOS) +import UIKit +#elseif os(macOS) +import AppKit +#endif + +private struct ImageHeaderData { + static let png: UInt8 = 0x89 + static let jpeg: UInt8 = 0xFF + static let gif: UInt8 = 0x47 + static let tiff_01: UInt8 = 0x49 + static let tiff_02: UInt8 = 0x4D +} + +enum ImageFormat { + case png + case jpeg + case gif + case tiff +} + +extension Data { + var imageFormat: ImageFormat? { + let buffer = self.first + if buffer == ImageHeaderData.png { + return .png + } else if buffer == ImageHeaderData.jpeg { + return .jpeg + } else if buffer == ImageHeaderData.gif { + return .gif + } else if buffer == ImageHeaderData.tiff_01 || buffer == ImageHeaderData.tiff_02 { + return .tiff + } else { + return nil + } + } +} + +public protocol ImageDataConverter { + /// Converts the image `data` to another format and returns the resulting Data. + func convert(_ data: Data) -> Data +} + +public extension ImageDataConverter { + #if os(macOS) + func jpegData(from image: NSImage) -> Data? { + guard let cgImage = image.cgImage(forProposedRect: nil, context: nil, hints: nil) else { return nil } + let bitmapRep = NSBitmapImageRep(cgImage: cgImage) + return bitmapRep.representation(using: .jpeg, properties: [:]) + } + #endif +} + +extension Collection where Element == ImageDataConverter { + /// Applies all converters to the provided `data` sequentially and returns the result. + func convert(_ data: Data) -> Data { + var result = data + for converter in self { + result = converter.convert(result) + } + return result + } +} + +/// An `ImageDataConverter` that converts image formats which are not supported by devRant to jpeg. +/// Data of supported formats is just returned without any conversion. +/// If the conversion fails, the original Data is returned. +public struct UnsupportedToJpegImageDataConverter: ImageDataConverter { + public func convert(_ data: Data) -> Data { + switch data.imageFormat { + case nil: // Format not recognized so it's probably not supported by devRant. + #if os(iOS) + return UIImage(data: data)?.jpegData(compressionQuality: 1) ?? data + #elseif os(macOS) + return NSImage(data: data).flatMap(jpegData) ?? data + #else + return data // This converter doesn't support platforms other than iOS and macOS. If you need to support other platforms, you can implement and use an own converter. + #endif + default: // Supported format recognized. No conversion needed. + return data + } + } +} + +public extension ImageDataConverter where Self == UnsupportedToJpegImageDataConverter { + static var unsupportedToJpeg: Self { Self() } +}