How to get the pixel color on touch?

后端 未结 5 2090
闹比i
闹比i 2020-11-27 02:28

I know this is a common question and there are a lot of answers of this question. I\'ve used some of this. Although many of them are the same. But the sad thing for me is th

相关标签:
5条回答
  • 2020-11-27 02:59

    Swift 4, Xcode 9 - With a UIImageView Extension

    This is a combination of all of the answers above but in an extension

    extension UIImageView {
        func getPixelColorAt(point:CGPoint) -> UIColor{
            
            let pixel = UnsafeMutablePointer<CUnsignedChar>.allocate(capacity: 4)
            let colorSpace = CGColorSpaceCreateDeviceRGB()
            let bitmapInfo = CGBitmapInfo(rawValue: CGImageAlphaInfo.premultipliedLast.rawValue)
            let context = CGContext(data: pixel, width: 1, height: 1, bitsPerComponent: 8, bytesPerRow: 4, space: colorSpace, bitmapInfo: bitmapInfo.rawValue)
            
            context!.translateBy(x: -point.x, y: -point.y)
            layer.render(in: context!)
            let color:UIColor = UIColor(red: CGFloat(pixel[0])/255.0,
                                        green: CGFloat(pixel[1])/255.0,
                                        blue: CGFloat(pixel[2])/255.0,
                                        alpha: CGFloat(pixel[3])/255.0)
            
            pixel.deallocate(capacity: 4)
            return color
        }
    }
    

    How to use

    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
        let touch = touches.first
        if let point = touch?.location(in: view) {
            let color = myUIImageView.getPixelColorAt(point: point)
            print(color)
        }
    }
    
    0 讨论(0)
  • 2020-11-27 03:04

    Thank you for @Aggressor's post the code above

    Swift 2.1

    func getPixelColorAtPoint(point:CGPoint) -> UIColor{
    
       let pixel = UnsafeMutablePointer<CUnsignedChar>.alloc(4)
       let colorSpace = CGColorSpaceCreateDeviceRGB()
       let bitmapInfo = CGBitmapInfo(rawValue: CGImageAlphaInfo.PremultipliedLast.rawValue)
       let context = CGBitmapContextCreate(pixel, 1, 1, 8, 4, colorSpace, bitmapInfo.rawValue)
    
       CGContextTranslateCTM(context, -point.x, -point.y)
       view.layer.renderInContext(context!)
       let color:UIColor = UIColor(red: CGFloat(pixel[0])/255.0, green: CGFloat(pixel[1])/255.0, blue: CGFloat(pixel[2])/255.0, alpha: CGFloat(pixel[3])/255.0)
    
       pixel.dealloc(4)
       return color
    }
    

    Swift 3, Xcode Version 8.2 (8C38) and Swift 4, Xcode Version 9.1 (9B55)

     func getPixelColorAtPoint(point:CGPoint, sourceView: UIView) -> UIColor{
    
        let pixel = UnsafeMutablePointer<CUnsignedChar>.allocate(capacity: 4)
        let colorSpace = CGColorSpaceCreateDeviceRGB()
        let bitmapInfo = CGBitmapInfo(rawValue: CGImageAlphaInfo.premultipliedLast.rawValue)
        let context = CGContext(data: pixel, width: 1, height: 1, bitsPerComponent: 8, bytesPerRow: 4, space: colorSpace, bitmapInfo: bitmapInfo.rawValue)
        var color: UIColor? = nil
    
        if let context = context {
            context.translateBy(x: -point.x, y: -point.y)
            sourceView.layer.render(in: context)
    
            color = UIColor(red: CGFloat(pixel[0])/255.0,
                            green: CGFloat(pixel[1])/255.0,
                            blue: CGFloat(pixel[2])/255.0,
                            alpha: CGFloat(pixel[3])/255.0)
    
            pixel.deallocate(capacity: 4)
        }
        return color
    }
    
    0 讨论(0)
  • 2020-11-27 03:09

    First, I'd like to thank the author of this code, it helped me a lot for my game project, as I was looking for this function to do a pixel-perfect hitbox (excluding where the aplha is O). Here's a little update for Swift 5:

    // Fonction permettant de retourner les valeurs RGBA d'un pixel d'une vue
    func getPixelColor(atPosition:CGPoint) -> UIColor{
    
        var pixel:[CUnsignedChar] = [0, 0, 0, 0];
        let colorSpace = CGColorSpaceCreateDeviceRGB();
        let bitmapInfo = CGBitmapInfo(rawValue:    CGImageAlphaInfo.premultipliedLast.rawValue);
        let context = CGContext(data: &pixel, width: 1, height: 1, bitsPerComponent: 8, bytesPerRow: 4, space: colorSpace, bitmapInfo: bitmapInfo.rawValue);
    
        context!.translateBy(x: -atPosition.x, y: -atPosition.y);
        layer.render(in: context!);
        let color:UIColor = UIColor(red: CGFloat(pixel[0])/255.0,
                                    green: CGFloat(pixel[1])/255.0,
                                    blue: CGFloat(pixel[2])/255.0,
                                    alpha: CGFloat(pixel[3])/255.0);
    
        return color;
    
    }
    

    I had somme issues with pixel.dealloc(4), as in Swift 5 it seems that you can't dealloc with capacity parameter anymore. I removed the (4), but it had some weird behavior (as the dealloc() didn't dealloc the whole array).

    I didn't do an extension of UIView as in my project I have my own subclass, but this can be easily done.

    The way I implement the code:

    // Méthode déterminant si le "touch" est validé par l'objet (par défaut, exclut les zones transparentes et les objets invisibles). A surcharger si nécessaire.
    func isHit(atPosition position:CGPoint) -> Bool
    {
    
        // Si l'objet n'est pas caché (paramètre isHidden) et si la zone touchée correspond à une zone effectivement dessinée (non transparente), retourne true.
        if (!self.isHidden && self.getPixelColor(atPosition: position).cgColor.alpha != 0) {return true}
        else {return false}
    
    }
    

    I hope this can help.

    0 讨论(0)
  • 2020-11-27 03:13

    Great answer rdelmar this helped me A LOT!

    Here is how I did the above in Swift:

    override func touchesBegan(touches: NSSet, withEvent event: UIEvent)
        {
            var touch:UITouch = event.allTouches()!.anyObject() as UITouch
            var loc = touch.locationInView(self)
            var color:UIColor = getPixelColorAtPoint(loc)
            println(color)
        }
    
        //returns the color data of the pixel at the currently selected point
        func getPixelColorAtPoint(point:CGPoint)->UIColor
        {
            let pixel = UnsafeMutablePointer<CUnsignedChar>.alloc(4)
            var colorSpace = CGColorSpaceCreateDeviceRGB()
            let bitmapInfo = CGBitmapInfo(CGImageAlphaInfo.PremultipliedLast.rawValue)
            let context = CGBitmapContextCreate(pixel, 1, 1, 8, 4, colorSpace, bitmapInfo)
    
            CGContextTranslateCTM(context, -point.x, -point.y)
            layer.renderInContext(context)
            var color:UIColor = UIColor(red: CGFloat(pixel[0])/255.0, green: CGFloat(pixel[1])/255.0, blue: CGFloat(pixel[2])/255.0, alpha: CGFloat(pixel[3])/255.0)
    
            pixel.dealloc(4)
            return color
        }
    
    0 讨论(0)
  • 2020-11-27 03:22

    This is the one I've used, and it looks simpler than the methods you've tried.

    In my custom view class, I have this:

    - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
        UITouch *touch = [[event allTouches] anyObject];
        CGPoint loc = [touch locationInView:self];
        self.pickedColor = [self colorOfPoint:loc];
    }
    

    colorOfPoint is a method in a category on UIView, with this code:

    #import "UIView+ColorOfPoint.h"
    #import <QuartzCore/QuartzCore.h>
    
    @implementation UIView (ColorOfPoint)
    
    -(UIColor *) colorOfPoint:(CGPoint)point
        {
        unsigned char pixel[4] = {0};
        CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
        CGContextRef context = CGBitmapContextCreate(pixel,
                1, 1, 8, 4, colorSpace, (CGBitmapInfo)kCGImageAlphaPremultipliedLast);
    
        CGContextTranslateCTM(context, -point.x, -point.y);
    
        [self.layer renderInContext:context];
    
        CGContextRelease(context);
        CGColorSpaceRelease(colorSpace);
        UIColor *color = [UIColor colorWithRed:pixel[0]/255.0
            green:pixel[1]/255.0 blue:pixel[2]/255.0
            alpha:pixel[3]/255.0];
        return color;
        }
    

    Don't forget to import the category into the custom view class and add the QuartzCore framework.


    Trivial note for 2013: cast that last argument as (CGBitmapInfo) to avoid an implicit conversion warning: example here. Hope it helps.

    0 讨论(0)
提交回复
热议问题