如何根据从扫描仪接收的数据创建图像

时间:2014-04-04 09:48:32

标签: objective-c cocoa image-capture image-scanner

我在使用NSData记录时从扫描仪接收数据(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 …
>

现在我认为这些是十六进制颜色,逐像素。

与此NSData对象一起,我还会收到图像宽度和高度等信息。

我的问题是如何从这些数据中创建图像(NSImageCGImageRef等...)?我使用了CGImageCreate,但我得到的只是很多噪音。

修改

根据其中一条评论中的要求,她是一张纸(A8)的完整数据,我用6种颜色扫描。

Pastebin of the data and metadata.

在底部还有我从扫描仪收到的其他信息。

我用rgb扫描图像,位深度为8位,分辨率为50ppi。下面是我用另一个应用程序扫描的纸张图像:

enter image description here

使用此代码创建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);

我得到了很多看起来像这样的噪音(对于上面显示的图像):

enter image description here

修改

正如其中一个答案中所建议的那样,我获得的数据大小与此图中所示的元数据相同:

enter image description here

2 个答案:

答案 0 :(得分:1)

我做了一个320 * 320px的测试bmp,添加了红色,绿色和蓝色区域。

enter image description here

在文本编辑器中打开它,并在开头删除元数据。

当我使用此代码时

NSString *imagePath = [[NSBundle mainBundle] pathForResource: @"test3" ofType: @"bmp"];

NSData *data = [NSData dataWithContentsOfFile:imagePath];
CGFloat width = 320.0;
CGFloat height = 320.0;

NSUInteger bitPerByte = 8;
NSUInteger bytePerColor = 3;
NSUInteger len = [data length];

Byte *byteData = (Byte*)malloc(len);
memcpy(byteData, [data bytes], len);


CGDataProviderRef provider = CGDataProviderCreateWithData(NULL,
                                                          byteData,
                                                          width*height*bytePerColor,
                                                          NULL);

CGColorSpaceRef colorSpaceRef = CGColorSpaceCreateDeviceRGB();

CGBitmapInfo bitmapInfo = kCGBitmapByteOrderDefault;

CGImageRef imageRef = CGImageCreate(width,
                                    height,
                                    bitPerByte,
                                    bytePerColor*bitPerByte,
                                    bytePerColor*width,colorSpaceRef,
                                    bitmapInfo,
                                    provider,NULL,NO,0);

红色和蓝色切换

enter image description here

数据看起来像这样

<… 00ff0000 ff0000ff 0000ff00 00ff0000 ff0000ff 0000ff00 00ff0000 ff0000ff 0000ff00 00ff0000 
ff0000ff 0000ff00 00ff0000 ff0000ff 0000ff00 00ff0000 ff0000ff 0000ff00 00ff0000 ff0000ff 
0000ff00 00ff0000 ff0000ff 0000ff00 00ff0000 ff0000ff 0000ff00 00ff0000 ff0000ff 0000ff00
00ff0000 ff0000ff 0000ff00 00ff0000 ff0000ff 0000ff00 00ff0000 ff0000ff 0000ff00 00ff0000
ff0000ff 0000ff00 00ff0000 ff0000ff 0000ff00 00ff0000 ff0000ff 0000ff00 00ff0000 ff0000ff
0000ff00 00ff0000 ff0000ff 0000ff00 00ff0000 ff0000ff 0000ff00 00ff0000 ff0000ff 0000ff00
00ff0000 ff0000ff 0000ff00 00ff0000 ff0000ff 0000ff00 00ff0000 ff0000ff 0000ff00 00ff0000
ff0000ff 0000ff00 00ff0000 ff0000ff 0000ff00 00ff0000 ff0000ff 0000ff00 00ff0000 ff0000ff
0000ff00 00ff0000 ff0000ff 0000ff00 00ff0000 ff0000ff 0000ff00 00ff0000 ffffffff ffffffff
ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff
ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff
ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff
ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff
ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff
ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff
ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff
ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff
ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff
ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff …>

BTW:8字节的摸索与图像中的颜色分量数无关。 NSData不知道它包含哪些数据。这就是它的描述方法显示数据的方式。

一个解决方案是创建一个BGR颜色空间,但我没有这个选项,因为我决定创建一个iOS应用程序,因为我对Mac Cocoa不是很熟悉。

相反,我手动交换红色和蓝色值

// on ios i cannot create a BGR colorspace, there for I swap red and blue values
for (NSUInteger i =2; i < len; i+=3) {
    Byte l = byteData[i-2];
    Byte r = byteData[i];
    byteData[i] = l;
    byteData[i-2] = r;
}

给我以下代码

NSString *imagePath = [[NSBundle mainBundle] pathForResource: @"test3" ofType: @"bmp"];

NSData *data = [NSData dataWithContentsOfFile:imagePath];
CGFloat width = 320.0;
CGFloat height = 320.0;

NSUInteger bitPerByte = 8;
NSUInteger bytePerColor = 3;
NSUInteger len = [data length];

Byte *byteData = (Byte*)malloc(len);
memcpy(byteData, [data bytes], len);

// on ios i cannot create a BGR colorspace, there for I swap red and blue values
for (NSUInteger i =2; i < len; i+=3) {
    Byte l = byteData[i-2];
    Byte r = byteData[i];
    byteData[i] = l;
    byteData[i-2] = r;
}

CGDataProviderRef provider = CGDataProviderCreateWithData(NULL,
                                                          byteData,
                                                          width*height*bytePerColor,
                                                          NULL);

CGColorSpaceRef colorSpaceRef = CGColorSpaceCreateDeviceRGB();

CGBitmapInfo bitmapInfo = kCGBitmapByteOrderDefault;

CGImageRef imageRef = CGImageCreate(width,
                                    height,
                                    bitPerByte,
                                    bytePerColor*bitPerByte,
                                    bytePerColor*width,colorSpaceRef,
                                    bitmapInfo,
                                    provider,NULL,NO,0);

,结果如下:

enter image description here


因为您还没有提供样本数据集,您可能需要调整某些内容,主要是bitPerBytebytePerColor。如果扫描仪添加了一些元数据,您还必须检查。


我不知道为什么,但原始数据阵列的字节数是metada所说的两倍,89352而不是44676.

使用此代码

NSData *data = [NSData dataWithContentsOfFile:imagePath];
CGFloat width = 146.0;
CGFloat height = 102.0;

NSUInteger bitPerByte = 8;
NSUInteger bytePerColor = 2*3;
NSUInteger len = [data length];

Byte *byteData = (Byte*)malloc(len);
memcpy(byteData, [data bytes], len);


CGDataProviderRef provider = CGDataProviderCreateWithData(NULL,
                                                          byteData,
                                                          width*height*bytePerColor,
                                                          NULL);

CGColorSpaceRef colorSpaceRef = CGColorSpaceCreateDeviceRGB();

CGBitmapInfo bitmapInfo = kCGBitmapByteOrder16Big;

CGImageRef imageRef = CGImageCreate(width,
                                    height,
                                    bitPerByte * 2,
                                    bytePerColor*bitPerByte ,
                                    bytePerColor*width ,
                                    colorSpaceRef,
                                    bitmapInfo,
                                    provider,NULL,NO,0);

我能够显示

enter image description here

答案 1 :(得分:0)

在上述答案的帮助下,我设法使它工作,这是我使用的代码:

- (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);
}

问题是我将NSData对象直接放入数据提供者。这为数据提供者提供了内存中与实际原始图像数据相比的其他数据,因此这是图片中的噪声。