Iphone之選擇圖片濾鏡功能的實現
首先大家在做關於自拍軟件的時候,會涉及到這樣的功能,就是說給圖片加濾鏡,比如黑白,復古等效果,來使照片顯示不同的效果。下面代碼,就是如何實現了這一功能,當然,你可以加上你自己的效果,
個實現的效果如圖:
#import <UIKit/UIKit.h> #import <QuartzCore/QuartzCore.h> @interface PhotoSelectViewController : UIViewController { IBOutlet UIImageView *imageView;//圖片 IBOutlet UIScrollView *scrollerView;//滾動視圖顯示所有濾鏡圖片 UIImage *theImage;//原始圖片 int selectIndex;//選擇的第幾個圖片 } @end
/******各種顏色的設定*******/ //LOMO const float colormatrix_lomo[] = { 1.7f, 0.1f, 0.1f, 0, -73.1f, 0, 1.7f, 0.1f, 0, -73.1f, 0, 0.1f, 1.6f, 0, -73.1f, 0, 0, 0, 1.0f, 0 }; //黑白 const float colormatrix_heibai[] = { 0.8f, 1.6f, 0.2f, 0, -163.9f, 0.8f, 1.6f, 0.2f, 0, -163.9f, 0.8f, 1.6f, 0.2f, 0, -163.9f, 0, 0, 0, 1.0f, 0 }; //復古 const float colormatrix_huajiu[] = { 0.2f,0.5f, 0.1f, 0, 40.8f, 0.2f, 0.5f, 0.1f, 0, 40.8f, 0.2f,0.5f, 0.1f, 0, 40.8f, 0, 0, 0, 1, 0 }; //哥特 const float colormatrix_gete[] = { 1.9f,-0.3f, -0.2f, 0,-87.0f, -0.2f, 1.7f, -0.1f, 0, -87.0f, -0.1f,-0.6f, 2.0f, 0, -87.0f, 0, 0, 0, 1.0f, 0 }; //銳化 const float colormatrix_ruise[] = { 4.8f,-1.0f, -0.1f, 0,-388.4f, -0.5f,4.4f, -0.1f, 0,-388.4f, -0.5f,-1.0f, 5.2f, 0,-388.4f, 0, 0, 0, 1.0f, 0 }; //淡雅 const float colormatrix_danya[] = { 0.6f,0.3f, 0.1f, 0,73.3f, 0.2f,0.7f, 0.1f, 0,73.3f, 0.2f,0.3f, 0.4f, 0,73.3f, 0, 0, 0, 1.0f, 0 }; //酒紅 const float colormatrix_jiuhong[] = { 1.2f,0.0f, 0.0f, 0.0f,0.0f, 0.0f,0.9f, 0.0f, 0.0f,0.0f, 0.0f,0.0f, 0.8f, 0.0f,0.0f, 0, 0, 0, 1.0f, 0 }; //清寧 const float colormatrix_qingning[] = { 0.9f, 0, 0, 0, 0, 0, 1.1f,0, 0, 0, 0, 0, 0.9f, 0, 0, 0, 0, 0, 1.0f, 0 }; //浪漫 const float colormatrix_langman[] = { 0.9f, 0, 0, 0, 63.0f, 0, 0.9f,0, 0, 63.0f, 0, 0, 0.9f, 0, 63.0f, 0, 0, 0, 1.0f, 0 }; //光暈 const float colormatrix_guangyun[] = { 0.9f, 0, 0, 0, 64.9f, 0, 0.9f,0, 0, 64.9f, 0, 0, 0.9f, 0, 64.9f, 0, 0, 0, 1.0f, 0 }; //藍調 const float colormatrix_landiao[] = { 2.1f, -1.4f, 0.6f, 0.0f, -31.0f, -0.3f, 2.0f, -0.3f, 0.0f, -31.0f, -1.1f, -0.2f, 2.6f, 0.0f, -31.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f }; //夢幻 const float colormatrix_menghuan[] = { 0.8f, 0.3f, 0.1f, 0.0f, 46.5f, 0.1f, 0.9f, 0.0f, 0.0f, 46.5f, 0.1f, 0.3f, 0.7f, 0.0f, 46.5f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f }; //夜色 const float colormatrix_yese[] = { 1.0f, 0.0f, 0.0f, 0.0f, -66.6f, 0.0f, 1.1f, 0.0f, 0.0f, -66.6f, 0.0f, 0.0f, 1.0f, 0.0f, -66.6f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f }; #import "PhotoSelectViewController.h" @interface PhotoSelectViewController () @end @implementation PhotoSelectViewController - (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil { self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]; if (self) { // Custom initialization } return self; } - (void)viewDidLoad { [super viewDidLoad]; theImage = [UIImage imageNamed:@"photo.png"]; imageView.image = theImage; //添加濾鏡 NSArray *arr = [NSArray arrayWithObjects:@"原圖",@"LOMO",@"黑白",@"復古",@"哥特",@"銳色",@"淡雅",@"酒紅",@"青檸",@"浪漫",@"光暈",@"藍調",@"夢幻",@"夜色", nil]; //設置滾動視頻的屬性 scrollerView.backgroundColor = [UIColor colorWithRed:0 green:0 blue:0 alpha:0.5]; scrollerView.indicatorStyle = UIScrollViewIndicatorStyleBlack; scrollerView.showsHorizontalScrollIndicator = NO; scrollerView.showsVerticalScrollIndicator = NO;//關閉縱向滾動條 scrollerView.bounces = NO; //把所有的顯示效果圖添加到scrollerView裡面 float x ;//計算x坐標 for(int i=0;i<arr.count;i++) { x = 5 + 51*i; //添加點擊手勢識別,來處理選擇的圖片 UITapGestureRecognizer *recognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(setImageStyle:)]; recognizer.numberOfTouchesRequired = 1; recognizer.numberOfTapsRequired = 1; //添加名字標簽 UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(x, 53, 40, 23)]; [label setBackgroundColor:[UIColor clearColor]]; [label setText:[arr objectAtIndex:i]]; [label setTextAlignment:NSTextAlignmentCenter]; [label setFont:[UIFont systemFontOfSize:13.0f]]; [label setTextColor:[UIColor whiteColor]]; [label setUserInteractionEnabled:YES]; [label setTag:i]; [scrollerView addSubview:label]; //添加效果圖片 int tag = i+1000; UIImageView *bgImageView = [[UIImageView alloc]initWithFrame:CGRectMake(x, 10, 43, 43)]; [bgImageView setTag:tag]; [bgImageView addGestureRecognizer:recognizer]; [bgImageView setUserInteractionEnabled:YES]; UIImage *bgImage = [self changeImage:bgImageView.tag imageView:nil]; bgImageView.image = bgImage; [scrollerView addSubview:bgImageView]; [bgImageView setBackgroundColor:[UIColor redColor]]; //導入 <QuartzCore/QuartzCore.h> //添加是否選中邊框,選中時邊框為黃色,默認是第一個被選中的 if (i == 0) { CALayer * layer = [bgImageView layer]; layer.borderColor = [[UIColor yellowColor] CGColor]; layer.borderWidth = 1.0f; selectIndex = tag; }else{ CALayer * layer = [bgImageView layer]; layer.borderColor = [[UIColor blackColor] CGColor]; layer.borderWidth = 1.0f; } } //設置滾動視圖的實際大小 scrollerView.contentSize = CGSizeMake(x + 55, 60); } //選擇圖片處理方法 - (IBAction)setImageStyle:(UITapGestureRecognizer *)sender { //獲取效果圖 UIImage *image = [self changeImage:sender.view.tag imageView:nil]; if (selectIndex != sender.view.tag) { //取消選擇邊框 UIImageView *noselectImageView = (UIImageView*)[self.view viewWithTag:selectIndex]; CALayer * nolayer = [noselectImageView layer]; nolayer.borderColor = [[UIColor blackColor] CGColor]; nolayer.borderWidth = 1.0f; selectIndex = sender.view.tag; UIImageView *selectImageView = (UIImageView*)[self.view viewWithTag:selectIndex]; //添加選擇邊框 CALayer * layer = [selectImageView layer]; layer.borderColor = [[UIColor yellowColor] CGColor]; layer.borderWidth = 1.0f; } //圖片設置 [imageView setImage:image]; } //選擇的效果圖 -(UIImage *)changeImage:(int)index imageView:(UIImageView *)imageView { UIImage *image; switch (index-1000) { case 0: { return theImage; } break; case 1: { image = [self imageWithImage:theImage withColorMatrix:colormatrix_lomo]; } break; case 2: { image = [self imageWithImage:theImage withColorMatrix:colormatrix_heibai]; } break; case 3: { image = [self imageWithImage:theImage withColorMatrix:colormatrix_huajiu]; } break; case 4: { image = [self imageWithImage:theImage withColorMatrix:colormatrix_gete]; } break; case 5: { image = [self imageWithImage:theImage withColorMatrix:colormatrix_ruise]; } break; case 6: { image = [self imageWithImage:theImage withColorMatrix:colormatrix_danya]; } break; case 7: { image = [self imageWithImage:theImage withColorMatrix:colormatrix_jiuhong]; } break; case 8: { image = [self imageWithImage:theImage withColorMatrix:colormatrix_qingning]; } break; case 9: { image = [self imageWithImage:theImage withColorMatrix:colormatrix_langman]; } break; case 10: { image = [self imageWithImage:theImage withColorMatrix:colormatrix_guangyun]; } break; case 11: { image = [self imageWithImage:theImage withColorMatrix:colormatrix_landiao]; } break; case 12: { image = [self imageWithImage:theImage withColorMatrix:colormatrix_menghuan]; } break; case 13: { image = [self imageWithImage:theImage withColorMatrix:colormatrix_yese]; } } return image; } //效果圖 -(UIImage*)imageWithImage:(UIImage*)inImage withColorMatrix:(const float*) f { unsigned char *imgPixel = RequestImagePixelData(inImage); CGImageRef inImageRef = [inImage CGImage]; GLuint w = CGImageGetWidth(inImageRef); GLuint h = CGImageGetHeight(inImageRef); int wOff = 0; int pixOff = 0; for(GLuint y = 0;y< h;y++)//雙層循環按照長寬的像素個數迭代每個像素點 { pixOff = wOff; for (GLuint x = 0; x<w; x++) { int red = (unsigned char)imgPixel[pixOff]; int green = (unsigned char)imgPixel[pixOff+1]; int blue = (unsigned char)imgPixel[pixOff+2]; int alpha = (unsigned char)imgPixel[pixOff+3]; changeRGBA(&red, &green, &blue, &alpha, f); //回寫數據 imgPixel[pixOff] = red; imgPixel[pixOff+1] = green; imgPixel[pixOff+2] = blue; imgPixel[pixOff+3] = alpha; pixOff += 4; //將數組的索引指向下四個元素 } wOff += w * 4; } NSInteger dataLength = w * h * 4; //下面的代碼創建要輸出的圖像的相關參數 CGDataProviderRef provider = CGDataProviderCreateWithData(NULL, imgPixel, dataLength, NULL); int bitsPerComponent = 8; int bitsPerPixel = 32; int bytesPerRow = 4 * w; CGColorSpaceRef colorSpaceRef = CGColorSpaceCreateDeviceRGB(); CGBitmapInfo bitmapInfo = kCGBitmapByteOrderDefault; CGColorRenderingIntent renderingIntent = kCGRenderingIntentDefault; CGImageRef imageRef = CGImageCreate(w, h, bitsPerComponent, bitsPerPixel, bytesPerRow,colorSpaceRef, bitmapInfo, provider, NULL, NO, renderingIntent);//創建要輸出的圖像 UIImage *myImage = [UIImage imageWithCGImage:imageRef]; CFRelease(imageRef); CGColorSpaceRelease(colorSpaceRef); CGDataProviderRelease(provider); return myImage; } static CGContextRef CreateRGBABitmapContext (CGImageRef inImage)// 返回一個使用RGBA通道的位圖上下文 { CGContextRef context = NULL; CGColorSpaceRef colorSpace; void *bitmapData; //內存空間的指針,該內存空間的大小等於圖像使用RGB通道所占用的字節數。 int bitmapByteCount; int bitmapBytesPerRow; size_t pixelsWide = CGImageGetWidth(inImage); //獲取橫向的像素點的個數 size_t pixelsHigh = CGImageGetHeight(inImage); //縱向 bitmapBytesPerRow = (pixelsWide * 4); //每一行的像素點占用的字節數,每個像素點的ARGB四個通道各占8個bit(0-255)的空間 bitmapByteCount = (bitmapBytesPerRow * pixelsHigh); //計算整張圖占用的字節數 colorSpace = CGColorSpaceCreateDeviceRGB();//創建依賴於設備的RGB通道 bitmapData = malloc(bitmapByteCount); //分配足夠容納圖片字節數的內存空間 context = CGBitmapContextCreate (bitmapData, pixelsWide, pixelsHigh, 8, bitmapBytesPerRow, colorSpace, kCGImageAlphaPremultipliedLast); //創建CoreGraphic的圖形上下文,該上下文描述了bitmaData指向的內存空間需要繪制的圖像的一些繪制參數 CGColorSpaceRelease( colorSpace ); //Core Foundation中通過含有Create、Alloc的方法名字創建的指針,需要使用CFRelease()函數釋放 return context; } static unsigned char *RequestImagePixelData(UIImage *inImage) // 返回一個指針,該指針指向一個數組,數組中的每四個元素都是圖像上的一個像素點的RGBA的數值(0-255),用無符號的char是因為它正好的取值范圍就是0-255 { CGImageRef img = [inImage CGImage]; CGSize size = [inImage size]; CGContextRef cgctx = CreateRGBABitmapContext(img); //使用上面的函數創建上下文 CGRect rect = {{0,0},{size.width, size.height}}; CGContextDrawImage(cgctx, rect, img); //將目標圖像繪制到指定的上下文,實際為上下文內的bitmapData。 unsigned char *data = CGBitmapContextGetData (cgctx); CGContextRelease(cgctx);//釋放上面的函數創建的上下文 return data; } static void changeRGBA(int *red,int *green,int *blue,int *alpha, const float* f)//修改RGB的值 { int redV = *red; int greenV = *green; int blueV = *blue; int alphaV = *alpha; *red = f[0] * redV + f[1] * greenV + f[2] * blueV + f[3] * alphaV + f[4]; *green = f[0+5] * redV + f[1+5] * greenV + f[2+5] * blueV + f[3+5] * alphaV + f[4+5]; *blue = f[0+5*2] * redV + f[1+5*2] * greenV + f[2+5*2] * blueV + f[3+5*2] * alphaV + f[4+5*2]; *alpha = f[0+5*3] * redV + f[1+5*3] * greenV + f[2+5*3] * blueV + f[3+5*3] * alphaV + f[4+5*3]; if (*red > 255) { *red = 255; } if(*red < 0) { *red = 0; } if (*green > 255) { *green = 255; } if (*green < 0) { *green = 0; } if (*blue > 255) { *blue = 255; } if (*blue < 0) { *blue = 0; } if (*alpha > 255) { *alpha = 255; } if (*alpha < 0) { *alpha = 0; } } - (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; // Dispose of any resources that can be recreated. } - (void)viewDidUnload { imageView = nil; scrollerView = nil; [super viewDidUnload]; } @end