2017-02-20 85 views
12

在我的应用程序中,我创建了一个图像映射浮点到像素值,并将其用作Google地图上的叠加层,但这需要永远做,Android中的相同情况几乎是瞬间的。我的代码看起来像这样:Swift中的绘图图像永远需要

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

    let bitsPerComponent = 8 
    let bitsPerPixel = bitsPerComponent * 4 
    let bytesPerRow = bitsPerPixel * width/8 

    let providerRef = CGDataProvider(
     data: NSData(bytes: pixels, length: height * width * 4) 
    ) 

    let cgimage = CGImage(
     width: width, 
     height: height, 
     bitsPerComponent: bitsPerComponent, 
     bitsPerPixel: bitsPerPixel, 
     bytesPerRow: bytesPerRow, 
     space: CGColorSpaceCreateDeviceRGB(), 
     bitmapInfo: CGBitmapInfo(rawValue: CGImageAlphaInfo.premultipliedFirst.rawValue), 
     provider: providerRef!, 
     decode: nil, 
     shouldInterpolate: true, 
     intent: .defaultIntent 
    ) 

    if cgimage == nil { 
     print("CGImage is not supposed to be nil") 
     return nil 
    } 
    return UIImage(cgImage: cgimage!) 
} 

任何关于这可能需要这么长时间的建议吗?我可以看到它使用大约96%的CPU功率。

func fromData(pair: AllocationPair) -> UIImage? { 

    let table = pair.table 
    let data = pair.data 

    prepareColors(allocations: table.allocations) 

    let height = data.count 
    let width = data[0].count 

    var colors = [PixelData]() 

    for row in data { 
     for val in row { 

      if (val == 0.0) { 
       colors.append(PixelData(a: 0, r: 0, g: 0, b: 0)) 
       continue 
      } 

      if let interval = findInterval(table: table, value: val) { 
       if let color = intervalColorDict[interval] { 
        colors.append(PixelData(a: color.a, r: color.r, g: color.g, b: color.b)) 
       } 
      } 
     } 
    } 

    return imageFromPixels(pixels: colors, width: width, height: height) 
} 

我试过时间分析它,这是需要时间的输出。

enter image description here

+0

基本上我只是显示与混合起来是绿色,红色或黄色像素的图片 – Recusiwe

+0

你确定问题这里,而不是在创建'[PixelData取出]'数组的?在调试版本中,操作大型数组非常慢。如果您在开启优化功能的情况下进行版本构建,则使用大型数组要快得多。确保问题出现在这里,而不是创建该数组。然后,当然,确保当你在主队列中显示你正在做的图像时。 – Rob

+1

@Recusiwe,您是否尝试过使用仪器来确定所有CPU的使用位置?你可以尝试从这个教程开始:https://www.raywenderlich.com/97886/instruments-tutorial-with-swift-getting-started –

回答

8

我想你的代码,我发现,这个问题是不是与你的函数。

我认为你应该使用基于UInt8的像素结构而不是基于CGFloat的结构。

我翻译你的Cocoa应用程序代码,这是结果:

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

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

    let bitsPerComponent = 8 
    let bitsPerPixel = bitsPerComponent * 4 
    let bytesPerRow = bitsPerPixel * width/8 

    let providerRef = CGDataProvider(
     data: NSData(bytes: pixels, length: height * width * 4) 
    ) 

    let cgimage = CGImage(
     width: width, 
     height: height, 
     bitsPerComponent: bitsPerComponent, 
     bitsPerPixel: bitsPerPixel, 
     bytesPerRow: bytesPerRow, 
     space: CGColorSpaceCreateDeviceRGB(), 
     bitmapInfo: CGBitmapInfo(rawValue: CGImageAlphaInfo.premultipliedFirst.rawValue), 
     provider: providerRef!, 
     decode: nil, 
     shouldInterpolate: true, 
     intent: .defaultIntent 
    ) 

    if cgimage == nil { 
     print("CGImage is not supposed to be nil") 
     return nil 
    } 
    return NSImage(cgImage: cgimage!, size: NSSize(width: width, height: height)) 
} 

var img = [PixelData]() 

for i: UInt8 in 0 ..< 20 { 
    for j: UInt8 in 0 ..< 20 { 
     // Creating a red 20x20 image. 
     img.append(PixelData(a: 255, r: 255, g: 0, b: 0)) 
    } 
} 

var ns = imageFromPixels(pixels: img, width: 20, height: 20) 

此代码是快,重量轻,这里的调试系统冲击值:

enter image description here

我认为问题出现在加载像素数据的部分,检查它并确保它正常工作。

+0

我不会采取NSImage和NSSize?它看起来如果它使用UIKit而不是AppKit? – Recusiwe

+0

@Recusiwe你可以使用'UIImage(cgImage:cgimage!)'并返回'UIImage'而不是'NSImage',如果你使用的是UIKit,那么把'NSData'改成'Data'。这里是[文档](https://developer.apple.com/reference/uikit/uiimage/1624090-init)。其他指示几乎相同... – Cristian

1

如果您需要访问和更改实际的位图数据,则可以使用CGImage。在其他情况下,使用CIImage表示的对象。因此,使用UIImage,将UIImage转换为CIImage,对其进行任何操作,然后将其转换回UIImage(如您在代码中使用CGImage所做的那样)。

这里有一个文章,解释什么是什么:UIImage vs. CIImage vs. CGImage

核心图像实际上并不渲染图像,直到它被告知这样做。这种“懒惰评估”方法允许Core Image尽可能高效地运行。

CIImage page in Apple Developer Documentation