2012-10-15 22 views
12

एनएसआईमेज को NSBitmapImageRep में कैसे परिवर्तित करें? मेरे पास कोड है:NSImage से NSBitmapImageRep

- (NSBitmapImageRep *)bitmapImageRepresentation 
{ 
    NSBitmapImageRep *ret = (NSBitmapImageRep *)[self representations]; 

    if(![ret isKindOfClass:[NSBitmapImageRep class]]) 
    { 
     ret = nil; 
     for(NSBitmapImageRep *rep in [self representations]) 
      if([rep isKindOfClass:[NSBitmapImageRep class]]) 
      { 
       ret = rep; 
       break; 
      } 
    } 

    if(ret == nil) 
    { 
     NSSize size = [self size]; 

     size_t width   = size.width; 
     size_t height  = size.height; 
     size_t bitsPerComp = 32; 
     size_t bytesPerPixel = (bitsPerComp/CHAR_BIT) * 4; 
     size_t bytesPerRow = bytesPerPixel * width; 
     size_t totalBytes = height * bytesPerRow; 

     NSMutableData *data = [NSMutableData dataWithBytesNoCopy:calloc(totalBytes, 1) length:totalBytes freeWhenDone:YES]; 

     CGColorSpaceRef space = CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB); 

     CGContextRef ctx = CGBitmapContextCreate([data mutableBytes], width, height, bitsPerComp, bytesPerRow, CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB), kCGBitmapFloatComponents | kCGImageAlphaPremultipliedLast); 

     if(ctx != NULL) 
     { 
      [NSGraphicsContext saveGraphicsState]; 
      [NSGraphicsContext setCurrentContext:[NSGraphicsContext graphicsContextWithGraphicsPort:ctx flipped:[self isFlipped]]]; 

      [self drawAtPoint:NSZeroPoint fromRect:NSZeroRect operation:NSCompositeCopy fraction:1.0]; 

      [NSGraphicsContext restoreGraphicsState]; 

      CGImageRef img = CGBitmapContextCreateImage(ctx); 

      ret = [[NSBitmapImageRep alloc] initWithCGImage:img]; 
      [self addRepresentation:ret]; 

      CFRelease(img); 
      CFRelease(space); 

      CGContextRelease(ctx); 
     } 
    } 


    return ret; 
} 

यह काम करता है, लेकिन यह स्मृति रिसाव का कारण बनता है। कम से कम जब मैं इसे एआरसी के साथ उपयोग कर रहा हूं। initWithData:[nsimagename TIFFRepresentation] का उपयोग करना यह सही ढंग से काम नहीं कर रहा है। कुछ छवियों के प्रतिनिधित्व अच्छे नहीं हैं। मुझे लगता है कि यह छवि के स्वरूप और रंगस्थान पर निर्भर करता है। क्या इसे हासिल करने के कोई अन्य तरीके हैं?


mrwalker द्वारा सुझाए गए समाधान के साथ परिणाम:

मूल छवि:
enter image description here

bitmapimagerep और वापस छवि के लिए 1-समय पर परिवर्तित:
enter image description here

में रूपांतरित बी आई टी एम apimagerep और वापस छवि के लिए 3 बार:
enter image description here

आप छवि NSBitmapImageRep

को परिवर्तित करने के बाद गहरा हो जाता है हर बार देख
+0

Hockeyman, आप अभी भी अपने प्रश्न का पूर्ण समाधान क्या है? मैं बिना किसी प्रक्रिया के पिक्सल रंगों की पहचान करने का एक तरीका ढूंढ रहा हूं। शायद NSBitmapImageRep किसी भी तरह से मेरी मदद कर सकता है। धन्यवाद। – RickON

उत्तर

11

आप इस पद्धति Mike Ash's "Obtaining and Interpreting Image Data" blog post से अनुकूलित की कोशिश कर सकते:

- (NSBitmapImageRep *)bitmapImageRepresentation { 
    int width = [self size].width; 
    int height = [self size].height; 

    if(width < 1 || height < 1) 
     return nil; 

    NSBitmapImageRep *rep = [[NSBitmapImageRep alloc] 
          initWithBitmapDataPlanes: NULL 
          pixelsWide: width 
          pixelsHigh: height 
          bitsPerSample: 8 
          samplesPerPixel: 4 
          hasAlpha: YES 
          isPlanar: NO 
          colorSpaceName: NSDeviceRGBColorSpace 
          bytesPerRow: width * 4 
          bitsPerPixel: 32]; 

    NSGraphicsContext *ctx = [NSGraphicsContext graphicsContextWithBitmapImageRep: rep]; 
    [NSGraphicsContext saveGraphicsState]; 
    [NSGraphicsContext setCurrentContext: ctx]; 
    [self drawAtPoint: NSZeroPoint fromRect: NSZeroRect operation: NSCompositeCopy fraction: 1.0]; 
    [ctx flushGraphics]; 
    [NSGraphicsContext restoreGraphicsState]; 

    return [rep autorelease]; 
} 
+0

वैसे यह विधि काम करता है लेकिन सही ढंग से नहीं। यह गहरे चित्र के साथ प्रतिनिधित्व देता है। मैं अपने प्रश्न में उदाहरण जोड़ूंगा। – hockeyman

+0

यदि आप 'एनएससीएलब्रेटेड आरजीबीसीओलर स्पेस' के बजाय 'एनएसडीवीसआरजीबीसीओलर स्पेस' का उपयोग करते हैं तो क्या परिणाम बेहतर होते हैं? – mrwalker

+0

बहुत बहुत धन्यवाद! :) – hockeyman

11

@Julius: आपका कोड बहुत जटिल है और इसमें कई बग शामिल हैं। मैं केवल प्रथम लाइनों के लिए एक सुधार कर देगा:

- (NSBitmapImageRep *)bitmapImageRepresentation 
{ 
    NSArray *ret =[self representations]; 
    for(NSImageRep *rep in [self representations]) 
     if([rep isKindOfClass:[NSBitmapImageRep class]]) return rep; 
    return nil; 
} 

यह पहली NSBitmapImageRep निकालने अगर यह अभ्यावेदन में सदस्य है या नहीं के बराबर वापस आ जाएगी, अगर कोई NSBitmapImageRepNSBitmapImageRep, NSPDFImageRep या NSCGImageSnapshotRep या ...

- (NSBitmapImageRep *)bitmapImageRepresentation 
{ 
    CGImageRef CGImage = [self CGImageForProposedRect:nil context:nil hints:nil]; 
    return [[[NSBitmapImageRep alloc] initWithCGImage:CGImage] autorelease]; 
} 

या NSImage की उपवर्गीकरण से बचने के लिए आप लिख सकते हैं:

NSImage *img = [[[NSImage alloc] initWithContentsOfFile:filename] autorelease]; 
CGImageRef CGImage = [img CGImageForProposedRect:nil context:nil hints:nil]; 
NSBitmapImageRep *rep = [[[NSBitmapImageRep alloc] initWithCGImage:CGImage] autorelease]; 
मैं आपको एक और समाधान जो हमेशा काम करेंगे जो कुछ भी NSImageReps अभ्यावेदन में हैं दे देंगे

यह केवल एक ही NSBitmapImageRep लौटाएगा जो शायद पर्याप्त नहीं है यदि छवि में एक से अधिक प्रतिनिधित्व होते हैं (उदाहरण के लिए टीआईएफएफ फाइलों से NSBitmapImageRep एस)। लेकिन कुछ कोड जोड़ना सरल है।

+0

एक अतिरिक्त सुझाव के रूप में, आप पुनरावृत्ति में 'ret' के साथ दूसरे' [स्वयं प्रतिनिधित्व] 'को प्रतिस्थापित करना चाहते हैं, क्योंकि अभी अभी 'ret' अप्रयुक्त है। –

+0

@ ब्रैड, अच्छा सुझाव! धन्यवाद। –

1

हो सकता है कि देर से पार्टी के लिए है, लेकिन इस @mrwalker प्रतिक्रिया से स्विफ्ट 3 संस्करण है:

extension NSImage { 
    func bitmapImageRepresentation(colorSpaceName: String) -> NSBitmapImageRep? { 
     let width = self.size.width 
     let height = self.size.height 

     if width < 1 || height < 1 { 
      return nil 
     } 

     if let rep = NSBitmapImageRep(bitmapDataPlanes: nil, pixelsWide: Int(width), pixelsHigh: Int(height), bitsPerSample: 8, samplesPerPixel: 4, hasAlpha: true, isPlanar: false, colorSpaceName: colorSpaceName, bytesPerRow: Int(width) * 4, bitsPerPixel: 32) 
     { 
      let ctx = NSGraphicsContext.init(bitmapImageRep: rep) 
      NSGraphicsContext.saveGraphicsState() 
      NSGraphicsContext.setCurrent(ctx) 
      self.draw(at: NSZeroPoint, from: NSZeroRect, operation: NSCompositingOperation.copy, fraction: 1.0) 
      ctx?.flushGraphics() 
      NSGraphicsContext.restoreGraphicsState() 
      return rep 
     } 
     return nil 
    } 
}