iOS-仿美圖定制

先看效果

t-shirt.gif

思路

1.以下圖像按順序稱(chēng)為A(背景圖像)儿礼、B(蒙版圖像)兩個(gè)圖像指蚜。
A B
timg.png
make.png
2.將B圖像按照合適的位置及大小献起,放在A圖像之上骂租,結(jié)果如下
c.png
3.取兩個(gè)圖像的交集部分
s.png
4.將交集部分顏色改為透明祷杈。形成一張根據(jù)B圖像形狀信息改變A圖像相應(yīng)顏色通道信息的新圖像。

代碼片段:

創(chuàng)建UIScrollView子類(lèi)渗饮,這將是最終貼紙但汞、文字部分內(nèi)容的顯示區(qū)域宿刮。在UIScrollView中創(chuàng)建一個(gè)UIImageView作為T(mén)-shirt的背景圖像顯示。

1.創(chuàng)建一張與UIScrollView子類(lèi)大小相同的圖像私蕾。

+ (UIImage *)imageWithColor:(UIColor *)color size:(CGSize)size {
    CGRect rect = CGRectMake(0.0f, 0.0f, size.width, size.height); //寬高 1.0只要有值就夠了
    UIGraphicsBeginImageContext(rect.size); //在這個(gè)范圍內(nèi)開(kāi)啟一段上下文
    CGContextRef context = UIGraphicsGetCurrentContext();
    
    CGContextSetFillColorWithColor(context, [color CGColor]);//在這段上下文中獲取到顏色UIColor
    CGContextFillRect(context, rect);//用這個(gè)顏色填充這個(gè)上下文
    
    UIImage *image = UIGraphicsGetImageFromCurrentImageContext();//從這段上下文中獲取Image屬性,,,結(jié)束
    UIGraphicsEndImageContext();
    
    return image;
}

2.將蒙版圖像(上文中B圖像)使用白色渲染一次(消除蒙版圖片灰度)

+ (UIImage *)imageWithColor:(UIColor *)color original:(UIImage*)originalImage
{
    UIGraphicsBeginImageContextWithOptions(originalImage.size, NO, originalImage.scale);
    CGContextRef context = UIGraphicsGetCurrentContext();
    CGContextTranslateCTM(context, 0, originalImage.size.height);
    CGContextScaleCTM(context, 1.0, -1.0);
    CGContextSetBlendMode(context, kCGBlendModeNormal);
    CGRect rect = CGRectMake(0, 0, originalImage.size.width, originalImage.size.height);
    CGContextClipToMask(context, rect, originalImage.CGImage);
    [color setFill];
    CGContextFillRect(context, rect);
    UIImage*newImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    return newImage;
}

3.背景圖片透明區(qū)域填充顏色

+ (UIImage *)colorImage:(UIImage *)origImage withColor:(UIColor *)color
{
    UIGraphicsBeginImageContextWithOptions(origImage.size, YES, 0);
    CGContextRef context = UIGraphicsGetCurrentContext();
    
    CGContextSetFillColorWithColor(context, [color CGColor]);
    CGContextFillRect(context, (CGRect){ {0,0}, origImage.size} );
    
    CGAffineTransform flipVertical = CGAffineTransformMake(1, 0, 0, -1, 0, origImage.size.height);
    CGContextConcatCTM(context, flipVertical);
    CGContextDrawImage(context, (CGRect){ {0,0}, origImage.size }, [origImage CGImage]);
    
    UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    
    return image;
}

4.使用新蒙版圖與背景圖進(jìn)行蒙層操作 產(chǎn)出蒙層圖片

+(UIImage*)maskImage:(UIImage *)image withMask:(UIImage *)maskImage
{
    CGImageRef maskRef = maskImage.CGImage;
    CGImageRef mask = CGImageMaskCreate(CGImageGetWidth(maskRef),
                                        CGImageGetHeight(maskRef),
                                        CGImageGetBitsPerComponent(maskRef),
                                        CGImageGetBitsPerPixel(maskRef),
                                        CGImageGetBytesPerRow(maskRef),
                                        CGImageGetDataProvider(maskRef), NULL, false);
    
    CGImageRef sourceImage = [image CGImage];
    CGImageRef imageWithAlpha = sourceImage;
    //add alpha channel for images that don't have one (ie GIF, JPEG, etc...)
    //this however has a computational cost
    if (CGImageGetAlphaInfo(sourceImage) == kCGImageAlphaNone) {
        //        imageWithAlpha = CopyImageAndAddAlphaChannel(sourceImage);
    }
    
    CGImageRef masked = CGImageCreateWithMask(imageWithAlpha, mask);
    
    CGImageRelease(mask);
    
    //release imageWithAlpha if it was created by CopyImageAndAddAlphaChannel
    if (sourceImage != imageWithAlpha) {
        CGImageRelease(imageWithAlpha);
    }
    
    UIImage* retImage = [UIImage imageWithCGImage:masked];
    CGImageRelease(masked);
    
    return retImage;
}

原理

  • 使用上下文CGContextRef對(duì)象創(chuàng)建與背景圖像(T-shirt)大小相同的全透明圖像
  • 使用白色渲染蒙版圖像
  • 蒙版圖像根據(jù)CGRect信息放入全透明圖像的合適位置合成一張與背景圖像(T-shirt)大小相同的新圖像
  • 背景圖像(T-shirt)與上步中產(chǎn)出的新圖像取交集僵缺,生成最終使用的蒙層圖像
  • 蒙層圖像加載在背景圖像(T-shirt)之上,因?yàn)?code>蒙層圖像邊緣透明指定定區(qū)域透明踩叭,所以在視覺(jué)顯示效果上磕潮,T-shirt還是以完整狀態(tài)顯示,在蒙層圖像背景圖像(T-shirt)之間添加貼紙對(duì)象與文字對(duì)象時(shí)容贝,就可以實(shí)現(xiàn)不規(guī)則蒙層遮擋自脯。達(dá)到在指定區(qū)域繪制T-shirt的目的。

完成代碼示例

CGSize groundSize = CGSizeMake(self.view.frame.size.width, self.view.frame.size.width);
// 1.創(chuàng)建最大寬度透明圖片
UIImage * alphaImage = [UIImage imageWithColor:[UIColor clearColor] size:groundSize];
// 2.獲取蒙版圖片 并且使用白色渲染蒙版圖片 (使用白色渲染是為了消除蒙版圖片的灰度值)
UIImage * masksImage = [UIImage imageWithColor:[UIColor whiteColor] original:[UIImage imageNamed:@"make"]];
// 3.將第二步中的圖片與第三部中的圖片進(jìn)行合并
UIImage *ZImage = [UIImage drawMaskImage:groundSize maskFrame:CGRectMake(110, 80, 190,320) alphaImage:alphaImage maskImage:masksImage];
// 4.背景圖片透明區(qū)域填充顏色
self.supportView.imageView.image = [UIImage colorImage:self.supportView.imageView.image withColor:[UIColor whiteColor]];
// 5.使用新蒙版圖與背景圖進(jìn)行蒙層操作 產(chǎn)出蒙層圖片
UIImage *maskedImage = [UIImage maskImage:[UIImage imageWithUIView:self.supportView.imageView] withMask:ZImage];
// 6.使用蒙層圖片
[self.bringView setImage:maskedImage];

通過(guò)截面GIF看一下

section.gif
通過(guò)PS制作一張中間透明的T-shirt的圖片放在背景T-shirt之上也能達(dá)到相同的效果斤富,至于我為什么這么做膏潮,額...
假設(shè)一件T-shirt有10種顏色,每種顏色都要P一次...

貼紙與文字

貼紙满力、文字都是UIView子類(lèi)焕参。控制圖像的旋轉(zhuǎn)縮放都是基于CGAffineTransform屬性與手勢(shì)UIPanGestureRecognizer進(jìn)行調(diào)整脚囊。
核心代碼如下:

- (void)circleViewDidPan:(UIPanGestureRecognizer*)sender
{
    CGPoint p = [sender translationInView:self.superview];
    
    static CGFloat tmpR = 1;
    static CGFloat tmpA = 0;
    if(sender.state == UIGestureRecognizerStateBegan)
    {
        _initialPoint = [self.superview convertPoint:_circleView.center fromView:_circleView.superview];
        
        CGPoint p = CGPointMake(_initialPoint.x - self.center.x, _initialPoint.y - self.center.y);
        tmpR = sqrt(p.x*p.x + p.y*p.y);
        tmpA = atan2(p.y, p.x);
        
        _initialArg = _arg;
        _initialScale = _scale;
    }
    
    p = CGPointMake(_initialPoint.x + p.x - self.center.x, _initialPoint.y + p.y - self.center.y);
    CGFloat R = sqrt(p.x*p.x + p.y*p.y);
    CGFloat arg = atan2(p.y, p.x);
    
    _arg   = _initialArg + arg - tmpA;
    [self setScale:MIN(_initialScale * R / tmpR, 10)];
}
- (void)setScale:(CGFloat)scale
{
    [self setScale:scale andScaleY:scale];
}
- (void)setScale:(CGFloat)scaleX andScaleY:(CGFloat)scaleY
{
    _scale = MIN(scaleX, scaleY);
    self.transform = CGAffineTransformIdentity;
    _imageView.transform = CGAffineTransformMakeScale(scaleX, scaleY);
    
    CGRect rct = self.frame;
    rct.origin.x += (rct.size.width - (_imageView.width)) / 2 - 5;
    rct.origin.y += (rct.size.height - (_imageView.height)) / 2 - 5;
    rct.size.width  = _imageView.width+10;
    rct.size.height = _imageView.height+10;
    self.frame = rct;
    
    _imageView.center = CGPointMake(rct.size.width/2, rct.size.height/2);
    self.transform = CGAffineTransformMakeRotation(_arg);
    
    _imageView.layer.borderWidth = 1/_scale;
}

代碼:https://github.com/wanggoing/CustomT-shirt

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末龟糕,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子悔耘,更是在濱河造成了極大的恐慌讲岁,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,657評(píng)論 6 505
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件衬以,死亡現(xiàn)場(chǎng)離奇詭異缓艳,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)看峻,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,889評(píng)論 3 394
  • 文/潘曉璐 我一進(jìn)店門(mén)阶淘,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人互妓,你說(shuō)我怎么就攤上這事溪窒。” “怎么了冯勉?”我有些...
    開(kāi)封第一講書(shū)人閱讀 164,057評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵澈蚌,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我灼狰,道長(zhǎng)宛瞄,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,509評(píng)論 1 293
  • 正文 為了忘掉前任交胚,我火速辦了婚禮份汗,結(jié)果婚禮上盈电,老公的妹妹穿的比我還像新娘。我一直安慰自己杯活,他們只是感情好匆帚,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,562評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布风宁。 她就那樣靜靜地躺著项滑,像睡著了一般。 火紅的嫁衣襯著肌膚如雪谨读。 梳的紋絲不亂的頭發(fā)上均践,一...
    開(kāi)封第一講書(shū)人閱讀 51,443評(píng)論 1 302
  • 那天晤锹,我揣著相機(jī)與錄音,去河邊找鬼彤委。 笑死鞭铆,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的焦影。 我是一名探鬼主播车遂,決...
    沈念sama閱讀 40,251評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼斯辰!你這毒婦竟也來(lái)了舶担?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 39,129評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤彬呻,失蹤者是張志新(化名)和其女友劉穎衣陶,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體闸氮,經(jīng)...
    沈念sama閱讀 45,561評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡剪况,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,779評(píng)論 3 335
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了蒲跨。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片译断。...
    茶點(diǎn)故事閱讀 39,902評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖或悲,靈堂內(nèi)的尸體忽然破棺而出孙咪,到底是詐尸還是另有隱情,我是刑警寧澤巡语,帶...
    沈念sama閱讀 35,621評(píng)論 5 345
  • 正文 年R本政府宣布翎蹈,位于F島的核電站,受9級(jí)特大地震影響捌臊,放射性物質(zhì)發(fā)生泄漏杨蛋。R本人自食惡果不足惜兜材,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,220評(píng)論 3 328
  • 文/蒙蒙 一理澎、第九天 我趴在偏房一處隱蔽的房頂上張望逞力。 院中可真熱鬧,春花似錦糠爬、人聲如沸寇荧。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,838評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)揩抡。三九已至,卻和暖如春镀琉,著一層夾襖步出監(jiān)牢的瞬間峦嗤,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,971評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工屋摔, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留烁设,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,025評(píng)論 2 370
  • 正文 我出身青樓钓试,卻偏偏與公主長(zhǎng)得像装黑,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子弓熏,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,843評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容