¿Alguien sabe por qué CGContextDrawImage
estaría dibujando mi imagen al revés? Estoy cargando una imagen desde mi aplicación:
UIImage *image = [UIImage imageNamed:@"testImage.png"];
Y luego simplemente pedirle a los gráficos principales que lo dibujen a mi contexto:
CGContextDrawImage(context, CGRectMake(0, 0, 145, 15), image.CGImage);
Se presenta en el lugar y las dimensiones correctos, pero la imagen está al revés. ¿Me estoy perdiendo algo realmente obvio aquí?
ios
cocoa-touch
core-graphics
cgcontextdrawimage
rustyshelf
fuente
fuente
Incluso después de aplicar todo lo que he mencionado, todavía he tenido dramas con las imágenes. Al final, acabo de usar Gimp para crear una versión 'vertical invertida' de todas mis imágenes. Ahora no necesito usar ninguna Transformación. Esperemos que esto no cause más problemas en el futuro.
Quartz2d utiliza un sistema de coordenadas diferente, donde el origen está en la esquina inferior izquierda. Entonces, cuando Quartz dibuja el píxel x [5], y [10] de una imagen de 100 * 100, ese píxel se dibuja en la esquina inferior izquierda en lugar de la superior izquierda. Causando así la imagen 'volteada'.
El sistema de coordenadas x coincide, por lo que deberá voltear las coordenadas y.
Esto significa que hemos traducido la imagen por 0 unidades en el eje xy por la altura de las imágenes en el eje y. Sin embargo, esto solo significará que nuestra imagen todavía está al revés, simplemente dibujada "image.size.height" debajo de donde deseamos que se dibuje.
La guía de programación Quartz2D recomienda usar ScaleCTM y pasar valores negativos para voltear la imagen. Puede usar el siguiente código para hacer esto:
Combine los dos justo antes de su
CGContextDrawImage
llamada y debería tener la imagen dibujada correctamente.Solo tenga cuidado si sus coordenadas imageRect no coinciden con las de su imagen, ya que puede obtener resultados no deseados.
Para volver a convertir las coordenadas:
fuente
CGContextSaveGState()
yCGContextRestoreGState()
para guardar y restaurar la matriz de transformación?Lo mejor de ambos mundos, use UIImage's
drawAtPoint:
odrawInRect:
mientras aún especifica su contexto personalizado:También evita modificar su contexto con
CGContextTranslateCTM
o loCGContextScaleCTM
que hace la segunda respuesta.fuente
UIGraphicsBeginImageContextWithOptions
lugar de simplemente iniciar un nuevoCGContext
, parecía funcionar.Documentos relevantes de Quartz2D: https://developer.apple.com/library/ios/documentation/2DDrawing/Conceptual/DrawingPrintingiOS/GraphicsDrawingOverview/GraphicsDrawingOverview.html#//apple_ref/doc/uid/TP40010156-CH14-SW4
fuente
Si alguien está interesado en una solución obvia para dibujar una imagen en un rectángulo personalizado en un contexto:
La imagen se escalará para llenar el rect.
fuente
No estoy seguro
UIImage
, pero este tipo de comportamiento generalmente ocurre cuando se cambian las coordenadas. La mayoría de los sistemas de coordenadas OS X tienen su origen en la esquina inferior izquierda, como en PostScript y PDF. Pero elCGImage
sistema de coordenadas tiene su origen en la esquina superior izquierda.Las posibles soluciones pueden involucrar una
isFlipped
propiedad o unascaleYBy:-1
transformación afín.fuente
UIImage
contiene aCGImage
como su principal miembro de contenido, así como factores de escala y orientación. Dado queCGImage
y sus diversas funciones se derivan de OSX, espera un sistema de coordenadas al revés en comparación con el iPhone. Cuando crea unUIImage
, el valor predeterminado es una orientación invertida para compensar (¡puede cambiar esto!). Utilizar el .CGImage
propiedad para acceder a lasCGImage
funciones muy potentes , pero dibujar en la pantalla del iPhone, etc., se realiza mejor con losUIImage
métodos.fuente
Respuesta suplementaria con código Swift
Los gráficos 2D de cuarzo usan un sistema de coordenadas con el origen en la parte inferior izquierda, mientras que UIKit en iOS usa un sistema de coordenadas con el origen en la parte superior izquierda. Por lo general, todo funciona bien, pero al realizar algunas operaciones gráficas, debe modificar el sistema de coordenadas usted mismo. La documentación dice:
Este fenómeno se puede ver en las siguientes dos instancias de vistas personalizadas que dibujan una imagen en sus
drawRect
métodos.En el lado izquierdo, la imagen está al revés y en el lado derecho el sistema de coordenadas se ha traducido y escalado para que el origen esté en la parte superior izquierda.
Imagen al revés
Sistema de coordenadas modificado
fuente
Swift 3.0 y 4.0
No se necesita alteración
fuente
Podemos resolver este problema usando la misma función:
fuente
drawInRect
es sin duda el camino a seguir. Aquí hay otra pequeña cosa que será útil cuando haga esto. Por lo general, la imagen y el rectángulo en el que va a ir no se ajustan. En ese casodrawInRect
se estirará la imagen. Aquí hay una forma rápida y genial de asegurarse de que la relación de aspecto de la imagen no cambie, invirtiendo la transformación (que será para encajar todo):fuente
Solución Swift 3 CoreGraphics
Si desea utilizar CG por cualquiera que sea su razón, en lugar de UIImage, esta construcción de Swift 3 basada en respuestas anteriores resolvió el problema por mí:
fuente
Ocurre porque QuartzCore tiene el sistema de coordenadas "abajo a la izquierda", mientras que UIKit - "arriba a la izquierda".
En el caso, puede extender CGContext :
fuente
Utilizo esta extensión Swift 5 , pura Core Graphics que maneja correctamente los orígenes distintos de cero en los rectificadores de imagen:
Puede usarlo exactamente como
CGContext
eldraw(: in:)
método habitual :fuente
Durante el curso de mi proyecto, salté de la respuesta de Kendall a la respuesta de Cliff para resolver este problema para las imágenes que se cargan desde el teléfono.
Al final terminé usando en su
CGImageCreateWithPNGDataProvider
lugar:Esto no sufre los problemas de orientación que obtendría al obtener
CGImage
de aUIImage
y se puede usar como el contenido de aCALayer
sin problemas.fuente
fuente
Respuesta rápida 5 basada en la excelente respuesta de @ZpaceZombor
Si tienes un UIImage, solo usa
Si tienes una CGImage usa mi categoría a continuación
Nota: a diferencia de otras respuestas, esta toma en cuenta que el rectángulo que desea dibujar puede tener y! = 0. Esas respuestas que no toman en cuenta eso son incorrectas y no funcionarán en el caso general.
Usar así:
fuente
También puede resolver este problema haciendo esto:
fuente