Перейти к содержанию
Fire Monkey от А до Я

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


Рекомендуемые сообщения

Как конвертировать растровую картинку в векторный 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
Ссылка на комментарий

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

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

1.jpg

Ссылка на комментарий

Добрый день!

Коллеги, хочу озвучить одну из причин, из-за которой может возникать ситуация " Иногда бывает что при вставке пути в 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

Ссылка на комментарий
  • 1 месяц спустя...

Попробовал поработать с 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 или нет?

Ссылка на комментарий
8 часов назад, Rusland сказал:

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

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

Ссылка на комментарий

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...