【问题标题】:NSImage to Base64 string loses qualityNSImage 到 Base64 字符串质量下降
【发布时间】:2017-03-02 14:15:41
【问题描述】:

我正在尝试将 NSImage 从 NSImageView 转换为 Base64 字符串,但在解码输出时最终会损失一半的质量。

转换为 Base64 的代码看起来很简单,我已将其放入 NSString 扩展中:

extension NSImage {

    func base64String() -> String? {
        guard
            let bits = self.representations.first as? NSBitmapImageRep,
            let data = bits.representation(using: .JPEG, properties: [:])
        else {
            return nil
        }

        return "data:image/jpeg;base64,\(data.base64EncodedString())"
    }
}

尝试使用 39KB 的测试 JPG 图像将其解码回 20KB。我尝试使用在线工具转换相同的图像并获得完美的编码->解码。

我尝试过的其他代码:

func base64String() -> String? {
    let cgImgRef = self.cgImage(forProposedRect: nil, context: nil, hints: nil)
    let bmpImgRef = NSBitmapImageRep(cgImage: cgImgRef!)
    let data = bmpImgRef.representation(using: NSBitmapImageFileType.JPEG, properties: [:])!
    return "data:image/jpeg;base64,\(data.base64EncodedString())"
}

这会产生一个 17KB 的文件。

任何帮助都将不胜感激,因为我已经为此绞尽脑汁好几个小时了。

【问题讨论】:

  • 如果可能的话,不要拿一些资产,转换成NSImage,然后再转换回来,抓住原始资产。要获取 JPEG,转换为 NSImage,然后再转换回 JPEG 会使资源变大或涉及质量损失(取决于您的设置)。使用PNG将忠实的压缩文件,但可能仍然比原始JPEG大。如果可能,请保留原始资产的 NSData/Data 并使用它(除非您要对其进行标记或以其他方式对其进行编辑)。
  • 感谢您的回复,但它有点棘手。该图像来自一个 Image Well(作为 NSImageView),因此除了可以从 NSImage 获得的内容之外,我没有对资产的原始访问权限。放入图像井中的图像然后作为 base64 字符串发送到 API。你知道我可以从 NSImageView 获取原始数据而不必将represent 它作为某种文件类型的方法吗?

标签: swift cocoa base64 nsimage


【解决方案1】:

您没有指定压缩值,所以它默认为默认压缩。没有压缩使用下面的代码:

let data = bits.representation(using: .JPEG, properties: [NSImageCompressionFactor:1.0])

【讨论】:

  • 现在好像走反了——从 39 到 51KB。有没有办法使用原版?
  • 这可能是比原始 JPEG 大得多的资产。不,你不能得到“原件”。您应该在首次加载时保存原始资产,而不是尝试从 NSImage 重建它。
  • 我遇到的问题是它正在使用一个 API,它将它作为其他数据中的一个字符串。理想情况下想做多部分表单,但不幸的是我无法控制后端
【解决方案2】:

根据documentationNSBitmapImageRep 渲染图像。您的代码似乎再次将图像重新编码为 jpeg。由于 jpeg 是一种松散的算法,这将导致质量损失。您可以尝试:

  • 使用png作为表示
  • jpeg 使用高(或 1.0)压缩系数。

【讨论】:

  • 是的,PNG 是不错的无损压缩。 JPEG @ 1.0 可以生成非常大的资源。
  • 也尝试了 PNG,但文件大小为 3 倍。图像将是头像和生成的缩略图,这会导致加载时间变慢
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-01-22
  • 1970-01-01
相关资源
最近更新 更多