ImageExtensionTests.swift 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211
  1. //
  2. // ImageExtensionTests.swift
  3. // Kingfisher
  4. //
  5. // Created by Wei Wang on 15/10/24.
  6. //
  7. // Copyright (c) 2018 Wei Wang <onevcat@gmail.com>
  8. //
  9. // Permission is hereby granted, free of charge, to any person obtaining a copy
  10. // of this software and associated documentation files (the "Software"), to deal
  11. // in the Software without restriction, including without limitation the rights
  12. // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  13. // copies of the Software, and to permit persons to whom the Software is
  14. // furnished to do so, subject to the following conditions:
  15. //
  16. // The above copyright notice and this permission notice shall be included in
  17. // all copies or substantial portions of the Software.
  18. //
  19. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  20. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  21. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  22. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  23. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  24. // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  25. // THE SOFTWARE.
  26. import XCTest
  27. import ImageIO
  28. @testable import Kingfisher
  29. class ImageExtensionTests: XCTestCase {
  30. override func setUp() {
  31. super.setUp()
  32. // Put setup code here. This method is called before the invocation of each test method in the class.
  33. }
  34. override func tearDown() {
  35. // Put teardown code here. This method is called after the invocation of each test method in the class.
  36. super.tearDown()
  37. }
  38. func testImageFormat() {
  39. var format: ImageFormat
  40. format = testImageJEPGData.kf.imageFormat
  41. XCTAssertEqual(format, ImageFormat.JPEG)
  42. format = testImagePNGData.kf.imageFormat
  43. XCTAssertEqual(format, ImageFormat.PNG)
  44. format = testImageGIFData.kf.imageFormat
  45. XCTAssertEqual(format, ImageFormat.GIF)
  46. let raw: [UInt8] = [1, 2, 3, 4, 5, 6, 7, 8]
  47. format = Data(bytes: raw).kf.imageFormat
  48. XCTAssertEqual(format, ImageFormat.unknown)
  49. }
  50. func testGenerateGIFImage() {
  51. let image = Kingfisher<Image>.animated(with: testImageGIFData, preloadAll: false)
  52. XCTAssertNotNil(image, "The image should be initiated.")
  53. #if os(iOS) || os(tvOS)
  54. let count = CGImageSourceGetCount(image!.kf.imageSource!.imageRef!)
  55. XCTAssertEqual(count, 8, "There should be 8 frames.")
  56. #else
  57. XCTAssertEqual(image!.kf.images!.count, 8, "There should be 8 frames.")
  58. XCTAssertEqual(image!.kf.duration, 0.8, accuracy: 0.001, "The image duration should be 0.8s")
  59. #endif
  60. }
  61. func testGIFRepresentation() {
  62. let image = Kingfisher<Image>.animated(with: testImageGIFData, preloadAll: false)!
  63. let data = image.kf.gifRepresentation()
  64. XCTAssertNotNil(data, "Data should not be nil")
  65. XCTAssertEqual(data?.kf.imageFormat, ImageFormat.GIF)
  66. let allLoadImage = Kingfisher<Image>.animated(with: data!, preloadAll: true)!
  67. let allLoadData = allLoadImage.kf.gifRepresentation()
  68. XCTAssertNotNil(allLoadData, "Data1 should not be nil")
  69. XCTAssertEqual(allLoadData?.kf.imageFormat, ImageFormat.GIF)
  70. }
  71. func testGenerateSingleFrameGIFImage() {
  72. let image = Kingfisher<Image>.animated(with: testImageSingleFrameGIFData, preloadAll: false)
  73. XCTAssertNotNil(image, "The image should be initiated.")
  74. #if os(iOS) || os(tvOS)
  75. let count = CGImageSourceGetCount(image!.kf.imageSource!.imageRef!)
  76. XCTAssertEqual(count, 1, "There should be 1 frames.")
  77. #else
  78. XCTAssertEqual(image!.kf.images!.count, 1, "There should be 1 frames.")
  79. XCTAssertEqual(image!.kf.duration, Double.infinity, "The image duration should be 0 since it is not animated image.")
  80. #endif
  81. }
  82. func testPreloadAllAnimationData() {
  83. let image = Kingfisher<Image>.animated(with: testImageSingleFrameGIFData, preloadAll: true)!
  84. XCTAssertNotNil(image, "The image should be initiated.")
  85. #if os(iOS) || os(tvOS)
  86. XCTAssertNil(image.kf.imageSource, "Image source should be nil")
  87. #endif
  88. XCTAssertEqual(image.kf.duration, image.kf.duration)
  89. XCTAssertEqual(image.kf.images!.count, image.kf.images!.count)
  90. }
  91. func testLoadOnlyFirstFrame() {
  92. let image = Kingfisher<Image>.animated(with: testImageGIFData,
  93. scale: 1.0,
  94. duration: 0.0,
  95. preloadAll: true,
  96. onlyFirstFrame: true)!
  97. XCTAssertNotNil(image, "The image should be initiated.")
  98. XCTAssertNil(image.kf.images, "The image should be nil")
  99. }
  100. func testSizeContent() {
  101. func getRatio(image: Image) -> CGFloat {
  102. return image.size.height / image.size.width
  103. }
  104. let image = testImage
  105. let ratio = getRatio(image: image)
  106. let targetSize = CGSize(width: 100, height: 50)
  107. let fillImage = image.kf.resize(to: targetSize, for: .aspectFill)
  108. XCTAssertEqual(getRatio(image: fillImage), ratio)
  109. XCTAssertEqual(max(fillImage.size.width, fillImage.size.height), 100)
  110. let fitImage = image.kf.resize(to: targetSize, for: .aspectFit)
  111. XCTAssertEqual(getRatio(image: fitImage), ratio)
  112. XCTAssertEqual(max(fitImage.size.width, fitImage.size.height), 50)
  113. let resizeImage = image.kf.resize(to: targetSize)
  114. XCTAssertEqual(resizeImage.size.width, 100)
  115. XCTAssertEqual(resizeImage.size.height, 50)
  116. }
  117. func testSizeConstraintByAnchor() {
  118. let size = CGSize(width: 100, height: 100)
  119. let topLeft = CGPoint(x: 0, y: 0)
  120. let top = CGPoint(x: 0.5, y: 0)
  121. let topRight = CGPoint(x: 1, y: 0)
  122. let center = CGPoint(x: 0.5, y: 0.5)
  123. let bottomRight = CGPoint(x: 1, y: 1)
  124. let invalidAnchor = CGPoint(x: -1, y: 2)
  125. let inSize = CGSize(width: 20, height: 20)
  126. let outX = CGSize(width: 120, height: 20)
  127. let outY = CGSize(width: 20, height: 120)
  128. let outSize = CGSize(width: 120, height: 120)
  129. XCTAssertEqual(size.kf.constrainedRect(for: inSize, anchor: topLeft), CGRect(x: 0, y: 0, width: 20, height: 20))
  130. XCTAssertEqual(size.kf.constrainedRect(for: outX, anchor: topLeft), CGRect(x: 0, y: 0, width: 100, height: 20))
  131. XCTAssertEqual(size.kf.constrainedRect(for: outY, anchor: topLeft), CGRect(x: 0, y: 0, width: 20, height: 100))
  132. XCTAssertEqual(size.kf.constrainedRect(for: outSize, anchor: topLeft), CGRect(x: 0, y: 0, width: 100, height: 100))
  133. XCTAssertEqual(size.kf.constrainedRect(for: inSize, anchor: top), CGRect(x: 40, y: 0, width: 20, height: 20))
  134. XCTAssertEqual(size.kf.constrainedRect(for: outX, anchor: top), CGRect(x: 0, y: 0, width: 100, height: 20))
  135. XCTAssertEqual(size.kf.constrainedRect(for: outY, anchor: top), CGRect(x: 40, y: 0, width: 20, height: 100))
  136. XCTAssertEqual(size.kf.constrainedRect(for: outSize, anchor: top), CGRect(x: 0, y: 0, width: 100, height: 100))
  137. XCTAssertEqual(size.kf.constrainedRect(for: inSize, anchor: topRight), CGRect(x: 80, y: 0, width: 20, height: 20))
  138. XCTAssertEqual(size.kf.constrainedRect(for: outX, anchor: topRight), CGRect(x: 0, y: 0, width: 100, height: 20))
  139. XCTAssertEqual(size.kf.constrainedRect(for: outY, anchor: topRight), CGRect(x: 80, y: 0, width: 20, height: 100))
  140. XCTAssertEqual(size.kf.constrainedRect(for: outSize, anchor: topRight), CGRect(x: 0, y: 0, width: 100, height: 100))
  141. XCTAssertEqual(size.kf.constrainedRect(for: inSize, anchor: center), CGRect(x: 40, y: 40, width: 20, height: 20))
  142. XCTAssertEqual(size.kf.constrainedRect(for: outX, anchor: center), CGRect(x: 0, y: 40, width: 100, height: 20))
  143. XCTAssertEqual(size.kf.constrainedRect(for: outY, anchor: center), CGRect(x: 40, y: 0, width: 20, height: 100))
  144. XCTAssertEqual(size.kf.constrainedRect(for: outSize, anchor: center), CGRect(x: 0, y: 0, width: 100, height: 100))
  145. XCTAssertEqual(size.kf.constrainedRect(for: inSize, anchor: bottomRight), CGRect(x: 80, y: 80, width: 20, height: 20))
  146. XCTAssertEqual(size.kf.constrainedRect(for: outX, anchor: bottomRight), CGRect(x: 0, y: 80, width: 100, height: 20))
  147. XCTAssertEqual(size.kf.constrainedRect(for: outY, anchor: bottomRight), CGRect(x:80, y: 0, width: 20, height: 100))
  148. XCTAssertEqual(size.kf.constrainedRect(for: outSize, anchor: bottomRight), CGRect(x: 0, y: 0, width: 100, height: 100))
  149. XCTAssertEqual(size.kf.constrainedRect(for: inSize, anchor: invalidAnchor), CGRect(x: 0, y: 80, width: 20, height: 20))
  150. XCTAssertEqual(size.kf.constrainedRect(for: outX, anchor: invalidAnchor), CGRect(x: 0, y: 80, width: 100, height: 20))
  151. XCTAssertEqual(size.kf.constrainedRect(for: outY, anchor: invalidAnchor), CGRect(x:0, y: 0, width: 20, height: 100))
  152. XCTAssertEqual(size.kf.constrainedRect(for: outSize, anchor: invalidAnchor), CGRect(x: 0, y: 0, width: 100, height: 100))
  153. }
  154. func testDecodeScale() {
  155. #if os(iOS) || os(tvOS)
  156. let image = testImage
  157. XCTAssertEqual(image.size, CGSize(width: 64, height: 64))
  158. XCTAssertEqual(image.scale, 1.0)
  159. let image_2x = Kingfisher<Image>.image(cgImage: image.cgImage!, scale: 2.0, refImage: image)
  160. XCTAssertEqual(image_2x.size, CGSize(width: 32, height: 32))
  161. XCTAssertEqual(image_2x.scale, 2.0)
  162. let decoded = image.kf.decoded
  163. XCTAssertEqual(decoded.size, CGSize(width: 64, height: 64))
  164. XCTAssertEqual(decoded.scale, 1.0)
  165. let decodedDifferentScale = image.kf.decoded(scale: 2.0)
  166. XCTAssertEqual(decodedDifferentScale.size, CGSize(width: 32, height: 32))
  167. XCTAssertEqual(decodedDifferentScale.scale, 2.0)
  168. let decoded_2x = image_2x.kf.decoded
  169. XCTAssertEqual(decoded_2x.size, CGSize(width: 32, height: 32))
  170. XCTAssertEqual(decoded_2x.scale, 2.0)
  171. #endif
  172. }
  173. }