Цель C: Как преобразовать CGImageRef в UIImageView?

Я использую структуру 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;   
      }

Это работает, если я выполняю этот код с помощью точек останова! Однако я думаю, что в какой-то момент изображение не готово к использованию?! Но не могу найти причину.

Что я пробовал:

  • использование imageRef и uiImage в качестве локальных переменных (EXC_BAD_ACCESS CRASH)
  • попробовал эту операцию в фоновом потоке (EXC_BAD_ACCESS CRASH)

То же самое здесь, каждое решение работало, если бы я использовал точки останова и шаг за шагом выполнял код. В чем здесь моя ошибка? Есть идеи? Заранее спасибо!


person longi    schedule 12.05.2014    source источник
comment
проверьте эту ссылку. может быть, вы получите некоторую помощь.   -  person Pawan Rai    schedule 12.05.2014
comment
Если вы проходите, каково содержимое imageRef?   -  person Sulthan    schedule 12.05.2014
comment
@pawan: спасибо, я нашел это, но он не знал, что именно   -  person longi    schedule 12.05.2014


Ответы (3)


После некоторых попыток и ошибок программирования я мог решить проблему, заменив следующие строки

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

с участием

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

Тем не менее, я не знаю почему?! Я почти уверен, что что-то не хранится в памяти или, возможно, CGImageRef не готово, если я попытаюсь преобразовать его в UIImage.

person longi    schedule 12.05.2014
comment
См. ссылку в комментарии pawan. Я считаю, что у него есть правильный ответ, который связан с ARC и иварами. - person Zev Eisenberg; 12.05.2014

Проблема заключается в том, что в [ZXImage imageWithMatrix:result] создается CGImage, и перед тем, как назначить его ZXImage, что увеличит количество сохранений, он выпускает CGImage с помощью CFRelease.

Чтобы устранить эту проблему, замените метод + (ZXImage *)imageWithMatrix:(ZXBitMatrix *)matrix приведенной ниже реализацией.

+ (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;
}
person Atif Khan    schedule 13.07.2014

Для людей, пишущих Swift, я столкнулся с той же проблемой, которую описал longilong. Ответ был в примерах проектов 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")
    }
}
person rustyMagnet    schedule 23.12.2015