Вземете алфа канал от 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(), преди да се опитате да съберете данните, ще проработи (само глупави предположения). Въпреки това, тъй като правите всичко останало на ниво CG, изглежда ненужно да скачате до ниво 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] ще бъде стойност за алфа. pixelData[0-2] са съответно RGB

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]
    }
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 стойностите всички те трябва да са unsigned char. Предполагам, че това може да е причинило проблема ви, тъй като знак със знак ще спре на 127 и никога няма да достигне пълната стойност 255, ако това изображение има непрозрачност 1 - и вероятно по-лошо, че не е правилно подравнено (прочетете).

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

Мисля, че това трябва да ви помогне.. https://github.com/OgreSwamp/ObjFloodFill

person iphonic    schedule 04.03.2013