Я пытаюсь удалить верхнюю часть изображения путем обрезки, но результат неожиданный. Используемый код:
extension UIImage {
class func removeStatusbarFromScreenshot(_ screenshot:UIImage) -> UIImage {
let statusBarHeight = 44.0
let newHeight = screenshot.size.height - statusBarHeight
let newSize = CGSize(width: screenshot.size.width, height: newHeight)
let newOrigin = CGPoint(x: 0, y: statusBarHeight)
let imageRef:CGImage = screenshot.cgImage!.cropping(to: CGRect(origin: newOrigin, size: newSize))!
let cropped:UIImage = UIImage(cgImage:imageRef)
return cropped
}
}
Моя логика заключается в том, что мне нужно сделать изображение меньше по высоте на 44 пикселя и переместить исходную точку y на 44 пикселя, но в конечном итоге это создаст изображение, намного меньшее в верхнем левом углу.
Единственный способ заставить его работать должным образом - умножить ширину на 2 и высоту на 2,5 в newSize, но это также удвоит размер созданного изображения. Что в любом случае не имеет особого смысла... может кто-нибудь помочь заставить его работать без использования магических значений?
Есть две основные проблемы с тем, что вы делаете:
UIImage имеет масштаб (обычно привязанный к разрешению экрана вашего устройства), а CGImage — нет.
Разные устройства имеют разную высоту «строки состояния». В общем, то, что вы хотите отрезать сверху, это не строка состояния, а безопасная область. В верхней части безопасной области начинается ваш контент.
Из-за этого:
Вы ошибаетесь, говоря о 44 px. Здесь нет пикселей. Пиксели — это физические атомарные подсветки на вашем экране. В коде есть точки. Точки не зависят от масштаба (а масштаб — это множитель между точками и пикселями).
Вы ошибаетесь, когда говорите о самом числе 44 так, будто оно жестко запрограммировано. Вместо этого вы должны добраться до вершины безопасной зоны.
Переходя в мир CGImage без учета масштаба, вы теряете информацию о масштабе, потому что CGImage ничего не знает о масштабе.
Вернувшись в мир UIImage без учета масштаба, вы получите UIImage с разрешением 1, которое может не совпадать с разрешением исходного UIImage.
Самое простое решение — не делать ничего из того, что вы делаете. Во-первых, получите высоту безопасной зоны; назовите это h
. Затем просто нарисуйте изображение снимка в контексте графического изображения, который имеет тот же масштаб, что и ваше изображение (что, если вы правильно разыграете свои карты, это будет автоматически), но на h
пунктов короче, чем высота вашего изображения — и нарисуйте его. с его y
началом в -h
, тем самым отсекая безопасную область. Извлеките полученное изображение, и все готово.
Пример! Этот код входит в контроллер представления. Во-первых, я сделаю снимок экрана текущего экрана моего собственного устройства (представление этого контроллера представления), когда мое приложение работает:
let renderer = UIGraphicsImageRenderer(size: view.bounds.size)
let screenshot = renderer.image { context in
view.layer.render(in: context.cgContext)
}
Теперь я вырезаю безопасную область в верхней части этого скриншота:
let h = view.safeAreaInsets.top
let size = screenshot.size
let r = UIGraphicsImageRenderer(
size: .init(width: size.width, height: size.height - h)
)
let result = r.image { _ in
screenshot.draw(at: .init(x: 0, y: -h))
}
Эксперименты подтвердят, что это отлично работает на любом устройстве, независимо от того, есть ли у него рамка и независимо от разрешения экрана: верхняя часть полученного изображения, result
, является верхней частью вашего фактического содержимого.