ios - resueltos - manejo de cuello de botella
Cómo encontrar el cuello de botella de UIImage (1)
Tengo una aplicación que usa objetos UIImage
. Hasta este punto, he estado usando objetos de imagen inicializados usando algo como esto:
UIImage *image = [UIImage imageNamed:imageName];
usando una imagen en mi paquete de aplicaciones. He estado agregando funcionalidad para permitir a los usuarios usar imágenes de la cámara o su biblioteca usando UIImagePickerController
. Estas imágenes, obviamente, no pueden estar en mi paquete de aplicaciones, así que inicializo el objeto UIImage
otra manera:
UIImage *image = [UIImage imageWithContentsOfFile:pathToFile];
Esto se hace después de cambiar el tamaño de la imagen a un tamaño similar a los otros archivos en mi paquete de aplicaciones, tanto en dimensiones de píxeles como en bytes totales, ambos usando formato JPEG (curiosamente, PNG fue mucho más lento, incluso para el mismo tamaño de archivo). En otras palabras, el archivo señalado por pathToFile
es un archivo de tamaño similar a una imagen en el paquete (las dimensiones de píxeles coinciden, y se eligió la compresión, por lo que el recuento de bytes fue similar).
La aplicación realiza un ciclo formando pequeñas piezas de la imagen original, entre otras cosas que no son relevantes para esta publicación. Mi problema es que recorrer el ciclo utilizando una imagen creada en el segundo sentido lleva mucho más tiempo que usar una imagen creada de la primera manera.
Me doy cuenta de que el primer método almacena en caché la imagen, pero no creo que sea relevante, a menos que no entienda cómo funciona el almacenamiento en caché. Si es el factor relevante, ¿cómo puedo agregar el almacenamiento en caché al segundo método?
La parte relevante del código que está causando el cuello de botella es esta:
[image drawInRect:self.imageSquare];
Aquí, self es una subclase de UIImageView. Su propiedad imageSquare es simplemente un CGRect
define lo que se dibuja. Esta porción es igual para ambos métodos. Entonces, ¿por qué el segundo método es mucho más lento con un objeto UIImage
tamaño similar?
¿Hay algo que podría estar haciendo de manera diferente para optimizar este proceso?
EDITAR: Cambio el acceso a la imagen en el paquete a imageWithContentsOfFile
y el tiempo para realizar el ciclo cambió de aproximadamente 4 segundos a poco más de un minuto. Por lo tanto, parece que necesito encontrar el modo de hacer el almacenamiento en caché como lo hace imageNamed
, pero con archivos no empaquetados.
UIImage imageNamed
no simplemente almacena en caché la imagen. Almacena en caché una imagen sin comprimir . El tiempo adicional que se gastó no fue causado por la lectura desde el almacenamiento local a la RAM, sino descomprimiendo la imagen.
La solución fue crear un nuevo objeto UIImage
sin comprimir y usarlo para la parte del código sensible al tiempo. El objeto descomprimido se descarta cuando se completa esa sección de código. Para completar, aquí hay una copia del método de clase para devolver un objeto UIImage
descomprimido de uno comprimido, gracias a otro hilo . Tenga en cuenta que esto supone que los datos están en CGImage
. Eso no es siempre cierto para los objetos UIImage
.
+(UIImage *)decompressedImage:(UIImage *)compressedImage
{
CGImageRef originalImage = compressedImage.CGImage;
CFDataRef imageData = CGDataProviderCopyData(
CGImageGetDataProvider(originalImage));
CGDataProviderRef imageDataProvider = CGDataProviderCreateWithCFData(imageData);
CFRelease(imageData);
CGImageRef image = CGImageCreate(
CGImageGetWidth(originalImage),
CGImageGetHeight(originalImage),
CGImageGetBitsPerComponent(originalImage),
CGImageGetBitsPerPixel(originalImage),
CGImageGetBytesPerRow(originalImage),
CGImageGetColorSpace(originalImage),
CGImageGetBitmapInfo(originalImage),
imageDataProvider,
CGImageGetDecode(originalImage),
CGImageGetShouldInterpolate(originalImage),
CGImageGetRenderingIntent(originalImage));
CGDataProviderRelease(imageDataProvider);
UIImage *decompressedImage = [UIImage imageWithCGImage:image];
CGImageRelease(image);
return decompressedImage;
}