Proper use of UIRectClip to scale a UIImage down t

2019-08-04 19:56发布

给出的任何尺寸的一个UIImage,我想产生方“图标”尺寸版本, px像素的一侧上,而没有任何失真(拉伸)。 不过,我运行了一个小障碍。 不太清楚问题出在哪里。 下面是我在做什么至今。

首先,给定的uImage size ,我确定三件事情: ratio缩小图像时使用; 一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);
 }

现在,让我们说你通过480像素高有一个像640像素宽,我们希望得到一个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}

所以,现在我们有一个宽50像素高RECT 62.5px一起工作,并抓住“中间” 50×50部分的剪辑矩形。

到最后冲刺! 接下来,我们建立了我们的形象方面,得出的UIImage(称为myImage这里)到RECT,设置剪辑矩形,获得(大概现在夹式)图像,使用它,最后清理我们的图像内容:

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

 // Do something with the icon here ...

 UIGraphicsEndImageContext();

只有一个问题:裁剪不会发生! 我最终的图像63px宽×50像素高。 :(

也许我滥用/误解UIRectClip? 我已经试过洗牌周围的各种事物:交换使用rectclipRect ,drawInRect前移动UIRectClip。 没有骰子。

我试图寻找这种方法的一个例子在线为好,都无济于事。 为了记录在案,UIRectClip被定义为:

通过用指定的矩形相交它修改当前剪切路径。

洗牌周围的事物会让我们有点接近:

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

现在,我们没有失真,但如我所料的截取图像不居中原始。 尽管如此,至少该图像是50×50,虽然变量名现在犯规了作为所述洗牌的结果。 (我会恭敬地休假重命名作为练习留给读者。)

Answer 1:

找到了! 我有事情有点混合起来。 这工作:

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×50的图像(在这个例子中)的由来。

也许有一个更简单的方法。 如果是这样,请权衡!



Answer 2:

我想达到类似的事情,但找到了答案从原来的海报也不太工作。 它扭曲图像。 这很可能只是因为他没有发布完整的解决方案,并改变一些变量是如何初始化:

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


Answer 3:

wheeliebin的答案是正确的,但他忘了一个减号destY前

destRect = CGRectMake(0, -destY, destSize, destHeight);


文章来源: Proper use of UIRectClip to scale a UIImage down to icon size