изменить изображение пользовательского интерфейса в массив строк

У меня есть UIImage, состоящий только из 4 типов пикселей.

static let black = RGBA32(red: 0, green: 0, blue: 0, alpha: 255)
static let red   = RGBA32(red: 255, green: 0, blue: 0, alpha: 255)
static let green = RGBA32(red: 0, green: 255, blue: 0, alpha: 255)
static let blue  = RGBA32(red: 0, green: 0, blue: 255, alpha: 255)

(ссылка на код, используемый для создания изображения https://stackoverflow.com/a/40207142/7010252)

Я сохранил изображение в библиотеке фотографий телефона, а затем снова открыл изображение в своем приложении. Я знаю, что количество пикселей одинаково.

Итак, как я могу получить данные RGBA для всех пикселей?


person l.b.dev    schedule 11.12.2016    source источник


Ответы (1)


Первое, что здесь нужно сделать, это просмотреть ваше изображение и создать карту всех точек на нем.

func getPixelColor(image: UIImage) {
    let width = image.size.width
    let height = image.size.height

    for x in 0..<Int(width) {
        for y in 0..<Int(height) {
            let color = image.pixelColor(CGPoint(x: CGFloat(x), y: CGFloat(y)))
            print(color.RGBA)
        }
    }
}

Получив желаемый цвет, он вызывает функцию RGBA в расширении UIColor, чтобы предоставить нужную строку.

Затем мы используем расширение UIImage, чтобы затем взять точки, предоставленные вышеприведенной функцией, и запросить данные изображения для его данных UIColor.

extension UIImage {
    func pixelColor(_ point: CGPoint) -> UIColor {
        let pixelData = cgImage?.dataProvider?.data
        let pointerData: UnsafePointer<UInt8> = CFDataGetBytePtr(pixelData)

        let pixelInfo = Int(((self.size.width * point.y) + point.x)) * 4

        let maxValue: CGFloat = 255.0
        let compare: CGFloat = 0.99

        let r: CGFloat = (CGFloat(pointerData[pixelInfo]) / maxValue) > compare ? 1.0 : 0.0
        let g: CGFloat = (CGFloat(pointerData[pixelInfo + 1]) / maxValue) > compare ? 1.0 : 0.0
        let b: CGFloat = (CGFloat(pointerData[pixelInfo + 2]) / maxValue) > compare ? 1.0 : 0.0
        let a = CGFloat(pointerData[pixelInfo + 3]) / maxValue

        return UIColor(red: r, green: g, blue: b, alpha: a)
    }
}

Это расширение использует необработанные данные для определения значений RGB для каждого пикселя. Затем он выполняет грубую проверку, чтобы не рисковать с CGFloats, чтобы увидеть, равно ли значение 255,0 для этого конкретного цвета. Если это так, он вернет значение 1,0, в противном случае он вернет 0,0.

Далее, есть расширение для UIColor, которое предоставит форматированную строку, которую вы ищете.

extension UIColor {
    var RGBA: String {
        guard let components = cgColor.components, components.count == 4 else {
            return ""
        }

        return "\(components[0])-\(components[1])-\(components[2])-\(components[3])"
    }
}

Это должно предоставить значения типа 1-0-0-1, которые вы ищете. Вы также можете изменить это, чтобы включить любую дополнительную информацию, которая вам нужна.

person CodeBender    schedule 11.12.2016
comment
но когда я использую этот код, возникает проблема. Я должен получить (rgba) 1-0-0-1 (красный) / 0-1-0-1 (зеленый) / 0-0-1-1 (синий) / 0-0-0-1 (черный) но я получаю двойное, например: (rgba) 0,6787878 - 0,823345 - 0,34522 - 1 - person l.b.dev; 14.12.2016
comment
Обновлено для решения вашей проблемы. Надеюсь, это решит это. - person CodeBender; 14.12.2016
comment
нет, не сработало, я всегда получаю 0.0-0.0-0.0-1.0. Это означает, что пиксель черный, но на самом деле изображение не черное. У вас есть идея, как мне это исправить? @CodeBender - person l.b.dev; 15.12.2016
comment
это не так: пусть r: CGFloat = (CGFloat(pointerData[pixelInfo]) / maxValue) › 254,9 ? 1,0 : 0,0 - person l.b.dev; 18.12.2016
comment
это: пусть r: CGFloat = (CGFloat(pointerData[pixelInfo]) / maxValue) › 0,9 ? 1,0 : 0,0 - person l.b.dev; 18.12.2016
comment
Плохо, я просто проверил это слишком поздно. Обновлен ответ, чтобы включить это. - person CodeBender; 18.12.2016