Форум программистов, компьютерный форум, киберфорум
Delphi: Графика, звук, видео
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.80/25: Рейтинг темы: голосов - 25, средняя оценка - 4.80
0 / 0 / 0
Регистрация: 02.09.2013
Сообщений: 29

Direct2D, TDirectCanvas и все-все-все

02.09.2013, 16:37. Показов 4711. Ответов 6
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Дня доброго.
Я тут новенький.
С Дельфи профессионально не работаю, моя стезя - 1С 8.2.

В 1с есть проблема - картинки, при выводе которых на экран/принтер через графическую систему 1С - идет отжор памяти без ее освобождения.

Немного об GDI от 1С: окна Windows ей нужны только для масштабирования окон (но не элементов) а также для отлова событий от ОС (WM_CLOSE, и.т.д.). Вся отрисовка - своя, основана на перехвате WM_PAINT

Запилил addins через отдельную dll, в которой формочка (окно), отдельное от графической системы 1С (1С не перехватывает его WM_PAINT). На формочке - TImage. Все нормально, супергуд.

10 метровые фотки летают...
Но хочется большего.
По умолчанию - GDI не поддерживает TIFF (а это важно, часто сканы в 1С - это сканы сопроводиловки - Ч/Б печать).

Впилил GDI+. Но даже по ощущениям увидел, что медленней стало.
Замерил - примерно в 5 раз медленнее таже конвертация из bmp в jpeg идет. Бида.

Узнал про поддержку Direct2D в Win7, начал экспериментировать.
Увидел, что она действительно работает - например масштабирование рисунка через TDirect2DCanvas.RenderTarget выполняется раза в 2.5 быстрее, чем через GDI (реализацию приведу чуть позже) и при это загружен GPU видюхи на 17-20 процентов. Профит.

Но вот как потом получить трансформированное изображение с TDirect2DCanvas - не могу осилить.
0
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
02.09.2013, 16:37
Ответы с готовыми решениями:

все символы
Выдайте на экран все символы загруженной кодовой таблицы, по порядку их номеров, помещая по 60 символов в строке(в первой строке-символы с...

Свернуть все процедуры
Есть ли команда чтобы свернуть все процедуры, что бы они были по одной строке. Delphi 2007.

Все про то же: печать
Два вопроса. 1. Есть форма. На ней 15memo и 10 edit. Как вывести на печать содержимое мемов и едитов? 2. Можно ли вывести...

6
angstrom
02.09.2013, 16:41
Странно, GDI+ не может быть медленнее по-определению чем GDI.
0 / 0 / 0
Регистрация: 02.09.2013
Сообщений: 29
02.09.2013, 23:27  [ТС]
И, это. Есть какой-нибудь наследник от TImage, который рисует на TDirectCanvas, а то я начал его писать и не хватает мозгов допилить.

Добавлено через 6 часов 40 минут
Вот этот кусок кода:

Delphi
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
procedure Tform2.Scale1();
var
Status:Hresult;
ImagingFactory:IWICImagingFactory;
DirectCanvas:TDirect2DCanvas;
DirectBitmap:ID2D1Bitmap;
RenderTarget: ID2D1RenderTarget;
size : TD2DSizeF;
WicImage : TWicImage;
FormatConverter : IWICFormatConverter;
Scale:TD2D1Matrix3x2F;
D2DSizeF:D2D1_SIZE_F;
D2DPointF:D2D_POINT_2F;
begin
try
DirectCanvas := TDirect2DCanvas.Create(Canvas.Handle,ClientRect); //Связываем Direct 2D canvas с canvas формы
RenderTarget:= DirectCanvas.RenderTarget as ID2D1RenderTarget; //Получаем контекст построителя изображения
WicImage := TWicImage.Create(); //Создаем объект-обертку над WIC -апи  [url]http://msdn.microsoft.com/en-us/library/windows/desktop/ee719673%28v=vs.85%29.aspx[/url]
ImagingFactory := WicImage.ImagingFactory;  //Контекст фабрики для создания объектов для преобразования изображений
WicImage.LoadFromFile(pchar('c:\in.jpg'));  //Загружаем файл, скорее всего во внутренний IStream
Status:=ImagingFactory.CreateFormatConverter(FormatConverter); //Создаем конвертер из фабрики
if not Succeeded(Status) then raise Exception.Create('');
Status:=FormatConverter.Initialize(WicImage.Handle, GUID_WICPixelFormat32bppPBGRA,WICBitmapDitherTypeNone,nil,0,WICBitmapPaletteTypeCustom); //инициализируем конвертер потоком с изображением, при этом он и сделает то, что требуется.
//То есть, конвертация происходит при инициации, а не при выполении отдельного метода, к примеру Convert(). fuck my mint! см. _http://msdn.microsoft.com/en-us/library/windows/desktop/ee690274%28v=vs.85%29.aspx
if not Succeeded(Status) then raise Exception.Create('');
Status:=RenderTarget.CreateBitmapFromWicBitmap(FormatConverter,nil,DirectBitmap); //Создаем bitmap, годный для операций с Direct2D, типа ID2D1Bitmap. Это уже голый Direct2D, до этого был WIC. еще понятный. см. _http://msdn.microsoft.com/en-us/library/windows/desktop/dd742779%28v=vs.85%29.aspx
if not Succeeded(Status) then raise Exception.Create('');
 
RenderTarget.BeginDraw(); //Начинаем рисовать
RenderTarget.Clear(D2D1ColorF(clRed)); //Очищаем красным, чтобы было видно
DirectBitmap.GetSize(Size); //Получаем размер изображения, потом пригодится. пока не используется.
ZeroMemory(@Scale,16);
RenderTarget.GetSize(Size); //получаем размер холста, он равен размеру ClientRect формы
D2DSizeF.width:=2;
D2DSizeF.height:=2; //Увеличиваем рисунок в 2 раза по длине и ширине.
D2DPointF.x:=Round(Size.width/2);
D2DPointF.y:=Round(Size.height/2);
Scale:=TD2DMatrix3x2F.Scale(D2DSizeF,D2DPointF); //Создаем матрицу пространственного преобразования
RenderTarget.SetTransform(Scale); //Преобразовываем Direct2D холст, по аналогии с SetWorldTransform() для HDC
if assigned(DirectBitmap) then RenderTarget.DrawBitmap(DirectBitmap); // Рисуем картинку. Все норм, на форме она есть. Ура.
//Как ее теперь вытащить из формы? Опять получать через HDC и CopyBitmap() ? Чето не то...
RenderTarget.EndDraw();
finally
RenderTarget:=nil;
DirectCanvas.Free;
ImagingFactory:=nil;
WicImage.Free;
end;
 
end;
0
0 / 0 / 0
Регистрация: 02.09.2013
Сообщений: 29
08.10.2013, 12:31  [ТС]
Вернемся к старым песням.
С конвертацией изображений разобрался, все быстро и четко.
Особенно понравился новый формат HD-Photo (JPEG-XR) на основе вейвлет сжатия. На малом качестве он творит чудеса, вытягивая картинку.

Но мы движемся дальше.
Теперь моя цель - создать свой компонент на основе TImage который будет отрисовывать Direct2D графику. Вот первые наброски:

Delphi
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
unit Direct2DImages;
 
interface
 
uses Windows,SysUtils,Classes,messages,Controls,Forms,ExtCtrls,Direct2d,WinCodec,d2d1,Graphics,ActiveX;
 
type
  TDirect2DImage= class(TImage)
  private
    fOldWidth:integer;
    fOldHeight:integer;
    fDirectBitmap:IWICFormatConverter;
    procedure SetDirectImage(ImageData:TMemoryStream);
    procedure DirectPaint();
  protected
    procedure Paint;override;
    procedure WMResize(var MSG:TWMSize);message WM_SIZE;
  public
    constructor Create(AOwner:TComponent);override;
    Property DirectImage:TMemoryStream write SetDirectImage;
  published
    { Published declarations }
  end;
 
procedure Register;
 
implementation
 
procedure Register;
begin
  RegisterComponents('Samples',[TDirect2DImage]);
end;
 
function _GetErrorMsg(ecode:DWORD):string;
var
  Buf: array [0..1024] of char;
begin
  SetString(result,Buf,FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM,nil,ecode,0,@Buf,sizeOf(Buf),nil));
  result:=StringReplace(result,#13#10,'',[rfReplaceAll]);
end;
{ TDirect2DImage }
 
constructor TDirect2DImage.Create(AOwner:TComponent);
begin
  inherited Create(AOwner);
  fOldWidth:=0;
  fOldHeight:=0;
end;
 
procedure TDirect2DImage.DirectPaint;
var
  Status:Hresult;
  ImagingFactory:IWICImagingFactory;
  DirectCanvas:TDirect2DCanvas;
  DirectBitmap:ID2D1Bitmap;
  RenderTarget:ID2D1RenderTarget;
  BitmapSize,RenderSize:TD2DSizeF;
  Scale:TD2D1Matrix3x2F;
  D2DSizeF:D2D1_SIZE_F;
  D2DPointF:D2D_POINT_2F;
  ImageRect,OwnerRect:TRect;
  ScaleX,ScaleY:real;
begin
  if fDirectBitmap=nil then
    exit;
  try
    ImageRect:=(self as TImage).ClientRect;
    OwnerRect:=(self.Owner as TForm).ClientRect;
    ImageRect.Left:=ImageRect.Left+(self as TImage).Left;
    ImageRect.Right:=ImageRect.Right+(self as TImage).Left;
    ImageRect.Top:=ImageRect.Top+(self as TImage).Top;
    ImageRect.Bottom:=ImageRect.Bottom+(self as TImage).Top;
    DirectCanvas:=TDirect2DCanvas.Create((self.Owner as TForm).Canvas.Handle,ImageRect); // Связываем Direct 2D canvas с canvas формы
    RenderTarget:=DirectCanvas.RenderTarget as ID2D1RenderTarget;
    Status:=RenderTarget.CreateBitmapFromWicBitmap(fDirectBitmap,nil,DirectBitmap); // Создаем bitmap, годный для операций с Direct2D, типа ID2D1Bitmap. Это уже голый Direct2D, до этого был WIC. еще понятный. см. [url]http://msdn.microsoft.com/en-us/library/windows/desktop/dd742779%28v=vs.85%29.aspx[/url]
    if not Succeeded(Status) then
      raise Exception.Create('Не удалось создать контекст изображения D2D про причине:"'+_GetErrorMsg(ResultCode(Status))+'"');
    RenderTarget.BeginDraw(); // Начинаем рисовать
    RenderTarget.Clear(D2D1ColorF(clRed)); // Очищаем красным, чтобы было видно
    DirectBitmap.GetSize(BitmapSize); // Получаем размер изображения
    ZeroMemory(@Scale,16);
    RenderTarget.GetSize(RenderSize); // получаем размер холста
    ScaleX:=RenderSize.Width/BitmapSize.Width;
    ScaleY:=RenderSize.height/BitmapSize.height;
    D2DSizeF.Width:=ScaleX;
    D2DSizeF.height:=ScaleY; // Увеличиваем рисунок до холста, потом будет с сохранением пропорций
    D2DPointF.x:=0;
    D2DPointF.y:=0;
    Scale:=TD2DMatrix3x2F.Scale(D2DSizeF,D2DPointF); // Создаем матрицу пространственного преобразования
    RenderTarget.SetTransform(Scale); // Преобразовываем Direct2D холст, по аналогии с SetWorldTransform() для HDC
    // Мне дико непонятно, какой режим масштабирования - тупо "ближайший сосед", "Билинейная" или годная "Бикубическая". Есть мысли?
    if assigned(DirectBitmap) then
      RenderTarget.DrawBitmap(DirectBitmap); // Рисуем картинку. Все норм, на форме она есть. Ура.
    RenderTarget.EndDraw(); // Фиксируем
  finally
    RenderTarget:=nil;
    DirectCanvas.Free;
    ImagingFactory:=nil;
  end;
end;
 
procedure TDirect2DImage.Paint; // Что то изменилось, размеры, лиюо форма перекрыта другой.
begin
  // if ((Self.Owner as TForm).Width<>fOldWidth) or ((Self.Owner as TForm).Height<>fOldHeight) then
  if ((self as TImage).Width<>fOldWidth)or((self as TImage).height<>fOldHeight) then begin
    fOldWidth:=(self as TImage).Width;
    fOldHeight:=(self as TImage).height;
    DirectPaint();
  end;
end;
 
// Загружаем изобрадение из потока в Конвертер, выполняется 1 раз, при этом происходит масштабирование до размера экрана
procedure TDirect2DImage.SetDirectImage(ImageData:TMemoryStream);
  function Max(const A,B:Extended):Extended;
  begin
    if A>B then
      result:=A
    else
      result:=B;
  end;
 
var
  ImagingFactory:IWICImagingFactory;
  WicImage:TWicImage;
  BitmapScaler:IWICBitmapScaler;
  HDC:THandle;
  ScreenWidth:integer;
  ScreenHeight:integer;
  CoefWidth:real;
  CoefHeight:real;
  TotalCoef:real;
  Status:Hresult;
begin
  if ImageData=nil then
    exit; // Нуавдруг
  HDC:=GetDC((self.Owner as TForm).Handle);
  ScreenWidth:=GetDeviceCaps(HDC,HORZRES);
  ScreenHeight:=GetDeviceCaps(HDC,VERTRES);
  WicImage:=TWicImage.Create(); // Обертка Дельфи над IWicBitmap. Воспользуемся.
  ImagingFactory:=WicImage.ImagingFactory;
  ImageData.Seek(0,0); // На начало, мало ли.
  WicImage.LoadFromStream(ImageData); // Загрузим из потока
  CoefWidth:=WicImage.Width/ScreenWidth;
  CoefHeight:=WicImage.height/ScreenHeight;
  TotalCoef:=Max(CoefWidth,CoefHeight);
  TotalCoef:=Max(1,TotalCoef); // Нам надо отмасштабировать под размер экрана, сохранив пропорции
  Status:=ImagingFactory.CreateBitmapScaler(BitmapScaler); // Создадим масштабировщик
  if not Succeeded(Status) then
    raise Exception.Create('');
  // Инициируем масштабирование, бикубичесое.
  Status:=BitmapScaler.Initialize(WicImage.Handle,Round(WicImage.Width/TotalCoef),Round(WicImage.height/TotalCoef),WICBitmapInterpolationModeCubic);
  if not Succeeded(Status) then
    raise Exception.Create('');
  Status:=ImagingFactory.CreateFormatConverter(fDirectBitmap); // Создаем конвертер из фабрики
  if not Succeeded(Status) then
    raise Exception.Create('');
  // Render не принимает на отрисовку BitmapScaler, а BitmapConverter - Норм, дадим ему его.
  Status:=fDirectBitmap.Initialize(BitmapScaler,GUID_WICPixelFormat32bppPBGRA,WICBitmapDitherTypeNone,nil,0,WICBitmapPaletteTypeCustom); // инициализируем конвертер потоком с изображением, при этом он и сделает то, что требуется.
  BitmapScaler:=nil;
  ImagingFactory:=nil;
  WicImage.Free;
end;
 
procedure TDirect2DImage.WMResize(var MSG:TWMSize);
begin
end;
 
end.
Добавлено через 10 минут
Чего пока нет:
1) Годной обработки ошибок.
2) Поддержки старого GDI (2-х режимности, ну это нетрудно).

Есть много вопросов:

1) Как перехватить ресайз TImage. Именно ресайс. При отлове Paint - этих сообщений дико много, по каждому чиху (движение формы, например) - и отрисовка кадрируется. Даже после предварительного масштабирования до размера экрана. Смотрел как сделано в типовой Дельфи - вроде все также, однако не тормозит. Ниасилил.
2) Изображение можно масштабировать 2 методами - через WIC (Интерфейс IWICBitmapScaler) и непосредственно при rendere через SetWorldTransform(). В первом случае можно задать режим масштабирования (бикубический, билинейный, ближайший), однако я не уверен, что там (в WIC) используется Direct2D (обработка через GPU). Во втором случае точно используется GPU (мерил через MSI Afterburner), однако не понятно, как указать режим масштабирования. Есть мысли?

Добавлено через 18 часов 14 минут
Мертвовато что-то. Где все спецы?
0
Заблокирован
08.10.2013, 20:32
Hadgehogs
Да скачайте модуль TIFF и GDI будет его поддерживать.
Или поставьте KOL. Там есть очень хороший модуль этого формата.

Добавлено через 5 минут
Hadgehogs,
И вообще, бросьте этот Direct2D
Это просто преждевременный выкидыш. Как, например, Виста.
Он сырой, нет полноценной обещанной аппаратной поддержки. Привязка к определённой системе.
И вообще муть...
0
0 / 0 / 0
Регистрация: 02.09.2013
Сообщений: 29
08.10.2013, 21:36  [ТС]
Этот сырой Direct2D выигрывает в 1.5-2 раза в сравнении с GDI. А если tiff - тогда там GDI+, а там по скорости еще печальнее.

Он сырой, нет полноценной обещанной аппаратной поддержки. Привязка к определённой системе.

Спасибо, посмеялся. Ну да, привязка к WinAPI (ну или ее продолжателю в виде набора интерфейсов, не суть). А некоторые еще и под Яндекс.API пишут - вот это я понимаю, экстремалы.
0
Заблокирован
11.10.2013, 09:00
Hadgehogs,
У него привязка к 7 и 8-ке А у людей до сих пор ХP и более древние системы. Можете ржать сколько хотите, но выигрыш в 2 раза - смешон. Если был бы на порядок...
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
11.10.2013, 09:00
Помогаю со студенческими работами здесь

Все картинки на странице
Всем привет. Есть ли способ получить все адреса картинок на веб странице? Абсолютно всех.

Опишите все функции в Delphi7
Напишите пожалуйста функции которые есть в Delphi7.

Как перебрать все CheckBox'
добрый день, подскажите...Как перебрать все условия ??? Это для 2) а как сделать для 8 CheckBox??? Спасибо)

Удалить из строки все звездочки
Дана строка символов удалить из строки все звездочки

Сложить все нечетные числа от 1 до 15.
Помогите решить!!! 1. Сложить все нечетные числа от 1 до 15. 2. Создать приложение, использующее три формы. На каждой форме в центре...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
7
Ответ Создать тему
Новые блоги и статьи
Новый ноутбук
volvo 07.12.2025
Всем привет. По скидке в "черную пятницу" взял себе новый ноутбук Lenovo ThinkBook 16 G7 на Амазоне: Ryzen 5 7533HS 64 Gb DDR5 1Tb NVMe 16" Full HD Display Win11 Pro
Музыка, написанная Искусственным Интеллектом
volvo 04.12.2025
Всем привет. Некоторое время назад меня заинтересовало, что уже умеет ИИ в плане написания музыки для песен, и, собственно, исполнения этих самых песен. Стихов у нас много, уже вышли 4 книги, еще 3. . .
От async/await к виртуальным потокам в Python
IndentationError 23.11.2025
Армин Ронахер поставил под сомнение async/ await. Создатель Flask заявляет: цветные функции - провал, виртуальные потоки - решение. Не threading-динозавры, а новое поколение лёгких потоков. Откат?. . .
Поиск "дружественных имён" СОМ портов
Argus19 22.11.2025
Поиск "дружественных имён" СОМ портов На странице: https:/ / norseev. ru/ 2018/ 01/ 04/ comportlist_windows/ нашёл схожую тему. Там приведён код на С++, который показывает только имена СОМ портов, типа,. . .
Сколько Государство потратило денег на меня, обеспечивая инсулином.
Programma_Boinc 20.11.2025
Сколько Государство потратило денег на меня, обеспечивая инсулином. Вот решила сделать интересный приблизительный подсчет, сколько государство потратило на меня денег на покупку инсулинов. . . .
Ломающие изменения в C#.NStar Alpha
Etyuhibosecyu 20.11.2025
Уже можно не только тестировать, но и пользоваться C#. NStar - писать оконные приложения, содержащие надписи, кнопки, текстовые поля и даже изображения, например, моя игра "Три в ряд" написана на этом. . .
Мысли в слух
kumehtar 18.11.2025
Кстати, совсем недавно имел разговор на тему медитаций с людьми. И обнаружил, что они вообще не понимают что такое медитация и зачем она нужна. Самые базовые вещи. Для них это - когда просто люди. . .
Создание Single Page Application на фреймах
krapotkin 16.11.2025
Статья исключительно для начинающих. Подходы оригинальностью не блещут. В век Веб все очень привыкли к дизайну Single-Page-Application . Быстренько разберем подход "на фреймах". Мы делаем одну. . .
Фото: Daniel Greenwood
kumehtar 13.11.2025
Расскажи мне о Мире, бродяга
kumehtar 12.11.2025
— Расскажи мне о Мире, бродяга, Ты же видел моря и метели. Как сменялись короны и стяги, Как эпохи стрелою летели. - Этот мир — это крылья и горы, Снег и пламя, любовь и тревоги, И бескрайние. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2025, CyberForum.ru