Кто-нибудь знает, почему CGContextDrawImage
бы рисовать мое изображение с ног на голову? Я загружаю изображение из моего приложения:
UIImage *image = [UIImage imageNamed:@"testImage.png"];
А затем просто попросите основную графику нарисовать ее в моем контексте:
CGContextDrawImage(context, CGRectMake(0, 0, 145, 15), image.CGImage);
Он рендерит в нужном месте и размеры, но изображение перевернуто. Должно быть, я что-то упустил здесь действительно очевидное?
ios
cocoa-touch
core-graphics
cgcontextdrawimage
rustyshelf
источник
источник
Даже после применения всего, что я упомянул, у меня все еще были драмы с изображениями. В конце концов, я просто использовал Gimp для создания «перевернутой вертикали» версии всех моих изображений. Теперь мне не нужно использовать какие-либо преобразования. Надеюсь, это не вызовет дальнейших проблем в будущем.
Quartz2d использует другую систему координат, где начало координат находится в левом нижнем углу. Поэтому, когда Кварц рисует пиксель x [5], y [10] изображения 100 * 100, этот пиксель рисуется в левом нижнем углу вместо верхнего левого. Таким образом вызывая «перевернутое» изображение.
Система координат x совпадает, поэтому вам нужно будет перевернуть координаты y.
Это означает, что мы перевели изображение на 0 единиц по оси x и по высоте изображений по оси y. Однако, это само по себе будет означать, что наше изображение все еще вверх дном, просто рисуем «image.size.height» ниже, где мы хотим, чтобы оно было нарисовано.
Руководство по программированию Quartz2D рекомендует использовать ScaleCTM и передавать отрицательные значения для переворачивания изображения. Вы можете использовать следующий код для этого -
Объедините их сразу перед
CGContextDrawImage
вызовом, и вы должны правильно нарисовать изображение.Просто будьте осторожны, если ваши координаты imageRect не совпадают с координатами вашего изображения, так как вы можете получить непредвиденные результаты.
Чтобы преобразовать обратно координаты:
источник
CGContextSaveGState()
иCGContextRestoreGState()
для сохранения и восстановления матрицы преобразования?Лучше всего в обоих мирах использовать UIImage
drawAtPoint:
или, вdrawInRect:
то же время, указав свой пользовательский контекст:Также вы избегаете изменения своего контекста
CGContextTranslateCTM
или того,CGContextScaleCTM
что делает второй ответ.источник
UIGraphicsBeginImageContextWithOptions
вместо того, чтобы просто начинать новыйCGContext
, это, казалось, работало.Соответствующие документы Quartz2D: https://developer.apple.com/library/ios/documentation/2DDrawing/Conceptual/DrawingPrintingiOS/GraphicsDrawingOverview/GraphicsDrawingOverview.html#//apple_ref/doc/uid/TP400101WW4
источник
Если кого-то интересует простое решение для рисования изображения в пользовательском прямоугольнике в контексте:
Изображение будет масштабировано, чтобы заполнить прямоугольник.
источник
Я не уверен
UIImage
, но такое поведение обычно происходит, когда координаты перевернуты. Большинство систем координат OS X имеют свое происхождение в нижнем левом углу, как в Postscript и PDF. НоCGImage
система координат имеет свое начало в верхнем левом углу.Возможные решения могут включать
isFlipped
свойство илиscaleYBy:-1
аффинное преобразование.источник
UIImage
содержит вCGImage
качестве основного элемента содержимого, а также факторы масштабирования и ориентации. Так какCGImage
и его различные функции получены из OSX, он ожидает, что система координат перевернута по сравнению с iPhone. Когда вы создаетеUIImage
, по умолчанию используется перевернутая ориентация для компенсации (вы можете изменить это!). Использовать .CGImage
свойство для доступа к очень мощнымCGImage
функциям, но рисование на экране iPhone и т. д. лучше всего делать с помощьюUIImage
методов.источник
Дополнительный ответ с кодом Swift
Кварцевая 2D графика использует систему координат с началом координат внизу слева, в то время как UIKit в iOS использует систему координат с началом координат слева вверху. Обычно все работает нормально, но при выполнении некоторых графических операций вы должны сами изменить систему координат. В документации говорится:
Это явление можно увидеть в следующих двух случаях пользовательских представлений, которые рисуют изображение в своих
drawRect
методах.С левой стороны изображение перевернуто, а с правой стороны система координат переведена и масштабирована так, что начало координат находится слева вверху.
Перевернутое изображение
Модифицированная система координат
источник
Swift 3.0 и 4.0
Никаких изменений не требуется
источник
Мы можем решить эту проблему, используя ту же функцию:
источник
drawInRect
это конечно путь. Вот еще одна мелочь, которая пригодится при этом. Обычно изображение и прямоугольник, в который он собирается войти, не соответствуют. В таком случаеdrawInRect
растяну картинку. Вот быстрый и крутой способ убедиться, что соотношение сторон изображения не изменилось, изменив преобразование (которое будет соответствовать целиком):источник
Swift 3 CoreGraphics Solution
Если вы хотите использовать CG по любой причине, вместо UIImage, эта конструкция Swift 3, основанная на предыдущих ответах, решила проблему для меня:
источник
Это происходит потому, что QuartzCore имеет систему координат «внизу слева», а UIKit - «вверху слева».
В случае, если вы можете расширить CGContext :
источник
Я использую это Swift 5 , чистое расширение Core Graphics, которое правильно обрабатывает ненулевое происхождение в ректах изображения:
Вы можете использовать его так же, как
CGContext
обычныйdraw(: in:)
метод:источник
В ходе моего проекта я подпрыгнул от ответа Кендалла в ответ Клиффа , чтобы решить эту проблему для изображений, которые загружаются с самого телефона.
В конце концов я использовал
CGImageCreateWithPNGDataProvider
вместо этого:Это не страдает от проблем ориентации, которые вы могли бы получить от
CGImage
a,UIImage
и его можно использовать в качестве содержимогоCALayer
без заминки.источник
источник
Swift 5 ответ на основе превосходного ответа @ ZpaceZombor
Если у вас есть UIImage, просто используйте
Если у вас есть CGImage, используйте мою категорию ниже
Примечание: в отличие от некоторых других ответов, этот учитывает, что прямоугольник, который вы хотите нарисовать, может иметь y! = 0. Те ответы, которые не учитывают это, являются неправильными и не будут работать в общем случае.
Используйте как это:
источник
Вы также можете решить эту проблему следующим образом:
источник