Rendimiento de Quartz2D: cómo mejorar

Estoy trabajando en iOS y se me ha presentado este problema. Recibiré un conjunto de datos relativamente grande (una matriz de estilo C de 500x500 o más). Necesito construir lo que es esencialmente un gráfico X / Y a partir de estos datos, donde cada punto de datos en la cuadrícula de 500x500 corresponde a un color basado en su valor. El caso es que esto cambia con el tiempo, creando una animación por así decirlo, por lo que los cálculos deben ser rápidos para cambiar cuando ingresa un nuevo conjunto de datos.

Entonces, básicamente, para cada punto de la matriz, necesito averiguar a qué color debería mapear, luego averiguar el cuadrado para dibujar en la cuadrícula para representar los datos. Si mi cuadrícula fuera de 768x768 píxeles, pero tengo un conjunto de datos de 500x500, entonces cada punto de datos representaría aproximadamente un rectángulo de 1.5x1.5 (eso es redondeado, pero espero que entiendas la idea).

Intenté esto creando una nueva clase de vista y anulando drawRect. Sin embargo, eso se encontró con un rendimiento horrible con cualquier conjunto de datos de más de 20x20.

He visto algunas sugerencias sobre cómo escribir en búferes de imágenes, pero no he podido encontrar ningún ejemplo de cómo hacerlo (soy bastante nuevo en iOS). ¿Tiene alguna sugerencia o podría indicarme algún recurso que pueda ayudar?

Gracias por su tiempo,

Darryl

preguntado el 16 de mayo de 11 a las 20:05

2 Respuestas

Aquí hay un código que puede poner en un método que generará y devolverá un UIImage en un contexto fuera de la pantalla. Para mejorar el rendimiento, intente encontrar formas de minimizar el número de iteraciones, como hacer que sus "píxeles" sean más grandes o solo dibujar una parte que cambie.

    UIGraphicsBeginImageContext(size); // Use your own image size here      

CGContextRef context = UIGraphicsGetCurrentContext();       

// push context to make it current 
// (need to do this manually because we are not drawing in a UIView)
//
UIGraphicsPushContext(context);                             

for (CGFloat x = 0.0; x<size.width; x+=1.0) {
   for (CGFloat y=0.0; y< size.height; y+=1.0) {
// Set your color here
      CGContextSetRGBFillColor(context, 1.0, 1.0, 1.0, 1.0));
      CGContextFillRect(context, CGRectMake(x, y, 1.0, 1.0));
   }
}


// pop context 
//
UIGraphicsPopContext();     


// get a UIImage from the image context- enjoy!!!
//
UIImage *outputImage = UIGraphicsGetImageFromCurrentImageContext();
[outputImage retain];

// clean up drawing environment
//
UIGraphicsEndImageContext();
return [outputImage autorelease];

contestado el 19 de mayo de 11 a las 03:05

No, estaba usando drawRect en una subclase de UIView, que sería mucho más lento que dibujar en un contexto de imagen fuera de la pantalla. - Chris Garrett

¿Qué hace que esto sea mucho más rápido? ¿Por qué dibujar en el contexto fuera de la pantalla es mucho más barato? También sugiero la renderización fuera de la pantalla, pero accediendo directamente a la memoria en lugar de hacer 25,000 llamadas a quartz, que pensar (no medidos) son el cuello de botella de rendimiento aquí. - Eiko

¡Eso funcionó, gracias! (Lo siento, acabo de volver a esto). - W. Wright

Si desea ser rápido, no debe llamar a funciones de dibujo explícitas para cada píxel. Puede asignar memoria y usar CGBitmapContextCreate para construir una imagen con los datos en esa memoria, que es básicamente una matriz de bytes. Haga sus cálculos y escriba la información de color (argb) directamente en ese búfer. Sin embargo, debe hacer los cálculos por su cuenta, con respecto a la precisión de subpíxeles (combinación).

No tengo un ejemplo a mano, pero estoy buscando CGBitmapContextCreate debería llevarte en la dirección correcta.

contestado el 19 de mayo de 11 a las 03:05

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.