{
  "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
}