先看效果
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;
}