Manipulation de bitmap (SetDIBits) [Résolu]

Messages postés
77
Date d'inscription
mardi 27 juin 2006
Dernière intervention
12 août 2010
- - Dernière réponse : _michel
Messages postés
77
Date d'inscription
mardi 27 juin 2006
Dernière intervention
12 août 2010
- 25 oct. 2006 à 19:10
Encore une fois, j'ai un problème avec les bitmaps.
J'ai bien cherché, en comparant avec un programme qui fonctionne, mais j'ai rien trouvé.
Voila le code complet de mon programme (il est compilé mais affiche un fond noir, comme si le bmp avait été créé mais pas modifié):

#include <windows.h>



// Prototypes de fonctions
LRESULT CALLBACK WinMainProc (HWND, UINT, WPARAM, LPARAM);



// Variables globales du programme
HINSTANCE hInstance;
HWND hWndMain;
unsigned int largeur = 300;
unsigned int hauteur = 200;
HDC hMainDC = NULL;
HDC hMemDC;





/******************************************************************************/


int WINAPI WinMain (HINSTANCE hThisInstance, HINSTANCE hPrevInstance, LPSTR lpszArgument, int nFunsterStil)
{
    MSG messages;
    WNDCLASSEX wincl;
 RECT rect;
 HMENU hMenu;


 hInstance = hThisInstance;


    wincl.cbSize = sizeof (WNDCLASSEX);
    wincl.style = 0;
    wincl.lpfnWndProc = WinMainProc;
    wincl.cbClsExtra = 0;
    wincl.cbWndExtra = 0;
    wincl.hInstance = hInstance;
    wincl.hIcon = LoadIcon (NULL, IDI_APPLICATION);
    wincl.hCursor = LoadCursor (NULL, IDC_ARROW);
    wincl.hbrBackground = CreateSolidBrush (RGB (127, 127, 127));
    wincl.lpszMenuName = NULL;
    wincl.lpszClassName = "MainClass";
    wincl.hIconSm = LoadIcon (NULL, IDI_APPLICATION);


    RegisterClassEx (&wincl);


 rect.left = 100;
 rect.right = 100 + largeur;
 rect.top = 100;
 rect.bottom = 100 + hauteur;
    AdjustWindowRectEx (&rect, WS_CAPTION, FALSE, 0);


    hWndMain = CreateWindowEx (0, "MainClass", "Fenêtre",
        WS_SYSMENU | WS_MINIMIZEBOX | WS_VISIBLE, CW_USEDEFAULT, CW_USEDEFAULT,
        rect.right - rect.left, rect.bottom - rect.top,
        HWND_DESKTOP, NULL, hInstance, NULL);


    while (GetMessage (&messages, NULL, 0, 0)){
        TranslateMessage(&messages);
        DispatchMessage(&messages);
    }


    return messages.wParam;
}


/******************************************************************************/


LRESULT CALLBACK WinMainProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    PAINTSTRUCT ps;
    HBITMAP hbmp;
    HDC hdc;


 HBITMAP hBmp;
 BITMAP bmp;
 BITMAPINFO bi;
 int ligne;
 char *image;
 long x, y;
 int pos;
 char couleur;


    switch (message)
    {
        case WM_PAINT:
   if (hMainDC == NULL){
    // Initialise les DC et le bitmap.
    hMainDC = GetDC (hwnd);
    hMemDC = CreateCompatibleDC (hMainDC);
    hbmp = CreateCompatibleBitmap (hMemDC, largeur, hauteur);
    SelectObject(hMemDC, hbmp);
    DeleteObject (hBmp);


    // Recupère le handle du bitmap.
    hBmp = GetCurrentObject(hMemDC, OBJ_BITMAP);
    // Récupère les données sur l'image.
    GetObject(hBmp, sizeof(bmp), &bmp);


    // Remplie la structure BITMAPINFO
    ZeroMemory(&bi, sizeof(bi));
    bi.bmiHeader.biSize = sizeof(bi.bmiHeader);
    bi.bmiHeader.biWidth = bmp.bmWidth;
    bi.bmiHeader.biHeight = bmp.bmHeight;
    bi.bmiHeader.biPlanes = bmp.bmPlanes;
    bi.bmiHeader.biBitCount = 24;
    bi.bmiHeader.biCompression = BI_RGB;


    // Allocation de la mémoire.
    ligne = 4*((3*bi.bmiHeader.biWidth+3)/4);
    image = LocalAlloc(0, ligne*bi.bmiHeader.biHeight);


    // Récupération de l'image du DC mémoire dans un buffer
    GetDIBits(hMemDC, hBmp, 0, bi.bmiHeader.biHeight, image, &bi, DIB_RGB_COLORS);


    // Calcul proprement dit.
    for(y = 0; y < bi.bmiHeader.biHeight; y++){
     for(x = 0; x < bi.bmiHeader.biWidth; x++){
      // Calcule de la position dans le buffer
      pos = ((bi.bmiHeader.biHeight - (y + 1)) * ligne) + (x * 3);


      // Calcul de la couleur du pixel.
      couleur = 10;


      image[pos] = couleur;   // Bleu
      image[pos+1] = couleur; // Vert
      image[pos+2] = couleur; // Rouge
     }
    }


    // Réentre l'image modifiée dans le DC mémoire

/*
 * ! : C'est là que la fonction ne semble pas avoir d'effet
 */
    SetDIBits(hMemDC, hBmp, 0, bi.bmiHeader.biHeight, image, &bi, DIB_RGB_COLORS);


    LocalFree(image);
    DeleteObject(hBmp);
   }
    
   hdc = BeginPaint (hwnd, &ps);
 
   BitBlt(hdc, 0, 0, largeur, hauteur, hMemDC, 0, 0, SRCCOPY);
            EndPaint (hwnd, &ps);
            return 0;


        case WM_DESTROY:
   // Libère les DC.
   ReleaseDC (hwnd, hMainDC);
   DeleteDC (hMemDC);
            PostQuitMessage (0);
            return 0;


        default:
            return DefWindowProc (hwnd, message, wParam, lParam);
    }
}
Afficher la suite 

Votre réponse

8 réponses

Meilleure réponse
Messages postés
3213
Date d'inscription
lundi 7 novembre 2005
Dernière intervention
16 février 2009
3
Merci
Tu veux créé l'image de toute pièce? Ha mais moi je croyais que tu voulait simplement modifier un bmp existant. Dans ce cas va voir cette source:
http://www.cppfrance.com/codes/EXEMPLE-UTILISATION-SETDIBITSTODEVICE_37657.aspx
C'est à peu près le même principe.

C++ (@++)<!--

Merci SAKingdom 3

Quelques mots de remerciements seront grandement appréciés. Ajouter un commentaire

Codes Sources a aidé 105 internautes ce mois-ci

Commenter la réponse de SAKingdom
Messages postés
1791
Date d'inscription
lundi 22 novembre 2004
Dernière intervention
31 janvier 2009
0
Merci
le device context sur le quel on veut dessiner doit être celui retourner par BeginPaint en tout cas

ULARGE_INTEGERJokyQi=QI("Joky"
Commenter la réponse de cs_Joky
Messages postés
1791
Date d'inscription
lundi 22 novembre 2004
Dernière intervention
31 janvier 2009
0
Merci
Ah j'avais pas vu le reste du code désolé ;)

ULARGE_INTEGERJokyQi=QI("Joky"
Commenter la réponse de cs_Joky
Messages postés
2333
Date d'inscription
samedi 28 février 2004
Dernière intervention
26 juillet 2013
0
Merci
Salut :

// La procédure WndProc
// ...

HBITMAP      hBitmap;
BITMAP       Bmp;
HDC          hDC;
PAINTSTRUCRT ps;

case WM_CREATE:
     hBitmap = (HBITMAP)LoadImage(NULL,
                                 
"res/fond.bmp",
                                 
IMAGE_BITMAP,
                                  0,
                                  0,
                                  LR_LOADFROMFILE);
     if (hBitamp == NULL)
         SendMessage (hWnd, WM_QUIT, 0, 0);

     GetObject ((HBITMAP)hBitmap,
                 sizeof (BITMAP),
                 (BITMAP *)&Bmp);
     // ...

     break;

case WM_PAINT:
     hDC = BeginPaint (hWnd, &ps);
     HDC hMemDC = CreateCompatibleDC (hDC);
     HBITMAP hOldBitmap = (HBITMAP)SelectObject (
                                 
hMemDC,


                                  (HBITMAP)hBitmap);
     BitBlt (hDC,
             0,
             0,
             Bmp.bmWidth,
             Bmp.bmHeight,
             hMemDC,
             0,
             0,
             SRCCOPY);
     SelectObject (hMemDC, hOldBitmap);
     DeleteObject ((HBITMAP)hOldBitmap);
     DeleteDC (hMemDC);
     EndPaint (hWnd, &ps);
     break;

case WM_DESTROY:
     if (hBitmap)
         DeleteObject ((HBITMAP)hBitmap);
     // ...
     break;
// ...
Commenter la réponse de Ombitious_Developper
Messages postés
77
Date d'inscription
mardi 27 juin 2006
Dernière intervention
12 août 2010
0
Merci
Non, je ne veux pas charger un bmp d'un fichier; je veux le créer, puis le modifier, et enfin l'afficher.
En fait, mon but est de conserver un bitmap en mémoire et de le modifier à ma volonté, sans passer par des ressources, et c'est la modification de ce bmp qui ne marche pas (SetDIBits ()).
Merci quand même.
Commenter la réponse de _michel
Messages postés
77
Date d'inscription
mardi 27 juin 2006
Dernière intervention
12 août 2010
0
Merci
Ok, mais pourquoi utiliser un DC mémoire pour un bmp déja fait et pas pour un bmp créé par le programme ?
Ca semble plus simple de ne jamais en utiliser, et puis ça évite d'allouer 2 fois la mémoire quand tu le modifie -> GetDIBits(hMemDC, hBmp, 0, bi.bmiHeader.biHeight, lpBits, &bi, DIB_RGB_COLORS);

Et puis pourquoi ça marche pas mon essai, c'est à peu près la copie conforme de ton programme.

En tout cas, merci pour ta source.
Commenter la réponse de _michel
Messages postés
3213
Date d'inscription
lundi 7 novembre 2005
Dernière intervention
16 février 2009
0
Merci
Ça ne fonctionne pas car l'autre source (Get et SetDIBits) est fais pour modifier un bmp déjà présent sur la fenetre et le réafficher. Donc quand tu fais GetObject, tu essais de récupérer des informations inexistantes. Regarde bien cette source (SetDIBitsToDevice). Elle montre comment créé un bitmap sur une fenetre de toute pièce.

C++ (@++)<!--
Commenter la réponse de SAKingdom
Messages postés
77
Date d'inscription
mardi 27 juin 2006
Dernière intervention
12 août 2010
0
Merci
Super, ca marche.


Merci encore a vous tous et a votre dynamisme, qui fait qu'en un rien de temps on trouve tout ce qu'on veut sur ce forum.




 
Commenter la réponse de _michel

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.