mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-11-07 01:10:09 +00:00
Various Fixes
This commit is contained in:
parent
1dcdde3fbd
commit
851f106afd
@ -354,7 +354,7 @@ private final class AnimatedStickerDirectFrameSourceCache {
|
|||||||
|
|
||||||
let queue = self.queue
|
let queue = self.queue
|
||||||
self.storeQueue.async { [weak self] in
|
self.storeQueue.async { [weak self] in
|
||||||
let compressedData = compressFrame(width: width, height: height, rgbData: rgbData)
|
let compressedData = compressFrame(width: width, height: height, rgbData: rgbData, unpremultiply: true)
|
||||||
|
|
||||||
queue.async {
|
queue.async {
|
||||||
guard let strongSelf = self else {
|
guard let strongSelf = self else {
|
||||||
|
|||||||
@ -72,8 +72,9 @@ public final class AnimatedStickerFrame {
|
|||||||
let index: Int
|
let index: Int
|
||||||
let isLastFrame: Bool
|
let isLastFrame: Bool
|
||||||
let totalFrames: Int
|
let totalFrames: Int
|
||||||
|
let multiplyAlpha: Bool
|
||||||
|
|
||||||
init(data: Data, type: AnimationRendererFrameType, width: Int, height: Int, bytesPerRow: Int, index: Int, isLastFrame: Bool, totalFrames: Int) {
|
init(data: Data, type: AnimationRendererFrameType, width: Int, height: Int, bytesPerRow: Int, index: Int, isLastFrame: Bool, totalFrames: Int, multiplyAlpha: Bool = false) {
|
||||||
self.data = data
|
self.data = data
|
||||||
self.type = type
|
self.type = type
|
||||||
self.width = width
|
self.width = width
|
||||||
@ -83,6 +84,7 @@ public final class AnimatedStickerFrame {
|
|||||||
self.index = index
|
self.index = index
|
||||||
self.isLastFrame = isLastFrame
|
self.isLastFrame = isLastFrame
|
||||||
self.totalFrames = totalFrames
|
self.totalFrames = totalFrames
|
||||||
|
self.multiplyAlpha = multiplyAlpha
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -422,7 +424,7 @@ public final class AnimatedStickerNode: ASDisplayNode {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
strongSelf.renderer?.render(queue: strongSelf.queue, width: frame.width, height: frame.height, bytesPerRow: frame.bytesPerRow, data: frame.data, type: frame.type, completion: {
|
strongSelf.renderer?.render(queue: strongSelf.queue, width: frame.width, height: frame.height, bytesPerRow: frame.bytesPerRow, data: frame.data, type: frame.type, mulAlpha: frame.multiplyAlpha, completion: {
|
||||||
guard let strongSelf = self else {
|
guard let strongSelf = self else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -527,7 +529,7 @@ public final class AnimatedStickerNode: ASDisplayNode {
|
|||||||
|
|
||||||
assert(frame.bytesPerRow != 0)
|
assert(frame.bytesPerRow != 0)
|
||||||
|
|
||||||
strongSelf.renderer?.render(queue: strongSelf.queue, width: frame.width, height: frame.height, bytesPerRow: frame.bytesPerRow, data: frame.data, type: frame.type, completion: {
|
strongSelf.renderer?.render(queue: strongSelf.queue, width: frame.width, height: frame.height, bytesPerRow: frame.bytesPerRow, data: frame.data, type: frame.type, mulAlpha: frame.multiplyAlpha, completion: {
|
||||||
guard let strongSelf = self else {
|
guard let strongSelf = self else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -679,7 +681,7 @@ public final class AnimatedStickerNode: ASDisplayNode {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
strongSelf.renderer?.render(queue: strongSelf.queue, width: frame.width, height: frame.height, bytesPerRow: frame.bytesPerRow, data: frame.data, type: frame.type, completion: {
|
strongSelf.renderer?.render(queue: strongSelf.queue, width: frame.width, height: frame.height, bytesPerRow: frame.bytesPerRow, data: frame.data, type: frame.type, mulAlpha: frame.multiplyAlpha, completion: {
|
||||||
guard let strongSelf = self else {
|
guard let strongSelf = self else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
@ -8,7 +8,7 @@ public enum AnimationRendererFrameType {
|
|||||||
}
|
}
|
||||||
|
|
||||||
protocol AnimationRenderer {
|
protocol AnimationRenderer {
|
||||||
func render(queue: Queue, width: Int, height: Int, bytesPerRow: Int, data: Data, type: AnimationRendererFrameType, completion: @escaping () -> Void)
|
func render(queue: Queue, width: Int, height: Int, bytesPerRow: Int, data: Data, type: AnimationRendererFrameType, mulAlpha: Bool, completion: @escaping () -> Void)
|
||||||
|
|
||||||
func setOverlayColor(_ color: UIColor?, replace: Bool, animated: Bool)
|
func setOverlayColor(_ color: UIColor?, replace: Bool, animated: Bool)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,7 +2,7 @@ import Foundation
|
|||||||
import Compression
|
import Compression
|
||||||
import YuvConversion
|
import YuvConversion
|
||||||
|
|
||||||
func compressFrame(width: Int, height: Int, rgbData: Data) -> Data? {
|
func compressFrame(width: Int, height: Int, rgbData: Data, unpremultiply: Bool) -> Data? {
|
||||||
let bytesPerRow = rgbData.count / height
|
let bytesPerRow = rgbData.count / height
|
||||||
|
|
||||||
let yuvaPixelsPerAlphaRow = (Int(width) + 1) & (~1)
|
let yuvaPixelsPerAlphaRow = (Int(width) + 1) & (~1)
|
||||||
@ -26,7 +26,7 @@ func compressFrame(width: Int, height: Int, rgbData: Data) -> Data? {
|
|||||||
var rgbData = rgbData
|
var rgbData = rgbData
|
||||||
rgbData.withUnsafeMutableBytes { (buffer: UnsafeMutableRawBufferPointer) -> Void in
|
rgbData.withUnsafeMutableBytes { (buffer: UnsafeMutableRawBufferPointer) -> Void in
|
||||||
if let baseAddress = buffer.baseAddress {
|
if let baseAddress = buffer.baseAddress {
|
||||||
encodeRGBAToYUVA(yuvaFrameData.assumingMemoryBound(to: UInt8.self), baseAddress.assumingMemoryBound(to: UInt8.self), Int32(width), Int32(height), Int32(bytesPerRow))
|
encodeRGBAToYUVA(yuvaFrameData.assumingMemoryBound(to: UInt8.self), baseAddress.assumingMemoryBound(to: UInt8.self), Int32(width), Int32(height), Int32(bytesPerRow), unpremultiply)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -4,13 +4,14 @@ import AsyncDisplayKit
|
|||||||
import Display
|
import Display
|
||||||
import SwiftSignalKit
|
import SwiftSignalKit
|
||||||
import YuvConversion
|
import YuvConversion
|
||||||
|
import Accelerate
|
||||||
|
|
||||||
final class SoftwareAnimationRenderer: ASDisplayNode, AnimationRenderer {
|
final class SoftwareAnimationRenderer: ASDisplayNode, AnimationRenderer {
|
||||||
private var highlightedContentNode: ASDisplayNode?
|
private var highlightedContentNode: ASDisplayNode?
|
||||||
private var highlightedColor: UIColor?
|
private var highlightedColor: UIColor?
|
||||||
private var highlightReplacesContent = false
|
private var highlightReplacesContent = false
|
||||||
|
|
||||||
func render(queue: Queue, width: Int, height: Int, bytesPerRow: Int, data: Data, type: AnimationRendererFrameType, completion: @escaping () -> Void) {
|
func render(queue: Queue, width: Int, height: Int, bytesPerRow: Int, data: Data, type: AnimationRendererFrameType, mulAlpha: Bool, completion: @escaping () -> Void) {
|
||||||
assert(bytesPerRow > 0)
|
assert(bytesPerRow > 0)
|
||||||
queue.async { [weak self] in
|
queue.async { [weak self] in
|
||||||
switch type {
|
switch type {
|
||||||
@ -38,13 +39,24 @@ final class SoftwareAnimationRenderer: ASDisplayNode, AnimationRenderer {
|
|||||||
decodeYUVAToRGBA(baseAddress.assumingMemoryBound(to: UInt8.self), pixelData, Int32(width), Int32(height), Int32(contextBytesPerRow))
|
decodeYUVAToRGBA(baseAddress.assumingMemoryBound(to: UInt8.self), pixelData, Int32(width), Int32(height), Int32(contextBytesPerRow))
|
||||||
}
|
}
|
||||||
case .argb:
|
case .argb:
|
||||||
data.withUnsafeBytes { bytes -> Void in
|
var data = data
|
||||||
|
data.withUnsafeMutableBytes { bytes -> Void in
|
||||||
guard let baseAddress = bytes.baseAddress else {
|
guard let baseAddress = bytes.baseAddress else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
if mulAlpha {
|
||||||
|
var srcData = vImage_Buffer(data: baseAddress.assumingMemoryBound(to: UInt8.self), height: vImagePixelCount(height), width: vImagePixelCount(width), rowBytes: bytesPerRow)
|
||||||
|
var destData = vImage_Buffer(data: pixelData, height: vImagePixelCount(height), width: vImagePixelCount(width), rowBytes: bytesPerRow)
|
||||||
|
|
||||||
|
let permuteMap: [UInt8] = [3, 2, 1, 0]
|
||||||
|
vImagePermuteChannels_ARGB8888(&srcData, &destData, permuteMap, vImage_Flags(kvImageDoNotTile))
|
||||||
|
vImagePremultiplyData_ARGB8888(&destData, &destData, vImage_Flags(kvImageDoNotTile))
|
||||||
|
vImagePermuteChannels_ARGB8888(&destData, &destData, permuteMap, vImage_Flags(kvImageDoNotTile))
|
||||||
|
} else {
|
||||||
memcpy(pixelData, baseAddress.assumingMemoryBound(to: UInt8.self), bytes.count)
|
memcpy(pixelData, baseAddress.assumingMemoryBound(to: UInt8.self), bytes.count)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -44,7 +44,7 @@ private final class VideoStickerFrameSourceCache {
|
|||||||
self.width = width
|
self.width = width
|
||||||
self.height = height
|
self.height = height
|
||||||
|
|
||||||
let version: Int = 2
|
let version: Int = 3
|
||||||
self.path = "\(pathPrefix)_\(width)x\(height)-v\(version).vstickerframecache"
|
self.path = "\(pathPrefix)_\(width)x\(height)-v\(version).vstickerframecache"
|
||||||
var file = ManagedFile(queue: queue, path: self.path, mode: .readwrite)
|
var file = ManagedFile(queue: queue, path: self.path, mode: .readwrite)
|
||||||
if let file = file {
|
if let file = file {
|
||||||
@ -189,7 +189,7 @@ private final class VideoStickerFrameSourceCache {
|
|||||||
|
|
||||||
let queue = self.queue
|
let queue = self.queue
|
||||||
self.storeQueue.async { [weak self] in
|
self.storeQueue.async { [weak self] in
|
||||||
let compressedData = compressFrame(width: width, height: height, rgbData: rgbData)
|
let compressedData = compressFrame(width: width, height: height, rgbData: rgbData, unpremultiply: false)
|
||||||
|
|
||||||
queue.async {
|
queue.async {
|
||||||
guard let strongSelf = self else {
|
guard let strongSelf = self else {
|
||||||
@ -270,6 +270,8 @@ private final class VideoStickerFrameSourceCache {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private let useCache = true
|
||||||
|
|
||||||
final class VideoStickerDirectFrameSource: AnimatedStickerFrameSource {
|
final class VideoStickerDirectFrameSource: AnimatedStickerFrameSource {
|
||||||
private let queue: Queue
|
private let queue: Queue
|
||||||
private let path: String
|
private let path: String
|
||||||
@ -299,7 +301,7 @@ final class VideoStickerDirectFrameSource: AnimatedStickerFrameSource {
|
|||||||
VideoStickerFrameSourceCache(queue: queue, pathPrefix: cachePathPrefix, width: width, height: height)
|
VideoStickerFrameSourceCache(queue: queue, pathPrefix: cachePathPrefix, width: width, height: height)
|
||||||
}
|
}
|
||||||
|
|
||||||
if let cache = self.cache, cache.frameCount > 0 {
|
if useCache, let cache = self.cache, cache.frameCount > 0 {
|
||||||
self.source = nil
|
self.source = nil
|
||||||
self.frameRate = Int(cache.frameRate)
|
self.frameRate = Int(cache.frameRate)
|
||||||
self.frameCount = Int(cache.frameCount)
|
self.frameCount = Int(cache.frameCount)
|
||||||
@ -325,7 +327,7 @@ final class VideoStickerDirectFrameSource: AnimatedStickerFrameSource {
|
|||||||
|
|
||||||
self.currentFrame += 1
|
self.currentFrame += 1
|
||||||
if draw {
|
if draw {
|
||||||
if let cache = self.cache, let yuvData = cache.readUncompressedYuvaFrame(index: frameIndex) {
|
if useCache, let cache = self.cache, let yuvData = cache.readUncompressedYuvaFrame(index: frameIndex) {
|
||||||
return AnimatedStickerFrame(data: yuvData, type: .yuva, width: self.width, height: self.height, bytesPerRow: self.width * 2, index: frameIndex, isLastFrame: frameIndex == self.frameCount - 1, totalFrames: self.frameCount)
|
return AnimatedStickerFrame(data: yuvData, type: .yuva, width: self.width, height: self.height, bytesPerRow: self.width * 2, index: frameIndex, isLastFrame: frameIndex == self.frameCount - 1, totalFrames: self.frameCount)
|
||||||
} else if let source = self.source {
|
} else if let source = self.source {
|
||||||
let frameAndLoop = source.readFrame(maxPts: nil)
|
let frameAndLoop = source.readFrame(maxPts: nil)
|
||||||
@ -377,7 +379,7 @@ final class VideoStickerDirectFrameSource: AnimatedStickerFrameSource {
|
|||||||
|
|
||||||
self.cache?.storeUncompressedRgbFrame(index: frameIndex, rgbData: frameData)
|
self.cache?.storeUncompressedRgbFrame(index: frameIndex, rgbData: frameData)
|
||||||
|
|
||||||
return AnimatedStickerFrame(data: frameData, type: .argb, width: self.width, height: self.height, bytesPerRow: self.bytesPerRow, index: frameIndex, isLastFrame: frameIndex == self.frameCount - 1, totalFrames: self.frameCount)
|
return AnimatedStickerFrame(data: frameData, type: .argb, width: self.width, height: self.height, bytesPerRow: self.bytesPerRow, index: frameIndex, isLastFrame: frameIndex == self.frameCount - 1, totalFrames: self.frameCount, multiplyAlpha: true)
|
||||||
} else {
|
} else {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
@ -301,7 +301,7 @@ public final class CachedVideoStickerRepresentation: CachedMediaResourceRepresen
|
|||||||
public let height: Int32
|
public let height: Int32
|
||||||
|
|
||||||
public var uniqueId: String {
|
public var uniqueId: String {
|
||||||
let version: Int = 2
|
let version: Int = 3
|
||||||
return "video-sticker-\(self.width)x\(self.height)-v\(version)"
|
return "video-sticker-\(self.width)x\(self.height)-v\(version)"
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -63,6 +63,7 @@ public final class ChannelMembersSearchController: ViewController {
|
|||||||
self.statusBar.statusBarStyle = self.presentationData.theme.rootController.statusBarStyle.style
|
self.statusBar.statusBarStyle = self.presentationData.theme.rootController.statusBarStyle.style
|
||||||
|
|
||||||
self.title = self.presentationData.strings.Channel_Members_Title
|
self.title = self.presentationData.strings.Channel_Members_Title
|
||||||
|
|
||||||
self.navigationItem.leftBarButtonItem = UIBarButtonItem(title: self.presentationData.strings.Common_Cancel, style: .plain, target: self, action: #selector(self.cancelPressed))
|
self.navigationItem.leftBarButtonItem = UIBarButtonItem(title: self.presentationData.strings.Common_Cancel, style: .plain, target: self, action: #selector(self.cancelPressed))
|
||||||
|
|
||||||
self.scrollToTop = { [weak self] in
|
self.scrollToTop = { [weak self] in
|
||||||
@ -87,6 +88,18 @@ public final class ChannelMembersSearchController: ViewController {
|
|||||||
strongSelf.presentationData = presentationData
|
strongSelf.presentationData = presentationData
|
||||||
strongSelf.controllerNode.updatePresentationData(presentationData)
|
strongSelf.controllerNode.updatePresentationData(presentationData)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
let _ = (context.account.postbox.loadedPeerWithId(peerId)
|
||||||
|
|> take(1)
|
||||||
|
|> deliverOnMainQueue).start(next: { [weak self] peer in
|
||||||
|
if let strongSelf = self {
|
||||||
|
if let peer = peer as? TelegramChannel, case .broadcast = peer.info {
|
||||||
|
strongSelf.title = strongSelf.presentationData.strings.Channel_Subscribers_Title
|
||||||
|
} else {
|
||||||
|
strongSelf.title = strongSelf.presentationData.strings.Channel_Members_Title
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
required public init(coder aDecoder: NSCoder) {
|
required public init(coder aDecoder: NSCoder) {
|
||||||
|
|||||||
@ -457,15 +457,15 @@ class ChannelMembersSearchControllerNode: ASDisplayNode {
|
|||||||
var canInviteByLink = false
|
var canInviteByLink = false
|
||||||
var isChannel = false
|
var isChannel = false
|
||||||
if let peer = peerViewMainPeer(peerView) {
|
if let peer = peerViewMainPeer(peerView) {
|
||||||
|
if let peer = peer as? TelegramChannel, case .broadcast = peer.info {
|
||||||
|
isChannel = true
|
||||||
|
}
|
||||||
if !(peer.addressName?.isEmpty ?? true) {
|
if !(peer.addressName?.isEmpty ?? true) {
|
||||||
canInviteByLink = true
|
canInviteByLink = true
|
||||||
} else if let peer = peer as? TelegramChannel {
|
} else if let peer = peer as? TelegramChannel {
|
||||||
if peer.flags.contains(.isCreator) || (peer.adminRights?.rights.contains(.canInviteUsers) == true) {
|
if peer.flags.contains(.isCreator) || (peer.adminRights?.rights.contains(.canInviteUsers) == true) {
|
||||||
canInviteByLink = true
|
canInviteByLink = true
|
||||||
}
|
}
|
||||||
if case .broadcast = peer.info {
|
|
||||||
isChannel = true
|
|
||||||
}
|
|
||||||
} else if let peer = peer as? TelegramGroup {
|
} else if let peer = peer as? TelegramGroup {
|
||||||
if case .creator = peer.role {
|
if case .creator = peer.role {
|
||||||
canInviteByLink = true
|
canInviteByLink = true
|
||||||
|
|||||||
@ -49,7 +49,7 @@ public func fetchCompressedLottieFirstFrameAJpeg(data: Data, size: CGSize, fitzM
|
|||||||
free(yuvaFrameData)
|
free(yuvaFrameData)
|
||||||
}
|
}
|
||||||
|
|
||||||
encodeRGBAToYUVA(yuvaFrameData.assumingMemoryBound(to: UInt8.self), context.bytes.assumingMemoryBound(to: UInt8.self), Int32(size.width), Int32(size.height), Int32(context.bytesPerRow))
|
encodeRGBAToYUVA(yuvaFrameData.assumingMemoryBound(to: UInt8.self), context.bytes.assumingMemoryBound(to: UInt8.self), Int32(size.width), Int32(size.height), Int32(context.bytesPerRow), true)
|
||||||
decodeYUVAToRGBA(yuvaFrameData.assumingMemoryBound(to: UInt8.self), context.bytes.assumingMemoryBound(to: UInt8.self), Int32(size.width), Int32(size.height), Int32(context.bytesPerRow))
|
decodeYUVAToRGBA(yuvaFrameData.assumingMemoryBound(to: UInt8.self), context.bytes.assumingMemoryBound(to: UInt8.self), Int32(size.width), Int32(size.height), Int32(context.bytesPerRow))
|
||||||
|
|
||||||
if let colorSourceImage = context.generateImage(), let alphaImage = generateGrayscaleAlphaMaskImage(image: colorSourceImage) {
|
if let colorSourceImage = context.generateImage(), let alphaImage = generateGrayscaleAlphaMaskImage(image: colorSourceImage) {
|
||||||
@ -201,7 +201,7 @@ public func cacheAnimatedStickerFrames(data: Data, size: CGSize, fitzModifier: E
|
|||||||
|
|
||||||
let appendStartTime = CACurrentMediaTime()
|
let appendStartTime = CACurrentMediaTime()
|
||||||
|
|
||||||
encodeRGBAToYUVA(yuvaFrameData.assumingMemoryBound(to: UInt8.self), currentFrameData.assumingMemoryBound(to: UInt8.self), Int32(size.width), Int32(size.height), Int32(bytesPerRow))
|
encodeRGBAToYUVA(yuvaFrameData.assumingMemoryBound(to: UInt8.self), currentFrameData.assumingMemoryBound(to: UInt8.self), Int32(size.width), Int32(size.height), Int32(bytesPerRow), true)
|
||||||
|
|
||||||
appendingTime += CACurrentMediaTime() - appendStartTime
|
appendingTime += CACurrentMediaTime() - appendStartTime
|
||||||
|
|
||||||
@ -351,7 +351,7 @@ public func cacheVideoStickerFrames(path: String, size: CGSize, cacheKey: String
|
|||||||
let originalWidth = CVPixelBufferGetWidth(imageBuffer!)
|
let originalWidth = CVPixelBufferGetWidth(imageBuffer!)
|
||||||
let originalHeight = CVPixelBufferGetHeight(imageBuffer!)
|
let originalHeight = CVPixelBufferGetHeight(imageBuffer!)
|
||||||
if let srcBuffer = CVPixelBufferGetBaseAddress(imageBuffer!) {
|
if let srcBuffer = CVPixelBufferGetBaseAddress(imageBuffer!) {
|
||||||
resizeAndEncodeRGBAToYUVA(yuvaFrameData.assumingMemoryBound(to: UInt8.self), srcBuffer.assumingMemoryBound(to: UInt8.self), Int32(size.width), Int32(size.height), Int32(bytesPerRow), Int32(originalWidth), Int32(originalHeight), Int32(originalBytesPerRow))
|
resizeAndEncodeRGBAToYUVA(yuvaFrameData.assumingMemoryBound(to: UInt8.self), srcBuffer.assumingMemoryBound(to: UInt8.self), Int32(size.width), Int32(size.height), Int32(bytesPerRow), Int32(originalWidth), Int32(originalHeight), Int32(originalBytesPerRow), false)
|
||||||
}
|
}
|
||||||
CVPixelBufferUnlockBaseAddress(imageBuffer!, CVPixelBufferLockFlags(rawValue: 0))
|
CVPixelBufferUnlockBaseAddress(imageBuffer!, CVPixelBufferLockFlags(rawValue: 0))
|
||||||
|
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
#import <Foundation/Foundation.h>
|
#import <Foundation/Foundation.h>
|
||||||
|
|
||||||
void encodeRGBAToYUVA(uint8_t *yuva, uint8_t const *argb, int width, int height, int bytesPerRow);
|
void encodeRGBAToYUVA(uint8_t *yuva, uint8_t const *argb, int width, int height, int bytesPerRow, bool unpremultiply);
|
||||||
void resizeAndEncodeRGBAToYUVA(uint8_t *yuva, uint8_t const *argb, int width, int height, int bytesPerRow, int originalWidth, int originalHeight, int originalBytesPerRow);
|
void resizeAndEncodeRGBAToYUVA(uint8_t *yuva, uint8_t const *argb, int width, int height, int bytesPerRow, int originalWidth, int originalHeight, int originalBytesPerRow, bool unpremultiply);
|
||||||
|
|
||||||
void decodeYUVAToRGBA(uint8_t const *yuva, uint8_t *argb, int width, int height, int bytesPerRow);
|
void decodeYUVAToRGBA(uint8_t const *yuva, uint8_t *argb, int width, int height, int bytesPerRow);
|
||||||
void decodeYUVAPlanesToRGBA(uint8_t const *srcYpData, int srcYpBytesPerRow, uint8_t const *srcCbData, int srcCbBytesPerRow, uint8_t const *srcCrData, int srcCrBytesPerRow, bool hasAlpha, uint8_t const *alphaData, uint8_t *argb, int width, int height, int bytesPerRow);
|
void decodeYUVAPlanesToRGBA(uint8_t const *srcYpData, int srcYpBytesPerRow, uint8_t const *srcCbData, int srcCbBytesPerRow, uint8_t const *srcCrData, int srcCrBytesPerRow, bool hasAlpha, uint8_t const *alphaData, uint8_t *argb, int width, int height, int bytesPerRow);
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
#import <YuvConversion/YUV.h>
|
#import <YuvConversion/YUV.h>
|
||||||
#import <Accelerate/Accelerate.h>
|
#import <Accelerate/Accelerate.h>
|
||||||
|
|
||||||
void encodeRGBAToYUVA(uint8_t *yuva, uint8_t const *argb, int width, int height, int bytesPerRow) {
|
void encodeRGBAToYUVA(uint8_t *yuva, uint8_t const *argb, int width, int height, int bytesPerRow, bool unpremultiply) {
|
||||||
static vImage_ARGBToYpCbCr info;
|
static vImage_ARGBToYpCbCr info;
|
||||||
static dispatch_once_t onceToken;
|
static dispatch_once_t onceToken;
|
||||||
dispatch_once(&onceToken, ^{
|
dispatch_once(&onceToken, ^{
|
||||||
@ -20,7 +20,9 @@ void encodeRGBAToYUVA(uint8_t *yuva, uint8_t const *argb, int width, int height,
|
|||||||
uint8_t permuteMap[4] = {3, 2, 1, 0};
|
uint8_t permuteMap[4] = {3, 2, 1, 0};
|
||||||
error = vImagePermuteChannels_ARGB8888(&src, &src, permuteMap, kvImageDoNotTile);
|
error = vImagePermuteChannels_ARGB8888(&src, &src, permuteMap, kvImageDoNotTile);
|
||||||
|
|
||||||
|
if (unpremultiply) {
|
||||||
error = vImageUnpremultiplyData_ARGB8888(&src, &src, kvImageDoNotTile);
|
error = vImageUnpremultiplyData_ARGB8888(&src, &src, kvImageDoNotTile);
|
||||||
|
}
|
||||||
|
|
||||||
uint8_t *alpha = yuva + width * height * 2;
|
uint8_t *alpha = yuva + width * height * 2;
|
||||||
int i = 0;
|
int i = 0;
|
||||||
@ -51,7 +53,7 @@ void encodeRGBAToYUVA(uint8_t *yuva, uint8_t const *argb, int width, int height,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
void resizeAndEncodeRGBAToYUVA(uint8_t *yuva, uint8_t const *argb, int width, int height, int bytesPerRow, int originalWidth, int originalHeight, int originalBytesPerRow) {
|
void resizeAndEncodeRGBAToYUVA(uint8_t *yuva, uint8_t const *argb, int width, int height, int bytesPerRow, int originalWidth, int originalHeight, int originalBytesPerRow, bool unpremultiply) {
|
||||||
static vImage_ARGBToYpCbCr info;
|
static vImage_ARGBToYpCbCr info;
|
||||||
static dispatch_once_t onceToken;
|
static dispatch_once_t onceToken;
|
||||||
dispatch_once(&onceToken, ^{
|
dispatch_once(&onceToken, ^{
|
||||||
@ -80,7 +82,9 @@ void resizeAndEncodeRGBAToYUVA(uint8_t *yuva, uint8_t const *argb, int width, in
|
|||||||
uint8_t permuteMap[4] = {3, 2, 1, 0};
|
uint8_t permuteMap[4] = {3, 2, 1, 0};
|
||||||
error = vImagePermuteChannels_ARGB8888(&dst, &dst, permuteMap, kvImageDoNotTile);
|
error = vImagePermuteChannels_ARGB8888(&dst, &dst, permuteMap, kvImageDoNotTile);
|
||||||
|
|
||||||
|
if (unpremultiply) {
|
||||||
error = vImageUnpremultiplyData_ARGB8888(&dst, &dst, kvImageDoNotTile);
|
error = vImageUnpremultiplyData_ARGB8888(&dst, &dst, kvImageDoNotTile);
|
||||||
|
}
|
||||||
|
|
||||||
uint8_t *alpha = yuva + width * height * 2;
|
uint8_t *alpha = yuva + width * height * 2;
|
||||||
int i = 0;
|
int i = 0;
|
||||||
@ -173,8 +177,8 @@ void decodeYUVAPlanesToRGBA(uint8_t const *srcYpData, int srcYpBytesPerRow, uint
|
|||||||
static vImage_YpCbCrToARGB info;
|
static vImage_YpCbCrToARGB info;
|
||||||
static dispatch_once_t onceToken;
|
static dispatch_once_t onceToken;
|
||||||
dispatch_once(&onceToken, ^{
|
dispatch_once(&onceToken, ^{
|
||||||
vImage_YpCbCrPixelRange pixelRange = (vImage_YpCbCrPixelRange){ 0, 128, 255, 255, 255, 1, 255, 0 };
|
vImage_YpCbCrPixelRange pixelRange = (vImage_YpCbCrPixelRange){ 16, 128, 235, 240, 255, 0, 255, 0 };
|
||||||
vImageConvert_YpCbCrToARGB_GenerateConversion(kvImage_YpCbCrToARGBMatrix_ITU_R_709_2, &pixelRange, &info, kvImage420Yp8_Cb8_Cr8, kvImageARGB8888, 0);
|
vImageConvert_YpCbCrToARGB_GenerateConversion(kvImage_YpCbCrToARGBMatrix_ITU_R_601_4, &pixelRange, &info, kvImage420Yp8_Cb8_Cr8, kvImageARGB8888, 0);
|
||||||
});
|
});
|
||||||
|
|
||||||
vImage_Error error = kvImageNoError;
|
vImage_Error error = kvImageNoError;
|
||||||
@ -216,6 +220,7 @@ void decodeYUVAPlanesToRGBA(uint8_t const *srcYpData, int srcYpBytesPerRow, uint
|
|||||||
}
|
}
|
||||||
|
|
||||||
uint8_t permuteMap[4] = {3, 2, 1, 0};
|
uint8_t permuteMap[4] = {3, 2, 1, 0};
|
||||||
|
error = vImageUnpremultiplyData_ARGB8888(&dest, &dest, kvImageDoNotTile);
|
||||||
error = vImagePermuteChannels_ARGB8888(&dest, &dest, permuteMap, kvImageDoNotTile);
|
error = vImagePermuteChannels_ARGB8888(&dest, &dest, permuteMap, kvImageDoNotTile);
|
||||||
|
|
||||||
if (error != kvImageNoError) {
|
if (error != kvImageNoError) {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user