iOS開發CoreGraphics核心圖形框架之七——圖像處理

iOS開發CoreGraphics核心圖形框架之七——圖像處理

1、引言

    位圖圖像數據實際上一個像素陣列,其中每一個像素表明了圖像中的一個點。位圖實際上只支持矩形區域的渲染,可是使用透明技術能夠實現任意形狀圖像的渲染。開發者也能夠對要進行渲染的圖像進行旋轉、切割等操做。前端

2、經過圖像裁剪建立圖像

    CoreGraphics框架中提供了許多方法來建立位圖數據引用CGImageRef對象,其中封裝在CGImage.h文件中。在UIKit框架中也提供了方便的接口供開發者進行CGImageRef與UIImage對象的相互轉換。算法

    經過CoreGraphics框架中提供的圖像裁剪方法,開發者能夠截取一張大圖片中的一部分做爲新的圖像進行渲染。在Web開發中,爲了減小請求次數,經常會將許多小圖片合成一張大圖片返回給前端,同時還會給前端返回一個json文件,文件中存放着每一個獨立小圖的座標位置,前端在使用時進行截取便可,這種圖片經常被稱做雪碧圖。在iOS開發中遊戲開發中,不少遊戲引擎也提供了相似的方法,方便開發者對遊戲素材進行管理。實際上,經過CoreGraphics框架,開發者也能夠本身實現一套這樣的圖片加載邏輯,若是在本身的應用中,同時須要異步加載的小圖片不少,也能夠設計成下載一張大圖後從中截取須要的圖片。進行圖像截取的示例代碼以下:json

-(void)drawRect:(CGRect)rect{
    CGContextRef contextRef = UIGraphicsGetCurrentContext();
    //進行座標系的翻轉
    CGContextTranslateCTM(contextRef, 0, rect.size.height);
    CGContextScaleCTM(contextRef, 1.0, -1.0);
    CGImageRef orignImage = [UIImage imageNamed:@"image"].CGImage;
    CGContextDrawImage(contextRef, CGRectMake(0, 0, 320, 200), orignImage);
    CGImageRef rectImage =  CGImageCreateWithImageInRect(orignImage, CGRectMake(300, 400, 800, 400));
    CGContextDrawImage(contextRef, CGRectMake(0, 220, 320, 200), rectImage);
    CGImageRelease(orignImage);
    CGImageRelease(rectImage);
}

效果以下圖所示:數組

須要注意,CGContextDrawImage()方法渲染的圖像是上下翻轉的,能夠經過調整座標系來將圖片翻轉回來。框架

3、經過膜層來實現圖像的自定義裁剪

    經過Mask膜層能夠實現炫酷的圖像裁剪與風格重繪。膜層能夠簡單的理解爲將一個圖層追加到原圖層上,但須要注意,圖層中顏色爲純黑的部分,會按照原圖繪製,純白的部分會被徹底遮擋,這中間的顏色會以特定的算法進行alpha值的更改。例如將以下圖片做爲膜層繪製到原圖像上:異步

代碼以下:ide

-(void)drawRect:(CGRect)rect{
    CGContextRef contextRef = UIGraphicsGetCurrentContext();
    //進行座標系的翻轉
    CGContextTranslateCTM(contextRef, 0, rect.size.height);
    CGContextScaleCTM(contextRef, 1.0, -1.0);

    CGImageRef orignImage = [UIImage imageNamed:@"image"].CGImage;
    CGImageRef maskRef = [UIImage imageNamed:@"maskImage"].CGImage;
    //經過圖片數據建立膜層
    CGImageRef mask = CGImageMaskCreate(CGImageGetWidth(maskRef),
                      CGImageGetHeight(maskRef),
                      CGImageGetBitsPerComponent(maskRef),
                      CGImageGetBitsPerPixel(maskRef),
                      CGImageGetBytesPerRow(maskRef),
                      CGImageGetDataProvider(maskRef), nil, YES);
    CGImageRef resultImage =  CGImageCreateWithMask(orignImage, mask);
    CGContextDrawImage(contextRef, CGRectMake(0, 0, 320, 200), resultImage);
    CGImageRelease(orignImage);
    CGImageRelease(maskRef);
    CGImageRelease(mask);
}

效果以下圖所示:spa

    除了使用圖片膜層來對原圖像數據進行裁剪處理外,還能夠經過顏色數據定義膜層來進行裁剪。這個方法就能增強大了,其能夠將圖像中某個範圍的顏色所對應的全部區域裁剪出來。示例代碼以下:設計

-(void)drawRect:(CGRect)rect{
    CGContextRef contextRef = UIGraphicsGetCurrentContext();
    //進行座標系的翻轉
    CGContextTranslateCTM(contextRef, 0, rect.size.height);
    CGContextScaleCTM(contextRef, 1.0, -1.0);

    CGImageRef orignImage = [UIImage imageNamed:@"image2"].CGImage;
    const CGFloat myMaskingColors[6] = {35, 154,  23, 194, 103, 214};
    CGImageRef mask2 = CGImageCreateWithMaskingColors(orignImage, myMaskingColors);
    CGContextDrawImage(contextRef, CGRectMake(0, 0, 320, 200), mask2);
    
    CGImageRelease(orignImage);
    CGImageRelease(mask2);
}

CGImageCreateWithMaskingColors()這個方法須要兩個參數,第一個參數是要進行裁剪的圖像,那二個參數須要設置爲一個表示色彩的數組,須要注意,這個數組中元素的個數須要是當前色彩空間顏色原色數的兩倍,例如RGB色彩空間對應這個數組須要有6個元素{min1,max1,min2,max2,min3,max3}。以後會對圖像數據中的每個像素點進行遍歷,假如此像素點的顏色值爲{c1,c2,c3}。則當知足以下條件時,這個像素點會被裁剪:code

min1<c1<max1,min2<c2<max2,min3<c3<max3

須要注意,使用這種方式進行膜層裁剪,原圖像不能夠有alpha通道,色值的取值範圍爲0-255之間。上面示例代碼會將原圖像裁剪成以下效果:

對於被裁剪出來的部分,開發者可使用其餘顏色進行填充,示例代碼以下:

-(void)drawRect:(CGRect)rect{
    CGContextRef contextRef = UIGraphicsGetCurrentContext();
    //進行座標系的翻轉
    CGContextTranslateCTM(contextRef, 0, rect.size.height);
    CGContextScaleCTM(contextRef, 1.0, -1.0);
    CGImageRef orignImage = [UIImage imageNamed:@"image2"].CGImage;
    //設置填充
    [[UIColor redColor] setFill];
    CGContextFillRect(contextRef, CGRectMake(0, 0, 320, 200));
    const CGFloat myMaskingColors[6] = {35, 154,  23, 194, 103, 214};
    CGImageRef mask2 = CGImageCreateWithMaskingColors(orignImage, myMaskingColors);
    CGContextDrawImage(contextRef, CGRectMake(0, 0, 320, 200), mask2);
    
    CGImageRelease(orignImage);
}

效果以下圖:

    除了上面介紹了兩種對圖像進行裁剪的方法外,CoreGraphics框架中還提供了一種裁剪方式,示例代碼以下:

-(void)drawRect:(CGRect)rect{
    CGContextRef contextRef = UIGraphicsGetCurrentContext();
    //進行座標系的翻轉
    CGContextTranslateCTM(contextRef, 0, rect.size.height);
    CGContextScaleCTM(contextRef, 1.0, -1.0);

    CGImageRef orignImage = [UIImage imageNamed:@"image2"].CGImage;
    CGImageRef maskRef = [UIImage imageNamed:@"maskImage"].CGImage;
    CGImageRef mask = CGImageMaskCreate(CGImageGetWidth(maskRef),
                      CGImageGetHeight(maskRef),
                      CGImageGetBitsPerComponent(maskRef),
                      CGImageGetBitsPerPixel(maskRef),
                      CGImageGetBytesPerRow(maskRef),
                      CGImageGetDataProvider(maskRef), nil, YES);
    //進行膜層的裁剪
    CGContextClipToMask(contextRef, CGRectMake(0, 0, 320, 200), mask);
    CGContextDrawImage(contextRef, CGRectMake(0, 0, 320, 200), orignImage);
    CGImageRelease(orignImage);
}

4、進行圖像混合

    使用CoreGraphics框架也能夠繪製複雜的圖像混合效果,在進行圖像混合時,須要先繪製背景圖像,以後設置圖像混合模式,在繪製前景圖像,CoreGraphics會根據混合模式來進行最後圖像的繪製。例如使用以下背景圖像來與前景圖像來進行混合:

背景圖像:

前景圖像:

示例代碼以下:

-(void)drawRect:(CGRect)rect{
    CGContextRef contextRef = UIGraphicsGetCurrentContext();
    //進行座標系的翻轉
    CGContextTranslateCTM(contextRef, 0, rect.size.height);
    CGContextScaleCTM(contextRef, 1.0, -1.0);
    CGImageRef background = [UIImage imageNamed:@"background"].CGImage;
    CGContextDrawImage(contextRef, CGRectMake(60, 25, 200, 150), background);
    CGContextSetBlendMode(contextRef, kCGBlendModeNormal);
    CGImageRef orignImage = [UIImage imageNamed:@"image2"].CGImage;
    CGContextDrawImage(contextRef, CGRectMake(0, 0, 320, 200), orignImage);
    CGImageRelease(background);
    CGImageRelease(orignImage);
}

kCGBlendModeNormal模式的混合就是簡單覆蓋,前景圖像會徹底將背景圖像覆蓋,運行效果以下:

kCGBlendModeMultiply模式是疊加混合模式,其會將前景圖alpha化,效果以下:

kCGBlendModeScreen模式會將前景圖進行裁剪,最終的結果顏色將比原圖輕,效果以下:

kCGBlendModeOverlay模式也會將前景圖進行裁剪,會保持原圖色彩,效果以下:

kCGBlendModeDarken混合模式會將原圖色值加深,效果以下:

kCGBlendModeLighten在混合時則會選擇色值較輕的圖像進行混合,效果以下:

kCGBlendModeColorDodge混合模式效果以下:

kCGBlendModeColorBurn混合模式效果以下:

kCGBlendModeSoftLight爲柔光混合模式,效果以下:

kCGBlendModeHardLight爲重光混合模式,效果以下:

kCGBlendModeDifference差別混合模式會取顏色的逆向值,效果以下:

kCGBlendModeExclusion混合模式效果以下:

kCGBlendModeHue混合模式會改變色彩的飽和度,效果以下:

kCGBlendModeSaturation混合模式效果以下:

kCGBlendModeColor混合模式效果以下:

kCGBlendModeLuminosity光影混合模式會將前景圖進行黑白化,效果以下:

專一技術,熱愛生活,交流技術,也作朋友。

——琿少 QQ羣:203317592

相關文章
相關標籤/搜索