2014-05-12 13 views
5

Utilizzo il framework XZINGObjC per creare un'immagine EAN-Barcode. In seguito la documentazione, lo sto facendo comeObiettivo C: Come convertire CGImageRef in UIImageView?

//in viewDidAppear 

//XZING: create Matrix 
NSString* eanString = @"1234567890123"; //sth. like that 
ZXBitMatrix* result = [writer encode:eanString 
           format:kBarcodeFormatEan13 
           width:500 
           height:500 
           error:&error]; 
if (result) { 
     //XZING: convert matrix to CGImageRef 
     CGImageRef imageRef = [[ZXImage imageWithMatrix:result] cgimage]; 

     //CRASHLINE HERE!! (this is NOT in the XZING documentation, but i cannot figure out the issue!) 
     UIImage* uiImage = [[UIImage alloc] initWithCGImage:imageRef]; //<--CRASH: EXC_BAD_ACCESS 

     if(image != nil){ 
      //assigning image to ui 
      self.barCodeImageView.image = uiImage; 
     } 

Funziona, se io passo attraverso questo codice utilizzando i punti di interruzione! Tuttavia, penso che ad un certo punto un'immagine non sia pronta per l'uso ?! Ma non riesco a trovare la ragione.

Quello che ho cercato:

  • utilizzando imageRef e uiImage come variabili locali (EXC_BAD_ACCESS CRASH)
  • provato che il funzionamento in un thread in background (EXC_BAD_ACCESS CRASH)

Stesso qui, ogni soluzione ha funzionato se ho usato punti di interruzione e ho fatto un passo dopo fila attraverso il codice. Qual è il mio errore qui? Qualche idea? Grazie in anticipo!

+1

controllare questo [collegamento di riferimento] (http://stackoverflow.com/questions/12756295/uiimage-from-cgimageref). forse avrai un po 'di aiuto. – Pawan

+0

Se stai passando, qual è il contenuto di 'imageRef'? – Sulthan

+0

@pawan: grazie, l'ho trovato ma non ha risolto il mio problema @Sulthan: 'imageRef' non è nullo se intendi che ... funziona come dovrebbe se usassi i breakpoint. Quindi qualcosa è già stato rilasciato o non è pronto per l'uso, ma non so che cosa esattamente – longilong

risposta

9

Dopo qualche tentativo e errore di programmazione, ho potuto risolvere il problema sostituendo le seguenti righe

CGImageRef imageRef = [[ZXImage imageWithMatrix:result] cgimage]; 
    UIImage* uiImage = [[UIImage alloc] initWithCGImage:imageRef]; //<--CRASH 

con

UIImage* uiImage = [[UIImage alloc] initWithCGImage:[[ZXImage imageWithMatrix:result] cgimage]]; 

Eppure, non so perché ?! Sono abbastanza sicuro che qualcosa non è presente nella memoria o forse lo CGImageRef non è pronto se provo a convertirlo in UIImage.

+1

Vedere il collegamento in [commento di pawan] (http://stackoverflow.com/questions/23609593/objective-c-how-to-convert -cgimageref-to-UIImageView # comment36244155_23609593). Credo che abbia la risposta giusta, che ha a che fare con ARC e Ivars. –

1

Il problema è con in [ZXImage imageWithMatrix: risultato], sta creando CGImage e prima di assegnarlo a ZXImage che aumenterà il suo conteggio di mantenimento sta rilasciando il CGImage da CFRelease.

Per risolvere questo problema, sostituire + (ZXImage *) imageWithMatrix: (ZXBitMatrix *) metodo di matrice con implementazione inferiore.

+ (ZXImage *)imageWithMatrix:(ZXBitMatrix *)matrix { 
    int width = matrix.width; 
    int height = matrix.height; 
    int8_t *bytes = (int8_t *)malloc(width * height * 4); 
    for(int y = 0; y < height; y++) { 
     for(int x = 0; x < width; x++) { 
      BOOL bit = [matrix getX:x y:y]; 
      int8_t intensity = bit ? 0 : 255; 
      for(int i = 0; i < 3; i++) { 
       bytes[y * width * 4 + x * 4 + i] = intensity; 
      } 
      bytes[y * width * 4 + x * 4 + 3] = 255; 
     } 
    } 

    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); 
    CGContextRef c = CGBitmapContextCreate(bytes, width, height, 8, 4 * width, colorSpace, kCGBitmapAlphaInfoMask & kCGImageAlphaPremultipliedLast); 

    CGImageRef image = CGBitmapContextCreateImage(c); 


    ZXImage *zxImage = [[ZXImage alloc] initWithCGImageRef:image]; 
    CFRelease(colorSpace); 
    CFAutorelease(image); 
    CFRelease(c); 
    free(bytes); 
    return zxImage; 
} 
2

Per le persone che scrivono Swift, ho riscontrato lo stesso problema descritto da lungo tempo. La risposta è stata nei progetti di esempio dell'obiettivo C di ZXingObjC. Ricorda: questo è solo per generare un codice a barre.

internal func encodeBarcode(){ 
    let writer : ZXMultiFormatWriter! = ZXMultiFormatWriter() 
    var result: ZXBitMatrix! 
    let hint: ZXEncodeHints! = ZXEncodeHints() 

    do { 
     hint.margin = 0 
     result = try writer.encode("Example String", format: kBarcodeFormatAztec, width: 500, height: 500, hints: hint) 

     **let rawBarcode: ZXImage = ZXImage(matrix: result) 
     barcodeUIImage.image = UIImage(CGImage: rawBarcode.cgimage)** 

    } catch { 
     print("failed to generate barcode") 
    } 
}