? ? ? ? ? ? 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;
}