Decode static image = Q: How to convert NSBitmapImageRep* to ZXBinaryBitmap* ??

166 views
Skip to first unread message

notarysojac

unread,
Sep 10, 2012, 6:38:34 PM9/10/12
to zx...@googlegroups.com
Hi ZXing Folks, 

It would be great to be able to pass a static image into the ZXing decoder.

At this point I am trying to derive a ZXBinaryBitmap* from an NSImage*.

Does anyone have an idea how best to do that?  

It appears that ZXBinaryBitmap* is not a wrapper for NSBitmapImageRep* so I've it a wall-of-disconnect as per what to do next. 

Ultimately, I'd like to be able to do something like what is shown below...   


- (void) decodeStaticImage:(NSBitmapImageRep*) inBitmap

    {      
   
ZXBinaryBitmap* zxbitmap = [someZXobject convert: inBitmap];
   
ZXDecodeHints*  hints    = [[[ZXDecodeHints alloc] init] autorelease];
    ZXQRCodeReader* reader   = [[[ZXQRCodeReader alloc] init] autorelease];
    ZXResult* result         = [reader decode:zxbitmap hints:hints];
    [captureDelegate captureResult:self result:result];
    }



notarysojac

unread,
Sep 10, 2012, 9:52:15 PM9/10/12
to zx...@googlegroups.com

Well -- who knows if this'll be of value to anyone - but here it is... 

// ----------------------------------------------------------------------------------------------

- (CGImageRef) makeCGImageFromNSImage:(NSImage*) inImage

       {

       CGImageRef              result;

       NSData*                 imagedata       = [inImage TIFFRepresentation];

       NSBitmapImageRep*       bitmaprep       = [[NSBitmapImageRep imageRepWithData:imagedata] retain];

       size_t                 rowBytes         = [bitmaprep bytesPerRow];

       size_t                 wid              = [bitmaprep pixelsWide];

       size_t                 hgt              = [bitmaprep pixelsHigh];

       size_t                 bpp              = [bitmaprep bitsPerPixel];

       size_t                  spp             = [bitmaprep samplesPerPixel];

       CGDataProviderRef       provider        = CGDataProviderCreateWithCFData((CFDataRef)imagedata);

       CGColorSpaceRef         colorspace      = CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB);

       CGBitmapInfo            bitsInfo        = kCGImageAlphaLast;

                               result          = CGImageCreate(wid,hgt,spp,bpp,rowBytes,                                                                                            
                                                               colorspace,bitsInfo,provider,NULL,NO,                                                                                                        
                                                               kCGRenderingIntentDefault);

       CGDataProviderRelease(provider);

       CGColorSpaceRelease(colorspace);

       return(result);

       }

//==========================================

- (void) decodeStaticImage:(NSImage*) inImage

       {

       NSLog(@"ZXCapture::decodeStaticImage - ENTER");

       CGImageRef cgImage = [self makeCGImageFromNSImage:inImage];

       ZXCGImageLuminanceSource* source = [[ZXCGImageLuminanceSource alloc] initWithCGImage:cgImage]

       ZXHybridBinarizer* binarizer = [ZXHybridBinarizer alloc];

       [[binarizer initWithSource:source] autorelease];

       ZXBinaryBitmap* bitmap  = [[[ZXBinaryBitmap alloc] initWithBinarizer:binarizer] autorelease];

       @try

           {


           
ZXDecodeHints*  hints  = [[[ZXDecodeHints alloc] init] autorelease];

           ZXQRCodeReader* reader = [[[ZXQRCodeReader alloc] init] autorelease];

           ZXResult* result = [reader decode:bitmap hints:hints];

           [captureDelegate captureResult:self result:result];

           }

       @catch (ZXReaderException* rex)

          {

          NSLog(@"ERROR ZXCapture::decodeStaticImage - failed to decode, caught ReaderException [%@]",
                rex
.
reason);

          }

       @catch (ZXIllegalArgumentException* iex)

        {

        NSLog(@"ERROR ZXCapture::decodeStaticImage - failed to decode, caught IllegalArgumentException '%@'",
iex
.
reason);


                }


               


        @catch (id ue)


                {


                NSLog(@"ERROR ZXCapture::decodeStaticImage - Caught unknown exception: %@", ue);


                }


        }



Steven Parkes

unread,
Sep 10, 2012, 9:55:37 PM9/10/12
to notarysojac, zx...@googlegroups.com
On Sep 10, 2012, at 3:38 PM, notarysojac <hydrat...@gmail.com> wrote:

> At this point I am trying to derive a ZXBinaryBitmap* from an NSImage*.

I think you want to use NSImage's

- (CGImageRef)CGImageForProposedRect:(NSRect *)proposedDestRect context:(NSGraphicsContext *)referenceContexthints:(NSDictionary *)hints

This will return a CGImageRef and you can create a ZXCGImageLuminanceSource from that.

notarysojac

unread,
Sep 10, 2012, 11:13:43 PM9/10/12
to zx...@googlegroups.com, notarysojac
Hi Steven -   

Well yeah... that is simpler - I did not know that call would do the trick - but, if you say so - that's cool.  Actually, I did see that call in the API - but the contents of what might need to be included in the referenceContexthints dictionary and whatever should be the size of the proposedDestRect introduced F.U.D. into the equation - so I did a hand-wrought build on the CGImageRef.  

Interestingly, the static image decode worked well on images created with 'code'... like this: 

but did not work on this image taken with the camera in my iPhone....



BTW - The error reported was that it could not locate the three corners.  I would be interested to hear what you think might be the scoop.  

Anyway - the ZXing code is remarkably robust and capable - it's quite a pleasure to be working with it.  Thanks... 

Steven Parkes

unread,
Sep 10, 2012, 11:29:25 PM9/10/12
to notarysojac, zx...@googlegroups.com
> I did not know that call would do the trick - but, if you say so - that's cool.

Just something I found on SO; no personal experience. I don't do much with AppKit but I've done similar things with UIKit. That's why I put the CGImage interfaces in there, because CoreGraphics is on both OS X and iOS.

> BTW - The error reported was that it could not locate the three corners. I would be interested to hear what you think might be the scoop.

Yeah, I don't know what's going on here. The standard answer is "not every image decodes" but that image does decode with Java, just not with C++. I'll give a shot at trying to figure out what's going on but I can't make any promises.

notarysojac

unread,
Sep 11, 2012, 9:53:02 AM9/11/12
to zx...@googlegroups.com, notarysojac
Hi Steven - Thanks for taking a look at what's the scoop with that image.  I found that using the 'Barcodes' app and shooting that barcode off of my computer screen allowed it to be decoded - whereas sending it directly in as an image did not work with the '3 corners not found' error.   Again - thanks for your interest.   

Also, FYI, here's what comes back (and is correct) when the image in question is decoded:  


Steven Parkes

unread,
Sep 11, 2012, 10:40:54 AM9/11/12
to notarysojac, zx...@googlegroups.com
> I found that using the 'Barcodes' app and shooting that barcode off of my computer screen allowed it to be decoded - whereas sending it directly in as an image did not work with the '3 corners not found' error.

That's not uncommon. Lots of images don't decode, for various reasons. ZXing is targeted at live scans from phones so the heuristic development hasn't focused on making every image decode.

However, the Java and C++ ports should be in parity (at least for QR codes) and since this image decodes in Java but not C++, that indicates there's a difference between the two that should be corrected.

Steven Parkes

unread,
Oct 29, 2012, 4:40:09 PM10/29/12
to notarysojac, zx...@googlegroups.com
I can't replicate this at this point. The synthetic image doesn't decode with either Java or C++ but the captured image decodes with both.

I didn't try any hints, etc. We know there are images that the algorithms don't decode. I saved this to look at primarily because I wanted to check the Java vs. C++ results.

On Sep 10, 2012, at 8:13 PM, notarysojac <hydrat...@gmail.com> wrote:

> Hi Steven -
>
> Well yeah... that is simpler - I did not know that call would do the trick - but, if you say so - that's cool. Actually, I did see that call in the API - but the contents of what might need to be included in the referenceContexthints dictionary and whatever should be the size of the proposedDestRect introduced F.U.D. into the equation - so I did a hand-wrought build on the CGImageRef.
>
> Interestingly, the static image decode worked well on images created with 'code'... like this:
>
>
>
> but did not work on this image taken with the camera in my iPhone....
>
>
>
>
>
>
> BTW - The error reported was that it could not locate the three corners. I would be interested to hear what you think might be the scoop.
>
> Anyway - the ZXing code is remarkably robust and capable - it's quite a pleasure to be working with it. Thanks...
>
> --
>
>
>

Reply all
Reply to author
Forward
0 new messages