在 Cocoa 中创建动画 GIF - 定义帧类型

2024-03-26

我已经能够改编在 SO 上找到的一些代码,从我的视图的“屏幕截图”生成动画 GIF,但结果是不可预测的。 GIF 帧有时是完整图像、完整帧(“替换”模式,正如 GIMP 所标记的那样),其他时候只是与上一层的“差异”(“组合”模式)。

据我所知,当涉及的帧较少和/或较小时,CG 以“组合”模式写入 GIF,但无法获得正确的颜色。事实上,移动部件的颜色是正确的,背景是错误的。 当CG将GIF保存为全帧时,颜色还可以。文件大小较大,但是,嘿,显然你无法两全其美。 :)

有没有办法:

    a) force CG to create "full frames" when saving the GIF
    b) fix the colors (color table?)

我所做的是(ARC模式):

捕获视图的可见部分

[[scrollView contentView] dataWithPDFInsideRect:[[scrollView contentView] visibleRect]];

将其转换并调整大小为 PNG 类型的 NSImageBitmapRep

-(NSMutableDictionary*) pngImageProps:(int)quality {
  NSMutableDictionary *pngImageProps;  
  pngImageProps = [[NSMutableDictionary alloc] init];
  [pngImageProps setValue:[NSNumber numberWithBool:NO] forKey:NSImageInterlaced];
  double compressionF = 1;

  [pngImageProps setValue:[NSNumber numberWithFloat:compressionF] forKey:NSImageCompressionFactor];
  return pngImageProps;
}


-(NSData*) resizeImageToData:(NSData*)data toDimX:(int)xdim andDimY:(int)ydim withQuality:(int)quality{
  NSImage *image = [[NSImage alloc] initWithData:data];
  NSRect inRect = NSZeroRect;
  inRect.size = [image size];

  NSRect outRect = NSMakeRect(0, 0, xdim, ydim);
  NSImage *outImage = [[NSImage alloc] initWithSize:outRect.size];

  [outImage lockFocus];
    [image drawInRect:outRect fromRect:inRect operation:NSCompositeCopy fraction:1];
    NSBitmapImageRep* bitmapRep = [[NSBitmapImageRep alloc] initWithFocusedViewRect:outRect];
  [outImage unlockFocus];

  NSMutableDictionary *imageProps = [self pngImageProps:quality];
  NSData* imageData = [bitmapRep representationUsingType:NSPNGFileType properties:imageProps];
  return [imageData copy];
}

获取 BitmapReps 数组并创建 GIF

-(CGImageRef) pngRepDataToCgImageRef:(NSData*)data {
  CFDataRef imgData = (__bridge CFDataRef)data;
  CGDataProviderRef imgDataProvider = CGDataProviderCreateWithCFData (imgData);
  CGImageRef image = CGImageCreateWithPNGDataProvider(imgDataProvider, NULL, true, kCGRenderingIntentDefault);
  return image;
}

////////// create GIF from 

NSArray *images;  // holds all BitmapReps

CGImageDestinationRef destination = CGImageDestinationCreateWithURL((__bridge CFURLRef)[NSURL fileURLWithPath:pot],
                                                                    kUTTypeGIF,
                                                                    allImages,
                                                                    NULL);
// set frame delay
NSDictionary *frameProperties = [NSDictionary
                                 dictionaryWithObject:[NSDictionary
                                                       dictionaryWithObject:[NSNumber numberWithFloat:0.2f]
                                                       forKey:(NSString *) kCGImagePropertyGIFDelayTime]
                                 forKey:(NSString *) kCGImagePropertyGIFDictionary];

// set gif color properties
NSMutableDictionary *gifPropsDict = [[NSMutableDictionary alloc] init];
[gifPropsDict setObject:(NSString *)kCGImagePropertyColorModelRGB forKey:(NSString *)kCGImagePropertyColorModel];
[gifPropsDict setObject:[NSNumber numberWithBool:YES] forKey:(NSString *)kCGImagePropertyGIFHasGlobalColorMap];

// set gif loop
NSDictionary *gifProperties = [NSDictionary
                               dictionaryWithObject:gifPropsDict
                               forKey:(NSString *) kCGImagePropertyGIFDictionary];

// loop through frames and add them to GIF 
for (int i=0; i < [images count]; i++) {
  NSData *imageData = [images objectAtIndex:i];
  CGImageRef imageRef = [self pngRepDataToCgImageRef:imageData];
    CGImageDestinationAddImage(destination, imageRef, (__bridge CFDictionaryRef) (frameProperties));
}

// save the GIF
CGImageDestinationSetProperties(destination, (__bridge CFDictionaryRef)(gifProperties));
CGImageDestinationFinalize(destination);
CFRelease(destination);

我检查了 ImageBitmapReps,当单独保存为 PNG 时,它们就很好。 据我了解,颜色表应该由 CG 处理,还是我负责生成抖动颜色?怎么做?

即使重复制作相同的动画,生成的 GIF 也可能会有所不同。

这是单个 BitmapRep

single frame
(source: andraz.eu http://andraz.eu/stuff/gif/frame.png)

And this is the GIF with the invalid colors ("combine" mode) combined frames
(source: andraz.eu http://andraz.eu/stuff/gif/anim2.gif)


我读了你的代码。创建 CGImageDestinationRef 时,请仔细检查“allImages”和“[images count]”。

以下测试代码工作正常:

NSDictionary *prep = [NSDictionary dictionaryWithObject:[NSDictionary dictionaryWithObject:[NSNumber numberWithFloat:0.2f] forKey:(NSString *) kCGImagePropertyGIFDelayTime] forKey:(NSString *) kCGImagePropertyGIFDictionary];

CGImageDestinationRef dst = CGImageDestinationCreateWithURL((__bridge CFURLRef)(fileURL), kUTTypeGIF, [filesArray count], nil);

for (int i=0;i<[filesArray count];i++)
{
    //load anImage from array
    ...

    CGImageRef imageRef=[anImage CGImageForProposedRect:nil context:nil hints:nil];
    CGImageDestinationAddImage(dst, imageRef,(__bridge CFDictionaryRef)(prep));

}

bool fileSave = CGImageDestinationFinalize(dst);
CFRelease(dst);
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

在 Cocoa 中创建动画 GIF - 定义帧类型 的相关文章

  • C++ 引用类型作为 Objective-C++ 中的实例变量

    Objective C 中禁止将 C 引用类型用作实例变量 我该如何解决这个问题 您不能明智地使用引用作为实例变量 因为无法初始化实例变量并且无法重新放置引用 另一种选择可能是简单地使用 可能是智能的 指针 另一种让您更接近 C 行为的可能
  • 为什么 Obj-C 属性默认所有权“分配”而不是“强”

    我正在向旧项目添加 Swift 类 一切进展顺利 直到我尝试向 Swift 类添加属性 生成的标头无法编译 我认为问题是 在生成的代码中 Swift 省略了strong所有权并仅将其声明为nonatomic 这通常应该足够了 因为 prop
  • Objective-C 实现文件中方法名后面的分号

    void designImageViewNow some code here 分号写法正确吗 就在实现文件 Objective C 中方法名称之后 正文括号之前 这行得通吗 当我正在开发 iPhone 应用程序时 我错误地将分号放在了一个自
  • For 循环不适用于 JavaScript 动画

    我正在尝试编写一个 for 循环 以在单击形状按钮时重复 爆炸 路径的动画 但 for 循环无法工作 执行 而且我看不出哪里出了问题 for循环的目的 循环动画路径的过程 然后将动画反转回其原始路径 我知道问题出在 for 循环中的某个地方
  • 将 NSString 的 NSArray 转换为 NSNumber 的更好方法

    考虑下面的代码 NSString param string 1 3 6 10 15 22 28 30 NSArray params param string componentsSeparatedByString NSNumberForma
  • UITextField 文本更改事件

    如何检测文本字段中的任何文本更改 委托方法shouldChangeCharactersInRange适用于某些东西 但它并不能完全满足我的需求 因为在它返回 YES 之前 textField 文本不可用于其他观察者方法 例如在我的代码中ca
  • UISegmentedControl 中的自定义字体禁用调整FontSizeToFitWidth

    我已经为我的 UISegmentedControl 设置了自定义字体 但它似乎禁用了默认字体自动调整字体大小以适合宽度范围 Before After 这是我用来设置自定义字体的代码 UISegmentedControl segmentedC
  • 创建类似于邮件应用程序菜单的 iPhone 弹出菜单

    当您想要回复消息时 我想创建一个类似于邮件应用程序中的弹出菜单 我在多个应用程序中看到过这一点 所以我不确定框架中是否内置了某些内容或一些示例代码 在 Swift 中创建操作表 代码已使用 Swift 5 进行测试 从 iOS 8 开始 U
  • iPhone iOS 保存从 UIImageJPEGRepresentation() 获得的数据第二次失败:ImageIO: CGImageRead_mapData 'open' failed

    我的 UIImage 操作遇到了一个奇怪的问题 我正在进行保管箱同步 并且必须将我的图像存储为本地文件 为此 我使用以下命令保存它们UIImagePNGRepresentation image or UIImageJPEGRepresent
  • 将第 3 方库 ZXing 导入 Xcode

    我尝试了多种方法将第 3 方库 ZXing 导入我的 iOS 应用程序 但所有方法都很痛苦 或者根本不起作用 如果有人可以建议我做错了什么 或者提出导入 ZXing 等库的更好方法 我将非常感激 一定比这个容易 这就是我所做的 结果是 My
  • iPad 照片选择器崩溃

    我正在使用以下函数根据 UIActionSheet 的结果激活设备相机或图像选择器 如果 fromCamera YES 那么它适用于 iPhone 和 iPad 如果 fromCamera NO 那么它可以在 iPhone 上运行并出现图像
  • 如何从右向左缩放按钮,android动画

    要将从左到右的缩放应用于按钮 我使用了以下代码 我的按钮位于布局的右侧 我希望按钮应该从右侧 X 位置开始并缩放到左侧 X 位置 如何实现这一点 view startAnimation new ScaleAnimation 0 0f 1 0
  • 您是否标记 UIView 或将它们保留为属性?

    这主要是一个风格问题 但自从我开始为 iPhone 编程以来 我一直很好奇其他人的想法是什么 当您的 iPhone 应用程序中有一个 UIView 并且需要在应用程序的其他位置访问它时 通常在视图控制器中的另一个函数中 您是否喜欢用整数标记
  • Cocos2d 变色精灵

    我需要我的精灵从一种颜色过渡到另一种颜色 然后不断地 比如蓝色 然后绿色 然后紫色 但我找不到任何好的动作 我想知道 我应该使用动画吗 或者是否有为此采取的联合行动 您可以使用 CCTintTo 操作来更改精灵的颜色 sprite runA
  • 如何在 iOS 9 上可靠地检测是否连接了外部键盘?

    在 iOS 9 之前 确定是否连接外部键盘的最可靠方法是监听UIKeyboardWillShowNotification并使文本字段成为第一响应者 如中所述这个问题 https stackoverflow com questions 289
  • 导入 RNCryptor 后架构 armv7 的未定义符号

    我导入了 RNCryptor 可以在这里找到 https github com rnapier RNCryptor https github com rnapier RNCryptor进入我的应用程序 但是 我在日志中收到了三个错误 Und
  • 如何将 UILabel 的值绑定到实例变量?

    我是 mac objective c 的新手 我的问题是 我想知道是否可以将 UILabel 文本绑定到变量 而不必在值更改时手动设置文本 例如 在 Mac OS 上 当我打开新的 Finder 窗口并删除文件时 任务栏中的全局可用空间就会
  • 覆盖层不与 UITableView 一起滚动 - iOS

    我有一个 UITableView 类 它使用以下方法在转到下一个屏幕时调用加载覆盖 问题是这个加载屏幕不随列表滚动 所以如果你滚动一点并单击某些东西 加载屏幕不会显示 因为它位于顶部 如何让加载屏幕始终保持在 UITableView 的顶部
  • 推送动画,没有阴影和停电

    我有一个简单的iOS NavigationController基于应用程序 二UICollectionViews 相继 如果元素打开 第一个合集 被点击时 第二集 将被打开 非常简单 重要的提示 Both UICollectionViews
  • 在 UIScrollview 上显示缩略图的最佳方法是什么(从服务器下载)

    我想在 UIScrollview 如照片应用程序 上显示许多图像 作为缩略图 所有图像将从服务器下载 据我所知 有几种选择 1 通过创建 UIImageviews 然后将它们添加为主滚动视图上的子视图 2 通过子类化一个UIView类 然后

随机推荐

  • Bootstrap 输入组插件对齐问题

    我的输入组插件与我的输入文本框不对齐 我做错了什么 div class form group div
  • 我无法让 phpseclib 工作

    我想做的事 我想要upload download一个文件通过sftp using php The phpseclib library看起来很有前途 我已经做了什么 我将composer json更改为 require nicolab php
  • 如何在Azure中创建或使用本地文件夹?

    我需要从 SFTP 服务器下载文件 下载的文件存储到本地文件夹 D Data tempData csv 我必须从本地文件读取数据并在我的应用程序中使用以进行其他数据操作 此作业是使用 Azure Web 作业中的 Web 挂钩计划程序创建的
  • 我的“zipLatest”运算符是否已经存在?

    关于我自己写的一个运算符的快速问题 请原谅我可怜的大理石图表 zip aa bb cc dd ee ff gg 11 22 33 44 55 a1 b2 c3 d4 e5 combineLatest aa bb cc dd ee ff gg
  • 使用 f:convertNumber 时设置小数点分隔符

    我想知道如何在 JSF 应用程序上设置默认的小数点分隔符 我有一些
  • NodeJS UDP 多播如何

    我正在尝试将 UDP 多播数据包发送到 230 185 192 108 以便每个订阅的人都会收到 有点卡住了 我相信它的广播正确 但似乎无法从任何客户端获取任何信息 Server var news Borussia Dortmund win
  • 如何将多个参数传递给 Scrapy 蜘蛛(不再支持使用多个蜘蛛运行“scrapy scrapy”时出现错误)?

    我想将多个用户定义的参数传递给我的 scrapy spider 所以我尝试遵循这篇文章 如何在 scrapy 蜘蛛中传递用户定义的参数 https stackoverflow com questions 15611605 how to pa
  • CMTime 和 AVFoundation 中单帧的移动

    我正在尝试使用 AVFoundation 播放视频 我使用以下代码作为将播放前进一帧的按钮 它间歇性地工作 在某些执行中它会做正确的事情并前进一帧 但大多数时候我必须按按钮 3 或 4 次才能前进一帧 这让我认为这是某种精度问题 但我无法弄
  • 为什么单函数访问器似乎被认为是坏习惯?

    我经常看到 即在 Slim 框架内 单一函数访问器风格 如下面的 1 已弃用 取而代之的是经典的 Java ish 2 函数访问器 get set 如下面的 2 就我个人而言 我更喜欢更少的代码行 在 1 中 和更少的输入 get set
  • Java多线程数据库访问[关闭]

    Closed 这个问题需要多问focused help closed questions 目前不接受答案 对于多线程 Java 应用程序来说 确保所有线程同步访问数据库的最佳解决方案是什么 例如 每个线程代表单独的事务 并且首先检查数据库的
  • 使用 FFT 进行 Matlab 模板匹配

    我正在努力解决 Matlab 中傅立叶域中的模板匹配问题 这是我的图片 艺术家是 DeviantArt 上的 RamalamaCreatures 我的目标是在负鼠的耳朵周围放置一个边界框 就像这个例子 我使用normxcorr2执行模板匹配
  • Stripe webhook 签名失败 - Stripe.net

    我正在尝试使用 Jayme Davis 的 C 库 Stripe net 来实现 stripe webhook 我已经在条带仪表板中设置了测试端点并生成了秘密 端点命中良好 并将使用 StripeEventUtility ParseEven
  • Django Celery 内存未释放

    在我的 django 项目中 我有以下依赖项 Django 1 5 4 django celery 3 1 9 amqp 1 4 3 海带 3 0 14 librabbitmq 1 0 3 按照建议https stackoverflow c
  • MongoDB:文档大小会影响查询性能吗?

    假设一款手机游戏由 MongoDB 数据库支持 其中包含User包含数百万份文档的集合 现在假设必须与用户关联的几十个属性 例如一个数组 id的值Friend文件 他们的用户名 照片 一系列 id的值Game文件 上次登录日期 游戏货币数量
  • C++ 传递字符串文字而不是 const std::string&?

    我有以下代码 使用 g 进行编译时没有警告 Wall pedantic include
  • Kotlin 中带有 val 的循环引用

    在 Kotlin 中 假设我有data class A val f B and data class B val f A 我想初始化本地var a A and var b B这样a f is b and b f is a A f and B
  • CUDA __syncthreads() 编译正常,但带有红色下划线

    我已经使用 CUDA 4 2 一周了 但遇到了一些问题 当我编写 syncthreads 函数时 它会带有下划线 看起来是错误的 然后 如果我将鼠标放在该函数上 则会出现一条消息 标识符 syncthreads 未定义 但是当我编译我的项目
  • VB6 解析器/词法分析器/脚本编写器

    我有一个 VB6 游戏 它运行得很好 但我一直在考虑创建一个脚本引擎的想法 我想我希望 VB6 为我读取纯文本脚本文件 然后 lex parse execute 它们 我有很好的编程经验 之前也搭建过一个简单的C编译器 以及一个LOGO模拟
  • Android ExpandableListView 和 onChildClick 不起作用

    我已经阅读了很多与我遇到相同问题的线程 但我无法弄清楚发生了什么 我有一个可扩展的列表视图 但我无法使 onChildClickListener 工作 onGroupClickListener 工作正常 但我并不真正需要它 我看了很多例子
  • 在 Cocoa 中创建动画 GIF - 定义帧类型

    我已经能够改编在 SO 上找到的一些代码 从我的视图的 屏幕截图 生成动画 GIF 但结果是不可预测的 GIF 帧有时是完整图像 完整帧 替换 模式 正如 GIMP 所标记的那样 其他时候只是与上一层的 差异 组合 模式 据我所知 当涉及的