オフスクリーンビットマップにレンダリングし、Core Graphicsを使用してスクリーンにブリットする方法
-
03-07-2019 - |
質問
オフスクリーンビットマップ(またはRGBA値の配列)にレンダリングし、ビューの drawRect
関数でそれらを UIView
にblitします。完全な32ビットレンダリング(アルファチャネルを含む)を行うことを希望しますが、24ビットレンダリングを使用したコンテンツにもなります。
コードスニペットまたは関連するAPIを使用して正しい方向に向けてくれる人はいませんか?
また、OpenGLを使用してこれを行う方法を正確に知っています。CoreGraphics自体でこの作業を行うことをお勧めします。
解決
オフスクリーンコンテキストにレンダリングしてCGImageRefとして保存するには:
void *bitmapData = calloc(height, bytesPerLine);
CGContextRef offscreen = CGBitmapContextCreate(..., bitmapData, ...)
// draw stuff into offscreen
CGImageRef image = CGBitmapContextCreateImage(offscreen);
CFRelease(offscreen);
free(bitmapData);
画面に描画するには:
- (void)drawRect:(CGRect)rect {
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextDrawImage(context, rect, image);
}
ビューのレイヤーのコンテンツプロパティ( view.layer.contents = image
)に画像を保存するか、UIImageViewを使用することもできます。
他のヒント
CGBitmapContext を使用できます。 CGBitmapContextから画像を生成し、drawRectで描画できます。
ビットマップコンテキストが不要で CGImageRef
のみが必要な場合は、 CGDataProviderCreateWithData
および CGImageCreate
を使用します。
今後の参考のために、オフスクリーンビットマップにレンダリングして画面に表示するSwift 2.1の完全な例を示します。
ビットマップコンテキストを作成したら、さらに多くのコンテンツを描画して、必要に応じてビューを更新できることに注意してください。これは、バックグラウンドスレッドで長時間の描画操作を行い、定期的にユーザーに進行状況を表示する場合に便利です。
View Controller:
import UIKit
class ViewController: UIViewController {
@IBOutlet var myView: MyView!
var bitmapContext: CGContext?
override func viewDidLoad() {
super.viewDidLoad()
createBitmapContext()
drawContentIntoBitmap()
myView.update(from: bitmapContext)
releaseBitmapContext()
}
func createBitmapContext() {
bitmapContext = CGBitmapContextCreate(
nil, // auto-assign memory for the bitmap
Int (myView.bounds.width * UIScreen.mainScreen().scale), // width of the view in pixels
Int (myView.bounds.height * UIScreen.mainScreen().scale), // height of the view in pixels
8, // 8 bits per colour component
0, // auto-calculate bytes per row
CGColorSpaceCreateDeviceRGB(), // create a suitable colour space
CGImageAlphaInfo.PremultipliedFirst.rawValue) // use quartz-friendly byte ordering
}
func drawContentIntoBitmap() {
CGContextScaleCTM(bitmapContext, UIScreen.mainScreen().scale, UIScreen.mainScreen().scale) // convert to points dimensions
CGContextSetStrokeColorWithColor (bitmapContext, UIColor.redColor().CGColor)
CGContextSetLineWidth (bitmapContext, 5.0)
CGContextStrokeEllipseInRect (bitmapContext, CGRectMake(50, 50, 100, 100))
}
func releaseBitmapContext() {
bitmapContext = nil // in Swift, CGContext and CGColorSpace objects are memory managed by automatic reference counting
}
}
UIViewのサブクラス:
import UIKit
class MyView: UIView {
var cgImage: CGImage?
func update(from bitmapContext: CGContext?) {
cgImage = CGBitmapContextCreateImage(bitmapContext)
setNeedsDisplay()
}
override func drawRect(rect: CGRect) {
let displayContext = UIGraphicsGetCurrentContext()
CGContextDrawImage(displayContext, bounds, cgImage)
}
}