LoginSignup
4
2

More than 3 years have passed since last update.

Swift:NSImageからDataを生成するときのポイント

Posted at

背景

Twitterに画像を投稿するために、画像のファイルURLからNSImageを生成して、それをDataに変換してPOST APIに投げるというコードを書いていました。一見上手く動いているように見えて、特定のPNG画像だと色がおかしい状態で投稿されることがあることが判明し、原因を究明したところ、NSImageからDataを生成する時、注意しないとデータの透明度に関するデータが欠損するのか、不完全なDataが生成されることがわかりました。

オリジナルのPNG画像↓
sample.png

色がおかしくなったPNG画像↓
bad_image.png

対処方法

検索して出てきた記事によると、いったんNSImageCGImageに変換してから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)
}
4
2
1

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
4
2