GDI+: графика нового поколения
От: Виталий Брусенцев www.airbandits.com/
Дата: 02.10.02 19:15
Оценка: 165 (9)
Статья:
GDI+: графика нового поколения
Автор(ы): Виталий Брусенцев
В статье рассмотрена работа с растрами средствами GDI+ — новой библиотеки от Microsoft. Описываются методы создания растров из внешних источников, их взаимодействие с устройствами вывода и работа с графическими файлами.


Авторы:
Виталий Брусенцев

Аннотация:
В статье рассмотрена работа с растрами средствами GDI+ — новой библиотеки от Microsoft. Описываются методы создания растров из внешних источников, их взаимодействие с устройствами вывода и работа с графическими файлами.
Успехов,
Виталий.
Прямой доступ к данным - 2
От: AP999 http://www.elecard.net.ru/graphics/
Дата: 07.03.03 03:47
Оценка:
Продолжая тему, хочу поделиться своими наблюдениями.
Если создать Bitmap конструктором:
Bitmap(const BITMAPINFO* gdiBitmapInfo, VOID* gdiBitmapData);
внутреннего буфера в bitmap-e, видимо, не создается и изменения, произведенные, "вручную" в данных gdiBitmapData, отражаются на bitmap-объекте и наооборот. Еще одна фича, которая мне понравилась — это создать объект Graphics на основе bitmap-а. Тогда можно рисовать прямо на буффере gdiBitmapData методами Graphics.

Алексей.
Прямой доступ к данным
От: AP999 http://www.elecard.net.ru/graphics/
Дата: 18.01.03 09:07
Оценка:
Привет. Отличная статья.
По поводу Bitmap::GetHBITMAP() — если я правильно понял описание в SDK, то этот метод создает HBITMAP — копию изображения, содержащегося в объекте Bitmap. В этом случае изменение данных в HBITMAP не отобразится на Bitmap. Похоже в любом случае для быстрой работы (модификации) данных придется с использовать копию, создаваемую LockBits, а потом заливать ее обратно в Bitmap с помощью UnlockBits. Есть ли еще способы быстрого доступа к растровым данным?
Ой, нагнал!
От: Igor Trofimov  
Дата: 03.10.02 19:17
Оценка:
Пардон! Что-то я как-то неподробно прочитал... Упоминается ImageAttributes, хоть и кратенько.
Маловато будет!
От: Igor Trofimov  
Дата: 03.10.02 19:15
Оценка:
Статья обошла стороной очень интересные возможности GDI+ в области работы с картинками, связанные с использванием класса ImageAttributes при отрисовке растра.

Этот класс позволяет проделывать много презабавных штук с картинками, в частности — задавать при отрисовке линейное преобразование каждого пиксела в пространстве ARGB. Есть и другие полезные возможности.
Да, создается копия
От: retalik www.airbandits.com/
Дата: 20.01.03 05:40
Оценка:
Спасибо за отзыв.
Действительно, метод GetHBITMAP создаст _копию_ растровых данных, но содержащуюся именно в DIB Section, как и было сказано в статье. Правда, это поведение так и не было документировано.

Если же требуется быстрый доступ к битам растра на запись, то можно попробовать пойти от противного: держать растр изначально в "сыром" формате DIB Section, а для получения GDI+ Bitmap создавать его, например, при помощи FromHBITMAP. При этом способ вполне законный и налицо экономия одного копирования.
Успехов,
Виталий.
Re: Ой, нагнал!
От: retalik www.airbandits.com/
Дата: 08.10.02 10:08
Оценка:
Всего же и не охватишь. И так статья здоровущая получилась, в 2.5 раза больше первой части.
А вообще, комментарии приветствуются :)
Успехов,
Виталий.
Re: Да, создается копия
От: dad  
Дата: 19.02.04 07:00
Оценка:
R>Спасибо за отзыв.

Отлично создаются форматы gip, png, только вот немеренных объемов ( до 2М) при развмере
600х400 , как я ни бился сжимать не удается, атрибуты качества есть только у jpeg , но они както игнорируются.
Что посоветуешь для сжатия выходных картинок?
Веру-ю-у! В авиацию, в научную революци-ю-у, в механизацию сельского хозяйства, в космос и невесомость! Веру-ю-у! Ибо это объективно-о! (Шукшин)
Re[2]: Да, создается копия
От: Andrew Simontsev Россия  
Дата: 20.02.04 06:10
Оценка:
Здравствуйте, dad, Вы писали:

R>>Спасибо за отзыв.


dad>Отлично создаются форматы gip, png, только вот немеренных объемов ( до 2М) при развмере

dad>600х400 , как я ни бился сжимать не удается, атрибуты качества есть только у jpeg , но они както игнорируются.
dad>Что посоветуешь для сжатия выходных картинок?

TIFF c LZW недостаточно сжимает?
Sincerely yours,
Andrew Simontsev.
Re: Да, создается копия
От: Andrew Simontsev Россия  
Дата: 20.02.04 06:11
Оценка:
Здравствуйте, AP999, Вы писали:

AP>Продолжая тему, хочу поделиться своими наблюдениями.

AP>Если создать Bitmap конструктором:
AP>Bitmap(const BITMAPINFO* gdiBitmapInfo, VOID* gdiBitmapData);
AP>внутреннего буфера в bitmap-e, видимо, не создается и изменения, произведенные, "вручную" в данных gdiBitmapData, отражаются на bitmap-объекте и наооборот. Еще одна фича, которая мне понравилась — это создать объект Graphics на основе bitmap-а. Тогда можно рисовать прямо на буффере gdiBitmapData методами Graphics.

Увы, на палитровых битмапах рисовать нельзя...
Sincerely yours,
Andrew Simontsev.
Re[2]: Да, создается копия
От: retalik www.airbandits.com/
Дата: 20.02.04 06:30
Оценка:
Здравствуйте, dad, Вы писали:

dad>Отлично создаются форматы gip, png, только вот немеренных объемов ( до 2М) при развмере

dad>600х400 , как я ни бился сжимать не удается, атрибуты качества есть только у jpeg , но они както игнорируются.
dad>Что посоветуешь для сжатия выходных картинок?

Странно — у меня скриншот экрана в формате PNG занимает около 50 килобайт при формате 1024х768.
Вот код (можно скачать отсюда
Автор(ы): Виталий Брусенцев
Дата: 31.10.2002
Класс, призванный упростить инициализацию/очистку GDI+ для программистов графики на C++. Реализация также дает возможность корректно обрабатывать ситуацию отсутствия этой библиотеки.
):
#define STRICT
#include <windows.h>
#include <GdiPlus.h>
#include "InitGdiPlus.h"

static const GUID guidPng = 
{ 0x557cf406, 0x1a04, 0x11d3, { 0x9a, 0x73, 0x00, 0x00, 0xf8, 0x1e, 0xf3, 0x2e } };

static const GUID guidBmp = 
{ 0x557cf400, 0x1a04, 0x11d3, { 0x9a, 0x73, 0x00, 0x00, 0xf8, 0x1e, 0xf3, 0x2e } };

int CALLBACK WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, 
                     LPSTR lpCmdLine, int nShowCmd )
{
  HDC hdc = ::GetDC(NULL);
  RECT rc={0, 0, GetSystemMetrics(SM_CXFULLSCREEN),
    GetSystemMetrics(SM_CYFULLSCREEN)};
  HDC hdcMem = CreateCompatibleDC(hdc);

  HBITMAP hBitmap = CreateCompatibleBitmap(hdc, (int)rc.right,
    (int)rc.bottom);
  HBITMAP hOldBmp = (HBITMAP)SelectObject(hdcMem, hBitmap);
  BitBlt(hdcMem, 0, 0, (int)rc.right, (int)rc.bottom, hdc,
    0, 0, SRCCOPY);
  hBitmap =(HBITMAP) SelectObject(hdcMem, hOldBmp);
  DeleteDC(hdcMem);
  RSDN::InitGdiPlus init;
  if(init.Good())
  {
    Gdiplus::Bitmap bitmap(hBitmap, NULL);
    bitmap.Save(L"c:\\screen.png", &guidPng);
    bitmap.Save(L"c:\\screen.bmp", &guidBmp);
  }
  else
    MessageBox(0, "Ошибка инициализации GDI+", 0, MB_OK|MB_ICONHAND);
  DeleteObject(hBitmap);
  return 0;
}
... silent
Успехов,
Виталий.
Re[3]: Да, создается копия
От: dad  
Дата: 20.02.04 07:36
Оценка:
dad>>Отлично создаются форматы gip, png, только вот немеренных объемов ( до 2М) при развмере
dad>>600х400 , как я ни бился сжимать не удается, атрибуты качества есть только у jpeg , но они както игнорируются.
dad>>Что посоветуешь для сжатия выходных картинок?

R>Странно — у меня скриншот экрана в формате PNG занимает около 50 килобайт при формате 1024х768.

R>Вот код (можно скачать отсюда
Автор(ы): Виталий Брусенцев
Дата: 31.10.2002
Класс, призванный упростить инициализацию/очистку GDI+ для программистов графики на C++. Реализация также дает возможность корректно обрабатывать ситуацию отсутствия этой библиотеки.
):


вот мой код (я рисую в памяти в битмап b_):
CLSID img_cls;
if ( get_encoder_clsid(L"image/png", &img_cls) == -1 )//там из самплов процедура
    throw gtl_exception(L"clis id for img n't finded");

std::auto_ptr< Gdiplus::Bitmap > b( new Gdiplus::Bitmap( v_->get_screen_width(), v_->get_screen_height()) );

std::auto_ptr< Gdiplus::Graphics > g( new Gdiplus::Graphics( b.get() ) );

if ( true)
{
         //вяские cashed этоу же потом добавлял, суть не в этом
    Gdiplus::CachedBitmap cb(b_.get(), g.get() );
    g->DrawCachedBitmap( &cb, 0,0 );
    g->Flush();
    //Gdiplus::EncoderParameters par; всякие оптимизации пробовал
    b->Save(fn.data(), &img_cls, 0);
}


причем картинку которая получалась мог смотреть только мозила
ни адоп ни ие ее не открывали..
но я уже переделал на cximage сохранение
Веру-ю-у! В авиацию, в научную революци-ю-у, в механизацию сельского хозяйства, в космос и невесомость! Веру-ю-у! Ибо это объективно-о! (Шукшин)
Re[3]: Да, создается копия
От: dad  
Дата: 20.02.04 07:39
Оценка:
dad>>Отлично создаются форматы gip, png, только вот немеренных объемов ( до 2М) при развмере
dad>>600х400 , как я ни бился сжимать не удается, атрибуты качества есть только у jpeg , но они както игнорируются.
dad>>Что посоветуешь для сжатия выходных картинок?

AS>TIFF c LZW недостаточно сжимает?


мне нужен был png & gif
Веру-ю-у! В авиацию, в научную революци-ю-у, в механизацию сельского хозяйства, в космос и невесомость! Веру-ю-у! Ибо это объективно-о! (Шукшин)
Re[3]: Да, создается копия
От: dad  
Дата: 21.02.04 11:47
Оценка:
dad>>Отлично создаются форматы gip, png, только вот немеренных объемов ( до 2М) при развмере
dad>>600х400 , как я ни бился сжимать не удается, атрибуты качества есть только у jpeg , но они както игнорируются.
dad>>Что посоветуешь для сжатия выходных картинок?

R>Странно — у меня скриншот экрана в формате PNG занимает около 50 килобайт при формате 1024х768.


У меня был баг, я в процедуре выбора кодека, написал
if( frm.compare( pImageCodecInfo[j].MimeType ) == 1 )
врезультате чего у меня всегда все сохранялось в едином формате,bmp
поэтому ие и шоп не понимал, только мозила умная

Но cximage все таки получше ужимает, да более явно у него все сделано в том числе и с доп. настройкой качества и весит не много (40-60К) к экзезешничку если статично.

Короче если бы знал, что сделаю с cximage от gdiplus, наверно, отказался бы теперь уже просто некогда либу переписывать под winapi
Спасибо что откликнулся.
Веру-ю-у! В авиацию, в научную революци-ю-у, в механизацию сельского хозяйства, в космос и невесомость! Веру-ю-у! Ибо это объективно-о! (Шукшин)
Re: GDI+: графика нового поколения
От: Аноним  
Дата: 10.02.05 15:29
Оценка:
Здравствуйте, Виталий Брусенцев, Вы писали:

ВБ>Статья:



ВБ>Авторы:

ВБ> Виталий Брусенцев

ВБ>Аннотация:

ВБ>В статье рассмотрена работа с растрами средствами GDI+ — новой библиотеки от Microsoft. Описываются методы создания растров из внешних источников, их взаимодействие с устройствами вывода и работа с графическими файлами.

Скажите, пожалуйста, а как создасть кисть GPBrush, реализующую текстурную заливку (элементом GPImage) с заданным значением полупрозрачности (альфа-канала для всех пикселей изображения), эта кисть затем применяется для всевозможных заливок!!!

Очень надо!
Re: GDI+: графика нового поколения
От: sgi1981  
Дата: 01.04.06 00:25
Оценка: -1 :))
Здравствуйте, Виталий Брусенцев, Вы писали:

ВБ>Статья:

ВБ>GDI+: графика нового поколения
Автор(ы): Виталий Брусенцев
В статье рассмотрена работа с растрами средствами GDI+ — новой библиотеки от Microsoft. Описываются методы создания растров из внешних источников, их взаимодействие с устройствами вывода и работа с графическими файлами.


ВБ>Авторы:

ВБ> Виталий Брусенцев

ВБ>Аннотация:



Хорошо.
Но я бы хотел знать вовсе не то какие существуют классы использующие библиотеку gdiplus.dll.
Мне нужно знать как непосредственно использовать подпрограммы из этой библиотеки.
Я понимаю, что классы разных там языков используют эти подпрограммы.
Но прочитав вашу статью я так и не понял как именно используются сами подпрограммы этой библиотеки.
Во первых — это интереснее, во вторых в голове сразу становится яснее понимание работы компьютера.
К сожалению, я не могу по другому лучше понять использование библиотек API.
ДА И НЕ ХОЧУ В ПРИНЦИПЕ. ВОТ.
Где я могу узнать об использовании подпрограмм библиотеки gdiplus32.dll чтобы мне меньше всего начисляло по трафику?
Ну очень хочется узнать как использовать сами подпрограммы.

Представьте себе, если программа составляется на АССЕМБЛЕРЕ, где нет этих классов.
Там нужно записывать в стек определенные параметры инструкциями процессора например
push eax

и затем вызывать нужную подпрограмму библиотеки инструкцией, например
call GdipBitmapSetPixel


Вот так например я могу на АСМе вызвать функцию SetDIBitsToDevice
библиотеки gdi32.dll

push DIB_RGB_COLORS;
push dword ptr bi;
push dword ptr p;
push dword ptr NumScans;
push dword ptr StartScan;
push dword ptr SrcY1;
push dword ptr SrcX1;
push dword ptr 24;
push dword ptr Width1;
push dword ptr DestY1;
push dword ptr DestX1;
push dword ptr D;
call SetDIBitsToDevice;


Я считаю, что такой путь использования функций графических библиотек понятнее.
Я серьезно говорю. Пусть на меня никто не обидится. Так мы же четко понимаем то что происходит в компьютере. А прочитав использование классов я ничего толком не понимаю.
Подобным вышеприведенным методом можно вызывать все 609 функций библиотеки gdiplus.dll.
Даже если возникает необходимость узнать адрес конкретной функции, это можно сделать имея адреса всего двух API-функций
LoadLibrary — находит библиотеку в памяти или загружает ее и возвр. описатель её в регистре eax ЦП
GetProcAddress — возвращает адрес нужной функции в в регистре eax ЦП.
Затем загнать в четырехбайтную ячейку памяти (например переменная addr) этот адрес и вызвать инструкцию
call addr


А ещё меня просто сводит с ума расширения арифметико-логического устройства процессора SSE и SSE2.
Там такие инструкции...! За одну инструкцию можно выполнить сразу четыре арифметические операции.

Кстати, вот можете скопировать в буфер обмена мое творение на встроенном ассемблере C++ Builder.
Тут используются инструкции SSE2. Я добился ими ускорения вычисления массива изображения в 8 раз по сравнению с обычними командами процессора.
Есть одно несовершенство — разрезание динамически меняющегося изображения.
Но я думаю что эта проблема будет решена.

#include <vcl.h>
#pragma hdrstop

#include "Unit1effectSetDIBitsToDevice.h"
#include "math.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
unsigned int masim[4000000];
tagBITMAPINFO* bi= new tagBITMAPINFO;
void* p;
int i;
int pr;
unsigned int  DestX1, DestY1, Width1, Height1, SrcX1, SrcY1, StartScan, NumScans,
  X1,X2,Y1,Y2;
HDC D;
HINSTANCE HDLL;
FARPROC Addrf1;
unsigned int mas1ht[4];
unsigned int mas2Yj[4];
unsigned int mas3i[4];
unsigned int mas4_4[4];
unsigned int mas5m[4];
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
        : TForm(Owner)
{

}
//---------------------------------------------------------------------------

void __fastcall TForm1::FormClick(TObject *Sender)
{
//int i,fy,j,k;
//SetDIBitsToDevice(D,DestX1,DestY1,Width1,Height1,SrcX1,SrcY1,StartScan,NumScans,p,bi,0);
}
//---------------------------------------------------------------------------

void __fastcall TForm1::FormCreate(TObject *Sender)
{
bi->bmiHeader.biSize=sizeof(bi->bmiHeader);
bi->bmiHeader.biWidth=1024;
bi->bmiHeader.biHeight=768;
bi->bmiHeader.biPlanes=1;
bi->bmiHeader.biCompression=0;
bi->bmiHeader.biBitCount=32;
bi->bmiHeader.biSizeImage=1024*768*4;
DestX1=0;
DestY1=0;
Width1=1024;
Height1=768;
SrcX1=0;
SrcY1=0;
StartScan=0;
NumScans=1024;
p=masim;
D=CreateDC("DISPLAY",0,0,0);
HDLL=LoadLibrary("gdi32.dll");
Addrf1=GetProcAddress(HDLL,"SetDIBitsToDevice");
Form1->Hide();
mas4_4[0]=4;
mas4_4[1]=4;
mas4_4[2]=4;
mas4_4[3]=4;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::FormMouseMove(TObject *Sender, TShiftState Shift,
      int X, int Y)
{
unsigned int x,y,i,j,c,r,Yj;
/*c=0;
for (j=768;j>0;j--)
for (i=0;i<1024;i++)
{r=(X-i)*(X-i)+(Y-j)*(Y-j);
masim[c]=r*256;
c++;}*/
SrcY1=0;
DestY1=0;
asm{
mov esi,X;
mov edi,Y;
mov ecx,0;
mov j,768;
@c2:cmp j,0;
jz @2;
mov i,0;
mov eax,edi;
sub eax,j;
imul eax;
mov Yj,eax;
@c1:cmp i,1024;
jz @3;
mov eax,esi;
sub eax,i;
imul eax;
add eax,Yj;
shl eax,8;
mov masim+ecx*4,eax;
inc ecx;
inc i;
jmp @c1;
@3:dec j;
jmp @c2;
@2:
};
SetDIBitsToDevice(D,DestX1,DestY1,Width1,Height1,SrcX1,SrcY1,StartScan,NumScans,p,bi,0);
}
//---------------------------------------------------------------------------
void __fastcall TForm1::FormMouseUp(TObject *Sender, TMouseButton Button,
      TShiftState Shift, int X, int Y)
{
unsigned int x,y,i,j,c,r,ht,ht1,c1,Yj,b1,ecx1;
unsigned int v1000=6;
tagPOINT tp1;
ht=0;
asm
{
mov c1,0;
@c3:cmp c1,5000;//???????
jz @1;
}
GetCursorPos(&tp1);
asm{
mov esi,dword ptr tp1;
mov edi,dword ptr tp1+4;
inc ht;
mov eax,ht;
mul eax;
imul v1000;
mov ht1,eax;
mov mas1ht,eax;//??? XMM
mov mas1ht+4,eax;
mov mas1ht+8,eax;
mov mas1ht+12,eax;
mov mas5m,esi;
mov mas5m+4,esi;
mov mas5m+8,esi;
mov mas5m+12,esi;
mov ecx,0;
mov j,768;
mov b1,0;
mov SrcY1,0;
mov DestY1,744;
//XMM
movdqu xmm7,dqword ptr mas1ht;
movdqu xmm4,dqword ptr mas5m;
movdqu xmm3,dqword ptr mas4_4;
@c2:cmp b1,24;
jz @22;
cmp j,0;
jz @2;
mov i,0;
mov eax,edi;
sub eax,j;
imul eax;
mov Yj,eax;
mov mas2Yj,eax;//??? XMM
mov mas2Yj+4,eax;
mov mas2Yj+8,eax;
mov mas2Yj+12,eax;
mov mas3i,0;
mov mas3i+4,1;
mov mas3i+8,2;
mov mas3i+12,3;
//XMM
movdqu xmm6,dqword ptr mas2Yj;
movdqu xmm5,dqword ptr mas3i;
@c1:cmp i,256;//1024;
jz @3;
/*mov eax,esi;
sub eax,i;
imul eax;
add eax,Yj;
sub eax,ht1;
shl eax,8;
mov masim+ecx*4,eax;
inc ecx;*/
movdqa xmm0,xmm4;
psubd xmm0,xmm5;
pmaddwd xmm0,xmm0;
paddd xmm0, xmm6;
psubd xmm0,xmm7;
pslld xmm0,8;
movdqa dqword ptr masim+ecx,xmm0;
add ecx,16;
paddd xmm5,xmm3;
inc i;
jmp @c1;
@3:dec j;
inc b1;
jmp @c2;
@22:mov b1,0;
push DIB_RGB_COLORS;
push dword ptr bi;
push dword ptr p;
push dword ptr NumScans;
push dword ptr StartScan;
push dword ptr SrcY1;
push dword ptr SrcX1;
push dword ptr 24;
push dword ptr Width1;
push dword ptr DestY1;
push dword ptr DestX1;
push dword ptr D;
call SetDIBitsToDevice;

mov ecx,0;
sub DestY1,24;
jmp @c2;
@2:inc c1;
jmp @c3;
@1:
};
/*for (c1=0;c1<100;c1++){ht++;c=0;
for (j=768;j>0;j--)
for (i=0;i<1024;i++)
{r=abs(X-i)*abs(X-i)+abs(Y-j)*abs(Y-j)-ht*ht*1000;
masim[c]=r*256;
c++;}
SetDIBitsToDevice(D,DestX1,DestY1,Width1,Height1,SrcX1,SrcY1,StartScan,NumScans,p,bi,0);
}*/
}
Везде и всегда должна быть физическая реальность и должен быть здравый смысл
Re[2]: GDI+: графика нового поколения
От: algol Россия about:blank
Дата: 04.04.06 11:09
Оценка:
Здравствуйте, sgi1981, Вы писали:

S>Но я бы хотел знать вовсе не то какие существуют классы использующие библиотеку gdiplus.dll.

S>Мне нужно знать как непосредственно использовать подпрограммы из этой библиотеки.
S>Я понимаю, что классы разных там языков используют эти подпрограммы.
S>Но прочитав вашу статью я так и не понял как именно используются сами подпрограммы этой библиотеки.

В SDK есть такой файл — GdiPlusFlat.h. Там объявлены все функции API. Можете использовать их напрямую без "классов разных там языков".
Re[3]: GDI+: графика нового поколения
От: sgi1981  
Дата: 04.04.06 18:42
Оценка:
Здравствуйте, algol, Вы писали:

A>В SDK есть такой файл — GdiPlusFlat.h. Там объявлены все функции API. Можете использовать их напрямую без "классов разных там языков".


ВОт. Теперь первая часть проблемы отпала. Остается только узнать для чего каждый параметр предназначен, а то предназначение не описано в gdiplusflat.h
Везде и всегда должна быть физическая реальность и должен быть здравый смысл
Re: Аппаратное ускорение
От: dimaZ13 Россия  
Дата: 06.04.06 06:22
Оценка:
А кто нибудь слышал, что в GF 7900, 7600 есть "полная аппаратная поддержка всех функция GDI+".
Я вот такое в обзоре этих карточек на IXBT увидел.
И вопрос: Все GDI+ радости на этих картах будут очень быстро рисоваться или я
что-то не так понимаю?
И если это так, то кто-нибудь пробовал?
Re: GDI+: графика нового поколения
От: Аноним  
Дата: 06.04.06 18:40
Оценка:
Возник вопрос по использованию GDI+
Вот код:

bool TModule::LoadBitmap(AnsiString FileName,Graphics::TBitmap *&pBitmap)
{
 Gdiplus::Bitmap *tImage=Gdiplus::Bitmap::FromFile(WideString(FileName));
 pBitmap=new Graphics::TBitmap();
 Gdiplus::Color tBackGround;
 HBITMAP handle;
 tImage->GetHBITMAP(tBackGround,&handle);
 tImage->GetRawFormat(&Main);
 pBitmap->Handle=handle;
 delete tImage; 
 return true;
};
bool TModule::SaveBitmap(AnsiString FileName,::Graphics::TBitmap *pBitmap)
{
 Gdiplus::Bitmap *tImage=Gdiplus::Bitmap::FromHBITMAP(pBitmap->Handle,pBitmap->Palette);
 Gdiplus::Status tRes=tImage->Save(WideString(FileName).c_bstr(),&Main);
 delete tImage;
 return true;
};


Проблема в том, что при любом FileName функция SaveBitmap выдаёт результат (tRes) равный FileNotFound.
Неважно, корректное или нет имя файла.
В чём проблема?
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.