UIImage+Haneke.swift 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081
  1. //
  2. // UIImage+Haneke.swift
  3. // Haneke
  4. //
  5. // Created by Hermes Pique on 8/10/14.
  6. // Copyright (c) 2014 Haneke. All rights reserved.
  7. //
  8. import UIKit
  9. extension UIImage {
  10. func hnk_imageByScaling(toSize size: CGSize) -> UIImage {
  11. UIGraphicsBeginImageContextWithOptions(size, !hnk_hasAlpha(), 0.0)
  12. draw(in: CGRect(x: 0, y: 0, width: size.width, height: size.height))
  13. let resizedImage = UIGraphicsGetImageFromCurrentImageContext()
  14. UIGraphicsEndImageContext()
  15. return resizedImage!
  16. }
  17. func hnk_hasAlpha() -> Bool {
  18. guard let alphaInfo = self.cgImage?.alphaInfo else { return false }
  19. switch alphaInfo {
  20. case .first, .last, .premultipliedFirst, .premultipliedLast, .alphaOnly:
  21. return true
  22. case .none, .noneSkipFirst, .noneSkipLast:
  23. return false
  24. }
  25. }
  26. func hnk_data(compressionQuality: Float = 1.0) -> Data! {
  27. let hasAlpha = self.hnk_hasAlpha()
  28. let data = hasAlpha ? self.pngData() : self.jpegData(compressionQuality: CGFloat(compressionQuality))
  29. return data
  30. }
  31. func hnk_decompressedImage() -> UIImage! {
  32. let originalImageRef = self.cgImage
  33. let originalBitmapInfo = originalImageRef?.bitmapInfo
  34. guard let alphaInfo = originalImageRef?.alphaInfo else { return UIImage() }
  35. // See: http://stackoverflow.com/questions/23723564/which-cgimagealphainfo-should-we-use
  36. var bitmapInfo = originalBitmapInfo
  37. switch alphaInfo {
  38. case .none:
  39. let rawBitmapInfoWithoutAlpha = (bitmapInfo?.rawValue)! & ~CGBitmapInfo.alphaInfoMask.rawValue
  40. let rawBitmapInfo = rawBitmapInfoWithoutAlpha | CGImageAlphaInfo.noneSkipFirst.rawValue
  41. bitmapInfo = CGBitmapInfo(rawValue: rawBitmapInfo)
  42. case .premultipliedFirst, .premultipliedLast, .noneSkipFirst, .noneSkipLast:
  43. break
  44. case .alphaOnly, .last, .first: // Unsupported
  45. return self
  46. }
  47. let colorSpace = CGColorSpaceCreateDeviceRGB()
  48. let pixelSize = CGSize(width: self.size.width * self.scale, height: self.size.height * self.scale)
  49. guard let context = CGContext(data: nil, width: Int(ceil(pixelSize.width)), height: Int(ceil(pixelSize.height)), bitsPerComponent: (originalImageRef?.bitsPerComponent)!, bytesPerRow: 0, space: colorSpace, bitmapInfo: (bitmapInfo?.rawValue)!) else {
  50. return self
  51. }
  52. let imageRect = CGRect(x: 0, y: 0, width: pixelSize.width, height: pixelSize.height)
  53. UIGraphicsPushContext(context)
  54. // Flip coordinate system. See: http://stackoverflow.com/questions/506622/cgcontextdrawimage-draws-image-upside-down-when-passed-uiimage-cgimage
  55. context.translateBy(x: 0, y: pixelSize.height)
  56. context.scaleBy(x: 1.0, y: -1.0)
  57. // UIImage and drawInRect takes into account image orientation, unlike CGContextDrawImage.
  58. self.draw(in: imageRect)
  59. UIGraphicsPopContext()
  60. guard let decompressedImageRef = context.makeImage() else {
  61. return self
  62. }
  63. let scale = UIScreen.main.scale
  64. let image = UIImage(cgImage: decompressedImageRef, scale:scale, orientation:UIImage.Orientation.up)
  65. return image
  66. }
  67. }