88 lines
2.8 KiB
Swift
Raw Normal View History

2024-12-13 13:41:26 +00:00
#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() }
}