iOS 圖片抖動(dòng)算法

弗洛伊德-斯坦伯格抖動(dòng)算法

這是一個(gè)真實(shí)的魔法技術(shù)。它愚弄了你的眼睛和大腦,讓你以為自己看到的顏色要比實(shí)際的多纽绍。
image.png
一般來說,抖動(dòng)是通過增加人工噪聲去減少一個(gè)圖像的顏色空間势似,主旨在于拌夏,一個(gè)區(qū)域的光量應(yīng)該保持一致。
image.png
弗洛伊德-斯坦伯格抖動(dòng)算法對(duì)周圍的像素使用非均勻分布的量化誤差達(dá)到抖動(dòng)的目的履因。這就意味著要先將中心像素四舍五入為0或1障簿,而后將殘差加入其周圍的像素中。
image.png
以上你看到的三張圖片都是灰階抖動(dòng)的栅迄,它們?nèi)慷际侵挥蓛煞N顏色的噪音組成站故,而其余的信息,當(dāng)然是因?yàn)槟愕拇竽X在轉(zhuǎn)嘍毅舆。

算法實(shí)現(xiàn)

#pragma mark - 分配內(nèi)存
 uint32_t* oldImageBuf = (uint32_t*)malloc(bytesPerRow * imageHeight);
 uint32_t* newImageBuf = (uint32_t*)malloc(bytesPerRow * imageHeight);
#pragma mark - 創(chuàng)建context
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();// 色彩范圍的容器
CGContextRef oldContext = CGBitmapContextCreate(oldImageBuf, imageWidth, imageHeight, 8, bytesPerRow, colorSpace,kCGBitmapByteOrder32Little | kCGImageAlphaNoneSkipLast);
CGContextDrawImage(oldContext, CGRectMake(0, 0, imageWidth, imageHeight), self.CGImage);
CGContextRef newContext = CGBitmapContextCreate(newImageBuf, imageWidth, imageHeight, 8, bytesPerRow, colorSpace,kCGBitmapByteOrder32Little | kCGImageAlphaNoneSkipLast);
CGContextDrawImage(newContext, CGRectMake(0, 0, imageWidth, imageHeight), self.CGImage);
#pragma mark -遍歷像素計(jì)算殘差
 //殘差
                    int eRgb[3];
                    if (nearColor == 0) {
                        newptr[3] = 0;
                        newptr[2] = 0;
                        newptr[1] = 0;
                        newptr[0] = 255;
                        eRgb[0] = r;
                        eRgb[1] = g;
                        eRgb[2] = b;
                    } else {
                        newptr[3] = 255;
                        newptr[2] = 255;
                        newptr[1] = 255;
                        newptr[0] = 255;
                        eRgb[0] = r-255;
                        eRgb[1] = g-255;
                        eRgb[2] = b-255;
                    }
                    //殘差 16分之 7西篓、5、3憋活、1
                    float rate1 = 0.4375;
                    float rate2 = 0.3125;
                    float rate3 = 0.1875;
                    float rate4 = 0.0625;
                    uint32_t rgb1 = [self getPixel:oldImageBuf width:imageWidth height:imageHeight row:row column:column+1 rate:rate1 eRgb:eRgb];
                    uint32_t rgb2 = [self getPixel:oldImageBuf width:imageWidth height:imageHeight row:row+1 column:column rate:rate2 eRgb:eRgb];
                    uint32_t rgb3 = [self getPixel:oldImageBuf width:imageWidth height:imageHeight row:row+1 column:column-1 rate:rate3 eRgb:eRgb];
                    uint32_t rgb4 = [self getPixel:oldImageBuf width:imageWidth height:imageHeight row:row+1 column:column+1 rate:rate4 eRgb:eRgb];
                    [self setPixel:oldImageBuf width:imageWidth height:imageHeight row:row column:column+1 value:rgb1];
                    [self setPixel:oldImageBuf width:imageWidth height:imageHeight row:row+1 column:column value:rgb2];
                    [self setPixel:oldImageBuf width:imageWidth height:imageHeight row:row+1 column:column-1 value:rgb3];
                    [self setPixel:oldImageBuf width:imageWidth height:imageHeight row:row+1 column:column+1 value:rgb4];
#pragma mark - 獲取像素
- (uint32_t)getPixel:(uint32_t*)imageBuf width:(int)width height:(int)height   row:(int)row column:(int)column rate:(float)rate eRgb:(int *)eRgb {
    if (row < 0 || row >= height || column < 0 || column >= width) {
        return 0xFFFFFFFF;
    }
    int index = row * width + column;
    uint32_t *ptr = imageBuf + index;
    uint8_t* newptr = (uint8_t*)ptr;
    uint8_t r = newptr[3];
    uint8_t g = newptr[2];
    uint8_t b = newptr[1];
    uint8_t a = newptr[0];
    int er = eRgb[0];
    int eg = eRgb[1];
    int eb = eRgb[2];
    r = clamp(r + (int)(rate*er));
    g = clamp(g + (int)(rate*eg));
    b = clamp(b + (int)(rate*eb));
    return (r << 24) + (g << 16) + (b << 8) + a;
}

#pragma mark - 設(shè)置像素
- (void)setPixel:(uint32_t*)imageBuf width:(int)width height:(int)height   row:(int)row column:(int)column value:(uint32_t)value {
    if (row < 0 || row >= height || column < 0 || column >= width) {
        return;
    }
    int index = row * width + column;
    uint32_t *ptr = imageBuf + index;
    uint8_t* newptr = (uint8_t*)ptr;
    int r = (value & 0xFF000000) >> 24;
    int g = (value & 0x00FF0000) >> 16;
    int b = (value & 0x0000FF00) >> 8;
    int a = value & 0x000000FF;

    newptr[3] = r;
    newptr[2] = g;
    newptr[1] = b;
    newptr[0] = a;
}

總結(jié)

圖片抖動(dòng)算法就是獲取當(dāng)前點(diǎn)的像素與相鄰的點(diǎn)的像素比較,并進(jìn)行相應(yīng)處理的過程,是一個(gè)區(qū)域的光量保持一致

代碼傳送門

請(qǐng)關(guān)注我的專題 iOS - Developer - OC 進(jìn)階大全

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末岂津,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子悦即,更是在濱河造成了極大的恐慌吮成,老刑警劉巖橱乱,帶你破解...
    沈念sama閱讀 218,386評(píng)論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異粱甫,居然都是意外死亡泳叠,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,142評(píng)論 3 394
  • 文/潘曉璐 我一進(jìn)店門茶宵,熙熙樓的掌柜王于貴愁眉苦臉地迎上來析二,“玉大人,你說我怎么就攤上這事节预。” “怎么了属韧?”我有些...
    開封第一講書人閱讀 164,704評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵安拟,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我宵喂,道長(zhǎng)糠赦,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,702評(píng)論 1 294
  • 正文 為了忘掉前任锅棕,我火速辦了婚禮拙泽,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘裸燎。我一直安慰自己顾瞻,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,716評(píng)論 6 392
  • 文/花漫 我一把揭開白布德绿。 她就那樣靜靜地躺著荷荤,像睡著了一般。 火紅的嫁衣襯著肌膚如雪移稳。 梳的紋絲不亂的頭發(fā)上蕴纳,一...
    開封第一講書人閱讀 51,573評(píng)論 1 305
  • 那天,我揣著相機(jī)與錄音个粱,去河邊找鬼古毛。 笑死,一個(gè)胖子當(dāng)著我的面吹牛都许,可吹牛的內(nèi)容都是我干的稻薇。 我是一名探鬼主播,決...
    沈念sama閱讀 40,314評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼梭稚,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼颖低!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起弧烤,我...
    開封第一講書人閱讀 39,230評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤忱屑,失蹤者是張志新(化名)和其女友劉穎蹬敲,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體莺戒,經(jīng)...
    沈念sama閱讀 45,680評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡伴嗡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,873評(píng)論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了从铲。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片瘪校。...
    茶點(diǎn)故事閱讀 39,991評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖名段,靈堂內(nèi)的尸體忽然破棺而出阱扬,到底是詐尸還是另有隱情,我是刑警寧澤伸辟,帶...
    沈念sama閱讀 35,706評(píng)論 5 346
  • 正文 年R本政府宣布麻惶,位于F島的核電站,受9級(jí)特大地震影響信夫,放射性物質(zhì)發(fā)生泄漏窃蹋。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,329評(píng)論 3 330
  • 文/蒙蒙 一静稻、第九天 我趴在偏房一處隱蔽的房頂上張望警没。 院中可真熱鬧,春花似錦振湾、人聲如沸杀迹。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,910評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)佛南。三九已至,卻和暖如春嵌言,著一層夾襖步出監(jiān)牢的瞬間嗅回,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,038評(píng)論 1 270
  • 我被黑心中介騙來泰國(guó)打工摧茴, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留绵载,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,158評(píng)論 3 370
  • 正文 我出身青樓苛白,卻偏偏與公主長(zhǎng)得像娃豹,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子购裙,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,941評(píng)論 2 355

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

  • 那些想獲得精神分析知識(shí)的人們所面臨的困難很多懂版,尤其是缺乏一本適用的教科書可用以開始他們的研究。這些人從前可在三類課...
    暖陽(yáng)_1332閱讀 1,036評(píng)論 0 1
  • 正確寫法應(yīng)該是:弗洛伊德 弗洛伊德生平 作為一個(gè)治療精神疾病的醫(yī)生躏率,弗洛伊德創(chuàng)立了一個(gè)涉及人類心理結(jié)構(gòu)和功能的學(xué)說...
    昭的私房家伙閱讀 520評(píng)論 0 0
  • 一直到要放寒假躯畴,嚴(yán)安也沒有來找過蘇瑾芮民鼓。兩個(gè)人即使在路上碰到,也會(huì)裝作不認(rèn)識(shí)蓬抄,匆匆走過丰嘉。蘇瑾芮在心里偷偷松了口氣,...
    趙小作z閱讀 469評(píng)論 0 43
  • Objective-c 線程系列一 atomic是安全的嗎Objective-c 線程系列二 @synchro...
    海森V閱讀 372評(píng)論 0 0
  • 想要寫點(diǎn)東西很久了,嗯阅爽,卻只是想路幸。深夜不是工作,不是考慮寫什么付翁,只是單純的玩的太晚了劝赔。看著看著胆敞,總要開始,這便是開...
    南瓜芝士呢閱讀 389評(píng)論 0 0