欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

iOS 关于监听手机截图,UIView生成UIImage, UIImage裁剪与压缩的总结

程序员文章站 2022-07-04 10:59:19
一. 关于监听手机截图 1. 背景: 发现商品的售价页总是被人转发截图,为了方便用户添加截图分享的小功能 首先要注册用户截屏操作的通知 之后人为截图 人为截图,在这里可以对图片进行一些操作,比如添加自己的APP二维码啥的类似微博 当然最后不要忘记注销通知,这里要注意,根据需求来,如果商品详情页又可以 ......

一.  关于监听手机截图

1. 背景: 发现商品的售价页总是被人转发截图,为了方便用户添加截图分享的小功能

首先要注册用户截屏操作的通知

- (void)viewdidload {
    [super viewdidload];
    //注册用户的截屏操作通知
    [[nsnotificationcenter defaultcenter] addobserver:self
                                             selector:@selector(userdidtakescreenshot:)
                                                 name:uiapplicationuserdidtakescreenshotnotification object:nil];
}

之后人为截图

// 截屏响应
- (void)userdidtakescreenshot:(nsnotification *)notification
{
    //人为截屏, 模拟用户截屏行为, 获取所截图片
    _screenshotimg = [uiutils imagewithscreenshot]; // 这里封装了一下 获得图片就可以取分享啦
    dhshareactionsheetscreenshot *sharealert = [[dhshareactionsheetscreenshot alloc] init];
    [sharealert showwithimg:_screenshotimg];
}

人为截图,在这里可以对图片进行一些操作,比如添加自己的app二维码啥的类似微博

/**
 *  截取当前屏幕 并修改
 */
+ (uiimage *)imagewithscreenshot
{
    cgsize imagesize = cgsizezero;
    uiinterfaceorientation orientation = [uiapplication sharedapplication].statusbarorientation;
    if (uiinterfaceorientationisportrait(orientation))
        imagesize = [uiscreen mainscreen].bounds.size;
    else
        imagesize = cgsizemake([uiscreen mainscreen].bounds.size.height, [uiscreen mainscreen].bounds.size.width);
    
    uigraphicsbeginimagecontextwithoptions(imagesize, no, 0);
    cgcontextref context = uigraphicsgetcurrentcontext();
    for (uiwindow *window in [[uiapplication sharedapplication] windows])
    {
        cgcontextsavegstate(context);
        cgcontexttranslatectm(context, window.center.x, window.center.y);
        cgcontextconcatctm(context, window.transform);
        cgcontexttranslatectm(context, -window.bounds.size.width * window.layer.anchorpoint.x, -window.bounds.size.height * window.layer.anchorpoint.y);
        if (orientation == uiinterfaceorientationlandscapeleft)
        {
            cgcontextrotatectm(context, m_pi_2);
            cgcontexttranslatectm(context, 0, -imagesize.width);
        }else if (orientation == uiinterfaceorientationlandscaperight)
        {
            cgcontextrotatectm(context, -m_pi_2);
            cgcontexttranslatectm(context, -imagesize.height, 0);
        } else if (orientation == uiinterfaceorientationportraitupsidedown) {
            cgcontextrotatectm(context, m_pi);
            cgcontexttranslatectm(context, -imagesize.width, -imagesize.height);
        }
        if ([window respondstoselector:@selector(drawviewhierarchyinrect:afterscreenupdates:)])
        {
            [window drawviewhierarchyinrect:window.bounds afterscreenupdates:yes];
        }
        else
        {
            [window.layer renderincontext:context];
        }
        cgcontextrestoregstate(context);
    }
    
    uiimage *image = uigraphicsgetimagefromcurrentimagecontext();
    uigraphicsendimagecontext();
    
    return  image;
}

当然最后不要忘记注销通知,这里要注意,根据需求来,如果商品详情页又可以跳转到别的商品详情页最好这样注销,

避免跳到别的商品详情页多次截图

- (void)viewwilldisappear:(bool)animated {
    [super viewwilldisappear:animated];
    [[nsnotificationcenter defaultcenter] removeobserver:self name:uiapplicationuserdidtakescreenshotnotification object:nil];

}

二. uiview生成uiimag

uiview生成uiimage 时可以转一下jpg格式,这样图片不会太大具体参数可以百度,屏幕密度我一般采用0.7;

// uiview生成图片
+(uiimage*)convertviewtoimage:(uiview*)v{
    cgsize s = v.bounds.size;
    // 下面方法,第一个参数表示区域大小。第二个参数表示是否是非透明的。如果需要显示半透明效果,需要传no,否则传yes。第三个参数就是屏幕密度了
    //    nslog(@"[uiscreen mainscreen].scale-%f",[uiscreen mainscreen].scale);
    // 3.0 高清图 分享不了 用2.0即可 或者分享的时候压缩图片
    uigraphicsbeginimagecontextwithoptions(s, yes, [uiscreen mainscreen].scale);
    [v.layer renderincontext:uigraphicsgetcurrentcontext()];
    uiimage*image = uigraphicsgetimagefromcurrentimagecontext();
    uigraphicsendimagecontext();
    
    nsdata * data = uiimagejpegrepresentation(image, 0.7);
    uiimage* imagelast = [uiimage imagewithdata:data];
    
    return imagelast;
}

三. uiimage的裁剪

// 图片裁剪
+ (uiimage *)ct_imagefromimage:(uiimage *)image inrect:(cgrect)rect{
    
    //把像 素rect 转化为 点rect(如无转化则按原图像素取部分图片)
    cgfloat scale = [uiscreen mainscreen].scale;
    cgfloat x= rect.origin.x*scale,y=rect.origin.y*scale,w=rect.size.width*scale,h=rect.size.height*scale;
    cgrect dianrect = cgrectmake(x, y, w, h);
    
    //截取部分图片并生成新图片
    cgimageref sourceimageref = [image cgimage];
    cgimageref newimageref = cgimagecreatewithimageinrect(sourceimageref, dianrect);
    uiimage *newimage = [uiimage imagewithcgimage:newimageref scale:[uiscreen mainscreen].scale orientation:uiimageorientationup];
    
    nsdata * data = uiimagejpegrepresentation(newimage, 0.7);
    uiimage* imagelast = [uiimage imagewithdata:data];
    return imagelast;
}

四. uiimage的压缩

分享图片时根据分享的应用不同对图片大小是有限制的,微信是10m,但是qq小一些,

另外小程序分享的话也是有限制的128kb,当截图裁剪后无法满足时就需要压缩一下

先是密度压缩然后大小压缩,一般都可以解决的

// 图片压缩
+ (uiimage *)compressimage:(uiimage *)image tobyte:(nsuinteger)maxlength {
    // compress by quality
    cgfloat compression = 0.7;
    //uiimage转换为nsdata
    nsdata *data = uiimagejpegrepresentation(image, compression);
    if (data.length < maxlength){
        return image;
    }
    cgfloat max = 1;
    cgfloat min = 0;
    for (int i = 0; i < 6; ++i) {
        compression = (max + min) / 2;
        data = uiimagejpegrepresentation(image, compression);
        if (data.length < maxlength * 0.9) {
            min = compression;
        } else if (data.length > maxlength) {
            max = compression;
        } else {
            break;
        }
    }
    uiimage *resultimage = [uiimage imagewithdata:data];
    if (data.length < maxlength){
        return resultimage;
    }
    // compress by size
    nsuinteger lastdatalength = 0;
    while (data.length > maxlength && data.length != lastdatalength) {
        lastdatalength = data.length;
        cgfloat ratio = (cgfloat)maxlength / data.length;
        cgsize size = cgsizemake((nsuinteger)(resultimage.size.width * sqrtf(ratio)),
                                 (nsuinteger)(resultimage.size.height * sqrtf(ratio))); // use nsuinteger to prevent white blank
        uigraphicsbeginimagecontext(size);
        [resultimage drawinrect:cgrectmake(0, 0, size.width, size.height)];
        resultimage = uigraphicsgetimagefromcurrentimagecontext();
        uigraphicsendimagecontext();
        data = uiimagejpegrepresentation(resultimage, compression);
    }
    return resultimage;
}

这些是最近app的截图分享,小程序分享的关于图片的总结.希望帮助到需要的人.