iOS 操作像素點(diǎn)美白圖片

女神鎮(zhèn)樓
劉亦菲.jpg

我們都知道圖像美白大致有三種情況

  • 自己圖片處理算法(操作具體的像素點(diǎn))
  • 第三方開源庫(GPUImage杠愧。 openCV等等)
  • 第三方框架(閉源驰弄,收費(fèi))(face++到涂,百度圖像處理框架等等)

今天我們就講解一下圖片處理算法美白府蛇,請(qǐng)看簡(jiǎn)單的效果圖

美白前

美白前.png

美白后

美白后.png

人物雖然丑了點(diǎn)判帮,但是我們不要注意這個(gè)細(xì)節(jié)轨奄,哈哈哈哈。

書接正文

我們創(chuàng)建一個(gè)image處理類ImageUtils奠衔,里面有一個(gè)返回處理過后image的方法+ (UIImage*)imageProcess:(UIImage*)image

第一步

首先我們需要先確定圖片的大小谆刨,獲取圖片大小有兩種方式

  • image.size.width,image.size.height
  • CGImageGetWidth ,CGImageGetHeight

CGImageRef是基于像素的矩陣塘娶,每個(gè)點(diǎn)都對(duì)應(yīng)了圖片中點(diǎn)的像素信息归斤。CGImageRef是定義在QuartzCore框架中的一個(gè)結(jié)構(gòu)體指針,用C語言編寫刁岸。更加詳細(xì)的解析脏里,請(qǐng)看iOS中使用像素位圖(CGImageRef)對(duì)圖片進(jìn)行處理

獲取代碼

   CGImageRef imageFef = image.CGImage;
    NSUInteger width = CGImageGetWidth(imageFef);
    NSUInteger height = CGImageGetHeight(imageFef);
    
第二步:開辟顏色內(nèi)存空間

開辟內(nèi)存空間的目的就是:讓我們可以獲取內(nèi)存空間的指針,然后根據(jù)指針找到像素點(diǎn)虹曙,操作像素點(diǎn)

創(chuàng)建顏色空間有兩種

  • 灰色顏色空間
  • 彩色顏色空間

灰色顏色空間沒辦法進(jìn)行美白迫横,只有彩色內(nèi)存空間才能根據(jù)RGB值的改變,來增加美白功能
代碼

CGColorSpaceRef colorSpaceRef = CGColorSpaceCreateDeviceRGB();
第三步:創(chuàng)建圖片上下文

這是創(chuàng)建圖片上下文的方法酝碳,下面我們來解釋一下各個(gè)參數(shù)的意義

CCB70F8C-7347-4239-85D5-5613957AB1C9.png
參數(shù)1

我們看第一個(gè)參數(shù)可知矾踱,這是一個(gè)指針,我們需要放置一個(gè)指針疏哗。
圖片其實(shí)就是一個(gè)像素?cái)?shù)組呛讲,他是一塊內(nèi)存空間,指針指向像素?cái)?shù)組的首地址(c/c++語言語法)

圖片使用像素?cái)?shù)組組成===》由每一個(gè)像素組成===》ARGB組成==》每一個(gè)分量組成(每一個(gè)分量大蟹捣睢:8位)
也就意味著一個(gè)像素點(diǎn)最大的大斜锤椤(4*8=32)
例如:一個(gè)像素點(diǎn)組成(ARGB。RGB芽偏。R雷逆,G,B污尉, BG)
我們不知道圖片每一個(gè)像素點(diǎn)的大小是多大膀哲,所以采用最大的

代碼

UInt32 *inputPixels = (UInt32*)calloc(width * height, sizeof(UInt32));
參數(shù)2:寬
參數(shù)3:高
參數(shù)4:每一個(gè)像素點(diǎn)往产,每一個(gè)分量的大小(固定式:8位)
參數(shù)5:每一行占用的內(nèi)存大小

1某宪、計(jì)算每一個(gè)像素點(diǎn)的大形嫫搿(大小ARGB 4*8 ==》沒8位=1字節(jié) ==》4字節(jié))
2、每一行的大小 = 像素點(diǎn) * 寬 = 4 * width

參數(shù)6:顏色空間
參數(shù)7:是否有透明度

bitmapInfo : 指定bitmap是否包含alpha通道缩抡,像素中alpha通道的相對(duì)位置奠宜,像素組件是整形還是浮點(diǎn)型等信息的字符串
CGImageAlphaInfo結(jié)構(gòu)體

typedef CF_ENUM(uint32_t, CGImageAlphaInfo) {
kCGImageAlphaNone, /* For example, RGB. /
kCGImageAlphaPremultipliedLast, /
For example, premultiplied RGBA /
kCGImageAlphaPremultipliedFirst, /
For example, premultiplied ARGB /
kCGImageAlphaLast, /
For example, non-premultiplied RGBA /
kCGImageAlphaFirst, /
For example, non-premultiplied ARGB /
kCGImageAlphaNoneSkipLast, /
For example, RBGX. /
kCGImageAlphaNoneSkipFirst, /
For example, XRGB. /
kCGImageAlphaOnly /
No color data, alpha data only */
};

代碼

UInt32 *inputPixels = (UInt32*)calloc(width * height, sizeof(UInt32));

CGContextRef contextRef = CGBitmapContextCreate(inputPixels, width, height, 8, 4 * width, colorSpaceRef, kCGBitmapByteOrderDefault|kCGImageAlphaPremultipliedLast);
第四步:根據(jù)上下文繪制美白圖片

代碼

CGContextDrawImage(contextRef, CGRectMake(0, 0, width, height), imageFef);
第五步:開始美白

美白的原理:操作像素點(diǎn) ==》 操作分量 ==》 修改分量值(增或減少)
我們知道:美白處理其實(shí)就是增加RGB的各個(gè)值
0-255變化的趨勢(shì)是什么?越來越白
我們循環(huán)便利像素點(diǎn)瞻想,把每一個(gè)像素點(diǎn)的值都增加压真,結(jié)果就會(huì)出現(xiàn)美白效果。
在使用之前我們需要了解兩個(gè)概念:&,>>
不知道的同學(xué)可以參考這篇文章

首先我們定義了一些宏

#define MaskB(x) ((x) & 0xFF)
#define R(x) (MaskB(x))
#define G(x) (MaskB(x >> 8))
#define B(x) (MaskB(x >> 16))
#define A(x) (MaskB(x >> 24))
#define RGBA(r,g,b,a) (MaskB(r) | MaskB(g)<<8 | MaskB(b) << 16 | MaskB(a) << 24)

我們先討論一些怎么獲取RGB中的R,其他的都是一樣的蘑险。
我們知道滴肿,像素點(diǎn)是一排一排的向下的,示意圖

屏幕快照 2017-04-19 上午10.06.51.png
  • 我們首先獲取當(dāng)前圖片的像素點(diǎn)-->指針位移 inputPixels數(shù)組的首地址佃迄,不會(huì)變泼差。UInt32 *currnetPixels = inputPixels + (i * width) + j;

  • 然后獲取我們像素點(diǎn)對(duì)應(yīng)的顏色值(*取值 &取地址)UInt32 color = *currnetPixels;

  • 最后獲取R, G, B的值。

color 轉(zhuǎn)化為二進(jìn)制
進(jìn)行邏輯規(guī)則運(yùn)算(&:同為1 不同為0)
color = 111111 0011001 00010101 001000 (A R G B)呵俏,

代碼如下

//循環(huán)便利圖片像素點(diǎn)
    for (int i = 0; i < height; i++) {
        for (int j = 0; j < width; j++) {
            //獲取當(dāng)前圖片的像素點(diǎn) -->指針位移  inputPixels數(shù)組的首地址堆缘,不會(huì)變
            UInt32 *currnetPixels = inputPixels + (i * width) + j;
            //獲取我們像素點(diǎn)對(duì)應(yīng)的顏色值(*取值 &取地址)
            UInt32 color = *currnetPixels;
//            NSLog(@"====%d====",color);
            UInt32 thisR,thisG,thisB,thisA;
            //定義亮度
            int lumi = 50;
            //如何獲取
            //獲取紅色分量值(R)
            /*
             原理:
             已知:color = 4290822858
             0xFF 轉(zhuǎn)化為二進(jìn)制
             color 轉(zhuǎn)化為二進(jìn)制
             進(jìn)行邏輯規(guī)則運(yùn)算(&:同為1 不同為0)
             color = 111111 0011001 00010101 001000 (A R G B)
             
             */
            
            thisR = R(color);
            thisR = thisR + lumi;
            thisR = thisR > 255 ? 255 : thisR;
           // NSLog(@"紅色值:%d",thisR);
            //獲取綠色分量值
            /*
             第一步:進(jìn)行`為`運(yùn)算,向右移動(dòng)8位
             第二部:獲取G的值普碎,進(jìn)行邏輯運(yùn)算(&)
             color = 111111 0011001 00010101 001000 (A R G B)
             第三部:
             */
            thisG = G(color);
            thisG = thisG + lumi;
            thisG = thisG > 255 ? 255 : thisG;
            thisB = B(color);
            thisB = thisB + lumi;
            thisB = thisB > 255 ? 255 : thisB;
            thisA = A(color);
            
            //修改像素點(diǎn)的值
            *currnetPixels = RGBA(thisR, thisG, thisB, thisA);
            
            
        }
    }
    

第六步:創(chuàng)建UIImage

代碼

CGImageRef newImageRef = CGBitmapContextCreateImage(contextRef);
    UIImage *newImage = [UIImage imageWithCGImage:newImageRef];
第七步:釋放內(nèi)存
CGColorSpaceRelease(colorSpaceRef);
    CGContextRelease(contextRef);
    CGImageRelease(newImageRef);
    free(inputPixels);

完整代碼

+ (UIImage*)imageProcess:(UIImage*)image{
    //第一步:確定圖片的大小
    CGImageRef imageFef = image.CGImage;
    NSUInteger width = CGImageGetWidth(imageFef);
    NSUInteger height = CGImageGetHeight(imageFef);
    
   第二部:創(chuàng)建顏色空間(開辟內(nèi)存空間吼肥,目的:操作像素點(diǎn))
    CGColorSpaceRef colorSpaceRef = CGColorSpaceCreateDeviceRGB();
    
    //第三部:創(chuàng)建圖片上下文
   UInt32 *inputPixels = (UInt32*)calloc(width * height, sizeof(UInt32));
    
    CGContextRef contextRef = CGBitmapContextCreate(inputPixels, width, height, 8, 4 * width, colorSpaceRef, kCGBitmapByteOrderDefault|kCGImageAlphaPremultipliedLast);
    
    //第四步:根據(jù)上下文繪制美白圖片
    CGContextDrawImage(contextRef, CGRectMake(0, 0, width, height), imageFef);
    
    //第五部:正式開始美白
   
    //循環(huán)便利圖片像素點(diǎn)
    for (int i = 0; i < height; i++) {
        for (int j = 0; j < width; j++) {
            //獲取當(dāng)前圖片的像素點(diǎn) -->指針位移  inputPixels數(shù)組的首地址,不會(huì)變
            UInt32 *currnetPixels = inputPixels + (i * width) + j;
            //獲取我們像素點(diǎn)對(duì)應(yīng)的顏色值(*取值 &取地址)
            UInt32 color = *currnetPixels;
//            NSLog(@"====%d====",color);
            UInt32 thisR,thisG,thisB,thisA;
            //定義亮度
            int lumi = 50;
            //如何獲取
            //獲取紅色分量值(R)
          
            thisR = R(color);
            thisR = thisR + lumi;
            thisR = thisR > 255 ? 255 : thisR;
           // NSLog(@"紅色值:%d",thisR);
            //獲取綠色分量值
           
            thisG = G(color);
            thisG = thisG + lumi;
            thisG = thisG > 255 ? 255 : thisG;
            thisB = B(color);
            thisB = thisB + lumi;
            thisB = thisB > 255 ? 255 : thisB;
            thisA = A(color);
            
            //修改像素點(diǎn)的值
            *currnetPixels = RGBA(thisR, thisG, thisB, thisA);
            
            
        }
    }
    
    //創(chuàng)建UIImage
    CGImageRef newImageRef = CGBitmapContextCreateImage(contextRef);
    UIImage *newImage = [UIImage imageWithCGImage:newImageRef];
    
    //第七步:釋放內(nèi)存
    CGColorSpaceRelease(colorSpaceRef);
    CGContextRelease(contextRef);
    CGImageRelease(newImageRef);
    free(inputPixels);
    
    
    return newImage;
}

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末麻车,一起剝皮案震驚了整個(gè)濱河市缀皱,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌动猬,老刑警劉巖啤斗,帶你破解...
    沈念sama閱讀 221,576評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異赁咙,居然都是意外死亡钮莲,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,515評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門序目,熙熙樓的掌柜王于貴愁眉苦臉地迎上來臂痕,“玉大人,你說我怎么就攤上這事猿涨∥胀” “怎么了?”我有些...
    開封第一講書人閱讀 168,017評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵叛赚,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我,道長(zhǎng)豺总,這世上最難降的妖魔是什么犁功? 我笑而不...
    開封第一講書人閱讀 59,626評(píng)論 1 296
  • 正文 為了忘掉前任恨诱,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己揪胃,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,625評(píng)論 6 397
  • 文/花漫 我一把揭開白布氛琢。 她就那樣靜靜地躺著喊递,像睡著了一般。 火紅的嫁衣襯著肌膚如雪阳似。 梳的紋絲不亂的頭發(fā)上骚勘,一...
    開封第一講書人閱讀 52,255評(píng)論 1 308
  • 那天,我揣著相機(jī)與錄音撮奏,去河邊找鬼俏讹。 笑死,一個(gè)胖子當(dāng)著我的面吹牛畜吊,可吹牛的內(nèi)容都是我干的泽疆。 我是一名探鬼主播,決...
    沈念sama閱讀 40,825評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼定拟,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼于微!你這毒婦竟也來了逗嫡?” 一聲冷哼從身側(cè)響起青自,我...
    開封第一講書人閱讀 39,729評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎驱证,沒想到半個(gè)月后延窜,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,271評(píng)論 1 320
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡抹锄,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,363評(píng)論 3 340
  • 正文 我和宋清朗相戀三年逆瑞,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片伙单。...
    茶點(diǎn)故事閱讀 40,498評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡获高,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出吻育,到底是詐尸還是另有隱情念秧,我是刑警寧澤,帶...
    沈念sama閱讀 36,183評(píng)論 5 350
  • 正文 年R本政府宣布布疼,位于F島的核電站摊趾,受9級(jí)特大地震影響币狠,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜砾层,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,867評(píng)論 3 333
  • 文/蒙蒙 一漩绵、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧肛炮,春花似錦止吐、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,338評(píng)論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至粟害,卻和暖如春蕴忆,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背悲幅。 一陣腳步聲響...
    開封第一講書人閱讀 33,458評(píng)論 1 272
  • 我被黑心中介騙來泰國(guó)打工套鹅, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人汰具。 一個(gè)月前我還...
    沈念sama閱讀 48,906評(píng)論 3 376
  • 正文 我出身青樓卓鹿,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親留荔。 傳聞我的和親對(duì)象是個(gè)殘疾皇子吟孙,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,507評(píng)論 2 359

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