How can I create a CGImageSourceRef from image source data?

How to create CGImageSourceRef

from raw data? I have one file which only consists of image pixel information. I know the resolution and depth, etc. (For example, 640x860, RGB, 8 bit, orientation = 1, DPI = 300). This data is not stored inside the file. As I already wrote, this file only stores the raw pixel information.

Now I tried the following:

NSString *path = @"/Users/.../Desktop/image";
NSData *data = [NSData dataWithContentsOfFile: path];
CFDataRef cfdata = CFDataCreate(NULL, [data bytes], [data length]);
CFDictionaryRef options;
CGImageSourceRef imageSource = CGImageSourceCreateWithData(cfdata, nil);

      

Image is not rendered correctly due to undefined image dimensions. I don't know how to determine the image information (resolution, etc.) for this CFImageSourceRef

. I think I need to initialize CFDictionaryRef options

and deliver it to

CGImageSourceRef imageSource = CGImageSourceCreateWithData(cfdata, options);

      

How do I create CFDictionaryRef

which can be used for a method CGImageSourceCreateWithData

?

+3


source to share


2 answers


You don't want to use CGImageSource

. This is not suitable for raw pixel data. This is for standard image file formats (PNG, GIF, JPEG, etc.). You have to create CGImage

directly using CGImageCreate()

:

NSString *path = @"/Users/.../Desktop/image";
NSData *data = [NSData dataWithContentsOfFile: path];
CGDataProviderRef provider = CGDataProviderCreateWithCFData((__bridge CFDataRef)data);
CGColorSpaceRef colorspace = CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB);
CGImageRef image = CGImageCreate(640, // width
                                 860, // height
                                 8, // bitsPerComponent
                                 32, // bitsPerPixel
                                 4 * 640, // bytesPerRow
                                 colorspace,
                                 kCGImageAlphaNoneSkipFirst, // bitmapInfo
                                 provider,
                                 NULL, // decode
                                 true, // shouldInterpolate
                                 kCGRenderingIntentDefault // intent
                                 );
CGColorSpaceRelease(colorspace);
CGDataProviderRelease(provider);

      



Some of the above ( bitsPerComponent

, bitsPerPixel

, bytesPerRow

, bitmapInfo

) are guesses based on your brief description of your data pixels. If they are incorrect for your data, please adjust them.

You can create a data provider directly from a file using CGDataProviderCreateWithURL()

or CGDataProviderCreateWithFilename()

, but I decided to illustrate more general ways to create one with raw data that can be retrieved from anywhere.

+2


source


I'm not sure if this code will help you, but this is how I create images downloaded from the net. I originally found this code in one of the AFNetworking classes .



- (UIImage *)imageFromResponse:(NSHTTPURLResponse *)response data:(NSData *)data scale:(CGFloat)scale {

    if (!data || [data length] == 0) {
        return nil;
    }

    CGImageRef imageRef = NULL;
    CGDataProviderRef dataProvider = CGDataProviderCreateWithCFData((__bridge CFDataRef)data);

    if ([response.MIMEType isEqualToString:@"image/png"]) {
        imageRef = CGImageCreateWithPNGDataProvider(dataProvider,  NULL, true, kCGRenderingIntentDefault);
    } else if ([response.MIMEType isEqualToString:@"image/jpeg"]) {
        imageRef = CGImageCreateWithJPEGDataProvider(dataProvider, NULL, true, kCGRenderingIntentDefault);

        // CGImageCreateWithJPEGDataProvider does not properly handle CMKY, so if so, fall back to AFImageWithDataAtScale
        if (imageRef) {
            CGColorSpaceRef imageColorSpace = CGImageGetColorSpace(imageRef);
            CGColorSpaceModel imageColorSpaceModel = CGColorSpaceGetModel(imageColorSpace);
            if (imageColorSpaceModel == kCGColorSpaceModelCMYK) {
                CGImageRelease(imageRef);
                imageRef = NULL;
            }
        }
    }

    CGDataProviderRelease(dataProvider);

    UIImage *anImage = [[UIImage alloc] initWithData:data];
    UIImage *image = [[UIImage alloc] initWithCGImage:[anImage CGImage] scale:scale orientation:anImage.imageOrientation];

    if (!imageRef) {
        if (image.images || !image) {
            return image;
        }

        imageRef = CGImageCreateCopy([image CGImage]);
        if (!imageRef) {
            return nil;
        }
    }

    size_t width = CGImageGetWidth(imageRef);
    size_t height = CGImageGetHeight(imageRef);
    size_t bitsPerComponent = CGImageGetBitsPerComponent(imageRef);

    if (width * height > 1024 * 1024 || bitsPerComponent > 8) {
        CGImageRelease(imageRef);

        return image;
    }

    size_t bytesPerRow = 0; // CGImageGetBytesPerRow() calculates incorrectly in iOS 5.0, so defer to CGBitmapContextCreate
    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
    CGColorSpaceModel colorSpaceModel = CGColorSpaceGetModel(colorSpace);
    CGBitmapInfo bitmapInfo = CGImageGetBitmapInfo(imageRef);

    if (colorSpaceModel == kCGColorSpaceModelRGB) {
        uint32_t alpha = (bitmapInfo & kCGBitmapAlphaInfoMask);
        if (alpha == kCGImageAlphaNone) {
            bitmapInfo &= ~kCGBitmapAlphaInfoMask;
            bitmapInfo |= kCGImageAlphaNoneSkipFirst;
        } else if (!(alpha == kCGImageAlphaNoneSkipFirst || alpha == kCGImageAlphaNoneSkipLast)) {
            bitmapInfo &= ~kCGBitmapAlphaInfoMask;
            bitmapInfo |= kCGImageAlphaPremultipliedFirst;
        }
    }

    CGContextRef context = CGBitmapContextCreate(NULL, width, height, bitsPerComponent, bytesPerRow, colorSpace, bitmapInfo);

    CGColorSpaceRelease(colorSpace);

    if (!context) {
        CGImageRelease(imageRef);
        return image;
    }

    CGContextDrawImage(context, CGRectMake(0.0f, 0.0f, width, height), imageRef);
    CGImageRef inflatedImageRef = CGBitmapContextCreateImage(context);

    CGContextRelease(context);

    UIImage *inflatedImage = [[UIImage alloc] initWithCGImage:inflatedImageRef scale:scale orientation:image.imageOrientation];

    CGImageRelease(inflatedImageRef);
    CGImageRelease(imageRef);

    return inflatedImage;
}

      

0


source







All Articles