And*_*re 4 image-processing gif ios swift
我正在开发一款 iOS 应用程序,它允许用户拍摄一系列照片 - 然后将照片放入动画中并导出为 MP4 和 GIF。
虽然 MP4 呈现源质量,但 GIF 颜色等级是可见的。
这是视觉比较:
动图:
MP4
我用于导出为 GIF 的代码:
var dictFile = new NSMutableDictionary();
var gifDictionaryFile = new NSMutableDictionary();
gifDictionaryFile.Add(ImageIO.CGImageProperties.GIFLoopCount, NSNumber.FromFloat(0));
dictFile.Add(ImageIO.CGImageProperties.GIFDictionary, gifDictionaryFile);
var dictFrame = new NSMutableDictionary();
var gifDictionaryFrame = new NSMutableDictionary();
gifDictionaryFrame.Add(ImageIO.CGImageProperties.GIFDelayTime, NSNumber.FromFloat(0f));
dictFrame.Add(ImageIO.CGImageProperties.GIFDictionary, gifDictionaryFrame);
InvokeOnMainThread(() =>
{
var imageDestination = CGImageDestination.Create(fileURL, MobileCoreServices.UTType.GIF, _images.Length);
imageDestination.SetProperties(dictFile);
for (int i = 0; i < this._images.Length; i++)
{
imageDestination.AddImage(this._images[i].CGImage, dictFrame);
}
imageDestination.Close();
});
Run Code Online (Sandbox Code Playgroud)
我用于导出为 MP4 的代码:
var videoSettings = new NSMutableDictionary();
videoSettings.Add(AVVideo.CodecKey, AVVideo.CodecH264);
videoSettings.Add(AVVideo.WidthKey, NSNumber.FromNFloat(images[0].Size.Width));
videoSettings.Add(AVVideo.HeightKey, NSNumber.FromNFloat(images[0].Size.Height));
var videoWriter = new AVAssetWriter(fileURL, AVFileType.Mpeg4, out nsError);
var writerInput = new AVAssetWriterInput(AVMediaType.Video, new AVVideoSettingsCompressed(videoSettings));
var sourcePixelBufferAttributes = new NSMutableDictionary();
sourcePixelBufferAttributes.Add(CVPixelBuffer.PixelFormatTypeKey, NSNumber.FromInt32((int)CVPixelFormatType.CV32ARGB));
var pixelBufferAdaptor = new AVAssetWriterInputPixelBufferAdaptor(writerInput, sourcePixelBufferAttributes);
videoWriter.AddInput(writerInput);
if (videoWriter.StartWriting())
{
videoWriter.StartSessionAtSourceTime(CMTime.Zero);
for (int i = 0; i < images.Length; i++)
{
while (true)
{
if (writerInput.ReadyForMoreMediaData)
{
var frameTime = new CMTime(1, 10);
var lastTime = new CMTime(1 * i, 10);
var presentTime = CMTime.Add(lastTime, frameTime);
var pixelBufferImage = PixelBufferFromCGImage(images[i].CGImage, pixelBufferAdaptor);
Console.WriteLine(pixelBufferAdaptor.AppendPixelBufferWithPresentationTime(pixelBufferImage, presentTime));
break;
}
}
}
writerInput.MarkAsFinished();
await videoWriter.FinishWritingAsync();
Run Code Online (Sandbox Code Playgroud)
我将不胜感激您的帮助!
亲切的问候,
安德烈
这只是我的评论的总结...
我不在你们的平台上编码,所以我只提供通用答案(以及我自己的GIF编码器/解码器编码经验的见解)。
GIF图像格式支持每像素高达 8 位,从而通过简单编码实现每像素最多 256 种颜色。廉价的编码器只是将输入图像截断为 256 种或更少的颜色,通常会导致丑陋的像素化结果。为了提高GIF的着色质量,我知道有 3 种方法:
多个框架覆盖屏幕并带有自己的调色板
只需将图像划分为多个叠加层,每个叠加层都有自己的调色板。这是很慢的(就解码而言,因为您需要为每个图像处理更多帧,这可能会导致某些查看器出现同步错误,并且您需要为每个图像多次处理所有与帧相关的块)。编码本身很快,因为您只需根据颜色或区域/位置将帧分离为多个帧。这里(基于区域/位置)示例:
示例图像取自此处:Wiki
GIF支持透明度,因此子帧可以重叠...这种方法从物理上增加了每个像素可能的颜色(或对于透明帧),其中是每个图像使用的帧或调色板的数量。N*256
N*255
N
抖动
抖动是一种在仅使用指定颜色(来自调色板)的情况下近似区域颜色以尽可能接近地匹配颜色的技术。这是快速且易于实现的,但结果有点嘈杂。有关更多信息,请参阅我的一些相关答案:
更好的色彩量化方法
廉价的编码器只是将颜色截断为预定义的调色板。通过基于直方图对使用的颜色进行聚类可以获得更好的结果。例如参见:
结果通常比抖动好得多,但与抖动相比,编码时间很长......
# 1和#3可以一起使用以进一步提高质量......
如果您无权访问编码代码或管道,您仍然可以在编码之前转换图像本身,进行量化和调色板计算,并将结果直接加载到GIF编码器,这应该是可能的(如果您使用的GIF编码器至少是有点复杂……)
归档时间: |
|
查看次数: |
2133 次 |
最近记录: |