iOS-為圖片添加傾斜水印效果

轉(zhuǎn)載請(qǐng)聯(lián)系作者獲取授權(quán),并標(biāo)明文章作者,謝謝!

所謂水印是向數(shù)據(jù)多媒體(如圖像、聲音、視頻信號(hào)等)中添加某些數(shù)字信息以達(dá)到文件真?zhèn)舞b別、版權(quán)保護(hù)等功能。嵌入的水印信息隱藏于宿主文件中,不影響原始文件的可觀性和完整性。也就是在圖片上打上半透明的標(biāo)記。我們先來(lái)看一下Demo的運(yùn)行效果圖。
源圖片打上水印
核心技術(shù):CoreGraphics繪圖。閑話少說(shuō),上代碼。
#define HORIZONTAL_SPACE 30//水平間距
#define VERTICAL_SPACE 50//豎直間距
#define CG_TRANSFORM_ROTATION (M_PI_2 / 3)//旋轉(zhuǎn)角度(正旋45度 || 反旋45度)
/**
 根據(jù)目標(biāo)圖片制作一個(gè)蓋水印的圖片
 
 @param originalImage 源圖片
 @param title 水印文字
 @param markFont 水印文字font(如果不傳默認(rèn)為23)
 @param markColor 水印文字顏色(如果不傳遞默認(rèn)為源圖片的對(duì)比色)
 @return 返回蓋水印的圖片
 */
+ (UIImage *)getWaterMarkImage: (UIImage *)originalImage andTitle: (NSString *)title andMarkFont: (UIFont *)markFont andMarkColor: (UIColor *)markColor{
    
    UIFont *font = markFont;
    if (font == nil) {
        font = [UIFont systemFontOfSize:23];
    }
    UIColor *color = markColor;
    if (color == nil) {
        color = [self mostColor:originalImage];
    }
    //原始image的寬高
    CGFloat viewWidth = originalImage.size.width;
    CGFloat viewHeight = originalImage.size.height;
    //為了防止圖片失真,繪制區(qū)域?qū)捀吆驮紙D片寬高一樣
    UIGraphicsBeginImageContext(CGSizeMake(viewWidth, viewHeight));
    //先將原始image繪制上
    [originalImage drawInRect:CGRectMake(0, 0, viewWidth, viewHeight)];
    //sqrtLength:原始image的對(duì)角線length。在水印旋轉(zhuǎn)矩陣中只要矩陣的寬高是原始image的對(duì)角線長(zhǎng)度,無(wú)論旋轉(zhuǎn)多少度都不會(huì)有空白。
    CGFloat sqrtLength = sqrt(viewWidth*viewWidth + viewHeight*viewHeight);
    //文字的屬性
    NSDictionary *attr = @{
                           //設(shè)置字體大小
                           NSFontAttributeName: font,
                           //設(shè)置文字顏色
                           NSForegroundColorAttributeName :color,
                           };
    NSString* mark = title;
    NSMutableAttributedString *attrStr = [[NSMutableAttributedString alloc] initWithString:mark attributes:attr];
    //繪制文字的寬高
    CGFloat strWidth = attrStr.size.width;
    CGFloat strHeight = attrStr.size.height;
    
    //開(kāi)始旋轉(zhuǎn)上下文矩陣,繪制水印文字
    CGContextRef context = UIGraphicsGetCurrentContext();

    //將繪制原點(diǎn)(0,0)調(diào)整到源image的中心
    CGContextConcatCTM(context, CGAffineTransformMakeTranslation(viewWidth/2, viewHeight/2));
    //以繪制原點(diǎn)為中心旋轉(zhuǎn)
    CGContextConcatCTM(context, CGAffineTransformMakeRotation(CG_TRANSFORM_ROTATION));
    //將繪制原點(diǎn)恢復(fù)初始值,保證當(dāng)前context中心和源image的中心處在一個(gè)點(diǎn)(當(dāng)前context已經(jīng)旋轉(zhuǎn),所以繪制出的任何layer都是傾斜的)
    CGContextConcatCTM(context, CGAffineTransformMakeTranslation(-viewWidth/2, -viewHeight/2));
    
    //計(jì)算需要繪制的列數(shù)和行數(shù)
    int horCount = sqrtLength / (strWidth + HORIZONTAL_SPACE) + 1;
    int verCount = sqrtLength / (strHeight + VERTICAL_SPACE) + 1;
    
    //此處計(jì)算出需要繪制水印文字的起始點(diǎn),由于水印區(qū)域要大于圖片區(qū)域所以起點(diǎn)在原有基礎(chǔ)上移
    CGFloat orignX = -(sqrtLength-viewWidth)/2;
    CGFloat orignY = -(sqrtLength-viewHeight)/2;
    
    //在每列繪制時(shí)X坐標(biāo)疊加
    CGFloat tempOrignX = orignX;
    //在每行繪制時(shí)Y坐標(biāo)疊加
    CGFloat tempOrignY = orignY;
    for (int i = 0; i < horCount * verCount; i++) {
        [mark drawInRect:CGRectMake(tempOrignX, tempOrignY, strWidth, strHeight) withAttributes:attr];
        if (i % horCount == 0 && i != 0) {
            tempOrignX = orignX;
            tempOrignY += (strHeight + VERTICAL_SPACE);
        }else{
            tempOrignX += (strWidth + HORIZONTAL_SPACE);
        }
    }
    //根據(jù)上下文制作成圖片
    UIImage *finalImg = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    CGContextRestoreGState(context);
    return finalImg;
}
下面我們講一下原理
1.繪制源圖片

拿到源圖片,根據(jù)源圖片尺寸調(diào)用UIGraphicsBeginImageContext方法將源圖片繪制在畫(huà)布上。

2.繪制水印文字:

要想繪制出傾斜任意角度的文字首先我們需要將畫(huà)布傾斜,這樣畫(huà)出來(lái)的文字可以和沒(méi)有傾斜的圖片形成角度對(duì)比,給人感官上文字是傾斜的。
Demo中采用CGContextConcatCTM方法旋轉(zhuǎn)畫(huà)布,但是筆者查閱資料發(fā)現(xiàn)該方法并不是繞著中心點(diǎn)旋轉(zhuǎn),而是繞著繪制原點(diǎn)(也就是初始值0,0)旋轉(zhuǎn)。所以轉(zhuǎn)出來(lái)是這樣的效果。


(0,0)點(diǎn)旋轉(zhuǎn)45度

如果在這樣的畫(huà)布上繪制水印很明顯不是我們想要的。所以我們先將繪制原點(diǎn)平移到源圖片區(qū)域的中心點(diǎn),然后旋轉(zhuǎn)角度,最后在按照之前平移的X軸,Y軸數(shù)據(jù)反方向平移回去。這樣就能保證旋轉(zhuǎn)完畫(huà)布的中心點(diǎn)和源圖片的中心點(diǎn)在同一位置。


將繪制原點(diǎn)平移后旋轉(zhuǎn)
旋轉(zhuǎn)完后源路徑平移回去

注意:在旋轉(zhuǎn)過(guò)后當(dāng)前畫(huà)布的X軸,Y軸方向也跟著旋轉(zhuǎn),所以再次平移可以回到中心點(diǎn)。
這樣我們得到了一個(gè)傾斜的畫(huà)布開(kāi)始繪制文字就可以了,還需注意如果我們還按照源圖片大小的區(qū)域去繪制水印文字難免會(huì)有空白的地方(我們不知道水印要旋轉(zhuǎn)多少度),所以我們要保證不出現(xiàn)空白,采用以源圖片中心點(diǎn),長(zhǎng)寬為源圖片對(duì)角線長(zhǎng)度的繪制區(qū)域。這樣無(wú)論旋轉(zhuǎn)多少度都不會(huì)出現(xiàn)空白。如下圖:

外圈正方形為繪制區(qū)域

所以我們需要根據(jù)源圖片的長(zhǎng)寬計(jì)算出orignX和orignY(向上和向左偏移多少開(kāi)始繪制)。同時(shí)根據(jù)水印文字的長(zhǎng)寬,計(jì)算出整個(gè)繪制區(qū)域可以繪制出多少個(gè)水印,然后for循環(huán)繪制。
最后結(jié)束繪圖調(diào)用UIGraphicsGetImageFromCurrentImageContext形成一個(gè)閉合區(qū)間的圖片返回。
注意:代碼中的mostColor方法作用是:根據(jù)圖片獲取一個(gè)對(duì)比色保證水印能清楚顯示。參考地址:iOS代碼獲取圖片主色調(diào)

總結(jié)

Core Graphics是一個(gè)古老的基于C的繪圖專用API,也被稱為QuartZ或QuartZ 2D,是一個(gè)二維繪圖引擎。真如我們所知UIView底層都是覆蓋著一層CALayer,而這個(gè)CALayer正是在/System/Library/Frameworks/QuartzCore.framework中定義,所以幾乎所有的UI控件都是基于Core Graphics完成的。想要自定制UI組件Core Graphics是個(gè)很不錯(cuò)的選擇。當(dāng)然還有基于它封裝的上層API UIBezierPath。

作者:Olivia_Zqy

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容