@Claude31, thank you for your reply, but is not work.
I found the solution
in UIView.draw function create a CGImageContext with final image pixel size
draw UIImage into CGImageContext
get CGImage from CGImageContext
draw this CGImage into CGContext of UIView.draw
it works well.
there is my code:
override func draw(_ rect: CGRect) {
guard let ctx = UIGraphicsGetCurrentContext() else { return }
// fill background with black color
ctx.addRect(bounds)
ctx.setFillColor(UIColor.black.cgColor)
ctx.fillPath()
if var im = image {
// image pixel size is 4032 * 4032, so aspect is 1:1=1,
// bounds size is logical size (384 * 512), so I need found a max size in bounds and keep my image aspect
// so 'size' is (384 * 384)
let size = Math.getMaxSizeWithAspect(size: CGSize(width: bounds.width, height: bounds.height), radioWidthToHeight: im.size.width / im.size.height)
// pixelSize = (384 * 3, 384 * 3) = (1152, 1152)
let pixelSize = CGSize(width: size.width * layer.contentsScale, height: size.height * layer.contentsScale)
// I create a pixelSize ImageContext
UIGraphicsBeginImageContextWithOptions(pixelSize, true, 1)
guard let imgCtx = UIGraphicsGetCurrentContext() else { return }
// draw UIImage into ImageContext
im.draw(in: CGRect(x: 0, y: 0, width: pixelSize.width, height: pixelSize.height))
// get cgImage
guard let cgImg = imgCtx.makeImage() else { return }
// there is another strange thing, CGContext draw cgImg will show a vertical flip result
// so I have to vertical flip first
ctx.scaleBy(x: 1, y: -1)
ctx.translateBy(x: 0, y: -bounds.height)
// draw cgImage into UIView's context
ctx.draw(cgImg, in: CGRect(x: (bounds.width - size.width) / 2, y: (bounds.height - size.height) / 2, width: size.width, height: size.height))
// it works like charm :D
}
}