Objective C: How to convert CGImageRef to UIImageView?
Asked Answered
B

3

6

I'm using the XZINGObjC framework to create an EAN-Barcode-Image. Following the documentation, I'm doing it like

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

It works, if I step through this code using breakpoints! However, I think at some point an Image is not ready for use?! But I cannot find the reason.

What I tried:

  • using imageRef and uiImage as local variables (EXC_BAD_ACCESS CRASH)
  • tried that operation in a background thread (EXC_BAD_ACCESS CRASH)

Same here, every solution worked if I used breakpoints and stepped line by line through the code. What is my mistake here? Any ideas? Thanks in advance!

Bard answered 12/5, 2014 at 12:51 Comment(3)
check this reference link. may be you will get some help.Truman
If you are stepping through, what is the contents of imageRef?Sacks
@pawan: thanks, i found that but it didnt solve my issue @Sulthan: 'imageRef' is not nil if you mean that... it works like it should if I use breakpoints. So something is already released or not ready to use, but I dont know what exactelyBard
B
13

After some try and error programming, I could fix the issue by replacing the following lines

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

with

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

Still, I don't know why?! I'm pretty sure something isn't hold in the memory or maybe the CGImageRef isn't ready if I try to convert it to UIImage.

Bard answered 12/5, 2014 at 13:36 Comment(1)
See the link in pawan’s comment. I believe it has the right answer, which has to do with ARC and ivars.Tinctorial
G
2

Problem is with in [ZXImage imageWithMatrix:result], it is creating CGImage and before assigning it to ZXImage which will increase its retain count it is releasing the CGImage by CFRelease.

To fix this issue, replace + (ZXImage *)imageWithMatrix:(ZXBitMatrix *)matrix method with below implementation.

+ (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;
}
Gemeinschaft answered 13/7, 2014 at 9:26 Comment(0)
F
2

For people writing Swift, I hit the same problem that longilong described. The answer was in the ZXingObjC objective C example projects. Remember: this is for generating a barcode only.

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")
    }
}
Fonville answered 23/12, 2015 at 14:26 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.