7

给定任何尺寸的UIImage,我希望生成一个方形“图标”大小的版本,px像素到一边,没有任何失真(拉伸)。但是,我遇到了一个小障碍。不太确定问题出在哪里。这是我目前正在做的事情。

首先,给定一个UImage size,我确定三件事:ratio缩小图像时使用的;a delta(我们想要的图标大小和最长边之间的差异)和an offset(用于在裁剪图像时计算我们的原点坐标):

 if (size.width > size.height) {
   ratio = px / size.width;
   delta = (ratio*size.width - ratio*size.height);
   offset = CGPointMake(delta/2, 0);
 } else {
   ratio = px / size.height;
   delta = (ratio*size.height - ratio*size.width);
   offset = CGPointMake(0, delta/2);
 }

现在,假设您有一个 640px 宽 x 480px 高的图像,我们希望从中得到一个 50px x 50px 的图标。宽度大于高度,所以我们的计算是:

ratio = 50px / 640px = 0.078125
delta = (ratio * 640px) - (ratio * 480px) = 50px - 37.5px = 12.5px
offset = {x=6.25, y=0}

接下来,我创建了一个足够大的CGRect rect,可以将其裁剪到我们想要的图标大小而不会变形,加上一个clipRect用于裁剪目的:

CGRect rect = CGRectMake(0.0, 0.0, (ratio * size.width) + delta,
                                   (ratio * size.height) + delta);
CGRect clipRect = CGRectMake(offset.x, offset.y, px, px);

从上面替换我们的值,我们得到:

rect = origin {x=0.0, y=0.0}, size {width=62.5, height=50.0}
clipRect = origin {x=6.25, y=0}, size {width=50.0, height=50.0}

所以现在我们有一个 62.5px 宽 x 50px 高的矩形可以使用,还有一个可以抓取“中间”50x50 部分的剪切矩形。

回到主场!接下来,我们设置我们的图像上下文,将UIImagemyImage此处称为)绘制到 rect 中,设置剪切矩形,获取(可能是现在剪切的)图像,使用它,最后清理我们的图像上下文:

 UIGraphicsBeginImageContext(rect.size);
 [myImage drawInRect:rect]; 
 UIRectClip(clipRect);
 UIImage *icon = UIGraphicsGetImageFromCurrentImageContext();

 // Do something with the icon here ...

 UIGraphicsEndImageContext();

只有一个问题:剪辑永远不会发生!我最终得到一个 63px 宽 x 50px 高的图像。:(

也许我在滥用/误解UIRectClip?我尝试过改组各种事情:交换使用rectand ,在drawInRect:之前clipRect移动UIRectClip。没有骰子。

我也尝试在网上搜索此方法的示例,但无济于事。作为记录,UIRectClip定义为:

通过与指定矩形相交来修改当前剪切路径。

洗牌让我们更接近一点:

UIGraphicsBeginImageContext(clipRect.size);
UIRectClip(rect);
[myImage drawInRect:rect];

现在我们没有失真,但剪裁的图像不像我预期的那样以原始图像为中心。尽管如此,至少图像是 50x50,尽管变量名称现在由于所述改组而被弄乱了。(我会恭敬地将重命名作为读者的练习。)

4

3 回答 3

7

尤里卡!我有点搞混了。这有效:

CGRect clipRect = CGRectMake(-offset.x, -offset.y,
                             (ratio * size.width) + delta,
                             (ratio * size.height) + delta);
UIGraphicsBeginImageContext(CGSizeMake(px, px));
UIRectClip(clipRect);
[myImage drawInRect:clipRect];
UIImage *icon = UIGraphicsGetImageFromCurrentImageContext();

// Do something with the icon here ...

UIGraphicsEndImageContext();

不再需要rect. 诀窍似乎是在剪切矩形中使用偏移量,从而对齐我们想要抓取 50 x 50 图像的原点(在此示例中)。

也许有更简单的方法。如果有,请称重!

于 2009-09-10T15:47:24.933 回答
1

我想实现类似的事情,但发现原始海报的答案不太奏效。它扭曲了图像。这很可能仅仅是因为他没有发布整个解决方案并且改变了一些变量的初始化方式:

 (if (size.width > size.height) 
       ratio = px / size.width;

我的解决方案是错误的(它想使用源图像中最大的正方形)。此外,没有必要使用 UIClipRect - 如果您将上下文设置为要提取的图像的大小,则无论如何都不会在该矩形之外进行实际绘图。这只是缩放图像矩形的大小并偏移一个原点坐标的问题。我在下面发布了我的解决方案:

+(UIImage *)makeIconImage:(UIImage *)image
{
    CGFloat destSize = 400.0;
    CGRect rect = CGRectMake(0, 0, destSize, destSize);

    UIGraphicsBeginImageContext(rect.size);

    if(image.size.width != image.size.height)
    {
        CGFloat ratio;
        CGRect destRect;

        if (image.size.width > image.size.height)
        {
            ratio = destSize / image.size.height;

            CGFloat destWidth = image.size.width * ratio;
            CGFloat destX = (destWidth - destSize) / 2.0;

            destRect = CGRectMake(-destX, 0, destWidth, destSize);

        }
        else
        {
            ratio = destSize / image.size.width;

            CGFloat destHeight = image.size.height * ratio;
            CGFloat destY = (destHeight - destSize) / 2.0;

            destRect = CGRectMake(0, destY, destSize, destHeight);
        }
        [image drawInRect:destRect];
    }
    else
    {
        [image drawInRect:rect];
    }
    UIImage *scaledImage = UIGraphicsGetImageFromCurrentImageContext();

    UIGraphicsEndImageContext();

    return scaledImage;
}
于 2014-03-06T11:48:05.157 回答
0

Wheeliebin 的答案是正确的,但他忘记了 destY 前面的减号

destRect = CGRectMake(0, -destY, destSize, destHeight);
于 2014-03-14T22:51:28.377 回答