Skip to content

Commit

Permalink
added loopcount property
Browse files Browse the repository at this point in the history
  • Loading branch information
awxkee committed Oct 17, 2023
1 parent 45548d6 commit 79e56b2
Show file tree
Hide file tree
Showing 16 changed files with 439 additions and 241 deletions.
12 changes: 6 additions & 6 deletions Package.resolved
Original file line number Diff line number Diff line change
Expand Up @@ -5,26 +5,26 @@
"kind" : "remoteSourceControl",
"location" : "https://github.com/awxkee/libaom.swift.git",
"state" : {
"revision" : "b779e43ea03e5be8487ab80ce17c534958b279ab",
"version" : "1.0.3"
"revision" : "506308364f5f83e3ae2797521d9b3958205ec0e8",
"version" : "1.0.4"
}
},
{
"identity" : "libdav1d.swift",
"kind" : "remoteSourceControl",
"location" : "https://github.com/awxkee/libdav1d.swift.git",
"state" : {
"revision" : "35195058fd3d11ae28c34b20bcb8e095ff91ebe0",
"version" : "1.0.6"
"revision" : "027c2111fa7bad62318d2447712d02db60b53aa7",
"version" : "1.0.10"
}
},
{
"identity" : "libwebp-ios",
"kind" : "remoteSourceControl",
"location" : "https://github.com/awxkee/libwebp-ios.git",
"state" : {
"revision" : "4abd7aaa8dbdb1e4afd797849da04a825604b30f",
"version" : "1.0.9"
"revision" : "09ab26afc64c55a49332c396c4b465c278fcb05f",
"version" : "1.1.1"
}
},
{
Expand Down
127 changes: 127 additions & 0 deletions Sources/SDWebImageAVIFCoder.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
//
// SDWebImageAVIFCoder.swift
// avif.swift [https://github.com/awxkee/avif.swift]
//
// Created by Radzivon Bartoshyk on 30/08/2023.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//

import Foundation
import SDWebImage
#if canImport(avif)
import avif
#endif
#if !os(macOS)
import UIKit.UIImage
import UIKit.UIColor
/// Alias for `UIImage`.
public typealias AVIFSDImage = UIImage
#else
import AppKit.NSImage
/// Alias for `NSImage`.
public typealias AVIFSDImage = NSImage
#endif

public class SDWebImageAVIFCoder: NSObject, SDImageCoder {
public func canDecode(from data: Data?) -> Bool {
guard let data else { return false }
return data.isAVIFFormat
}

public func decodedImage(with data: Data?, options: [SDImageCoderOption : Any]? = nil) -> AVIFSDImage? {
guard let data else {
return nil
}
return AVIFDecoder.decode(data)
}

public func canEncode(to format: SDImageFormat) -> Bool {
return true
}

public func encodedData(with image: AVIFSDImage?, format: SDImageFormat, options: [SDImageCoderOption : Any]? = nil) -> Data? {
guard let image else {
return nil
}
return try? AVIFEncoder.encode(image: image, quality: 50)
}

public override init() {
}
}

public class SDWebImageAVIFAnimatedCoder: NSObject, SDAnimatedImageCoder {

private let decoder: AnimatedDecoder

public required init?(animatedImageData data: Data?, options: [SDImageCoderOption : Any]? = nil) {
guard let data, let mDecoder = try? AnimatedDecoder(data: data) else {
return nil
}
decoder = mDecoder
super.init()
}

public func canDecode(from data: Data?) -> Bool {
guard let data else {
return false
}
return AVIFDecoder().isAVIF(data: data)
}

public func decodedImage(with data: Data?, options: [SDImageCoderOption : Any]? = nil) -> AVIFSDImage? {
guard let data else {
return nil
}
return AVIFDecoder.decode(data)
}

public func canEncode(to format: SDImageFormat) -> Bool {
return true
}

public func encodedData(with image: AVIFSDImage?, format: SDImageFormat, options: [SDImageCoderOption : Any]? = nil) -> Data? {
guard let image else {
return nil
}
return try? AVIFEncoder.encode(image: image, quality: 50)
}

public var animatedImageData: Data? {
nil
}

public var animatedImageFrameCount: UInt {
UInt(decoder.numberOfFrames)
}

public var animatedImageLoopCount: UInt {
UInt.max
}

public func animatedImageFrame(at index: UInt) -> AVIFSDImage? {
return try? decoder.getImage(frame: Int(index))
}

public func animatedImageDuration(at index: UInt) -> TimeInterval {
TimeInterval(decoder.duration(of: Int(index)))
}

}
58 changes: 0 additions & 58 deletions Sources/SDWebImageNukePlugin.swift

This file was deleted.

51 changes: 46 additions & 5 deletions Sources/avif/AVIF+Errors.swift
Original file line number Diff line number Diff line change
Expand Up @@ -25,14 +25,55 @@

import Foundation

public struct AVIFReadError: Error, Equatable { }
public struct OpenStreamError: Error, Equatable { }
public struct AVIFDecodingError: Error, Equatable { }
public struct AVIFReadError: LocalizedError, CustomNSError {
public var errorDescription: String {
"Can't read AVIF data"
}

public var errorUserInfo: [String : Any] {
[NSLocalizedDescriptionKey: errorDescription]
}
}

public struct OpenStreamError: LocalizedError, CustomNSError {
public var errorDescription: String {
"Can't open AVIF Stream"
}

public var errorUserInfo: [String : Any] {
[NSLocalizedDescriptionKey: errorDescription]
}
}

public struct AVIFDecodingError: LocalizedError, CustomNSError {
public var errorDescription: String {
"Can't decode AVIF"
}

public struct AVIFUnderlyingError: LocalizedError {
public var errorUserInfo: [String : Any] {
[NSLocalizedDescriptionKey: errorDescription]
}
}

public struct AVIFFrameDecodingError: LocalizedError, CustomNSError {
public var frame: Int
public var errorDescription: String {
"Can't decode frame at index: \(frame) in AVIF"
}

public var errorUserInfo: [String : Any] {
[NSLocalizedDescriptionKey: errorDescription]
}
}

public struct AVIFUnderlyingError: LocalizedError, CustomNSError {
let underlyingError: String

public var errorDescription: String? {
public var errorDescription: String {
underlyingError
}

public var errorUserInfo: [String : Any] {
[NSLocalizedDescriptionKey: errorDescription]
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -28,37 +28,41 @@ import avifc

public class AnimatedDecoder {

private let _decoder: AVIFAnimatedDecoder
private let mAVIFAnimatedDecoder: AVIFAnimatedDecoder

public init(data: Data) throws {
guard let decoder = AVIFAnimatedDecoder(data: data) else {
throw AVIFReadError()
}
_decoder = decoder
mAVIFAnimatedDecoder = decoder
}

public var numberOfFrames: Int {
return Int(_decoder.framesCount())
return Int(mAVIFAnimatedDecoder.framesCount())
}


public var loopsCount: Int {
Int(mAVIFAnimatedDecoder.loopsCount())
}

public var duration: Int {
return Int(_decoder.duration())
return Int(mAVIFAnimatedDecoder.duration())
}

public func duration(of frame: Int) -> Int {
return Int(_decoder.frameDuration(Int32(frame)))
return Int(mAVIFAnimatedDecoder.frameDuration(Int32(frame)))
}

public func getImage(frame: Int) throws -> PlatformImage {
guard let image = _decoder.getImage(Int32(frame)) else {
throw AVIFDecodingError()
guard let image = mAVIFAnimatedDecoder.getImage(Int32(frame)) else {
throw AVIFFrameDecodingError(frame: frame)
}
return image
}

public func get(frame: Int) throws -> CGImage {
guard let image = _decoder.get(Int32(frame)) else {
throw AVIFDecodingError()
guard let image = mAVIFAnimatedDecoder.get(Int32(frame)) else {
throw AVIFFrameDecodingError(frame: frame)
}
return image.takeRetainedValue()
}
Expand Down
4 changes: 4 additions & 0 deletions Sources/avifc/AVIFAnimatedDecoder.mm
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,10 @@ -(int)framesCount {
return _idec->imageCount;
}

-(int)loopsCount {
return _idec->repetitionCount;
}

-(int)duration {
return (int)(1000.0f / ((float)_idec->timescale) * (float)_idec->durationInTimescales);
}
Expand Down
10 changes: 9 additions & 1 deletion Sources/avifc/AVIFAnimatedEncoder.mm
Original file line number Diff line number Diff line change
Expand Up @@ -106,12 +106,20 @@ - (void)setCompressionQuality:(double)quality {
}
}

- (void)setLoopsCount:(NSInteger)loopsCount {
if (encoder) {
encoder->repetitionCount = static_cast<int>(loopsCount);
}
}

- (NSData* _Nullable)encode:(NSError * _Nullable *_Nullable)error {
avifRWData avifOutput = AVIF_DATA_EMPTY;
avifResult finishResult = avifEncoderFinish(encoder, &avifOutput);
if (finishResult != AVIF_RESULT_OK) {
[self cleanUp];
*error = [[NSError alloc] initWithDomain:@"AVIFEncoder" code:500 userInfo:@{ NSLocalizedDescriptionKey: [NSString stringWithFormat: @"encoding failed with result: %s", avifResultToString(finishResult)] }];
*error = [[NSError alloc] initWithDomain:@"AVIFEncoder"
code:500
userInfo:@{ NSLocalizedDescriptionKey: [NSString stringWithFormat: @"encoding failed with result: %s", avifResultToString(finishResult)] }];
return nil;
}

Expand Down
2 changes: 1 addition & 1 deletion Sources/avifc/AVIFImageXForm.mm
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ - (_Nullable CGImageRef)formCGImage:(nonnull avifDecoder*)decoder scale:(CGFloat
avifRGBImageSetDefaults(&rgbImage, decoder->image);

auto imageUsesAlpha = decoder->image->imageOwnsAlphaPlane || decoder->image->alphaPlane != nullptr;

int components = imageUsesAlpha ? 4 : 3;

auto colorPrimaries = decoder->image->colorPrimaries;
Expand Down
7 changes: 3 additions & 4 deletions Sources/avifc/Color/Colorspace.h
Original file line number Diff line number Diff line change
Expand Up @@ -199,10 +199,9 @@ class ColorSpaceMatrix {
inline void convert(float& r, float& g, float& b) {
#if __arm64
float32x4_t v = { r, g, b, 0.0f };
v = vaddq_f32(vaddq_f32(vmulq_f32(v, row1), vmulq_f32(v, row2)), vmulq_f32(v, row3));
r = vgetq_lane_f32(v, 0);
g = vgetq_lane_f32(v, 1);
b = vgetq_lane_f32(v, 2);
r = vdot_f32(v, row1);
g = vdot_f32(v, row2);
b = vdot_f32(v, row3);
#else
const float newR = matrix[0]*r + matrix[1]*g + matrix[2]*b;
const float newG = matrix[3]*r + matrix[4]*g + matrix[5]*b;
Expand Down
Loading

0 comments on commit 79e56b2

Please sign in to comment.