IOS-手写签名的实现(实现了手势绘制字体,添加文字水印,图片剪切、图片压缩)

最近要实现一个手写签名功能,要求是,在一定区域绘制文字签名,签名完成后,添加新的水印,并且将图片仅保留签字区域剪切,并且宽度不能大于128,经多方努力,终于完成了,现在上代码,总结一下:
首先,新建单视图项目,然后新建一个继承view的类signatureView,绘制功能和图片的处理就是在该类实现的,该类代码如下:

.h文件

#import <UIKit/UIKit.h>

@protocol GetSignatureImageDele <NSObject>

-(void)getSignatureImg:(UIImage*)image;

@end

@interface signatureView : UIView
{
    CGFloat min;
    CGFloat max;
    CGRect origRect;
    CGFloat origionX;
    CGFloat totalWidth;
    BOOL  isSure;
}
//签名完成后的水印文字
@property (strong,nonatomic) NSString *showMessage;
@property(nonatomic,assign)id<GetSignatureImageDele> delegate;
- (void)clear;
- (void)sure;
@end

.m文件

#import "signatureView.h"
#import <QuartzCore/QuartzCore.h>
#define StrWidth 150
#define StrHeight 20

staticCGPoint midpoint(CGPoint p0,CGPoint p1) {
   return (CGPoint) {
        (p0.x + p1.x) /2.0,
        (p0.y + p1.y) /2.0
    };
}

@interface signatureView () {
    UIBezierPath *path;
   CGPoint previousPoint;
}
@end

@implementation signatureView
- (void)commonInit {
    
    path = [UIBezierPathbezierPath];
    [pathsetLineWidth:2];
    
   max = 0;
   min = 0;
    // Capture touches
    UIPanGestureRecognizer *pan = [[UIPanGestureRecognizeralloc] initWithTarget:selfaction:@selector(pan:)];
    pan.maximumNumberOfTouches = pan.minimumNumberOfTouches =1;
    [selfaddGestureRecognizer:pan];
    
}

-(void)clearPan
{
    path = [UIBezierPathbezierPath];
    [pathsetLineWidth:3];
    
    [selfsetNeedsDisplay];
}


- (id)initWithCoder:(NSCoder *)aDecoder
{
   if (self = [superinitWithCoder:aDecoder]) [selfcommonInit];
    return self;
}
- (id)initWithFrame:(CGRect)frame
{
   if (self = [superinitWithFrame:frame]) [selfcommonInit];
    return self;
}


void ProviderReleaseData (void *info,const void *data,size_t size)
{
   free((void*)data);
}


- (UIImage*) imageBlackToTransparent:(UIImage*) image
{
    // 分配内存
   const int imageWidth = image.size.width;
   const int imageHeight = image.size.height;
   size_t      bytesPerRow = imageWidth * 4;
   uint32_t* rgbImageBuf = (uint32_t*)malloc(bytesPerRow * imageHeight);
    
    // 创建context
    CGColorSpaceRef colorSpace =CGColorSpaceCreateDeviceRGB();
   CGContextRef context = CGBitmapContextCreate(rgbImageBuf, imageWidth, imageHeight, 8, bytesPerRow, colorSpace,
                                                kCGBitmapByteOrder32Little | kCGImageAlphaNoneSkipLast);
    
   CGContextDrawImage(context, CGRectMake(0, 0, imageWidth, imageHeight), image.CGImage);
    
    // 遍历像素
   int pixelNum = imageWidth * imageHeight;
   uint32_t* pCurPtr = rgbImageBuf;
   for (int i =0; i < pixelNum; i++, pCurPtr++)
    {
        //        if ((*pCurPtr & 0xFFFFFF00) == 0)    //将黑色变成透明
       if (*pCurPtr == 0xffffff)
        {
           uint8_t* ptr = (uint8_t*)pCurPtr;
            ptr[0] =0;
        }
        
        //改成下面的代码,会将图片转成灰度
        /*uint8_t* ptr = (uint8_t*)pCurPtr;
         // gray = red * 0.11 + green * 0.59 + blue * 0.30
         uint8_t gray = ptr[3] * 0.11 + ptr[2] * 0.59 + ptr[1] * 0.30;
         ptr[3] = gray;
         ptr[2] = gray;
         ptr[1] = gray;*/
    }
    
    // 将内存转成image
   CGDataProviderRef dataProvider = CGDataProviderCreateWithData(NULL, rgbImageBuf, bytesPerRow * imageHeight,ProviderReleaseData);
   CGImageRef imageRef = CGImageCreate(imageWidth, imageHeight, 8,32, bytesPerRow, colorSpace,
                                       kCGImageAlphaLast | kCGBitmapByteOrder32Little, dataProvider,
                                       NULL, true,kCGRenderingIntentDefault);
    CGDataProviderRelease(dataProvider);
    
   UIImage* resultUIImage = [UIImageimageWithCGImage:imageRef];
    
    // 释放
   CGImageRelease(imageRef);
    CGContextRelease(context);
    CGColorSpaceRelease(colorSpace);
    // free(rgbImageBuf) 创建dataProvider时已提供释放函数,这里不用free
    
   return resultUIImage;
}


-(void)handelSingleTap:(UITapGestureRecognizer*)tap
{
    return [selfimageRepresentation];
}
-(void) imageRepresentation {
   
    if(UIGraphicsBeginImageContextWithOptions !=NULL)
    {
        UIGraphicsBeginImageContextWithOptions(self.bounds.size,NO, [UIScreenmainScreen].scale);
    }else {
        UIGraphicsBeginImageContext(self.bounds.size);
        
    }
    
    [self.layerrenderInContext:UIGraphicsGetCurrentContext()];
    
    UIImage *image =UIGraphicsGetImageFromCurrentImageContext();
    
    UIGraphicsEndImageContext();
    image = [selfimageBlackToTransparent:image];
    
   NSLog(@"width:%f,height:%f",image.size.width,image.size.height);
    
   UIImage *img = [selfcutImage:image];
    
    [self.delegategetSignatureImg:[selfscaleToSize:img]];
}

//压缩图片,最长边为128
- (UIImage *)scaleToSize:(UIImage *)img {
   CGRect rect ;
   CGFloat imageWidth = img.size.width;
    //判断图片宽度
   if(imageWidth >= 128)
    {
        rect =CGRectMake(0,0, 128, self.frame.size.height);
    }
   else
    {
        rect =CGRectMake(0,0, img.size.width,self.frame.size.height);
        
    }
   CGSize size = rect.size;
    UIGraphicsBeginImageContext(size);
    [imgdrawInRect:rect];
    UIImage* scaledImage =UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    UIImageWriteToSavedPhotosAlbum(scaledImage,nil, nil, nil);
    
    [selfsetNeedsDisplay];
   return scaledImage;
}

//只截取签名部分图片
- (UIImage *)cutImage:(UIImage *)image
{
   CGRect rect ;
    //签名事件没有发生
   if(min == 0&&max == 0)
    {
        rect =CGRectMake(0,0, 0, 0);
    }
    else//签名发生
    {
        rect =CGRectMake(min-3,0, max-min+6,self.frame.size.height);
    }
    CGImageRef imageRef =CGImageCreateWithImageInRect([image CGImage], rect);
   UIImage * img = [UIImageimageWithCGImage:imageRef];
    
   UIImage *lastImage = [selfaddText:img text:self.showMessage];
    
    [selfsetNeedsDisplay];
   return lastImage;
}

//签名完成,给签名照添加新的水印
- (UIImage *) addText:(UIImage *)img text:(NSString *)mark {
   int w = img.size.width;
   int h = img.size.height;
    
    //根据截取图片大小改变文字大小
   CGFloat size = 20;
   UIFont *textFont = [UIFontsystemFontOfSize:size];
   CGSize sizeOfTxt = [mark sizeWithFont:textFont constrainedToSize:CGSizeMake(128,30)];
    
   if(w<sizeOfTxt.width)
    {
        
       while (sizeOfTxt.width>w) {
            size --;
            textFont = [UIFontsystemFontOfSize:size];
            
            sizeOfTxt = [marksizeWithFont:textFont constrainedToSize:CGSizeMake(128,30)];
        }
        
    }
   else
    {
        
        size =45;
        textFont = [UIFontsystemFontOfSize:size];
        sizeOfTxt = [marksizeWithFont:textFont constrainedToSize:CGSizeMake(self.frame.size.width,30)];
       while (sizeOfTxt.width>w) {
            size ++;
            textFont = [UIFontsystemFontOfSize:size];
            sizeOfTxt = [marksizeWithFont:textFont constrainedToSize:CGSizeMake(self.frame.size.width,30)];
        }
        
    }
    UIGraphicsBeginImageContext(img.size);
    [[UIColorredColor] set];
    [imgdrawInRect:CGRectMake(0,0, w, h)];
    [markdrawInRect:CGRectMake((w-sizeOfTxt.width)/2,(h-sizeOfTxt.height)/2, sizeOfTxt.width, sizeOfTxt.height)withFont:textFont];
    UIImage *aimg =UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
   return aimg;
}
- (void)pan:(UIPanGestureRecognizer *)pan {
   CGPoint currentPoint = [pan locationInView:self];
   CGPoint midPoint = midpoint(previousPoint, currentPoint);
     NSLog(@"获取到的触摸点的位置为--currentPoint:%@",NSStringFromCGPoint(currentPoint));
    
   CGFloat viewHeight = self.frame.size.height;
   CGFloat currentY = currentPoint.y;
    if (pan.state ==UIGestureRecognizerStateBegan) {
        [pathmoveToPoint:currentPoint];
                
    } elseif (pan.state ==UIGestureRecognizerStateChanged) {
        [pathaddQuadCurveToPoint:midPoint controlPoint:previousPoint];
        
       
    }
    
   if(0 <= currentY && currentY <= viewHeight)
    {
       if(max == 0&&min == 0)
        {
           max = currentPoint.x;
           min = currentPoint.x;
        }
       else
        {
           if(max <= currentPoint.x)
            {
               max = currentPoint.x;
            }
           if(min>=currentPoint.x)
            {
               min = currentPoint.x;
            }
        }
        
    }
    
   previousPoint = currentPoint;
    
    [selfsetNeedsDisplay];
}

- (void)drawRect:(CGRect)rect
{
    self.backgroundColor = [UIColorwhiteColor];
    [[UIColorblackColor] setStroke];
    [pathstroke];
    
    self.layer.cornerRadius =5.0;
    self.clipsToBounds =YES;
    self.layer.borderWidth =0.5;
   self.layer.borderColor = [[UIColorgrayColor] CGColor];
    
    CGContextRef context =UIGraphicsGetCurrentContext();
    
   if(!isSure)
    {
        
       NSString *str = @"请绘制签名";
       CGContextSetRGBFillColor (context,  108/255, 108/255,108/255, 0.3);//设置填充颜色
       CGRect rect1 = CGRectMake((rect.size.width -StrWidth)/2, (rect.size.height -StrHeight)/2-5,StrWidth, StrHeight);
       origionX = rect1.origin.x;
       totalWidth = rect1.origin.x+StrWidth;
        
       UIFont  *font = [UIFontsystemFontOfSize:25];//设置字体
        [strdrawInRect:rect1 withFont:font];
    }
   else
        
    {
       isSure = NO;
    }
    
}

- (void)clear
{
   max = 0;
   min = 0;
    path = [UIBezierPathbezierPath];
    [pathsetLineWidth:2];
    
    [selfsetNeedsDisplay];
}
- (void)sure
{
    //没有签名发生时
   if(min == 0&&max == 0)
    {
       min = 0;
       max = 0;
    }
   isSure = YES;
    [selfsetNeedsDisplay];
    return [selfimageRepresentation];
}


@end

其中有两个方法过期了

替换方法:

1:

   NSDictionary *attribute = @{NSFontAttributeName:textFont};
    CGSize sizeOfTxt = [str boundingRectWithSize:size options: NSStringDrawingTruncatesLastVisibleLine | NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingUsesFontLeading attributes:attribute context:nil].size;

2:

    [mark drawInRect:CGRectMake((w-sizeOfTxt.width)/2,(h-sizeOfTxt.height)/2, sizeOfTxt.width, sizeOfTxt.height) withAttributes:@{NSFontAttributeName:textFont}];

在根视图viewController里面代码如下:

.h文件

#import <UIKit/UIKit.h>
#import "signatureView.h"
@interface ViewController :UIViewController<GetSignatureImageDele>
{
   UIImage *saveImage;
   UIView *saveView;
}
@property (strong,nonatomic) signatureView *signatureView;
@end

.m文件

@implementation ViewController

- (void)viewDidLoad {
    [superviewDidLoad];
    self.view.backgroundColor = [UIColorgrayColor];
    self.signatureView = [[signatureViewalloc] initWithFrame:CGRectMake(10,70, 300, 100)];
    self.signatureView.backgroundColor = [UIColorwhiteColor];
    self.signatureView.delegate =self;
    self.signatureView.showMessage =@"完成";
    [self.viewaddSubview:self.signatureView];
    
    UIButton *button = [UIButtonbuttonWithType:UIButtonTypeCustom];
    [button setTitle:@"重签"forState:UIControlStateNormal];
    [button setTitleColor:[UIColorcolorWithHue:72saturation:106brightness:123alpha:0.7]forState:UIControlStateNormal];
    [buttonsetFrame:CGRectMake(20,self.signatureView.frame.origin.y+120,130, 40)];
    button.layer.cornerRadius =5.0;
    button.clipsToBounds =YES;
    button.layer.borderWidth =1.0;
    button.titleLabel.font = [UIFontsystemFontOfSize:17];
    button.layer.borderColor = [[UIColorblackColor]CGColor];
    [button addTarget:selfaction:@selector(clear:)forControlEvents:UIControlEventTouchUpInside];
    [self.viewaddSubview:button];
    
    UIButton *button2 = [UIButtonbuttonWithType:UIButtonTypeCustom];
    [button2 setTitle:@"确认"forState:UIControlStateNormal];
    [button2 setTitleColor:[UIColorwhiteColor] forState:UIControlStateNormal];
    button2.titleLabel.font = [UIFontsystemFontOfSize:17];
    button2.backgroundColor = [UIColorblueColor];
    [button2setFrame:CGRectMake(170,self.signatureView.frame.origin.y+120,130, 40)];
    button2.layer.cornerRadius =5.0;
    button2.clipsToBounds =YES;
    [button2 addTarget:selfaction:@selector(add:)forControlEvents:UIControlEventTouchUpInside];
    [self.viewaddSubview:button2];

    saveView = [[UIViewalloc] initWithFrame:CGRectMake(10, button2.frame
                                                        .origin.y+60,300, 140)];
    saveView.backgroundColor = [UIColorlightGrayColor];
    [self.viewaddSubview:saveView];
    // Do any additional setup after loading the view, typically from a nib.
}
- (void)add:(UIButton *)sender
{
    [self.signatureViewsure];
    
}

- (void)clear:(UIButton *)sender
{
   NSLog(@"重签");
    [self.signatureViewclear];
   for(UIView *viewin saveView.subviews)
    {
        [view removeFromSuperview];
    }
}

-(void)getSignatureImg:(UIImage*)image
{
   if(image)
    {
        NSLog(@"haveImage");
        
       UIImageView *image1 = [[UIImageViewalloc] initWithImage:image];
        image1.frame =CGRectMake((saveView.frame.size.width-image.size.width)/2, (saveView.frame.size.height-image.size.height)/2, image.size.width, image.size.height) ;
        [saveViewaddSubview:image1];

       saveImage = image;
        [selfsaveImage:saveImage];
        //[self makeUpLoad];
        
    }
   else
    {
       NSLog(@"NoImage");
        
    }
    
}

//图片保存到本地
- (void)saveImage:(UIImage *)image
{
    //设置图片名
    NSDateFormatter *dateFormatter = [[NSDateFormatteralloc] init];
    [dateFormattersetDateFormat:@"yyyyMMdd"];
   NSString *currentDateStr = [dateFormatter stringFromDate:[NSDate date]];
   NSString *dateStr = [NSStringstringWithFormat:@"%@.png",currentDateStr];
    
   
    NSString *path = [NSTemporaryDirectory()stringByAppendingFormat:@"%@",dateStr];
    BOOL existed = [[NSFileManagerdefaultManager] fileExistsAtPath:pathisDirectory:nil];
   if ( existed  )
    {
        [[NSFileManagerdefaultManager] removeItemAtPath:patherror:nil];
    }
   //NSData *imgData = UIImageJPEGRepresentation(image, 1);
    NSData *imgData = UIImagePNGRepresentation(image);
    [imgDatawriteToFile:path atomically:YES];
    
}

- (void)didReceiveMemoryWarning {
    [superdidReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

效果图:


DF8DD5F1-DD2C-4794-9B40-8694AC2B48F0.png
EAE337AC-582B-4F42-B670-A43ACCB7AFDE.png

摘自:http://blog.csdn.net/u012890196/article/details/42269045

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 202,723评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,080评论 2 379
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,604评论 0 335
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,440评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,431评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,499评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,893评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,541评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,751评论 1 296
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,547评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,619评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,320评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,890评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,896评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,137评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,796评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,335评论 2 342

推荐阅读更多精彩内容

  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 171,368评论 25 707
  • *面试心声:其实这些题本人都没怎么背,但是在上海 两周半 面了大约10家 收到差不多3个offer,总结起来就是把...
    Dove_iOS阅读 27,118评论 29 470
  • ¥开启¥ 【iAPP实现进入界面执行逐一显】 〖2017-08-25 15:22:14〗 《//首先开一个线程,因...
    小菜c阅读 6,344评论 0 17
  • 很高兴又到了给好种子浇水施肥的时候了! 我99天的践行目标是家庭收入增加200万元。 业力伙伴赵琳的99...
    绚风阅读 274评论 0 2
  • 尽管人们都知道“良药苦口”、“忠言逆耳”,然而一方面,大部分药都是普遍药,而非良药,很多的言也非多么地良,仅是不坏...
    管理顾问王荣增阅读 604评论 4 12