NSPasteboardの基本
-
【Apple】URL Reading Options
-
NSPasteboard
に関する全体の話。ベースとしてここを参照しています。 - ※ただしサンプルコードはObjective-Cです。
-
クリップボードからファイルのURLを取得
- 画像のタイプ(png/jpeg/tiff/gif/...)の判別には、UTIを使うと便利そうです。
-
URL
からUTI
を取得する関数は以下を参考にしました。
// ファイルパスがコピーされている場合を考える
let pasteboard = NSPasteboard.general
// NSImageの扱うUTIを指すfileURLのみ抽出する設定
// 具体的にはprint(NSImage.imageTypes)で確認できる
let classes = [NSURL.self]
let options: [NSPasteboard.ReadingOptionKey : Any] = [.urlReadingFileURLsOnly : true,
.urlReadingContentsConformToTypes : NSImage.imageTypes]
let canRead = pasteboard.canReadObject(forClasses: classes, options: options)
if canRead {
let objectsToPaste = pasteboard.readObjects(forClasses: classes,
options: options) ?? []
if objectsToPaste.count > 0 {
let fileURL = objectsToPaste[0] as! URL
if let uti = uti(url: fileURL) {
// 画像フォーマットを取得できる
print(uti) // e.g. UTI: Optional("public.png")
}
imageView.image = NSImage(contentsOf: fileURL) // 出力して確認
}
} else {
print("クリップボードにファイルパスはありませんでした")
}
func uti(url: URL) -> String? {
guard let r = try? url.resourceValues(forKeys: [.typeIdentifierKey]) else {
return nil
}
return r.typeIdentifier
}
クリップボードから画像を取得
NSImageとして取得
-
NSImage
のコンストラクタにNSPasteboard
のインスタンスを渡すことができます。
// 画像がクリップボードにコピーされている場合
let pasteboard = NSPasteboard.general
if let image = NSImage(pasteboard: pasteboard) {
imageView.image = image // 出力して確認
} else {
print("クリップボードに画像はありませんでした")
}
- もし複数のクリップボードのアイテムを取得したい場合は、下記の通り
objectsToPaste
を経由します。- 前述の
readObjects
のforClasses
をNSImage
と変えています。
- 前述の
// 画像がクリップボードにコピーされている場合
let pasteboard = NSPasteboard.general
let classes = [NSImage.self]
let options = [NSPasteboard.ReadingOptionKey : Any]()
let canRead = pasteboard.canReadObject(forClasses: classes, options: options)
if canRead {
let objectsToPaste = pasteboard.readObjects(forClasses: classes,
options: options) ?? []
if objectsToPaste.count > 0 {
let image = objectsToPaste[0] as! NSImage
imageView.image = image // 出力して確認
}
} else {
print("クリップボードに画像はありませんでした")
}
- ただ欠点として、
NSImage
としてデータを保持してしまうと、元の画像のフォーマットを取得できません。 - つまり
NSImage
として読み込む前の段階で、画像のフォーマット情報を得ておく必要があります。
Dataを経由して取得(画像のフォーマット情報も取得できる)
-
NSPasteboard
の機能をうまく利用すると、画像のフォーマット情報を取得することができます。 -
toolinbox/iPicUploader
- ここのコードを参考にしました。サンプルプロジェクトから
Jump to Definition
を繰り返せば色々見れるはずです。 - 今回私のコードはなるべく短くしています。きちんと書く場合は、クラスや関数の分け方を上記ソースから参考にすると良いと思います。
- ここのコードを参考にしました。サンプルプロジェクトから
// クリップボードの内容を一旦全て取得する
guard let pasteboardItems = NSPasteboard.general.pasteboardItems else {
return
}
var myImages = [MyImageInfo]()
for pasteboardItem in pasteboardItems {
for type in pasteboardItem.types {
if let data = pasteboardItem.data(forType: type) {
if let image = NSImage(data: data) {
myImages.append(MyImageInfo(image: image, uti: type))
}
}
}
}
struct MyImageInfo {
let image: NSImage
let uti: NSPasteboard.PasteboardType
}
-
NSPasteboard.PasteboardType
- しかし足りないものもあって、例えばjpg(
public.jpeg
)は定数で用意されていないから自分で用意しないといけないかもです。
- しかし足りないものもあって、例えばjpg(
print(NSPasteboard.PasteboardType.png.rawValue) // public.png
- StackOverflow等を検索すると、画像のバイナリの先頭数バイトを見て判断、というアイディアしか見つかりませんでした。
- (ゴリゴリ系はあまり実装したくないですね)
-
How to identify a NSData's image format?
- PNGとJPGを最初の4byteで見分ける。
- Finding image type from NSData or UIImage
-
How to identify a NSData's image format?
- 実際にHex Fiendでバイナリを確認してみると以下の通り。
デバッグ時の小ネタ
スクリーンショットの拡張子を変更する
- デフォルトは
png
ですが下記の通り変更可能です。
defaults write com.apple.screencapture type jpeg
現在のクリップボードを確認する
- Finderのメニューから
クリップボードを表示
から確認できます。 - 拡張子も確認できるので、デバッグ時のお供に。
NSImageのUTIを確認する
let utis = NSImage.imageTypes
for uti in utis {
print(uti)
}
com.adobe.pdf
com.apple.pict
com.adobe.encapsulated-postscript
public.jpeg
public.png
com.compuserve.gif
com.canon.tif-raw-image
com.adobe.raw-image
com.dxo.raw-image
com.canon.cr2-raw-image
com.canon.cr3-raw-image
com.leafamerica.raw-image
com.hasselblad.fff-raw-image
com.hasselblad.3fr-raw-image
com.nikon.raw-image
com.nikon.nrw-raw-image
com.pentax.raw-image
com.samsung.raw-image
com.sony.raw-image
com.sony.sr2-raw-image
com.sony.arw-raw-image
com.epson.raw-image
com.kodak.raw-image
public.tiff
public.jpeg-2000
com.apple.atx
org.khronos.astc
org.khronos.ktx
public.avci
public.heic
public.heics
public.heif
com.canon.crw-raw-image
com.fuji.raw-image
com.panasonic.raw-image
com.panasonic.rw2-raw-image
com.leica.raw-image
com.leica.rwl-raw-image
com.konicaminolta.raw-image
com.olympus.sr-raw-image
com.olympus.or-raw-image
com.olympus.raw-image
com.phaseone.raw-image
com.microsoft.ico
com.microsoft.bmp
com.apple.icns
com.adobe.photoshop-image
com.microsoft.cur
com.truevision.tga-image
com.ilm.openexr-image
com.sgi.sgi-image
public.radiance
public.pbm
public.mpo-image
public.pvr
com.microsoft.dds