<commit_before>import Foundation
import ImageIO

//TODO: Copy/Paste documentation from ImageIO

/** ImageSource objects, available in OS X v10.4 or later and iOS 4.0 and later, abstract the data-reading task. An image source can read image data from a URL, a CFData object, or a data consumer.

    After creating a ImageSource object for the appropriate source, you can obtain images, thumbnails, image properties, and other image information.
    - seealso: [CGImageSource](https://developer.apple.com/library/mac/documentation/GraphicsImaging/Reference/CGImageSource/index.html)
 */
public class ImageSource {
  /// Reference to CGImageSource object
  let imageSource: CGImageSource
  
  /**
   Creates an image source that reads from a location specified by a URL.
   
   - parameter url:     The URL to read from.
   - parameter options: An array of `ImageSource.Options` that specifies additional creation options. See `ImageSource.Options` for the keys you can supply.
   
   - returns: An `ImageSource` or nil, if `ImageSource` cannot be created for whatever reason.
   - seealso: `CGImageSourceCreateWithURL`
   */
  public init?(url: NSURL, options: [Options]?) {
    guard let imageSource = CGImageSourceCreateWithURL(url as CFURL, options?.rawOptions()) else { return nil }
    self.imageSource = imageSource
  }
  
  /**
   Creates an image source that reads from a Foundation data object.
   
   - parameter data:    The data object to read from.
   - parameter options: An array of `ImageSource.Options` that specifies additional creation options. See `ImageSource.Options` for the keys you can supply.
   
   - returns: An `ImageSource` or nil, if `ImageSource` cannot be created for whatever reason.
   - seealso: `CGImageSourceCreateWithData`
   */
  public init?(data: NSData, options: [Options]?) {
    guard let imageSource = CGImageSourceCreateWithData(data as CFData, options?.rawOptions()) else { return nil }
    self.imageSource = imageSource
  }
  
  /**
   Creates an image source wrapper around `CGImageSource`
   
   - parameter imageSource: `CGImageSource` object to wrap around
   
   - returns: An `ImageSource` for `CGImageSource`
   */
  public init(imageSource: CGImageSource) {
    self.imageSource = imageSource
  }
  
  //TODO: CGImageSourceCreateWithDataProvider
  
  /**
   Available options which you can submit for various `ImageSource` functions
   
   - TypeIdentifierHint: The best guess of the uniform type identifier (UTI) for the format of the image source file. This key can be provided in the options dictionary when you create a `ImageSource` object.
   - ShouldAllowFloat: Whether the image should be returned as a CGImage object that uses floating-point values, if supported by the file format. CGImage objects that use extended-range floating-point values may require additional processing to render in a pleasing manner. The default value is `true`.
   - ShouldCache: Whether the image should be cached in a decoded form. The default value is `false` in 32-bit, `true` in 64-bit. This key can be provided in the options array that you can pass to the methods `propertiesForImage` and `properties`.
   - CreateThumbnailFromImageIfAbsent: Whether a thumbnail should be automatically created for an image if a thumbnail isn't present in the image source file. The thumbnail is created from the full image, subject to the limit specified by `kCGImageSourceThumbnailMaxPixelSize`. If a maximum pixel size isn't specified, then the thumbnail is the size of the full image, which in most cases is not desirable. The default value is `false`. This key can be provided in the options array that you pass to the method `createThumbnail`.
   - CreateThumbnailFromImageAlways: Whether a thumbnail should be created from the full image even if a thumbnail is present in the image source file. The thumbnail is created from the full image, subject to the limit specified by `kCGImageSourceThumbnailMaxPixelSize`. If a maximum pixel size isn't specified, then the thumbnail is the size of the full image, which probably isn't what you want. The default value is `false`. This key can be provided in the options array that you can pass to the method `createThumbnail`
   - ThumbnailMaxPixelSize: The maximum width and height in pixels of a thumbnail. If this key is not specified, the width and height of a thumbnail is not limited and thumbnails may be as big as the image itself. This key can be provided in the options array that you pass to the method `createThumbnail`
   - CreateThumbnailWithTransform: Whether the thumbnail should be rotated and scaled according to the orientation and pixel aspect ratio of the full image. The default value is `false`.
   */
  public enum Options {
    case TypeIdentifierHint(UTI: String)
    case ShouldAllowFloat(Bool)
    case ShouldCache(Bool)
    case CreateThumbnailFromImageIfAbsent(Bool)
    case CreateThumbnailFromImageAlways(Bool)
    case ThumbnailMaxPixelSize(Int)
    case CreateThumbnailWithTransform(Bool)
  }
}

public extension ImageSource.Options {
  /// Converts ImageSource.Options to ImageIO key/value options
  public var imageIOOption: (key: String, value: AnyObject) {
    switch self {
    case .TypeIdentifierHint(let UTI):
      return (key: kCGImageSourceTypeIdentifierHint as String, value: UTI)
    case .ShouldAllowFloat(let allow):
      return (key: kCGImageSourceShouldAllowFloat as String, value: allow)
    case .ShouldCache(let shouldCache):
      return (key: kCGImageSourceShouldCache as String, value: shouldCache)
    case .CreateThumbnailFromImageIfAbsent(let createThumbnail):
      return (key: kCGImageSourceCreateThumbnailFromImageIfAbsent as String, value: createThumbnail)
    case .CreateThumbnailFromImageAlways(let createThumbnail):
      return (key: kCGImageSourceCreateThumbnailFromImageAlways as String, value: createThumbnail)
    case .ThumbnailMaxPixelSize(let size):
      return (key: kCGImageSourceThumbnailMaxPixelSize as String, value: size)
    case .CreateThumbnailWithTransform(let createWithTransform):
      return (key: kCGImageSourceCreateThumbnailWithTransform as String, value: createWithTransform)
    }
  }
}

#if swift(>=3.0)
  public extension Sequence where Iterator.Element == ImageSource.Options {
    /// Converts array of ImageSource.Options to ImageIO dictionary of options
    func rawOptions() -> CFDictionary {
      var dictionary: [String: AnyObject] = [:]
      for option in self {
        let (key, value) = option.imageIOOption
        dictionary[key] = value
      }
      
      return dictionary as CFDictionary
    }
  }
#else
  public extension SequenceType where Generator.Element == ImageSource.Options {
    /// Converts array of ImageSource.Options to ImageIO dictionary of options
    func rawOptions() -> CFDictionary {
      var dictionary: [String: AnyObject] = [:]
      for option in self {
        let (key, value) = option.imageIOOption
        dictionary[key] = value
      }
      
      return dictionary as CFDictionary
    }
  }
#endif

public final class IncrementalImageSource: ImageSource {
}

public extension ImageSource {
  /// Returns an array of the UTIs that are supported for image sources.
  public static func supportedUTIs() -> [String] {
    let identifiers = CGImageSourceCopyTypeIdentifiers() as [AnyObject] as! [String]
    return identifiers
  }
  
  /// Returns whether ImageSource supports provided s`UTI`
  public static func supportsUTI(UTI: String) -> Bool {
    return supportedUTIs().contains(UTI)
  }
}

//MARK: - Creating Images From an Image Source
public extension ImageSource {
  /**
   Creates a CGImage object for the image data associated with the specified index in an image source.
   
   - parameter index:   The index that specifies the location of the image. The index is zero-based.
   - parameter options: An array that specifies additional creation options.
   
   - returns: Returns a `CGImage` object.
   */
  public func createImage(atIndex index: Int = 0, options: [Options]? = nil) -> CGImage? {
    return CGImageSourceCreateImageAtIndex(imageSource, index, options?.rawOptions())
  }
  
  /**
   Creates a thumbnail image of the image located at a specified location in an image source.
   
   - parameter index:   The index that specifies the location of the image. The index is zero-based.
   - parameter options: An array that specifies additional creation options.
   
   - returns: A `CGImage` object.
   */
  public func createThumbnail(atIndex index: Int = 0, options: [Options]? = nil) -> CGImage? {
    return CGImageSourceCreateThumbnailAtIndex(imageSource, index, options?.rawOptions())
  }
  
  public static func createIncremental(options options: [Options]? = nil) -> IncrementalImageSource {
    return IncrementalImageSource(imageSource: CGImageSourceCreateIncremental(options?.rawOptions()))
  }
}

// convenient
public extension ImageSource {
  /**
   Creates a thumbnail image of the image located at first index in an image source with the maximum width and height in pixels of a thumbnail equal to `size`.
   
   CreateThumbnailFromImageAlways = true<commit_msg>Add createIncremental documentation<commit_after>import Foundation
import ImageIO

//TODO: Copy/Paste documentation from ImageIO

/** ImageSource objects, available in OS X v10.4 or later and iOS 4.0 and later, abstract the data-reading task. An image source can read image data from a URL, a CFData object, or a data consumer.

    After creating a ImageSource object for the appropriate source, you can obtain images, thumbnails, image properties, and other image information.
    - seealso: [CGImageSource](https://developer.apple.com/library/mac/documentation/GraphicsImaging/Reference/CGImageSource/index.html)
 */
public class ImageSource {
  /// Reference to CGImageSource object
  let imageSource: CGImageSource
  
  /**
   Creates an image source that reads from a location specified by a URL.
   
   - parameter url:     The URL to read from.
   - parameter options: An array of `ImageSource.Options` that specifies additional creation options. See `ImageSource.Options` for the keys you can supply.
   
   - returns: An `ImageSource` or nil, if `ImageSource` cannot be created for whatever reason.
   - seealso: `CGImageSourceCreateWithURL`
   */
  public init?(url: NSURL, options: [Options]?) {
    guard let imageSource = CGImageSourceCreateWithURL(url as CFURL, options?.rawOptions()) else { return nil }
    self.imageSource = imageSource
  }
  
  /**
   Creates an image source that reads from a Foundation data object.
   
   - parameter data:    The data object to read from.
   - parameter options: An array of `ImageSource.Options` that specifies additional creation options. See `ImageSource.Options` for the keys you can supply.
   
   - returns: An `ImageSource` or nil, if `ImageSource` cannot be created for whatever reason.
   - seealso: `CGImageSourceCreateWithData`
   */
  public init?(data: NSData, options: [Options]?) {
    guard let imageSource = CGImageSourceCreateWithData(data as CFData, options?.rawOptions()) else { return nil }
    self.imageSource = imageSource
  }
  
  /**
   Creates an image source wrapper around `CGImageSource`
   
   - parameter imageSource: `CGImageSource` object to wrap around
   
   - returns: An `ImageSource` for `CGImageSource`
   */
  public init(imageSource: CGImageSource) {
    self.imageSource = imageSource
  }
  
  //TODO: CGImageSourceCreateWithDataProvider
  
  /**
   Available options which you can submit for various `ImageSource` functions
   
   - TypeIdentifierHint: The best guess of the uniform type identifier (UTI) for the format of the image source file. This key can be provided in the options dictionary when you create a `ImageSource` object.
   - ShouldAllowFloat: Whether the image should be returned as a CGImage object that uses floating-point values, if supported by the file format. CGImage objects that use extended-range floating-point values may require additional processing to render in a pleasing manner. The default value is `true`.
   - ShouldCache: Whether the image should be cached in a decoded form. The default value is `false` in 32-bit, `true` in 64-bit. This key can be provided in the options array that you can pass to the methods `propertiesForImage` and `properties`.
   - CreateThumbnailFromImageIfAbsent: Whether a thumbnail should be automatically created for an image if a thumbnail isn't present in the image source file. The thumbnail is created from the full image, subject to the limit specified by `kCGImageSourceThumbnailMaxPixelSize`. If a maximum pixel size isn't specified, then the thumbnail is the size of the full image, which in most cases is not desirable. The default value is `false`. This key can be provided in the options array that you pass to the method `createThumbnail`.
   - CreateThumbnailFromImageAlways: Whether a thumbnail should be created from the full image even if a thumbnail is present in the image source file. The thumbnail is created from the full image, subject to the limit specified by `kCGImageSourceThumbnailMaxPixelSize`. If a maximum pixel size isn't specified, then the thumbnail is the size of the full image, which probably isn't what you want. The default value is `false`. This key can be provided in the options array that you can pass to the method `createThumbnail`
   - ThumbnailMaxPixelSize: The maximum width and height in pixels of a thumbnail. If this key is not specified, the width and height of a thumbnail is not limited and thumbnails may be as big as the image itself. This key can be provided in the options array that you pass to the method `createThumbnail`
   - CreateThumbnailWithTransform: Whether the thumbnail should be rotated and scaled according to the orientation and pixel aspect ratio of the full image. The default value is `false`.
   */
  public enum Options {
    case TypeIdentifierHint(UTI: String)
    case ShouldAllowFloat(Bool)
    case ShouldCache(Bool)
    case CreateThumbnailFromImageIfAbsent(Bool)
    case CreateThumbnailFromImageAlways(Bool)
    case ThumbnailMaxPixelSize(Int)
    case CreateThumbnailWithTransform(Bool)
  }
}

public extension ImageSource.Options {
  /// Converts ImageSource.Options to ImageIO key/value options
  public var imageIOOption: (key: String, value: AnyObject) {
    switch self {
    case .TypeIdentifierHint(let UTI):
      return (key: kCGImageSourceTypeIdentifierHint as String, value: UTI)
    case .ShouldAllowFloat(let allow):
      return (key: kCGImageSourceShouldAllowFloat as String, value: allow)
    case .ShouldCache(let shouldCache):
      return (key: kCGImageSourceShouldCache as String, value: shouldCache)
    case .CreateThumbnailFromImageIfAbsent(let createThumbnail):
      return (key: kCGImageSourceCreateThumbnailFromImageIfAbsent as String, value: createThumbnail)
    case .CreateThumbnailFromImageAlways(let createThumbnail):
      return (key: kCGImageSourceCreateThumbnailFromImageAlways as String, value: createThumbnail)
    case .ThumbnailMaxPixelSize(let size):
      return (key: kCGImageSourceThumbnailMaxPixelSize as String, value: size)
    case .CreateThumbnailWithTransform(let createWithTransform):
      return (key: kCGImageSourceCreateThumbnailWithTransform as String, value: createWithTransform)
    }
  }
}

#if swift(>=3.0)
  public extension Sequence where Iterator.Element == ImageSource.Options {
    /// Converts array of ImageSource.Options to ImageIO dictionary of options
    func rawOptions() -> CFDictionary {
      var dictionary: [String: AnyObject] = [:]
      for option in self {
        let (key, value) = option.imageIOOption
        dictionary[key] = value
      }
      
      return dictionary as CFDictionary
    }
  }
#else
  public extension SequenceType where Generator.Element == ImageSource.Options {
    /// Converts array of ImageSource.Options to ImageIO dictionary of options
    func rawOptions() -> CFDictionary {
      var dictionary: [String: AnyObject] = [:]
      for option in self {
        let (key, value) = option.imageIOOption
        dictionary[key] = value
      }
      
      return dictionary as CFDictionary
    }
  }
#endif

public final class IncrementalImageSource: ImageSource {
}

public extension ImageSource {
  /// Returns an array of the UTIs that are supported for image sources.
  public static func supportedUTIs() -> [String] {
    let identifiers = CGImageSourceCopyTypeIdentifiers() as [AnyObject] as! [String]
    return identifiers
  }
  
  /// Returns whether ImageSource supports provided s`UTI`
  public static func supportsUTI(UTI: String) -> Bool {
    return supportedUTIs().contains(UTI)
  }
}

//MARK: - Creating Images From an Image Source
public extension ImageSource {
  /**
   Creates a CGImage object for the image data associated with the specified index in an image source.
   
   - parameter index:   The index that specifies the location of the image. The index is zero-based.
   - parameter options: An array that specifies additional creation options.
   
   - returns: Returns a `CGImage` object.
   */
  public func createImage(atIndex index: Int = 0, options: [Options]? = nil) -> CGImage? {
    return CGImageSourceCreateImageAtIndex(imageSource, index, options?.rawOptions())
  }
  
  /**
   Creates a thumbnail image of the image located at a specified location in an image source.
   
   - parameter index:   The index that specifies the location of the image. The index is zero-based.
   - parameter options: An array that specifies additional creation options.
   
   - returns: A `CGImage` object.
   */
  public func createThumbnail(atIndex index: Int = 0, options: [Options]? = nil) -> CGImage? {
    return CGImageSourceCreateThumbnailAtIndex(imageSource, index, options?.rawOptions())
  }
  
  /**
   Create an incremental image source.
   
   - parameter options: An array that specifies additional creation options.
   
   - returns: Returns an image source object.
   - seealso: `CGImageSourceCreateIncremental`
   */
  public static func createIncremental(options options: [Options]? = nil) -> IncrementalImageSource {
    return IncrementalImageSource(imageSource: CGImageSourceCreateIncremental(options?.rawOptions()))
  }
}

// convenient
public extension ImageSource {
  /**
   Creates a thumbnail image of the image located at first index in an image source with the maximum width and height in pixels of a thumbnail equal to `size`.
   
   CreateThumbnailFromImageAlways = true
{'fraction_non_alphanumeric': 0.06700167504187604, 'fraction_numerical': 0.0014048738315232073, 'mean_word_length': 3.874374506189097, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 19, 'https://': 2, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5969687', 'n_tokens_mistral': 4902, 'n_tokens_neox': 4793, 'n_words': 2057}