I have paging UIScrollview. The UIScrollview is the choice of the user selected. I'm supposed to blur out those pages that is not inside the scrollview frame. Any suggestions on this? Here is the screenshot for the implemented UIScrollview. The black box with low alpha component is to be replaced by blurry effect on the other pages.
I achieved this with a category on UIImage
...
.h file:
#import <Foundation/Foundation.h>
@interface UIImage (StackBlur)
- (UIImage*) stackBlur:(NSUInteger)radius;
- (UIImage *) normalize ;
@end
.m file:
#import "UIImage+StackBlur.h"
@implementation UIImage (StackBlur)
// Stackblur algorithm
// from
// http://incubator.quasimondo.com/processing/fast_blur_deluxe.php
// by Mario Klingemann
- (UIImage*) stackBlur:(NSUInteger)inradius
{
int radius=inradius; // Transform unsigned into signed for further operations
if (radius<1){
return self;
}
// Suggestion xidew to prevent crash if size is null
if (CGSizeEqualToSize(self.size, CGSizeZero)) {
return self;
}
// return [other applyBlendFilter:filterOverlay other:self context:nil];
// First get the image into your data buffer
CGImageRef inImage = self.CGImage;
int nbPerCompt=CGImageGetBitsPerPixel(inImage);
if(nbPerCompt!=32){
UIImage *tmpImage=[self normalize];
inImage=tmpImage.CGImage;
}
CFDataRef m_DataRef = CGDataProviderCopyData(CGImageGetDataProvider(inImage));
UInt8 * m_PixelBuf=malloc(CFDataGetLength(m_DataRef));
CFDataGetBytes(m_DataRef,
CFRangeMake(0,CFDataGetLength(m_DataRef)) ,
m_PixelBuf);
CGContextRef ctx = CGBitmapContextCreate(m_PixelBuf,
CGImageGetWidth(inImage),
CGImageGetHeight(inImage),
CGImageGetBitsPerComponent(inImage),
CGImageGetBytesPerRow(inImage),
CGImageGetColorSpace(inImage),
CGImageGetBitmapInfo(inImage)
);
int w=CGImageGetWidth(inImage);
int h=CGImageGetHeight(inImage);
int wm=w-1;
int hm=h-1;
int wh=w*h;
int div=radius+radius+1;
int *r=malloc(wh*sizeof(int));
int *g=malloc(wh*sizeof(int));
int *b=malloc(wh*sizeof(int));
memset(r,0,wh*sizeof(int));
memset(g,0,wh*sizeof(int));
memset(b,0,wh*sizeof(int));
int rsum,gsum,bsum,x,y,i,p,yp,yi,yw;
int *vmin = malloc(sizeof(int)*MAX(w,h));
memset(vmin,0,sizeof(int)*MAX(w,h));
int divsum=(div+1)>>1;
divsum*=divsum;
int *dv=malloc(sizeof(int)*(256*divsum));
for (i=0;i<256*divsum;i++){
dv[i]=(i/divsum);
}
yw=yi=0;
int *stack=malloc(sizeof(int)*(div*3));
int stackpointer;
int stackstart;
int *sir;
int rbs;
int r1=radius+1;
int routsum,goutsum,boutsum;
int rinsum,ginsum,binsum;
memset(stack,0,sizeof(int)*div*3);
for (y=0;y<h;y++){
rinsum=ginsum=binsum=routsum=goutsum=boutsum=rsum=gsum=bsum=0;
for(int i=-radius;i<=radius;i++){
sir=&stack[(i+radius)*3];
/* p=m_PixelBuf[yi+MIN(wm,MAX(i,0))];
sir[0]=(p & 0xff0000)>>16;
sir[1]=(p & 0x00ff00)>>8;
sir[2]=(p & 0x0000ff);
*/
int offset=(yi+MIN(wm,MAX(i,0)))*4;
sir[0]=m_PixelBuf[offset];
sir[1]=m_PixelBuf[offset+1];
sir[2]=m_PixelBuf[offset+2];
rbs=r1-abs(i);
rsum+=sir[0]*rbs;
gsum+=sir[1]*rbs;
bsum+=sir[2]*rbs;
if (i>0){
rinsum+=sir[0];
ginsum+=sir[1];
binsum+=sir[2];
} else {
routsum+=sir[0];
goutsum+=sir[1];
boutsum+=sir[2];
}
}
stackpointer=radius;
for (x=0;x<w;x++){
r[yi]=dv[rsum];
g[yi]=dv[gsum];
b[yi]=dv[bsum];
rsum-=routsum;
gsum-=goutsum;
bsum-=boutsum;
stackstart=stackpointer-radius+div;
sir=&stack[(stackstart%div)*3];
routsum-=sir[0];
goutsum-=sir[1];
boutsum-=sir[2];
if(y==0){
vmin[x]=MIN(x+radius+1,wm);
}
/* p=m_PixelBuf[yw+vmin[x]];
sir[0]=(p & 0xff0000)>>16;
sir[1]=(p & 0x00ff00)>>8;
sir[2]=(p & 0x0000ff);
*/
int offset=(yw+vmin[x])*4;
sir[0]=m_PixelBuf[offset];
sir[1]=m_PixelBuf[offset+1];
sir[2]=m_PixelBuf[offset+2];
rinsum+=sir[0];
ginsum+=sir[1];
binsum+=sir[2];
rsum+=rinsum;
gsum+=ginsum;
bsum+=binsum;
stackpointer=(stackpointer+1)%div;
sir=&stack[((stackpointer)%div)*3];
routsum+=sir[0];
goutsum+=sir[1];
boutsum+=sir[2];
rinsum-=sir[0];
ginsum-=sir[1];
binsum-=sir[2];
yi++;
}
yw+=w;
}
for (x=0;x<w;x++){
rinsum=ginsum=binsum=routsum=goutsum=boutsum=rsum=gsum=bsum=0;
yp=-radius*w;
for(i=-radius;i<=radius;i++){
yi=MAX(0,yp)+x;
sir=&stack[(i+radius)*3];
sir[0]=r[yi];
sir[1]=g[yi];
sir[2]=b[yi];
rbs=r1-abs(i);
rsum+=r[yi]*rbs;
gsum+=g[yi]*rbs;
bsum+=b[yi]*rbs;
if (i>0){
rinsum+=sir[0];
ginsum+=sir[1];
binsum+=sir[2];
} else {
routsum+=sir[0];
goutsum+=sir[1];
boutsum+=sir[2];
}
if(i<hm){
yp+=w;
}
}
yi=x;
stackpointer=radius;
for (y=0;y<h;y++){
// m_PixelBuf[yi]=0xff000000 | (dv[rsum]<<16) | (dv[gsum]<<8) | dv[bsum];
int offset=yi*4;
m_PixelBuf[offset]=dv[rsum];
m_PixelBuf[offset+1]=dv[gsum];
m_PixelBuf[offset+2]=dv[bsum];
rsum-=routsum;
gsum-=goutsum;
bsum-=boutsum;
stackstart=stackpointer-radius+div;
sir=&stack[(stackstart%div)*3];
routsum-=sir[0];
goutsum-=sir[1];
boutsum-=sir[2];
if(x==0){
vmin[y]=MIN(y+r1,hm)*w;
}
p=x+vmin[y];
sir[0]=r[p];
sir[1]=g[p];
sir[2]=b[p];
rinsum+=sir[0];
ginsum+=sir[1];
binsum+=sir[2];
rsum+=rinsum;
gsum+=ginsum;
bsum+=binsum;
stackpointer=(stackpointer+1)%div;
sir=&stack[(stackpointer)*3];
routsum+=sir[0];
goutsum+=sir[1];
boutsum+=sir[2];
rinsum-=sir[0];
ginsum-=sir[1];
binsum-=sir[2];
yi+=w;
}
}
free(r);
free(g);
free(b);
free(vmin);
free(dv);
free(stack);
CGImageRef imageRef = CGBitmapContextCreateImage(ctx);
CGContextRelease(ctx);
UIImage *finalImage = [UIImage imageWithCGImage:imageRef];
CGImageRelease(imageRef);
CFRelease(m_DataRef);
free(m_PixelBuf);
return finalImage;
}
- (UIImage *) normalize {
CGColorSpaceRef genericColorSpace = CGColorSpaceCreateDeviceRGB();
CGContextRef thumbBitmapCtxt = CGBitmapContextCreate(NULL,
self.size.width,
self.size.height,
8, (4 * self.size.width),
genericColorSpace,
kCGImageAlphaPremultipliedLast);
CGColorSpaceRelease(genericColorSpace);
CGContextSetInterpolationQuality(thumbBitmapCtxt, kCGInterpolationDefault);
CGRect destRect = CGRectMake(0, 0, self.size.width, self.size.height);
CGContextDrawImage(thumbBitmapCtxt, destRect, self.CGImage);
CGImageRef tmpThumbImage = CGBitmapContextCreateImage(thumbBitmapCtxt);
CGContextRelease(thumbBitmapCtxt);
UIImage *result = [UIImage imageWithCGImage:tmpThumbImage];
CGImageRelease(tmpThumbImage);
return result;
}
@end
using this code to blur an image ...
self.rawImage.image=[self.rawImage.image stackBlur:10.0f];