在UITableViewCell图像上设置UIImage尺寸

7
我有一个标准的UITableViewCell,我使用文本和图像属性来显示一个favicon.ico和一个标签。大多数情况下,这很好用,因为UIImage支持ICO格式。但是,一些网站(如Amazon.com)有一些利用ICO格式在同一个文件中存储多个尺寸的favicon.ico,亚马逊存储了四种不同的尺寸,最高可达48x48。
这导致大多数图像都是16x16,除了一些以32x32或48x48出现的图像,使一切看起来很糟糕。我在这里、官方论坛、文档和其他地方进行了搜索,但没有成功。我尝试了我能想到的所有方法来约束图像大小。唯一有效的方法是一种未经记录的方法,我不打算使用它。这是我的第一个应用程序,也是我第一次接触Cocoa(来自C#)。
如果我没有表明我的意思,理想情况下建议应围绕设置UIImage的尺寸展开,以便48x48版本缩小至16x16,或者告诉UIImage使用ICO文件中存在的16x16版本。我不一定需要代码,只要建议一个方法即可。
有人有什么建议吗?(我在官方论坛中也提出了这个问题,因为我已经花了一天以上的时间在这个问题上。如果那里发布了解决方案,我也会在这里发布。)
6个回答

23

以下是来自官方论坛用户“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;
}

BCD的版本是UIImage上的一个类别,这比我在这里做的要合理得多。 - bbrown

4

我在我的应用程序中做了类似的事情。

    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;
}

然后创建一个新的图像,限制比例。将“image”替换为您从亚马逊获得的ICO文件。

CGRect sz = CGRectMake(0.0f, 0.0f, 16, 16);
UIImage *resized = resizedImage(image, sz);

由于某些原因,您的代码在我的电脑上出现了许多CoreGraphics错误。这可能与ICO格式有关。不过,这是一个很好的答案。 - bbrown
1
它们是编译/链接错误吗?我认为Xcode默认不会为新项目链接到CoreGraphics框架,因此您需要添加相应的@import语句。 - Daniel Dickison
1
是的,您需要链接到CoreGraphics框架。如果没有链接,那就是为什么会出现这些错误的原因。 - Brandon Schlenker
你的每行字节数是错误的,正如crafterm在他的评论答案中指出的那样。请参阅我的评论以获取详细信息,但你应该将宽度乘以4,而不是3。 - Peter Hosey

1

目前还没有足够的声望来评论答案,但我在以上bbrandons代码上取得了良好的成功。

然而,我在控制台上收到了相当多的警告,指出每行字节设置不够高-在阅读post的答案后,我最终将其设置为0,这可以让系统确定正确的值。

例如:

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

如果您声明每个组件8位,那么每个组件就是1字节。Brandon的答案避免了kCGImageAlphaNone,因此对于RGB颜色空间,总是有四个组件(三个颜色加上alpha)。这是1×4=4字节每像素。因此,他和您应该将宽度(每行像素)乘以4,而不是3。在那里传递0没有记录可以工作,所以您可能不应该依赖它,而应该不使用该技巧或提交文档错误报告要求记录:https://bugreport.apple.com - Peter Hosey
感谢你对计算的描述,Peter。很有道理 - 我也会为自动计算提交文档错误报告。 - crafterm

1

这是我做的方法。该技术确保将文本和详细文本标签适当地向左移动:

@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;
}

0

我修改了别人的类别,以便使所有图像占用相同的宽度(可见宽度),而不进行缩放:

-(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;
}

0

我不知道ico文件的工作原理,也许可以方便地提取16x16的图像并使用它,但我不知道如何操作。

就我所知,在通用的UITableViewCell中无法设置任何有用的图像属性。最简单的方法(尤其是对于新手来说仍然很麻烦)是继承一个UITableViewCell子类,并给它一个UIImageView,始终将图像视图大小设置为16x16,并将其contentMode设置为UIViewContentModeAspectFit


我尝试了这种方法,但它没有起作用,可能是因为我做错了。 - bbrown

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接