2017-02-20 6 views
12

मेरे ऐप में मैं एक छवि मैपिंग फ्लोट को पिक्सेल मान पर बना रहा हूं और इसे Google मानचित्र पर ओवरले के रूप में उपयोग करता हूं, लेकिन यह हमेशा के लिए होता है, एंड्रॉइड में एक ही चीज़ लगभग तुरंत है। मेरा कोड इस तरह दिखता है:स्विफ्ट में चित्रकारी छवि हमेशा के लिए लेती है

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% सीपीयू पावर का उपयोग करता है।

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, क्या आपने यह निर्धारित करने के लिए इंस्ट्रूमेंट्स का उपयोग करने की कोशिश की है कि सभी सीपीयू खर्च किए जा रहे हैं? आप इस ट्यूटोरियल से शुरू करने का प्रयास कर सकते हैं: https://www.raywenderlich.com/97886/instruments-tutorial-with-swift-getting-started –

उत्तर

8

मैं अपने कोड की कोशिश की और मुझे पता चला है कि समस्या अपने कार्य के साथ नहीं है।

मुझे लगता है कि आपको UInt8 आधारित पिक्सेल संरचना का उपयोग करना चाहिए, न कि CGFloat आधारित संरचना।

मैं एक कोको आवेदन के लिए आपके कोड अनुवाद है, और इस परिणाम है:

enter image description here

मैं:

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) 

इस कोड को तेजी से और प्रकाश है, यहाँ डिबग प्रणाली प्रभाव मान है लगता है कि समस्या उस भाग के साथ आता है जो पिक्सेल डेटा लोड करता है, इसे जांचें और सुनिश्चित करें कि यह ठीक से काम करता है।

+0

मैं एनएसआईमेज और एनएसएसआईएस नहीं लेगा? यह कैसे लगेगा अगर यह ऐपकिट के बजाय UIKit का उपयोग करता है? – Recusiwe

+0

@Recusiwe आप 'UIImage (cgImage: cgimage!) 'का उपयोग कर सकते हैं और' NSImage' के बजाय 'UIImage' वापस कर सकते हैं, फिर यदि आप UIKit का उपयोग कर रहे हैं तो' NSData' को' डेटा' में बदलें। यहां [प्रलेखन] (https://developer.apple.com/reference/uikit/uiimage/1624090-init) है। अन्य निर्देश लगभग समान हैं ... – Cristian

1

यदि आपको वास्तविक बिटमैप डेटा तक पहुंचने और बदलने की आवश्यकता है, तो आप CGImage का उपयोग कर सकते हैं। अन्य मामलों में सीआईएममेज वस्तुओं का प्रतिनिधित्व करते हैं। तो यूआईएममेज के साथ काम करें, यूआईएममेज से सीआईएममेज में कनवर्ट करें, उस पर कोई हस्तक्षेप करें, और उसके बाद इसे वापस यूआईएममेज में परिवर्तित करें (जैसा कि आपने अपने कोड में CGImage के साथ किया था)। UIImage vs. CIImage vs. CGImage

मुख्य छवि वास्तव में एक छवि प्रदर्शित नहीं होता है जब तक यह ऐसा करने के लिए कहा है:

यहाँ एक पोस्ट समझा क्या है क्या है। यह "आलसी मूल्यांकन" विधि कोर छवि को यथासंभव कुशलतापूर्वक संचालित करने की अनुमति देती है।

CIImage page in Apple Developer Documentation

संबंधित मुद्दे