超大尺寸的图片无法使用UIActivityViewController分享问题

通过系统控件UIActivityViewController分享一个6000*4000尺寸的图片(https://pan.baidu.com/s/1O7GsFl_Y2vhkDnigZ1nqbg 这个是2兆的7441 × 10524尺寸分辨率为900图片:https://image.oss.m.1-joy.com/2018-07-26/f936995c4f51f006a77c27b039a0745c.JPG)。你会发现显示不了分享图片的页面。因为现在苹果屏幕分辨率最大的手机是iphone x 才5.8英寸屏(分辨率才1242x2208ps像素),手机支持的最大分辨率不能太高,像6000*4000这样的超高尺寸的图片在app上使用很容易出问题。可能苹果操作系统不支持这样的图片的使用。因为图像的分辨率对应的是二维的点阵图,iphone x 5.8物理像素分辨率才375*812。一张图片的图片大小主要取决于图片尺寸(点阵图如6000*4000就时指的图片尺寸,iphone x 5.8物理像素分辨率375*812也是指的点阵图),分辨率,图像压缩算法(学过图像处理的人知道,图片简单的是位图,就时bitMap,对应的是原始无压缩的点阵图,而jpeg等图像算法能把相同的连续图像点按照对应图像压缩算法对位图进行压缩保存,也可以还原位图)。所以图片压缩分三类:尺寸压缩最快成比例压缩(下面的就是图片图像格式方面的压缩算法,理论上可以压缩到接近无限小),分辨和图像格式方面的压缩(如:把bitMap转换为jpeg,PNG等图片格式,通过UIImageJPEGRepresentation(image, compressionQuality)进行分辨率和压缩算法方面的压缩,注意:compressionQuality是图像质量参数不是简单压缩比,这种压缩有压缩下限。由于图片的点阵图尺寸不会变,而连续相同的像素点也是固定,最多你把一个像素点灰阶从很大压缩到1,使用UIImageJPEGRepresentation压缩图像是说的是图像连续点的压缩,而修改它的compressionQuality主要是修改它的分辨率,所以通过UIImageJPEGRepresentation修改compressionQuality对图片压缩到一定程度,图像大小是无限趋近于不变化而不是无限接近0),也就时超大尺寸的图片经过非尺寸方面的压缩后可能很小,但是不会无限小。具体见文章《图像的压缩算法—尺寸压缩和大小压缩 》(https://blog.csdn.net/jia12216/article/details/81334363)。苹果的图像处理器是在高通定制的,图像处理是苹果自己开发的。所以苹果手机对严重超过手机分辨率的超大尺寸的图像不支持好是很正常的。并且通用第三方图片下载控件SDWebImage下载这样的高分辨率大尺寸的图片(如这样的图片:7441 × 10524尺寸分辨率为900图片:https://image.oss.m.1-joy.com/2018-07-26/f936995c4f51f006a77c27b039a0745c.JPG,6000*4000的图片让它崩溃不了)会crash。苹果不支持的不是超高分辨率(超大灰阶)的图片,也不时比较大的图片(当然你给苹果一个1G那么大的图片它也吃不消),而时超大尺寸的图片(这个超大尺寸的图片是相对的,至少6000*4000的它就不能完全支持了,有兴趣的同学可以自己试一试这个尺寸的临界点)。
那么怎么处理呢?就时检查图像的尺寸,若太大就进行压缩后再分享(包括其它类似问题)。
下面是图片压缩的部分代码:

/**最大尺寸手机支持的最大宽度,单位:ps像素(不是物理像素)*/
static const long long maxIphoneScreenMaxSizeWidth = 1242; //现在是iphone x
/**最大尺寸手机支持的最大高度,单位:ps像素(不是物理像素)*/
static const long long maxIphoneScreenMaxSizeHeight = 2208; //现在是iphone x

-(UIImage *)compressImageWithDada : (NSData *)data
{
    UIImage *image = [UIImage imageWithData:data];
    if((image.size.height <= maxIphoneScreenMaxSizeHeight) && (image.size.width <= maxIphoneScreenMaxSizeWidth))
    {
        return image;
    }
    if((maxIphoneScreenMaxSizeWidth == 0) || (maxIphoneScreenMaxSizeHeight == 0))
    {
        //防止除数为0而crash,理论上不该出现maxIphoneScreenMaxSizeHeight为0
        return nil;
    }
//    float imageWidth = image.size.width;
//    float imageHeight = image.size.height;
    //iphonex 5.8英寸屏 1242x2208
    float width = maxIphoneScreenMaxSizeWidth;
    float height = image.size.height/(image.size.width/width);

    if((image.size.width >= maxIphoneScreenMaxSizeWidth) && (image.size.height >= maxIphoneScreenMaxSizeHeight))
    {
        width = maxIphoneScreenMaxSizeWidth;
        height = image.size.height/(image.size.width/width);
        if(height > maxIphoneScreenMaxSizeHeight)
        {
            height = maxIphoneScreenMaxSizeHeight;
            width = image.size.width/(image.size.height/height);
        }
    }
    else if(image.size.width >= maxIphoneScreenMaxSizeWidth)
    {
        height = maxIphoneScreenMaxSizeHeight;
        width = image.size.width/(image.size.height/height);
    }
//    else if(image.size.height >= maxIphoneScreenMaxSizeHeight)
//    {
//        width = maxIphoneScreenMaxSizeWidth;
//        height = image.size.height/(image.size.width/width);
//    }


//    float widthScale = imageWidth /width;
//    float heightScale = imageHeight /height;

    // 创建一个bitmap的context
    // 并把它设置成为当前正在使用的context
    UIGraphicsBeginImageContext(CGSizeMake(width, height));
    [image drawInRect:CGRectMake(0, 0, width , height)];
//    if (widthScale > heightScale) {
//        [image drawInRect:CGRectMake(0, 0, imageWidth /heightScale , height)];
//    }
//    else {
//        [image drawInRect:CGRectMake(0, 0, width , imageHeight /widthScale)];
//    }

    // 从当前context中创建一个改变大小后的图片
    UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
    // 使当前的context出堆栈
    UIGraphicsEndImageContext();

    return newImage;

}

使用时的部分代码:

                NSData *data = [NSData dataWithContentsOfURL:[NSURL  URLWithString:url]];
                UIImage *image = [self compressImageWithDada:data];
                [activityItems addSafeObject:image];

经过测试iPhone5s也能使用这个iPhone x的这个图片尺寸,iPhone 4s由于没有测试机,所以无法测试。
不过若出现高分辨率的图片那么这张图片再怎么使用UIImageJPEGRepresentation压缩也不可能无限小,这个2.2兆的图,就是把他它的图像质量参数设置0.0001那么它也有500K以上(UIImageJPEGRepresentation(compressedImage, 0.0001)),只能使用图像尺寸方面的压缩。并且这样大的图片下载很费时间的,可能需要1秒以上,这样既浪费流量,浪费时间(用户体验很不好),还容易出问题。所以解决这个问题源头是图片上传时控制图片的分辨率(图片尺寸),最好把图片大小也控制下,这样利于用户体验。注意:有的图片是高分辨率的小图片(200K左右),仅仅控制上传时的图片大小不能完全控制高分辨率的图片。
具体方案是:1,用户提交是告诉他图片最大尺寸,禁止超标的图片提供;2,用户提交时,若图片尺寸超标提示图片超过最大的具体尺寸,提示用户是否压缩,并且告诉用户图像压缩可能失真。
超大尺寸的图片无法使用UIActivityViewController分享问题_第1张图片

你可能感兴趣的:(ios)