對於了解視覺方面的事情平時自然也很有興趣,
所以用 Swift 寫寫圖片相關的東西了解運作也是很正常的。
回到主題,之前是因為看到有人用 Objective-C 寫了一個 Image Dump,
而最近因為寫一個簡報,就順手改寫了個 Swift 的版本,
也把一些筆記整理進來。
先來看一下程式碼,如下:
func imageDump(img:UIImage){ let imageRef = img.CGImage let width = CGImageGetWidth(imageRef) let height = CGImageGetHeight(imageRef) let bytesPerRow = CGImageGetBytesPerRow(imageRef) let bitsPerPixel = CGImageGetBitsPerPixel(imageRef) let colorSpace = CGImageGetColorSpace(imageRef) let bitPerComponent = CGImageGetBitsPerComponent(imageRef); let bytesPerPixel = bitsPerPixel / bitPerComponent; let provider:CGDataProviderRef = CGImageGetDataProvider(imageRef) let data:NSData = CGDataProviderCopyData(provider) let bytes = data.bytes // Needs to be changed to ConstUnsafePointer<()> in xCode beta3 let bytePointer = UnsafePointer(bytes) println("\n") println("Pixel Data:\n") var printString:String = "" for var row:Int = 0; row < Int(height); row++ { for var col:Int = 0; col < Int(width); col++ { printString += "(" for var x = 0; x < Int(bytesPerPixel); x++ { var channel:UInt8 = bytePointer[row * Int(bytesPerRow) + col * Int(bytesPerPixel) + x] printString += NSString(format:"%.2X, ", channel) } printString += ")" if col < Int(width) - 1 { printString += "," } } printString += "\n" } println(printString) }
關於 CGImage 參數
這邊使用的是一張 4 x 3 像素的 png 圖片,
一開始先把 UIImage 轉為 CGImage,
藉由 CGImage 取得一些需要的數據,
println("bytesPerRow",bytesPerRow) //16 println("bitsPerPixel",bitsPerPixel) //32 println("bitPerComponent",bitPerComponent) //8 println("bytesPerPixel",bytesPerPixel) //4bitPerComponent 為 8, 是因為圖片為 ARGB8888。
*關於ARGB8888參考連結
bytesPerPixel 為 4 bytes 是由 bitPerComponent 而來,
R、G、B、A 每個 Channel 都使用 8 bits,
所以每個像素的 R、G、B、A 加起來是 32 bits = 4 bytes。 (1 bit = 8 bytes)
因此 bitsPerPixel 從 bytesPerPixel 換算來就是 32 bits。
bytesPerRow 為 16 是跟圖片的寬度有關,
前面說一個像素是 4 bytes,乘上圖片寬度 4 像素, 就為 16 啦!
*別處對於CGImageRef的參數解釋
println(data) 的話,可以直接看到 4 x 3 的圖片 RGBA 數據
39b64eff fcee09ff 0005e8ff ed1b2eff 00bbf7ff e90189ff fc9512ff fcf006ff ee352bff c9e3daff 3ab84aff 02abecff
關於 row 跟 col 的迴圈
for迴圈那是利用 row(height) 跟 col(width) 來取得每個像素位置,如下圖

關於每個像素 channel 的值
最內層的迴圈for var x = 0; x < Int(bytesPerPixel); x++
x會為0~3,也就是像素的寬度。
在 bytePointer[row * Int(bytesPerRow) + col * Int(bytesPerPixel) + x] 得到的數值可以這樣看
另外,不知道為什麼下面這些程式碼開專案寫可以,但寫在Playground就不行。
let imageRef = img.CGImage let provider:CGDataProviderRef = CGImageGetDataProvider(imageRef) let data:NSData = CGDataProviderCopyData(provider)
其他相關資料:
ROMAIN GUY講位圖質量
關於轉換位圖陣列ARGB8888到RGB565
I recommend iDealshare VideoGo as the most professional audio converter and video converter.https://www.idealshare.net/3ga-to-mp3-converter.html
ReplyDelete