create objective-c ios ipad uiimageview

objective-c - create uiimageview programmatically swift 3



La imagen de escalado de iOS UIImageView produce una imagen con alias en el iPad 2 (5)

Estoy usando UIImageView para mostrar miniaturas de imágenes que luego se pueden seleccionar para verlas a tamaño completo. El UIImageView tiene su modo de contenido configurado para un ajuste de aspecto.

Las imágenes generalmente se reducen de 500px x 500px a 100px x 100px. En el iPad retina se muestran muy bien mientras que en el iPad2 tienen un mal alias hasta que el tamaño se acerca al tamaño de la imagen original.

Ejemplos:

Imagen original

Retina iPad que rinde en 100px x 100px

iPad 2 a 100px x 100px

La diferencia entre el iPad 2 y el nuevo iPad podría ser la resolución de la pantalla o podría ser que la GPU esté mejor equipada para escalar imágenes. De cualquier manera, la representación del iPad 2 es muy pobre.

Intenté primero reducir el tamaño de la imagen creando un nuevo contexto, estableciendo la calidad de interpolación en alto y dibujando la imagen en el contexto. En este caso, la imagen se ve bien en ambos iPads.

Antes de continuar por la imagen copiar / redimensionar avenida, quería comprobar que no había algo más simple que me faltaba. Aprecio que UIImage no esté allí para ser escalado, pero tenía la impresión de que UIImageView estaba allí para manejar el escalamiento, pero por el momento no parece estar haciendo un buen trabajo al reducirse. ¿Qué (si hay algo) me estoy perdiendo?

Actualización : Nota: La sombra paralela en las imágenes renderizadas / redimensionadas se agrega en el código. Deshabilitar esto no hizo ninguna diferencia en la calidad de la escala.


Aplicar un pequeño sesgo de filtro de minificación puede ayudar con esto si no desea volver a muestrear la imagen usted mismo:

imageView.layer.minificationFilter = kCAFilterTrilinear imageView.layer.minificationFilterBias = 0.1

La imagen de la izquierda no tiene filtros aplicados. La imagen de la derecha tiene un sesgo de 0.1 filtro.

Tenga en cuenta que no se requiere una rasterización explícita.

Jugando con valores muy pequeños, generalmente se puede obtener un valor que suaviza los artefactos de escalado lo suficiente, y es mucho más fácil que cambiar el tamaño del mapa de bits usted mismo. Ciertamente, se pierde detalle a medida que aumenta el sesgo, por lo que valores incluso inferiores a 0,1 son probablemente suficientes, aunque todo depende del tamaño del marco de la vista de la imagen que muestra la imagen.

Solo mipmapping en cuenta que el filtrado trilineal permite realizar mipmapping en la capa, lo que básicamente significa que genera copias adicionales del mapa de bits a escalas progresivamente más pequeñas. Es una técnica muy común que se utiliza en el renderizado para aumentar la velocidad de renderizado y también para reducir el aliasing de escala. La desventaja es que requiere más memoria, aunque el uso de la memoria para los mapas de bits sucesivos reducidos se reduce exponencialmente.

Otra ventaja potencial de esta técnica, aunque no la he probado, es que puedes animar minificationFilterBias . Por lo tanto, si va a escalar una vista de imagen mucho como parte de una animación, considere también animar el sesgo de filtro de 0.0 a cualquier valor pequeño que haya determinado que sea apropiado para el tamaño reducido.

Finalmente, como han señalado otros, si la imagen de origen es muy grande, esta técnica no es apropiada si se usa en exceso, porque la Animación central siempre se mantendrá alrededor del mapa de bits original. Es mejor cambiar el tamaño de la imagen y luego descartar la imagen de origen en lugar de usar mipmapping en la mayoría de los casos, pero para casos puntuales o casos en que las vistas de sus imágenes van a ser desasignadas lo suficientemente rápido, está bien.


El siguiente me ayudó:

imageView.layer.minificationFilter = kCAFilterTrilinear imageView.layer.shouldRasterize = true imageView.layer.rasterizationScale = UIScreen.mainScreen().scale

Esté atento al rendimiento si se usa en listas de desplazamiento.


Otro enfoque que he probado que parece estar mejorando las cosas es establecer el minificationFilter:

[imageView.layer setMinificationFilter:kCAFilterTrilinear]

La calidad ciertamente ha mejorado y no he notado un golpe de rendimiento.


Si no tienes miedo de gastar memoria y saber lo que estás haciendo para un caso en particular, esto funciona maravillosamente.

myView.layer.shouldRasterize = YES; myView.layer.rasterizationScale = 2;

La calidad resultante es mucho mejor que setMinificationFilter.

Estoy usando imágenes que son 256x256 y escalarlas a algo así como 48 px. Obviamente, una solución más segura sería reducir las imágenes al tamaño de destino exacto.


si coloca la imagen grande en una pequeña imagen, se verá realmente mal.

la solución es cambiar el tamaño de la imagen correctamente ... Añadiré una función de ejemplo que hace el truco:

- (UIImage *)resizeImage:(UIImage*)image newSize:(CGSize)newSize { CGRect newRect = CGRectIntegral(CGRectMake(0, 0, newSize.width, newSize.height)); CGImageRef imageRef = image.CGImage; UIGraphicsBeginImageContextWithOptions(newSize, NO, 0); CGContextRef context = UIGraphicsGetCurrentContext(); CGContextSetInterpolationQuality(context, kCGInterpolationHigh); CGAffineTransform flipVertical = CGAffineTransformMake(1, 0, 0, -1, 0, newSize.height); CGContextConcatCTM(context, flipVertical); CGContextDrawImage(context, newRect, imageRef); CGImageRef newImageRef = CGBitmapContextCreateImage(context); UIImage *newImage = [UIImage imageWithCGImage:newImageRef]; CGImageRelease(newImageRef); UIGraphicsEndImageContext(); return newImage; }

esta función puede llevar algo de tiempo ... por lo que es posible que desee guardar el resultado en un archivo de caché.