IOS-手寫簽名的實現(xiàn)(實現(xiàn)了手勢繪制字體哀托,添加文字水印,圖片剪切劳秋、圖片壓縮)

最近要實現(xiàn)一個手寫簽名功能仓手,要求是,在一定區(qū)域繪制文字簽名玻淑,簽名完成后嗽冒,添加新的水印,并且將圖片僅保留簽字區(qū)域剪切补履,并且寬度不能大于128添坊,經(jīng)多方努力,終于完成了箫锤,現(xiàn)在上代碼贬蛙,總結一下:
首先,新建單視圖項目谚攒,然后新建一個繼承view的類signatureView阳准,繪制功能和圖片的處理就是在該類實現(xiàn)的,該類代碼如下:

.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);
    
    // 創(chuàng)建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) 創(chuàng)建dataProvider時已提供釋放函數(shù)野蝇,這里不用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 ;
    //簽名事件沒有發(fā)生
   if(min == 0&&max == 0)
    {
        rect =CGRectMake(0,0, 0, 0);
    }
    else//簽名發(fā)生
    {
        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;
    
    //根據(jù)截取圖片大小改變文字大小
   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
{
    //沒有簽名發(fā)生時
   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

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市绕沈,隨后出現(xiàn)的幾起案子锐想,更是在濱河造成了極大的恐慌,老刑警劉巖乍狐,帶你破解...
    沈念sama閱讀 206,602評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件赠摇,死亡現(xiàn)場離奇詭異,居然都是意外死亡澜躺,警方通過查閱死者的電腦和手機蝉稳,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,442評論 2 382
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來掘鄙,“玉大人耘戚,你說我怎么就攤上這事〔倌” “怎么了收津?”我有些...
    開封第一講書人閱讀 152,878評論 0 344
  • 文/不壞的土叔 我叫張陵,是天一觀的道長浊伙。 經(jīng)常有香客問我撞秋,道長,這世上最難降的妖魔是什么嚣鄙? 我笑而不...
    開封第一講書人閱讀 55,306評論 1 279
  • 正文 為了忘掉前任吻贿,我火速辦了婚禮,結果婚禮上哑子,老公的妹妹穿的比我還像新娘舅列。我一直安慰自己,他們只是感情好卧蜓,可當我...
    茶點故事閱讀 64,330評論 5 373
  • 文/花漫 我一把揭開白布帐要。 她就那樣靜靜地躺著,像睡著了一般弥奸。 火紅的嫁衣襯著肌膚如雪榨惠。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,071評論 1 285
  • 那天盛霎,我揣著相機與錄音赠橙,去河邊找鬼。 笑死愤炸,一個胖子當著我的面吹牛期揪,可吹牛的內容都是我干的。 我是一名探鬼主播摇幻,決...
    沈念sama閱讀 38,382評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼横侦,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了绰姻?” 一聲冷哼從身側響起枉侧,我...
    開封第一講書人閱讀 37,006評論 0 259
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎狂芋,沒想到半個月后榨馁,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,512評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡帜矾,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 35,965評論 2 325
  • 正文 我和宋清朗相戀三年翼虫,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片屡萤。...
    茶點故事閱讀 38,094評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡珍剑,死狀恐怖,靈堂內的尸體忽然破棺而出死陆,到底是詐尸還是另有隱情招拙,我是刑警寧澤,帶...
    沈念sama閱讀 33,732評論 4 323
  • 正文 年R本政府宣布措译,位于F島的核電站别凤,受9級特大地震影響,放射性物質發(fā)生泄漏领虹。R本人自食惡果不足惜规哪,卻給世界環(huán)境...
    茶點故事閱讀 39,283評論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望塌衰。 院中可真熱鬧诉稍,春花似錦、人聲如沸猾蒂。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,286評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽肚菠。三九已至舔箭,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間蚊逢,已是汗流浹背层扶。 一陣腳步聲響...
    開封第一講書人閱讀 31,512評論 1 262
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留烙荷,地道東北人镜会。 一個月前我還...
    沈念sama閱讀 45,536評論 2 354
  • 正文 我出身青樓,卻偏偏與公主長得像终抽,于是被迫代替她去往敵國和親戳表。 傳聞我的和親對象是個殘疾皇子桶至,可洞房花燭夜當晚...
    茶點故事閱讀 42,828評論 2 345

推薦閱讀更多精彩內容

  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 171,510評論 25 707
  • *面試心聲:其實這些題本人都沒怎么背,但是在上海 兩周半 面了大約10家 收到差不多3個offer,總結起來就是把...
    Dove_iOS閱讀 27,125評論 29 470
  • ¥開啟¥ 【iAPP實現(xiàn)進入界面執(zhí)行逐一顯】 〖2017-08-25 15:22:14〗 《//首先開一個線程,因...
    小菜c閱讀 6,358評論 0 17
  • 很高興又到了給好種子澆水施肥的時候了匾旭! 我99天的踐行目標是家庭收入增加200萬元镣屹。 業(yè)力伙伴趙琳的99...
    絢風閱讀 274評論 0 2
  • 盡管人們都知道“良藥苦口”、“忠言逆耳”价涝,然而一方面女蜈,大部分藥都是普遍藥,而非良藥色瘩,很多的言也非多么地良伪窖,僅是不壞...
    管理顧問王榮增閱讀 605評論 4 12