Afficher des images sous windows NT

L'auteur

Site personnel

Liens sociaux

Viadeo Twitter Facebook Share on Google+   

I. Introduction

Nous avons vu comment afficher des images bitmap tout en les chargeant avec la fonction LoadImage, hélas cette fonction ne permet pas de charger une image depuis un fichier sous Windows NT. Nous allons devoir charger le fichier et le traiter avant affichage.

II. Chargement du fichier

L'ouverture du fichier se fait avec la fonction CreateFile. Nous extrayons tout d'abord l'entête du fichier BITMAPFILEHEADER à l'aide de la fonction ReadFile. Ensuite nous chargeons le bitmap dans un buffer.

 
Sélectionnez
    static LPVOID buffer;   

    

    

    /* ... */    

    

             HANDLE hf;

             DWORD FileSize,nbcharRead;

             BITMAPFILEHEADER bfh;



             hf = CreateFile("image.bmp", GENERIC_READ, 0,NULL,

                                    OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);



             FileSize = GetFileSize(hf, NULL);

             ReadFile(hf, &bfh, sizeof(bfh), &nbcharRead, NULL) ;



             buffer = GlobalAlloc(GMEM_FIXED, FileSize);

             ReadFile(hf, buffer, FileSize - sizeof(BITMAPFILEHEADER),

                                                             &nbcharRead, NULL);

                                                             

             

             /* ... */

             CloseHandle(hf);

             /* ... */

             GlobalFree(buffer);  

III. Création de la palette de couleur

Si le bitmap à un nombre de couleurs inférieur ou égal à 256, il faut générer sa palette de couleur. Les bitmaps ayant plus de 256 couleurs n'ont pas de palette. Chaque pixel est représenté par la valeur réelle de sa couleur. Le bitmap contient un entête BITMAPINFO donnant ces informations nous y extrayons le nombre de couleurs et créons la palette si besoin. La palette sera ensuite accessible via son handle de palette hpal de type HPALETTE.

 
Sélectionnez
    static LPVOID buffer;   

    static UINT nbColors; 

    static HPALETTE hpal;

    static BITMAPINFO *bmInfo;   

    

    /* ... */ 



             bmInfo = (BITMAPINFO*)buffer;

             nbColors = bmInfo->bmiHeader.biClrUsed ?

                                         bmInfo->bmiHeader.biClrUsed :

                                              1 << bmInfo->bmiHeader.biBitCount;



             if( nbColors <= 256 )

               {

                UINT i;

                UINT nSize = sizeof(LOGPALETTE) +

                                              (sizeof(PALETTEENTRY) * nbColors);



                LOGPALETTE *pLPal = (LOGPALETTE*) GlobalAlloc(GMEM_FIXED,nSize);

                pLPal->palVersion = 0x300;

                pLPal->palNumEntries = nbColors;

                for( i=0; i < nbColors; i++)

                 {

                  pLPal->palPalEntry[i].peRed = bmInfo->bmiColors[i].rgbRed;

                  pLPal->palPalEntry[i].peGreen = bmInfo->bmiColors[i].rgbGreen;

                  pLPal->palPalEntry[i].peBlue = bmInfo->bmiColors[i].rgbBlue;

                  pLPal->palPalEntry[i].peFlags = 0;

                 }

                hpal = CreatePalette(pLPal);

                GlobalFree(pLPal);

               }

IV. Affichage de l'image

L'affichage de l'image se fait avec la fonction SetDIBitsToDevice. Cette fonction reçoit entre autres un pointeur sur l'entête du bitmap (bmInfo) mais aussi un pointeur sur les pixels (lpDIBBits) qu'il faut calculer en fonction des infos contenues dans l'entête du bitmap. Et s'il y a une palette, il faut la sélectionner.

 
Sélectionnez
        

    static LPVOID buffer;   

    static UINT nbColors; 

    static HPALETTE hpal;

    static BITMAPINFO *bmInfo;  

    

    /* ... */        

        

        case WM_PAINT :

            {

              HDC hdc;

              PAINTSTRUCT ps;

              LPVOID lpDIBBits;



              if( bmInfo->bmiHeader.biBitCount > 8 )

                lpDIBBits = (bmInfo->bmiColors +

                  bmInfo->bmiHeader.biClrUsed) +

                    ((bmInfo->bmiHeader.biCompression == BI_BITFIELDS) ? 3 : 0);

              else

                lpDIBBits = bmInfo->bmiColors + nbColors;

                

              hdc = BeginPaint(hwnd, &ps);      



              if( hpal && (GetDeviceCaps(hdc,RASTERCAPS) & RC_PALETTE) )

                {

                 SelectPalette(hdc, hpal, FALSE);

                 RealizePalette(hdc);

                }              



              SetDIBitsToDevice(hdc,10,10,bmInfo->bmiHeader.biWidth,

                              bmInfo->bmiHeader.biHeight, 0, 0, 0,

                                 bmInfo->bmiHeader.biHeight, lpDIBBits, bmInfo,

                                                                DIB_RGB_COLORS);



              EndPaint(hwnd, &ps);



              return 0;

            }

V. Code complet

L'exemple pour rester simple n'effectue aucun test de validité. Il va de soi que dans un cas réel il faudra effectuer ces tests.

winmain.c
Sélectionnez
#include <windows.h>



LRESULT CALLBACK MainWndProc(HWND, UINT, WPARAM, LPARAM);



int WINAPI WinMain(HINSTANCE hinstance, HINSTANCE hPrevInstance,

                                                LPSTR lpCmdLine, int nCmdShow)

{

    HWND hwnd;

    MSG msg;

    WNDCLASS wc;



    wc.style = 0;

    wc.lpfnWndProc = MainWndProc;

    wc.cbClsExtra = 0;

    wc.cbWndExtra = 0;

    wc.hInstance = hinstance;

    wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);

    wc.hCursor = LoadCursor(NULL, IDC_ARROW);

    wc.hbrBackground = (HBRUSH)(1 + COLOR_BTNFACE);

    wc.lpszMenuName =  NULL;

    wc.lpszClassName = "MaWinClass";



    if(!RegisterClass(&wc)) return FALSE;



    hwnd = CreateWindow("MaWinClass", "Dessiner", WS_OVERLAPPEDWINDOW,

                                   CW_USEDEFAULT, CW_USEDEFAULT, 280, 240,

                                                   NULL, NULL, hinstance, NULL);

    if (!hwnd) return FALSE;



    ShowWindow(hwnd, nCmdShow);

    UpdateWindow(hwnd);





    while (GetMessage(&msg, NULL, 0, 0))

    {

        TranslateMessage(&msg);

        DispatchMessage(&msg);

    }

    return msg.wParam;

}

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



LRESULT CALLBACK MainWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)

{



    static LPVOID buffer;

    static BITMAPINFO *bmInfo;

    static UINT nbColors;

    static HPALETTE hpal;



    switch (uMsg)

    {

       case WM_CREATE :

            {

             HANDLE hf;

             DWORD FileSize,nbcharRead;

             BITMAPFILEHEADER bfh;



             hf = CreateFile("image.bmp", GENERIC_READ, 0,NULL,

                                    OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);



             FileSize = GetFileSize(hf, NULL);

             ReadFile(hf, &bfh, sizeof(bfh), &nbcharRead, NULL) ;



             buffer = GlobalAlloc(GMEM_FIXED, FileSize);

             ReadFile(hf, buffer, FileSize - sizeof(BITMAPFILEHEADER),

                                                             &nbcharRead, NULL);

             bmInfo = (BITMAPINFO*)buffer;

             nbColors = bmInfo->bmiHeader.biClrUsed ?

                                         bmInfo->bmiHeader.biClrUsed :

                                              1 << bmInfo->bmiHeader.biBitCount;



             if( nbColors <= 256 )

               {

                UINT i;

                UINT nSize = sizeof(LOGPALETTE) +

                                              (sizeof(PALETTEENTRY) * nbColors);



                LOGPALETTE *pLPal = (LOGPALETTE*) GlobalAlloc(GMEM_FIXED,nSize);

                pLPal->palVersion = 0x300;

                pLPal->palNumEntries = nbColors;

                for( i=0; i < nbColors; i++)

                 {

                  pLPal->palPalEntry[i].peRed = bmInfo->bmiColors[i].rgbRed;

                  pLPal->palPalEntry[i].peGreen = bmInfo->bmiColors[i].rgbGreen;

                  pLPal->palPalEntry[i].peBlue = bmInfo->bmiColors[i].rgbBlue;

                  pLPal->palPalEntry[i].peFlags = 0;

                 }

                hpal = CreatePalette(pLPal);

                GlobalFree(pLPal);

               }



             CloseHandle(hf);

             return 0;

            }



        case WM_PAINT :

            {

              HDC hdc;

              PAINTSTRUCT ps;

              LPVOID lpDIBBits;



              if( bmInfo->bmiHeader.biBitCount > 8 )

                lpDIBBits = (bmInfo->bmiColors +

                  bmInfo->bmiHeader.biClrUsed) +

                    ((bmInfo->bmiHeader.biCompression == BI_BITFIELDS) ? 3 : 0);

              else

                lpDIBBits = bmInfo->bmiColors + nbColors;

                

              hdc = BeginPaint(hwnd, &ps);      



              if( hpal && (GetDeviceCaps(hdc,RASTERCAPS) & RC_PALETTE) )

                {

                SelectPalette(hdc, hpal, FALSE);

                RealizePalette(hdc);

                }              



              SetDIBitsToDevice(hdc,10,10,bmInfo->bmiHeader.biWidth,

                              bmInfo->bmiHeader.biHeight, 0, 0, 0,

                                 bmInfo->bmiHeader.biHeight, lpDIBBits, bmInfo,

                                                                DIB_RGB_COLORS);



              EndPaint(hwnd, &ps);



              return 0;

            }



        case WM_DESTROY :

            GlobalFree(buffer);

            PostQuitMessage(0);

            return 0;



        default :

            return DefWindowProc(hwnd, uMsg, wParam, lParam);

    }

}

J'ai testé les compilations avec C++ Builder et DevC++.


À vos PC.

CGi

Sommaire

Vous avez aimé ce tutoriel ? Alors partagez-le en cliquant sur les boutons suivants : Viadeo Twitter Facebook Share on Google+   

C/C++
  Les pointeurs du C/C++.   Les listes chaînées.             Liste simple.             Liste triée.             Liste double.   Les arbres.   Les tas.   Le C orienté objets ?
  1 - La fenêtre principale.   2 - Contrôles et messages.   3 - Les commandes.   4 - Dialogue std.   5 - Contexte de périph.   6 - Dessiner.   7 - Les ressources.   8 - Dialogue perso.   9 - Dialogue comm.   10 - Les accélérateurs.
C++ BUILDER
  Trucs et astuces.   Composant.   TRichEdit.   TDrawGrid.   Application MDI.   TThread.   wxWidgets.   Style Win XP.
  Première application.   Construire un menu.   Dessiner.   Sisers, Timers...   Dialogues standards.   Dialogues perso.
DotNet
  Composant C# Builder.   Contrôle WinForm.   Application MDI.
  

Les sources présentées sur cette page sont libres de droits et vous pouvez les utiliser à votre convenance. Par contre, la page de présentation constitue une œuvre intellectuelle protégée par les droits d'auteur. Copyright © 2013 CGI. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.