Manipulation de bitmap (SetDIBits) [Résolu]

_michel 77 Messages postés mardi 27 juin 2006Date d'inscription 12 août 2010 Dernière intervention - 21 oct. 2006 à 20:23 - Dernière réponse : _michel 77 Messages postés mardi 27 juin 2006Date d'inscription 12 août 2010 Dernière intervention
- 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
SAKingdom 3213 Messages postés lundi 7 novembre 2005Date d'inscription 16 février 2009 Dernière intervention - 22 oct. 2006 à 17:12
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

Avec quelques mots c'est encore mieux Ajouter un commentaire

Codes Sources a aidé 124 internautes ce mois-ci

Commenter la réponse de SAKingdom
cs_Joky 1791 Messages postés lundi 22 novembre 2004Date d'inscription 31 janvier 2009 Dernière intervention - 22 oct. 2006 à 02:52
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
cs_Joky 1791 Messages postés lundi 22 novembre 2004Date d'inscription 31 janvier 2009 Dernière intervention - 22 oct. 2006 à 02:54
0
Merci
Ah j'avais pas vu le reste du code désolé ;)

ULARGE_INTEGERJokyQi=QI("Joky"
Commenter la réponse de cs_Joky
Ombitious_Developper 2333 Messages postés samedi 28 février 2004Date d'inscription 26 juillet 2013 Dernière intervention - 22 oct. 2006 à 04:40
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
_michel 77 Messages postés mardi 27 juin 2006Date d'inscription 12 août 2010 Dernière intervention - 22 oct. 2006 à 11:14
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
_michel 77 Messages postés mardi 27 juin 2006Date d'inscription 12 août 2010 Dernière intervention - 22 oct. 2006 à 18:19
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
SAKingdom 3213 Messages postés lundi 7 novembre 2005Date d'inscription 16 février 2009 Dernière intervention - 22 oct. 2006 à 18:55
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
_michel 77 Messages postés mardi 27 juin 2006Date d'inscription 12 août 2010 Dernière intervention - 25 oct. 2006 à 19:10
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.