Sky*_*ren 10 core-graphics animated-gif uiimage ios swift
我有这个非常奇怪的问题.我正在用UIImages创建GIF动画,大多数时候它们都是正确的.然而,当我开始进入更大尺寸的图像时,我的颜色开始消失.例如,如果我做一个4帧32 x 32像素图像,不超过10种颜色没有问题.如果我将相同的图像缩放到832 x 832,我会失去粉红色,而我的棕色会变成绿色.
@ 1x 32 x 32
@ 10x 320 x 320
@ 26x 832 x 832
这是我用来创建gif的代码......
var kFrameCount = 0
for smdLayer in drawingToUse!.layers{
if !smdLayer.hidden {
kFrameCount += 1
}
}
let loopingProperty = [String(kCGImagePropertyGIFLoopCount): 0]
let fileProperties: [String: AnyObject] = [String(kCGImagePropertyGIFDictionary): loopingProperty as AnyObject];
let frameProperty = [String(kCGImagePropertyGIFDelayTime): Float(speedLabel.text!)!]
let frameProperties: [String: AnyObject] = [String(kCGImagePropertyGIFDictionary): frameProperty as AnyObject];
let documentsDirectoryPath = "file://\(NSTemporaryDirectory())"
if let documentsDirectoryURL = URL(string: documentsDirectoryPath){
let fileURL = documentsDirectoryURL.appendingPathComponent("\(drawing.name)\(getScaleString()).gif")
let destination = CGImageDestinationCreateWithURL(fileURL as CFURL, kUTTypeGIF, kFrameCount, nil)!
CGImageDestinationSetProperties(destination, fileProperties as CFDictionary);
for smdLayer in drawingToUse!.layers{
if !smdLayer.hidden{
let image = UIImage(smdLayer: smdLayer, alphaBlend: useAlphaLayers, backgroundColor: backgroundColorButton.backgroundColor!, scale: scale)
CGImageDestinationAddImage(destination, image.cgImage!, frameProperties as CFDictionary)
}
}
if (!CGImageDestinationFinalize(destination)) {
print("failed to finalize image destination")
}
}
Run Code Online (Sandbox Code Playgroud)
在我打电话之前,我已经设置了一个断点CGImageDestinationAddImage(destination, image.cgImage!, frameProperties as CFDictionary),并且正确的颜色图像非常精细.我希望那里的人知道我错过了什么.
更新
这是一个示例项目.请注意,虽然它在预览中没有动画,但它保存了动画gif,我在控制台中注销了图像的位置.
似乎关闭全局颜色映射可以解决问题:
let loopingProperty: [String: AnyObject] = [
kCGImagePropertyGIFLoopCount as String: 0 as NSNumber,
kCGImagePropertyGIFHasGlobalColorMap as String: false as NSNumber
]
Run Code Online (Sandbox Code Playgroud)
请注意,与PNG不同,GIF只能使用256色图,而不使用透明度.对于动画GIF,可以是全局或每帧颜色映射.
不幸的是,Core Graphics不允许我们直接使用色彩映射,因此在编码GIF时会有一些自动颜色转换.
似乎关闭全局色彩图就是所需要的.同样明确地为每个帧使用设置颜色映射kCGImagePropertyGIFImageColorMap也可能有效.
由于这似乎不能可靠地工作,让我们为每一帧创建自己的颜色映射:
struct Color : Hashable {
let red: UInt8
let green: UInt8
let blue: UInt8
var hashValue: Int {
return Int(red) + Int(green) + Int(blue)
}
public static func ==(lhs: Color, rhs: Color) -> Bool {
return [lhs.red, lhs.green, lhs.blue] == [rhs.red, rhs.green, rhs.blue]
}
}
struct ColorMap {
var colors = Set<Color>()
var exported: Data {
let data = Array(colors)
.map { [$0.red, $0.green, $0.blue] }
.joined()
return Data(bytes: Array(data))
}
}
Run Code Online (Sandbox Code Playgroud)
现在让我们更新我们的方法:
func getScaledImages(_ scale: Int) -> [(CGImage, ColorMap)] {
var sourceImages = [UIImage]()
var result: [(CGImage, ColorMap)] = []
...
var colorMap = ColorMap()
let pixelData = imageRef.dataProvider!.data
let rawData: UnsafePointer<UInt8> = CFDataGetBytePtr(pixelData)
for y in 0 ..< imageRef.height{
for _ in 0 ..< scale {
for x in 0 ..< imageRef.width{
let offset = y * imageRef.width * 4 + x * 4
let color = Color(red: rawData[offset], green: rawData[offset + 1], blue: rawData[offset + 2])
colorMap.colors.insert(color)
for _ in 0 ..< scale {
pixelPointer[byteIndex] = rawData[offset]
pixelPointer[byteIndex+1] = rawData[offset+1]
pixelPointer[byteIndex+2] = rawData[offset+2]
pixelPointer[byteIndex+3] = rawData[offset+3]
byteIndex += 4
}
}
}
}
let cgImage = context.makeImage()!
result.append((cgImage, colorMap))
Run Code Online (Sandbox Code Playgroud)
和
func createAnimatedGifFromImages(_ images: [(CGImage, ColorMap)]) -> URL {
...
for (image, colorMap) in images {
let frameProperties: [String: AnyObject] = [
String(kCGImagePropertyGIFDelayTime): 0.2 as NSNumber,
String(kCGImagePropertyGIFImageColorMap): colorMap.exported as NSData
]
let properties: [String: AnyObject] = [
String(kCGImagePropertyGIFDictionary): frameProperties as AnyObject
];
CGImageDestinationAddImage(destination, image, properties as CFDictionary);
}
Run Code Online (Sandbox Code Playgroud)
当然,这只有在颜色数小于256时才有效.我真的推荐一个可以正确处理颜色转换的自定义GIF库.
| 归档时间: |
|
| 查看次数: |
860 次 |
| 最近记录: |