Отрисовка картинки Png c прозрачностью+текста

Общие вопросы программирования, алгоритмы и т.п.

Модератор: Модераторы

Отрисовка картинки Png c прозрачностью+текста

Сообщение RedCat » 17.04.2019 12:43:10

Всем доброго времени суток, у меня возникла такая проблема:
Вводные данные
Lazarus 2.0.0
ОС в данный момент Win7 но планируется кроссплатформенность
пишу компонент на котором отрисовывается и картинка png с альфаканалом и текст (методом textout) и вся проблема заключается в том что:
1 если рисовать без буфера прямо на канве компонента все рисуется как мне нужно, но жутко мерцает
Код: Выделить всё
Canvas.Brush.Style:=bsSolid;
canvas.fillrect(Canvas.ClipRect);
if Assigned(FBackPicture) then
Canvas.CopyRect(slidebackrect,FBackPicture.Bitmap.Canvas,rect);
Canvas.Pen.Color:=clBlack;
Canvas.Pen.Style:=psSolid;
Canvas.Brush.Style:=bsClear;
Canvas.TextOut(2,10,'Текст');

2 если рисовать с буфером но при pixelformat:=pf32bit png отрисовывается с прозрачностью а текст не рисуется вообще
рисую приблизительно так:
Код: Выделить всё
bufferbmp.Canvas.Brush.Style:=bsSolid;
bufferbmp.canvas.fillrect(Canvas.ClipRect);
if Assigned(FBackPicture) then
bufferbmp.Canvas.CopyRect(slidebackrect,FBackPicture.Bitmap.Canvas,rect);
bufferbmp.Canvas.Pen.Color:=clBlack;
bufferbmp.Canvas.Pen.Style:=psSolid;
bufferbmp.Canvas.Brush.Style:=bsClear;
bufferbmp.Canvas.TextOut(2,10,'Текст');
Canvas.CopyRect(slideBackrect,bufferbmp.Canvas,rect);

3 если рисовать с буфером но при pixelformat:=pf24bit все отрисовывается правильно, но без прозрачности
RedCat
незнакомец
 
Сообщения: 8
Зарегистрирован: 17.04.2019 12:15:03

Re: Отрисовка картинки Png c прозрачностью+текста

Сообщение Лекс Айрин » 17.04.2019 16:12:22

Конечно, у тебя не будет прозрачности. ВМР ее просто не поддерживает используй PNG в качестве буфера.
Аватара пользователя
Лекс Айрин
долгожитель
 
Сообщения: 5723
Зарегистрирован: 19.02.2013 16:54:51
Откуда: Волгоград

Re: Отрисовка картинки Png c прозрачностью+текста

Сообщение olegy123 » 17.04.2019 20:55:20

Нужно иметь функционал который знает о альфе слое, может рисовать на канве и знает шрифт.
таких есть три:
есть в коробке FPimage + TIntfFreeTypeDrawer + EasyLazFreeType

Код: Выделить всё
var
   Image: TLazIntfImage;
   lRawImage: TRawImage;
   FontCaption:TFreeTypeFont
   fontDrawer: TIntfFreeTypeDrawer;


  RawImage.Init;
  RawImage.Description.Init_BPP32_R8G8B8A8_BIO_TTB( width,height);
  RawImage.CreateData(True);
  Image := TLazIntfImage.Create(0,0);
  Image.SetRawImage(lRawImage);
  fontDrawer := TIntfFreeTypeDrawer.Create(AImage);
  fontDrawer.DrawTextRect("Текст", FontCaption, 1, 1, x_start, y_start, fpcolor , [ftaCenter]);




есть еще BGRABitmap http://wiki.freepascal.org/BGRABitmap

и третий AGG http://www.crossgl.com/aggpas/

можно добавить еще Cairo https://www.cairographics.org/ https://forum.lazarus.freepascal.org/in ... ic=25615.0
olegy123
энтузиаст
 
Сообщения: 1407
Зарегистрирован: 25.02.2016 12:10:20

Re: Отрисовка картинки Png c прозрачностью+текста

Сообщение Лекс Айрин » 17.04.2019 21:55:12

olegy123, а ещё можно использовать обычный канвас. Или даже невизуальный компонент в одном из стандартных модулей. Окстись, человеку нужно просто сохранить картинку, перерисовать, а потом просто перенести на место. А значит, все должно быть как можно проще.
Аватара пользователя
Лекс Айрин
долгожитель
 
Сообщения: 5723
Зарегистрирован: 19.02.2013 16:54:51
Откуда: Волгоград

Re: Отрисовка картинки Png c прозрачностью+текста

Сообщение RedCat » 18.04.2019 07:27:13

Лекс Айрин писал(а): а ещё можно использовать обычный канвас.
Можно но оно жутко мерцает поэтому и пришлось использовать буферную картинку
Лекс Айрин писал(а): Или даже невизуальный компонент в одном из стандартных модулей.
тоже не вариант так.как пишу свой компонент и это нужно для него
Лекс Айрин писал(а): Окстись, человеку нужно просто сохранить картинку, перерисовать, а потом просто перенести на место.
не совсем так, мне нужно отрисовать в буфере картинку с прозрачностью, поверх нее отрисовать текст с прозрачностью и вывести все это дело на канву моего компонента(естественно с прозрачностью)
olegy123 FPimage + TIntfFreeTypeDrawer + EasyLazFreeType, а можно подробнее проэ эту связку?
RedCat
незнакомец
 
Сообщения: 8
Зарегистрирован: 17.04.2019 12:15:03

Re: Отрисовка картинки Png c прозрачностью+текста

Сообщение Лекс Айрин » 18.04.2019 18:47:46

RedCat а кто говорит, что это видимый канвас? Вообще, мерцает если не успевает отрисоваться в уложенное время. Возможно, проще всего тупо увеличить шаг отрисовки. Плюс к этому, с чем связана необходимость рисовать текст прямо на канвасе?
Хотя лично у меня текст поверх картинки прекрасно пишется. Правда не в компоненте. Попробуй писать текст не поверх картинки, а в расположенной поверх нее метки с прозрачным фоном.
Плюс к этому, можно привести текст метода целиком или хотя бы указать какой это метод? Текст будет меняться или статичен? Если будет, то ассоциирован ли он с картинкой или нет? Есть подозрение, что это просто логическая ошибка при проектировании.
Аватара пользователя
Лекс Айрин
долгожитель
 
Сообщения: 5723
Зарегистрирован: 19.02.2013 16:54:51
Откуда: Волгоград

Re: Отрисовка картинки Png c прозрачностью+текста

Сообщение RedCat » 18.04.2019 20:58:23

Лекс Айрин Мне неважно где его рисовать, прямо на канвасе моего компонента или же сначала в буфере, главное чтоб не было белого прямоугольника и мерцания, компонента из себя представляет подобие помеси прогресс и трек бара, но с временными метками,(TRedCatTimeline будет обзываться компонента) т.е. текст меняется только один раз, в момент подгрузки медиафайла, постоянно перерисовывается ползунок и полоса прогресса, фон,полоса прогресса и ползунок это картинки, временные метки это текст и полоски, текст рисуется методом canvas.textout, полоски методом lineto(это абсолютно не принципиально просто не знаю других способов)
RedCat
незнакомец
 
Сообщения: 8
Зарегистрирован: 17.04.2019 12:15:03

Re: Отрисовка картинки Png c прозрачностью+текста

Сообщение olegy123 » 18.04.2019 22:47:31

Лекс Айрин писал(а): а ещё можно использовать обычный канвас.
там ключевое слово альфа..
Возможно нужно учитывать прозрачность..

RedCat писал(а): FPimage + TIntfFreeTypeDrawer + EasyLazFreeType, а можно подробнее проэ эту связку?

http://wiki.freepascal.org/Developing_w ... TLazCanvas
Код: Выделить всё
Image: TLazIntfImage;
RawImage: TRawImage;
font:TFreeTypeFont;
fontDrawer: TIntfFreeTypeDrawer;
canvas:TLazCanvas;

RawImage.Init;
RawImage.Description.Init_BPP32_R8G8B8A8_BIO_TTB(width,height);
RawImage.CreateData(True);
Image := TLazIntfImage.Create(0,0);
Image.SetRawImage(RawImage);

fontDrawer:= TIntfFreeTypeDrawer.Create(Image);
font := TFreeTypeFont.Create;
font.Name := 'FontAwesome.ttf';
font.SizeInPixels := ASize;
font.Hinted := true;
font.ClearType := true;
font.Quality := grqHighQuality;
font.SmallLinePadding := false;
   
fontDrawer.FillPixels(colTransparent);
fontDrawer.DrawText("текст", font, x, y , colBlack, [ftaRight, ftaBottom]);

canvas := TLazCanvas.Create(Image);
canvas.FillColor(colWhite,true);
canvas.Brush.FPColor:=colBlack;   

RawImage.Data -- тут данные картинки в формате BPP32_R8G8B8A8_BIO_TTB
это мне нужно чтобы загрузить сюда:
  glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0,  GL_RGBA, GL_UNSIGNED_BYTE, RawImage.Data);
ну и загрузка в битмап
b:TBitmap
b:=TBitmap.Create;
b.LoadFromIntfImage(Image);

очищение:
  RawImage.FreeData;
  FreeAndNil(Image);
  FreeAndNil(canvas);
  FreeAndNil(font);
  FreeAndNil(fontDrawer);


Добавлено спустя 6 минут 36 секунд:
Внимание !
TFPColor имеет формат 16бит на цвет R16B16B16A16

Добавлено спустя 9 минут 24 секунды:
есть еще эксперименты с Skia https://skia.org/
библиотека применяется в Google Chrome

Добавлено спустя 5 минут 9 секунд:
AGG лучше.. он более оптимизирован на скорость..
olegy123
энтузиаст
 
Сообщения: 1407
Зарегистрирован: 25.02.2016 12:10:20

Re: Отрисовка картинки Png c прозрачностью+текста

Сообщение Лекс Айрин » 19.04.2019 06:15:16

olegy123, альфа-канал имеет любой канвас. А чем сложнее компонент, тем медленней он работает.
RedCat, ну так и используй метки для текста.
Надо понять из-за чего возникает мерцание. Так как метод отрисовки на каркасе достаточно быстр, то значит где-то есть паразитная отрисовка. Ты молчишь как партизан в каком методе ты отрисовываешь картинку. Подозреваю, что в onpaint по таймеру. Кстати, рисовать прямоугольники отдельно линиями не самый лучший метод. Рисуй именно залитыми прямоугольниками, есть там подобные методы. Они более оптимизированы. Вчера только нашел свою заготовку для компонента в виде кругового трекбара и никакого мерцания при перерисовке нет.
Аватара пользователя
Лекс Айрин
долгожитель
 
Сообщения: 5723
Зарегистрирован: 19.02.2013 16:54:51
Откуда: Волгоград

Re: Отрисовка картинки Png c прозрачностью+текста

Сообщение RedCat » 19.04.2019 09:34:24

Лекс Айрин Да, отрисовка происходит в OnPaint, Но не по таймеру
Вот весь код отрисовки вот так мерцает, но с прозрачностью все в норме
Код: Выделить всё
Canvas.Brush.Style:=bsSolid;
canvas.fillrect(Canvas.ClipRect);
  if Assigned(FBackPicture) then
Canvas.CopyRect(slidebackrect,FBackPicture.Bitmap.Canvas,slidebackrect);
if Assigned(FFullPicture) then
Canvas.CopyRect(slidefullrect,FFullPicture.Bitmap.Canvas,slidefullrect);

Canvas.Pen.Color:=clBlack;

   Canvas.Pen.Style:=psSolid;
   Canvas.Brush.Style:=bsClear;
  Canvas.MoveTo(FThumbWidth div 2,FThumbRect.Bottom-1);
  Canvas.LineTo(FThumbWidth div 2,FThumbRect.Bottom+4);
  Canvas.MoveTo(ClientWidth-(FThumbWidth div 2),FThumbRect.Bottom-1);
  Canvas.LineTo(ClientWidth-(FThumbWidth div 2),FThumbRect.Bottom+4);
  LinesCount:=round(Fmax/1000) div 36;
  BigLinesCount:=LinesCount div 36;
   if LinesCount>0 then
     begin
   Linesinterval:=ClientWidth div LinesCount;
   BigLinesinterval:=ClientWidth div BigLinesCount;
   for iLinesC:=0 to LinesCount  do
   begin
  Canvas.MoveTo((Linesinterval*iLinesC)+(FThumbWidth div 2),FThumbRect.Bottom-1);
  Canvas.LineTo((Linesinterval*iLinesC)+(FThumbWidth div 2),FThumbRect.Bottom+2);
   end;
   for iBigLinesC:=0 to BigLinesCount-1  do
     begin
  Canvas.MoveTo((BigLinesinterval*iBigLinesC)+(FThumbWidth div 2),FThumbRect.Bottom-1);
  Canvas.LineTo((BigLinesinterval*iBigLinesC)+(FThumbWidth div 2),FThumbRect.Bottom+4);
     if BigLinesinterval*iBigLinesC > 0 then
  Canvas.TextOut((BigLinesinterval*iBigLinesC)-20,FThumbRect.Bottom+2,FormatDateTime('hh:nn:ss',((iLinesC*36)*1000)/MSecsPerDay));
     end;
     end;
  Canvas.TextOut(0,FThumbRect.Bottom+2,FormatDateTime('hh:nn:ss',tmin));
  Canvas.TextOut(ClientWidth-41,FThumbRect.Bottom+2,FormatDateTime('hh:nn:ss',tmax));

     if Assigned(FThumbPicture) then
  Canvas.Draw(FAbsPos,0,FThumbPicture.Bitmap);
     


если рисовать сначала в буфере(Tbitmap), а потом перерисовывать буфер на канву за один раз мерцания нет, но и нет прозрачности

olegy123 спасибо, только я одного не понял как получившийся результат отрисовать на канве самого компонента
RedCat
незнакомец
 
Сообщения: 8
Зарегистрирован: 17.04.2019 12:15:03

Re: Отрисовка картинки Png c прозрачностью+текста

Сообщение Лекс Айрин » 19.04.2019 10:22:42

RedCat, и не будет. У тебя идёт преобразование из png в bmp, в котором нет прозрачности. Сейчас не скажу сходу на каком уровне, кажется в tBitmap, есть именно png, с которым можно работать. Но нужно определить прозрачный цвет.

Добавлено спустя 4 минуты 3 секунды:
Ну или попробуй поискать в полях и методах канваса перенос именно с учётом прозрачности. Кажется такая возможность есть в fillRect.
Аватара пользователя
Лекс Айрин
долгожитель
 
Сообщения: 5723
Зарегистрирован: 19.02.2013 16:54:51
Откуда: Волгоград

Re: Отрисовка картинки Png c прозрачностью+текста

Сообщение RedCat » 19.04.2019 10:58:11

Лекс Айрин Или использовать в качестве буфера альтернативу Tbitmap с поддержкой альфа канала, подозреваю что нужно смотреть в сторону tRawImage(как и предлагал olegy123
RedCat
незнакомец
 
Сообщения: 8
Зарегистрирован: 17.04.2019 12:15:03

Re: Отрисовка картинки Png c прозрачностью+текста

Сообщение Лекс Айрин » 19.04.2019 11:18:53

RedCat, альтернативу ты всегда успеешь. Будет по ом мучительно больно, если потом обнаружишь способ проще и все придется переделывать. Я точно помню, что я накладывал текст на прозрачную картинку без использования допкомпонент. И прозрачность оставалась.
Аватара пользователя
Лекс Айрин
долгожитель
 
Сообщения: 5723
Зарегистрирован: 19.02.2013 16:54:51
Откуда: Волгоград

Re: Отрисовка картинки Png c прозрачностью+текста

Сообщение RedCat » 19.04.2019 11:46:52

Лекс Айрин я сколько не пытался, такого способа не нашел, вернее мне удалось сохранить прозрачность рисуя на прямую на канве, но стоит начать использовать буфер, прозрачность сразу пропадает, единственное чего удалось добиться это при использовании буфера с pixelfotmat:=pf32bit png отрисовывается правильно, а все что должно рисоваться на прозрачном фоне не рисуется вообще, предполагаю что прозрачная область не перерисовывается вообще, а при pf24bit нет прозрачности, что вполне логично, так как 24 бита по 8 бит на канал это 3 канала т.е. rgb, а вот почему tbitmap так себя ведёт при 32 битах не понимаю
RedCat
незнакомец
 
Сообщения: 8
Зарегистрирован: 17.04.2019 12:15:03

Re: Отрисовка картинки Png c прозрачностью+текста

Сообщение olegy123 » 19.04.2019 12:04:51

RedCat писал(а):только я одного не понял как получившийся результат отрисовать на канве самого компонента

http://wiki.freepascal.org/TCanvas

Код: Выделить всё
b:TBitmap;
b:=TBitmap.Create;
b.LoadFromIntfImage(Image);
Form1.Canvas.Draw(x, y, b);


Добавлено спустя 11 минут 19 секунд:
Весь фокус заключается в том что TWinControl так таковой Canvas не имеет. Имеет его потомок TGraphicControl, он создает свой Bitmap.

чтобы на TWinControl что то нарисовалось, вы должны в системе (Windows/Gnome/KDE/Wayland/MacOS) создать Bitmap(не исключено что он может быть в каждой системе разным, например VideoOverlay/GL/DirectX его может и не быть) и выгрузить в дисплейную память.

Lazarus должен упрощать все это.
olegy123
энтузиаст
 
Сообщения: 1407
Зарегистрирован: 25.02.2016 12:10:20

След.

Вернуться в Общее

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 2

Рейтинг@Mail.ru