2009-06-01 2 views
6

Мне нужно создать строковое представление base64 объекта какао NSImage. Каков наилучший способ справиться с этим, документация на Apple, по-видимому, немного коротка по этому вопросу (или я просто не могу ее найти). Кодировка Base64 кажется довольно сложной извне.NSImage to Base64

Любая помощь будет очень оценена.

Приветствия 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]; 

ответ

4

NSImage - очень абстрактный объект. NSImage все равно, является ли это растровым изображением или векторным изображением; объект NSImage может даже иметь растровые, векторные, и даже программные представления сразу - это общий.

Прежде чем вы сможете генерировать данные Base64, вы должны решить, , что вы хотите кодировать.

Первый шаг - решить, хотите ли вы кодировать растр или векторы. Первое довольно легко, и я думаю, это, вероятно, то, что вы имели в виду. Тем не менее, NSImage мог возникнуть из векторного источника, такого как документ PDF.

Если вы знаете, что создали изображение из растрового источника, вы можете просто закодировать исходные данные.

Если он исходит от источника вектора, вы все равно можете просто закодировать его, если знаете, что приложение на конце декодирования сможет обрабатывать его (например, если это другое приложение Cocoa или Cocoa Touch). С другой стороны, если приложение на конце декодирования может не справиться с векторными данными, вам следует избегать этой тактики.

Единственное решение, которое работает во всех случаях является использование NSBitmapImageRep для create a raster capture изображения. Заблокируйте фокус на изображении, затем создайте NSBitmapImageRep, используя этот метод, затем откройте фокус. Затем используйте representationUsingType:properties: для генерации PNG (или любого другого формата) данных для изображения. Затем Base64-кодирует данные PNG (или любого другого формата).

+0

Я предполагаю, что Алекс не хочет base64 кодирования изображения для его собственных целей, но для удовлетворения контракта какого-либо получателя, например веб-службы. В этом случае он должен будет использовать base64 именно то, что ожидает веб-сервис (возможно, данные JPG или PNG). Я сомневаюсь, что существует много предположений о различных способах кодирования изображения, но, возможно, Алекс подтвердит то или другое. – danielpunkass

+0

Эй, ребята, я думаю, что кодировка base64 работает правильно, используя код от dribin.org, но в то время как Wordpress принимает и создает файл, а не образ. http://alexmillsdesign.files.wordpress.com/2009/06/quickicon5.jpg Я считаю, что я не получаю нужные данные от объекта NSImage, поэтому я изменил свой код, который находится в редакции моего исходного вопроса. Я новичок в программировании изображений, где я ошибаюсь? –

+0

1. Используйте именованные константы (NSImageCompressionFactor, а не @ "NSImageCompressionFactor"). 2. Используйте экземпляр NSNumber, а не строку, содержащую десятичное представление. 3. Не важно, потому что PNG не поддерживает NSImageCompressionFactor. 4. Вы создаете и загружаете PNG-данные, а не JPEG. Либо используйте .png как расширение имени файла, либо создайте и загрузите данные JPEG, а не PNG. 5. Если вы загрузите это, вы обнаружите, что это данные base64. Может быть, вам действительно не нужно кодировать base64? –

2

компании Apple не предоставляет какой-либо конкретной помощи здесь, так что вам придется решать сложности на собственном, так или иначе.

К счастью, есть несколько доступных ресурсов, чтобы сделать это проще. Первый подход - буквально сделать кодирование и декодирование. Google Toolbox для Mac имеет хороший пример такого подхода, и вы могли бы просто использовать этот исходный файл как есть:

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

Если вы строите только для Mac, где библиотеки OpenSSH являются в наличии, то вы можете воспользоваться некоторыми функциями в этих библиотеках, чтобы сделать кодирование и декодирование:

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

2

Я получил кучу кода, включая Base64 разбор на основе внедрения в OmniFoundation, в my toolkit on github , В частности, посмотрите Extensions/NSData + Base64.h.

1

Вот Swift 2 расширение для преобразования NSImage в 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: []) 
    } 
}