Accueil > > > COMMENT AFFICHER DES BITMAPS AVEC DES OPTIONS
COMMENT AFFICHER DES BITMAPS AVEC DES OPTIONS
Information sur la source
Description
Il est facile d'afficher une bitmap. Maintenant il est parfois utile de dessinner une partie d'une bitmap, comme par exemple pour faire des bitmaps transparentes, bon ici j'ai pris l'exemple d'une loupe : on a une loupe et donc on veut afficher une bitmap loupe mais on ne veut pas que l'interieur et la contour de la bimtap loupe s'afficher a l'ecran.Donc voici une source qui permet de voir comment afficher des bimtaps avec quelques options ... vous pouvez choisir l'operation qui sera effectuee avec l'ecran (deux operations a choisir) je donne que le bout de code relatif a cela, le reste vous le trouverez dans les zip ... :)
Source
- //----------------------------------------------------------
- // BITMAP FUNCTION
- //----------------------------------------------------------
- // notre structure de notre bitmap
- // il y a toutes les informations necessaires pour effectuer
- // les operations voulues
- // bon voila a quoi correspondent les noms, les prefixes en disent long aussi ...
- // - Mem : memoire du resultat en bitmap
- // - Image : l'image que l'on veut afficher
- // - Mask : ceci est le mask (bitmap monochrome) pour identifier le fonc du devant (back/foreground)*
- // - Background : concerne le fond de l'image (a definir par une fonction lors de la creation de notre <BMP_AML>)
- // - Foreground : concerne le devant de l'image (si ce n'est pas du fond, c'est au devant)
- typedef struct tagMY_BITMAP_AML
- {
- // taille reelle de l'image
- int cxImage,
- cyImage;
- // taille a l'ecran de l'image
- int cx,
- cy;
- // tous les DC
- HDC hdcMem,
- hdcImage,
- hdcMask,
- hdcBackground,
- hdcForeground;
- // les handles de bitmap
- HBITMAP bmpMem,
- bmpImage,
- bmpMask,
- bmpBackground,
- bmpForeground;
- // on garde en memoire les anciennes bitmaps selectionnees dans les DC
- HBITMAP oldBmpMem,
- oldBmpImage,
- oldBmpMask,
- oldBmpBackground,
- oldBmpForeground;
- // on peut "verrouiller" l'affichage du fond ou du devant
- // cela peut sevir eventuellement pour faire de la transparence, et d'autres choses ...
- BOOL bLockBackground,
- bLockForeground;
- // les operations de dessin
- DWORD rasterOpBackground,rasterOpForeground;
- }MY_BITMAP_AML,*P_MY_BITMAP_AML,**PP_MY_BITMAP_AML;
- //----------------------------------------------------------
- // cette fonction cree un bitmap 'fait maison'
- // elle permetera de faire des operations dessus du genre transparence
- // pour cela la bitmap est le 'devant' de notre bitmap, cependant l'on doit
- // definir ou est le fond (ou par exemple la zone de transparence)
- // pour cela on doit donner une fonction qui dit si ce pixel appartient
- // au fond ou au devant de la bitmap
- // cette fonction peut choisir de definir une seule ou plusieurs
- // couleurs comme fond pour l'image
- // on a besoin aussi de l'<hdc> pour avoir des compatibleDCs
- P_MY_BITMAP_AML myCreateBitmapAml(HDC hdc,int cx,int cy,HBITMAP hBmp,int (*isForeground)(COLORREF))
- {
- int w,h; // width, height
- int i,j; // indices
- P_MY_BITMAP_AML bmpAml; // notre bitmap
- BITMAP infoBmp; // struture d'informations sur la bitmap
- BITMAPINFO paramBmp; // parametres de la bitmap <bmp>
- COLORREF *dataBmp; // zone de donnees de la bitmap <bmp>
- COLORREF *pLineBmp; // pointeur sur un element de <dataBmp>
- char *dataMask; // zone de donnees de la bitmap <maskBmp>
- char *pLineMask; // pointeur sur un element de <dataMask>
- int sizeLineAligned;// taille en octets d'un ligne pour <maskBmp> aligne sur 32 bits
- int sizeLine; // taille en octets d'un ligne pour <maskBmp>
-
- // on recupere les informations de la bitmaps
- if(0 == GetObject(hBmp,sizeof(BITMAP),(LPVOID)(&infoBmp)))
- {
- return NULL;
- }
- // on s'assure qu'il y a des couleurs du type COLORREF
- Assert(1 == infoBmp.bmPlanes);
- Assert(32 == infoBmp.bmBitsPixel);
- Assert(infoBmp.bmWidth == ((infoBmp.bmWidthBytes+3)/4));
-
- // on recupere la hauteur et la largeur
- w = infoBmp.bmWidth;
- h = infoBmp.bmHeight;
- // on alloue notre bitmap, puis on initialise ses champs
- bmpAml = Malloc(MY_BITMAP_AML,1);
- bmpAml->hdcImage = CreateCompatibleDC(hdc);
- bmpAml->bmpImage = hBmp;
- bmpAml->cxImage = w;
- bmpAml->cyImage = h;
- bmpAml->cx = cx;
- bmpAml->cy = cy;
- bmpAml->bLockBackground = FALSE; // par defaut, on affiche le fond
- bmpAml->bLockForeground = FALSE; // par defaut, on affiche le devant
- bmpAml->rasterOpBackground = SRCCOPY;
- bmpAml->rasterOpForeground = SRCCOPY;
-
- // maintenant on cree la bitmap de mask, i.e. qui determine
- // si le pixel appartient au fond ou au devant de l'image
- // c'est la fontion <isForeground> qui fait la sepration background/foreground
- // ATTENTION : sachant qu'il nous faut 2 octets pour 16 pixels, il faut
- // prevoir assez de place, voire plus, de memoire pour les pixels
- // c'est pourquoi il faut prendre le diviseur de 16 superieur au nombre de pixels sur une ligne
- // pour cela on ajoute 15 (=16-1) avant de diviser pas 16 (arrondie superieure)
- // (help : "Each scan line in the rectangle must be word aligned")
- sizeLineAligned = ((w + 15) >> 4) << 1; // <=> 2*( (w+15)/16 )
- sizeLine = (7 + w) >> 3; // <=> (7+w)/8
- dataMask = Malloc(char,sizeLineAligned*h);
-
- // on initialise pour recevoir les bits de <bmp>
- paramBmp.bmiHeader.biSize = sizeof(paramBmp.bmiHeader);
- paramBmp.bmiHeader.biWidth = w;
- paramBmp.bmiHeader.biHeight = -h; // ici la valeur opposee, est pour specifier que l'origine est en haut a gauche de la bitmap
- paramBmp.bmiHeader.biPlanes = infoBmp.bmPlanes;
- paramBmp.bmiHeader.biBitCount = infoBmp.bmBitsPixel; // on veut forcement une couleur du type COLORREF
- paramBmp.bmiHeader.biCompression = BI_RGB; // couleurs RGB, pas de compression
- paramBmp.bmiHeader.biSizeImage = w*h*sizeof(COLORREF);
- paramBmp.bmiHeader.biXPelsPerMeter = 1;
- paramBmp.bmiHeader.biYPelsPerMeter = 1;
- paramBmp.bmiHeader.biClrUsed = 0;
- paramBmp.bmiHeader.biClrImportant = 0;
- // on alloue une zone ou recevoir les octets
- dataBmp = (COLORREF*)Malloc(COLORREF,paramBmp.bmiHeader.biSizeImage);
- // on peut maintenant recevoir les informations
- // i.e. on recupere les couleurs de la bitmap en type COLORREF (32 bits)
- if(0 == GetDIBits(hdc,hBmp,0,h,dataBmp,¶mBmp,DIB_RGB_COLORS))
- {
- Error(("GetDIBits n'a pas marche"));
- }
-
- // on decremente <pBmp> pour incerementer directement plus tard
- pLineBmp = dataBmp - 1;
- pLineMask = dataMask;
- // on commence la boucle
- // on y va, c'est fastidieux, mais il faut le faire une fois pour toute
- for(i=0;i<h;i++)
- {
- COLORREF *pBmp;
- char *pMask;
-
- pBmp = pLineBmp;
- pMask = pLineMask;
- // ici on doit remplir octets par octets (seulement les octets a remplir totatelement)
- for(j=0;j<w/8;j++)
- {
- char byte;
- // on traite 8 pixels par iteration
- byte = (char)
- (
- ((isForeground(*++pBmp) != 0) << 7)
- |
- ((isForeground(*++pBmp) != 0) << 6)
- |
- ((isForeground(*++pBmp) != 0) << 5)
- |
- ((isForeground(*++pBmp) != 0) << 4)
- |
- ((isForeground(*++pBmp) != 0) << 3)
- |
- ((isForeground(*++pBmp) != 0) << 2)
- |
- ((isForeground(*++pBmp) != 0) << 1)
- |
- ((isForeground(*++pBmp) != 0) << 0)
- );
- // on l'enregistre dans <pMask>
- *pMask = byte;
- // au pixel suivant !
- pMask ++;
- }
- // ici on remplit les pixels qui ne sont pas completement remplis (donc cela va de 0 a 7 pixels)
- // rappel : w & 7 <=> w % 8
- if(w & 7) // si il n'y a pas un multiple de 8 en largeur
- {
- *pMask = 0;
- for(j=7;j>=7-(w&7);j--)
- {
- (*pMask) |= ((isForeground(*++pBmp) != 0) << j);
- }
- pMask ++;
- }
-
- // ligne suivante
- pLineMask += sizeLineAligned;
- pLineBmp += infoBmp.bmWidthBytes/sizeof(COLORREF);
- }
- // on n'a plus qu'a cree notre bitmap de transparence
- bmpAml->bmpMask = CreateBitmap(
- w, // taille identique a <bmp> ...
- h, // ... car on a un 0/1 pour chaque pixel de <bmp>
- 1, // c'est pour que la bitmap soit monochrome
- 1, // il nous faut un bit par pixel, car c'est monochrome, donc 0 ou 1
- (void*)dataMask // le paquet de bits, donc de pixels
- );
- Assert(NULL != bmpAml->bmpMask);
- // on a eu besoin de <dataMask> et de <dataBmp> juste pour initialiser les pixels
- // on peut et on doit maintenant les liberer
- Free(dataBmp);
- Free(dataMask);
- // on peut enfin selectionner la bitmap dans notre compatibileDC
- // si on ne peut pas recevoir nos informations (Help : "The bitmap identified by the hbmp parameter must not be selected into a device context when the application calls this function.")
- bmpAml->oldBmpImage = SelectObject(bmpAml->hdcImage,hBmp);
- // bon on a tous les champs de la structure a initialiser
- // il faut creer et selectionner des bitmaps dans les DCs <hdcBackground> et <hdcForeground>
- // car il en fiat pour subir les operations GDI genre <BitBlt> ou <StretchBlt>
-
- // pour Mask
- bmpAml->hdcMask = CreateCompatibleDC(hdc);
- Assert(NULL != bmpAml->hdcMask);
- bmpAml->oldBmpMask = (HBITMAP)SelectObject(bmpAml->hdcMask,bmpAml->bmpMask);
- // pour Mem
- bmpAml->hdcMem = CreateCompatibleDC(hdc);
- Assert(NULL != bmpAml->hdcMem);
- bmpAml->bmpMem = CreateCompatibleBitmap(hdc,cx,cy);
- Assert(NULL != bmpAml->bmpMem);
- bmpAml->oldBmpMem = (HBITMAP)SelectObject(bmpAml->hdcMem,bmpAml->bmpMem);
- // pour Background
- bmpAml->hdcBackground = CreateCompatibleDC(hdc);
- Assert(NULL != bmpAml->hdcBackground);
- bmpAml->bmpBackground = CreateCompatibleBitmap(hdc,cx,cy);
- Assert(NULL != bmpAml->bmpBackground);
- bmpAml->oldBmpBackground = (HBITMAP)SelectObject(bmpAml->hdcBackground,bmpAml->bmpBackground);
- // pour Foreground
- bmpAml->hdcForeground = CreateCompatibleDC(hdc);
- Assert(NULL != bmpAml->hdcForeground);
- bmpAml->bmpForeground = CreateCompatibleBitmap(hdc,cx,cy);
- Assert(NULL != bmpAml->bmpForeground);
- bmpAml->oldBmpForeground = (HBITMAP)SelectObject(bmpAml->hdcForeground,bmpAml->bmpForeground);
- // on a fini le boulot de l'initialisation
- return bmpAml;
- } // myCreateBitmapAml()
- //----------------------------------------------------------
- // remet l'ancienne bitmap et supprimer si cela est demander celle courant
- // puis detruit le DC
- void myCleanDC(HDC hdc,HBITMAP old,BOOL bDestroyBmp)
- {
- HBITMAP bmp;
- // on remet la bonne bitmap
- bmp = SelectObject(hdc,old);
- // on detruit la bitmap
- // si on nous demande de faire ce boulot
- if(bDestroyBmp)
- {
- DeleteObject(bmp);
- }
- // puis enfin on detruit le DC
- DeleteDC(hdc);
- } // myCleanDC()
- // cette fonction detruit un bitmap sans detruire la bitmap 'source' ou 'fille'
- // qui a ete donnee par le fonction <myCreateBitmapAml>
- HBITMAP myDeleteBitmapAml(P_MY_BITMAP_AML bmpAml)
- {
- HBITMAP hBmp;
- // on sauve la veritable bitmap, que l'on doit retourner
- hBmp = bmpAml->bmpImage;
-
- // bon maintenant on supprimer les DC, mais avant cele on reselectionne
- // les anciennes bitmaps, et on supprimera les courantes (sauf <bmpImage>)
- myCleanDC(bmpAml->hdcImage ,bmpAml->bmpImage ,FALSE );
- myCleanDC(bmpAml->hdcMem ,bmpAml->bmpMem ,TRUE );
- myCleanDC(bmpAml->hdcMask ,bmpAml->bmpMask ,TRUE );
- myCleanDC(bmpAml->hdcBackground ,bmpAml->bmpBackground ,TRUE );
- myCleanDC(bmpAml->hdcForeground ,bmpAml->bmpForeground ,TRUE );
- // et enfin on detruit l'allocation memoire
- Free(bmpAml);
- return hBmp;
- } // myDeleteBitmapAml()
- //----------------------------------------------------------
- // premet de changer l'operation de dessin
- // on retourne l'ancien oparateur et on selectionne le nouveau
- DWORD myChangeRasterOpBackground(P_MY_BITMAP_AML bmpAml,DWORD rasterOp)
- {
- DWORD old;
- old = bmpAml->rasterOpBackground;
- bmpAml->rasterOpBackground = rasterOp;
- return old;
- } // myChangeRasterOpBackground()
- //----------------------------------------------------------
- // premet de changer l'operation de dessin
- // on retourne l'ancien oparateur et on selectionne le nouveau
- DWORD myChangeRasterOpForeground(P_MY_BITMAP_AML bmpAml,DWORD rasterOp)
- {
- DWORD old;
- old = bmpAml->rasterOpForeground;
- bmpAml->rasterOpForeground = rasterOp;
- return old;
- } // myChangeRasterOpForeground()
- //----------------------------------------------------------
- // permet de verrouiller ou non le fond de la bitmap
- // <bLock> doit valoir TRUE si oui, sinon FALSE
- // de plus cette fonction retourne l'ancienne valeur
- BOOL myLockBackground(P_MY_BITMAP_AML bmpAml,BOOL bLock)
- {
- BOOL old;
- old = bmpAml->bLockBackground;
- bmpAml->bLockBackground = bLock;
- return old;
- } // myLockBackGround()
- //----------------------------------------------------------
- // permet de verrouiller ou non le devant de la bitmap
- // <bLock> doit valoir TRUE si oui, sinon FALSE
- // de plus cette fonction retourne l'ancienne valeur
- BOOL myLockForeground(P_MY_BITMAP_AML bmpAml,BOOL bLock)
- {
- BOOL old;
- old = bmpAml->bLockForeground;
- bmpAml->bLockForeground = bLock;
- return old;
- } // myLockForeGround()
- //----------------------------------------------------------
- // on fait nos calculs dans des DCs intermediaires
- // on affiche que le resultat final dans <hdcMem> pour avoir un
- // meilleur rendu visuel, car il ne faut pas effectuer un operation
- // sur un DC a l'ecran (cligonotement, problemes de raifraichissement, ...)
- BOOL WINAPI myRecalcBitmapAml(HDC hdc,int x,int y,P_MY_BITMAP_AML bmpAml)
- {
- BOOL success,lockBackground,lockForeground;
- HDC hdcMem,hdcImage,hdcMask,hdcBackground,hdcForeground;
- DWORD dwRopForeground,dwRopBackground;
- int w,h,cx,cy;
- // on prend tous les HDC utiles
- hdcMem = bmpAml->hdcMem;
- hdcImage = bmpAml->hdcImage;
- hdcMask = bmpAml->hdcMask;
- hdcBackground = bmpAml->hdcBackground;
- hdcForeground = bmpAml->hdcForeground;
- // on prend les verrouillage
- lockBackground = bmpAml->bLockBackground;
- lockForeground = bmpAml->bLockForeground;
- // on recupere la taille
- w = bmpAml->cxImage;
- h = bmpAml->cyImage;
- cx = bmpAml->cx;
- cy = bmpAml->cy;
- // les raster ops
- dwRopBackground = bmpAml->rasterOpBackground;
- dwRopForeground = bmpAml->rasterOpForeground;
- // pour les valeurs de retours de tout les <BitBlt>
- success = TRUE;
- // on commence a faire notre tres lourde operation (8 BitBlt au maximum !!)
- // on gere le fond
-
- success &= BitBlt (hdcBackground , 0, 0, cx, cy, hdc , x, y, SRCCOPY);
- if(!lockBackground) success &= StretchBlt (hdcBackground , 0, 0, cx, cy, hdcImage , 0, 0, w, h, dwRopBackground);
- success &= StretchBlt (hdcBackground , 0, 0, cx, cy, hdcMask , 0, 0, w, h, 0x00220326); // <=> hdcBackGround & (~hdcMask)
- // on gere le devant
- success &= BitBlt (hdcForeground , 0, 0, cx, cy, hdc , x, y, SRCCOPY);
- if(!lockForeground) success &= StretchBlt (hdcForeground , 0, 0, cx, cy, hdcImage , 0, 0, w, h, dwRopForeground);
- success &= StretchBlt (hdcForeground , 0, 0, cx, cy, hdcMask , 0, 0, w, h, SRCAND);
- // on fusionne le devant au fond
- success &= BitBlt (hdcMem , 0, 0, cx, cy, hdcForeground , 0, 0, SRCCOPY);
- success &= BitBlt (hdcMem , 0, 0, cx, cy, hdcBackground , 0, 0, SRCPAINT);
- // on a fini le boulot, on retourne TRUE si tout c'est bien passe sinon FALSE
- return success;
- } // myRecalcBitmapAml()
- //----------------------------------------------------------
- BOOL WINAPI myDrawBitmapAml(HDC hdc,int x,int y,P_MY_BITMAP_AML bmpAml)
- {
- int cx,cy;
- HDC hdcMem;
- // on prend le <hdcMem>
- hdcMem = bmpAml->hdcMem;
- // on recupere la taille
- cx = bmpAml->cx;
- cy = bmpAml->cy;
- // et on affiche
- return BitBlt(hdc,x,y,cx,cy,hdcMem,0,0,SRCCOPY);
- } // myDrawBitmapAml()
- //----------------------------------------------------------
- // cette fonction definie le blanc comme etant la seule couleur du fond
- int whiteBackground(COLORREF color)
- {
- return color - RGB(255,255,255);
- } // whiteBackground()
//----------------------------------------------------------
// BITMAP FUNCTION
//----------------------------------------------------------
// notre structure de notre bitmap
// il y a toutes les informations necessaires pour effectuer
// les operations voulues
// bon voila a quoi correspondent les noms, les prefixes en disent long aussi ...
// - Mem : memoire du resultat en bitmap
// - Image : l'image que l'on veut afficher
// - Mask : ceci est le mask (bitmap monochrome) pour identifier le fonc du devant (back/foreground)*
// - Background : concerne le fond de l'image (a definir par une fonction lors de la creation de notre <BMP_AML>)
// - Foreground : concerne le devant de l'image (si ce n'est pas du fond, c'est au devant)
typedef struct tagMY_BITMAP_AML
{
// taille reelle de l'image
int cxImage,
cyImage;
// taille a l'ecran de l'image
int cx,
cy;
// tous les DC
HDC hdcMem,
hdcImage,
hdcMask,
hdcBackground,
hdcForeground;
// les handles de bitmap
HBITMAP bmpMem,
bmpImage,
bmpMask,
bmpBackground,
bmpForeground;
// on garde en memoire les anciennes bitmaps selectionnees dans les DC
HBITMAP oldBmpMem,
oldBmpImage,
oldBmpMask,
oldBmpBackground,
oldBmpForeground;
// on peut "verrouiller" l'affichage du fond ou du devant
// cela peut sevir eventuellement pour faire de la transparence, et d'autres choses ...
BOOL bLockBackground,
bLockForeground;
// les operations de dessin
DWORD rasterOpBackground,rasterOpForeground;
}MY_BITMAP_AML,*P_MY_BITMAP_AML,**PP_MY_BITMAP_AML;
//----------------------------------------------------------
// cette fonction cree un bitmap 'fait maison'
// elle permetera de faire des operations dessus du genre transparence
// pour cela la bitmap est le 'devant' de notre bitmap, cependant l'on doit
// definir ou est le fond (ou par exemple la zone de transparence)
// pour cela on doit donner une fonction qui dit si ce pixel appartient
// au fond ou au devant de la bitmap
// cette fonction peut choisir de definir une seule ou plusieurs
// couleurs comme fond pour l'image
// on a besoin aussi de l'<hdc> pour avoir des compatibleDCs
P_MY_BITMAP_AML myCreateBitmapAml(HDC hdc,int cx,int cy,HBITMAP hBmp,int (*isForeground)(COLORREF))
{
int w,h; // width, height
int i,j; // indices
P_MY_BITMAP_AML bmpAml; // notre bitmap
BITMAP infoBmp; // struture d'informations sur la bitmap
BITMAPINFO paramBmp; // parametres de la bitmap <bmp>
COLORREF *dataBmp; // zone de donnees de la bitmap <bmp>
COLORREF *pLineBmp; // pointeur sur un element de <dataBmp>
char *dataMask; // zone de donnees de la bitmap <maskBmp>
char *pLineMask; // pointeur sur un element de <dataMask>
int sizeLineAligned;// taille en octets d'un ligne pour <maskBmp> aligne sur 32 bits
int sizeLine; // taille en octets d'un ligne pour <maskBmp>
// on recupere les informations de la bitmaps
if(0 == GetObject(hBmp,sizeof(BITMAP),(LPVOID)(&infoBmp)))
{
return NULL;
}
// on s'assure qu'il y a des couleurs du type COLORREF
Assert(1 == infoBmp.bmPlanes);
Assert(32 == infoBmp.bmBitsPixel);
Assert(infoBmp.bmWidth == ((infoBmp.bmWidthBytes+3)/4));
// on recupere la hauteur et la largeur
w = infoBmp.bmWidth;
h = infoBmp.bmHeight;
// on alloue notre bitmap, puis on initialise ses champs
bmpAml = Malloc(MY_BITMAP_AML,1);
bmpAml->hdcImage = CreateCompatibleDC(hdc);
bmpAml->bmpImage = hBmp;
bmpAml->cxImage = w;
bmpAml->cyImage = h;
bmpAml->cx = cx;
bmpAml->cy = cy;
bmpAml->bLockBackground = FALSE; // par defaut, on affiche le fond
bmpAml->bLockForeground = FALSE; // par defaut, on affiche le devant
bmpAml->rasterOpBackground = SRCCOPY;
bmpAml->rasterOpForeground = SRCCOPY;
// maintenant on cree la bitmap de mask, i.e. qui determine
// si le pixel appartient au fond ou au devant de l'image
// c'est la fontion <isForeground> qui fait la sepration background/foreground
// ATTENTION : sachant qu'il nous faut 2 octets pour 16 pixels, il faut
// prevoir assez de place, voire plus, de memoire pour les pixels
// c'est pourquoi il faut prendre le diviseur de 16 superieur au nombre de pixels sur une ligne
// pour cela on ajoute 15 (=16-1) avant de diviser pas 16 (arrondie superieure)
// (help : "Each scan line in the rectangle must be word aligned")
sizeLineAligned = ((w + 15) >> 4) << 1; // <=> 2*( (w+15)/16 )
sizeLine = (7 + w) >> 3; // <=> (7+w)/8
dataMask = Malloc(char,sizeLineAligned*h);
// on initialise pour recevoir les bits de <bmp>
paramBmp.bmiHeader.biSize = sizeof(paramBmp.bmiHeader);
paramBmp.bmiHeader.biWidth = w;
paramBmp.bmiHeader.biHeight = -h; // ici la valeur opposee, est pour specifier que l'origine est en haut a gauche de la bitmap
paramBmp.bmiHeader.biPlanes = infoBmp.bmPlanes;
paramBmp.bmiHeader.biBitCount = infoBmp.bmBitsPixel; // on veut forcement une couleur du type COLORREF
paramBmp.bmiHeader.biCompression = BI_RGB; // couleurs RGB, pas de compression
paramBmp.bmiHeader.biSizeImage = w*h*sizeof(COLORREF);
paramBmp.bmiHeader.biXPelsPerMeter = 1;
paramBmp.bmiHeader.biYPelsPerMeter = 1;
paramBmp.bmiHeader.biClrUsed = 0;
paramBmp.bmiHeader.biClrImportant = 0;
// on alloue une zone ou recevoir les octets
dataBmp = (COLORREF*)Malloc(COLORREF,paramBmp.bmiHeader.biSizeImage);
// on peut maintenant recevoir les informations
// i.e. on recupere les couleurs de la bitmap en type COLORREF (32 bits)
if(0 == GetDIBits(hdc,hBmp,0,h,dataBmp,¶mBmp,DIB_RGB_COLORS))
{
Error(("GetDIBits n'a pas marche"));
}
// on decremente <pBmp> pour incerementer directement plus tard
pLineBmp = dataBmp - 1;
pLineMask = dataMask;
// on commence la boucle
// on y va, c'est fastidieux, mais il faut le faire une fois pour toute
for(i=0;i<h;i++)
{
COLORREF *pBmp;
char *pMask;
pBmp = pLineBmp;
pMask = pLineMask;
// ici on doit remplir octets par octets (seulement les octets a remplir totatelement)
for(j=0;j<w/8;j++)
{
char byte;
// on traite 8 pixels par iteration
byte = (char)
(
((isForeground(*++pBmp) != 0) << 7)
|
((isForeground(*++pBmp) != 0) << 6)
|
((isForeground(*++pBmp) != 0) << 5)
|
((isForeground(*++pBmp) != 0) << 4)
|
((isForeground(*++pBmp) != 0) << 3)
|
((isForeground(*++pBmp) != 0) << 2)
|
((isForeground(*++pBmp) != 0) << 1)
|
((isForeground(*++pBmp) != 0) << 0)
);
// on l'enregistre dans <pMask>
*pMask = byte;
// au pixel suivant !
pMask ++;
}
// ici on remplit les pixels qui ne sont pas completement remplis (donc cela va de 0 a 7 pixels)
// rappel : w & 7 <=> w % 8
if(w & 7) // si il n'y a pas un multiple de 8 en largeur
{
*pMask = 0;
for(j=7;j>=7-(w&7);j--)
{
(*pMask) |= ((isForeground(*++pBmp) != 0) << j);
}
pMask ++;
}
// ligne suivante
pLineMask += sizeLineAligned;
pLineBmp += infoBmp.bmWidthBytes/sizeof(COLORREF);
}
// on n'a plus qu'a cree notre bitmap de transparence
bmpAml->bmpMask = CreateBitmap(
w, // taille identique a <bmp> ...
h, // ... car on a un 0/1 pour chaque pixel de <bmp>
1, // c'est pour que la bitmap soit monochrome
1, // il nous faut un bit par pixel, car c'est monochrome, donc 0 ou 1
(void*)dataMask // le paquet de bits, donc de pixels
);
Assert(NULL != bmpAml->bmpMask);
// on a eu besoin de <dataMask> et de <dataBmp> juste pour initialiser les pixels
// on peut et on doit maintenant les liberer
Free(dataBmp);
Free(dataMask);
// on peut enfin selectionner la bitmap dans notre compatibileDC
// si on ne peut pas recevoir nos informations (Help : "The bitmap identified by the hbmp parameter must not be selected into a device context when the application calls this function.")
bmpAml->oldBmpImage = SelectObject(bmpAml->hdcImage,hBmp);
// bon on a tous les champs de la structure a initialiser
// il faut creer et selectionner des bitmaps dans les DCs <hdcBackground> et <hdcForeground>
// car il en fiat pour subir les operations GDI genre <BitBlt> ou <StretchBlt>
// pour Mask
bmpAml->hdcMask = CreateCompatibleDC(hdc);
Assert(NULL != bmpAml->hdcMask);
bmpAml->oldBmpMask = (HBITMAP)SelectObject(bmpAml->hdcMask,bmpAml->bmpMask);
// pour Mem
bmpAml->hdcMem = CreateCompatibleDC(hdc);
Assert(NULL != bmpAml->hdcMem);
bmpAml->bmpMem = CreateCompatibleBitmap(hdc,cx,cy);
Assert(NULL != bmpAml->bmpMem);
bmpAml->oldBmpMem = (HBITMAP)SelectObject(bmpAml->hdcMem,bmpAml->bmpMem);
// pour Background
bmpAml->hdcBackground = CreateCompatibleDC(hdc);
Assert(NULL != bmpAml->hdcBackground);
bmpAml->bmpBackground = CreateCompatibleBitmap(hdc,cx,cy);
Assert(NULL != bmpAml->bmpBackground);
bmpAml->oldBmpBackground = (HBITMAP)SelectObject(bmpAml->hdcBackground,bmpAml->bmpBackground);
// pour Foreground
bmpAml->hdcForeground = CreateCompatibleDC(hdc);
Assert(NULL != bmpAml->hdcForeground);
bmpAml->bmpForeground = CreateCompatibleBitmap(hdc,cx,cy);
Assert(NULL != bmpAml->bmpForeground);
bmpAml->oldBmpForeground = (HBITMAP)SelectObject(bmpAml->hdcForeground,bmpAml->bmpForeground);
// on a fini le boulot de l'initialisation
return bmpAml;
} // myCreateBitmapAml()
//----------------------------------------------------------
// remet l'ancienne bitmap et supprimer si cela est demander celle courant
// puis detruit le DC
void myCleanDC(HDC hdc,HBITMAP old,BOOL bDestroyBmp)
{
HBITMAP bmp;
// on remet la bonne bitmap
bmp = SelectObject(hdc,old);
// on detruit la bitmap
// si on nous demande de faire ce boulot
if(bDestroyBmp)
{
DeleteObject(bmp);
}
// puis enfin on detruit le DC
DeleteDC(hdc);
} // myCleanDC()
// cette fonction detruit un bitmap sans detruire la bitmap 'source' ou 'fille'
// qui a ete donnee par le fonction <myCreateBitmapAml>
HBITMAP myDeleteBitmapAml(P_MY_BITMAP_AML bmpAml)
{
HBITMAP hBmp;
// on sauve la veritable bitmap, que l'on doit retourner
hBmp = bmpAml->bmpImage;
// bon maintenant on supprimer les DC, mais avant cele on reselectionne
// les anciennes bitmaps, et on supprimera les courantes (sauf <bmpImage>)
myCleanDC(bmpAml->hdcImage ,bmpAml->bmpImage ,FALSE );
myCleanDC(bmpAml->hdcMem ,bmpAml->bmpMem ,TRUE );
myCleanDC(bmpAml->hdcMask ,bmpAml->bmpMask ,TRUE );
myCleanDC(bmpAml->hdcBackground ,bmpAml->bmpBackground ,TRUE );
myCleanDC(bmpAml->hdcForeground ,bmpAml->bmpForeground ,TRUE );
// et enfin on detruit l'allocation memoire
Free(bmpAml);
return hBmp;
} // myDeleteBitmapAml()
//----------------------------------------------------------
// premet de changer l'operation de dessin
// on retourne l'ancien oparateur et on selectionne le nouveau
DWORD myChangeRasterOpBackground(P_MY_BITMAP_AML bmpAml,DWORD rasterOp)
{
DWORD old;
old = bmpAml->rasterOpBackground;
bmpAml->rasterOpBackground = rasterOp;
return old;
} // myChangeRasterOpBackground()
//----------------------------------------------------------
// premet de changer l'operation de dessin
// on retourne l'ancien oparateur et on selectionne le nouveau
DWORD myChangeRasterOpForeground(P_MY_BITMAP_AML bmpAml,DWORD rasterOp)
{
DWORD old;
old = bmpAml->rasterOpForeground;
bmpAml->rasterOpForeground = rasterOp;
return old;
} // myChangeRasterOpForeground()
//----------------------------------------------------------
// permet de verrouiller ou non le fond de la bitmap
// <bLock> doit valoir TRUE si oui, sinon FALSE
// de plus cette fonction retourne l'ancienne valeur
BOOL myLockBackground(P_MY_BITMAP_AML bmpAml,BOOL bLock)
{
BOOL old;
old = bmpAml->bLockBackground;
bmpAml->bLockBackground = bLock;
return old;
} // myLockBackGround()
//----------------------------------------------------------
// permet de verrouiller ou non le devant de la bitmap
// <bLock> doit valoir TRUE si oui, sinon FALSE
// de plus cette fonction retourne l'ancienne valeur
BOOL myLockForeground(P_MY_BITMAP_AML bmpAml,BOOL bLock)
{
BOOL old;
old = bmpAml->bLockForeground;
bmpAml->bLockForeground = bLock;
return old;
} // myLockForeGround()
//----------------------------------------------------------
// on fait nos calculs dans des DCs intermediaires
// on affiche que le resultat final dans <hdcMem> pour avoir un
// meilleur rendu visuel, car il ne faut pas effectuer un operation
// sur un DC a l'ecran (cligonotement, problemes de raifraichissement, ...)
BOOL WINAPI myRecalcBitmapAml(HDC hdc,int x,int y,P_MY_BITMAP_AML bmpAml)
{
BOOL success,lockBackground,lockForeground;
HDC hdcMem,hdcImage,hdcMask,hdcBackground,hdcForeground;
DWORD dwRopForeground,dwRopBackground;
int w,h,cx,cy;
// on prend tous les HDC utiles
hdcMem = bmpAml->hdcMem;
hdcImage = bmpAml->hdcImage;
hdcMask = bmpAml->hdcMask;
hdcBackground = bmpAml->hdcBackground;
hdcForeground = bmpAml->hdcForeground;
// on prend les verrouillage
lockBackground = bmpAml->bLockBackground;
lockForeground = bmpAml->bLockForeground;
// on recupere la taille
w = bmpAml->cxImage;
h = bmpAml->cyImage;
cx = bmpAml->cx;
cy = bmpAml->cy;
// les raster ops
dwRopBackground = bmpAml->rasterOpBackground;
dwRopForeground = bmpAml->rasterOpForeground;
// pour les valeurs de retours de tout les <BitBlt>
success = TRUE;
// on commence a faire notre tres lourde operation (8 BitBlt au maximum !!)
// on gere le fond
success &= BitBlt (hdcBackground , 0, 0, cx, cy, hdc , x, y, SRCCOPY);
if(!lockBackground) success &= StretchBlt (hdcBackground , 0, 0, cx, cy, hdcImage , 0, 0, w, h, dwRopBackground);
success &= StretchBlt (hdcBackground , 0, 0, cx, cy, hdcMask , 0, 0, w, h, 0x00220326); // <=> hdcBackGround & (~hdcMask)
// on gere le devant
success &= BitBlt (hdcForeground , 0, 0, cx, cy, hdc , x, y, SRCCOPY);
if(!lockForeground) success &= StretchBlt (hdcForeground , 0, 0, cx, cy, hdcImage , 0, 0, w, h, dwRopForeground);
success &= StretchBlt (hdcForeground , 0, 0, cx, cy, hdcMask , 0, 0, w, h, SRCAND);
// on fusionne le devant au fond
success &= BitBlt (hdcMem , 0, 0, cx, cy, hdcForeground , 0, 0, SRCCOPY);
success &= BitBlt (hdcMem , 0, 0, cx, cy, hdcBackground , 0, 0, SRCPAINT);
// on a fini le boulot, on retourne TRUE si tout c'est bien passe sinon FALSE
return success;
} // myRecalcBitmapAml()
//----------------------------------------------------------
BOOL WINAPI myDrawBitmapAml(HDC hdc,int x,int y,P_MY_BITMAP_AML bmpAml)
{
int cx,cy;
HDC hdcMem;
// on prend le <hdcMem>
hdcMem = bmpAml->hdcMem;
// on recupere la taille
cx = bmpAml->cx;
cy = bmpAml->cy;
// et on affiche
return BitBlt(hdc,x,y,cx,cy,hdcMem,0,0,SRCCOPY);
} // myDrawBitmapAml()
//----------------------------------------------------------
// cette fonction definie le blanc comme etant la seule couleur du fond
int whiteBackground(COLORREF color)
{
return color - RGB(255,255,255);
} // whiteBackground()
Conclusion
Bon j'aurais pu autiliser la fonction MaskBlt, le petit probleme c'est que sous Win98 ca ne marche pas, il faut se la reprogrammer, c'est long (c'est pourquoi ca clignote)
Sources du même auteur
Sources de la même categorie
Commentaires et avis
|
Derniers Blogs
IMAGINE CUP 2012, MAKE A SIGN EN FINALEIMAGINE CUP 2012, MAKE A SIGN EN FINALE par junarnoalg
Voilà qui est fait, la nouvelle est officielle ! L'équipe belge "Make a Sign" va au pays des kangourous défendre son projet dans la catégorie Software Design. http://www.imaginecup.com/CompetitionsContent/Competition/WorldwideFinalists.aspx V...
Cliquez pour lire la suite de l'article par junarnoalg KINECT 1.5 IS OUT !KINECT 1.5 IS OUT ! par Vko
La version 1.5 du Kinect For Microsoft vient tout juste de sortir ! Plein de nouveautés: Tracking de squelette en Near Mode Détection en position assise Détection faciale avec un SDK dédié Documentation et des guideline (enfin) Un out...
Cliquez pour lire la suite de l'article par Vko LES ACTUALITéS DE LA SEMAINE SUR C2I.FR (14 MAI - 20 MAI) LES ACTUALITéS DE LA SEMAINE SUR C2I.FR (14 MAI - 20 MAI) par richardc
Mise à jour des Web API du 14 Mai
Réservez dès maintenant votre journée du 20 juin pour le Windows Azure Dev Camp 2012 à Paris
Mise à jour de Team Foundation Service
MechCommander 2 sur Windows 8
Entity Framework 5 Release Candidate e...
Cliquez pour lire la suite de l'article par richardc REACTIVE EXTENSIONS : CONSOMMER DES SERVICES AVEC RX PARTIE 3, LES PIèGES à éVITERREACTIVE EXTENSIONS : CONSOMMER DES SERVICES AVEC RX PARTIE 3, LES PIèGES à éVITER par Groc
Une mauvaise utilisation de rx lors de l'écriture d'une couche d'accès à des services peut conduire à des cas embarassants avec des erreurs mal gérées, des appels qui ne partent lorsqu'ils le devraient, et même des résultats incorrects . le tout nuis...
Cliquez pour lire la suite de l'article par Groc SHAREPOINT BLOG SITE, PROBLèME D'ARCHIVESSHAREPOINT BLOG SITE, PROBLèME D'ARCHIVES par junarnoalg
Dernièrement, nous avons migré le site
myTIC
vers un nouveau serveur SharePoint 2010. Dans les contenus que nous vouloins récupérer, nous avions un certain nombre de blogs.
Nous avons utilisé les commandes Power...
Cliquez pour lire la suite de l'article par junarnoalg
Forum
MATRICE TEMPLATEMATRICE TEMPLATE par hjr2610
Cliquez pour lire la suite par hjr2610 RE : SAC A DOS RE : SAC A DOS par hadjkaddour
Cliquez pour lire la suite par hadjkaddour
Logiciels
sDEVIS-FACTURES vlPRO (8.1.0.3)SDEVIS-FACTURES VLPRO (8.1.0.3)sDEVIS-FACTURES vlPRO a été mis au point pour les particuliers, créateurs, entrepreneurs, artisa... Cliquez pour télécharger sDEVIS-FACTURES vlPRO 974 Application Server (12.2.4.6)974 APPLICATION SERVER (12.2.4.6)Développez de puissantes applications dans un environnement de 'cloud computing', clusterisé, séc... Cliquez pour télécharger 974 Application Server vPicture (1.4.2.1)VPICTURE (1.4.2.1)Avec vPicture, hébergez vos images facilement et rapidement.
vPicture est un utilitaire simple, ... Cliquez pour télécharger vPicture Easy-Planning (2.2.1.6)EASY-PLANNING (2.2.1.6)Easy-Planning permet de créer des plannings sous la représentation de diagrammes et est adapté au... Cliquez pour télécharger Easy-Planning COM-BACKUP (2.0)COM-BACKUP (2.0)
COM-BACKUP est un logiciel de sauvegarde qui permet de planifier les sauvegardes de vos dossiers ...
Cliquez pour télécharger COM-BACKUP
|