NSImage转换为Base64

7
我需要创建一个NSImage cocoa对象的base64字符串表示。如何处理这个问题,苹果的文档似乎有点简略(或者我找不到)。从外部来看,Base64编码似乎相当复杂。
非常感谢任何帮助。
干杯 Alex
编辑
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];
6个回答

4

NSImage是一个非常抽象的对象。NSImage并不关心它是栅格图像还是矢量图像;一个NSImage对象甚至可以同时具有栅格、矢量和编程表示,这就是它的普遍性。

在生成Base64数据之前,您必须决定要编码什么。

第一步是决定您想要编码栅格还是矢量图像。前者相当容易,我想这可能是您想要的。然而,NSImage可能来自矢量源,例如PDF文档。

如果您知道您从栅格源创建了图像,则可以只编码该源数据。

如果它来自矢量源,则仍然可以只编码它,如果您知道解码端的应用程序将能够处理它(例如,如果它是另一个Cocoa或Cocoa Touch应用程序)。另一方面,如果解码端的应用程序可能无法处理矢量数据,则应避免使用此策略。

适用于所有情况的唯一解决方案是使用NSBitmapImageRep创建图像的栅格捕获。在图像上锁定焦点,然后使用该方法创建一个NSBitmapImageRep,然后解锁焦点。然后,使用representationUsingType:properties:生成PNG(或适当格式)数据的图像。然后对PNG(或其他格式)数据进行Base64编码。


我猜想Alex并不是为了自己的目的而要对图像进行base64编码,而是为了满足某个接收方的合同,比如一个Web服务。既然如此,他需要根据Web服务所期望的方式(可能是JPG或PNG数据)来进行base64编码。我怀疑没有必要对图像编码的各种方式进行推测,但也许Alex会确认其中一种方式。 - danielpunkass
嘿大家,我认为我使用dribin.org的代码已经正确地实现了base64编码,但是尽管WordPress接受并创建了该文件,它不是一个图像。http://alexmillsdesign.files.wordpress.com/2009/06/quickicon5.jpg 我相信我没有从NSImage对象中获取正确的数据,所以我更改了我的代码,它在原始问题的编辑中。我对图像编程还很陌生,我哪里错了? - Alex Mills
  1. 使用命名常量(NSImageCompressionFactor,而不是@“NSImageCompressionFactor”)。
  2. 使用NSNumber实例,而不是包含十进制表示的字符串。
  3. PNG不支持NSImageCompressionFactor,所以并不重要。
  4. 您正在创建和上传PNG数据,而不是JPEG。要么将文件扩展名用.png,要么创建和上传JPEG数据,而不是PNG。
  5. 如果您下载它,您会发现它是base64数据。也许您实际上不需要对其进行base64编码?
- Peter Hosey
2
你把变量命名为“tiff_data”,但是你却放了PNG数据进去。诚实地命名你的变量,当你几个月或几年后回来阅读这段代码时,它会保持你的理智。 - Peter Hosey
他可能正在使用WordPress的XMLRPC接口上传文件。由于它是基于文本的XML格式,这就解释了为什么他需要base64编码。 - danielpunkass
1
danielpunkass:这并不能解释为什么文件内容是base-64编码的,除非他对其进行了两次base64编码。 - Peter Hosey

3

Swift 4

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: .calibratedRGB,
            bytesPerRow: 0,
            bitsPerPixel: 0
            ) else {
                print("Couldn't create bitmap representation")
                return nil
        }
        
        NSGraphicsContext.saveGraphicsState()
        NSGraphicsContext.current = NSGraphicsContext(bitmapImageRep: rep)
        draw(at: NSZeroPoint, from: NSZeroRect, operation: .sourceOver, fraction: 1.0)
        NSGraphicsContext.restoreGraphicsState()
        
        guard let data = rep.representation(using: NSBitmapImageRep.FileType.png, properties: [NSBitmapImageRep.PropertyKey.compressionFactor: 1.0]) else {
            print("Couldn't create PNG")
            return nil
        }
        
        // With prefix
        // return "data:image/png;base64,\(data.base64EncodedString(options: []))" 
        // Without prefix
        return data.base64EncodedString(options: [])
    }
}

2

苹果公司在此方面没有提供任何特殊帮助,所以您必须自己解决复杂性。幸运的是,有一些资源可用于使这更容易。第一种方法是直接自己进行编码和解码。Google 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
我有一堆代码,其中包括基于OmniFoundation实现的Base64解析,在我的GitHub工具包中。特别是要看Extensions/NSData+Base64.h。

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: [])
    }
}

1
这是一个将NSImage转换为base64字符串的Swift 2扩展程序:
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([])
}
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接