Como render
-
03-07-2019 - |
Pergunta
Eu gostaria de renderizar um bitmap fora da tela (ou matriz de valores de RGBA) e depois prendê -los a um UIView
Durante o View's drawRect
função. Eu preferiria fazer uma renderização completa de 32 bits (incluindo o canal alfa), mas também se contentaria com a renderização de 24 bits.
Alguém se importaria de me apoiar na direção certa com alguns trechos de código ou APIs relevantes?
Além disso, eu sei exatamente como fazer isso usando o OpenGL - eu preferiria fazer esse trabalho nos próprios gráficos principais.
Solução
Para renderizar um contexto fora da tela e salvá -lo como um CGIMAGEREF:
void *bitmapData = calloc(height, bytesPerLine);
CGContextRef offscreen = CGBitmapContextCreate(..., bitmapData, ...)
// draw stuff into offscreen
CGImageRef image = CGBitmapContextCreateImage(offscreen);
CFRelease(offscreen);
free(bitmapData);
Para desenhá -lo na tela:
- (void)drawRect:(CGRect)rect {
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextDrawImage(context, rect, image);
}
Você também pode apenas salvar a imagem na propriedade de conteúdo da camada da vista (view.layer.contents = image
), ou use um UIImageView.
Outras dicas
Você pode usar um CGBITMAPCONTEXT. Você pode gerar uma imagem a partir de um cgbitmapContext e desenhá -la durante o seu drawrect.
Usar CGDataProviderCreateWithData
e CGImageCreate
Se você não precisa do contexto de bitmap e só deseja o CGImageRef
.
Para referência futura, aqui está um exemplo completo no Swift 2.1 de renderização para um bitmap fora da tela e exibi -lo na tela.
Observe que, depois de criar o contexto do bitmap, você pode continuar desenhando mais conteúdo e atualizando a visualização quando quiser. Isso é ótimo se você deseja fazer uma longa operação de desenho em um encadeamento de segundo plano e mostrar periodicamente o progresso para o usuário.
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
}
}
Subclasse de 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)
}
}