Affichage d'une hbitmap avec DX9 [Résolu]

Signaler
Messages postés
5
Date d'inscription
mercredi 16 mars 2005
Statut
Membre
Dernière intervention
14 septembre 2007
-
Messages postés
5
Date d'inscription
mercredi 16 mars 2005
Statut
Membre
Dernière intervention
14 septembre 2007
-
bonjour a tous,

Je cherche toute personne pouvant m'aider, soit en me donnant des informations ou des pistes de recherche, pour afficher un hbitmap que je crée de toute piece.

En faite cette demande vient d'une videoconference que j'ai réalisé avec l'envoi par ip compression decompression divx mais il ne me manque plus que l'affichage de l'image.

En vous remerciant par avance,
mes sources pour la connexion ip et compression decompression ne sont pas disponible pour l'instant mais bientot

bibou

5 réponses

Messages postés
3874
Date d'inscription
mardi 8 mars 2005
Statut
Modérateur
Dernière intervention
7 novembre 2014
13
Salut,

Sous DirectX9 tu peux créer une texture vide, la locker, puis mettre copier les donner de ta bitmap qui arrive dedans. Si ta bitmap est une 24 bits tableau de couleur, tu peux probablement faire un banal CopyMemory  de la taille largeur * hauteur * 3.

Commence par essayer des images de taille puissance de deux.
Messages postés
3874
Date d'inscription
mardi 8 mars 2005
Statut
Modérateur
Dernière intervention
7 novembre 2014
13
heu c'est peut être un peut trops Direct3D tout ça.

DirectDraw à l'air nettement mieux armé pour la 2D.
Messages postés
3874
Date d'inscription
mardi 8 mars 2005
Statut
Modérateur
Dernière intervention
7 novembre 2014
13
Argh.
Je reviens sur ce que je suis revenu.
DirectDraw est deprecated.

Redmond conseil bien d'utiliser DirectGraphics. Pour ça on peut faire mumuse avec les matrices, mais le plus simple est d'utiliser des vertices avec des coordonnées écrans. On vat faire quatres vertices pour avoir un rectangle qui va prendre tout la fenêtre de rendu.

Je suis parvenu à afficher une bitmap chargée avec D3DXCreateTextureFromFile, mais pas en lui mettant directement un tableau de bits. M'enfin je crois avoir bien débroussaillé l'algo. Il faut pas copier toutes les infos d'un coup, mais lignes par lignes, car DirectX stocke des informations à la fin des lignes. On connait la taille des lignes avec la propriété Pitch des infos de la texture.

J'ai mis une compilation conditionnelle pour spécifier le mode de chargement. Dans le cas du chargement du tableau de RGB, le programme ne crash pas, la texture rendu à l'écran est juste pas ce qu'il faudrait.

J'ai écrit tout ça en Delphi, mais la convertion ne devrait pas te poser de problèmes : je n'ai pratiquement rien utiliser de Delphi, à part un ShowMessage à la place d'une MessageBox. Même la fenêtre est en Win32. Si tu as quand même des problèmes de convertion, n'hésite pas, j'ai un peu 'epérience en C/C++.

Merci de me tenir au courant si tu trouve ce que j'ai foiré.
program BitmapDX9;

//************************************************************************
// Merci infiniment à Alexey Barkovoy pour les headers.
// http://clootie.narod.ru/delphi/index.html
//************************************************************************

uses
Windows, Messages, Direct3D9, Dialogs, Forms, D3DX9;

// Commenter pour charger depuis un tableaux de RGB
{$DEFINE CreateFromBitmap}

var
uD3D9: IDirect3D9; // DirectX 9
uDevice: IDirect3DDevice9; // Le device

uClient: TRect; // Taille de la zone cliente

uVB: IDirect3DVertexBuffer9; // La liste des vertices
uTex: IDirect3DTexture9; // La texture

// Un vertex
type TRHWVertex = packed record
position: TD3DXVector4; // Position
tu: Single; // x de texture
tv: Single; // y de texture
end;

// Pour faire des modifs plus facilement dans le vertex buffer
TRHWVertexArray = array [0..3] of TRHWVertex;
PRHWVertexArray = ^TRHWVertexArray;

procedure FatalError(sMsg: String);
begin
ShowMessage(sMsg);
Halt;
end;

procedure CreateVertexBuffer();
var
uVBData: PRHWVertexArray; // Pointeur sur les données du VB
nI: Integer;
begin
// Création de 4 vertices pour les 4 coins de notre rectangle
if Failed(uDevice.CreateVertexBuffer(4 * SizeOf(TRHWVertex),
D3DUSAGE_WRITEONLY, D3DFVF_XYZRHW or D3DFVF_TEX1,
D3DPOOL_MANAGED, uVB, nil)) then FatalError('Echec création du VB');

// Il faut bloquer le VB pour pouvoir le modifier
uVB.Lock(0, 0, Pointer(uVBData), 0);

// Z doit être égale à 0 et W à 1
for nI:= 0 to 3 do
with uVBData[nI].position do
begin
z:= 0;
w:= 1;
end;

with uVBData[0] do
begin
position.x:= 0;
position.y:= 0;
tu:= 0;
tv:= 0;
end;

with uVBData[1] do
begin
position.x:= uClient.Right;
position.y:= 0;
tu:= 1;
tv:= 0;
end;

with uVBData[2] do
begin
position.x:= uClient.Right;
position.y:= uClient.Bottom;
tu:= 1;
tv:= 1;
end;

with uVBData[3] do
begin
position.x:= 0;
position.y:= uClient.Bottom;
tu:= 0;
tv:= 1;
end;

// On débloque le VB
uVB.UnLock;

// On sélectionne le format de vertices dans le device
uDevice.SetFVF(D3DFVF_XYZRHW or D3DFVF_TEX1);

// On sélectionne le vertex buffer dans le device
uDevice.SetStreamSource(0, uVB, 0, SizeOf(TRHWVertex));
end;

procedure CreateTexture(hDC: HDC; sBitmapFile: String);
{$IFDEF CreateFromBitmap}
var
hFile: THandle; // Handle du fichier de la bitmap
uFileHeader: TBitmapFileHeader; // Infos sur le contenu du fichier de la bitmap
uBitmapHeader: TBitmapInfoHeader; // Infos sur la bitmap
uBits: Pointer; // Données de la bitmap
nRead: Cardinal; // Bytes lus
nBitsSize: Integer; // Taille des bits de la bitmap
uTexData: TD3DLockedRect; // Zone de la texture lockée
uInTexData: Pointer; // Progression dans les données de la texture
uInBitmapData: Pointer; // Progression dans les données de la bitmap
nI: Integer;
{$ENDIF}
begin
{$IFDEF CreateFromBitmap}

// Ouverture du fichier
hFile:= CreateFile(PChar(sBitmapFile), GENERIC_READ, FILE_SHARE_READ, nil, OPEN_EXISTING, FILE_ATTRIBUTE_READONLY, 0);
if hFile = 0 then FatalError('Echec chargement de la bitmap');

// Récupération du BITMAPFILEHEADER
ReadFile(hFile, uFileHeader, SizeOf(BITMAPFILEHEADER), nRead, nil);

// Récupération du BITMAPINFOHEADER
ReadFile(hFile, uBitmapHeader, sizeof(BITMAPINFOHEADER), nRead, nil);

// Allocation d'un emplacement de stockage des bits de l'image
nBitsSize:= uFileHeader.bfSize - uFileHeader.bfOffBits;
uBits:= GlobalAllocPtr(GMEM_FIXED, nBitsSize);

// Lecture des bits
ReadFile(hFile, uBits, nBitsSize, nRead, nil);

// Fermeture du fichier
CloseHandle(hFile);

if Failed(D3DXCreateTexture(uDevice, uBitmapHeader.biWidth, uBitmapHeader.biHeight,
1, 0, D3DFMT_R8G8B8, D3DPOOL_MANAGED, uTex)) then FatalError('Echec de la création de la texture');

// On va recopier les bits de la bitmap vers la texture
uTex.LockRect(0, uTexData, nil, 0);

// Recopie des données de la bitmap dans la texture
uInTexData:= uTexData.pBits;
uInBitmapData:= uBits;
for nI:= 0 to uBitmapHeader.biHeight - 1 do
begin
CopyMemory(uInTexData, uInBitmapData, uBitmapHeader.biWidth * 3);
uInTexData:= Pointer(Cardinal(uInTexData) + uTexData.Pitch);
uInBitmapData:= Pointer(Cardinal(uInBitmapData) + uBitmapHeader.biWidth * 3);
end;

uTex.UnlockRect(0);

// Demande de mise à jour de la texture
uDevice.UpdateTexture(uTex, uTex);

// Libération des bits du tableau
GlobalFreePtr(uBits);

{$ELSE}
// Création de la texture
if Failed(D3DXCreateTextureFromFile(uDevice, 'Test.bmp', uTex)) then FatalError('Echec du chrgement de la texture');
{$ENDIF}

// Sélection de la texture dans le device
uDevice.SetTexture(0, uTex);
end;

procedure CreateDevice(hWnd: HWND);
var
uPresentParameters: TD3DPresentParameters; // Paramètres de création du device
begin
// Création de DirectX9
uD3D9:= Direct3DCreate9(D3D_SDK_VERSION);
if (uD3D9 = nil) then FatalError('Echec création device');

// Préparation des paramètres de création du device
ZeroMemory(@uPresentParameters, SizeOf(uPresentParameters));
with uPresentParameters do
begin
Windowed:= True;
SwapEffect:= D3DSWAPEFFECT_DISCARD;
BackBufferFormat:= D3DFMT_UNKNOWN;
end;

if Failed(uD3D9.CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd,
D3DCREATE_HARDWARE_VERTEXPROCESSING or D3DCREATE_PUREDEVICE,
@uPresentParameters, uDevice)) then FatalError('Echec de la création du device');
end;

procedure DestroyDevice;
begin
uVB:= nil;
uTex:= nil;
uDevice:= nil;
uD3D9:= nil;
end;

procedure Render;
begin
// Nettoyage du buffer
uDevice.Clear(0, nil, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0, 0, 0), 1.0, 0);

// Début du dessin
if (SUCCEEDED(uDevice.BeginScene)) then
begin
// Dessin des 4 vertices du quad (2 triangles)
uDevice.DrawPrimitive(D3DPT_TRIANGLEFAN, 0, 2);

// Fin du dessin
uDevice.EndScene;
end;

// Présentation du dessin
uDevice.Present(nil, nil, 0, nil);
end;

function MsgProc(hWnd: HWND; uMsg: UINT; wParam: WPARAM; lParam: LPARAM): LRESULT; stdcall;
begin
case uMsg of
WM_DESTROY:
begin
DestroyDevice;
PostQuitMessage(0);
Result:= 0;
Exit;
end;

WM_PAINT:
begin
Render;
ValidateRect(hWnd, nil);
Result:= 0;
Exit;
end;
end;

Result:= DefWindowProc(hWnd, uMsg, wParam, lParam);
end;

var
uWndClass: TWndClassEx = (
cbSize: SizeOf(TWndClassEx);
style: CS_CLASSDC;
lpfnWndProc: @MsgProc;
cbClsExtra: 0;
cbWndExtra: 0;
hInstance: 0;
hIcon: 0;
hCursor: 0;
hbrBackground: 0;
lpszMenuName: nil;
lpszClassName: 'BitmapDX9';
hIconSm: 0);
hWindow: HWND;
uMsg: TMsg;
begin
// Registration de la classe
with uWndClass do
begin
hInstance:= GetModuleHandle(nil);
hIcon:= LoadIcon(0, IDI_APPLICATION);
hCursor:= LoadCursor(0, IDC_ARROW);
end;
RegisterClassEx(uWndClass);

// Création de la fenêtre
hWindow:= CreateWindow('BitmapDX9', 'BitmapDX9',
WS_OVERLAPPEDWINDOW, 100, 100, 300, 300,
0, 0, uWndClass.hInstance, nil);

// Récupération de la taille de la zone cliente
GetClientRect(hWindow, uClient);

// Création du device
CreateDevice(hWindow);

// Création des vertice du quad qui ou serat rendu la texture
CreateVertexBuffer;

// Création de la texture
CreateTexture(GetDC(hWindow), 'Test.bmp');

// Affichage de la fenêtre
ShowWindow(hWindow, SW_SHOWDEFAULT);
UpdateWindow(hWindow);

// Traitement des messages
while GetMessage(uMsg, 0, 0, 0) do
begin
TranslateMessage(uMsg);
DispatchMessage(uMsg);
end;
end.
Messages postés
3874
Date d'inscription
mardi 8 mars 2005
Statut
Modérateur
Dernière intervention
7 novembre 2014
13
Bon ben j'ai corrigé.

Si j'ai bien compris la doc, D3DFMT_R8G8B8 n'est pas un format valide pour une texture.
Je me suis donc reporté sur un D3DFMT_X8R8G8B8, 32 bits : RGB + un octet non utilisé.
Le souci, c'est que l'on se retrouve à copier des texels de 24 bits dans des texels de 32...
Il faut donc copier texel par texel, mais on peut copier 32 vers 32 vu que le dernier octet n'a pas d'importance.

Autre "détail", la bitmap que j'ai utilisée est bottum-up : la dernière ligne du tableau correspond à la première de l'image.

Dans ton cas, je te conseil vivement de ne pas décompresser dans une bitmap et de faire une copie des données de la bitmap dans une texture.

Décompresse plutôt directement dans la texture.

Et n'oublie pas : texture avec hauteur/largeur multiples de deux.

La nouvelle CreateTexture. Le paramètre hDC ne sert à rien.
Bon courage pour la traduction.
procedure CreateTexture(hDC: HDC; sBitmapFile: String);
{$IFDEF CreateFromBitmap}
var
  hFile: THandle;                     // Handle du fichier de la bitmap
  uFileHeader: TBitmapFileHeader;     // Infos sur le contenu du fichier de la bitmap
  uBitmapHeader: TBitmapInfoHeader;   // Infos sur la bitmap
  uBits: Pointer;                     // Données de la bitmap
  nRead: Cardinal;                    // Bytes lus
  nBitsSize: Integer;                 // Taille des bits de la bitmap
  uTexData: TD3DLockedRect;           // Zone de la texture lockée
  nPitch: Integer;                    // Nombre de bits à oublier en bout de ligne de texture
  nBitmapLineWidth: Integer;          // Largeur de la ligne d'une bitmap en octets
  uBitmapLastLine: Pointer;           // Adresse du début de la dernière ligne de la bitmap
  label NextLine;
  label NextTexel;
{$ENDIF}
begin
  {$IFDEF CreateFromBitmap}

  // Ouverture du fichier
  hFile:= CreateFile(PChar(sBitmapFile), GENERIC_READ, FILE_SHARE_READ, nil, OPEN_EXISTING, FILE_ATTRIBUTE_READONLY, 0);
  if hFile = 0 then FatalError('Echec chargement de la bitmap');

  // Récupération du BITMAPFILEHEADER
  ReadFile(hFile, uFileHeader, SizeOf(BITMAPFILEHEADER), nRead, nil);
 
  // Récupération du BITMAPINFOHEADER
  ReadFile(hFile, uBitmapHeader, sizeof(BITMAPINFOHEADER), nRead, nil);

  // Allocation d'un emplacement de stockage des bits de l'image
  // Le "+ 1" ne sert qu'à s'assurer qu'il n'y ai pas de violation
  // d'accès lors de la copie 32bits -> 32bits, alors que l'on
  // en a que 24.
  nBitsSize:= uFileHeader.bfSize - uFileHeader.bfOffBits;
  uBits:= GlobalAllocPtr(GMEM_FIXED, nBitsSize + 1);

  // Lecture des bits
  ReadFile(hFile, Byte(uBits^), nBitsSize, nRead, nil);

  // Fermeture du fichier
  CloseHandle(hFile);

  // Création d'une texture vide
  if Failed(D3DXCreateTexture(uDevice, uBitmapHeader.biWidth, uBitmapHeader.biHeight,
                             
1, 0, D3DFMT_X8R8G8B8, D3DPOOL_MANAGED, uTex)) then FatalError('Echec
de la création de la texture');

  // Il faut locker la bitmap pour pouvoir la modifier
  // Les locks de vertex buffer et de textures sont à éviter autant que possible
  // pour des raisons de performances.
  uTex.LockRect(0, uTexData, nil, 0);

  // Calcul de la taille de la zone à ne pas toucher en fin de texture
  nPitch:= uTexData.Pitch - uBitmapHeader.biWidth * 4;

  // Calcul de la largeur d'une ligne de la bitmap
  nBitmapLineWidth:= uBitmapHeader.biWidth * 3;

  // Calcul de l'adresse du début de la dernière ligne de la bitmap
  uBitmapLastLine:= Pointer(Integer(uBits) + nBitmapLineWidth * (uBitmapHeader.biHeight - 1));

  // Recopie des données de la bitmap dans la texture
  // ecx : Se décremente sur les lignes
  // ebx : Pointe dans la texture
  // edx : S'incrémente de 3 par texel dans une ligne
  // eax : Pointe dans la bitmap
  // edi : Impossible de copier RAM->RAM
  asm
    mov ecx, uBitmapHeader.biHeight
    mov ebx, uTexData.pBits;
    mov eax, uBitmapLastLine

    NextLine:
    xor edx, edx
    NextTexel:

    // Copie de la bitmap vers la texture
    mov edi, [eax + edx]
    mov [ebx], edi

    // Passage au texel suivant
    add ebx, 4
    add edx, 3

    // Fin de la ligne ?
    cmp edx, nBitmapLineWidth
    jne NextTexel

    // Prise en compte des bits en fin de ditmap
    add ebx, nPitch
   
    // Passage à la ligne suivante
    sub eax, nBitmapLineWidth
    dec ecx
    jnz NextLine
  end;
 
  uTex.UnlockRect(0);

  // Demande de mise à jour de la texture
  uDevice.UpdateTexture(uTex, uTex);

  // Libération des bits du tableau
  GlobalFreePtr(uBits);

  {$ELSE}
  // Création de la texture
  if Failed(D3DXCreateTextureFromFile(uDevice, 'Test.bmp', uTex)) then FatalError('Echec du chrgement de la texture');
  {$ENDIF}

  // Sélection de la texture dans le device
  uDevice.SetTexture(0, uTex);
end;
Messages postés
5
Date d'inscription
mercredi 16 mars 2005
Statut
Membre
Dernière intervention
14 septembre 2007

Salut ! trop enorme tu m'enleve une vrai epine du pied.
car directx c vraiment la galere, je vais potasser ton ton prog, trop cool !! :)