Перейти к содержанию
  • 0
Камышев Александр

Сглаживание при рисовании в буфер bitmap

Вопросы

в разделе Антиалиасинг обсуждалось присвоение свойству Quality формы HighQuality и рисование на канве.

если рисовать сразу к примеру в PaintBox или на канву формы, то это работает.

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

 

по коду, буфер:

bmp_buf = new TBitmap();bmp_buf->Width = window_rect.Width();
bmp_buf->Height = window_rect.Height();

рисование:

TPathData *pd = new TPathData;

pd->MoveTo( Point( 100, 100 ) );
pd->LineTo( Point( 150, 100 ) );
pd->LineTo( Point( 100, 150 ) );

bmp_buf->Canvas->Stroke->Thickness = 5;
bmp_buf->Canvas->Stroke->Kind = TBrushKind::Solid;
bmp_buf->Canvas->Stroke->Dash = TStrokeDash::Solid;
bmp_buf->Canvas->Stroke->Color = (TAlphaColor)TAlphaColorRec::Black;

bmp_buf->Canvas->DrawPath( pd, 1 );

delete pd;

на OnPaint копирование буфера:

pbMap->Canvas->BeginScene();pbMap->Canvas->DrawBitmap( bmp_buf, bmp_rect, window_rect, 1, false );
pbMap->Canvas->EndScene();

в результате все быстро, без морганий, но антиалиасинга нет.

у канвы буфера bmp_buf есть свойство Quality: 
__property TCanvasQuality Quality = {read=FQuality, nodefault}; - только чтение

принимает значения:

enum class DECLSPEC_DENUM TCanvasQuality : unsigned int { ccSystemDefault, ccHighPerformance, ccHighQuality };

по умолчанию ccSystemDefault

 
вот как бы и вопрос, как создать буферный TBitmap с TCanvas, у которого Quality == ccHighQuality?
возможно есть другие варианты рисовать ломаные линии с антиалиасинг?

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


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

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

  • 0

В общем для битмапа нельзя установить качество.

Могу вам предложить только дежурный вариант. Открываете файл FMX.Graphics.pas и находите метод TBitmap.GetCanvas (ориентировочно 3621 строка):

function TBitmap.GetCanvas: TCanvas;
begin
  if FCanvas = nil then
  begin
    CopyToNewReference;
    FCanvas := CanvasClass.CreateFromBitmap(Self);
  end;
  Result := FCanvas;
end;

И там можете добавить вторым параметром в CreateFromBitmap качество:

function TBitmap.GetCanvas: TCanvas;
begin
  if FCanvas = nil then
  begin
    CopyToNewReference;
    FCanvas := CanvasClass.CreateFromBitmap(Self, TCanvasQuality.HighQuality);
  end;
  Result := FCanvas;
end;

Но имейте в виду, что это будет работать сразу для всех битмапов.

 

После добавить исправленный юнит в проект.

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


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

сори не написал, под андроид пишу приложение с графикой, канва FMX

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


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

Так, прежде, чем читать мое сообщение выше, есть еще другой легальный способ. Создать канву из битмапа:

MyCanvas := TCanvasManager.CreateFromBitmap(Bitmap, quality);

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

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


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

протестировал 3 варианта:

1. правка FMX.Graphics.pas как указано выше

2. пишу на с++, можно исправить файл FMX.Graphics.hpp

 заменить код 

__property TCanvasQuality Quality = {read=FQuality, nodefault};

на 

__property TCanvasQuality Quality = {read=FQuality, write=FQuality, nodefault};

после этого можно 

bmp_buf->Canvas->Quality = TCanvasQuality::HighQuality;

3. Создать новую канву как указано выше

TCanvas *MyCanvas = TCanvasManager::CreateFromBitmap( bmp_buf, TCanvasQuality::HighQuality );

во всех трех случаях свойство Quality под debug имеет значение HighQuality, проверял перед DrawPath:

bool b = MyCanvas->Quality == TCanvasQuality::HighQuality;

и во всех вариантах эффекта не было... :(

неспроста Quality для формы нужно ставить в design-time

что происходит при сборке, из-чего включается антиалиасинг?

.

Отредактировал Камышев Александр

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


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

искал информацию по теме, необязательно Quality для формы устанавливать в design-time, в FormCreate срабатывает 

Quality = TCanvasQuality::HighQuality;
RecreateCanvas();
Invalidate();

по нажатию кнопки этот код не дает эффекта

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


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

А решение для битмапа внутри стиля так и не существует?

http://fire-monkey.ru/topic/1047-smoothing-dlia-izobrazheniia-iz-stilia/

Отредактировал POV

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


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

А решение для битмапа внутри стиля так и не существует?

http://fire-monkey.ru/topic/1047-smoothing-dlia-izobrazheniia-iz-stilia/

для этого придумали Scale

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


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

для этого придумали Scale

 

 

 

 

Мммм, а подробнее? Что за scale и как он относится к качестве перемесштабированного растра?

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


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

 

для этого придумали Scale

 

 

 

 

Мммм, а подробнее? Что за scale и как он относится к качестве перемесштабированного растра?

 

напрямую относится, подробней тут

грузить картинку нужно самому в соответствии скейла или хотя бы подготовить

Отредактировал ZuBy

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


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

Вижу, понимаю.. Согласен, что это поможет. Хотя странно, что нет алгоритмов сглаживания.

Отредактировал POV

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


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

Сделать антиалиасинг пока не получилось, но... Изначально неправильная постановка задачи, не нужен буфер для рисования, это же не GDI. Прорисовка в PaintBox на OnPaint с заливанием фона, копированием слоя подложки и иконок, рисование ломаных линий и фигур, прозрачность, антиалиасинг и т.д. абсолютно не вызывает  проблем с ресурсами и морганием, все рисуется быстро и плавно.

Отредактировал Камышев Александр

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


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

Итак на Android и iOS нет сглаживания при отрисовке примитивов (линий, кругов, вектора).

Метод 1 (Native Draw, Delphi ONLY ) - лучший и простой. 

На Canvas PaintBox рисуем как обычно.

Если нужно нарисовать на Canvas Bitmap'a, а не на PaintBox, тогда нужно правильно подготовить Bitmap: 

if Scene <> nil then
  lScale := Scene.GetSceneScale
else
  lScale := 1;

// fBitmap.BitmapScale := lScale; //это только для DrawPath
fBitmap.SetSize(Ceil(Width * lScale), Ceil(Height * lScale) );

 

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

https://github.com/OneChen/FMXNativeDraw

Если нужно сохранить в Bitmap, то делаем PaintBox.MakeScreenshot (TControl.PaintTo) в результате получаем сглаженный Bitmap. Кстати вызвать PaintTo не получится в Paint и Afterpaint методах текущего контрола - будет циклический вызов Paint и в результате переполнение стэка, нужно делать это в AfterPaint формы или фрейма. 

Метод 2.

http://riversoftavg.com/blogs/index.php/2016/06/09/use-supersampling-for-offscreen-bitmaps-on-delphi-mobile/

Отредактировал ENERGY

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


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

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

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

Гость
Ответить на вопрос...

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

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

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

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

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


  • Последние посетители   0 пользователей онлайн

    Ни одного зарегистрированного пользователя не просматривает данную страницу

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