2009-06-01 8 views
6

Potrzebuję utworzyć łańcuchową reprezentację base64 obiektu kakaowego NSImage. Jaki jest najlepszy sposób, aby to zrobić, dokumentacja Apple wydaje się być trochę krótka na ten temat (lub po prostu nie mogę go znaleźć). Kodowanie Base64 wydaje się dość skomplikowane z zewnątrz.NSImage to Base64

Każda pomoc będzie bardzo ceniona.

Cheers Alex

EDIT

NSArray *keys = [NSArray arrayWithObject:@"NSImageCompressionFactor"]; 
NSArray *objects = [NSArray arrayWithObject:@"1.0"]; 
NSDictionary *dictionary = [NSDictionary dictionaryWithObjects:objects forKeys:keys]; 

NSImage *image = [[NSImage alloc] initWithContentsOfFile:[imageField stringValue]]; 
NSBitmapImageRep *imageRep = [[NSBitmapImageRep alloc] initWithData:[image TIFFRepresentation]]; 
NSData *tiff_data = [imageRep representationUsingType:NSPNGFileType properties:dictionary]; 

NSString *base64 = [tiff_data encodeBase64WithNewlines:NO]; 

Odpowiedz

4

NSImage jest bardzo abstrakcyjnym obiektem. NSImage nie przejmuje się tym, czy jest to obraz rastrowy czy wektorowy; obiekt NSImage może mieć nawet rastrowe, wektorowe, i nawet programowalne reprezentacje wszystkie naraz - to ten ogólny.

Zanim będzie można wygenerować dane Base64, należy zdecydować, , które kodowanie ma zostać zmienione na.

Pierwszym krokiem jest podjęcie decyzji, czy kodować rastry czy wektory. Ta pierwsza jest dość łatwa i domyślam się, że to właśnie masz na myśli. Jednak NSImage mógł pochodzić ze źródła wektorowego, takiego jak dokument PDF.

Jeśli wiesz, że obraz został utworzony ze źródła rastrowego, możesz po prostu zakodować te dane źródłowe.

Jeśli pochodzi ze źródła wektorowego, możesz je kodować, jeśli wiesz, że aplikacja po stronie dekodującej będzie w stanie obsłużyć to (np. Jeśli jest to inna aplikacja Cocoa Touch lub Cocoa Touch). Z drugiej strony, jeśli aplikacja na końcu dekodującym może nie być w stanie obsłużyć danych wektorowych, powinieneś unikać tej taktyki.

Jedno rozwiązanie działające we wszystkich przypadkach: to użycie NSBitmapImageRep do create a raster capture obrazu. Zablokuj fokus na obrazie, a następnie utwórz NSBitmapImageRep, używając tej metody, a następnie odblokuj ostrość. Następnie użyj representationUsingType:properties: do wygenerowania danych PNG (lub innego formatu) dla obrazu. Następnie zakodowane w Base64 dane PNG (lub innego formatu).

+0

zgaduję, że Alex nie chce base64 kodowania obrazu dla własnych celów, ale aby spełnić warunki umowy z jakimś odbiorcą, np usługa internetowa. W tym przypadku będzie musiał baz64 dokładnie to, czego oczekuje serwis internetowy (prawdopodobnie dane JPG lub PNG). Wątpię, czy istnieje duża potrzeba spekulacji na temat różnych sposobów kodowania obrazu, ale być może Alex potwierdzi jedno lub drugie. – danielpunkass

+0

Hej, chłopaki, myślę, że kodowanie base64 działa poprawnie, używając kodu z dribin.org, ale podczas gdy wordpress akceptuje i tworzy plik, nie jest obrazem. http://alexmillsdesign.files.wordpress.com/2009/06/quickicon5.jpg Uważam, że nie otrzymuję właściwych danych z obiektu NSImage, więc zmieniono mój kod, który jest w edycji mojego pierwotnego pytania. Jestem nowy w programowaniu obrazów, gdzie się mylę? –

+0

1. Użyj nazwanych stałych (NSImageCompressionFactor, a nie @ "NSImageCompressionFactor"). 2. Użyj instancji NSNumber, a nie łańcucha zawierającego reprezentację dziesiętną. 3. Nie to ma znaczenia, ponieważ PNG i tak nie obsługuje NSImageCompressionFactor. 4. Tworzysz i ładujesz dane PNG, a nie JPEG. Użyj rozszerzenia .png jako rozszerzenia nazwy pliku lub utwórz i prześlij dane JPEG, a nie PNG. 5. Jeśli to pobierzesz, przekonasz się, że to dane base64. Może faktycznie nie musisz go kodować64? –

2

Apple nie zapewnia żadnej konkretnej pomocy tutaj, więc masz do walki złożoności na własną rękę, taki czy inny sposób.

Na szczęście istnieje kilka zasobów, które ułatwiają to zadanie. Pierwszym podejściem jest dosłowne samodzielne kodowanie i dekodowanie. Google Toolbox for Mac jest dobrym przykładem tego podejścia i może być w stanie po prostu użyć tego pliku źródłowego jak jest:

http://code.google.com/p/google-toolbox-for-mac/source/browse/trunk/Foundation/GTMBase64.m

Jeśli budujesz tylko dla Mac, gdzie są biblioteki OpenSSH dostępne, to można skorzystać z niektórych funkcji w tych bibliotekach zrobić kodowanie i dekodowanie:

http://www.dribin.org/dave/blog/archives/2006/03/12/base64_cocoa/

2

mam kilka kodu, włączając Base64 parsowania opiera się na realizacji w OmniFoundation w my toolkit on github . W szczególności spójrz na Extensions/NSData + Base64.h.

1

Oto Swift 2 rozszerzenie do konwersji NSImage na ciąg base64:

private extension NSImage { 
    var base64String:String? { 
    guard let rep = NSBitmapImageRep(
     bitmapDataPlanes: nil, 
     pixelsWide: Int(size.width), 
     pixelsHigh: Int(size.height), 
     bitsPerSample: 8, 
     samplesPerPixel: 4, 
     hasAlpha: true, 
     isPlanar: false, 
     colorSpaceName: NSDeviceRGBColorSpace, 
     bytesPerRow: 0, 
     bitsPerPixel: 0 
     ) else { 
      print("Couldn't create bitmap representation") 
      return nil 
    } 

    NSGraphicsContext.saveGraphicsState() 
    NSGraphicsContext.setCurrentContext(NSGraphicsContext(bitmapImageRep: rep)) 
    drawAtPoint(NSZeroPoint, fromRect: NSZeroRect, operation: .CompositeSourceOver, fraction: 1.0) 
    NSGraphicsContext.restoreGraphicsState() 

    guard let data = rep.representationUsingType(NSBitmapImageFileType.NSPNGFileType, properties: [NSImageCompressionFactor: 1.0]) else { 
     print("Couldn't create PNG") 
     return nil 
    } 
    return data.base64EncodedStringWithOptions([]) 
} 
} 
1

Swift 3

extension NSImage { 
    var base64String:String? { 
     guard let rep = NSBitmapImageRep(
      bitmapDataPlanes: nil, 
      pixelsWide: Int(size.width), 
      pixelsHigh: Int(size.height), 
      bitsPerSample: 8, 
      samplesPerPixel: 4, 
      hasAlpha: true, 
      isPlanar: false, 
      colorSpaceName: NSDeviceRGBColorSpace, 
      bytesPerRow: 0, 
      bitsPerPixel: 0 
      ) else { 
       print("Couldn't create bitmap representation") 
       return nil 
     } 

     NSGraphicsContext.saveGraphicsState() 
     NSGraphicsContext.setCurrent(NSGraphicsContext(bitmapImageRep: rep)) 
     draw(at: NSZeroPoint, from: NSZeroRect, operation: .sourceOver, fraction: 1.0) 
     NSGraphicsContext.restoreGraphicsState() 

     guard let data = rep.representation(using: NSBitmapImageFileType.PNG, properties: [NSImageCompressionFactor: 1.0]) else { 
      print("Couldn't create PNG") 
      return nil 
     } 

     return data.base64EncodedString(options: []) 
    } 
}