精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

用函數式的 Swift 實現圖片轉字符畫的功能

移動開發 iOS
今天整理 Pocket 中待看的文章,看到這篇《Creating ASCII art in functional Swift》,講解如何用 Swift 將圖片轉成 ASCII 字符。具體原理文中講解的很詳細,不再贅述,但是標題中的 in functional Swift 讓我很感興趣,想知道 functional 到底體現在哪里,于是下載 swift-ascii-art 源碼一探究竟。

今天整理 Pocket 中待看的文章,看到這篇《Creating ASCII art in functional Swift》,講解如何用 Swift 將圖片轉成 ASCII 字符。具體原理文中講解的很詳細,不再贅述,但是標題中的 in functional Swift 讓我很感興趣,想知道 functional 到底體現在哪里,于是下載 swift-ascii-art 源碼一探究竟。

Pixel

圖片是由各個像素點組成的,在代碼中像素通過 Pixel 這個 struct 實現。每個像素分配了4個字節,這4個字節 (2^8 = 256) 分別用來存儲 RBGA 的值。

createPixelMatrix

可以通過 createPixelMatrix 這個靜態方法創建一個 width * height 像素矩陣:

  1. static func createPixelMatrix(width: Int, _ height: Int) -> [[Pixel]] { 
  2. return map(0.. map(0.. let offset = (width * row + col) * Pixel.bytesPerPixel 
  3. return Pixel(offset) 


和傳統方法中使用 for 循環來創建多維數組有所不同的是,這里是通過 map 函數實現的。在 Swift 2.0 中, map 函數已經被干掉了,只能作為方法調用。

intensityFromPixelPointer

intensityFromPixelPointer 方法計算并返回像素點的亮度值,代碼如下:

  1. func intensityFromPixelPointer(pointer: PixelPointer) -> Double { 
  2. let 
  3. red = pointer[offset + 0], 
  4. green = pointer[offset + 1], 
  5. blue = pointer[offset + 2
  6. return Pixel.calculateIntensity(red, green, blue) 
  7. private static func calculateIntensity(r: UInt8, _ g: UInt8, _ b: UInt8) -> Double { 
  8. let 
  9. redWeight = 0.229
  10. greenWeight = 0.587
  11. blueWeight = 0.114
  12. weightedMax = 255.0 * redWeight + 
  13. 255.0 * greenWeight + 
  14. 255.0 * blueWeight, 
  15. weightedSum = Double(r) * redWeight + 
  16. Double(g) * greenWeight + 
  17. Double(b) * blueWeight 
  18. return weightedSum / weightedMax 

calculateIntensity 方法基于 Y’UV 編碼獲取某個像素的亮度 (intensity) :

  1. Y’ = 0.299 R’ + 0.587 G’ + 0.114 B’ 

YUV 是一種顏色編碼方法,Y 表示亮度, UV 用來表示色差, U 和 V 是構成彩色的兩個分量。它的優點是可以利用人眼的特性來降低數字彩色圖像所需要的存儲容量。我們通過這個公式獲取到的 Y 就是亮度的值。

Offset

Pixel 中其實只存了一個值: offset 。 Pixel.createPixelMatrix 創建出來的矩陣是這樣的:

  1. [[048, ...], ...] 

并沒有像想象中那樣存儲了每個像素相關數據,而更像是一個轉換工具,計算 PixelPointer 的灰度值。

AsciiArtist

AsciiArtist 里封裝了一些生成字符畫的方法。

createAsciiArt

createAsciiArt 方法就是創建字符畫:

  1. func createAsciiArt() -> String { 
  2. let 
  3. // 加載圖片數據,獲取指針對象 
  4. dataProvider = CGImageGetDataProvider(image.CGImage), 
  5. pixelData = CGDataProviderCopyData(dataProvider), 
  6. pixelPointer = CFDataGetBytePtr(pixelData), 
  7. // 將圖片轉成亮度值矩陣 
  8. intensities = intensityMatrixFromPixelPointer(pixelPointer), 
  9. // 將亮度值轉成對應字符 
  10. symbolMatrix = symbolMatrixFromIntensityMatrix(intensities) 
  11. return join("\n", symbolMatrix) 

其中 CFDataGetBytePtr 函數返回了圖像的字節數組指針,數組里每個元素都是一個字節,即 0~255 的整數。每4個字節組成了一個 Pixel ,分別對應著 RGBA 的值。

intensityMatrixFromPixelPointer

intensityMatrixFromPixelPointer 這個方法是通過 PixelPointer 生成對應的亮度值矩陣:

  1. private func intensityMatrixFromPixelPointer(pointer: PixelPointer) -> [[Double]] 
  2. let 
  3. width = Int(image.size.width), 
  4. height = Int(image.size.height), 
  5. matrix = Pixel.createPixelMatrix(width, height) 
  6. return matrix.map { pixelRow in 
  7. pixelRow.map { pixel in 
  8. pixel.intensityFromPixelPointer(pointer) 

首先通過 Pixel.createPixelMatrix 方法創建了一個空的二維數組,用來存放數值。然后用兩個 map 嵌套遍歷里面的所有元素,將像素 (pixel) 轉換成亮度 (intensity) 的值。

symbolMatrixFromIntensityMatrix

symbolMatrixFromIntensityMatrix 函數將亮度值數組轉換成字符畫數組:

  1. private func symbolMatrixFromIntensityMatrix(matrix: [[Double]]) -> [String] 
  2. return matrix.map { intensityRow in 
  3. intensityRow.reduce("") { 
  4. $0 + self.symbolFromIntensity($1

map + reduce 成功實現了字符串的累加,每次 reduce 都是通過 symbolFromIntensity 方法獲取到亮度值對應的字符。 symbolFromIntensity 方法如下:

  1. private func symbolFromIntensity(intensity: Double) -> String 
  2. assert(0.0 <= intensity && intensity <= 1.0
  3. let 
  4. factor = palette.symbols.count - 1
  5. value = round(intensity * Double(factor)), 
  6. index = Int(value) 
  7. return palette.symbols[index] 

傳入 intensity ,在確保了值的范圍是 0 ~ 1 之后,通過 AsciiPalette 將它轉換成對應的字符,輸出 sumbol 。

AsciiPalette

AsciiPalette 是用來將數值轉換成字符的工具,像是一個字符畫里的調色板一樣,根據不同的顏色生成字符。

loadSymbols

loadSymbols 加載了所有的字符:

  1. private func loadSymbols() -> [String] 
  2. return symbolsSortedByIntensityForAsciiCodes(32...126// from ' ' to '~' 

可以看到,我們選用的字符范圍是 32 ~ 126 的字符,接下來就是通過 symbolsSortedByIntensityForAsciiCodes 方法將這些字符按照亮度進行排序。比如 & 符號肯定代表著比 . 暗的區域,那么它是如何比較的呢?請看排序方法。

symbolsSortedByIntensityForAsciiCodes

symbolsSortedByIntensityForAsciiCodes 方法實現了字符串的生成和排序:

  1. private func symbolsSortedByIntensityForAsciiCodes(codes: Range) -> [String] 
  2. let 
  3. // 通過 Ascii 碼生成字符數組備用 
  4. symbols = codes.map { self.symbolFromAsciiCode($0) }, 
  5. // 將字符繪制出來,把字符數組轉換成圖片數組,用于比較亮度 
  6. symbolImages = symbols.map { UIImage.imageOfSymbol($0, self.font) }, 
  7. // 將圖片數組轉換成亮度值數組,亮度值的表現形式是圖片中白色像素的個數 
  8. whitePixelCounts = symbolImages.map { self.countWhitePixelsInImage($0) }, 
  9. // 將字符數組通過亮度值就行排序 
  10. sortedSymbols = sortByIntensity(symbols, whitePixelCounts) 
  11. return sortedSymbols 

其中, sortByIntensity 這個排序方法如下:

  1. private func sortByIntensity(symbols: [String], _ whitePixelCounts: [Int]) -> [String] 
  2. let 
  3. // 用字典建立 白色像素數目 和 字符 之間的關系 
  4. mappings = NSDictionary(objects: symbols, forKeys: whitePixelCounts), 
  5. // 白色像素數目數組去重 
  6. uniqueCounts = Set(whitePixelCounts), 
  7. // 白色像素數目數組排序 
  8. sortedCounts = sorted(uniqueCounts), 
  9. // 利用前面的字典映射,將排序后的白色像素數目轉換成對應的字符,從而輸出有序數組 
  10. sortedSymbols = sortedCounts.map { mappings[$0] as! String } 
  11. return sortedSymbols 

小結

簡單了過了一下項目,可以隱約感覺到一些函數式風格的氣息,主要體現在一下幾個方面:

map reduce 等函數的應用恰到好處,自如處理數組的轉換和拼接。

通過 input 和 output 進行數據處理,比如 sortByIntensity 方法和 symbolFromIntensity 方法。

很少有狀態和屬性,更多的是直接的函數轉換,函數邏輯不依賴外部變量,只依賴于傳入的參數

代碼感覺簡單輕快。通過這個簡單的小例子,驗證了前面在 函數式的特性 中學習到的東西。

感覺很贊!

責任編輯:chenqingxiang 來源: Why's blog
相關推薦

2015-08-03 11:42:27

Swift漢堡式過度動畫

2015-03-18 09:39:10

函數編程Swift

2009-11-26 13:52:07

PHP字符串替換函數s

2013-07-23 13:06:50

2009-06-16 11:49:00

JQuery實現loaWCF

2021-08-26 05:27:57

Swift 監聽系統泛型

2014-07-15 09:26:13

swiftiosMPGNotifica

2023-09-08 09:12:57

內存緩存圖像

2009-11-30 15:10:46

PHP substr函

2022-12-30 17:18:04

2009-12-07 16:44:45

PHP圖形處理函數

2009-09-11 10:44:07

JavaScript實

2009-11-30 17:49:51

PHP函數preg_s

2021-08-27 08:38:10

CSS 技巧 resize

2017-09-01 15:42:00

MySQLOracledblink功能

2009-06-19 14:23:41

RMIJava分布式計算

2021-12-09 10:45:19

分布式事務框架

2021-02-25 15:14:12

鴻蒙HarmonyOS應用開發

2012-05-17 16:34:28

思亞諾美滿電子

2015-01-06 16:41:32

Swiftenum多選
點贊
收藏

51CTO技術棧公眾號

国产一区调教| 国精一区二区三区| 精品综合久久久久久8888| 久久视频在线直播| 男女一区二区三区| av在线日韩| 亚洲一区视频在线| 日本中文不卡| 三级网站免费观看| 麻豆精品一区二区av白丝在线| 久久影院在线观看| 国产精品九九九九九| 日韩免费在线电影| 偷拍日韩校园综合在线| 亚洲资源在线网| 五月婷婷综合久久| 国产制服丝袜一区| 欧美综合在线观看| 久草视频中文在线| 欧美日韩在线播放视频| 亚洲第一区中文99精品| 中文字幕永久有效| 久久爱91午夜羞羞| 亚洲国产精品久久人人爱| 亚洲欧美日韩另类精品一区二区三区 | 日本久久久久久久| 久久久久久久国产视频| 日韩中文在线电影| 亚洲精品视频网上网址在线观看 | 免费精品一区二区三区在线观看| 欧美性色视频在线| 国产曰肥老太婆无遮挡| 日本三级在线播放完整版| 97精品国产97久久久久久久久久久久| 成人免费网站在线观看| 欧美综合激情| 国产成人久久婷婷精品流白浆| 国产精品久久久久久福利| 久久伊99综合婷婷久久伊| 粉嫩高清一区二区三区精品视频 | 日本欧美电影在线观看| 国产精品剧情在线亚洲| 欧美日韩三区四区| 爽爽视频在线观看| 成人av免费在线观看| 91免费观看网站| 中文在线免费看视频| 亚洲影音先锋| 久久久久久成人精品| 亚洲一级生活片| 99久久这里只有精品| 国产亚洲精品久久久久久777| 亚洲第一页av| 日韩高清成人在线| 日韩电影免费观看中文字幕| 国产激情第一页| 国产精品调教| 亚洲精品国产综合久久| 亚洲熟女乱综合一区二区三区| 精品网站aaa| 亚洲精品97久久| 黄色性生活一级片| 久久爱www成人| 亚洲欧洲在线观看| 精品无码在线观看| 久久神马影院| 欧美区二区三区| 国产精品成人av久久| 99精品热6080yy久久| 欧美在线观看视频| 超碰在线97观看| 美日韩一区二区三区| 成人h视频在线| 亚洲av无码国产精品久久不卡| 成人黄色网址在线观看| 国内精品一区二区| 国产一区二区三区不卡在线| 国产精品久久久爽爽爽麻豆色哟哟| 一区二区三视频| 最爽无遮挡行房视频在线| 亚洲影院理伦片| 日本中文字幕网址| 国产精品久久亚洲不卡| 91精品午夜视频| 尤物网站在线观看| 黑丝美女一区二区| 欧美另类在线观看| wwwwww国产| 麻豆视频观看网址久久| 999精品视频一区二区三区| 色噜噜一区二区三区| 国产日本欧洲亚洲| 777久久精品一区二区三区无码| 阿v视频在线| 欧美日韩精品一区二区三区 | 伊人网中文字幕| 国产经典欧美精品| 日本一区免费在线观看| 国产高清一区二区三区视频| 欧美日韩免费一区| 激情五月婷婷基地| 亚洲免费福利一区| 久久6免费高清热精品| 亚洲av无码精品一区二区| 国产在线视频精品一区| 牛人盗摄一区二区三区视频| 成人在线观看亚洲| 色呦呦国产精品| 少妇献身老头系列| 欧美1级片网站| 欧美一级大片在线免费观看| a级片在线播放| 国产日韩v精品一区二区| 国产欧美日韩小视频| 成人免费视频观看| 日韩精品免费在线视频| 欧美日韩大片在线观看| 丝袜美腿成人在线| 精品国产二区在线| 狂野欧美性猛交xxxxx视频| 欧美色网一区二区| 美女脱光内衣内裤| 亚洲美女一区| 国产精品久久久久久免费观看| 日本三级视频在线播放| 欧美亚洲一区三区| 蜜桃精品一区二区| 夜夜嗨av一区二区三区网站四季av| 92看片淫黄大片看国产片| av在线电影观看| 日本道免费精品一区二区三区| 日本不卡视频一区| 欧美亚韩一区| 91高跟黑色丝袜呻吟在线观看| 色视频在线免费观看| 欧美在线观看你懂的| 亚洲做受高潮无遮挡| 99热在线精品观看| 国产在线一区二区三区欧美| av中文资源在线资源免费观看| 日韩一区二区三区高清免费看看| tube国产麻豆| 国内成人免费视频| 色撸撸在线观看| 91精品福利观看| 久久精彩免费视频| 91亚洲欧美激情| 最新日韩av在线| 污免费在线观看| 欧美国产免费| 97超碰人人看人人| 欧洲性视频在线播放| 精品美女在线观看| 国产污视频在线看| 91亚洲午夜精品久久久久久| 国产精品后入内射日本在线观看| 日韩超碰人人爽人人做人人添| 欧美一区亚洲一区| 蜜桃视频在线免费| 欧亚洲嫩模精品一区三区| 中文字幕第二区| 九九热在线视频观看这里只有精品| 久久久国产精华液999999| 欧美激情三级| 久久久久国产视频| 欧洲亚洲在线| 欧美日韩一区三区| 成人免费精品动漫网站| 国产91精品一区二区| 无码专区aaaaaa免费视频| 亚瑟一区二区三区四区| 国产精品免费小视频| 久久综合之合合综合久久| 日韩欧美一级二级| 成人免费区一区二区三区| 久久久www免费人成精品| 九色porny自拍| 午夜日本精品| 久久久久一区二区| 欧美成a人片免费观看久久五月天| 久久九九有精品国产23| 亚洲第一大网站| 粉嫩av一区二区三区免费野| 国产在视频线精品视频| 国产精品99久久久久| 久久综合九色综合88i| 波多野结衣在线观看一区二区| 亚洲专区在线视频| 午夜伦理福利在线| 精品国产拍在线观看| 手机在线观看免费av| 欧美日韩一区二区三区不卡 | 日韩成人影视| 亚洲大胆人体视频| 欧美成人精品网站| 亚洲一二三级电影| 天天操天天舔天天射| 成人免费三级在线| 91精品无人成人www| 一区免费视频| 一个色的综合| 偷拍亚洲色图| 成人动漫视频在线观看免费| 日本.亚洲电影| 久久久久久久久电影| 午夜视频在线观看网站| 日韩国产精品视频| www.97超碰| 在线中文字幕不卡| 国产大片中文字幕| 中文字幕一区二区三| 中文乱码人妻一区二区三区视频| 久久99热这里只有精品| 日韩欧美一区三区| 欧美日韩视频一区二区三区| 偷拍视频一区二区| 亚洲传媒在线| 国产三级精品在线不卡| 国产一区二区三区亚洲综合| 国产成人啪精品视频免费网| 91av久久| 欧美精品久久久久久久免费观看| 国产精品实拍| 中文字幕日韩av电影| 日中文字幕在线| 亚洲国产精品成人精品| 精品欧美一区二区精品少妇| 欧美日韩国产大片| 337p粉嫩色噜噜噜大肥臀| 第一福利永久视频精品| 国产真实夫妇交换视频| 亚洲男同性恋视频| 中文字幕五月天| 亚洲色图欧美在线| 国产真人真事毛片视频| 久久久www成人免费毛片麻豆 | 欧美aaaa视频| 手机在线观看国产精品| 久久99国产精一区二区三区| 久久免费视频1| 色爱av综合网| 麻豆av一区二区| 亚洲自拍电影| 欧美一区二区福利| 精品国产精品久久一区免费式| 久久资源av| 九九视频免费观看视频精品| 免费久久久一本精品久久区| 中日韩免视频上线全都免费| 久久亚洲综合网| 精品产国自在拍| 亚洲精品中字| 91精品福利| 免费的一级黄色片| 亚洲高清毛片| 国产成人a亚洲精v品无码| 国产一区二区三区久久久久久久久| 极品美女扒开粉嫩小泬| 免费永久网站黄欧美| 欧美视频第三页| 美腿丝袜在线亚洲一区| 国产资源中文字幕| 成人综合在线观看| 久久精品国产亚洲av麻豆| 欧美国产禁国产网站cc| 一起操在线播放| 亚洲国产乱码最新视频| 成人免费看片98欧美| 欧美中文字幕一二三区视频| 国产一区二区小视频| 欧美成人vr18sexvr| 日本在线丨区| 精品国产一区二区三区四区在线观看 | 亚洲欧美另类久久久精品2019| 久久精品久久国产| 色婷婷av久久久久久久| 一区二区三区免费在线视频| 欧美草草影院在线视频| 免费黄网站在线观看| 日韩中文字幕视频在线观看| 亚洲奶水xxxx哺乳期| 欧美在线日韩在线| 日本亚洲欧洲无免费码在线| 国产99午夜精品一区二区三区| 欧美热在线视频精品999| 亚洲欧美日韩不卡| 一本色道久久| 日韩av加勒比| 久久亚洲精品小早川怜子| 疯狂撞击丝袜人妻| 精品国产老师黑色丝袜高跟鞋| 中文在线字幕av| 亚洲成年人在线| 97最新国自产拍视频在线完整在线看| 欧美黑人极品猛少妇色xxxxx| 亚洲www免费| a级国产乱理论片在线观看99| 国产免费播放一区二区| 亚洲欧美韩国综合色| 久久久国产精品久久久| 久久久精品欧美丰满| 久久久精品99| 欧美日韩国产影片| 天天干免费视频| 欧美成人午夜视频| 天天免费亚洲黑人免费| 成人一区二区在线| 日韩精品网站| 精品免费国产一区二区| 成人美女在线视频| 午夜国产福利一区二区| 色狠狠桃花综合| 亚洲 欧美 激情 另类| 毛片精品免费在线观看| 91精品国产66| 欧美精品国产精品久久久| 黑人一区二区三区四区五区| 波多野结衣天堂| 久久久久国产精品麻豆ai换脸 | 亚洲精品日韩av| 精品精品99| 黄色a级片免费| 99久久婷婷国产综合精品| 99热精品免费| 亚洲国产精品自拍| 99热这里只有精品3| 色阁综合伊人av| 久久电影天堂| 亚洲精品日韩成人| 日韩国产欧美在线视频| 国产人妻一区二区| 日韩欧美999| 色综合888| 欧美怡春院一区二区三区| 老汉色老汉首页av亚洲| 欧美国产日韩激情| 不卡的av在线播放| 国产一区二区三区影院| 亚洲小说欧美另类婷婷| 97se国产在线视频| 欧美 日韩 国产精品免费观看| 亚洲高清在线不卡| 中文字幕人成不卡一区| 一级黄色a视频| 日韩在线视频线视频免费网站| 日本成人片在线| 色姑娘综合网| 麻豆国产一区二区| 欧美日韩生活片| 欧美日韩精品综合在线| 麻豆网站在线观看| 91九色视频导航| 欧美日韩一区自拍| 在线观看成人动漫| 欧美日韩亚洲高清| 国产原创av在线| 国产一区二区在线免费视频| 999久久久91| 欧美体内she精高潮| 亚洲一区二区综合| 亚洲人妻一区二区三区| 欧洲午夜精品久久久| 欧美日韩在线二区| 亚洲精品永久视频| 亚洲一区二区三区精品在线| 日本加勒比一区| 日本国产精品视频| 欧美日韩在线播放视频| 一级黄色大片儿| 亚洲成年人影院| 免费在线黄色网址| 成人av.网址在线网站| 欧美国产三级| 好吊日免费视频| 欧美另类videos死尸| 欧美24videosex性欧美| 免费日韩av电影| 久久99精品久久久久婷婷| 日本免费在线播放| 国产亚洲精品美女久久久| 日本精品视频| 欧美日韩在线不卡视频| 成人免费在线观看入口| 欧日韩在线视频| 国产精品一二三视频| 欧美日韩1区2区3区| www.久久av| 日韩视频免费观看高清在线视频| 日韩av影片| 日韩精品福利片午夜免费观看| 91婷婷韩国欧美一区二区| 91成年人视频| 欧美一区二区色| 一区二区三区在线| aaaaa级少妇高潮大片免费看| 欧美一区二区三区免费在线看| 欧美1级2级| 六月婷婷激情综合| 国产精品的网站| 欧美白人做受xxxx视频|