目标C:如何将CGImageRef转换为UIImageView?

时间:2014-05-12 12:51:45

标签: objective-c uiimage exc-bad-access cgimageref

我正在使用XZINGObjC框架来创建EAN-Barcode-Image。在文档之后,我就像

一样
 //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;   
      }

如果我使用断点逐步执行此代码,它可以工作!但是,我认为在某些时候图像还没有准备好使用?!但我找不到原因。

我尝试了什么:

  • 使用imageRefuiImage作为局部变量(EXC_BAD_ACCESS CRASH)
  • 在后台线程中尝试该操作(EXC_BAD_ACCESS CRASH)

同样,如果我使用断点并逐行逐步执行代码,每个解决方案都有效。这里我的错误是什么?有任何想法吗?提前谢谢!

3 个答案:

答案 0 :(得分:11)

经过一些尝试和错误编程后,我可以通过替换以下行来解决问题

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

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

仍然,我不知道为什么?!我很确定内存中没有内容,或者如果我尝试转换,CGImageRef可能还没有准备就绪它到UIImage

答案 1 :(得分:2)

问题出在[ZXImage imageWithMatrix:result]中,它正在创建CGImage,在将它分配给ZXImage之前会增加其保留计数,它会通过CFRelease释放CGImage。

要解决此问题,请将+(ZXImage *)imageWithMatrix:(ZXBitMatrix *)矩阵方法替换为以下实现。

+ (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 :(得分:2)

对于编写Swift的人来说,我遇到了龙陇描述的同样问题。答案是在ZXingObjC目标C示例项目中。请记住:这仅用于生成条形码。

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