【问题标题】:How do I mirror a JPEG file in macOS如何在 macOS 中镜像 JPEG 文件
【发布时间】:2019-04-01 09:30:10
【问题描述】:

如何镜像 jpeg 文件、swift、macOS?

使用像 CGImageSourceCreateWithURL 这样的东西会很好。我想更改一个属性,然后再次写出文件。不确定这是否可能。

另一种方法似乎是绘制图像,然后将其写入文件。图像需要使用 -1 比例缩放并转换,以便它仍然正确显示在目标中。我一直找不到这样做的快速示例。这是一个不快速的例子。我无法迅速复制它。同样使用 NSImage 需要解码然后编码 JPEG 文件。不这样做的解决方案会更好。 Flip NSImage on both axes

编辑: vImage 可能是一个中间立场。这将需要通过读取 JPEG 来填充,但可以翻转数据而无需以 -1 的比例“绘制”它。我认为可以使用 initWithContentsOfURL 或 initByReferencingURL 制作 NSImage,使用 CGImageForProposedRect 从 NSImage 制作 CGImage。由CGImage制作的vImage?

【问题讨论】:

  • @Rob 你知道我如何在 MacOS 上从 JPEG 文件中获取 vImage 吗? iOS 示例使用 UIImage,但我认为这在 macOS 上不可用。我想大概是可以做到的。它只是知道从 URL 或路径到 vImage 的链。 (然后我必须再次将其写入 JPEG 文件。)

标签: swift macos jpeg


【解决方案1】:

要使用vImage mirroring routines 镜像NSImage,您可以执行以下操作:

extension NSImage {
    func mirrored() -> NSImage? {
        guard
            let cgImage = cgImage(forProposedRect: nil, context: nil, hints: nil),
            let colorSpace = cgImage.colorSpace else {
                return nil
        }

        var format = vImage_CGImageFormat(bitsPerComponent: UInt32(cgImage.bitsPerComponent),
                                          bitsPerPixel: UInt32(cgImage.bitsPerPixel),
                                          colorSpace: Unmanaged.passRetained(colorSpace),
                                          bitmapInfo: cgImage.bitmapInfo,
                                          version: 0,
                                          decode: nil,
                                          renderingIntent: cgImage.renderingIntent)

        var source = vImage_Buffer()
        var result = vImageBuffer_InitWithCGImage(
            &source,
            &format,
            nil,
            cgImage,
            vImage_Flags(kvImageNoFlags))

        guard result == kvImageNoError else { return nil }

        defer { free(source.data) }

        var destination = vImage_Buffer()
        result = vImageBuffer_Init(
            &destination,
            vImagePixelCount(cgImage.height),
            vImagePixelCount(cgImage.width),
            UInt32(cgImage.bitsPerPixel),
            vImage_Flags(kvImageNoFlags))

        guard result == kvImageNoError else { return nil }

        result = vImageHorizontalReflect_ARGB8888(&source, &destination, vImage_Flags(kvImageNoFlags))
        guard result == kvImageNoError else { return nil }

        defer { free(destination.data) }

        return vImageCreateCGImageFromBuffer(&destination, &format, nil, nil, vImage_Flags(kvImageNoFlags), nil).map {
            NSImage(cgImage: $0.takeRetainedValue(), size: size)
        }
    }

}

因此,在我的编辑器中对以上内容进行屏幕快照,然后我mirrored 图像,结果:

【讨论】:

  • 这看起来很棒。我曾希望直接操纵 JPEG 表示。这种方法是在操作解压后的数据,但直接操作。这感觉比使用 NSAffineTransform 方法要好。
  • 是的,我不知道任何 JPEG 直接方法。虽然我没有对基于变换的方法进行基准测试,但我的经验是 vImage 操作通常会快得多。
  • 这基本上有效。但是,我得到了一些经过重新采样并且看起来像拇指指甲的图像。我认为可能会发生两件事之一。我可能是从图像文件中获取缩略图,或者分辨率很高,但正在以较低的分辨率生成。
  • 添加:self.representations[0].size.width = CGFloat(self.representations[0].pixelsWide) self.representations[0].size.height = CGFloat(self.representations[0 ].pixelsHigh) 到顶部。效果很好!
猜你喜欢
  • 2011-01-19
  • 1970-01-01
  • 1970-01-01
  • 2010-11-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-06-30
  • 2022-07-04
相关资源
最近更新 更多