【问题标题】:Core Graphics messing changes UIimage formatCore Graphics 乱改 UIimage 格式
【发布时间】:2015-07-22 16:59:34
【问题描述】:

我编写了一个简单的算法来检测 UIImage 中的边缘。它适用于从捆绑包中拍摄的图像(查看第一张图像)。 在我进行一些图像处理(应用过滤器、蒙版、裁剪等)并将图像传递给相同的函数之后,它就会变得一团糟(图 2)。我假设 CoreGrahics 正在更改图像内部的某些内容。问题是什么?

这就是我开始处理图像的方式:

public struct PixelData {
    var a:UInt8 = 255
    var r:UInt8
    var g:UInt8
    var b:UInt8
}

   func findEdges(cgImage:CGImageRef)->UIImage{
    var pixelData = CGDataProviderCopyData(CGImageGetDataProvider(cgImage))

    //var data = CFDataGetMutableBytePtr
    var mdata: UnsafePointer<UInt8> = CFDataGetBytePtr(pixelData)
    var data = UnsafeMutablePointer<UInt8>(mdata)
    let height = CGImageGetHeight(cgImage)
    let width = CGImageGetWidth(cgImage)
    var start = CACurrentMediaTime()

    //create an empty buffer
    let emptyPixel = PixelData(a: 0, r: 0, g: 0, b: 0)
    let blackPixel = PixelData(a: 255, r: 255, g: 255, b: 255)

    var buffer = [PixelData](count: Int(width  * height), repeatedValue: emptyPixel)
    var booleanArray = [Bool](count: Int(width  * height), repeatedValue: false)


    for var y = 0; y < height-1; y++ {
        for var x = 0; x < width; x++ {
            //Current one
            var currentPixelInfo: Int = ((Int(width) * Int(y)) + Int(x)) * 4
            var currentAlpha = CGFloat(data[currentPixelInfo+3]) / CGFloat(255.0)
            var downPixelInfo: Int = ((Int(width) * Int(y+1)) + Int(x)) * 4
            var downAlpha = CGFloat(data[downPixelInfo+3]) / CGFloat(255.0)

            if y == 0 && currentAlpha != 0{ // Top Edge
                booleanArray[currentPixelInfo/4] = true
                buffer[currentPixelInfo/4] = blackPixel
            }

            if y > 0 && y < height - 2{
                //one up
                var topPixelInfo: Int = ((Int(width) * Int(y - 1)) + Int(x )) * 4
                var topAlpha = CGFloat(data[topPixelInfo+3]) / CGFloat(255.0)

                if downAlpha == 0 && currentAlpha != 0 {//edge
                    booleanArray[currentPixelInfo/4] = true
                    buffer[currentPixelInfo/4] = blackPixel
                }

                if topAlpha == 0 && currentAlpha != 0 {//edge
                    booleanArray[currentPixelInfo/4] = true
                    buffer[currentPixelInfo/4] = blackPixel
                }

            }

            if y == height - 2 && downAlpha != 0 {
                booleanArray[downPixelInfo/4] = true
                buffer[downPixelInfo/4] = blackPixel
            }

        }
    }


    for var y = 0; y < height-1; y++ {
        for var x = 0; x < width-1; x++ {

            //Current one
            var currentPixelInfo: Int = ((Int(width) * Int(y)) + Int(x)) * 4
            var currentAlpha = CGFloat(data[currentPixelInfo+3]) / CGFloat(255.0)
            //Next
            var nextPixelInfo: Int = ((Int(width) * Int(y)) + Int(x + 1)) * 4
            var nextAlpha = CGFloat(data[nextPixelInfo+3]) / CGFloat(255.0)


            //check horizontally
            if x == 0 && currentAlpha != 0{ // Edge case
                booleanArray[currentPixelInfo/4] = true
                buffer[currentPixelInfo/4] = blackPixel
            }
            if x > 0 && x < width - 2{
                //One before
                var previousPixelInfo: Int = ((Int(width) * Int(y)) + Int(x - 1)) * 4
                var previousAlpha = CGFloat(data[previousPixelInfo+3]) / CGFloat(255.0)

                if nextAlpha == 0 && currentAlpha != 0 {//Living on the edge
                    booleanArray[currentPixelInfo/4] = true
                    buffer[currentPixelInfo/4] = blackPixel
                }
                if previousAlpha == 0 && currentAlpha != 0 {//Living on the edge
                    booleanArray[currentPixelInfo/4] = true
                    buffer[currentPixelInfo/4] = blackPixel
                }
            }

            if x == width - 2 && nextAlpha != 0 {
                booleanArray[nextPixelInfo/4] = true
                buffer[nextPixelInfo/4] = blackPixel
            }
        }
    }


    var stop = CACurrentMediaTime()


    let image = imageFromARGB32Bitmap(buffer, width: width, height: height)

    println(stop - start)
    return image!;
    //self.imageView.image = image

}

func imageFromARGB32Bitmap(pixels:[PixelData], width:Int, height:Int)->UIImage? {

        let bitsPerComponent:Int = 8
        let bitsPerPixel:Int = 32

        assert(pixels.count == Int(width * height))

        var data = pixels // Copy to mutable []
        let providerRef = CGDataProviderCreateWithCFData(
            NSData(bytes: &data, length: data.count * sizeof(PixelData))
        )

        // let redPixel = PixelData(a: 255, r: 192, g: 0, b: 0)

        let cgim = CGImageCreate(
            width,
            height,
            bitsPerComponent,
            bitsPerPixel,
            width * Int(sizeof(PixelData)),
            rgbColorSpace,
            bitmapInfo,
            providerRef,
            nil,
            true,
            kCGRenderingIntentDefault
        )
        return UIImage(CGImage: cgim)
    }

[][3]

【问题讨论】:

    标签: ios core-graphics calayer mask


    【解决方案1】:

    虽然我没有弄清楚 UIImage 究竟对原始像素数据做了什么,但我编写的函数解决了这个问题。这里的关键点是使用位图信息的 CGImageAlphaInfo.PremultipliedFirst 值,因为我的数据结构需要 ARGB 格式。

         func imageFromBitmapContext(image:CGImageRef, width:Int, height:Int)->UIImage?
                {
    
                let colorSpace:CGColorSpace = CGColorSpaceCreateDeviceRGB()
                let bitmapInfo = CGBitmapInfo(CGImageAlphaInfo.PremultipliedFirst.rawValue)
                let bytesPerRow = 4 * width
                let context = CGBitmapContextCreate(nil, Int(width), Int(height), 8, Int(bytesPerRow), colorSpace, bitmapInfo)
    
                CGContextDrawImage(context, CGRectMake(0, 0, CGFloat(width), CGFloat(height)), image)
    
    
                let image = CGBitmapContextCreateImage(context)
    
                return UIImage(CGImage: image)
            }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-04-03
      • 1970-01-01
      • 2010-10-01
      • 1970-01-01
      相关资源
      最近更新 更多