0

I'm using this code to get CGLayer with alpha radial gradient:

    let scale = UIScreen.main.scale
    let roundedSize = round(size)
    var canvasSize = size_t(roundedSize)
    canvasSize *= size_t(scale)
    let colorSpace = CGColorSpaceCreateDeviceRGB()
    context = CGContext(data: nil,
                        width: canvasSize,
                        height: canvasSize,
                        bitsPerComponent: 8,
                        bytesPerRow: canvasSize * 4,
                        space: colorSpace,
                        bitmapInfo: CGBitmapInfo.alphaInfoMask.rawValue & CGImageAlphaInfo.premultipliedLast.rawValue)
    cgLayer = CGLayer(context, size: CGSize(width: canvasSize, height: canvasSize), auxiliaryInfo: nil)
    let ctx = cgLayer.context
    var ctxRect = CGRect.zero
    ctxRect.size.height = CGFloat(canvasSize)
    ctxRect.size.width = ctxRect.size.height
    ctx?.clear(ctxRect)
    ctxRect = ctxRect.insetBy(dx: 1.0, dy: 1.0)
    let innerColor = UIColor(white: !whiteBrush ? 1.0 : 0.0, alpha: CGFloat(min(hardness + 0.5, 1))).cgColor
    let outerColor = innerColor.copy(alpha: 0.0)
    if hardness != 1.0 {
        var locations = [CGFloat](repeating: 0.0, count: 2)
        locations[0] = hardness
        locations[1] = 1.0
        let colors = [innerColor, outerColor]
        let colorsCF = colors as CFArray
        let gradient = CGGradient(colorsSpace: colorSpace, colors: colorsCF, locations: &locations)
        let center = CGPoint(x: CGFloat(canvasSize) / 2.0, y: CGFloat(canvasSize) / 2.0)
        if let gradient = gradient {
            ctx?.drawRadialGradient(gradient,
                                    startCenter: center,
                                    startRadius: 0.0,
                                    endCenter: center,
                                    endRadius: center.x - 1.0,
                                    options: .drawsAfterEndLocation)
        }

It should render a smooth gradient but instead of this I've got two different results (images are white, looks ok on dark mode :D): One is a poor gradient with a solid center (solid center is expected if hardness is > 0.5)

enter image description here

Or with similar values of hardness and size, something more blurry and ugly:

enter image description here

How I can get better results with creating gradients? Instead of smooth transition, I have some pixelated half ovals, looks ugly. I want something like a brush in paint, that gives a smooth transition on the alpha channel.

I'm using this code to "render" them:

var image: UIImage? {
    context.setFillColor(gray: 1, alpha: 0)
    //CGContextSetFillColorWithColor(_context, [[UIColor clearColor] CGColor]);
    context.fill(context.boundingBoxOfClipPath)
    context.draw(cgLayer, at: CGPoint.zero)
    let cgImage = context.makeImage()
    var image: UIImage?
    if let cgImage = cgImage {
        image = UIImage(cgImage: cgImage, scale: 1, orientation: .up)
    }
    return image
}
Prettygeek
  • 2,461
  • 3
  • 22
  • 44
  • Are we intended to be seeing images here? – matt Sep 21 '20 at 13:22
  • @matt - white on white, I see them on dark mode:) – Prettygeek Sep 21 '20 at 13:23
  • Well, maybe this is intended as a joke. It's pretty much impossible to assess what you're asking. However, I've never seen CGLayer used for anything and I don't understand what you're doing with it here. There is a radial CGGradient, or use the radial gradient CIFilter. – matt Sep 21 '20 at 13:52
  • Yes but CGLayer is not CALayer; CGLayer is highly specialized. Of course I could be wrong, but I've been drawing with core graphics since like forever and I've never used CGLayer for anything. – matt Sep 21 '20 at 14:28
  • So how one can draw gradient on bitmap with alpha channel? – Prettygeek Sep 21 '20 at 14:30
  • It's all kind of abstract. I don't know why you need to create a bitmap rather than using an image graphics context. Perhaps you could show the _real_ usage you're trying to put this to? I mean, I make vignette gradients on images all the time, but not this way. – matt Sep 21 '20 at 14:33
  • @matt i’m using this context and its layer to paint this gradient on another contex, lets say canvas. So this works as brush, You can change size and hardness, and then use it to paint on canvas. If You have better library to achieve this functionality, I would be more than happy to rewrite my solution. – Prettygeek Sep 23 '20 at 09:45

0 Answers0