zxingify / zxingify-objc

An Objective-C Port of ZXing
Apache License 2.0
3.06k stars 752 forks source link

Incorrect capture's scanRect #433

Closed neacao closed 5 years ago

neacao commented 5 years ago

Seems like crop before rotate will return wrong scan view frame, as you can see below, the second image show correct cropped area on the thumbnail view.

Crop then rotate img_0658

Rotate then crop img_0657

benjohnde commented 5 years ago

Can you show me the code you are using to display the scanning rectangle?

I believe you are using lastScannedImage?

neacao commented 5 years ago

@benjohnde yes, i was displaying lastScannedImage, is it correct ?

ZXCapture.m

-(void)captureOutput: ... {
...
    CGImageRef rotatedImage = [self createRotatedImage:videoFrameImage degrees:self.rotation];
    CGImageRelease(videoFrameImage);
    self.lastScannedImage = rotatedImage;

    [self.delegate willProcessImage: self.lastScannedImage];
...
}

ViewController.m

-(void)viewDidLoad {
...
    _thumbnailView = [[UIImageView alloc] initWithFrame: CGRectMake(20, 20, 100, 100)];
    _thumbnailView.contentMode = UIViewContentModeScaleAspectFit;
    _thumbnailView.backgroundColor = [UIColor brownColor];
    [self.view addSubview: _thumbnailView];
...
}

#pragma mark - ZXCaptureDelegate Methods

-(void)willProcessImage:(CGImageRef)image {
    dispatch_async(dispatch_get_main_queue(), ^{
        UIImage *img = [UIImage imageWithCGImage: image];
        dispatch_async(dispatch_get_main_queue(), ^{
            self.thumbnailView.image = img;
        });
    });
}
neacao commented 5 years ago

Fore more information, both of luminanceLayer & my custom code return same result of incorrect scan rect

img_0664

benjohnde commented 5 years ago

Yeah that is basically correct, weird.

I don't see a false note in the code.

In ZXCapture.m:

      // If scanRect is set, crop the current image to include only the desired rect
      if (!CGRectIsEmpty(self.scanRect)) {
        CGImageRef croppedImage = CGImageCreateWithImageInRect(videoFrameImage, self.scanRect);
        CGImageRelease(videoFrameImage);
        videoFrameImage = croppedImage;
      }

      CGImageRef rotatedImage = [self createRotatedImage:videoFrameImage degrees:self.rotation];
      CGImageRelease(videoFrameImage);
      self.lastScannedImage = rotatedImage;
neacao commented 5 years ago

@benjohnde seem likes this relates to #222

benjohnde commented 5 years ago

Hmm you mean the small overlay (brighter area) does not match with the result thumbnail?

benjohnde commented 5 years ago

Because that is independent from ZXCapture.

neacao commented 5 years ago

That's true, should the BarcodeScanner to be updated to correct the scan view frame ?

benjohnde commented 5 years ago

Yeap, but as the BarcodeScanner should be rewritten in Swift, I wont fix it as of now

benjohnde commented 5 years ago

You can give it a try 🚀 🎉 :)

neacao commented 5 years ago

@benjohnde to solve this one, the transformVideoRect have to be converted from portrait to landscape if needed. Sample code:

// Correct video frame under Portrait mode cuz the framework will crop before rotate
CGPoint scanPoint = CGPointMake(
  transformedVideoRect.origin.y, 
  self.view.frame.size.width - transformedVideoRect.size.width - transformedVideoRect.origin.x);

CGSize scanSize = CGSizeMake(
  transformedVideoRect.size.height, 
  transformedVideoRect.size.width);

transformedVideoRect = CGRectMake(scanPoint.x, scanPoint.y, scanSize.width, scanSize.height);
benjohnde commented 5 years ago

Do you want to hand-in a pull request? :)

neacao commented 5 years ago

Sure, I will

neacao commented 5 years ago

PR #444 is ready