IOS下,利用捏合手势实现图像缩放和显示

来源:互联网 发布:淘宝视频直播申请 编辑:程序博客网 时间:2024/05/05 20:56

图像的缩放查看,在移动终端上早已不是问题,任何一个人都能够熟练的操作图像的缩放。本文所讲述的重点并不是应用层面上的,而是从编码的角度去自己实现一个图像的缩放应用。作者(就是我自己)最近在做一款APP,其中有一个功能就是抓取PC桌面的图像发送到手机上显示。虽说现在的手机屏幕在慢慢的变大,已经可以达到5.5英寸,但是相比PC显示器的20+英寸,还是显得很小,可以展现的内容也很有限。如果整个PC屏幕显示在手机屏幕上,可以自行脑补一下,你能够看清上面的文字和图片么?那么问题来了,整个功能就需要实现对抓取PC桌面的放大和缩小显示。下面我将比较详细接用代码写出使用捏合手势来实现的缩放功能。


        首先我们需要两个参数来保存重要的信息:

CGFloat m_fScale;  // 缩放倍数CGPoint m_ptStart; // 显示图像块的起始点

m_fScale这个参数很容易理解,你缩放图像,一定得有个缩放倍数,那么就是它了;至于m_ptStart这个参数,我想我可能需要稍微啰嗦两句,来解释一下:当你放大图像时,由于显示区域时固定的,那么你就不可能把整个放大的图像都显示出来,你只能显示某一个块图像,那么这一块图像需要有一个起始点。

好吧,我承认,以上的解释是废话,我们还是来举个例子来说明一下吧。

比如,你的图像是1920 x 1080的分辨率,你放大了2倍,那么整个图像的分辨率就会变成3840 x 2160;如果你把3840 x 2160的图像直接显示出来,那你看到的结果是非但没有放大的效果,还缩小了。因为可显示区域大小是固定的,分辨率越大,显示内容越小。那么如何才能显示放大的图像呢?这时m_ptStart这个参数的作用就显现出来了。假设这个参数的值为(0,0),那么就是说从图像的标准坐标原点开始显示,显示的长度宽度也是固定的(假设是1920 x 1080),那么针对于3840 x 2160这个放大的图像,从(0,0)点开始显示长宽为1920 x 1080的图像块,这样显示的图像就是放大了(因为原本在固定可显示区域要显示1920 x 1080的图像,现在只要显示960 x 540的图像块就可以了)。

这样的例子,不知道是不是所有人都能够理解,还不理解,我也表示无能为力了。


        其次,我们需要给一个UIView添加捏合手势识别,假设这个UIView就是我们要在上面显示图像的View,这段代码的作用是,将一个捏合手势添加的View上,并且关联了捏合手势的处理函数gesturePinch。

// m_pTouchView已经关联到了UIView空间上m_pTouchView.multipleTouchEnabled = YES;  // 允许UIView多点触控UIPinchGestureRecognizer *recongnizerPinch = [[UIPinchGestureRecognizer alloc]init];[recongnizerPinch addTarget:self action:@select(gesturePinch:)];[m_pTouchView addGestureRecognizer:recognizerPinch];

这是捏合手势的处理函数,对缩放倍数进行边界检查,并且设置缩放倍数。

-(void)gestruePinch:(id)sender {    UIPinchGestureRecognizer *gesture = (UIPinchGestureRecognizer*)sender;    if (gesture.state == UIGestureRecognizerStateBegan)    {         // 记录捏合手势开始时的缩放系数         m_fStartScale = m_fScale;    }        // 捏合手势默认的系数是1.0    // 当识别为放大手势时,系数会从1.0开始递加; 当识别为缩小手势时,系数会从1.0开始递减,直到为0.0    CGFloat scale = gesture.scale + m_fStartScale - 1.0;       // 锁定缩放倍数,缩放倍数只能在1.0~3.0之间    if (scale - 1.0 < 0.000001)    {        scale = 1.0;    }    else if (scale - 3.0 > 0.000001)    {        scale  = 3.0;    }    m_fScale = scale;}


好了,到此为止,所有准备工作都做完了,下面该最关键的部分登场了——抠图并放大。

-(void)captureImage:(UIImage*)org scale:(CGFloat)scale startPoint:(CGPoint)startPoint {    // 如果缩放倍数为1.0的话,表示不需要进行缩放处理    if (scale - 1.0 <= 0.000001)    {        return org;    }    // 根据缩放倍数计算需要显示的图像的宽度和高度    int nW = org.size.width  / scale;    int nH  = org.size.height / scale;   // 根据startPoint和新的宽度高度,调整新的显示起始点。    int nX = (org.size.width - startPoint.x) >= nW ? startPoint.x : (org.size.width - nW);    int nY = (org.size.height - startPoint.y) >= nH ? startPoint.y : (org.size.height - nH);    // 提取指定rect的图像块    CGImage subImageRef = CGImageCreateWidthImageInRect(org.CGImage, CGRectMake(nX, nY, nW, nH);    UIImage     *capImg = [UIImage imageWidthCGImage:subImageRef];    CGImageRelease(subImageRef);    // 针对提取出来的图像块,将它还原到可现实区域大小,以实现放大的效果    UIGraphicsBeginImageContext(org.size);    [capImg drawInRect:CGRectMake(0, 0, org.size.width, org.size.height)];    UIImage *retImage = UIGraphicsGetImageFromCurrentImageContext();    UIGraphicsEndImageContext();    return retImage;}

图像处理完毕了,剩下的就是将图像画到UIView上就行了。

-(void)drawImage:(UIImage*)img {    if (img == nil)    {        return ;    }    m_pTouchView.layer.contents = (id)[self captureImage:img scale:m_fScale startPoint:m_ptStart].CGImage;}

你发现了什么?有问题?有参数没介绍?

对,你答对了,m_pStart这个显示起始坐标还没有设置,我们一直假设的是原始坐标(0,0);

至于这个坐标,你可以再touchesBegan,touchesMoved和touchesEnded这些函数中处理一下,就可以得到坐标了,这里就不写出具体代码了,留给细心的读者作为课后作业吧。





0 0
原创粉丝点击