Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Objective C: How to convert CGImageRef to UIImageView?

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!

like image 795
longi Avatar asked May 12 '14 12:05

longi


People also ask

What is the difference between UIImage and UIImageView?

UIImage contains the data for an image. UIImageView is a custom view meant to display the UIImage .

How do you declare UIImage in Objective C?

For example: UIImage *img = [[UIImage alloc] init]; [img setImage:[UIImage imageNamed:@"anyImageName"]]; My UIImage object is declared in .

What is a CIImage?

A CIImage is a immutable object that represents an image. It is not an image. It only has the image data associated with it. It has all the information necessary to produce an image. You typically use CIImage objects in conjunction with other Core Image classes such as CIFilter, CIContext, CIColor, and CIVector.


3 Answers

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.

like image 120
longi Avatar answered Sep 22 '22 08:09

longi


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;
}
like image 35
Atif Khan Avatar answered Sep 21 '22 08:09

Atif Khan


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")
    }
}
like image 22
rustyMagnet Avatar answered Sep 21 '22 08:09

rustyMagnet