iOS 图片高斯模糊处理

weakSelf.bgImageView.image= [imageblurImageAtFrame:CGRectMake(0,0, image.size.width, image.size.height)];
- (UIImage*)blurImageAtFrame:(CGRect)frame {
return [self applyBlurWithRadius:20
tintColor:[UIColorcolorWithWhite:0alpha:0.0]
saturationDeltaFactor:1.4
maskImage:nil
atFrame:frame];
}
- (UIImage*)applyBlurWithRadius:(CGFloat)blurRadiustintColor:(UIColor*)tintColorsaturationDeltaFactor:(CGFloat)saturationDeltaFactormaskImage:(UIImage*)maskImage {
// Check pre-conditions.
if(self.size.width<1||self.size.height<1) {
NSLog (@"*** error: invalid size: (%.2f x %.2f). Both dimensions must be >= 1: %@", self.size.width, self.size.height, self);
returnnil;
}
if(!self.CGImage) {
NSLog (@"*** error: image must be backed by a CGImage: %@", self);
returnnil;
}
if(maskImage && !maskImage.CGImage) {
NSLog (@"*** error: maskImage must be backed by a CGImage: %@", maskImage);
returnnil;
}
CGRect imageRect = {CGPointZero,self.size};
UIImage*effectImage =self;
BOOLhasBlur = blurRadius >__FLT_EPSILON__;
BOOLhasSaturationChange =fabs(saturationDeltaFactor -1.) >__FLT_EPSILON__;
if(hasBlur || hasSaturationChange) {
UIGraphicsBeginImageContextWithOptions(self.size, NO, [[UIScreen mainScreen] scale]);
CGContextRefeffectInContext =UIGraphicsGetCurrentContext();
CGContextScaleCTM(effectInContext,1.0, -1.0);
CGContextTranslateCTM(effectInContext,0, -self.size.height);
CGContextDrawImage(effectInContext, imageRect,self.CGImage);
vImage_BuffereffectInBuffer;
effectInBuffer.data =CGBitmapContextGetData(effectInContext);
effectInBuffer.width =CGBitmapContextGetWidth(effectInContext);
effectInBuffer.height =CGBitmapContextGetHeight(effectInContext);
effectInBuffer.rowBytes=CGBitmapContextGetBytesPerRow(effectInContext);
UIGraphicsBeginImageContextWithOptions(self.size, NO, [[UIScreen mainScreen] scale]);
CGContextRefeffectOutContext =UIGraphicsGetCurrentContext();
vImage_BuffereffectOutBuffer;
effectOutBuffer.data =CGBitmapContextGetData(effectOutContext);
effectOutBuffer.width =CGBitmapContextGetWidth(effectOutContext);
effectOutBuffer.height =CGBitmapContextGetHeight(effectOutContext);
effectOutBuffer.rowBytes=CGBitmapContextGetBytesPerRow(effectOutContext);
if(hasBlur) {
// A description of how to compute the box kernel width from the Gaussian
// radius (aka standard deviation) appears in the SVG spec:
// http://www.w3.org/TR/SVG/filters.html#feGaussianBlurElement
//
// For larger values of 's' (s >= 2.0), an approximation can be used: Three
// successive box-blurs build a piece-wise quadratic convolution kernel, which
// approximates the Gaussian kernel to within roughly 3%.
//
// let d = floor(s * 3*sqrt(2*pi)/4 + 0.5)
//
// ... if d is odd, use three box-blurs of size 'd', centered on the output pixel.
//
CGFloatinputRadius = blurRadius * [[UIScreenmainScreen]scale];
NSUIntegerradius =floor(inputRadius *3.*sqrt(2*M_PI) /4+0.5);
if(radius %2!=1) {
radius +=1; // force radius to be odd so that the three box-blur methodology works.
}
vImageBoxConvolve_ARGB8888(&effectInBuffer, &effectOutBuffer,NULL,0,0, (uint32_t)radius, (uint32_t)radius,0,kvImageEdgeExtend);
vImageBoxConvolve_ARGB8888(&effectOutBuffer, &effectInBuffer,NULL,0,0, (uint32_t)radius, (uint32_t)radius,0,kvImageEdgeExtend);
vImageBoxConvolve_ARGB8888(&effectInBuffer, &effectOutBuffer,NULL,0,0, (uint32_t)radius, (uint32_t)radius,0,kvImageEdgeExtend);
}
BOOLeffectImageBuffersAreSwapped =NO;
if(hasSaturationChange) {
CGFloats = saturationDeltaFactor;
CGFloatfloatingPointSaturationMatrix[] = {
0.0722+0.9278* s, 0.0722-0.0722* s, 0.0722-0.0722* s, 0,
0.7152-0.7152* s, 0.7152+0.2848* s, 0.7152-0.7152* s, 0,
0.2126-0.2126* s, 0.2126-0.2126* s, 0.2126+0.7873* s, 0,
0, 0, 0, 1,
};
constint32_tdivisor =256;
NSUIntegermatrixSize =sizeof(floatingPointSaturationMatrix)/sizeof(floatingPointSaturationMatrix[0]);
int16_tsaturationMatrix[matrixSize];
for(NSUIntegeri =0; i < matrixSize; ++i) {
saturationMatrix[i] = (int16_t)roundf(floatingPointSaturationMatrix[i] * divisor);
}
if(hasBlur) {
vImageMatrixMultiply_ARGB8888(&effectOutBuffer, &effectInBuffer, saturationMatrix, divisor,NULL,NULL,kvImageNoFlags);
effectImageBuffersAreSwapped =YES;
}else{
vImageMatrixMultiply_ARGB8888(&effectInBuffer, &effectOutBuffer, saturationMatrix, divisor,NULL,NULL,kvImageNoFlags);
}
}
if(!effectImageBuffersAreSwapped) {
effectImage =UIGraphicsGetImageFromCurrentImageContext();
}
UIGraphicsEndImageContext();
if(effectImageBuffersAreSwapped) {
effectImage =UIGraphicsGetImageFromCurrentImageContext();
}
UIGraphicsEndImageContext();
}
// Set up output context.
UIGraphicsBeginImageContextWithOptions(self.size, NO, [[UIScreen mainScreen] scale]);
CGContextRef outputContext = UIGraphicsGetCurrentContext();
CGContextScaleCTM(outputContext,1.0, -1.0);
CGContextTranslateCTM(outputContext, 0, -self.size.height);
// Draw base image.
CGContextDrawImage(outputContext, imageRect,self.CGImage);
// Draw effect image.
if(hasBlur) {
CGContextSaveGState(outputContext);
if(maskImage) {
CGContextClipToMask(outputContext, imageRect, maskImage.CGImage);
}
CGContextDrawImage(outputContext, imageRect, effectImage.CGImage);
CGContextRestoreGState(outputContext);
}
// Add in color tint.
if(tintColor) {
CGContextSaveGState(outputContext);
CGContextSetFillColorWithColor(outputContext, tintColor.CGColor);
CGContextFillRect(outputContext, imageRect);
CGContextRestoreGState(outputContext);
}
// Output image is ready.
UIImage *outputImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
returnoutputImage;
}