iPhone: изменение CGImageAlphaInfo для CGImage

У меня есть изображение PNG с неподдерживаемым форматом пикселей контекста растровой графики. Каждый раз, когда я пытаюсь изменить размер изображения, CGBitmapContextCreate() подавляется неподдерживаемым форматом

Я получаю следующую ошибку (ошибка отформатирована для облегчения чтения):

CGBitmapContextCreate: unsupported parameter combination: 
    8 integer bits/component; 
    32 bits/pixel; 
    3-component colorspace; 
    kCGImageAlphaLast; 
    1344 bytes/row.

список поддерживаемых форматов пикселей определенно не поддерживает эту комбинацию. Похоже, мне нужно перерисовать изображение и переместить информацию об альфа-канале в kCGImageAlphaPremultipliedFirst или kCGImageAlphaPremultipliedLast.

Я понятия не имею, как это сделать.

В файле PNG нет ничего необычного и он не поврежден. Он отлично работает во всех остальных случаях. Я столкнулся с этой ошибкой случайно, но, очевидно, мои пользователи могли иметь файлы с аналогичным форматированием, поэтому мне придется проверить импортированные изображения моего приложения и исправить эту проблему.


person TechZen    schedule 16.03.2010    source источник


Ответы (2)


Да, у меня были проблемы с 8-битными (индексированными) .PNG. Мне пришлось преобразовать его в более родной образ для выполнения графических операций. По сути, я сделал что-то вроде этого:

- (UIImage *) normalize {

    CGColorSpaceRef genericColorSpace = CGColorSpaceCreateDeviceRGB();
    CGContextRef thumbBitmapCtxt = CGBitmapContextCreate(NULL, 
                                                         self.size.width, 
                                                         self.size.height, 
                                                         8, (4 * self.size.width), 
                                                         genericColorSpace, 
                                                         kCGImageAlphaPremultipliedFirst);
    CGColorSpaceRelease(genericColorSpace);
    CGContextSetInterpolationQuality(thumbBitmapCtxt, kCGInterpolationDefault);
    CGRect destRect = CGRectMake(0, 0, self.size.width, self.size.height);
    CGContextDrawImage(thumbBitmapCtxt, destRect, self.CGImage);
    CGImageRef tmpThumbImage = CGBitmapContextCreateImage(thumbBitmapCtxt);
    CGContextRelease(thumbBitmapCtxt);    
    UIImage *result = [UIImage imageWithCGImage:tmpThumbImage];
    CGImageRelease(tmpThumbImage);

    return result;    
}
person Alfons    schedule 20.03.2010
comment
Выглядит хорошо, попробую. Я ненавижу много обрабатывать, потому что боюсь, что непреднамеренно нарушу верность. - person TechZen; 21.03.2010
comment
Я наконец-то приступил к тестированию, и он отлично работает без заметной потери точности. - person TechZen; 26.03.2010
comment
У меня проблема с приведенным выше кодом, когда imageOrientation UIImage не является OrientationUp - это приводит к повороту изображения. Границы изображения остаются прежними, но пиксели внутри изображения поворачиваются и растягиваются, чтобы соответствовать исходным границам. Это похоже на то, что описано в: stackoverflow.com/questions/5973105/, но в этом случае проблема возникает из-за функции нормализации. Кто-нибудь еще это видел? Какое-нибудь исправление для этого? - person kurtzmarc; 03.10.2011
comment
Код ничего не предполагает об ориентации: информация об ориентации не сохраняется в UIImage. (Вы должны обработать ориентацию перед преобразованием изображения в UIImage.) - person Alfons; 17.10.2011
comment
см. мой ответ на этот вопрос неподдерживаемая комбинация параметров stackoverflow.com/questions/5545600/ - person unsynchronized; 24.10.2011
comment
Это дает гораздо лучшие результаты, чем метод, который я использовал, спасибо. - person Echilon; 09.09.2012

Вот обновленная версия метода из ответа Альфонса для учета масштаба экрана, а также некоторые глупые ошибки с десятичными знаками в значениях с плавающей запятой размера изображения, как описано в несинхронизированном комментарии к исходному ответу.

SCREEN_SCALE - это макрос, который возвращает либо 1.0, если масштаб не определен, либо независимо от фактического масштаба устройства ([UIScreen mainScreen] .scale).

- (UIImage *) normalize {

    CGSize size = CGSizeMake(round(self.size.width*SCREEN_SCALE), round(self.size.height*SCREEN_SCALE));
    CGColorSpaceRef genericColorSpace = CGColorSpaceCreateDeviceRGB();
    CGContextRef thumbBitmapCtxt = CGBitmapContextCreate(NULL, 
                                                         size.width, 
                                                         size.height, 
                                                         8, (4 * size.width), 
                                                         genericColorSpace, 
                                                         kCGImageAlphaPremultipliedFirst);
    CGColorSpaceRelease(genericColorSpace);
    CGContextSetInterpolationQuality(thumbBitmapCtxt, kCGInterpolationDefault);
    CGRect destRect = CGRectMake(0, 0, size.width, size.height);
    CGContextDrawImage(thumbBitmapCtxt, destRect, self.CGImage);
    CGImageRef tmpThumbImage = CGBitmapContextCreateImage(thumbBitmapCtxt);
    CGContextRelease(thumbBitmapCtxt);    
    UIImage *result = [UIImage imageWithCGImage:tmpThumbImage scale:SCREEN_SCALE orientation:UIImageOrientationUp];
    CGImageRelease(tmpThumbImage);

    return result;    
}
person psy    schedule 20.02.2012