Проблема преобразования Objective-C в Swift на CGBitmapInfo

У меня есть этот код Objective-C, который убирает непрозрачный фон фильтра. Я пытаюсь преобразовать его в последнюю версию Swift и повсюду возникают ошибки.

-(UIImage*)removeColorFromImage:(UIImage*)sourceImage grayLevel:(int)grayLevel
{
    int width = sourceImage.size.width * sourceImage.scale;
    int height = sourceImage.size.height * sourceImage.scale;
    CGFloat scale = sourceImage.scale;

    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
    CGContextRef context = CGBitmapContextCreate(NULL, width, height, 8, width * 4, colorSpace, kCGBitmapAlphaInfoMask & kCGImageAlphaPremultipliedFirst);
    CGColorSpaceRelease(colorSpace);

    CGContextDrawImage(context, CGRectMake(0, 0, width, height), sourceImage.CGImage);

    unsigned int *colorData = CGBitmapContextGetData(context);

    for (int i = 0; i < width * height; i++)
    {
        unsigned int color = *colorData;

        short a = color & 0xFF;
        short r = (color >> 8) & 0xFF;
        short g = (color >> 16) & 0xFF;
        short b = (color >> 24) & 0xFF;

        if ((r == grayLevel) && (g == grayLevel) && (b == grayLevel))
        {
            a = r = g = b = 0;
            *colorData = (unsigned int)(r << 8) + ((unsigned int)(g) << 16) + ((unsigned int)(b) << 24) + ((unsigned int)(a));
        }

        colorData++;
    }

    CGImageRef output = CGBitmapContextCreateImage(context);
    UIImage* retImage = [UIImage imageWithCGImage:output scale:scale orientation:UIImageOrientationUp];

    CGImageRelease(output);
    CGContextRelease(context);

    return retImage;
}

Когда я конвертирую построчно. Я дошел до этого, но у меня проблемы с преобразованием строк:

var context = CGBitmapContextCreate(nil, width, height, 8, width * 4, colorSpace, CGBitmapInfo(CGImageAlphaInfo.PremultipliedFirst.rawValue))

РЕДАКТИРОВАТЬ** Вот как выглядят ошибки: введите здесь описание изображения


person Gizmodo    schedule 04.05.2016    source источник
comment
В чем ошибка? Похоже, мне не хватает аргумента инициализатора rawValue: (из CGBitmapInfo). Также context скорее всего должна быть константой let.   -  person Hamish    schedule 05.05.2016
comment
Обновил Исходный пост.   -  person Gizmodo    schedule 05.05.2016
comment
Почему вы переходите на быстрый код? почему бы не использовать объективный код C в быстром использовании моста? developer.apple.com/library/ios/documentation/ Быстрый/Концептуальный/   -  person Hasya    schedule 05.05.2016


Ответы (1)


Я считаю, что это правильный порт исходного кода:

func removeColorFromImage(sourceImage: UIImage, grayLevel: UInt32) -> UIImage? {
    let scale = sourceImage.scale
    let width = Int(sourceImage.size.width * scale)
    let height = Int(sourceImage.size.height * scale)
    let colorSpace = CGColorSpaceCreateDeviceRGB()
    let bitmapInfo = CGBitmapInfo(rawValue: CGBitmapInfo.AlphaInfoMask.rawValue & CGImageAlphaInfo.PremultipliedFirst.rawValue)
    let context = CGBitmapContextCreate(nil, width, height, 8, width * 4, colorSpace, bitmapInfo.rawValue)
    CGContextDrawImage(context, CGRectMake(0, 0, CGFloat(width), CGFloat(height)), sourceImage.CGImage)

    let uncastedData = CGBitmapContextGetData(context)
    let colorData = UnsafeMutablePointer<UInt32>(uncastedData)
    for i in 0..<width * height {
        let color = colorData[i]
        var a = color & 0xFF
        var r = (color >> 8) & 0xFF
        var g = (color >> 16) & 0xFF
        var b = (color >> 24) & 0xFF
        if ((r == grayLevel) && (g == grayLevel) && (b == grayLevel)) {
            (a, r, g, b) = (0, 0, 0, 0)
            colorData[i] = (r << 8) + (g << 16) + (b << 24) + a
        }
        colorData.advancedBy(1)
    }

    if let output = CGBitmapContextCreateImage(context) {
        return UIImage(CGImage: output, scale: scale, orientation: UIImageOrientation.Up)
    }

    return nil
}

Вот пример (исходный -> вывод):

original output

removeColorFromImage(original, grayLevel: 175)

Объяснение изменений

Начиная с Swift 2 (я полагаю), вы должны использовать rawValue для последнего параметра CGBitmapContextCreate:

let context = CGBitmapContextCreate(nil, width, height, 8, width * 4, colorSpace, bitmapInfo.rawValue)

Кроме того, в вашем порту вы не использовали исходные значения из кода Objective-C:

// your new code was just using CGImageAlphaInfo.PremultipliedFirst.rawValue
// to match, it should be:
let bitmapInfo = CGBitmapInfo(rawValue: CGBitmapInfo.AlphaInfoMask.rawValue & CGImageAlphaInfo.PremultipliedFirst.rawValue)

Сдвиг битов, который вы выполняли в цикле for в стиле C, относился к недопустимым типам. Сейчас он на UInt32s. Я также избавился от предупреждения о цикле в стиле C :)

Наконец, вам нужно использовать это для инициализации окончательного UIImage:

UIImage(CGImage: output, scale: scale, orientation: UIImageOrientation.Up)

Функция класса, которую вы пытались использовать, недействительна.

person Jordan    schedule 05.05.2016