[Swift] 用 view 拼一隻咖波 #1

看了 Peter 用 view 去畫圖,好像沒什麼時間一個 view 一個 view 畫,所以想讓程式去抓圖片的 Pixel RGB 值,自動產生 view 在畫布上。

capoo.jpg 的解析度是 1024*1024 Pixel。

resolution of capoo.jpg
Bugcat Capoo
Bugcat Capoo: https://www.facebook.com/capoocat/

圖片來源:Bugcat Capoo
- Facebook:https://www.facebook.com/capoocat/
- Instagram:https://www.instagram.com/bugcat_capoo/

本來是用 Python 的 Pillow 去把 capoo.jpg 轉成一個 RGB List 存到 rgb.txt 中,再丟到 Swift 專案中讀取,然後畫 view。

from PIL import Image
import codecs
img = Image.open('capoo.jpg')
print(img.size)
if img.size[0] > 393 or img.size[1] > 393:
img = img.resize((393,393))
width, height = img.size
pixel_values = list(img.getdata())
f = codecs.open("rgb.txt", "w", "utf-8")
f.write(str(pixel_values))
f.close()

後來想到也可以在 Swift 做調整圖片解析度,以及取得每一個 Pixel 的 RGB 值,就直接寫在 Swift 中了。
有點懶得自己查文件,先 Google “resize image in Swift”,沒想到 StackOverflow 上也有人有一樣的問題。
https://stackoverflow.com/questions/31314412/how-to-resize-image-in-swift

func resizeImage(image: UIImage, targetSize: CGSize) -> UIImage? {
let size = image.size

let widthRatio = targetSize.width / size.width
let heightRatio = targetSize.height / size.height

// Figure out what our orientation is, and use that to form the rectangle
var newSize: CGSize
if(widthRatio > heightRatio) {
newSize = CGSize(width: size.width * heightRatio, height: size.height * heightRatio)
} else {
newSize = CGSize(width: size.width * widthRatio, height: size.height * widthRatio)
}

// This is the rect that we've calculated out and this is what is actually used below
let rect = CGRect(origin: .zero, size: newSize)

// Actually do the resizing to the rect using the ImageContext stuff
UIGraphicsBeginImageContextWithOptions(newSize, false, 1.0)
image.draw(in: rect)
let newImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()

return newImage
}

畫圖的部分使用迴圈,取得一個點的 RGB 值之後,將其插入到畫布中,圖片的大小已經先經過 resizeImage() 這個函式調整,會跟 superView 的寬度相同。

override func viewDidLoad() {
super.viewDidLoad()
// get superView width&height
let superViewWidth = self.view.frame.width
let superViewHeight = self.view.frame.height
print(superViewWidth, superViewHeight)

// recommended to use square images
if let image = UIImage(named: "capoo.jpg") {
let image = resizeImage(image:image, targetSize:CGSize(width:superViewWidth, height:superViewHeight))
guard let cgImage = image?.cgImage,
let data = cgImage.dataProvider?.data,
let bytes = CFDataGetBytePtr(data) else {
fatalError("Couldn't access image data")
}
assert(cgImage.colorSpace?.model == .rgb)

let bytesPerPixel = cgImage.bitsPerPixel / cgImage.bitsPerComponent
for y in 0 ..< cgImage.height {
for x in 0 ..< cgImage.width {
let offset = (y * cgImage.bytesPerRow) + (x * bytesPerPixel)
let components = (r: bytes[offset+2], g: bytes[offset+1], b: bytes[offset])
// print("[x:\(x), y:\(y)] \(components)")
let squareView = UIView()
squareView.backgroundColor = UIColor(red: CGFloat(components.r)/255, green: CGFloat(components.g)/255, blue: CGFloat(components.b)/255, alpha: 1.0)
// set view position and size
squareView.frame = CGRect(x: x, y: Int(superViewHeight/4)+y, width: 1, height: 1)

// add view to ViewController
self.view.addSubview(squareView)
}
// print("---")
}
} else {
print("Failed to load image from bundle.")
}
}

專案 Github:

https://github.com/s1031432/Capoo_view

--

--