Есть ли способ сделать цвет текста в TextInput в kivy, чтобы быть зависимым от фона? - PullRequest
0 голосов
/ 14 мая 2019

Я использую TextInput Kivy и у меня есть фоновое изображение позади него. Поскольку имеется фоновое изображение - текст над ним неясен (то есть черный текст на черном фоне и т. Д.).

Есть ли способ сделать цвет текста противоположным фону позади него?

Обратите внимание, что фон - это не одноцветное изображение, а обычное изображение. Спасибо!

Кроме того, я хотел бы иметь текстовый контур, чтобы он был более читабельным. Пробовал свойство text_outline, но оно для меток, а не для textInputs. Есть ли альтернатива?

Еще раз спасибо!

Ответы [ 2 ]

1 голос
/ 15 мая 2019

Общий алгоритм может быть следующим:

  1. найти средний цвет вашего изображения
  2. найти комплиментарный или контрастный цвет

  3. установить цвет text_input на контрастный цвет.

Реализация 1 и 2 может быть довольно сложной.В этом примере я покажу только грубый набросок.Конечно, вы можете найти или реализовать более эффективные функции.

  1. найти доминирующий цвет изображения:
from PIL import Image as I

def average_color(image_fn):
    im = I.open(image_fn)
    im = im.convert('RGB')
    #comment the above if you don't use images with opacity

    new_im = im.resize((1, 1))
    pixels = new_im.getpixel((0, 0))
    print pixels
    return pixels

Это очень-очень грубый способ.Я предположил, что изображение имеет квадратную форму.Затем, используя PIL, я просто изменяю его размер на 1 пиксель (1x1), затем я получаю RGB-цвет этого пикселя.

найти комплиментарный / контрастный цвет.
from colorsys import rgb_to_hls as rgb2hls
from colorsys import hls_to_rgb as hls2rgb

def contrast(rgb):
    h,l,s = rgb2hls(*rgb)
    new_l = 0 if l>=0.5 else 1
    new_rgb = hls2rgb(h, new_l,s)
    return new_rgb

Эта функция получает пиксель RGB, затем переводит его в HLS, затем устанавливает яркость на 0 или 1 (насколько это возможно от текущегозначение), затем переводит его обратно в RGB и возвращает это значение.Таким образом, мы получаем белый или черный цвет текста, в зависимости от того, какой из них более контрастен с текущим изображением.

Теперь давайте добавим эти алгоритмы в приложение kivy:

from __future__ import division

from kivy.app import App
from kivy.lang import Builder
from kivy.uix.image import Image
from kivy.core.window import Window

from PIL import Image as I

from colorsys import rgb_to_hls as rgb2hls
from colorsys import hls_to_rgb as hls2rgb


KV = """
FloatLayout
    MyImage
        id: image
        text_input:text_input
        #source: 'im.png'

    MyTextInput
        id: text_input

<MyTextInput@TextInput>
    font_size: 40
    background_normal : ''
    background_active: ''
    background_color: 0,0,0,0
    text: 'this is some text. Drag and drop an image here. '*20
"""



def average_color(image_fn):
    im = I.open(image_fn)
    im = im.convert('RGB')
    #comment the above if you don't use images with opacity

    new_im = im.resize((1, 1))
    pixels = new_im.getpixel((0, 0))
    print pixels
    return pixels




def contrast(rgb):
    h,l,s = rgb2hls(*rgb)
    new_l = 0 if l>=0.5 else 1
    new_rgb = hls2rgb(h, new_l,s)
    return new_rgb


class MyImage(Image):
    def on_source(self, inst, fn): 
        aver = [i/255 for i in average_color(fn)]
        contrast_rgba = [i for i in contrast(aver)]+[1]
        self.text_input.foreground_color = contrast_rgba


class MyApp(App):
    def build(self):
        self.root = Builder.load_string(KV)
        Window.bind(on_dropfile=self.manage_dropfile)

    def is_image(self, fn):
        if fn[-4:] in ['.png', '.jpg', 'jpeg']: return True
        return False

    def manage_dropfile(self, window, fn):
        fn = fn.decode('UTF-8')
        if self.is_image(fn):
            self.root.ids.image.source = fn

MyApp().run()

Самое важноеявляется то, что мы создали класс MyImage, в котором в методе on_source () (при каждом изменении источника изображения) мы получаем среднее значение цвета, затем контрастный цвет и, наконец, мы меняем foreground_color.

Также я реализовалдрагдроп изображений.Вы можете удалить любой файл изображения jpg / png из какой-либо папки на вашем компьютере, и текст автоматически изменит свой цвет на черный или белый.enter image description here

1 голос
/ 14 мая 2019

Не уверен, как изменить цвет текста, как вы описываете. Вы имеете в виду, что вы хотите, чтобы цвет текста изменялся в зависимости от того, что стоит за ним? Например, верхняя часть E может быть белой, а нижняя часть того же E может быть черной?

Но я думаю, что вы можете добавить свойство структуры к TextInput, подклассифицировав его:

from kivy.core.text import Label
from kivy.properties import NumericProperty, ListProperty
from kivy.uix.textinput import TextInput

class TextInputOutline(TextInput):
    outline_width = NumericProperty(0)
    outline_color = ListProperty((0,0,0))

    def _get_line_options(self):
        # Get or create line options, to be used for Label creation
        if self._line_options is None:
            self._line_options = kw = {
                'font_size': self.font_size,
                'font_name': self.font_name,
                'anchor_x': 'left',
                'anchor_y': 'top',
                'padding_x': 0,
                'padding_y': 0,
                'padding': (0, 0),
                'outline_width': self.outline_width,
                'outline_color': self.outline_color}
            self._label_cached = Label(**kw)
        return self._line_options

Приведенный выше метод _get_line_options заменяет тот же метод в TextInput. Единственная разница - это включение outline свойств. С помощью этого TextInputOutline вы можете указать толщину и цвет контура, например:

TextInputOutline:
    text: 'This is a Test'
    foreground_color: (1, 1, 1, 1)
    outline_color: (0, 0, 0)
    outline_width: 1

Обратите внимание, что этот метод переопределяет метод, начинающийся с _, поэтому нет гарантии, что он все равно будет работать, если TextInput изменится в будущем обновлении Kivy.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...