hpique
hpique

Reputation: 120364

Get alpha channel from UIImage rectangle

Given a CGRect (rect) and a UIImage (image), how do you obtain the alpha values (only) of the image pixels in the rectangle?

The following code always returns 0 alpha, no matter the image or rectangle.

CGContextRef context = CGBitmapContextCreate(NULL,
                                             rect.size.width,
                                             rect.size.height,
                                             8,
                                             rect.size.width,
                                             NULL,
                                             kCGImageAlphaOnly);

UIGraphicsPushContext(context);
[image drawInRect:rect];
char *pixels = CGBitmapContextGetData(context);
NSUInteger pixelCount = rect.size.width * rect.size.height;
for (int i = 0; i < pixelCount; i++)
{
    char pixel = pixels[i];
    CGFloat alpha = pixel / 255.0;
    NSLog(@"%f", alpha);
}
UIGraphicsPopContext();
CGContextRelease(context);

Upvotes: 1

Views: 2180

Answers (5)

Mastergalen
Mastergalen

Reputation: 4389

In Swift 4 the code for getting only the alpha channel would looks like this:

import UIKit

extension UIImage {
    func alphaData() -> [UInt8]? {
        let size = self.size
        var alphaData = [UInt8](repeating: 0, count: Int(size.width) * Int(size.height))
        let colorSpace = CGColorSpaceCreateDeviceGray()
        let context = CGContext(
            data: &alphaData,
            width: Int(size.width),
            height: Int(size.height),
            bitsPerComponent: 8,
            bytesPerRow: Int(size.width),
            space: colorSpace,
            bitmapInfo: CGImageAlphaInfo.alphaOnly.rawValue
        );

        guard let cgImage = self.cgImage else { return nil }
        context?.draw(cgImage, in: CGRect(x: 0, y: 0, width: size.width, height: size.height))

        return alphaData
    }
}

Upvotes: 2

iphonic
iphonic

Reputation: 12717

I think this should help you.. https://github.com/OgreSwamp/ObjFloodFill

Upvotes: 0

Khaled Barazi
Khaled Barazi

Reputation: 8741

In my experience with RGBA values is that they all have to be unsigned char. I am guessing this might have caused your problem since a signed char would stop at 127 and never attain the full 255 value if this image had an opacity of 1 - and possibly worse not being properly aligned (read).

Upvotes: 0

Jon Brooks
Jon Brooks

Reputation: 2492

In the past, I have had issues getting CGBitmapContext working properly. I wouldn't be surprised if there was an issue with kCGImageAlphaOnly. You might do some sanity checking with some of the more 'mainstream' pixel formats like kCGImageAlphaPremultipliedFirst.

You might also try drawing the image using CGImageDrawImage:

CGContextRef context = CGBitmapContextCreate(NULL,
                                         rect.size.width,
                                         rect.size.height,
                                         8,
                                         rect.size.width,
                                         NULL,
                                         kCGImageAlphaOnly);

CGContextDrawImage( context, rect, image.CGImage);

//etc...

CGContextRelease(context);

Upvotes: 0

Eric
Eric

Reputation: 4061

pixelData[index + 3] will be a value for Alpha. pixelData[0-2] are RGB respectively

CFDataRef theData;

    theData = CGDataProviderCopyData(CGImageGetDataProvider(sourceImage));

    CFMutableDataRef mutableData = CFDataCreateMutableCopy(0, 0, theData);

    UInt8 *pixelData = (UInt8 *) CFDataGetBytePtr(mutableData);

    int dataLength = CFDataGetLength(mutableData);

    for (int index = 0; index < dataLength; index += 4) {
       //code here for just alpha
       pixelData[index + 3]
    }

Upvotes: 0

Related Questions