TL; DR:在传统的Obj-C代码中,颜色空间参数值为NULL
。 Swift等效项中不允许这样做。有什么价值?
我继承了以下代码:
unsigned char pixel[1] = {0};
CGContextRef context = CGBitmapContextCreate(
pixel,1, 1, 8, 1, NULL, (CGBitmapInfo)kCGImageAlphaOnly
);
Swift 4 CGContext
的端口非常简单,除了NULL
颜色空间值。使用合理的值,我从nil
返回CGContext.init?()
。我的翻译是:
var pixelValue = UInt8(0)
var pixel = Data(buffer: UnsafeBufferPointer(start:&pixelValue, count:1))
let context = CGContext(
data : &pixel,
width : 1,
height : 1,
bitsPerComponent: 8,
bytesPerRow : 1,
space : CGColorSpace(name:CGColorSpace.genericRGBLinear)!,
bitmapInfo : CGImageAlphaInfo.alphaOnly.rawValue
)! // Returns nil; unwrapping crashes
问:space
的适当值是多少? (我提供的值不会返回nil
;它是CGContext()
调用本身。
设置环境变量CGBITMAP_CONTEXT_LOG_ERRORS
会产生如下错误日志:
Assertion failed: (0), function get_color_model_name,
file /BuildRoot/Library/Caches/com.apple.xbs/Sources/Quartz2D_Sim/
Quartz2D-1129.2.1/CoreGraphics/API/CGBitmapContextInfo.c, line 210.
对于更多的背景故事,上下文用于通过以下方式查找UIImage
中单个像素的alpha值:
unsigned char pixel[1] = {0};
CGContextRef context = CGBitmapContextCreate(pixel,1, 1, 8, 1, NULL, (CGBitmapInfo)kCGImageAlphaOnly);
UIGraphicsPushContext(context);
[image drawAtPoint:CGPointMake(-point.x, -point.y)];
UIGraphicsPopContext();
CGContextRelease(context);
CGFloat alpha = pixel[0]/255.0;
(我确实有找到alpha的替代方案,但为了保留遗留代码,我们希望保持这种方式。)
答案 0 :(得分:0)
我最近处理过类似的主题,也许这段代码示例可以帮助某人:
let image = UIImage(named: "2.png")
guard let cgImage = image?.cgImage else {
fatalError()
}
let width = cgImage.width
let height = cgImage.height
//CGColorSpaceCreateDeviceGray - 1 component, 8 bits
//i.e. 1px = 1byte
let bytesPerRow = width
let bitmapByteCount = width * height
let bitmapData: UnsafeMutablePointer<UInt8> = .allocate(capacity: bitmapByteCount)
defer {
bitmapData.deallocate()
}
bitmapData.initialize(repeating: 0, count: bitmapByteCount)
guard let context = CGContext(data: bitmapData, width: width, height: height,
bitsPerComponent: 8, bytesPerRow: bytesPerRow,
space: CGColorSpaceCreateDeviceGray(), bitmapInfo: CGImageAlphaInfo.alphaOnly.rawValue) else {
fatalError()
}
//draw image to context
var rect = CGRect(x: 0, y: 0, width: width, height: height)
context.draw(cgImage, in: rect)
// Enumerate through all pixels
for row in 0..<height {
for col in 0..<width {
let alphaValue = bitmapData[row * width + col]
if alphaValue != 0 {
//visible pixel
}
}
}
答案 1 :(得分:0)
以下是确定像素是否透明的方法:
let info = CGImageAlphaInfo.alphaOnly.rawValue
let pixel = UnsafeMutablePointer<UInt8>.allocate(capacity:1)
defer {
pixel.deinitialize(count: 1)
pixel.deallocate()
}
pixel[0] = 0
let sp = CGColorSpaceCreateDeviceGray()
let context = CGContext(data: pixel,
width: 1, height: 1, bitsPerComponent: 8, bytesPerRow: 1,
space: sp, bitmapInfo: info)!
UIGraphicsPushContext(context)
im.draw(at:CGPoint(-point.x, -point.y))
UIGraphicsPopContext()
let p = pixel[0]
let alpha = Double(p)/255.0
let transparent = alpha < 0.01
答案 2 :(得分:0)
记录下来,这就是我最后的想法。它还没有(但是)行为不端,所以基于“如果它还没有坏,就不要修复它”的原则,我将保留它。 (为清楚起见,我添加了self
。)但是您可以确定,如果将来需要,我会在其中粘贴Matt的代码。谢谢马特!
// Note that "self" is a UIImageView; "point" is the point under consideration.
let im = self.image!
// TODO: Why is this clamping necessary? We get points outside our size.
var x = point.x
var y = point.y
if x < 0 { x = 0 } else if x > im.size.width - 1 { x = im.size.width - 1 }
if y < 0 { y = 0 } else if y > im.size.height - 1 { y = im.size.height - 1 }
let screenWidth = self.bounds.width
let intrinsicWidth = im.size.width
x *= im.scale * intrinsicWidth/screenWidth
y *= im.scale * intrinsicWidth/screenWidth
let pixData = im.cgImage?.dataProvider?.data
let data = CFDataGetBytePtr(pixData!)
let pixIndex = Int(((Int(im.size.width*im.scale) * Int(y)) + Int(x)) * 4)
let r = data?[pixIndex]
let g = data?[pixIndex + 1]
let b = data?[pixIndex + 2]
let α = data?[pixIndex + 3]
let red = CGFloat(r!)/255
let green = CGFloat(g!)/255
let blue = CGFloat(b!)/255
let alpha = CGFloat(α!)/255