NSImageを特定のディレクトリに新しいファイル(png、jpg、...)として保存するにはどうすればよいですか?
このようなことをしてください:
NSBitmapImageRep *imgRep = [[image representations] objectAtIndex: 0];
NSData *data = [imgRep representationUsingType: NSPNGFileType properties: nil];
[data writeToFile: @"/path/to/file.png" atomically: NO];
このようにNSImageにカテゴリを追加できます
@interface NSImage(saveAsJpegWithName)
- (void) saveAsJpegWithName:(NSString*) fileName;
@end
@implementation NSImage(saveAsJpegWithName)
- (void) saveAsJpegWithName:(NSString*) fileName
{
// Cache the reduced image
NSData *imageData = [self TIFFRepresentation];
NSBitmapImageRep *imageRep = [NSBitmapImageRep imageRepWithData:imageData];
NSDictionary *imageProps = [NSDictionary dictionaryWithObject:[NSNumber numberWithFloat:1.0] forKey:NSImageCompressionFactor];
imageData = [imageRep representationUsingType:NSJPEGFileType properties:imageProps];
[imageData writeToFile:fileName atomically:NO];
}
@end
「TIFFRepresentation」の呼び出しは不可欠です。そうしないと、有効な画像を取得できない可能性があります。
あなたの残りの部分についてはわからないが、私は完全なエンチラーダを食べることを好む。上記で説明したことは機能し、何も問題はありませんが、いくつかの問題が残っています。ここで私の観察結果を強調します:
その画像を変換したい場合、本当にこれらすべてを失いたいですか?あなたが完全な食事を食べたいなら、読んでみましょう...
時々、私は時々、古き良きオールドスクールの開発よりも良いものはないことを意味します。ええ、それは私たちが少し仕事をしなければならないことを意味します!
始めましょう:
NSDataにカテゴリを作成します。これらはクラスメソッドです。これらのことをスレッドセーフにしたいので、スタックに置くよりも安全なものはないからです。メソッドには2つのタイプがあります。1つは非マルチページ画像の出力用、もう1つはマルチページ画像の出力用です。
単一画像のリスト: JPG、PNG、BMP、JPEG-2000
複数の画像のリスト: PDF、GIF、TIFF
まず、メモリ内に可変データスペースを作成します。
NSMutableData * imageData = [NSMutableData data];
次に、CGImageSourceRefを取得します。うん、もういですね。それほど悪くはありません、続けましょう...データの表現やNSImageチャンクではなく、ソースイメージが本当に必要です。ただし、小さな問題があります。ソースには互換性がない可能性があるため、CGImageSourceCopyTypeIdentifiers()からリストされたUTIとUTIを必ず確認してください。
いくつかのコード:
CGImageSourceRef imageSource = nil;
if ( /* CHECK YOUR UTI HERE */ )
return CGImageSourceCreateWithURL( (CFURLRef)aURL, nil );
NSImage * anImage = [[NSImage alloc] initWithContentsOfURL:aURL];
if ( anImage )
return CGImageSourceCreateWithData( (CFDataRef)[anImage TIFFRepresentation], nil );
ちょっと待って、なぜNSImageがあるのですか?メタデータがなく、CGImageSourceがサポートしていない形式もありますが、これらは有効な画像です。例は、古いスタイルのPICT画像です。
これでCGImageSourceRefができました。nilでないことを確認してから、CGImageDestinationRefを取得しましょう。これらすべての参照を追跡するのはすごい。これまでのところ、2になっています!
この関数を使用します:CGImageDestinationCreateWithData()
3番目のパラメータは、保存する画像の数です。単一の画像ファイルの場合、これは1です。それ以外の場合は、単に次を使用できます。
CGImageSourceGetCount(imageSource);
4番目のパラメーターはありません。
このCGImageDestinationRefがあるかどうかを確認し、ソースから画像を追加してみましょう...これには、すべて/すべてのメタデータが含まれ、解像度が保持されます。
複数の画像の場合、ループします:
for ( NSUInteger i = 0; i < count; ++i )
CGImageDestinationAddImageFromSource( imageDest, imageSource, i, nil );
単一の画像の場合、インデックス0の1行のコードです。
CGImageDestinationAddImageFromSource( imageDest, imageSource, 0, nil);
OK、ファイナライズしてディスクまたはデータコンテナーに書き込みます。
CGImageDestinationFinalize( imageDest );
そのため、最初からの可変データには、すべての画像データとメタデータが含まれています。
まだ終わってないか?ほとんど、ガベージコレクションを使用しても、クリーンアップする必要があります。参照元と送信先の2つのRefを覚えているので、CFRelease()
これで完了です。最終的に、メタデータ、解像度などをすべて保持する変換された画像になります。
NSDataのカテゴリメソッドは次のようになります。
+ (NSData *) JPGDataFromURL:(NSURL *)aURL;
+ (NSData *) PNGDataFromURL:(NSURL *)aURL;
+ (NSData *) BMPDataFromURL:(NSURL *)aURL;
+ (NSData *) JPG2DataFromURL:(NSURL *)aURL;
+ (NSData *) PDFDataFromURL:(NSURL *)aURL;
+ (NSData *) GIFDataFromURL:(NSURL *)aURL;
+ (NSData *) TIFFDataFromURL:(NSURL *)aURL;
サイズ変更やICO/ICNSはどうですか?これは別の日ですが、要約すると最初にサイズ変更に取り組みます...
ソースに埋め込まれた複数の画像をすすぎ、繰り返します。
ICOとICNSの唯一の違いは、1つは単一のイメージであり、もう1つは1つのファイル内の複数のイメージであることです。どっちがどっちなのか推測できる?! ;-)これらのフォーマットでは、特定のサイズにサイズ変更する必要があります。そうしないと、エラーが発生します。ただし、プロセスは適切なUTIを使用する場合とまったく同じですが、サイズ変更はもう少し厳密です。
これが他の人の助けになり、あなたが今と同じくらいいっぱいになっていることを願っています!
おっと、言及するのを忘れました。 NSDataオブジェクトを取得したら、writeToFile、writeToURL、または必要に応じて別のNSImageを作成します。
ハッピーコーディング!
import AppKit
extension NSImage {
@discardableResult
func saveAsPNG(url: URL) -> Bool {
guard let tiffData = self.tiffRepresentation else {
print("failed to get tiffRepresentation. url: \(url)")
return false
}
let imageRep = NSBitmapImageRep(data: tiffData)
guard let imageData = imageRep?.representation(using: .PNG, properties: [:]) else {
print("failed to get PNG representation. url: \(url)")
return false
}
do {
try imageData.write(to: url)
return true
} catch {
print("failed to write to disk. url: \(url)")
return false
}
}
}
Swift 4.2ソリューション
public extension NSImage {
public func writePNG(toURL url: URL) {
guard let data = tiffRepresentation,
let rep = NSBitmapImageRep(data: data),
let imgData = rep.representation(using: .png, properties: [.compressionFactor : NSNumber(floatLiteral: 1.0)]) else {
Swift.print("\(self) Error Function '\(#function)' Line: \(#line) No tiff rep found for image writing to \(url)")
return
}
do {
try imgData.write(to: url)
}catch let error {
Swift.print("\(self) Error Function '\(#function)' Line: \(#line) \(error.localizedDescription)")
}
}
}
迅速なスタイル:
if let imgRep = image?.representations[0] as? NSBitmapImageRep
{
if let data = imgRep.representationUsingType(NSBitmapImageFileType.NSPNGFileType, properties: [:])
{
data.writeToFile("/path/to/file.png", atomically: false)
}
}
クロスプラットフォームコードを支援するために、Macで実行する(およびNSImage
を使用する)バージョンのUIImagePNGRepresentation()
を実装しました。
#if os(macOS)
public func UIImagePNGRepresentation(_ image: NSImage) -> Data? {
guard let cgImage = image.cgImage(forProposedRect: nil, context: nil, hints: nil)
else { return nil }
let imageRep = NSBitmapImageRep(cgImage: cgImage)
imageRep.size = image.size // display size in points
return imageRep.representation(using: .png, properties: [:])
}
#endif
使用法:
if let data = UIImagePNGRepresentation(myImage) {
do { try data.write(to: url, options: [.atomic]) }
catch let error { print("Error writing image (\(error))") }
}
Swiftを使用した動作保証アプローチがもう1つあります。
ユーザーが任意の画像をドロップできる「Image Well」があります。そして、この「Image Well」には、アウトレットを介してアクセスされる(NSImageタイプの)イメージプロパティがあります。
@IBOutlet weak var imageWell: NSImageView!
そして、この画像を保存するコード(ボタンアクション内に配置できます)は次のとおりです。
if imageWell.image != nil {
let bMImg = NSBitmapImageRep(data: (imageWell?.image?.TIFFRepresentation)!)
let dataToSave = bMImg?.representationUsingType(NSBitmapImageFileType.NSJPEGFileType, properties: [NSImageCompressionFactor : 1])
dataToSave?.writeToFile("/users/user/desktop/image.jpg", atomically: true)
}
指定されたコードの1行目で、Image Wellに画像があるかどうかを確認します。
2行目では、その画像のビットマップ表現を作成します。
3行目では、BitmapRepresentationを、圧縮係数を「1」に設定したJPGタイプに変換します(圧縮なし)。
4行目では、指定されたパスでJPGデータを保存します。 「atomically:true」は、ファイルが1つのピースとして保存され、操作が成功することを保証することを意味します。
N.B.: 3行目の別のNSBitmapImageFileTypeを使用して、画像を別の形式で保存できます。たくさんあります:
NSBitmapImageFileType.NSBMPFileType
NSBitmapImageFileType.NSGIFFileType
NSBitmapImageFileType.NSPNGFileType
等.