如何从强度值重建灰度图像?

时间:2016-01-08 12:26:26

标签: swift uikit core-graphics

通常需要从图像获取像素数据或从像素数据重建该图像。如何拍摄图像,将其转换为像素值数组,然后使用Swift中的像素数组使用CoreGraphics重建图像?

这个问题的答案的质量已经到处都是,所以我想要一个规范的答案。

2 个答案:

答案 0 :(得分:5)

将像素值作为数组

此功能可以轻松扩展为彩色图像。为简单起见,我使用的是灰度,但我已经对这些更改进行了评论,以获得RGB。

func pixelValuesFromImage(imageRef: CGImage?) -> (pixelValues: [UInt8]?, width: Int, height: Int)
{
    var width = 0
    var height = 0
    var pixelValues: [UInt8]?
    if let imageRef = imageRef {
        width = CGImageGetWidth(imageRef)
        height = CGImageGetHeight(imageRef)
        let bitsPerComponent = CGImageGetBitsPerComponent(imageRef)
        let bytesPerRow = CGImageGetBytesPerRow(imageRef)
        let totalBytes = height * bytesPerRow

        let colorSpace = CGColorSpaceCreateDeviceGray()
        pixelValues = [UInt8](count: totalBytes, repeatedValue: 0)

        let contextRef = CGBitmapContextCreate(&pixelValues!, width, height, bitsPerComponent, bytesPerRow, colorSpace, 0)
        CGContextDrawImage(contextRef, CGRectMake(0.0, 0.0, CGFloat(width), CGFloat(height)), imageRef)
    }

    return (pixelValues, width, height)
}

从像素值

获取图像

我将一个图像(在这种情况下为每像素8位灰度)重建为CGImage

func imageFromPixelValues(pixelValues: [UInt8]?, width: Int, height: Int) ->  CGImage?
{
    var imageRef: CGImage?
    if let pixelValues = pixelValues {
        let bitsPerComponent = 8
        let bytesPerPixel = 1
        let bitsPerPixel = bytesPerPixel * bitsPerComponent
        let bytesPerRow = bytesPerPixel * width
        let totalBytes = height * bytesPerRow
        let providerRef = CGDataProviderCreateWithData(nil, pixelValues, totalBytes, nil)

        let colorSpaceRef = CGColorSpaceCreateDeviceGray()
        let bitmapInfo = CGBitmapInfo(rawValue: CGImageAlphaInfo.None.rawValue)
            .union(.ByteOrderDefault)
        imageRef = CGImageCreate(width,
            height,
            bitsPerComponent,
            bitsPerPixel,
            bytesPerRow,
            colorSpaceRef,
            bitmapInfo,
            providerRef,
            nil,
            false,
            CGColorRenderingIntent.RenderingIntentDefault)
    }

    return imageRef
}

在Playground中演示代码

您需要将图像复制到Playground的Resources文件夹中,然后在下面更改文件名和扩展名以匹配。最后一行的结果是从CGImage构造的UIImage。

var image: UIImage? = nil
let URL = NSBundle.mainBundle().URLForResource("zebra_5", withExtension: "tif")
if let path = URL?.path {
    if NSFileManager().fileExistsAtPath(path) {
        do {
            try NSData(contentsOfURL: URL!, options: .DataReadingMappedIfSafe)
        } catch let error as NSError {
            print ("Error: \(error.localizedDescription)")
        }
        image = UIImage(contentsOfFile: path)
    }
}

let (intensityValues, width, height) = pixelValuesFromImage(image?.CGImage)
let roundTrippedImage = imageFromPixelValues(intensityValues, width: width, height: height)
let zebra = UIImage(CGImage: roundTrippedImage!)

答案 1 :(得分:0)

我无法让上面的Cameron代码正常工作,所以我想测试另一种方法。我发现Vacawama's code,它依赖于ARGB像素。您可以使用该解决方案,只需将每个灰度值映射到每个灰度值即可将其转换为ARGB值:

msbuild -p:RestorePackagesConfig=true -t:restore;build