IOS, как сделать CIFilter VariableBlur темнее?

Я использую библиотеку VariableBlur в Swift, чтобы создать размытие над представлением моей коллекции под областью строки состояния как таковое:

IOS, как сделать CIFilter VariableBlur темнее?

Я пытаюсь понять, как сделать размытие темнее?

В библиотеке используется CIFilter, но я не знаю, что изменить, чтобы сделать его темнее. Я уже пробовал изменить UIBlurEffect(style: .regular) на .dark, но это не имело никакого значения.

А значок color0 на ciGradientFilter уже установлен на черный цвет. На самом деле, изменение его на красный или любой другой цвет не имеет никакого значения.

Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
0
60
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Ответ принят как подходящий

Существующий makeGradientImage уже создает градиентное изображение, причем color0 установлен на черный цвет, как вы заметили. Существующий код использует это как маску, но вы можете отобразить это изображение в своем собственном CALayer, который добавляется как родственный backdropLayer.

open class VariableBlurUIView: UIVisualEffectView {

    let darkLayer = CALayer()
    
    public init(maxBlurRadius: CGFloat = 20, direction: VariableBlurDirection = .blurredTopClearBottom, startOffset: CGFloat = 0) {
        super.init(effect: UIBlurEffect(style: .regular))

        // ...

        let gradientImage = makeGradientImage(startOffset: startOffset, direction: direction)

        variableBlur.setValue(maxBlurRadius, forKey: "inputRadius")
        variableBlur.setValue(gradientImage, forKey: "inputMaskImage")
        variableBlur.setValue(true, forKey: "inputNormalizeEdges")

        let backdropLayer = subviews.first?.layer

        backdropLayer?.filters = [variableBlur]
        
        darkLayer.contents = gradientImage
        darkLayer.zPosition = -1
        backdropLayer?.superLayer?.addSublayer(darkLayer)
        
        for subview in subviews.dropFirst() {
            subview.alpha = 0
        }
    }
    
    open override func layoutSublayers(of layer: CALayer) {
        darkLayer.frame = subviews.first?.layer.frame ?? .zero
    }

    // ...

}

Параллельное сравнение:

Знаете ли вы, почему на конце градиента внизу появляется внезапная прозрачная линия вместо гладкой? Это сложно показать, но более очевидно при прокрутке и когда контент под ним светлый. Например, с белым цветом это очень очевидно: i.imgur.com/dADDkLt.jpeg

sudoExclamationExclamation 16.08.2024 23:22

к сожалению, он все еще показывает внезапную прозрачную линию. В приложении «Фото» этой проблемы нет.

sudoExclamationExclamation 17.08.2024 06:44

в конечном итоге эта линия перемещается на половину высоты. Сначала вы можете не увидеть линию, но если вы посмотрите на нее на белом фоне, я думаю, вы ее заметите. Это не видно на изображении, которое вы используете в своем ответе. Линия присутствует, даже если мы отключим размытие. Градиент является причиной проблемы. Интересно, могу ли я установить градиент так, чтобы он был более темным в первой трети и менее темным в дальнейшем?

sudoExclamationExclamation 17.08.2024 10:05

@sudoExclamationExclamation Ну, это было бы darkLayer.locations = [0.0, 0.3333333], но я сомневаюсь, что это что-то изменит. Идея сделать этот слой родственным слоем состоит в том, чтобы на darkLayer также влияло размытие, которое, как я ожидаю, удалит линию. Попробуйте использовать полностью черный слой вместо CAGradientLayer. Оно должно быть размытым, но есть ли еще линия?

Sweeper 17.08.2024 10:12

@sudoExclamationExclamation На самом деле мне вообще не нужно использовать CAGradientLayer. Существующий метод makeGradientImage уже создает градиент от черного к прозрачному. Просто покажите это обычным CALayer! Я обновил ответ.

Sweeper 17.08.2024 10:41

ваш способ использования существующего метода makeGradientImage сработал хорошо! Вместо этого я также смог изменить значение color0 с black на CIColor(color: UIColor.black.withAlphaComponent(0.7)) для более утонченного вида. Спасибо!

sudoExclamationExclamation 17.08.2024 20:05
//import CoreImage

func applyVariableBlurAndDarken(to image: UIImage) -> UIImage? {
    guard let ciImage = CIImage(image: image) else { return nil }
     // Apply VariableBlur Filter
    let variableBlurFilter = CIFilter(name: "CIMaskedVariableBlur")!
    variableBlurFilter.setValue(ciImage, forKey: kCIInputImageKey)
    variableBlurFilter.setValue(10.0, forKey: "inputRadius")  // Adjust the blur radius as needed
    
    guard let blurredImage = variableBlurFilter.outputImage else { return nil }
    
    // Apply Color Controls to darken the image
    let colorControlsFilter = CIFilter(name: "CIColorControls")!
    colorControlsFilter.setValue(blurredImage, forKey: kCIInputImageKey)
    colorControlsFilter.setValue(-0.5, forKey: kCIInputBrightnessKey) // Reduce brightness to darken
    colorControlsFilter.setValue(1.2, forKey: kCIInputContrastKey)   // Optional: increase contrast
    
    guard let darkenedImage = colorControlsFilter.outputImage else { return nil }
    
    // Render the final image
    let context = CIContext()
    guard let cgImage = context.createCGImage(darkenedImage, from: darkenedImage.extent) else { return nil }
    
    return UIImage(cgImage: cgImage)
}

// Usage
if let image = UIImage(named: "your_image_name") {
    let processedImage = applyVariableBlurAndDarken(to: image)
    // Now you can use the processedImage
}

Это применение его к статическому изображению. Библиотека VariableBlurView, которую я использую, позволяет в реальном времени размывать прокручиваемый UICollectionView. Знаешь, как я могу это сделать?

sudoExclamationExclamation 16.08.2024 08:54

Привет, попробуйте решение ниже :)

Sk Ahammed 16.08.2024 12:12
/*To adjust the darkness of a real-time blur effect over a scrolling UICollectionView using the VariableBlurView*/

импортировать UIKit импортировать CoreImage импортировать VariableBlurView

класс DarkenedVariableBlurView: VariableBlurView {

override func applyBlurEffect() {
    super.applyBlurEffect()
    
    // Access the existing CIFilter used for blurring
    guard let blurFilter = self.currentBlurFilter else { return }
    
    // Create a CIColorControls filter to adjust brightness and contrast
    let colorControlsFilter = CIFilter(name: "CIColorControls")!
    colorControlsFilter.setValue(blurFilter.outputImage, forKey: kCIInputImageKey)
    colorControlsFilter.setValue(-0.5, forKey: kCIInputBrightnessKey) // Darkening effect
    colorControlsFilter.setValue(1.2, forKey: kCIInputContrastKey)    // Increase contrast
    
    // Apply the filter chain and update the view's content
    if let darkenedOutput = colorControlsFilter.outputImage {
        self.updateView(with: darkenedOutput)
    }
}

private func updateView(with image: CIImage) {
    let context = CIContext()
    if let cgImage = context.createCGImage(image, from: image.extent) {
        self.layer.contents = cgImage
    }
}

}

/* Замените VariableBlurView на свой собственный DarkenedVariableBlurView: Используйте класс DarkenedVariableBlurView в представлении, которое перекрывает ваш UICollectionView.*/

//Если VariableBlurView уже обновляется в режиме реального времени по мере прокрутки представления коллекции, то ваш пользовательский фильтр должен применяться динамически без дополнительного кода. Если нет, убедитесь, что ваше представление обновлено в методе делегата ScrollViewDidScroll:

расширение YourViewController: UIScrollViewDelegate {

func scrollViewDidScroll(_ scrollView: UIScrollView) {
    if let blurView = yourCustomBlurView as? DarkenedVariableBlurView {
        blurView.applyBlurEffect()
    }
}

}

пожалуйста, попробуйте это :)

Разве это не будет крайне низкой производительностью, поскольку каждый раз при вызове scrollViewDidScroll происходит переделка?

sudoExclamationExclamation 16.08.2024 23:07

Другие вопросы по теме