Frage

Wie kann ich spare eine NSImage als neue Datei (png, jpg, ...) in einem bestimmten Verzeichnis?

War es hilfreich?

Lösung

Do etwas wie folgt aus:

NSBitmapImageRep *imgRep = [[image representations] objectAtIndex: 0];
NSData *data = [imgRep representationUsingType: NSPNGFileType properties: nil];
[data writeToFile: @"/path/to/file.png" atomically: NO];

Andere Tipps

Sie können eine Kategorie NSImage wie diese

hinzufügen
@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

Der Aufruf von „TIFFRepresentation“ ist wichtig, sonst können Sie nicht ein gültiges Bild erhalten.

Nicht sicher den Rest von euch, aber ich ziehe meine volle Enchilada Essen. Was ist oben funktionieren wird und nichts beschrieben ist falsch, aber ich fand ein paar Dinge außen vor. Hier werde ich meine Beobachtungen hervorheben:

  • Erste die beste Darstellung vorgesehen, die scheinen 72 DPI zu sein selbst wenn die Bildauflösung als die größer ist. So verlieren Sie Auflösung
  • Zweite, was über mehrseitige Bilder, wie sie in animierte GIFs oder PDFs. Gehen Sie voran, versuchen Sie ein animiertes GIF, ist die Animation verloren
  • Schließlich jede Metadaten wie EXIF, GPS, etc ... werden Daten verloren.

Also, wenn Sie das Bild konvertieren möchten, tun Sie wirklich auf all das verlieren wollen? Wenn Sie Ihre volle Mahlzeit zu essen, lässt dann lesen Sie weiter ...

Manchmal und ich meine manchmal gibt es nichts Besseres als gute alte alte Schulentwicklung. Ja, das Mittel müssen wir ein bisschen Arbeit tun!

Lassen Sie uns den Einstieg:

ich eine Kategorie in NSData erstellen. Dies sind Klassenmethoden, weil Sie diese Dinge wollen Thread-sicher sein, und es ist nichts sicherer als Ihre Sachen auf dem Stack setzen. Es gibt zwei Arten von Methoden, eine für die Ausgabe von nicht-mehrseitige Bildern und einem für die Ausgabe von mehrseitigen Bildern.

Liste der Einzelbilder: JPG, PNG, BMP, JPEG-2000

Liste mehrerer Bilder: PDF, GIF, TIFF

Zuerst einen veränderbaren Datenraum im Speicher erstellen.

NSMutableData * imageData    = [NSMutableData data];

Zweite eine CGImageSourceRef erhalten. Ja klingt hässlich ist schon nicht. Es ist nicht so schlimm, wir halten zu gehen ... Sie wollen wirklich das Quellbild nicht eine Darstellung oder NSImage Datenblock. Allerdings haben wir ein kleines Problem. Die Quelle möglicherweise nicht kompatibel sein, so stellen Sie sicher, dass Sie Ihre UTI gegen die von CGImageSourceCopyTypeIdentifiers aufgeführt überprüfen ()

Einige Code:

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 );

Warten Sie eine Sekunde, warum ist NSImage da? Nun gibt es einige Formate, die keine Metadaten und CGImageSource nicht unterstützt, aber diese sind gültig Bilder. Ein Beispiel ist im alten Stil PICT-Bilder.

Jetzt haben wir eine CGImageSourceRef, stellen Sie sicher, es ist nicht null, und dann lassen Sie uns nun einen CGImageDestinationRef bekommen. Wow all diese ref ist im Auge zu behalten. Bisher sind wir bei 2!

Wir werden diese Funktion verwenden: CGImageDestinationCreateWithData ()

  • 1. Param ist Ihre imagedata (cast CFMutableDataRef)
  • 2. Param ist Ihr Ausgang UTI, erinnert die Liste oben. (z.B. kUTTypePNG)
  • 3. Param ist die Anzahl der Bilder zu speichern. Für einzelne Bilddateien dieser 1 sonst können Sie einfach die folgende verwenden:

    CGImageSourceGetCount (image);

  • 4. Param ist gleich Null.

Überprüfen Sie, ob Sie diese CGImageDestinationRef haben und jetzt wollen wir unsere Bilder von der Quelle in sie fügen ... das wird auch jede / alle Metadaten und die Auflösung beibehalten.

Für mehrere Bilder, die wir Schleife:

for ( NSUInteger i = 0; i < count; ++i )
                CGImageDestinationAddImageFromSource( imageDest, imageSource, i, nil );

Für einzelnes Bild ist es eine Zeile Code bei Index 0:

CGImageDestinationAddImageFromSource( imageDest, imageSource, 0, nil);

Ok, finalisieren es, die auf der Festplatte oder Datencontainer schreibt:

CGImageDestinationFinalize( imageDest );

Damit Veränderliche Daten von Anfang an haben alle unsere Bilddaten und Metadaten in ihm jetzt.

Sind wir endlich fertig? Fast, auch mit Garbage Collection müssen Sie reinigen-up! Denken Sie daran, zwei Ref ist eine für die Quelle und eine für das Ziel so tun ein CFRelease ()

Jetzt sind wir fertig und was Sie am Ende mit einem umgebauten Bild ist, alle seine Metadaten beibehalten, Auflösung, etc ...

Meine NSData Kategorie Methoden wie folgt aussehen:

+ (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;

Was ist Ändern der Größe oder ICO / ICNS? Dies ist für einen anderen Tag, aber zusammenfassend Sie zuerst angehen Ändern der Größe ...

  1. Erstellen Sie einen Zusammenhang mit neuer Größe: CGBitmapContextCreate ()
  2. Holen Sie sich das ein Bild ref aus dem Index: CGImageSourceCreateImageAtIndex ()
  3. Holen Sie sich eine Kopie der Metadaten: CGImageSourceCopyPropertiesAtIndex ()
  4. Zeichnen Sie das Bild in den Kontext: CGContextDrawImage ()
  5. Holen Sie sich das skalierte Bild aus dem Kontext: CGBitmapContextCreateImage ()
  6. Geben Sie nun das Bild hinzuzufügen und Metadaten an den Dest Ref: CGImageDestinationAddImage ()

Spülen und wiederholen Sie für Multiple-Bilder in der Quelle eingebettet ist.

Der einzige Unterschied zwischen einer ICO und ICNS ist, dass man ein einzelne Bild, während die andere mit mehreren Bildern in einer Datei. Ich wette, Sie können erraten, was was ist ?! ;-) Für diese Formate müssen Sie in einer bestimmten Größe die Größe nach unten sonst ERROR erfolgen wird. Das Verfahren ist jedoch genau das gleiche, wo Sie die richtige UTI verwenden, aber die Größenänderung ist ein bisschen strenge.

Ok hoffe, das hilft anderen da draußen, und Sie sind so voll wie ich jetzt bin!

Upps, vergessen zu erwähnen. Wenn Sie das NSData Objekt erhalten tun, wie Sie wollen mit ihm wie writeToFile, writeToURL oder erstellen Heck eine andere NSImage, wenn Sie wollen.

Happy Codierung!

Speichern als PNG mit swift3

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 Lösung

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)")
        }
    }
}

Swift Stil:

if let imgRep = image?.representations[0] as? NSBitmapImageRep
{
      if let data = imgRep.representationUsingType(NSBitmapImageFileType.NSPNGFileType, properties: [:])
      {
           data.writeToFile("/path/to/file.png", atomically: false)
      }
}

Nur noch eine garantierte Arbeit Ansatz SWIFT:

Ich habe ein „Bild Well“ wo man Benutzer jedes Bild fallen kann. Und das „Bild Well“ hat eine Bildeigenschaft (vom Typ NSImage) über den Auslass zugegriffen:

@IBOutlet weak var imageWell: NSImageView!

Und der Code, der das Bild speichert (Sie es im Inneren der Button-Aktion setzen kann) ist:

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)
}

In der ersten Zeile des gegebenen Code überprüfen wir, ob unser Bild Nun ein Bild hat.

In der 2. Zeile machen wir eine Bitmap-Darstellung des Bildes.

In der 3. Zeile setzen wir unsere BitmapRepresentation zu einem JPG-Typ mit einem Kompressionsfaktor auf „1“ (keine Komprimierung).

In der 4. Zeile wir speichern die JPG-Daten mit einem bestimmten Pfad. . „Atomar: true“ bedeutet, dass die Datei als ein Stück gespeichert wird und dass uns versichert, dass die Operation erfolgreich sein wird,

N. B:. Sie können eine andere NSBitmapImageFileType in der 3. Zeile verwenden können, Ihr Bild in ein anderes Format zu speichern. Es hat viel:

NSBitmapImageFileType.NSBMPFileType
NSBitmapImageFileType.NSGIFFileType
NSBitmapImageFileType.NSPNGFileType

etc.

Um Hilfe bei der Cross-Plattform-Code implementiert ich eine Version ofUIImagePNGRepresentation(), dass läuft auf Mac (und Verwendungen NSImage).

#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

Verbrauch:

if let data = UIImagePNGRepresentation(myImage) {
    do { try data.write(to: url, options: [.atomic]) }
    catch let error { print("Error writing image (\(error))") }
}
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top