2010-04-12 11 views
6

Tengo un método que necesita analizar a través de un montón de imágenes PNG grandes píxel por píxel (los PNG son 600x600 píxeles cada uno). Parece funcionar muy bien en el Simulador, pero en el dispositivo (iPad), obtengo un EXC_BAD_ACCESS en alguna función de copia de memoria interna. Parece que el tamaño es el culpable porque si lo pruebo en imágenes más pequeñas, todo parece funcionar. Aquí está la carne relacionada con la memoria del método a continuación.CGBitmapContextCreate en el iPhone/iPad

+ (CGRect) getAlphaBoundsForUImage: (UIImage*) image 
{  
    CGImageRef imageRef = [image CGImage]; 

NSUInteger width = CGImageGetWidth(imageRef); 
NSUInteger height = CGImageGetHeight(imageRef); 
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); 

unsigned char *rawData = malloc(height * width * 4); 
memset(rawData,0,height * width * 4); 

NSUInteger bytesPerPixel = 4; 
NSUInteger bytesPerRow = bytesPerPixel * width; 
NSUInteger bitsPerComponent = 8; 
CGContextRef context = CGBitmapContextCreate(rawData, width, height, bitsPerComponent, bytesPerRow, colorSpace, kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big); 

CGColorSpaceRelease(colorSpace); 

CGContextDrawImage(context, CGRectMake(0, 0, width, height), imageRef); 
CGContextRelease(context); 

/* non-memory related stuff */ 

free(rawData); 

Cuando ejecuto esto en un montón de imágenes, que se ejecuta 12 veces y luego dados a cabo, mientras que en el simulador se ejecuta sin problemas. ¿Tienen alguna idea?

Respuesta

0

Estaba recibiendo un bloqueo similar en mi iPad (iPhoneOS 3.2 por supuesto) usando CGImageCreate(). Ver tu dificultad me dio una pista. He resuelto el problema mediante la alineación de mi bytesPerRow a la siguiente potencia mayor de 2.

size_t bytesPerRowPower2 = (size_t) round(pow(2.0, trunc(log((double) bytesPerRow)/log(2.0)) + 1.0));

Háganos saber si proporcionar potencia de 2 alineación fila también resuelve su problema. Debería asignar * rawData con el tamaño ajustado y pasar bytesPerRowPower2 a CGBitmapContextCreate() ... La altura no parece necesitar alineación.

0

Quizás CGImageGetBytesPerRow (el poder de dos suena excesivo).

0

Usé una potencia de dos filas alineadas en una aplicación que definía el tamaño de fila directamente, ya que creaba imágenes mediante programación. Pero también recomendaría tostadas para probar CGImageGetBytesPerRow antes de probar mi sugerencia también.

3

Correr 12 veces y luego estrellarse suena como un problema de falta de memoria. Puede ser que internamente el CGContext está creando algunas estructuras autoreleases grandes. Ya que estás haciendo esto en un bucle, no están siendo liberados, así que te quedas sin memoria y mueres.

No estoy seguro de cómo Core Foundation trata con objetos temporales. No creo que los objetos de CF tengan el equivalente a la liberación automática, y un contexto de Núcleo de gráficos casi con certeza trata con objetos de CF en lugar de NSObjects.

Para reducir la falta de memoria en su código, le sugiero que refactorice para crear un CGContext fuera de la pantalla una vez antes de comenzar el procesamiento, y úselo repetidamente para procesar cada imagen. Luego, libéralo cuando termines. Eso va a ser más rápido en cualquier caso (ya que no está asignando enormes estructuras de datos en cada pasada del ciclo).

Apostaría que eliminará su problema de bloqueo, y apuesto a que también hace que su código mucho, mucho más rápido. La asignación de memoria es muy lenta en comparación con otras operaciones, y usted está manejando estructuras de datos bastante grandes para manejar imágenes RGBA de 600x600 píxeles.

0

Intenta ejecutar la asignación de instrumentos mientras ejecuta la aplicación en el dispositivo, ya que es un problema relacionado con la memoria. Si está en un bucle, cree dentro de ese bucle un grupo de autorizaciones automáticas.

3

Ir a producto -> Editar esquemas -> Activar objetos Zombie. Ponga una marca de verificación antes de Activar objetos Zombie. Ahora contrólalo y ejecútalo. Puede proporcionarle una descripción mejor y más precisa para el error EXC_BAD_ACCES.

0

Quizás reemplazar

CGColorSpaceRelease(colorSpace); 
CGContextDrawImage(context, CGRectMake(0, 0, width, height), imageRef); 

con

CGContextDrawImage(context, CGRectMake(0, 0, width, height), imageRef); 
CGColorSpaceRelease(colorSpace); 

como el espacio de color ref todavía podrían ser necesarios de alguna manera? Solo una conjetura al azar ... ¿Y tal vez incluso ponerlo detrás del lanzamiento del contexto?

// cleanup 
CGContextRelease(context); 
CGColorSpaceRelease(colorSpace); 
0

Resolví el problema haciendo un contexto cuadrado (ancho = alto). Estaba teniendo una textura de 512x256 y se bloqueaba cada vez que enviaba los datos a OpenGL. Ahora asigno un buffer de 512x512 PERO SIGUE renderizando 512x256. Espero que esto ayude.

Cuestiones relacionadas