{
"extension": ".swift",
"source": "#if os(iOS)\nimport UIKit\n#elseif os(macOS)\nimport AppKit\n#endif\n\nprivate struct ImageHeaderData {\n static let png: UInt8 = 0x89\n static let jpeg: UInt8 = 0xFF\n static let gif: UInt8 = 0x47\n static let tiff_01: UInt8 = 0x49\n static let tiff_02: UInt8 = 0x4D\n}\n\nenum ImageFormat {\n case png\n case jpeg\n case gif\n case tiff\n}\n\nextension Data {\n var imageFormat: ImageFormat? {\n let buffer = self.first\n if buffer == ImageHeaderData.png {\n return .png\n } else if buffer == ImageHeaderData.jpeg {\n return .jpeg\n } else if buffer == ImageHeaderData.gif {\n return .gif\n } else if buffer == ImageHeaderData.tiff_01 || buffer == ImageHeaderData.tiff_02 {\n return .tiff\n } else {\n return nil\n }\n }\n}\n\npublic protocol ImageDataConverter {\n /// Converts the image `data` to another format and returns the resulting Data.\n func convert(_ data: Data) -> Data\n}\n\npublic extension ImageDataConverter {\n #if os(macOS)\n func jpegData(from image: NSImage) -> Data? {\n guard let cgImage = image.cgImage(forProposedRect: nil, context: nil, hints: nil) else { return nil }\n let bitmapRep = NSBitmapImageRep(cgImage: cgImage)\n return bitmapRep.representation(using: .jpeg, properties: [:])\n }\n #endif\n}\n\nextension Collection where Element == ImageDataConverter {\n /// Applies all converters to the provided `data` sequentially and returns the result.\n func convert(_ data: Data) -> Data {\n var result = data\n for converter in self {\n result = converter.convert(result)\n }\n return result\n }\n}\n\n/// An `ImageDataConverter` that converts image formats which are not supported by devRant to jpeg.\n/// Data of supported formats is just returned without any conversion.\n/// If the conversion fails, the original Data is returned.\npublic struct UnsupportedToJpegImageDataConverter: ImageDataConverter {\n public func convert(_ data: Data) -> Data {\n switch data.imageFormat {\n case nil: // Format not recognized so it's probably not supported by devRant.\n #if os(iOS)\n return UIImage(data: data)?.jpegData(compressionQuality: 1) ?? data\n #elseif os(macOS)\n return NSImage(data: data).flatMap(jpegData) ?? data\n #else\n 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.\n #endif\n default: // Supported format recognized. No conversion needed.\n return data\n }\n }\n}\n\npublic extension ImageDataConverter where Self == UnsupportedToJpegImageDataConverter {\n static var unsupportedToJpeg: Self { Self() }\n}\n",
"review": "# 8\n\n## Bugs\n- No apparent bugs are evident within the given code; it seems to perform as intended.\n\n## Optimizations\n- The `convert` function in `UnsupportedToJpegImageDataConverter` makes use of platform-specific conditional compilation. This strategy might introduce code repetition. Consider abstracting platform-specific code into separate helper functions to avoid repetition.\n- Utilize guard statements in place of nested `if-else` to improve readability when determining the image format.\n- Consider using `switch` with associated values pattern, as it might make additions to image formats more straightforward.\n\n## Good points\n- The code makes good use of conditional compilation to cater to differences between iOS and macOS.\n- The implementation of the \"UnsupportedToJpegImageDataConverter\" effectively handles unsupported image formats by converting them to JPEG, which is a practical approach.\n- Use of extensions to add functionality to `Data` makes the code clean and modular.\n- Clear and descriptive documentation provided for methods and protocols.\n- Encapsulation using `private struct` for header data improves the code organization and readability.\n\n## Summary\nThe code is well-organized and provides functionality to determine image formats and convert unsupported formats to JPEG. It efficiently caters to platform-specific needs while maintaining a modular approach through the use of extensions. There is potential for optimization in terms of code readability and efficiency regarding image format determination and handling platform-specific tasks.\n\n## Open source alternatives\n- **SDWebImage**: A powerful tool for asynchronous image downloading and caching, equipped with functionalities for image format detection and conversion.\n- **AlamofireImage**: Another option that offers image downloading and caching capabilities with additional support for handling different image formats.",
"filename": "ImageDataConversion.swift",
"path": "Sources/SwiftDevRant/Conversion/ImageDataConversion.swift",
"directory": "Conversion",
"grade": 8,
"size": 2833,
"line_count": 88
}