- Java 双重比较
- java - 比较器与 Apache BeanComparator
- Objective-C 完成 block 导致额外的方法调用?
- database - RESTful URI 是否应该公开数据库主键?
我有以下代码从 UIImage
获取像素数据,这适用于大多数图像,但是当我使用 UIGraphicsImageRenderer
创建图像时不起作用。我希望有人知道解决这个问题的方法。
我当前的代码生成一个简单的图像,但随后访问数据会产生意想不到的结果。
func myDraw() {
let renderer = UIGraphicsImageRenderer(size: CGSize(width: 200, height: 200))
let image = renderer.image { context in
context.cgContext.setFillColor(UIColor.black.cgColor)
context.cgContext.addRect(CGRect(x: 0, y: 0, width: 100, height: 100))
context.cgContext.fillPath()
context.cgContext.setFillColor(UIColor.red.cgColor)
context.cgContext.addRect(CGRect(x: 100, y: 100, width: 100, height: 100))
context.cgContext.fillPath()
}
let providerData = image.cgImage!.dataProvider!.data
let data = CFDataGetBytePtr(providerData)!
var pixels = [PixelData]()
for i in stride(from: 0, to: 160000-1, by: 4) {
pixels.append(PixelData(a:data[i+3], r:data[i+0], g:data[i+1], b:data[i+2]))
}
self.canvas.image = self.imageFromARGB32Bitmap(pixels: pixels, width: 200, height: 200)
}
我已使用以下代码生成图像以查看其是否正常工作。
func imageFromARGB32Bitmap(pixels: [PixelData], width: Int, height: Int) -> UIImage? {
guard width > 0 && height > 0 else { return nil }
guard pixels.count == width * height else { return nil }
let rgbColorSpace = CGColorSpaceCreateDeviceRGB()
let bitmapInfo = CGBitmapInfo(rawValue: CGImageAlphaInfo.premultipliedFirst.rawValue)
let bitsPerComponent = 8
let bitsPerPixel = 32
var data = pixels // Copy to mutable []
guard let providerRef = CGDataProvider(data: NSData(bytes: &data,
length: data.count * MemoryLayout<PixelData>.size)
)
else { return nil }
guard let cgim = CGImage(
width: width,
height: height,
bitsPerComponent: bitsPerComponent,
bitsPerPixel: bitsPerPixel,
bytesPerRow: width * MemoryLayout<PixelData>.size,
space: rgbColorSpace,
bitmapInfo: bitmapInfo,
provider: providerRef,
decode: nil,
shouldInterpolate: true,
intent: .defaultIntent
)
else { return nil }
return UIImage(cgImage: cgim)
}
最佳答案
一些观察:
您的代码假定 UIGraphicsImageRenderer
生成比例为 1 的图像,而默认为 0(即您的设备使用的任何比例)。
相反,强制比例为 1:
let format = UIGraphicsImageRendererFormat()
format.scale = 1
let renderer = UIGraphicsImageRenderer(size: CGSize(width: 200, height: 200), format: format)
这不是这里的问题,但我们必须注意,您的代码只是假定 UIGraphicsImageRendererFormat
的格式将是特定的字节顺序和格式,您的 imageFromARGB32Bitmap
也是如此.如果你看看 Apple Technical Note 1509 (您的代码无疑最初是从中改编的),他们不只是假设缓冲区将采用特定格式。当我们想要操作/检查缓冲区时,我们应该 (a) 创建所需格式的上下文,(b) 将我们的图像(或其他)绘制到该上下文,只有这样我们才能可靠地查看提供者数据。
imageFromARGB32Bitmap
有效,但这让我有点紧张。
使用MemoryLayout<PixelData>.size
: Apple advises :
When allocating memory for multiple instances of T using an unsafe pointer, use a multiple of the type’s
stride
instead of itssize
.
所以,我会使用 stride
.
如果 stride
会怎样4 不是像您期望的那样吗?我无法想象它永远不会是 4,但数据提供者假设它们将被打包。这是一个次要的观察,但我可能会将这个假设明确化。
我们是否 100% 确信取消引用 &data
会给我们一个连续的缓冲区?我倾向于 withContiguousStorageIfAvailable
只是为了安全。
例如:
func imageFromARGB32Bitmap(pixels: [PixelData], width: Int, height: Int) -> UIImage? {
guard width > 0,
height > 0,
pixels.count == width * height else { return nil }
let rgbColorSpace = CGColorSpaceCreateDeviceRGB()
let bitmapInfo = CGBitmapInfo(rawValue: CGImageAlphaInfo.premultipliedFirst.rawValue)
let bitsPerComponent = 8
let bitsPerPixel = 32
let stride = MemoryLayout<PixelData>.stride
assert(stride == 4)
return pixels.withContiguousStorageIfAvailable { bufferPointer -> UIImage? in
let data = Data(buffer: bufferPointer)
return CGDataProvider(data: data as CFData)
.flatMap { CGImage(width: width,
height: height,
bitsPerComponent: bitsPerComponent,
bitsPerPixel: bitsPerPixel,
bytesPerRow: width * stride,
space: rgbColorSpace,
bitmapInfo: bitmapInfo,
provider: $0,
decode: nil,
shouldInterpolate: true,
intent: .defaultIntent) }
.flatMap { UIImage(cgImage: $0) }
} ?? nil
}
关于swift - 检索像素数据不能正确使用 UIGraphicsImageRenderer 图像,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54970212/
private func scale(image ciImage: CIImage?, for scale: CGFloat) -> UIImage { guard let ciImage =
问题 : 在我截取屏幕截图后,通过缩放检查时图像模糊。放大时图像内的文字似乎模糊不清。 我知道这个问题已经被提出很多次了,但他们都没有想要的解决方案。我已经检查了很多帖子,例如 this one 迄今
我想给照片加一个白色边框,同时保持照片的质量,所以我用UIGraphicsImageRenderer画了一个白色的背景,然后把照片画上去,结果是内存占用急剧增加,有没有更好的道路? 原图分辨率为403
使用我们的设备相机拍摄的图像比 iOS 设备上的屏幕大。通常,当我们在 iOS 中渲染图像时,我看到人们将渲染大小设置为主视图或 ImageView 的大小。 如this stack overflow
我有以下代码从 UIImage 获取像素数据,这适用于大多数图像,但是当我使用 UIGraphicsImageRenderer 创建图像时不起作用。我希望有人知道解决这个问题的方法。 我当前的代码生成
UIGraphicsImageRenderer是在 iOS 10 中新引入的。我想知道是否有可能用它旋转 UIImage(任何自定义角度)。我知道有 classic way使用 CGContextRo
默认情况下,UIGraphicsImageRenderer 将比例设置为设备的屏幕比例,在 iPhone 6s 上是 2x,在 iPhone 6s Plus 上是 3x,因此即使你给它一个尺寸为 30
我很喜欢使用来自 UIGraphicsImageRenderer 的新 API自 iOS 10 以来引入,但现在我想知道是否有可能获得灰度 Data来自其 pngData方法。 假设我有一个名为“ma
我正在尝试截取 SCNView 的屏幕截图以在其他地方显示。由于SCNView继承自UIView,我想我可以use a UIGraphicsImageRenderer : extension UIVi
我目前正在使用这种非常流行的方法来捕获 View ,以便用户分享它或将它保存到他的照片库中: let renderer = UIGraphicsImageRenderer(size: CGSize(w
UIGraphicsImageRenderer 是 iOS 10 创建图像上下文并绘制到其中的新方法。我正在尝试使用 UIGraphicsImageRenderer 绘制一个简单的图像: let si
我想在裁剪时对图像应用羽化效果,但我想使用 UIGraphicsImageRenderer 渲染图像渲染为零(iOS 9.3)是否有任何其他选项可以在 iOS 9.3 中渲染图像 这是我的代码: UI
我正在努力在 iOS 10 中添加对宽幅彩色照片的支持。当用户从相机拍摄照片时,我需要使用支持新色彩空间的新 API 来保存照片数据 - UIGraphicsImageRenderer 的 jpegD
当我尝试在 watchOS 应用程序中使用 UIGraphicsImageRenderer 时,编译器抛出错误。 entry in the documentation看起来它只适用于 iOS 和 tv
我有一个自定义的 UIView 类,它使用 UIGraphicsImageRenderer 绘制一些线条,我有一些 slider 来更改用于绘制线条的点,但这样做并没有不要删除旧线,它只是在它们上面绘
我正在将 UIView 转换为 UIImage,以将其设置为导航栏背景。 那个 View 有一个渐变层,当我使用 setBackgroundImage(_ backgroundImage: UIIma
我是一名优秀的程序员,十分优秀!