保存为GIF后图像质量下降 [英] Images lose quality after saving as GIF

查看:177
本文介绍了保存为GIF后图像质量下降的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在开发一个iOS应用程序,允许用户拍摄一系列照片 - 然后将照片放入动画中并导出为MP4和GIF。

Im developing an iOS app which allows users to take a sequence of photos - afterwards the photos are put in an animation and exported as MP4 and GIF.

MP4呈现源质量,GIF颜色等级可见。

While the MP4 presents the source quality, the GIF color grades are visible.

这里是视觉比较:

GIF:

MP4

我用于导出为GIF的代码:

The code I use for exporting as 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();
    });

我用于导出为MP4的代码:

The code I use for exporting as 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();

非常感谢您的帮助!

亲切的问候,

安德烈

推荐答案

这只是摘要我的评论......

This is just summarization of mine comments...

我不在您的平台上编码所以我只提供通用答案(以及我自己的 GIF 编码器/解码器的见解编码体验)。

I do not code on your platform so I only provide generic answer (and insights from mine own GIF encoder/decoder coding experience).

GIF 图像格式支持每像素高达8位,每个像素最多可显示256种颜色,并具有天真的编码功能。便宜的编码器只是将输入图像截断为256或更少的颜色,通常会导致难看的像素化结果。为了提高 GIF 的着色质量,我知道有3种方法:

GIF image format supports up to 8bit per pixel leading to max 256 colors per pixel with naive encoding. Cheap encoders just truncates input image to 256 or less colors usually leading to ugly pixelated results. To increase coloring quality of GIF there are 3 approaches I know of:


  1. 多个用自己的调色板覆盖屏幕的框架

只需将图像划分为叠加层,每个叠层层都有自己的调色板。这很慢(因为您需要处理每个单个图像的更多帧,这可能会导致某些查看器出现同步错误,并且您需要每个图像多次处理所有与帧相关的块)。编码本身很快,因为您只需将基于颜色或区域/位置的帧分离为多个帧。这里(基于地区/位置)示例:

Simply you divide image into overlays each with its own palette. This is slow (in therm of decoding as you need to process more frames per single image which can cause sync errors with some viewers and you need to process all frame related chunks multiple times per single image). The encoding itself is fast as you just either separate the frames based on colors or region/position to multiple frames. Here (region/position based) example:

样本图片来自这里: Wiki

GIF 支持透明度,因此子帧可以重叠... 此方法可以物理地将每像素的颜色增加到 N * 256 (或透明帧的 N * 255 )其中 N 是数字每张图片使用的框架或调色板。

The GIF supports transparency so the sub frames can overlap ... This approach physically increase the colors per pixel possible to N*256 (or N*255 for transparent frames) where N is the number of frames or palettes used per single image.

抖动

抖动是仅使用指定颜色(来自调色板)来近似区域颜色以尽可能接近颜色的技术。这是快速且易于实现的,但结果有点嘈杂。欲了解更多信息,请参阅我的一些相关答案:

Dithering is technique that approximate color of area to match colors as closely as possible while using only specified colors (from palette) only. This is fast and easily implementable but the result is kind of noisy. For more info see some related answers of mine:

  • Converting BMP image to set of instructions for a plotter?
  • c# image dithering routine that accepts an amount of dithering?

更好的色彩量化方法

便宜的编码器只是将颜色截断为预定义的调色板。通过基于直方图聚类使用的颜色可以获得更好的结果。例如,请参阅:

Cheap encoders just truncate the colors to predefined palette. Much better results are obtained by clustering the used colors based on histogram. For example see:

  • Effective gif/image color quantization?

结果通常比抖动好得多但编码时间与抖动相比是巨大的.. 。

The result is usually much better then dithering but the encoding time is huge in comparison to dithering...

#1 #3 可以是一起使用以提高质量......

The #1 and #3 can be used together to enhance quality even more ...

如果您无法访问编码代码或管道,您仍然可以在编码之前转换图像本身进行量化和调色板改为计算并将结果直接加载到 GIF 编码器,这应该是可能的(如果你使用的 GIF 编码器至少有点复杂......)

If you do not have access to the encoding code or pipeline you still can transform image itself before encoding doing the quantization and palette computation instead and load the result directly to GIF encoder which should be possible (if the GIF encoder you are using is at least a bit sophisticated ...)

这篇关于保存为GIF后图像质量下降的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆