Как ускорить прорисовку векторной графики ?

Вопросы программирования и использования среды Lazarus.

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

Ответить
Alex2013
долгожитель
Сообщения: 3247
Зарегистрирован: 03.04.2013 11:59:44

Сообщение Alex2013 »

zub писал(а):>>И что эмулировать на уровне канваса никак нельзя ? :roll: (Там же просто запись команд в формате WMF вместо реального рисования )
Тебе и карты в руки))
http://msdn.microsoft.com/en-us/library/cc250370.aspx
http://wvware.sourceforge.net/caolan/ora-wmf.html
http://www.symantec.com/avcenter/refere ... format.pdf

Мне в ближайшей перспективе пока не нужно ... о кто знает что дальше будет ... :idea:
Хотя я читал, что вроде уже есть готовая библиотека :arrow: http://wiki.lazarus.freepascal.org/fpvectorial
+ где-то что-то упрятано в TAChart.... (запись в WMF)
>>(Да и близко довольно к теме : мерцание нужно победить по возможности не теряя скорости )
Дак оно прекрасно побеждается без потерь производительности. Такими кусками кода ты общаешся сам с собой. Есть проблема - делаешь минимальную демку ее демонстрирующую

Мысль верная... но уж больно лениво . :oops: ... в прочем некоторые вещи действительно удобнее демкой показать ( больше шансов что кто-то повозится захочет ...)
zub
долгожитель
Сообщения: 2890
Зарегистрирован: 14.11.2005 22:51:26
Контактная информация:

Сообщение zub »

>>Хотя я читал, что вроде уже есть готовая библиотека :arrow: http://wiki.lazarus.freepascal.org/fpvectorial
С такимже успехом можно сказать что у тебя есть готовый векторный редактор. Забудь про вмф в линуксе.
Alex2013
долгожитель
Сообщения: 3247
Зарегистрирован: 03.04.2013 11:59:44

Сообщение Alex2013 »

zub писал(а):>>Хотя я читал, что вроде уже есть готовая библиотека :arrow: http://wiki.lazarus.freepascal.org/fpvectorial
С такимже успехом можно сказать что у тебя есть готовый векторный редактор. Забудь про вмф в линуксе.

Почти убедил ... :wink:
alexey38
долгожитель
Сообщения: 1627
Зарегистрирован: 27.04.2011 19:42:31

Сообщение alexey38 »

Alex2013 писал(а):Тормозов вроде не наблюдается


У нас основной способ был - это просто очистить битмап, и вывести в него метафайл штатными средствами. Это как раз работает довольно таки быстро, при разумном числе элементов.

Манипуляции с битмапом осуществлялись только в процессе рисования, когда мышкой тянем рамку, линию или иной элемент. Опять же не нужно бояться тупо делать вывод фоновой копии готового битмапа, все это работает быстро, т.к. объем битмапа ограничивается всего навсего мегабайтами. При наличии видеоускорителей эти операции ускорятся за счет реализации драйверов. То есть суть ускорения в том, чтобы внутри программы ничего не делать, а отдавать на откуп GDI вывод метафайла в битмап, и битмапа на форму, тогда аппаратное ускорение железа как раз и будет задействовано.
Linus
новенький
Сообщения: 47
Зарегистрирован: 11.01.2013 22:01:28

Сообщение Linus »

Дублирую сообщение
Имеется массив (некоторая область памяти), содержащая грубо говоря битовую матрицу. Как загрузить это / отобразить минуя

Код: Выделить всё

FileWrite (F, bmp[0], sizeof(...); ...LoadFromFile(....);\0


или банальная переформулировка вопроса:
Как сказать (компоненту) что вот здесь лежит изображение, возьми и загрузи его.
zub
долгожитель
Сообщения: 2890
Зарегистрирован: 14.11.2005 22:51:26
Контактная информация:

Сообщение zub »

Linus
TBitmap наследует от TRasterImage много вариантов LoadОткудаНибудь
в частности

Код: Выделить всё

    procedure LoadFromBitmapHandles(ABitmap, AMask: HBitmap; ARect: PRect = nil);
    procedure LoadFromDevice(DC: HDC); virtual;
    procedure LoadFromStream(AStream: TStream); overload; override;
    procedure LoadFromStream(AStream: TStream; ASize: Cardinal); overload; virtual;
    procedure LoadFromMimeStream(AStream: TStream; const AMimeType: string); override;
    procedure LoadFromRawImage(const AIMage: TRawImage; ADataOwner: Boolean);
    procedure LoadFromIntfImage(IntfImage: TLazIntfImage);

Возможно подойдет LoadFromStream или LoadFromRawImage. В первом случае "массив (некоторая область памяти)" должен быть в потоке, во втором надо создать TRawImage над "массив (некоторая область памяти)" естественно всё должно быть в понятных лцлю форматах, а не как вам на душу придет.
Linus
новенький
Сообщения: 47
Зарегистрирован: 11.01.2013 22:01:28

Сообщение Linus »

zub писал(а):Linus
TBitmap наследует от TRasterImage много вариантов LoadОткудаНибудь
в частности

Код: Выделить всё

    procedure LoadFromBitmapHandles(ABitmap, AMask: HBitmap; ARect: PRect = nil);
    procedure LoadFromDevice(DC: HDC); virtual;
    procedure LoadFromStream(AStream: TStream); overload; override;
    procedure LoadFromStream(AStream: TStream; ASize: Cardinal); overload; virtual;
    procedure LoadFromMimeStream(AStream: TStream; const AMimeType: string); override;
    procedure LoadFromRawImage(const AIMage: TRawImage; ADataOwner: Boolean);
    procedure LoadFromIntfImage(IntfImage: TLazIntfImage);

Возможно подойдет LoadFromStream или LoadFromRawImage. В первом случае "массив (некоторая область памяти)" должен быть в потоке, во втором надо создать TRawImage над "массив (некоторая область памяти)" естественно всё должно быть в понятных лцлю форматах, а не как вам на душу придет.


Я вот тоже склонялся к таким вариантам.. но наводит сомнения фраза в задании. "Массив есть файл" и надо "Указать ему адрес откуда взять и все...". Как вы поняли задачка в устной форме, не конкретная, что называется сломай голову.
Вот подумываю не создать ли какой либо класс хотя бы от TPicture, добавив функцию загрузки из TByteArray;
Последний раз редактировалось Linus 15.11.2016 01:14:39, всего редактировалось 1 раз.
zub
долгожитель
Сообщения: 2890
Зарегистрирован: 14.11.2005 22:51:26
Контактная информация:

Сообщение zub »

Задача сводится к преобразованию того что есть - "Массив есть файл" в того что может быть понято LCLем - нужна конкретика
Насколько я понимаю внутренний формат TRawImage можно довольно гибко настроить, возможно получится обойтись и без преобразований

Добавлено спустя 2 минуты 5 секунд:
>> Как вы поняли задачка в устной форме, не конкретная, что называется сломай голову.
>> Вот подумываю не создать ли какой либо
В усной форме можно подумывать о чем угодно. Впринципе можно даже сказать что задача решена))

Добавлено спустя 3 минуты 18 секунд:
>>класс хотя бы от TPicture, добавив функцию загрузки из TByteArray;
я ничего не пробовал, но глядя на TRawImageDescription думаю что получится грузить почти любой простой формат
Linus
новенький
Сообщения: 47
Зарегистрирован: 11.01.2013 22:01:28

Сообщение Linus »

zub писал(а):Задача сводится к преобразованию того что есть - "Массив есть файл" в того что может быть понято LCLем - нужна конкретика
Насколько я понимаю внутренний формат TRawImage можно довольно гибко настроить, возможно получится обойтись и без преобразований


TRawImage вроде то что нужно, однако как в него загрузить готовенькое не особо ясно. Примеров в сети не очень много.

Код: Выделить всё

RI.Init;
  RI.Data:=@bmp[0];
  RI.DataSize:=size;
  RI.Mask:=nil;
  RI.DataSize:=0;
  RI.Palette:=nil;
  RI.PaletteSize:=0;

im.Picture.Bitmap.LoadFromRawImage(RI, true/false);


Вроде и не шлет на ** и результата нет..
zub
долгожитель
Сообщения: 2890
Зарегистрирован: 14.11.2005 22:51:26
Контактная информация:

Сообщение zub »

надо настроить RI.Description в соответствии с форматом?
RI.DataSize:=0;??

Добавлено спустя 3 минуты 8 секунд:
давай демку
Linus
новенький
Сообщения: 47
Зарегистрирован: 11.01.2013 22:01:28

Сообщение Linus »

zub писал(а):надо настроить RI.Description в соответствии с форматом?
RI.DataSize:=0;??

Добавлено спустя 3 минуты 8 секунд:
давай демку


Я думал обойдется без этого. Снова расщеплять на хеадер и дату) хотя.. хедер = биты 0 до 25 дата = 26..и далее
RI.DataSize:=0; да не заметил, должен был быть MaskSize)

Добавлено спустя 18 минут 24 секунды:
Спасибо Zub через TRaw действительно удобно

Код: Выделить всё

RIHeader.Init;
  RIHeader.Init_BPP24_B8G8R8_BIO_TTB(w,h);

  RI.Init;
  RI.Description:= RIHeader;
  RI.Data:=@bmp[26];
  RI.DataSize:=size-26;

  im.Picture.Bitmap.LoadFromRawImage(RI, false);  \0


Однако просьба была хедеры генерировать вручную а тут TRawImageDescription....
<думаю как завязать его на содержимом массива>
zub
долгожитель
Сообщения: 2890
Зарегистрирован: 14.11.2005 22:51:26
Контактная информация:

Сообщение zub »

RI.Init;
RI.Description.Init_BPP24_B8G8R8_BIO_TTB(w,h);
RI.Data:=@bmp[26];
RI.DataSize:=size-26;

im.Picture.Bitmap.LoadFromRawImage(RI, false); \0
Linus
новенький
Сообщения: 47
Зарегистрирован: 11.01.2013 22:01:28

Сообщение Linus »

zub писал(а):RI.Init;
RI.Description.Init_BPP24_B8G8R8_BIO_TTB(w,h);
RI.Data:=@bmp[26];
RI.DataSize:=size-26;

im.Picture.Bitmap.LoadFromRawImage(RI, false);


по сути то же самое)

Вот. Думаю такой ответ устроит.

Код: Выделить всё

var
  bmp:TByteArray; 
  size:Dword;
  w,h:word;
  RI:TRawImage;
Begin
....
CreadeBMPHeader(bmp, w,h, size);  //скрыл в процедуру создание заголовка файла
...
//делаем с пикселями что хотим
...
//сохраняем на диск (для отладки)
...
 FileWrite (F, bmp[0], size);
 FileClose (F);

//выводим
RI.Init;
  with RI.Description do
  begin
        Init;
        format:=ricfRGBA;
        Depth:=bmp[24];
        BitsPerPixel:=Depth;

        Width:=bmp[18];
        Height:=bmp[20];

        RedPrec  :=(Depth div 3);
        GreenPrec:=RedPrec;
        BluePrec :=RedPrec;

        RedShift:=RedPrec*2;
        GreenShift:=GreenPrec;
        BlueShift:=0;
  end;

  RI.Data:=@bmp[bmp[10]];
  RI.DataSize:=size-bmp[10];

  im.Picture.Bitmap.LoadFromRawImage(RI, false);
zub
долгожитель
Сообщения: 2890
Зарегистрирован: 14.11.2005 22:51:26
Контактная информация:

Сообщение zub »

вместо Init_BPP24_B8G8R8_BIO_TTB ручная настройка на основе bmp[0]..bmp[26] = десяток строк.
кстати, наверно можно сразу юзать

Код: Выделить всё

TBitmap
property RawImage: TRawImage read GetRawImage; // be carefull with this, modify only within a begin/endupdate

Но это никакой не прямой доступ в видеопамять, как предполагалось в первоначальной постановке
Alex2013
долгожитель
Сообщения: 3247
Зарегистрирован: 03.04.2013 11:59:44

Сообщение Alex2013 »

А почему так нельзя ?

Код: Выделить всё

 Procedure SaveRAW(FN:String;B:TBitmap);
var
   F:TFileStream;
begin
F:=TFileStream.Create(FN,fmCreate );
F.Write(b.RawImage.Data^,b.RawImage.DataSize);
F.Free;
end;

Проще ведь ! :idea:
Если размер картинки и прочие параметры не меняются то ИМХО проще не придумаешь .
Ответить