Получить альфа-канал из прямоугольника UIImage

Учитывая CGRect (rect) и UIImage (image), как вы получаете альфа-значения (только) пикселей изображения в прямоугольнике?

Следующий код всегда возвращает 0 альфа, независимо от изображения или прямоугольника.

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);

person hpique    schedule 21.02.2013    source источник
comment
любопытно, попробовали ли вы мою рекомендацию ниже. Интересно, решило ли это проблему?   -  person Khaled Barazi    schedule 27.02.2013
comment
@Spectravideo328 Нет.   -  person hpique    schedule 02.03.2013
comment
Интересно, имеет ли значение цветовое пространство, когда вы делаете снимок из контекста? Вы пытались создать CGColorSpaceRef colorSpace=CGColorSpaceCreateDeviceRGB(); и присвоив его 6-му аргументу (заменив NULL).   -  person Khaled Barazi    schedule 03.03.2013
comment
@Spectravideo328 Согласно этому developer.apple.com/library/mac/ #qa/qa1037/_index.html , цветовое пространство должно быть NULL.   -  person hpique    schedule 03.03.2013
comment
Откуда берется ваше изображение, и вы уверены, что оно имеет только 1 бит ненулевой альфы?   -  person Khaled Barazi    schedule 03.03.2013
comment
@Spectravideo328 Ага. Мне удалось заставить это работать, используя CGContextDrawImage вместо drawInRect:, как указано в одном из ответов.   -  person hpique    schedule 03.03.2013


Ответы (5)


В прошлом у меня были проблемы с правильной работой CGBitmapContext. Я не удивлюсь, если возникнут проблемы с kCGImageAlphaOnly. Вы можете провести некоторую проверку работоспособности с некоторыми из более «основных» форматов пикселей, таких как kCGImageAlphaPremultipliedFirst.

Вы также можете попробовать нарисовать изображение, используя 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);
person Jon Brooks    schedule 26.02.2013
comment
Я пробовал с CGContextDrawImage, и kCGImageAlphaOnly работает так, как рекламируется. Я бы сказал, что использую drawInRect: неправильно. Есть идеи, почему? - person hpique; 02.03.2013
comment
Без понятия. Возможно, у UIGraphic есть недокументированная проблема с форматами пикселей kCGImageAlphaOnly, или, может быть, сработает вызов UIGraphicsPopContext() перед попыткой сбора данных (просто дикие догадки). Однако, поскольку все остальное вы делаете на уровне компьютерной графики, кажется ненужным переходить на уровень UIGraphics для рисования. - person Jon Brooks; 05.03.2013

В Swift 4 код для получения только альфа-канала будет выглядеть так:

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
    }
}
person Mastergalen    schedule 23.10.2018
comment
Как я могу добавить извлеченные альфа-данные в другой UIImage - person Ajay nath; 07.01.2021

pixelData[index + 3] будет значением для Alpha. pixelData[0-2] являются RGB соответственно

CFDataСсылка на данные;

    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]
    }
person Eric    schedule 21.02.2013
comment
kCGImageAlphaOnly не возвращает только один байт, как указано здесь: developer. apple.com/library/mac/#qa/qa1037/_index.html ? - person hpique; 22.02.2013
comment
Вы по-прежнему можете манипулировать данными или сбрасывать этот пиксель в операторе for. Бывший. если я хочу изменить альфу с 1 на 255, умножьте на 255. - person Eric; 22.02.2013
comment
Я не понимаю твоего решения. Вы не используете входной прямоугольник и загружаете все изображение в память. - person hpique; 02.03.2013
comment
мой код использует изображение, но я считаю, что вы можете получить один и тот же образец RGBA из любого представления. [index + 0(0) -> 0(3)] дает вам значения RGBA в 0-3 соответственно. - person Eric; 04.03.2013

По моему опыту со значениями RGBA, все они должны быть беззнаковыми символами. Я предполагаю, что это могло вызвать вашу проблему, поскольку подписанный символ остановится на 127 и никогда не достигнет полного значения 255, если это изображение имеет непрозрачность 1 - и, возможно, хуже, если оно не будет правильно выровнено (читай).

person Khaled Barazi    schedule 26.02.2013
comment
Переход на unsigned char не изменил результат. Тем не менее, в любом случае это должен быть беззнаковый символ, поэтому я отредактировал исходный вопрос. - person hpique; 02.03.2013

Я думаю, это должно вам помочь. https://github.com/OgreSwamp/ObjFloodFill

person iphonic    schedule 04.03.2013