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

首先,给定 UImage size ,我确定了三件事:缩小图像时使用的 ratio ; a delta (我们想要的图标大小和最长边之间的差异)和 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);
 }

现在,假设您的图像宽640像素,宽480像素,我们希望从中获得50像素x 50像素的图像。宽度大于高度,因此我们的计算是:

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.5像素宽,50像素高的矩形工作,还有一个抓住“中间”的剪切矩形。 50x50部分。

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

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

 // Do something with the icon here ...

 UIGraphicsEndImageContext();

只有一个问题:剪辑永远不会发生!我最终得到了63px宽x50px高的图像。 <代码>:(

也许我在滥用/误解 UIRectClip ?我试过改变各种各样的东西:交换使用 rect clipRect ,在 drawInRect:之前移动 UIRectClip 。没有骰子。

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

  

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

随身携带的东西让我们更接近:

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

现在我们没有失真,但剪裁的图像并没有像我预期的那样居中。尽管如此,至少图像是50x50,尽管变量名称现在由于所述改组而被犯规。 (我会尊重地将重命名作为读者的练习。)

有帮助吗?

解决方案

尤里卡!我把事情搞砸了。这有效:

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图像的原点(在本例中)。

也许有一种更简单的方法。如果是这样,请称重!

其他提示

我想要实现类似的东西,但发现原始海报的答案并不是很有效。它扭曲了图像。这可能完全是因为他没有发布整个解决方案,并改变了一些初始化变量的方法:

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

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

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

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

destRect = CGRectMake(0, -destY, destSize, destHeight);
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top