Как создать CGImageSourceRef из необработанных данных изображения?
Как создать CGImageSourceRef
из необработанных данных? У меня есть один файл, который состоит только из информации о пикселях изображения. Я знаю разрешение и глубину и так далее (например, 640x860, RGB, 8bit, ориентация = 1, DPI = 300). Эта информация не хранится внутри файла. Как я уже писал, этот файл просто хранит необработанную информацию о пикселях.
Теперь я попробовал следующее:
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);
Изображение не создано правильно из-за неопределенных размеров изображения. Я понятия не имею, как определить информацию об изображении (разрешение и т. Д.) Для этого CFImageSourceRef
, Думаю, я должен инициализировать CFDictionaryRef options
и доставить его
CGImageSourceRef imageSource = CGImageSourceCreateWithData(cfdata, options);
Как я могу создать CFDictionaryRef
что это пригодно для метода CGImageSourceCreateWithData
?
2 ответа
Вы не хотите использовать CGImageSource
, Это не подходит для необработанных данных пикселей. Это для стандартных форматов файлов изображений (PNG, GIF, JPEG и т. Д.). Вы должны создать CGImage
напрямую используя 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);
Некоторые из вышеперечисленных (bitsPerComponent
, bitsPerPixel
, bytesPerRow
, bitmapInfo
) предположения, основанные на вашем кратком описании ваших данных пикселей. Если они не соответствуют вашим данным, настройте их.
Вы можете создать поставщика данных непосредственно из файла, используя CGDataProviderCreateWithURL()
или же CGDataProviderCreateWithFilename()
, но я решил проиллюстрировать более общие способы его создания с необработанными данными, которые могут поступать откуда угодно.
Я не уверен, может ли этот код помочь вам, но таким образом я создаю изображения, загруженные из сети. Первоначально я нашел этот код в одном из классов AFNetworking.
- (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;
}