Search code examples
objective-ccocoaimage-captureimage-scanner

How to create an image from data received from scanner


I receive data (NSData) from the scanner that looks something like this when logged with NSLog:

2014-04-07 10:42:07.309 Pantelegraph[488:303] <
4c9d8f4d 9f9849a2 9a4fa79f 46a8984d a9a346aa 9f53aea0 50ad884d aa9354b4
9251b291 54b18f54 b28e47b3 9254b396 49af8d4f b3834fb1 904fb488 59b7874f
b38a4cb2 8551b186 4ab78556 b4884cb1 894eb180 59b17d4e b37b57b2 754fb386
56b98453 b38449b1 794fb37b 49ae8852 b08253ac 8652af80 58b18552 b08850b2
8856b086 51b08a51 ad9656ad 8d4fb091 50ab934c ab9753af 9a4aae9a 54af9c53
ae9c49b0 a451afa5 4faba450 aea54eae aa4db0a3 57b0a24e aea34caf a74eafa2
49b09b51 afa448ae a152b0a1 51aca147 aea44db3 9851b0a3 4ab49d50 b09d49b3
924fb198 49af964e b29553b1 8e50b294 52b6874b b18d50b2 944eb48d 49b28a56
b3844aae 934fb485 53af884d b08356b0 814eac84 52b37754 b08650ae 7d57b081
57ae8752 ac8356a9 9150ae8a 52af7f52 ac8e51ac 8554ad8e 44ae9851 ad9c55af
9d54b095 56ae9a52 afa052ae a150aca4 51aba74c aaa34eac a453aea7 4bafa254
af9c4fac a150b29a 54aea652 af9d4db0 9e4eb195 4eaf9454 af974caf 884eb086
54a98750 ad8d51ad 8249ac85 51ab7750 ad7951ae 8453ab80 4cac8553 …
>

Now I think those are hexadecimal colors, pixel by pixel.

Together with this NSData object I also receive information like the width and height of the image.

My question is how can I create an image (NSImage, CGImageRef, etc…) from this data? I used CGImageCreate but all I got from that is a lot of noise.

Edit

As requested in one of the comments her is the full data of an piece of paper (A8) I scanned with 6 colors on it.

Pastebin of the data and metadata.

At the bottom there is also the other information I received from the scanner.

I scanned the image in rgb with a bit depth of 8 bits and a resolution of 50ppi. Below is an image of the paper I scanned with another application:

enter image description here

When using this code to create a CGImageRef:

CGDataProviderRef provider = CGDataProviderCreateWithData(NULL, (__bridge const void *)([data dataBuffer]), [data dataSize], NULL);
    CGImageRef image = CGImageCreate([data fullImageWidth], [data fullImageHeight], [data bitsPerComponent], [data bitsPerPixel], [data bytesPerRow], CGColorSpaceCreateDeviceRGB(), kCGBitmapByteOrderDefault|kCGImageAlphaNone, provider, NULL, false, kCGRenderingIntentDefault);

I get a lot of noise that looks like this (for the image shown above) :

enter image description here

Edit

As suggested in one of the answers, the size of the data I get is the same as what the metadata says as seen in this picture:

enter image description here


Solution

  • With the help of the above answer I managed to make it work, this is the code I used:

    - (void)scannerDevice:(ICScannerDevice *)scanner didScanToBandData:(ICScannerBandData *)data {
        CGColorSpaceRef color = CGColorSpaceCreateDeviceGray();
        if ([data pixelDataType] == ICScannerPixelDataTypeRGB) color = CGColorSpaceCreateDeviceRGB();
        CGDataProviderRef provider = CGDataProviderCreateWithCFData(CFDataCreate(NULL, [[data dataBuffer] bytes], [data dataSize]));
        CGImageRef image = CGImageCreate([data fullImageWidth], [data fullImageHeight], [data bitsPerComponent], [data bitsPerPixel], [data bytesPerRow], color, kCGBitmapByteOrderDefault|kCGImageAlphaNone, provider, NULL, false, kCGRenderingIntentDefault);
    
        NSImage *finImage = [[NSImage alloc] initWithCGImage:image size:NSMakeSize([data fullImageWidth], [data fullImageHeight])];
        CGImageRelease(image);
        CGDataProviderRelease(provider);
        CGColorSpaceRelease(color);
    }
    

    The problem was that I'm putting the NSData object straight into the data provider. This gives the data provider other data in your memory than the actual raw image data, so that's the noise in the picture.