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.
Неважно, корректное или нет имя файла.
В чём проблема?
Re[2]: GDI+: графика нового поколения
От: algol Россия about:blank
Дата: 07.04.06 12:03
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Возник вопрос по использованию GDI+

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

Здесь ошибка в том, что GetRawFormat() получает GUID формата изображения (котороый сохраняется в переменной Main, как я понял), а в методе Save() нужно указывать CLSID энкодера для нужного формата изображения, а не сам формат. В MSDN для получения CLSID энкодера приводится функция GetEncoderClsid(), которую легко переделать, чтобы находить CLSID не по MimeType (как в примерах), а по FormatID.
И еще, BSTR в Save() не требуется, в функциях GDI+ обычно используются просто WCHAR*.
Re[3]: GDI+: графика нового поколения
От: Аноним  
Дата: 08.04.06 14:03
Оценка:
Здравствуйте, algol, Вы писали:

A>Здравствуйте, Аноним, Вы писали:


А>>Возник вопрос по использованию GDI+

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

A>Здесь ошибка в том, что GetRawFormat() получает GUID формата изображения (котороый сохраняется в переменной Main, как я понял), а в методе Save() нужно указывать CLSID энкодера для нужного формата изображения, а не сам формат.

Большое спасибо!! Я торопился и перепутал
теперь всё работает.
В MSDN для получения CLSID энкодера приводится функция GetEncoderClsid(), которую легко переделать, чтобы находить CLSID не по MimeType (как в примерах), а по FormatID.
Взгляну.
A>И еще, BSTR в Save() не требуется, в функциях GDI+ обычно используются просто WCHAR*.
Это просто привычка.

Огромное спасибо. Очень торопился и всё напутал.
FonBalrog
Re: GDI+: графика нового поколения
От: sgi1981  
Дата: 10.04.06 06:18
Оценка:
Здравствуйте, Виталий Брусенцев, Вы писали:

ВБ>Статья:

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


ВБ>Авторы:

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

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

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

Хорошо.
Я прочитал эту статью и нашел все АПИ-функции, действия которых соответствует действиям классов, примеры работы с которыми описаны в статье.
Но просматривая АПИ-функции включаемого файла я нашел интересную особенность этой библиотеки.
В ней есть функции предназначенные для загрузки изображений из файлов.
Пока я нашел вот такие из этих функций.

GdipLoadImageFromStream(IStream* stream, GpImage **image);
Загружают изображение image из потока.
GdipLoadImageFromFile(GDIPCONST WCHAR* filename, GpImage **image);
Загружают изображение image из файла.
GdipLoadImageFromStreamICM(IStream* stream, GpImage **image);
Загружают изображение image из потока используя ICM.
GdipLoadImageFromFileICM(GDIPCONST WCHAR* filename, GpImage **image);
Загружают изображение image из файла, используя ICM.

Приведенные выше функции читают файл или поток на предмет нахождения изображения в нем,
распознают декомпрессор этого изображения,
выделяют блок памяти для указателя *image (в саму функцию передается уже указатель на указатель на будущий блок памяти, тем самым обеспечивается возврат значения указателя), в котором содержится некоторый объект хранящий все пикселыизображения и све его свойства.

Это понятно.
Но в этой же библиотеке есть ещё и такие функции для загрузки изображений из файлов

GdipCreateBitmapFromStream(IStream* stream, GpBitmap **bitmap);
загружает BITMAP из потока

GdipCreateBitmapFromFile(GDIPCONST WCHAR* filename, GpBitmap **bitmap);
загружает BITMAP из файла

GdipCreateBitmapFromStreamICM(IStream* stream, GpBitmap **bitmap);
загружает BITMAP из потока методом ICM

GdipCreateBitmapFromFileICM(GDIPCONST WCHAR* filename, GpBitmap **bitmap);
загружает BITMAP из файла методом ICM

Эти функции уже загружают изображение не в объект image, а в объект BITMAP.

Возникает вопрос.
А чем отличаются друг от друга эти объекты ?
Ну думая, над этим вопросом, я пришел к мысли о нескольких различиях.
Во первых BITMAP — это объект содержащий меньше информации об изображении, чем объект image.
Но если допустить (может я не прав), что оба эти объекта хранят значения пикселов изображения, а не его сжатый вид,
то зачем создавать дополнительный "урезанный" объект BITMAP ? Ведь image содержит все то же самое и даже больше.
Ещё один вопрос в том, как перевести image в BITMAP. Функций прямого перевода я не нашел во включаемом файле.
Дело в том, что мне нужно получить прямой доступ к пикселам изображения в сжатом формате из файла.
Функции, которая бы давала массив значений цветов пикселов из объекта image я не нашел.
Я нашел только нужную функцию, которая дает этот массив из объекта BITMAP.
GdipBitmapLockBits(GpBitmap* bitmap,
GDIPCONST GpRect* rect,
UINT flags,
PixelFormat format,
BitmapData* lockedBitmapData);

Значит для загрузки изображения нужно применить функцию GdipCreateBitmapFromFile(GDIPCONST WCHAR* filename, GpBitmap **bitmap);
Но если файл содержит несколько кадров, а не один, то как мне получить в массиве пикселов только нужный кадр ?
Везде и всегда должна быть физическая реальность и должен быть здравый смысл
Re[2]: GDI+: графика нового поколения
От: romson  
Дата: 10.04.06 09:29
Оценка:
Здравствуйте, sgi1981, Вы писали:

S> .....? ... ? .....................?


Возможно, я Вас очень сильно удивлю, если подскажу, что кроме подключаемых файлов и вышеупомянутой статьи есть такой ресурс в инете, как msdn.microsoft.com. И там есть ответы на все Ваши вопросы: и про отличие Image от Bitmap, и про доступ к отдельным пикселям, и про многокадровые изображения, и даже на те вопросы, которые у Вас ещё не возникли. Так что, смелее!

Вот парочка ссылок для затравки:
Bitmap::SetPixel
Image::SelectActiveFrame
Re[3]: GDI+: графика нового поколения
От: sgi1981  
Дата: 10.04.06 11:18
Оценка:
Здравствуйте, romson, Вы писали:

R>Здравствуйте, sgi1981, Вы писали:


S>> .....? ... ? .....................?


R>Возможно, я Вас очень сильно удивлю, если подскажу, что кроме подключаемых файлов и вышеупомянутой статьи есть такой ресурс в инете, как msdn.microsoft.com.


Я хорошо знаю, что этот ресур есть.
Но :
во первых — веб страницы того сайта имеют большой размер и мне на денежный балланс за интернет идет большое уменьшение,
во вторых — язык мне тот не родной, думать я на нем не собираюсь и не хочу,
в третьих — для чего создавался тогда сайт http://rsdn.ru если есть сайт http://msdn.com ?
Может и всех форумчан так можно послать на http://msdn.com ?
Чего они забивают вопросами этот сайт, если на майкрософтовском сайте инфы дочЁрта ?
Вот пусть и читают там.
Кто что думает об этом... ?
Везде и всегда должна быть физическая реальность и должен быть здравый смысл
Re[4]: GDI+: графика нового поколения
От: algol Россия about:blank
Дата: 10.04.06 12:36
Оценка:
Здравствуйте, sgi1981, Вы писали:

S>во первых — веб страницы того сайта имеют большой размер и мне на денежный балланс за интернет идет большое уменьшение,


Есть еще оффлайновая версия MSDN, ставится на компьютере.

S>во вторых — язык мне тот не родной, думать я на нем не собираюсь и не хочу,


Думать не надо, а читать все-таки придется.

S>Кто что думает об этом... ?


Если по существу вопроса, то Image (GpImage) это базовый класс для Bitmap (GpBitmap) и Metafile (GpMetafile). Функции Image поддерживают оба типа изображений. Тип конкретного экземпляра можно узнать через GdipGetImageType(). Если тип ImageTypeBitmap, то GpImage* может быть приведен к GpBitmap* и использован в функциях Bitmap. GpBitmap* может быть использован везде как GpImage*.

Если вы посмотрите исходники класса Bitmap, то увидите, что указатель на GDI+ объект определен в базовом классе Image как GpImage* nativeImage. В конструкторах туда пишется GpBitmap*, а в методах Bitmap он приводится обратно в GpBitmap*:
static_cast<GpBitmap*>(nativeImage)

Для работы с отдельными пикселами есть GdipBitmapLockBits() и GdipBitmapGetPixel()/GdipBitmapSetPixel().
Для выбора нужного кадра можно использовать GdipImageGetFrameCount() и GdipImageSelectActiveFrame().
Re[4]: GDI+: графика нового поколения
От: romson  
Дата: 10.04.06 12:39
Оценка: :)
Здравствуйте, sgi1981, Вы писали:

S>Я хорошо знаю, что этот ресур есть.

S>Но :
S>во первых — веб страницы того сайта имеют большой размер и мне на денежный балланс за интернет идет большое уменьшение,
S>во вторых — язык мне тот не родной, думать я на нем не собираюсь и не хочу,
S>в третьих — для чего создавался тогда сайт http://rsdn.ru если есть сайт http://msdn.com ?
S>Может и всех форумчан так можно послать на http://msdn.com ?
S>Чего они забивают вопросами этот сайт, если на майкрософтовском сайте инфы дочЁрта ?
S>Вот пусть и читают там.
S>Кто что думает об этом... ?

Т.е. Вы хотите, чтобы кто-то за Вас полез на MSDN, нашёл нужную инфу, перевёл её на Ваш родной язык и выложил Вам на блюдечке? Оригинально! Я думаю, Вам всё же не помешает потратить немного Вашего драгоценного интернетного баланса на прочтение рекомендаций данного форума:

Прежде, чем задавать технический вопрос по электронной почте или в дискуссионную группу, в чате или на форуме, сделайте следующее:

1. Попытайтесь найти ответ с помошью поиска в Web.
2. Попытайтесь найти ответ в руководстве.
...

Re[5]: GDI+: графика нового поколения
От: sgi1981  
Дата: 10.04.06 14:37
Оценка:
Здравствуйте, romson, Вы писали:

R>Здравствуйте, sgi1981, Вы писали:


R>

R>Прежде, чем задавать технический вопрос по электронной почте или в дискуссионную группу, в чате или на форуме, сделайте следующее:

R>1. Попытайтесь найти ответ с помошью поиска в Web.
R>2. Попытайтесь найти ответ в руководстве.
R>...


Везде и всегда должна быть физическая реальность и должен быть здравый смысл
Re[5]: GDI+: графика нового поколения
От: sgi1981  
Дата: 10.04.06 15:28
Оценка:
Здравствуйте, algol, Вы писали:

A>Если по существу вопроса, то Image (GpImage) это базовый класс для Bitmap (GpBitmap) и Metafile (GpMetafile). Функции Image поддерживают оба типа изображений. Тип конкретного экземпляра можно узнать через GdipGetImageType(). Если тип ImageTypeBitmap, то GpImage* может быть приведен к GpBitmap* и использован в функциях Bitmap. GpBitmap* может быть использован везде как GpImage*.


ВОТ СПАСИБО !
Теперь я проверил на АСМЕ.
Вместо объекта image можно задавать функции вывода изображения GdipDrawImageI объект bitmap.

push offset graphics;указатель на указатель на будущий объект graphics
push WND;описатель окна
call GdipCreateFromHWND;создать объект graphics по описателю WND окна 
push offset bitmap1;теперь будем создавать объект bitmap1 (БИТМАП) из файла, имя которого
push ps1;здесь
call GdipCreateBitmapFromFile;читаем файл и создаем БИТМАП
push y3;а теперь будем выводить БИТМАП в окно - пишем в стек координаты начала вывода
push x3;
push bitmap1;задаем наш БИТМАП
push graphics;задаем объект graphics, в который выводится будет
call GdipDrawImageI;и WINDOWS рисует в нашем окне изображение
push 0;
push graphics;
call GdipFlush;



A>Для работы с отдельными пикселами есть GdipBitmapLockBits() и GdipBitmapGetPixel()/GdipBitmapSetPixel().

A>Для выбора нужного кадра можно использовать GdipImageGetFrameCount() и GdipImageSelectActiveFrame().

Да, ещё буду экспериментировать.
Везде и всегда должна быть физическая реальность и должен быть здравый смысл
Re[5]: GDI+: графика нового поколения
От: Аноним  
Дата: 12.04.06 12:06
Оценка:
Здравствуйте, algol, Вы писали:

A>Для работы с отдельными пикселами есть GdipBitmapLockBits() и GdipBitmapGetPixel()/GdipBitmapSetPixel().

A>Для выбора нужного кадра можно использовать GdipImageGetFrameCount() и GdipImageSelectActiveFrame().

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

написано
...
При этом, если указать формат временного буфера (PixelFormat), отличный от формата исходного растра, вызовы LockBits/UnlockBits потребуют дополнительных преобразований.
...

Так вот, незнаю, как на самом деле работает функция LockBits у класса.
Но когда я загружал 8-битный BMP-файл функцией
GdipCreateBitmapFromFile
и потом пытался преобразовать формат пикселов из 8-ми битного в 24-битный функцией
GdipBitmapLockBits, то
ничего не получилось и функция GdipBitmapLockBits выдала значение 2 — неправильно задан параметр.
удавалось таким образом выполнять преобразования
из 24-битного формата в 32-битный
из 16-битного в 32-битный.

Но из 8-битного в 32-битный никак та функция не преобразовывает.
Так что мне нужно специально сохранять изображение другим кодеком в файл в другом формате, а потом из файла опять его читать ?
Re: GDI+: графика нового поколения
От: Аноним  
Дата: 04.03.07 16:15
Оценка:
Здравствуйте, Виталий Брусенцев, Вы писали:

ВБ>Статья:

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


ВБ>Авторы:

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

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

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

Преогромнейшее спасибо! Статья помогла мне разобраться с возможностями этой графической библиотеки, особенно признателен за приложение — пример. Респект и уважуха!
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.