LoginSignup
0
0

More than 1 year has passed since last update.

iOSでAPNGを作成してみる

Posted at

iOSでAPNGを作成したいので調べてみた。
適当なライブラリを調べたらAPNGKitが出てきたが表示機能に限定していた。

C++から作れないのかなとlibpingを調べたらパッチを当てるのに票が集まらないわ、ライブラリがメンテナンスしてないわと混迷を極めていた。
APNG support on main libpng library? #267

調べていくと、こちらのページ下部にlibpngにapngパッチ当てたリンクやサンプルコードへのリンクがある。
http://littlesvr.ca/apng/

Apple Document Archive

ニッチ過ぎて情報を見つけるのに手間取ったが、AppleのDocumentにAPNGの作成方法があった。

Image I/O Programming Guide

適当に修正したらうまく動いた。

Animation.swift
import UniformTypeIdentifiers

enum AnimationError: Error {
    case create
    case finalize
}

func Animation(_ images: [UIImage], toUrl: URL, loopCount: Int = 0) throws {
  let frameCount = images.count
  
  let fileProperties = NSMutableDictionary()
  fileProperties.setObject(kCGImagePropertyPNGDictionary, forKey: NSDictionary(dictionary: [kCGImagePropertyAPNGLoopCount: loopCount]))
  
  let frameProperties = NSMutableDictionary()
  frameProperties.setObject(kCGImagePropertyPNGDictionary, forKey: NSDictionary(dictionary: [kCGImagePropertyAPNGDelayTime: 1.0 / Double(frameCount)]))
  
  guard let destination = CGImageDestinationCreateWithURL(toUrl as CFURL, UTType.png.identifier as CFString , frameCount, nil) else {
    throw AnimationError.create
  }
  
  CGImageDestinationSetProperties(destination, fileProperties.copy() as? NSDictionary)
  
  for image in images {
    autoreleasepool {
      CGImageDestinationAddImage(destination, image.cgImage!, frameProperties)
    }
  }
  
  if !CGImageDestinationFinalize(destination) {
    throw AnimationError.finalize
  }
}

評価用にプロジェクト内のPNGを探してテンポラリのAPNGにまとめる処理を書いてみた。
なお、画像は同じ幅のPNGのみ配置。

Example.swift
func test(){
  let path = Bundle.main.bundlePath
  let items = try? FileManager.default.contentsOfDirectory(atPath: path)
  
  do {
    let fileUrl: URL = FileManager.default.temporaryDirectory.appendingPathComponent("test.png")
    
    if FileManager.default.fileExists(atPath: fileUrl.path) {
      try FileManager.default.removeItem(at: fileUrl)
    }
    
    var images = [UIImage]()
    if let items = items {
      try items.sorted().forEach { f in
        if f.hasSuffix(".png") {
          let fileUrl = URL(fileURLWithPath: path).appendingPathComponent(f)
          if FileManager.default.fileExists(atPath: fileUrl.path) {
            let data = try Data(contentsOf: fileUrl)
            if let uiImage = UIImage(data: data) {
              images.append(uiImage)
            }
          }
        }
      }
    }
    try Animation(images, toUrl: fileUrl)
    print(fileUrl)
  } catch {
    print(error.localizedDescription)
  }
}
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0