位圖(Bitmap),又稱柵格圖(英語:Raster graphics)或點(diǎn)陣圖,是使用像素陣列(Pixel-array/Dot-matrix點(diǎn)陣)來表示的圖像督禽。
根據(jù)位深度,可將位圖分為1讲婚、4、8待德、16君丁、24及32位圖像等。每個像素使用的信息位數(shù)越多将宪,可用的顏色就越多绘闷,顏色表現(xiàn)就越逼真,相應(yīng)的數(shù)據(jù)量越大较坛。例如印蔗,位深度為 1 的像素位圖只有兩個可能的值(黑色和白色),所以又稱為二值位圖丑勤。位深度為 8 的圖像有 2^8(即 256)個可能的值华嘹。位深度為 8 的灰度模式圖像有 256 個可能的灰色值。
RGB圖像由三個顏色通道組成法竞。8 位/通道的 RGB 圖像中的每個通道有 256 個可能的值耙厚,這意味著該圖像有 1600 萬個以上可能的顏色值。有時將帶有 8 位/通道 (bpc) 的 RGB 圖像稱作 24 位圖像(8 位 x 3 通道 = 24 位數(shù)據(jù)/像素)岔霸。通常將使用24位RGB組合數(shù)據(jù)位表示的的位圖稱為真彩色位圖薛躬。
在iOS中,Bitmap的數(shù)據(jù)由CGContext封裝呆细,看下CGContext的初始化方法如下:
init?(data: UnsafeMutableRawPointer?, width: Int, height: Int, bitsPerComponent:Int, bytesPerRow: Int, space: CGColorSpace, bitmapInfo: UInt32)
data: UnsafeMutableRawPointer,用于存放位圖的點(diǎn)陣數(shù)據(jù)
width: Int 位圖的寬
height: Int 位圖的高
如width=10,height=10,則代表每一行有10個像素型宝,每一列有20個像素
bitsPerComponent:Int 顏色組件或者alpha組件占的bite數(shù),以32位圖為列:bitsPerComponent = 8
bytesPerRow: Int 位圖每行占的字節(jié)數(shù)(byte)以32位圖為例:一個像素有4byte(rgba)
那么一行字節(jié)數(shù):?bytesPerRow = 4*width
space: CGColorSpac 顏色空間?CGColorSpaceCreateDeviceRGB
bitmapInfo: UInt32?一個常量,描述這個位圖上下文所對應(yīng)的位圖的基本信息趴酣,例如:CGImageAlphaInfo.premultipliedLast
接下來我們以兩種方式把圖片從rgb888轉(zhuǎn)成rgb56
第一種以UInt32來接收位圖信息梨树,即一個數(shù)據(jù)包含了RGBA所有數(shù)據(jù)
func rbg565Data() -> Data? {
????????guard let cgImage = self.cgImage
????????????else { return Data() }
????????let width = Int(size.width)
????????let height = Int(size.height)
????????// bytes array
????????let srcRowBytes = 4 * width
????????var bytes = Array<UInt32>.init(repeating: 0, count: srcRowBytes * height)
????????// create context for image
????????guard let context = CGContext(data: &bytes, width: width, height: height, bitsPerComponent: 8, bytesPerRow: srcRowBytes, space: CGColorSpaceCreateDeviceRGB(), bitmapInfo: CGImageAlphaInfo.premultipliedLast.rawValue )
????????????else { return nil }
? ? ? ? // fill buffer
????????context.interpolationQuality = .high
????????context.draw(cgImage, in: CGRect(x: 0, y: 0, width: width, height: height))
????????var newBytes = [UInt8]()
????????for col in 0..<height {
????????????for row in 0..<width {
//????????????????let pixeIndex = (col*width+row)*4
????????????????let color = bytes[(col*width+row)]
????????????????let r = UInt8(( color >> 0 ) & 0xff )
????????????????let g = UInt8(( color >> 8 ) & 0xff )
????????????????let b = UInt8(( color >> 16) & 0xff )
????????????????let data = (r & 0xf8) | ((g >> 5) & 0x7)
????????????????newBytes.append(data)
????????????????let data2 = ((g<<3) & 0xE0) | ((b >> 3) & 0x1F)
????????????????newBytes.append(data2)
????????????}
????????}
????????return Data(bytes: newBytes, count: newBytes.count)
????}
第二種已UInt8來存儲位圖信息,即一個數(shù)據(jù)只包含RGBA中一個通道信息价卤,比如R
func rbg565Data() -> Data? {
????????guard let cgImage = self.cgImage
????????????else { return Data() }
????????let width = Int(size.width)
????????let height = Int(size.height)
????????// bytes array
????????let srcRowBytes = 4 * width
????????var bytes = Array<UInt8>.init(repeating: 0, count: srcRowBytes * height)
????????// create context for image
????????guard let context = CGContext(data: &bytes, width: width, height: height, bitsPerComponent: 8, bytesPerRow: srcRowBytes, space: CGColorSpaceCreateDeviceRGB(), bitmapInfo: CGImageAlphaInfo.premultipliedLast.rawValue )
????????????else { return nil }
????????// fill buffer
????????context.interpolationQuality = .high
????????context.draw(cgImage, in: CGRect(x: 0, y: 0, width: width, height: height))
????????var newBytes = [UInt8]()
????????for i in 0..<(bytes.count/4) {
????????????let pixeIndex = i*4
????????????let r = UInt8(bytes[pixeIndex])
????????????let g = UInt8(bytes[pixeIndex+1])
????????????let b = UInt8(bytes[pixeIndex+2])
????????????let data:UInt8 = (r & 0xf8) | ((g >> 5) & 0x7)
????????????newBytes.append(data)
????????????let data2:UInt8 = ((g<<3) & 0xE0) | ((b >> 3) & 0x1F)
????????????newBytes.append(data2)
//????????????logD("---r=\(r),g=\(g),b=\(b),data=\(data),data1=\(data2)")
????????}
????????return Data(bytes: newBytes, count: newBytes.count)
????}