實用小技巧(九):類頭條模糊背景的實現

版本記錄

版本號 時間
V1.0 2017.06.26

前言

在app中,類似頭條的視頻播放,在播放列表里面,會有背景是處理成模糊效果的,這中效果給人很新奇的感覺。這一篇,就仿照實現頭條的模糊效果。感興趣的可以看看我寫的其他小技巧
1. 實用小技巧(一):UIScrollView中上下左右滾動方向的判斷

2. 實用小技巧(二):屏幕橫豎屏的判斷和相關邏輯
3.實用小技巧(三):點擊手勢屏蔽子視圖的響應
4.實用小技巧(四):動態的增刪標簽視圖
5.實用小技巧(五):通過相冊或者相機更改圖標
6.實用小技巧(六):打印ios里所有字體
7. 實用小技巧(七):UITableViewCell自適應行高的計算
8. 實用小技巧(八):數字余額顯示的分隔

實現目標

類似頭條的視頻,會有很多模糊的效果,我截了兩張圖,大約就是這個效果。

實例1
示例2

大家可以看見熊貓和吾六一兩邊的都是模糊的效果。下面我就實現一個這種效果。

實現過程

下面還是直接看代碼,寫一個UIImageView的分類。

#import <Foundation/Foundation.h>

@interface UIImageView (ZBUntil)

- (void)sd_setGaussFuzzyImageWithURL:(nullable NSURL *)url placeholderImage:(nullable UIImage *)placeholder;

@end
#import "UIImageView+ZBUntil.h"

@implementation UIImageView (ZBUntil)

- (void)sd_setGaussFuzzyImageWithURL:(nullable NSURL *)url placeholderImage:(nullable UIImage *)placeholder 
{  
    self.contentMode = UIViewContentModeScaleToFill;
    
    NSArray *subViewsArr = self.subviews;
    [subViewsArr enumerateObjectsUsingBlock:^(UIView *obj, NSUInteger idx, BOOL * _Nonnull stop) {
        if (obj.tag == 100) {
            [obj removeFromSuperview];
        }
    }];
    
    UIImageView *gaosiView = [[UIImageView alloc] init];
    gaosiView.tag = 100;
    gaosiView.contentMode = UIViewContentModeScaleAspectFit;
    [self addSubview:gaosiView];
    [gaosiView mas_remakeConstraints:^(MASConstraintMaker *make) {
        make.left.right.top.bottom.mas_equalTo(self);
    }];
    gaosiView.image = [UIImage boxblurImage:placeholder withBlurNumber:0.5f];
    [self sd_setImageWithURL:url placeholderImage:placeholder options:0 progress:nil completed:^(UIImage * _Nullable image, NSError * _Nullable error, SDImageCacheType cacheType, NSURL * _Nullable imageURL) {
        if (image) {
            self.image = [UIImage boxblurImage:image withBlurNumber:0.5f];
            gaosiView.image = image;
        }
    }];
}

@end

+  (UIImage *)boxblurImage:(UIImage *)image withBlurNumber:(CGFloat)blu;
+(UIImage *)boxblurImage:(UIImage *)image withBlurNumber:(CGFloat)blur
{
    if (!image) {
        return nil;
    }
    if (blur < 0.f || blur > 1.f) {
        blur = 0.5f;
    }
    int boxSize = (int)(blur * 40);
    boxSize = boxSize - (boxSize % 2) + 1;
    CGImageRef img = image.CGImage;
    vImage_Buffer inBuffer, outBuffer;
    vImage_Error error;
    void *pixelBuffer;
    //從CGImage中獲取數據
    CGDataProviderRef inProvider = CGImageGetDataProvider(img);
    CFDataRef inBitmapData = CGDataProviderCopyData(inProvider);
    //設置從CGImage獲取對象的屬性
    inBuffer.width = CGImageGetWidth(img);
    inBuffer.height = CGImageGetHeight(img);
    inBuffer.rowBytes = CGImageGetBytesPerRow(img);
    inBuffer.data = (void*)CFDataGetBytePtr(inBitmapData);
    pixelBuffer = malloc(CGImageGetBytesPerRow(img) * CGImageGetHeight(img));
    if(pixelBuffer == NULL)
        NSLog(@"No pixelbuffer");
    outBuffer.data = pixelBuffer;
    outBuffer.width = CGImageGetWidth(img);
    outBuffer.height = CGImageGetHeight(img);
    outBuffer.rowBytes = CGImageGetBytesPerRow(img);
    error = vImageBoxConvolve_ARGB8888(&inBuffer, &outBuffer, NULL, 0, 0, boxSize, boxSize, NULL, kvImageEdgeExtend);
    if (error) {
        NSLog(@"error from convolution %ld", error);
    }
    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
    CGContextRef ctx = CGBitmapContextCreate( outBuffer.data, outBuffer.width, outBuffer.height, 8, outBuffer.rowBytes, colorSpace, kCGImageAlphaNoneSkipLast);
    CGImageRef imageRef = CGBitmapContextCreateImage (ctx);
    UIImage *returnImage = [UIImage imageWithCGImage:imageRef];
    //clean up CGContextRelease(ctx);
    CGColorSpaceRelease(colorSpace);
    free(pixelBuffer);
    CFRelease(inBitmapData);
    CGColorSpaceRelease(colorSpace);
    CGImageRelease(imageRef);
    return returnImage;
}

這里有幾句代碼我一開始的時候并沒有加。

    NSArray *subViewsArr = self.subviews;
    [subViewsArr enumerateObjectsUsingBlock:^(UIView *obj, NSUInteger idx, BOOL * _Nonnull stop) {
        if (obj.tag == 100) {
            [obj removeFromSuperview];
        }
    }];

但是,如果不加,就會發現有些對象釋放不掉,運行出來的視圖查看層次也是很多疊在一起的。效果如下:

效果1
效果2

下面我們查看圖層。

效果1圖層
效果2圖層

大家可以看到效果1中有間隙漏出來了,效果2中圖像根本不對,上一個cell的圖像漏出來了,說明上一個圖像并沒有釋放。加上我剛才寫的那幾行代碼就可以了,就可以釋放和正常顯示了。

實現效果

下面我們看一下最終的實現效果。

效果1
效果2
效果3

后記

這個效果挺有意思,就是一個高斯模糊,希望大家感興趣的留言討論,謝謝大家。

風景真美
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • 一 、思想動員緊跟進 1、向外橫向拓展。以某某班、某某校為參照,看看他們是怎么做的,向他們看齊,向他們學習...
    06acbd34ae17閱讀 1,508評論 0 0
  • 千里相隨,生死相依,不離不棄,永生不朽。大被同眠,小飯同桌,義薄云天,誓死追隨。桃園三義,吾備承天,吾云蓋世,吾飛...
    孫武芮雯閱讀 289評論 2 4
  • 一、Core ML簡介 1、Core ML框架iOS11推出了Core ML框架,極大地降低了開發者在iphone...
    SwordDevil閱讀 774評論 0 1
  • 又來繼續寫今天的流水賬啦。昨天因為發版本,所以今天又基本只上半天班~早上11點多到的公司。然后今天又可惡的下雨了。...
    丶Saikaka閱讀 168評論 0 0