2014-05-12 7 views
5

Używam szkieletu XZINGObjC do tworzenia obrazu kodu kreskowego EAN. Po dokumentacji, robię to jakCel C: Jak przekonwertować CGImageRef na 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; 
     } 

To działa, jeśli mogę przejść przez ten kod przy użyciu punktów przerwania! Jednak myślę, że w pewnym momencie Obraz nie jest gotowy do użycia ?! Ale nie mogę znaleźć przyczyny.

Co próbowałem:

  • użyciu imageRef i uiImage jako zmienne lokalne (EXC_BAD_ACCESS CRASH)
  • próbował tej operacji w wątku tła (EXC_BAD_ACCESS CRASH)

samo tutaj, każde rozwiązanie działał, gdy użyłem punktów przerwania i krok po linii przez kod. Jaki jest mój błąd? Jakieś pomysły? Z góry dziękuję!

+1

check to [link referencyjny] (http://stackoverflow.com/questions/12756295/uiimage-from-cgimageref). być może otrzymasz pomoc. – Pawan

+0

Jeśli przechodzisz przez, jaka jest zawartość 'imageRef'? – Sulthan

+0

@pawan: dziękuję, znalazłem, ale to nie rozwiązało mojego problemu @Sulthan: 'imageRef' nie jest zerowy, jeśli masz na myśli, że ... działa tak, jak powinien, jeśli używam punktów przerwania. Więc coś jest już wydane lub nie jest gotowe do użycia, ale nie wiem co dokładnie – longilong

Odpowiedz

9

Po pewnym programowania spróbować i błędów, mogę rozwiązać ten problem przez zastąpienie następujące linie

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

z

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

Still, nie wiem dlaczego ?! Jestem prawie pewien, że coś nie jest w pamięci, a może CGImageRef nie jest gotowy, jeśli próbuję przekonwertować go na UIImage.

+1

Zobacz link w [komentarz pawana] (http://stackoverflow.com/questions/23609593/objective-c-how-to-convert -cgimageref-to-uiimageview # comment36244155_23609593). Uważam, że ma właściwą odpowiedź, która ma związek z ARC i ivars. –

1

Problem dotyczy elementu [ZXImage imageWithMatrix: result], tworzy obraz CG i przed przypisaniem go do ZXImage, który zwiększy jego liczbę zatrzymań, zwalnia CGImage według CFRelease.

Aby naprawić ten problem, należy zastąpić metodę matrycy + (ZXImage *) imageWithMatrix: (ZXBitMatrix *) poniższą implementacją.

+ (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

Dla osób piszących Swift trafiam na ten sam problem, który opisałem na długo. Odpowiedź była w przykładach projektów C zXingObjC. Pamiętaj: służy wyłącznie do generowania kodu kreskowego.

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") 
    } 
}