ENRGY

[Статья] Как конвертировать растровую картинку в векторный TPath Firemonkey. How to convert a bitmap image (png, jpeg, bmp) into a Firemonkey vector TPath.

11 сообщений в этой теме

Как конвертировать растровую картинку в векторный TPath Firemonkey.
How to convert a bitmap image (png, jpeg, bmp) into a Firemonkey vector TPath. Manual.


Плюсы векторных изображений: 

  • Можно изменять размер избражения в любую сторону, уменьшать и увеличивать, без потери качества. Картинка всегда будет с четкими краями, без размытия по краям и квадратиков.
  • Можно легко изменять в RunTime цвет заливки и обводной рамки, изменяя цвета в полях Fill и Stroke компонента TPath. Заливка как правило одна - это цвет из свойства Fill Color. Но ... цвет может быть и градиентом из множества цветов, который можно указать в диспетчере объектов, там же можно загрузить и Bitmap как текстуру в качестве заливки. 
  • Можно анимировать изображение, изменяя вышеуказанные свойства, а также направление градиента, размер, толщину обводной линии итд.

Тоже можно менять и для Stroke свойства - обводной рамки.

Минусы:
Получаемое изображение упрощенное. Т.к. оно может содержать только один путь (Path) и одну плоскость.
Возможно получиться скомбинировать множества TPath, положив их друг на друга с прозрачностью. 
Векторное изображение вычисляется и рисуется "в живую", поэтому потребуется больше ресурсов, чем при отрисовке обычных растровых картинок png, jpg, bitmap.
Что означает нагрузку на аппаратную часть, замедление работы программы и более быструю разрядку мобильного устройства.
Поэтому если и использовать подобные векторные изображения, то в случае если нужно отобразить большие картинки-символы на разных экранах (не иконки) - например на маленьком экране телефона, и на большом планшете и на еще большем Desktop экране. 
Хотя в примере \Samples\Object Pascal\Multi-Device Samples\User Interface\CustomListBox\CustomListBox.dproj используется векторная иконка\чекбокс очень простая. 

 

Преимущества векторного изображения наглядно:

vectorImagevsBitmap.png

 

Ингредиенты: 

1. Векторный редактор, я взял бесплатный inkscape, который можно скачать здесь
2. Картинка. Желательно чтобы картинка была с большим разрешением, от 300px и больше. Если взять изображение маленького размера, например 48x48 или 64x64, то контуры получатся не такими точными. И хотя inkscape все равно применит сглаживание контуров, и квадратиков вы не увидите, обводные линии могут получиться другой формы, к примеру более жирными или могут слиться с другими линиями.
Исходное изображение лучше брать в формате PNG, т.к. JPEG оставляет артефакты в виде точек, в итоге программа при трассировке может захватить и их, что не желательно. Конечно же если другого исходника нету, то смысла конвертировать jpg в png нет - качество не улучшится.

Основной метод конвертации - это трассировка изображения, - когда алгоритм ищет края и обводные линии, и на основе их рисует свои. Потому качественные результаты получаться если брать изображение с одной плоскостью, без теней, градиентов и деталей, в стиле Windows 8\10 или Android. Т.н. Flat (плоский) icon. 

3. IDE RAD Studio Delphi или С++


Приступим. 

Запускаем incscape. 

Размер исходной png картинки 668x720.
broadcastsource.png

1. Меню File > Open - указываем путь. Иконка загрузилась.

2. Нажимаем левой кнопкой мыши на картинку, чтобы она выделилась.

3. Меню Path > Trace Bitmap. Сразу выберите чекбокс Live Preview (см скриншот).
Здесь есть разные методы, но нам нужна секция Single Scan: Creates a Path. Методы нужно подбирать визуально, "на глаз". 
Можно также использовать и секцию Multiply Scans, а затем скомбинировать пути в один (Path > Combine), т.к. нам нужен один путь, и один набор. Путь (Path) это набор инструкций о том как и сколько рисовать линий-векторов. Для нашего конкретного случая, этой конкретной иконки, оптимальный вариант Color Quantization и количество цветов = 2.

Color qantization2.png

 

4. Нажимаем OK и закрываем окно. Появилось наше изображение залитое черным цветом - это и есть наша векторная картинка. 
Стоит заметить что прямо под ним лежит наше исходного изображение. Чтобы его удалить нужно отодвинуть мышкой векторное изображение, выделить исходную картинку и удалить ее клавишей Delete.  

5. Вы можете отредактировать пути, выбрав в левой панели инструмент Edit Paths By nodes (F2) или добавить фильтры\эффекты в меню Path > Path Effects. В данном примере я ничего не менял.

6. File Save As > inkscape SVG .

7. Открываем полученный SVG файл в блокноте или в Lister тотал коммандера. Ищем массив чисел, который обычно начинается со строчки "<path". Находим эту строчку, нам нужно набор символов, который идет после буквы "d=", к примеру d="m 397.33334,c -48.1 ...-0.326 -1.64129,-0.66405 z" и копируем все, что внутри кавычек в буфер.
8. Далее в RAD IDE кидаем на форму TPath. В Object Inspector WrapMode устанавливаем в Fit, и в поле Data вставляем из буфера наш код.
9. Меняем Fill и Stroke цвета на нужные нам значения (здесь я установил желтый цвет и увеличил толщину обводки (Stroke)). 

form3.png

 

Еще пару примеров. 
Дерево - параметры Brightness Cutoff, Threshold 0.370 . Как видите здесь оптимальнее подходит метод Brightness Cutoff.  Здесь исходная png картинка - это дерево черного цвета, я ее распознал, и затем добавил в TPath, а в свойстве Fill указал градиент от черного до зеленого.
Наушники - Edge Detection 0. Конечно конкретно в этом случае нужно подчищать изображение.

tree and headphones.png

 


Иногда бывает что при вставке пути в TPath, компонент его отображает некорректно, если снова зайти в DATA TPath, то окажется что часть данных потеряна. 
Что исправить эту ситуацию, нужно путь упростить. Это значит что после шага 4, нужно выбрать в incscrape меню Path > Simplify, затем снова сохранить файл. 
Правда Simplify в incscrape работает не очень хорошо, часто загругляет прямые участки. Лучше делать Simplify в Adobe Illustrator.

 

Статья опубликована на сайте fire-monkey.ru и возможно будет изменяться и дополняться.

Автор: ENRGY  

24. 02. 17 

 

Изменено пользователем ENRGY
Alexander, Rusland, Kitty и 3 другим понравилось это

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Думаю будет полезно многим.Сам делал так же недавно в одном проекте,лучше этого метода тоже ничего не придумал.Да и svg оказался довольно годным форматом,который легко поддается манипуляциям.

Вот так у меня выглядит:

1.jpg

Равиль Зарипов (ZuBy) и dnekrasov понравилось это

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Замечательная статья! Отдельное спасибо за Inkscape, искал нечто подобное, но его пропустил.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Добрый день!

Коллеги, хочу озвучить одну из причин, из-за которой может возникать ситуация " Иногда бывает что при вставке пути в TPath, компонент его отображает некорректно"

Дело в том, что существуют сокращения в представлении данных и не все из низ TPath понимает, вот с чем столкнулся:

Есть команда 'c' - рисование кривой. не буду вдаваться в подробности, можно найти в интернете описание, скажу только то, что данная команда содержит 6 чисел. В идеале должно быть:

сX1 X2 X3 X4 X5 X6

Но очень часто (например в иконках Material Design) можно встретить:

c-1.1 0-1.99.9-1.99 2

И на этой строчке парсер TPath падает с ошибкой, так как пытается сконвертировать '-1.99.9' в число, что не верно. В реальности данная запись соответствует двум числам -1.99 и 0.9.

 

Для обхода проблемы я загружаю SVG в рантайме, и сроку пропускаю через корректор:

function CorrectSVG(const Value: String): String;
var
  SB : TStringBuilder;
  I: Integer;
  C : Char;
begin
  SB := TStringBuilder.Create;
  try
    I := 0;
    for C in Value do
    begin
      if C='.' then
        Inc(I) else
        if not CharInSet(C, ['0'..'9']) then
          I := 0;
      if I=2 then
      begin
        SB.Append(' 0.');
        I := 0;
      end else
        SB.Append(C);
    end;
    Result := SB.ToString;
  finally
    FreeAndNil(SB);
  end;
end;

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Кривяков Виталий

 

Спасибо за важную инфу.

Я надеюсь корректор вы запускаете только когда это необходимо - только когда видите визуально что TPath не справился в Design Time или, в случае если загружаете TPath в Runtime, - когда он отвалился с определенным исключением.  Иначе это пустая растрата ресурсов на и так слабеньких моб. процах\аккумуляторах.

Изменено пользователем ENRGY

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Я отказался пока от SVG, так как рассматривал его как вариант для отображения картинок кнопок - некрасиво, на маленьких размерах PNG выигрывает в качестве. Поэтому не заморачивался с тем когда вызывать код. Более правильно было бы сделать заплатку для FMX, но там такая реализация (через одно место), что только переносить исходники в проект, а это не дело.

Для примера скриншот изображения 24х24 для Windows и Android
 

Win_SVG_PNG.PNG

Android_SVG_PNG.PNG

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Попробовал поработать с TPath. К сожалению он некорректно обрабатывает (точнее не обрабатывает) квадратичные кривые Безье. Ошибка как в Berlin'е так и в Tokyo:

procedure TPathData.SetPathString(const Value: string);
......
          'Q', 'q':
            begin
              GetPointFromString(PathString, Pos);
              GetPointFromString(PathString, Pos);
            end;
.....

Вроде как должно быть:

 procedure TPathData.SetPathString(const Value: string);
......
         'Q', 'q':
            begin
              QuadCurveTo(GetPointFromString(PathString, Pos), GetPointFromString(PathString, Pos));
            end;

 

Задумался: Отправлять Bugreport или нет?

Евгений Корепов и Rusland понравилось это

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
8 часов назад, Rusland сказал:

Надо было написать и как исправить )

Не думаю. Я еще не настолько хорошо знаю FMX возможно есть еще места где  не хватает вызовов QuardCurveTo. Кроме того как я заметил не хватает функции QuadCurveToRel. 

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Создайте аккаунт или войдите для комментирования

Вы должны быть пользователем, чтобы оставить комментарий

Создать аккаунт

Зарегистрируйтесь для получения аккаунта. Это просто!


Зарегистрировать аккаунт

Войти

Уже зарегистрированы? Войдите здесь.


Войти сейчас

  • Похожие публикации

    • Автор: Макс Войтенко
      я знаю что можно добавить внешний файл в программу по пути (assets\internal)(скриншот) (раньше получали к нему доступ через)
      loadfromfille(GetDocumentsPath()+"test.txt")
      Сейчас GetDocumentsPath убрали из RadStudio и походу заменили чем то.
      я использовал в свой программе директорию 
      loadfromfille(GetHomePath()+"test.txt"), но я не знаю куда мне добавить программу через deploymant (скриншот)
      Тоесть
      1)GetDocumentsPath = (assets\internal) 
      2)GetHomePath= ??????
      3)GetDocumentsPath убрали из radstudio.
      Какую мне прописать директорию чтоб я имел к ней доступ через GetHomePath()??

    • Автор: sviat9440
      Привет. Как можно рисовать TPath? Зайдя в его свойства я вижу это:

    • Автор: Teodor
      Добрый день,
       
      В приложении динамически создается html страница (К примеру)
      const   html_doc = '<html>'+                      '<head>'+                      '</head>'+                      '<body>'+                     <div style="background-image:url(%image_url%)">HELLO WORLD!</div>                     '</body>'+                     '</html>'; Далее средствами StringReplace метка %image_url% подменяется на локальный путь к png файл,
      так вот собственно вопрос, где должен быть задеплоин этот png файл, и какой должен быть путь URL к локальной картинке? Сейчас деплоинг в "Assets\Internal\image.png"
      А путь: TPath.GetDocumentPath + PathDelim + 'image.png' <-- Картинка не грузится..
       
      Заранее благодарю за ответ!
       
    • Автор: brunnengi
      Здравствуйте.
      Подскажите пожалуйста, а есть ли механизм для реализации аминирования отрисовки TPath?
      Т.е. как нарисовать хотя бы линию слева направо с анимацией?
  • Сейчас на странице   0 пользователей

    Нет пользователей, просматривающих эту страницу