Skip to content

Commit 9536cfc

Browse files
authored
Merge pull request #412 from kean/webp
Add WebP ImageType and WebP decoding unit tests
2 parents a8b2c75 + 7278f8a commit 9536cfc

File tree

5 files changed

+44
-5
lines changed

5 files changed

+44
-5
lines changed

Documentation/Guides/image-formats.md

+6
Original file line numberDiff line numberDiff line change
@@ -392,4 +392,10 @@ ImagePipeline.shared.loadImage(with: url) { [weak self] result in
392392

393393
### WebP
394394

395+
#### Third-party Support
396+
395397
[WebP](https://developers.google.com/speed/webp) support is provided by [Nuke WebP Plugin](https://github.com/ryokosuge/Nuke-WebP-Plugin) built by [Ryo Kosuge](https://github.com/ryokosuge). Please follow the instructions from the repo.
398+
399+
#### Native Support (macOS 11, iOS 14, watchOS 7)
400+
401+
WebP is now supported natively. Nuke currently only supports baseline WebP (no progressive WebP support).

Nuke.xcodeproj/project.pbxproj

+4-2
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,7 @@
9595
0C91B0F42438E38B007F9100 /* CompositionTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0C91B0F32438E38B007F9100 /* CompositionTests.swift */; };
9696
0C91B0F62438E3CB007F9100 /* GaussianBlurTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0C91B0F52438E3CB007F9100 /* GaussianBlurTests.swift */; };
9797
0C91B0F82438E84E007F9100 /* fixture-tiny.jpeg in Resources */ = {isa = PBXBuildFile; fileRef = 0C91B0F72438E84E007F9100 /* fixture-tiny.jpeg */; };
98+
0C95FD542571B278008D4FC2 /* baseline.webp in Resources */ = {isa = PBXBuildFile; fileRef = 0C95FD532571B278008D4FC2 /* baseline.webp */; };
9899
0C973E141D9FDB9F00C00AD9 /* Nuke.framework in CopyFiles */ = {isa = PBXBuildFile; fileRef = 0C9174901BAE99EE004A7905 /* Nuke.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
99100
0C9B6E7620B9F3E2001924B8 /* ImagePipelineDeduplicationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0C9B6E7520B9F3E2001924B8 /* ImagePipelineDeduplicationTests.swift */; };
100101
0CAAB0101E45D6DA00924450 /* NukeExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0CAAB00F1E45D6DA00924450 /* NukeExtensions.swift */; };
@@ -228,8 +229,8 @@
228229
0C91B0F52438E3CB007F9100 /* GaussianBlurTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GaussianBlurTests.swift; sourceTree = "<group>"; };
229230
0C91B0F72438E84E007F9100 /* fixture-tiny.jpeg */ = {isa = PBXFileReference; lastKnownFileType = image.jpeg; path = "fixture-tiny.jpeg"; sourceTree = "<group>"; };
230231
0C94466D1D47EC0E006DB314 /* ImageViewTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ImageViewTests.swift; sourceTree = "<group>"; };
232+
0C95FD532571B278008D4FC2 /* baseline.webp */ = {isa = PBXFileReference; lastKnownFileType = file; path = baseline.webp; sourceTree = "<group>"; };
231233
0C9B6E7520B9F3E2001924B8 /* ImagePipelineDeduplicationTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImagePipelineDeduplicationTests.swift; sourceTree = "<group>"; };
232-
0CA301701DAF9CD1000B9105 /* .travis.yml */ = {isa = PBXFileReference; lastKnownFileType = text; path = .travis.yml; sourceTree = "<group>"; };
233234
0CA82BDC237AE09F00338375 /* install_swiftlint.sh */ = {isa = PBXFileReference; lastKnownFileType = text.script.sh; name = install_swiftlint.sh; path = Scripts/install_swiftlint.sh; sourceTree = "<group>"; };
234235
0CAAB00F1E45D6DA00924450 /* NukeExtensions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NukeExtensions.swift; sourceTree = "<group>"; };
235236
0CB26801208F2565004C83F4 /* DataCache.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DataCache.swift; sourceTree = "<group>"; };
@@ -337,6 +338,7 @@
337338
children = (
338339
0C70D9702089016800A49DAC /* baseline.jpeg */,
339340
0C70D96F2089016700A49DAC /* progressive.jpeg */,
341+
0C95FD532571B278008D4FC2 /* baseline.webp */,
340342
0C09B1651FE9A65600E8FE3B /* fixture.jpeg */,
341343
0C91B0F72438E84E007F9100 /* fixture-tiny.jpeg */,
342344
0C70D97B2089042400A49DAC /* fixture.png */,
@@ -557,7 +559,6 @@
557559
0C4326262424338200799446 /* LICENSE */,
558560
0CDB92811DAF9BC000002905 /* Nuke.podspec */,
559561
0CDB92831DAF9BCB00002905 /* Package.swift */,
560-
0CA301701DAF9CD1000B9105 /* .travis.yml */,
561562
0C179C772282AC50008AB488 /* .swiftlint.yml */,
562563
);
563564
name = Metadata;
@@ -752,6 +753,7 @@
752753
0C7CE29B2439417C0018C8C3 /* s-sepia.png in Resources */,
753754
0C91B0F82438E84E007F9100 /* fixture-tiny.jpeg in Resources */,
754755
0C70D9742089016800A49DAC /* baseline.jpeg in Resources */,
756+
0C95FD542571B278008D4FC2 /* baseline.webp in Resources */,
755757
0C7CE28B243933550018C8C3 /* s-rounded-corners.png in Resources */,
756758
0C70D9712089016800A49DAC /* progressive.jpeg in Resources */,
757759
0C7CE28D2439342C0018C8C3 /* s-rounded-corners-border.png in Resources */,

Sources/ImageDecoding.swift

+12-3
Original file line numberDiff line numberDiff line change
@@ -338,6 +338,11 @@ public struct ImageType: ExpressibleByStringLiteral, Hashable {
338338
/// HEIF (High Effeciency Image Format) by Apple.
339339
public static let heic: ImageType = "public.heic"
340340

341+
/// WebP
342+
///
343+
/// Native decoding support only available on the following platforms: macOS 11,
344+
/// iOS 14, watchOS 7, tvOS 14.
345+
public static let webp: ImageType = "public.webp"
341346
}
342347

343348
public extension ImageType {
@@ -350,12 +355,13 @@ public extension ImageType {
350355
}
351356

352357
private static func make(_ data: Data) -> ImageType? {
353-
func _match(_ numbers: [UInt8]) -> Bool {
358+
func _match(_ numbers: [UInt8?]) -> Bool {
354359
guard data.count >= numbers.count else {
355360
return false
356361
}
357-
return !zip(numbers.indices, numbers).contains { (index, number) in
358-
data[index] != number
362+
return zip(numbers.indices, numbers).allSatisfy { index, number in
363+
guard let number = number else { return true }
364+
return data[index] == number
359365
}
360366
}
361367

@@ -368,6 +374,9 @@ public extension ImageType {
368374
// GIF magic numbers https://en.wikipedia.org/wiki/GIF
369375
if _match([0x47, 0x49, 0x46]) { return .gif }
370376

377+
// WebP magic numbers https://en.wikipedia.org/wiki/List_of_file_signatures
378+
if _match([0x52, 0x49, 0x46, 0x46, nil, nil, nil, nil, 0x57, 0x45, 0x42, 0x50]) { return .webp }
379+
371380
// Either not enough data, or we just don't support this format.
372381
return nil
373382
}

Tests/ImageDecoderTests.swift

+22
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,18 @@ class ImageDecoderTests: XCTestCase {
133133
XCTAssertNotNil(container)
134134
XCTAssertNil(container?.data)
135135
}
136+
137+
func testDecodeBaselineWebP() {
138+
let data = Test.data(name: "baseline", extension: "webp")
139+
let container = ImageDecoders.Default().decode(data)
140+
if #available(OSX 15, iOS 14.0, watchOS 7.0, tvOS 999.0, *) {
141+
XCTAssertNotNil(container)
142+
XCTAssertNil(container?.data)
143+
} else {
144+
XCTAssertNil(container)
145+
XCTAssertNil(container?.data)
146+
}
147+
}
136148
}
137149

138150
class ImageTypeTests: XCTestCase {
@@ -176,6 +188,16 @@ class ImageTypeTests: XCTestCase {
176188
// Full image
177189
XCTAssertEqual(ImageType(data), .jpeg)
178190
}
191+
192+
// MARK: WebP
193+
194+
func testDetectBaselineWebP() {
195+
let data = Test.data(name: "baseline", extension: "webp")
196+
XCTAssertNil(ImageType(data[0..<1]))
197+
XCTAssertNil(ImageType(data[0..<2]))
198+
XCTAssertEqual(ImageType(data[0..<12]), .webp)
199+
XCTAssertEqual(ImageType(data), .webp)
200+
}
179201
}
180202

181203
class ImagePropertiesTests: XCTestCase {

Tests/Resources/baseline.webp

29.6 KB
Binary file not shown.

0 commit comments

Comments
 (0)