背景
Twitterに画像を投稿するために、画像のファイルURLからNSImage
を生成して、それをData
に変換してPOST APIに投げるというコードを書いていました。一見上手く動いているように見えて、特定のPNG画像だと色がおかしい状態で投稿されることがあることが判明し、原因を究明したところ、NSImage
からData
を生成する時、注意しないとデータの透明度に関するデータが欠損するのか、不完全なData
が生成されることがわかりました。
対処方法
検索して出てきた記事によると、いったんNSImage
をCGImage
に変換してからData
にすると良さそうだと判明したのでそちらを使ったところ上手く行きました。
実験に使ったサンプルコード
Command_Line_Tool_Project
import Foundation
import AppKit
func saveImage(name: String, data: Data) {
guard let dir = FileManager.default.urls(for: .desktopDirectory, in: .userDomainMask).first else { exit(3) }
let url: URL = dir.appendingPathComponent(name)
do {
try data.write(to: url)
} catch {
Swift.print(error.localizedDescription)
}
}
// 良い方法
func goodMethod(image: NSImage) -> Data? {
guard let cgImage = image.cgImage(forProposedRect: nil, context: nil, hints: nil) else { return nil }
let rep = NSBitmapImageRep(cgImage: cgImage)
return rep.representation(using: .png, properties: [:])
}
// 悪い方法
func badMethod(image: NSImage) -> Data? {
guard let rep = image.representations.first as? NSBitmapImageRep else { return nil }
return rep.representation(using: .png, properties: [:])
}
guard let image = NSImage(contentsOfFile: "/Users/ユーザ名/Desktop/sample.png") else { exit(0) }
if let data = goodMethod(image: image) {
saveImage(name: "good_image.png", data: data)
}
if let data = badMethod(image: image) {
saveImage(name: "bad_image.png", data: data)
}