Comments (3)
Ok it seems like I found a workaround by tinkering a bit. I believe the issue to arise from the calculateFrameDelay function in the UIImage+SwiftyGif.swift file. It seemed to have incorrectly taken into account the 120Hz refresh rate of the ProMotion Displays. The correct function code is listed below.
ORIGINAL CODE:
private func calculateFrameDelay(_ delaysArray: [Float], levelOfIntegrity: GifLevelOfIntegrity) {
let levelOfIntegrity = max(0, min(1, levelOfIntegrity))
var delays = delaysArray
var displayRefreshFactors = [Int]()
if #available(iOS 10.3, tvOS 10.3, *) {
// Will be 120 on devices with ProMotion display, 60 otherwise.
displayRefreshFactors.append(UIScreen.main.maximumFramesPerSecond)
}
if let first = displayRefreshFactors.first, first != 60 {
// Append 60 if needed.
displayRefreshFactors.append(60)
}
displayRefreshFactors.append(contentsOf: [30, 20, 15, 12, 10, 6, 5, 4, 3, 2, 1])
// maxFramePerSecond,default is 60
let maxFramePerSecond = displayRefreshFactors[0]
// frame numbers per second
let displayRefreshRates = displayRefreshFactors.map { maxFramePerSecond / $0 }
// time interval per frame
let displayRefreshDelayTime = displayRefreshRates.map { 1 / Float($0) }
// caclulate the time when each frame should be displayed at(start at 0)
for i in delays.indices.dropFirst() {
delays[i] += delays[i - 1]
}
//find the appropriate Factors then BREAK
for (i, delayTime) in displayRefreshDelayTime.enumerated() {
let displayPosition = delays.map { Int($0 / delayTime) }
var frameLoseCount: Float = 0
for j in displayPosition.indices.dropFirst() where displayPosition[j] == displayPosition[j - 1] {
frameLoseCount += 1
}
if displayPosition.first == 0 {
frameLoseCount += 1
}
if frameLoseCount <= Float(displayPosition.count) * (1 - levelOfIntegrity) || i == displayRefreshDelayTime.count - 1 {
imageCount = displayPosition.last
displayRefreshFactor = displayRefreshFactors[i]
displayOrder = []
var oldIndex = 0
var newIndex = 1
let imageCount = self.imageCount ?? 0
while newIndex <= imageCount && oldIndex < displayPosition.count {
if newIndex <= displayPosition[oldIndex] {
displayOrder?.append(oldIndex)
newIndex += 1
} else {
oldIndex += 1
}
}
break
}
}
}
EDITED CODE:
private func calculateFrameDelay(_ delaysArray: [Float], levelOfIntegrity: GifLevelOfIntegrity) {
let levelOfIntegrity = max(0, min(1, levelOfIntegrity))
var delays = delaysArray
var displayRefreshFactors = [Int]()
displayRefreshFactors.append(contentsOf: [60, 30, 20, 15, 12, 10, 6, 5, 4, 3, 2, 1])
// maxFramePerSecond,default is 60
let maxFramePerSecond = displayRefreshFactors[0]
// frame numbers per second
var displayRefreshRates = displayRefreshFactors.map { maxFramePerSecond / $0 }
if #available(iOS 10.3, *) {
// Will be 120 on devices with ProMotion display, 60 otherwise.
let maximumFramesPerSecond = UIScreen.main.maximumFramesPerSecond
if maximumFramesPerSecond == 120 {
displayRefreshRates.append(UIScreen.main.maximumFramesPerSecond)
}
}
// time interval per frame
let displayRefreshDelayTime = displayRefreshRates.map { 1 / Float($0) }
// caclulate the time when each frame should be displayed at(start at 0)
for i in delays.indices.dropFirst() {
delays[i] += delays[i - 1]
}
//find the appropriate Factors then BREAK
for (i, delayTime) in displayRefreshDelayTime.enumerated() {
let displayPosition = delays.map { Int($0 / delayTime) }
var frameLoseCount: Float = 0
for j in displayPosition.indices.dropFirst() where displayPosition[j] == displayPosition[j - 1] {
frameLoseCount += 1
}
if displayPosition.first == 0 {
frameLoseCount += 1
}
if frameLoseCount <= Float(displayPosition.count) * (1 - levelOfIntegrity) || i == displayRefreshDelayTime.count - 1 {
imageCount = displayPosition.last
displayRefreshFactor = displayRefreshFactors[i]
displayOrder = []
var oldIndex = 0
var newIndex = 1
let imageCount = self.imageCount ?? 0
while newIndex <= imageCount && oldIndex < displayPosition.count {
if newIndex <= displayPosition[oldIndex] {
displayOrder?.append(oldIndex)
newIndex += 1
} else {
oldIndex += 1
}
}
break
}
}
}
I believe the issue was a mathematical error which caused the displayRefreshRates to have incorrect values. The 120 value should have been inserted after the displayRefreshFactors mapping onto the displayRefreshRates value.
For those with SPM, I don't think you can edit the code directly, but I think with cocoapods you can.
Hope this issue is fixed globally!
from swiftygif.
I have the same issue. The playback is exactly 2 times slower on iPhone 13 Pro than on older devices. I've also checked if the same issue would occur if I use the Kingfisher library and I can confirm that it does not.
from swiftygif.
Same Issue here. I was a bit confused as maybe I had set the level of integrity to a low value, but that was not the case. I tested it on my iPhone X and it works as it should.
from swiftygif.
Related Issues (20)
- Issues with M1 ipad Pro with playback speed HOT 5
- Issue on loading a png image after loading a gif image in same image view. HOT 3
- Crash on UIImage.calculateFrameDelay since 5.4.3
- Index out of range crash in calculateFrameDelay() line 254 HOT 5
- Load gif from app local cache HOT 1
- Crash on UIImage.delayTimes()
- option to disable giflog HOT 1
- Fatal error: Unexpectedly found nil while unwrapping an Optional value
- watchOS compatible HOT 1
- $sSo7UIImageC9SwiftyGifE19calculateFrameDelay33_9658D83D62B37A941BEC0DE7CE976670LL_16levelOfIntegrityySaySfG_SftF HOT 1
- convert the delegate design to support closure HOT 2
- Privacy manifest HOT 3
- Shadow-like artefact with outlines of first frame remains when showing subsequent frames. HOT 1
- Support App Privacy Manifests HOT 4
- Incomplete PrivacyInfo.xcprivacy
- Memory issue HOT 1
- Need to update swift-tools-version HOT 1
- Add a privacy manifest file
- MacOS/AppKit support? HOT 1
- SwiftyGif- Not control Animating Speed
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from swiftygif.