在Swift 3中计算像素

时间:2017-04-23 21:42:31

标签: swift pixel cgimage

我有一个应用程序可以计算图像的像素,以获得图像中五种颜色的相对区域。 Swift 3的更新版本适用于应用程序支持文件中的声明图像,但不包含来自文档目录的可变图像。我错过了什么?

此版本有效:

import UIKit
import CoreGraphics

class ComputeAreaViewController: UIViewController {

var redValue: String!
var blueValue: String!
var greenValue: String!
var whiteValue: String!
var yellowValue: String!
var totalValue: String!

//var image: UIImage!

let image = UIImage(named: "test_image.png")!

override func viewDidLoad() {
    super.viewDidLoad()

    /*
    let fm = FileManager.default
    let docsurl = try! fm.url(for: .documentDirectory, in:      .userDomainMask, appropriateFor: nil, create: false)
    let myurl = docsurl.appendingPathComponent("tmp.png")
    image = UIImage(contentsOfFile: myurl.path)!
     */

    view.layer.contents = image.cgImage!

    computeArea()
}

func classifyPixel( _ r: UInt8, _ g: UInt8, _ b: UInt8, _ coverRed:   inout UInt, _ coverGreen: inout UInt, _ coverYellow: inout UInt, _ coverBlue: inout UInt, _ coverWhite: inout UInt ) {
    if r == 255 && g == 0 && b == 0 { coverRed += 1 }
    if r == 0 && g == 255 && b == 0 { coverGreen += 1 }
    if r == 255 && g == 255 && b == 0 { coverYellow += 1 }
    if r == 0 && g == 0 && b == 255 { coverBlue += 1 }
    if r == 255 && g == 255 && b == 255 { coverWhite += 1 }
}

func computeArea() {

    var coverRed: UInt = 0
    var coverGreen: UInt = 0
    var coverYellow: UInt = 0
    var coverBlue: UInt = 0
    var coverWhite: UInt = 0
    var coverTotal = 0

    let imageWidth = Int(image.size.width)
    let imageHeight = Int(image.size.height)

    let bitsPerComponent = 8
    let bytesPerPixel = 4
    let bytesPerRow = bytesPerPixel * imageWidth

    let bufferSize = bytesPerRow * imageHeight
    var bytesPointer = UnsafeMutableRawPointer.allocate( bytes: bufferSize, alignedTo: 1 )
    let bytesPointerSaved = bytesPointer

    if let bitmapContext = CGContext( data: bytesPointer, width: imageWidth, height: imageHeight, bitsPerComponent: bitsPerComponent, bytesPerRow: bytesPerRow, space: CGColorSpaceCreateDeviceRGB(), bitmapInfo: CGImageAlphaInfo.premultipliedLast.rawValue ) {

        bitmapContext.draw( (image.cgImage!), in: CGRect( x: 0, y: 0, width: imageWidth, height: imageHeight ), byTiling: false )

        for _ in 0..<imageHeight {
            for _ in 0..<imageWidth {
                var r: UInt8 = 0, g: UInt8 = 0, b: UInt8 = 0
                r = bytesPointer.load( as: UInt8.self )
                bytesPointer += 1
                g = bytesPointer.load( as: UInt8.self )
                bytesPointer += 1
                b = bytesPointer.load( as: UInt8.self )
                bytesPointer += 2
                classifyPixel( r, g, b, &coverRed, &coverGreen, &coverYellow, &coverBlue, &coverWhite )
                coverTotal += 1
            }
        }

    } else {
        print( #file + " " + #function + " failed to create bitmap context ")
    }
    bytesPointerSaved.deallocate( bytes: bufferSize, alignedTo: 1 )
    let fTotal = Float( coverTotal )
    print( "coverRed: \(100.0*Float(coverRed)/fTotal), coverGreen: \   (100.0*Float(coverGreen)/fTotal), coverYellow: \(100.0*Float(coverYellow)/fTotal), coverBlue: \(100.0*Float(coverBlue)/fTotal), coverWhite: \(100.0*Float(coverWhite)/fTotal), coverTotal: \(coverTotal), #ofPixels: \(bufferSize/bytesPerPixel)" )

    greenValue = String(describing: (100.0*Float(coverGreen)/fTotal))
    yellowValue = String(describing: (100.0*Float(coverYellow)/fTotal))
    redValue = String(describing: (100.0*Float(coverRed)/fTotal))
    blueValue = String(describing: (100.0*Float(coverBlue)/fTotal))
    whiteValue = String(describing: (100.0*Float(coverWhite)/fTotal))
}

override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
}

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {

    if segue.identifier == "computeResult" {

        let areaController = segue.destination as! AreaPercentViewController
        areaController.redValue = redValue
        areaController.blueValue = blueValue
        areaController.greenValue = greenValue
        areaController.whiteValue = whiteValue
        areaController.yellowValue = yellowValue
        areaController.totalValue = totalValue
    }
}
}

此版本不起作用:

import UIKit
import CoreGraphics

class ComputeAreaViewController: UIViewController {

var redValue: String!
var blueValue: String!
var greenValue: String!
var whiteValue: String!
var yellowValue: String!
var totalValue: String!

var image: UIImage!

//let image = UIImage(named: "test_image.png")!

override func viewDidLoad() {
    super.viewDidLoad()

    let fm = FileManager.default
    let docsurl = try! fm.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: false)
    let myurl = docsurl.appendingPathComponent("tmp.png")
    image = UIImage(contentsOfFile: myurl.path)!

    view.layer.contents = image.cgImage!

    computeArea()
}

func classifyPixel( _ r: UInt8, _ g: UInt8, _ b: UInt8, _ coverRed: inout UInt, _ coverGreen: inout UInt, _ coverYellow: inout UInt, _ coverBlue: inout UInt, _ coverWhite: inout UInt ) {
    if r == 255 && g == 0 && b == 0 { coverRed += 1 }
    if r == 0 && g == 255 && b == 0 { coverGreen += 1 }
    if r == 255 && g == 255 && b == 0 { coverYellow += 1 }
    if r == 0 && g == 0 && b == 255 { coverBlue += 1 }
    if r == 255 && g == 255 && b == 255 { coverWhite += 1 }
}

func computeArea() {

    var coverRed: UInt = 0
    var coverGreen: UInt = 0
    var coverYellow: UInt = 0
    var coverBlue: UInt = 0
    var coverWhite: UInt = 0
    var coverTotal = 0

    let imageWidth = Int(image.size.width)
    let imageHeight = Int(image.size.height)

    let bitsPerComponent = 8
    let bytesPerPixel = 4
    let bytesPerRow = bytesPerPixel * imageWidth

    let bufferSize = bytesPerRow * imageHeight
    var bytesPointer = UnsafeMutableRawPointer.allocate( bytes: bufferSize, alignedTo: 1 )
    let bytesPointerSaved = bytesPointer

    if let bitmapContext = CGContext( data: bytesPointer, width: imageWidth, height: imageHeight, bitsPerComponent: bitsPerComponent, bytesPerRow: bytesPerRow, space: CGColorSpaceCreateDeviceRGB(), bitmapInfo: CGImageAlphaInfo.premultipliedLast.rawValue ) {

        bitmapContext.draw( (image.cgImage!), in: CGRect( x: 0, y: 0, width: imageWidth, height: imageHeight ), byTiling: false )

        for _ in 0..<imageHeight {
            for _ in 0..<imageWidth {
                var r: UInt8 = 0, g: UInt8 = 0, b: UInt8 = 0
                r = bytesPointer.load( as: UInt8.self )
                bytesPointer += 1
                g = bytesPointer.load( as: UInt8.self )
                bytesPointer += 1
                b = bytesPointer.load( as: UInt8.self )
                bytesPointer += 2
                classifyPixel( r, g, b, &coverRed, &coverGreen, &coverYellow, &coverBlue, &coverWhite )
                coverTotal += 1
            }
        }

    } else {
        print( #file + " " + #function + " failed to create bitmap context ")
    }
    bytesPointerSaved.deallocate( bytes: bufferSize, alignedTo: 1 )
    let fTotal = Float( coverTotal )
    print( "coverRed: \(100.0*Float(coverRed)/fTotal), coverGreen: \(100.0*Float(coverGreen)/fTotal), coverYellow: \(100.0*Float(coverYellow)/fTotal), coverBlue: \(100.0*Float(coverBlue)/fTotal), coverWhite: \(100.0*Float(coverWhite)/fTotal), coverTotal: \(coverTotal), #ofPixels: \(bufferSize/bytesPerPixel)" )

    greenValue = String(describing: (100.0*Float(coverGreen)/fTotal))
    yellowValue = String(describing: (100.0*Float(coverYellow)/fTotal))
    redValue = String(describing: (100.0*Float(coverRed)/fTotal))
    blueValue = String(describing: (100.0*Float(coverBlue)/fTotal))
    whiteValue = String(describing: (100.0*Float(coverWhite)/fTotal))
}

override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
}

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {

    if segue.identifier == "computeResult" {

        let areaController = segue.destination as! AreaPercentViewController
        areaController.redValue = redValue
        areaController.blueValue = blueValue
        areaController.greenValue = greenValue
        areaController.whiteValue = whiteValue
        areaController.yellowValue = yellowValue
        areaController.totalValue = totalValue
    }
}
}

1 个答案:

答案 0 :(得分:0)

答案是传递图像的Alpha通道。它小于1.0,将其重置为1.0修复了计数问题。