Установка размеров UIImage на изображении UITableViewCell

У меня есть стандартный UITableViewCell, где я использую свойства текста и изображения для отображения favicon.ico и метки. По большей части это работает очень хорошо, поскольку UIImage поддерживает формат ICO. Однако на некоторых сайтах (например, Amazon.com есть favicon.icos, которые используют возможности формата ICO для хранения нескольких размеров в одном файле. Amazon хранит четыре разных размера, вплоть до 48x48.

Это приводит к тому, что большинство изображений имеют размер 16x16, за исключением некоторых, которые имеют размер 32x32 или 48x48 и заставляют все выглядеть ужасно. Я безуспешно искал здесь, на официальном форуме, в документации и в других местах. Я перепробовал все, что мог придумать, чтобы ограничить размер изображения. Единственное, что сработало, - это недокументированный метод, которым я не собираюсь пользоваться. Это мое первое приложение и мой первый опыт работы с Какао (пришло из C #).

В случае, если я не совсем понял, что ищу, в идеале совет будет сосредоточен вокруг установки размеров UIImage, чтобы версия 48x48 масштабировалась до 16x16, или метода, сообщающего UIImage использовать версию 16x16, присутствующую в файл ICO. Мне не обязательно нужен код: мне достаточно простого предложения подхода.

У кого-нибудь есть предложения? (Я также спросил на официальном форуме , потому что потратил больше суток на это уже. Если решение опубликовано там, я также помещу его сюда.)


person bbrown    schedule 02.06.2009    source источник


Ответы (6)


Вот что пользователь "bcd" на официальных форумах разместил, что в конечном итоге решило проблему ( с небольшой модификацией, сделанной мной, чтобы сделать его статическим для включения в набор служебных методов):

+ (UIImage *)scale:(UIImage *)image toSize:(CGSize)size
{
    UIGraphicsBeginImageContext(size);
    [image drawInRect:CGRectMake(0, 0, size.width, size.height)];
    UIImage *scaledImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    return scaledImage;
}
person bbrown    schedule 02.06.2009
comment
Версия BCD была категорией на UIImage, что имеет гораздо больше смысла, чем то, что я сделал здесь. - person bbrown; 03.06.2009

Я делаю нечто подобное в своем приложении.

    UIImage* resizedImage(UIImage *inImage, CGRect thumbRect)
{
    CGImageRef          imageRef = [inImage CGImage];
    CGImageAlphaInfo    alphaInfo = CGImageGetAlphaInfo(imageRef);

    if (alphaInfo == kCGImageAlphaNone)
        alphaInfo = kCGImageAlphaNoneSkipLast;

    CGContextRef bitmap = CGBitmapContextCreate (NULL, thumbRect.size.width, thumbRect.size.height, 8, thumbRect.size.width*3, 
                                                                                 CGColorSpaceCreateDeviceRGB(), alphaInfo);

    CGContextDrawImage(bitmap, thumbRect, imageRef);

    CGImageRef  ref = CGBitmapContextCreateImage(bitmap);
    UIImage*    result = [UIImage imageWithCGImage:ref];

    CGContextRelease(bitmap);
    CGImageRelease(ref);

    return result;
}

Затем создайте новое изображение, ограничивая пропорции. Замена «изображения» на файл ICO, полученный от Amazon.

CGRect sz = CGRectMake(0.0f, 0.0f, 16, 16);
UIImage *resized = resizedImage(image, sz);
person Brandon Schlenker    schedule 02.06.2009
comment
По какой-то причине ваш код вызывал у меня много ошибок CoreGraphics. Это может быть проблема с форматом ICO. Хотя это хороший ответ. - person bbrown; 03.06.2009
comment
Были ли они ошибки компиляции / компоновки? Я не думаю, что Xcode по умолчанию ссылается на структуру CoreGraphics для новых проектов, поэтому вам нужно будет добавить это и соответствующий оператор @import. - person Daniel Dickison; 03.06.2009
comment
Да, вам нужна ссылка на фреймворк CoreGraphics. Если бы вы этого не сделали, вы бы получили эти ошибки. - person Brandon Schlenker; 03.06.2009
comment
Ваши байты на строку неверны, как указал crafterm в своем комментирующем ответе. См. Подробности в моем комментарии к этому ответу, но вам следует умножать ширину на 4, а не на 3. - person Peter Hosey; 21.03.2010

У меня еще недостаточно кармы, чтобы комментировать ответы, но у меня был хороший успех с кодом bbrandons, приведенным выше.

Я получил на консоли изрядное количество предупреждений о том, что значение параметра байтов на строку недостаточно велико - после прочтения ответов на этот post В итоге я установил его на 0, что позволяет системе определять правильное значение.

eg:

CGContextRef bitmap = CGBitmapContextCreate(NULL, size.width, size.height, 8, 0, CGColorSpaceCreateDeviceRGB(), alphaInfo);
person crafterm    schedule 21.03.2010
comment
Если вы заявили 8 бит на компонент, это 1 байт на компонент. Ответ Брэндона предотвращает kCGImageAlphaNone, поэтому для цветового пространства RGB всегда есть четыре компонента (три цвета плюс альфа). Это 1 × 4 = 4 байта на пиксель. Таким образом, он и вы должны умножать ширину (пикселей в строке) на 4, а не на 3. Передача 0 не документирована для работы, поэтому вам, вероятно, не следует полагаться на это и не следует использовать этот трюк или записать ошибка документации, требующая документирования: bugreport.apple.com - person Peter Hosey; 21.03.2010
comment
Спасибо за описание вычислений, Питер, имеет смысл - я также запишу ошибку в документации для автоматического расчета. - person crafterm; 24.03.2010

Вот как я это сделал. Этот метод заботится о перемещении текста и детальных текстовых меток влево:

@interface SizableImageCell : UITableViewCell {}
@end
@implementation SizableImageCell
- (void)layoutSubviews {
    [super layoutSubviews];

    float desiredWidth = 80;
    float w=self.imageView.frame.size.width;
    if (w>desiredWidth) {
        float widthSub = w - desiredWidth;
        self.imageView.frame = CGRectMake(self.imageView.frame.origin.x,self.imageView.frame.origin.y,desiredWidth,self.imageView.frame.size.height);
        self.textLabel.frame = CGRectMake(self.textLabel.frame.origin.x-widthSub,self.textLabel.frame.origin.y,self.textLabel.frame.size.width+widthSub,self.textLabel.frame.size.height);
        self.detailTextLabel.frame = CGRectMake(self.detailTextLabel.frame.origin.x-widthSub,self.detailTextLabel.frame.origin.y,self.detailTextLabel.frame.size.width+widthSub,self.detailTextLabel.frame.size.height);
        self.imageView.contentMode = UIViewContentModeScaleAspectFit;
    }
}
@end

...

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    static NSString *CellIdentifier = @"Cell";

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    if (cell == nil) {
        cell = [[[SizableImageCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier] autorelease];
        cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
    }

    cell.textLabel.text = ...
    cell.detailTextLabel.text = ...
    cell.imageView.image = ...
    return cell;
}
person Chris    schedule 21.04.2011

Я ничего не знаю о том, как работают файлы ico, поэтому, возможно, можно легко извлечь изображение 16x16 и использовать его, но я понятия не имею, как.

Насколько мне известно, невозможно установить какие-либо полезные свойства изображения в общем UITableViewCell. Самый простой способ (все еще беспорядочный, особенно если вы новичок) уменьшить все до 16x16 - это создать подкласс UITableViewCell, присвоить ему UIImageView, всегда изменять размер изображения до 16x16 и установить его contentMode на UIViewContentModeAspectFit.

person zem    schedule 02.06.2009
comment
Я попробовал этот подход, и он не сработал, но, вероятно, я просто делал это неправильно. - person bbrown; 03.06.2009

Я изменил категорию людей других людей, чтобы все изображения занимали одинаковую ширину (видимую ширину), БЕЗ МАСШТАБА:

-(UIImage*) centerImage:(UIImage *)inImage inRect:(CGRect) thumbRect
{

    CGSize size= thumbRect.size;
    UIGraphicsBeginImageContext(size);  
    //calculation
    [inImage drawInRect:CGRectMake((size.width-inImage.size.width)/2, (size.height-inImage.size.height)/2, inImage.size.width, inImage.size.height)];
    UIImage *newThumbnail = UIGraphicsGetImageFromCurrentImageContext();        
    // pop the context
    UIGraphicsEndImageContext();
    return newThumbnail;
}
person LolaRun    schedule 27.04.2012