4

Ok, it appears that the I'm creating a PDFDocument where pixelWidth is incorrect in the images that I created. So the question becomes: How do I get the correct resolution into the image?

I start with bitmap data from a scanner. I'm doing this:

CGDataProviderRef provider= CGDataProviderCreateWithData(NULL (UInt8*)data, bytesPerRow * length, NULL);
CGImageRef cgImg =  CGImageCreate (
    width,
    length,
    bitsPerComponent,
    bitsPerPixel,
    bytesPerRow,
    colorspace,
    bitmapinfo, // ?        CGBitmapInfo bitmapInfo,
    provider,   //? CGDataProviderRef provider,
    NULL, //const CGFloat decode[],
    true, //bool shouldInterpolate,
    kCGRenderingIntentDefault // CGColorRenderingIntent intent
    );
/*  CGColorSpaceRelease(colorspace); */

NSData* imgData = [NSMutableData data];
CGImageDestinationRef dest = CGImageDestinationCreateWithData
    (imgData, kUTTypeTIFF, 1, NULL);
CGImageDestinationAddImage(dest, cgImg, NULL);
CGImageDestinationFinalize(dest);
NSImage* img = [[NSImage alloc] initWithData: imgData];

there doesn't appear to be anywhere in there to include the actual width/height in inches or points, nor the actual resolution, which I DO know at this point... how am I supposed to do this?

Peter Hosey
  • 95,783
  • 15
  • 211
  • 370
Brian Postow
  • 11,709
  • 17
  • 81
  • 125

3 Answers3

7

Hope this will be helpful

size_t bufferLength = width * height * 4;
CGDataProviderRef provider = CGDataProviderCreateWithData(NULL, data, bufferLength, NULL);
size_t bitsPerComponent = 8;
size_t bitsPerPixel = 32;
size_t bytesPerRow = 4 * width;
CGColorSpaceRef colorSpaceRef = CGColorSpaceCreateDeviceRGB();
CGBitmapInfo bitmapInfo = kCGBitmapByteOrderDefault | kCGImageAlphaPremultipliedLast;
CGColorRenderingIntent renderingIntent = kCGRenderingIntentDefault;

CGImageRef iref = CGImageCreate(width, 
                                height, 
                                bitsPerComponent, 
                                bitsPerPixel, 
                                bytesPerRow, 
                                colorSpaceRef, 
                                bitmapInfo, 
                                provider,   // data provider
                                NULL,       // decode
                                YES,        // should interpolate
                                renderingIntent);

_image = [[NSImage alloc] initWithCGImage:iref size:NSMakeSize(width, height)];
Guinzoo
  • 164
  • 1
  • 5
7

If you've got a chunk of data, the easiest way to turn it into an NSImage is to use NSBitmapImageRep. Specifically something like:

NSData * byteData = [NSData dataWithBytes:data length:length];
NSBitmapImageRep * imageRep = [NSBitmapImageRep imageRepWithData:byteData];
NSSize imageSize = NSMakeSize(CGImageGetWidth([imageRep CGImage]), CGImageGetHeight([imageRep CGImage]));

NSImage * image = [[NSImage alloc] initWithSize:imageSize];
[image addRepresentation:imageRep];

...use image
Dave DeLong
  • 242,470
  • 58
  • 448
  • 498
  • 2
    how does imageRepWithData know if the data is color or black and white, or what the hieght and width of the data is? The data is pure bitmap, or pixel data. – Brian Postow Aug 05 '10 at 18:33
  • 1
    Brian Postow: Then you'll need to allocate a bitmap image rep and initialize it using its designated initializer, passing all of the relevant facts (pixels per row, number of rows, bytes per row, etc.) yourself. – Peter Hosey Aug 06 '10 at 05:19
  • 1
    NSBitMapImageRep imageRepWithData will only work if the data is the binary image of a PNG file, or some other know representation. – Glyn Williams Jun 18 '15 at 20:56
0

version with channel not 4:

size_t bufferLength = width * height * channel;
CGDataProviderRef provider = CGDataProviderCreateWithData(NULL, data, bufferLength, NULL);
size_t bitsPerComponent = 8;
size_t bitsPerPixel = bitsPerComponent * channel;
size_t bytesPerRow = channel * width;
CGColorSpaceRef colorSpaceRef = CGColorSpaceCreateDeviceRGB();
CGBitmapInfo bitmapInfo = kCGBitmapByteOrderDefault | kCGImageAlphaPremultipliedLast;
if(channel < 4) {
    bitmapInfo = kCGBitmapByteOrderDefault | kCGImageAlphaNone;
}
CGColorRenderingIntent renderingIntent = kCGRenderingIntentDefault;

CGImageRef iref = CGImageCreate(width, 
                                height, 
                                bitsPerComponent, 
                                bitsPerPixel, 
                                bytesPerRow, 
                                colorSpaceRef, 
                                bitmapInfo, 
                                provider,   // data provider
                                NULL,       // decode
                                YES,        // should interpolate
                                renderingIntent);

_image = [[NSImage alloc] initWithCGImage:iref size:NSMakeSize(width, height)];
andrewchan2022
  • 4,953
  • 45
  • 48