月圆之夜,紫禁之巅,一剑西来,天外飞仙。

0%

本文实现将一张彩色图片转换为灰色图片。


方法一:通过自定义方法实现。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
+(UIImage*)systemImageToGray:(UIImage*)image
{
int width = image.size.width;
int height = image.size.height;

//第一步:开辟颜色空间
CGColorSpaceRef colorSpaceRef = CGColorSpaceCreateDeviceGray();

//第二步:创建颜色空间的上下文
CGContextRef contextRef = CGBitmapContextCreate(nil, width, height, 8, 0,colorSpaceRef, kCGImageAlphaNone);

if (contextRef == nil)
{
return nil;
}
//第三步:渲染图片
CGContextDrawImage(contextRef, CGRectMake(0, 0, width, height), image.CGImage);

//第四步:创建图片 将绘制的颜色空间转成CGImage
CGImageRef grayImageRef = CGBitmapContextCreateImage(contextRef);

//第五步:将C/C++图片转成UIImage

UIImage * newImage = [UIImage imageWithCGImage:grayImageRef];

//释放内存
CGColorSpaceRelease(colorSpaceRef);
CGContextRelease(contextRef);
CGImageRelease(grayImageRef);

return newImage;

}

方法二:通过openCV框架实现。

1
2
#import <opencv2/opencv.hpp>
#import <opencv2/imgcodecs/ios.h>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
+(UIImage*)imageToGray:(UIImage *)image
{
//第一步:将ios平台下的图片-->openCV图片

Mat mat_image_color;

UIImageToMat(image, mat_image_color);

//第二步:将openCV的图片进行灰度处理
Mat mat_image_gray;
//参数三:转换类型
cvtColor(mat_image_color, mat_image_gray, COLOR_RGB2GRAY);

//第三步:将灰色图片转成可现实图片
cvtColor(mat_image_gray, mat_image_color, COLOR_GRAY2RGB);

//第四步:将openCV的图片转成ios图片

UIImage * newImage = MatToUIImage(mat_image_color);

return newImage;

}

如有错误请见谅!

在上篇文章中整理了自定义方法实现图片美白,下面介绍一下使用openC实现图片美白。


第一步:下载openCV的framework。
openCV官方网址:http://opencv.org

第二步:将framework导入工程。
再将framework导入工程中后,进行编译有可能会出现错误,自己这边出了如下错误。

解决方法是

第三步:引入所需要的头文件。

1
2
#import <opencv2/opencv.hpp>
#import <opencv2/imgcodecs/ios.h>

第四步:创建命名空间
将涉及到的.m文件的文件名改为.mm

1
using namespace cv;

第五步:创建一个方法实现美白效果

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
+(UIImage *)openCVImageWhitening:(UIImage *)image:(int)MAX
{
Mat mat_image_src;
UIImageToMat(image, mat_image_src);

Mat mat_image_dst;
cvtColor(mat_image_src, mat_image_dst, CV_RGBA2RGB,3);

Mat mat_image_clone = mat_image_dst.clone();

for (int i = 0; i< MAX; i = i + 2)
{
bilateralFilter(mat_image_dst, mat_image_clone, i, i * 2, i / 2);

}
UIImage * newImage = MatToUIImage(mat_image_clone);
return newImage;
}

仅供学习使用,如有错误请见谅!

在iOS开发中,图片美白通常的方法有自定义方法和第三方框架实现,下面就自己在学习的过程中用到的方法做个整理。

通过自定义方法实现
个人认为图片美白实际上就是对图片的像素点进行修改,可以分为一下几个步骤:
第一步:拿到图片;
第二步:创建颜色空间;
第三步:创建图片上下文;
第四步:绘制图片;
第五步:对像素点进行修改;
第六步:创建Image对象;
第七步:释放内存。
下面上代码:

1
2
3
4
5
6
7
//定义宏用来获取ARGB分量值
#define Mask8(x) ((x) & 0xFF)
#define R(x) ( Mask8(x) )
#define G(x) ( Mask8(x >>8 ) )
#define B(x) ( Mask8(x >>16) )
#define A(x) ( Mask8(x >>24) )
#define RGBAMake(r, g, b, a) ( Mask8(r) | Mask8(g) << 8 | Mask8(b) << 16 | Mask8(a) << 24)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
+(UIImage *)pictureTheWhitening:(UIImage *)image
{
int lumi = 10;
//第一步:拿到图片
CGImageRef imageRef = [image CGImage];
NSUInteger width = CGImageGetWidth(imageRef);
NSUInteger height = CGImageGetHeight(imageRef);

//第二步:创建颜色空间
CGColorSpaceRef colorSpaceRef = CGColorSpaceCreateDeviceRGB();

UInt32 * inputPixels = (UInt32*)calloc(width * height, sizeof(UInt32));

//第三步:创建图片上下文
CGContextRef contextRef = CGBitmapContextCreate(inputPixels, width, height, 8, width * 4, colorSpaceRef, kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big);

//第四步:绘制图片
CGContextDrawImage(contextRef, CGRectMake(0, 0, width, height), imageRef);

//第五步:对像素点进行修改
for (int i = 0; i < height; i++)
{
for(int j = 0;j < width; j++)
{
UInt32 * currentPixels = inputPixels + i * width + j;

UInt32 color = * currentPixels;
UInt32 colorA,colorR,colorG,colorB;

colorR = R(color);
colorR = colorR + lumi;
colorR = colorR > 255 ? 255 : colorR;

colorG = G(color);
colorG = colorG + lumi;
colorG = colorG > 255 ? 255 : colorG;

colorB = B(color);
colorB = colorB + lumi;
colorB = colorB > 255 ? 255 : colorB;

colorA = A(color);
*currentPixels = RGBAMake(colorR, colorG, colorB, colorA);
}
}

//第六步:创建Image对象
CGImageRef newImageRef = CGBitmapContextCreateImage(contextRef);
UIImage * newImage = [UIImage imageWithCGImage:newImageRef];

//第七步:释放内存
CGColorSpaceRelease(colorSpaceRef);
CGContextRelease(contextRef);
CGImageRelease(newImageRef);
free(inputPixels);

return newImage;
}

仅供学习使用,如有错误请见谅!

gif图片合成的过程分为以下四步:

1
2
3
4
1.获取图片数据
2.创建gif图片
3.配置gif图片
4.单帧图片添加到gif

在这之前需要在工程中添加framework:ImageIO和MobileCoreServices

1
2
#import <ImageIO/ImageIO.h>
#import <MobileCoreServices/MobileCoreServices.h>
1
2
//1.获取图片数据
NSMutableArray * imagesArray = [[NSMutableArray alloc]initWithObjects:[UIImage imageNamed:@"Documentation0.png"],[UIImage imageNamed:@"Documentation1.png"],[UIImage imageNamed:@"Documentation2.png"],[UIImage imageNamed:@"Documentation3.png"], nil];
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
-(void)gifPictureSynthetic:(NSMutableArray*)imagesArray
{

//2.创建gif文件

NSArray * document = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);

NSString * doucmentStr =[document objectAtIndex:0];

NSFileManager * filemanager =[NSFileManager defaultManager];

NSString * textdic = [doucmentStr stringByAppendingString:@"/gif"];

[filemanager createDirectoryAtPath:textdic withIntermediateDirectories:YES attributes:nil error:nil];

//路径
NSString * path = [textdic stringByAppendingString:@"test1.gif"];

NSLog(@"path = %@",path);

//3.配置gif属性
CGImageDestinationRef destion;

CFURLRef url = CFURLCreateWithFileSystemPath(kCFAllocatorDefault, (CFStringRef)path, kCFURLPOSIXPathStyle, false);
destion = CGImageDestinationCreateWithURL(url, kUTTypeGIF, imagesArray.count, NULL);

//相关属性
NSDictionary * frameDic = [NSDictionary dictionaryWithObject:[NSMutableDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithFloat:0.3],(NSString *)kCGImagePropertyGIFDelayTime, nil] forKey:(NSString *)kCGImagePropertyGIFDelayTime];//延时

NSMutableDictionary * gifdic = [NSMutableDictionary dictionaryWithCapacity:2];

[gifdic setObject:[NSNumber numberWithBool:YES] forKey:(NSString *)kCGImagePropertyGIFHasGlobalColorMap];//颜色

[gifdic setObject:(NSString *)kCGImagePropertyColorModelRGB forKey:(NSString *)kCGImagePropertyColorModel];

[gifdic setObject:[NSNumber numberWithInt:8] forKey:(NSString *)kCGImagePropertyDepth];//颜色深度

[gifdic setObject:[NSNumber numberWithInt:0] forKey:(NSString *)kCGImagePropertyGIFLoopCount];//是否重复

NSDictionary * gifproperty = [NSDictionary dictionaryWithObject:gifdic forKey:(NSString *)kCGImagePropertyGIFDictionary];

//4.单帧添加到gif

for (UIImage * dimage in imagesArray)
{
CGImageDestinationAddImage(destion, dimage.CGImage, (__bridge CFDictionaryRef)frameDic);
}

CGImageDestinationSetProperties(destion, (__bridge CFDictionaryRef)gifproperty);
CGImageDestinationFinalize(destion);

CFRelease(destion);

}

gif图片分解的过程可以分为以下四步:

1.获取gif图片的数据
2.将gif图片分解成帧
3.将单帧数据转化为UIimage
4.单帧图片保存

在这之前需要在工程中添加framework:ImageIO和MobileCoreServices

1
2
#import <ImageIO/ImageIO.h>
#import <MobileCoreServices/MobileCoreServices.h>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
-(void)gifPictureDecomposition:(NSString*)pictureName
{
//1.获取gif图片数据
//将图片数据转化为data
NSData * data = [NSData dataWithContentsOfFile:gifpathsource];

CGImageSourceRef sourec = CGImageSourceCreateWithData((__bridge CFDataRef)data, NULL);

//2.将gif图片分解成帧

size_t count = CGImageSourceGetCount(sourec);

//定义数组保存单帧图片数据
self.tmpArr = [[NSMutableArray alloc]init];

for (size_t i = 0; i < count; i++)
{
CGImageRef imageRef = CGImageSourceCreateImageAtIndex(sourec, i, NULL);

//3.将单帧图片转化为UIimage
UIImage * image = [UIImage imageWithCGImage:imageRef scale:[UIScreen mainScreen].scale orientation:UIImageOrientationUp];

[self.tmpArr addObject:image];

//释放imageRef
CGImageRelease(imageRef);
}
//释放sourec
CFRelease(sourec);

//4.单帧图片保存

int i = 0;
for (UIImage * image in self.tmpArr)
{
NSData * data = UIImagePNGRepresentation(image);

NSArray * path = NSSearchPathForDirectoriesInDomains(NSDocumentationDirectory, NSUserDomainMask, YES);

NSString * gifpath = path[0];

NSString * pathNum = [gifpath stringByAppendingString:[NSString stringWithFormat:@"%d.png",i]];

i++;

[data writeToFile:pathNum atomically:NO];

NSLog(@"%@",path);//图片存储的路径
}
}

iOS 获取IP地址方法

闲来无事做个东西要获取iPhone的ip地址,网上好多方法没法用,这有一个能用的,记录下来。

代码块

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
引入文件

#import <ifaddrs.h>
#import <arpa/inet.h>

获取ip地址
-(void)getIPaddress
{
NSString *address = @"error";
struct ifaddrs * ifaddress = NULL;
struct ifaddrs * temp_address = NULL;
int success = 0;
success = getifaddrs(&ifaddress);
if(success == 0) {
temp_address = ifaddress;
while(temp_address != NULL) {
if(temp_address->ifa_addr->sa_family == AF_INET) {
if([[NSString stringWithUTF8String:temp_address->ifa_name] isEqualToString:@"en0"]) {
address = [NSString stringWithUTF8String:inet_ntoa(((struct sockaddr_in *)temp_address->ifa_addr)->sin_addr)];
}
}
temp_address = temp_address->ifa_next;
}
}


NSLog(@"获取到的IP地址为:%@",address);
}

1
最近在项目中遇到了这样一个问题,在tableView的cell上添加textfiled,然后获取cell上textfiled的值。cell的个数是可以动态改变的。如下图:

iOS学习笔记-tableView中如何获取cell上textfiled的值

1
在网上看了很多别人写的没找见容易点的实现方法,自己写了一个比较笨的方法。主要代码如下:
1
2
3
4
5
6
7
@property(nonatomic,strong)NSMutableArray * arrray//数组中元素的个数为cell的行数

@property(nonatomic,strong)NSMutableArray * tmparrray;//存cell

@property(nonatomic,strong)NSMutableArray * tmpIndexPath;//存indexPath

@property(nonatomic,strong)NSMutableArray * tmparrayaaaaa;//获取cell的数据
1
2
3
4
在-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath方法中加入

[self.tmpIndexPath addObject:indexPath];
[self.tmparrray addObject:cell];

定义一个按钮,当点击按钮的时候获取cell上textfiled中所填的值。

1
2
3
4
5
6
7
8
9
10
11
12
for(int i = 0; i<self.tmpIndexPath.count; i++)
{
[self.tmparrayaaaaa removeObject:[NSString stringWithFormat:@"%id",i]];
cell= [self.tmpTableView cellForRowAtIndexPath:[self.tmpIndexPath objectAtIndex:i]];
[self.tmparrayaaaaa addObject:cell.tmpTextfiled.text];

for (int i = 0; i < ((self.arrray.count * (self.arrray.count +1)) /2 ) - self.arrray.count; i++)
{
[self.tmparrayaaaaa removeObjectAtIndex:0];
}

NSLog(@"======获取cell的值====>%@",self.tmparrayaaaaa);
1
主要思路:在点击取值按钮后根据indexpath来遍历cell ,然后将cell中textfiled得值存到tmparrayaaaaa数组中。因为i每次循环,textfiled的值都要添加到数组中,所以数组终会有重复值,此时tmparrayaaaaa数组中元素的个数为(self.arrray.count * (self.arrray.count +1)) /2 ,故用循环的方式一次移除多余的元素。

1
本文介绍使用tableView自带的方法来实现多选功能。
1
2
3
@property(nonatomic,strong)UITableView *  tmptabelView;
@property(nonatomic,strong)NSMutableArray * saveArray;
@property(nonatomic,strong)NSMutableArray * array;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
self.array = [NSMutableArray arrayWithObjects:@"普通话",@"英语",@"法语",@"俄语",@"日语",@"韩语",@"德语",@"西班牙语",@"泰语",@"小语种",nil];

self.saveArray = [NSMutableArray array];

self.tmptabelView = [[UITableView alloc]initWithFrame:CGRectMake(0, 0, 300, 400)];

[self.tmptabelView setBackgroundColor:[UIColor whiteColor]];


[self.tmptabelView setDelegate:self];

[self.tmptabelView setDataSource:self];

self.tmptabelView.editing = YES;

self.tmptabelView.allowsMultipleSelectionDuringEditing = YES;

[self.view addSubview:self.tmptabelView];
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return self.array.count;

}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString * ID = @"ID";

UITableViewCell * cell = [tableView dequeueReusableCellWithIdentifier:ID];

if (!cell)
{
cell = [[UITableViewCell alloc]initWithStyle:(UITableViewCellStyleDefault) reuseIdentifier:ID];
}

[cell.textLabel setText:[NSString stringWithFormat:@"%@",self.array[indexPath.row]]];

cell.selectedBackgroundView = [[UIView alloc] init];

return cell;
}

-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
//将选中的元素保存
[self.saveArray addObject:self.array[indexPath.row]];

}

- (void)tableView:(UITableView *)tableView didDeselectRowAtIndexPath:(NSIndexPath *)indexPath{


if (self.array.count > indexPath.row)
{

//将选中的元素移除
if (self.saveArray.count > 0)
{

[self.saveArray removeObject:self.array[indexPath.row]];

}
}

}

最近在学习使用Masonry,在这里简单的做个分享。


Masonry主要有3个核心函数:

1
2
3
4
5
6
7
8
// 构建约束
mas_makeConstraints

// 更新约束 - 修改已经建立的约束,如果约束不存在,会在控制台输出错误
mas_updateConstraints

// 删除已经建立的所有约束,然后重新生成约束
mas_remakeConstraints

应用举例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
UIView *redView = [[UIView alloc]init];

[self.view addSubview:redView];

//构建约束
[redView mas_makeConstraints:^(MASConstraintMaker *make) {
//约束条件
}];

//更新约束
[redView mas_updateConstraints:^(MASConstraintMaker *make) {
//约束条件
}];

//删除约束重新添加
[redView mas_remakeConstraints:^(MASConstraintMaker *make) {
//约束条件
}];

几个方法:

1
2
3
4
equalTo(参照对象)
offset(CGFloat) 偏移量
dividedBy(),除以某个量,用以实现按比例设置约束
multipliedBy(),乘以某个量

举例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
make.top.left.equalTo(self.view).offset(10);//距上,左10个单位

make.bottom.right.equalTo(self.view).offset(-10);//距下,右10个单位

make.edges.equalTo(self.view).insets(UIEdgeInsetsMake(20, 20, 20, 20));//边距20个单位

make.height.equalTo(self.view).dividedBy(2);//宽 父视图的宽除以2

make.size.mas_equalTo(CGSizeMake(100, 100));//长 100 单位 宽 100单位

//动画
[UIView animateWithDuration:2.0 animations:^{
[self.view layoutIfNeeded];
}];

仅个人见解,如有错误请见谅!

1
闲言少叙,直接上代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
+(UIViewController *)getCurrentVC
{
UIViewController *rootViewController = [UIApplication sharedApplication].keyWindow.rootViewController;

UIViewController *currentVC = [self getCurrentVCFrom:rootViewController];

return currentVC;
}

+(UIViewController *)getCurrentVCFrom:(UIViewController *)rootVC
{
UIViewController *currentVC;

if ([rootVC presentedViewController]) {


rootVC = [rootVC presentedViewController];
}

if ([rootVC isKindOfClass:[UITabBarController class]]) {


currentVC = [self getCurrentVCFrom:[(UITabBarController *)rootVC selectedViewController]];

} else if ([rootVC isKindOfClass:[UINavigationController class]]){


currentVC = [self getCurrentVCFrom:[(UINavigationController *)rootVC visibleViewController]];

} else {


currentVC = rootVC;
}

return currentVC;
}