Combinaisons de bitmaps

Description

programme generique :
calcul une bitmap a partir de deux bitmaps sources (dans l'exemple un quadrillage colore et une smiley) avec des fonctions pour definir l'operation suivant les composantes Rouge,Vert,et Bleu.

ici le programme montre un mixte des deux images suivants un poucentage.
les touches sont : 'a' pour augmenter le poucentage de rouge de la premier image.
'q' pour diminuer le poucentage de rouge de la premier image.
ect ... ('z' et 's' pour le vert, et 'e' et 'd' pour le bleu).

Toutes les informations sont dans la status bar (bar en bas de l'ecran)

Source / Exemple :


#ifndef _UTIL_H_
	#include "util.h"
#endif // _UTIL_H_

#ifndef _MATH_H_
	#include "math.h"
#endif // _MATH_H_

#ifndef _LIST_H_
	#include "list.h"
#endif // _LIST_H_

#ifndef _WINUTIL_H_
	#include "winutil.h"
#endif // _WINUTIL_H_

#include "resource.h"

//-------------------------------------------------
#define WM_USER_COMBIN_DELETE       (WM_USER + 1)
#define WM_USER_COMBIN_CREATE       (WM_USER + 2)

//-------------------------------------------------
// COMBIN BMP
//-------------------------------------------------
BOOL CombinBmp(P_MY_HDC hdc,SIZE *pInfo,COLORREF *dataBitmap1,COLORREF *dataBitmap2,BYTE funcR(int i,int j,BYTE r1,BYTE r2,void *param),BYTE funcG(int i,int j,BYTE g1,BYTE g2,void *param),BYTE funcB(int i,int j,BYTE b1,BYTE b2,BYTE *param),void *param)
{
HBITMAP     hBmp;
COLORREF    *data,*pDest,*p1,*p2;
int         i,j,n;
struct {BITMAPINFO bmih;RGBQUAD colors[2];}
          bmpInfo;

n     = pInfo->cx*pInfo->cy;
data  = Malloc(COLORREF,n);
hBmp  = myGetCurBitmap(hdc);
myPopBitmapIndirect(hdc,FALSE);

pDest = data;
p1    = dataBitmap1;
p2    = dataBitmap2;

for(j=0;j<pInfo->cy;j++)
  {
  for(i=0;i<pInfo->cx;i++)
    {
    COLORREF  c,c1,c2;
    BYTE      r,r1,r2;
    BYTE      g,g1,g2;
    BYTE      b,b1,b2;

    c1      = *p1;
    c2      = *p2;

    r1      = GetRValue(c1);
    g1      = GetGValue(c1);
    b1      = GetBValue(c1);

    r2      = GetRValue(c2);
    g2      = GetGValue(c2);
    b2      = GetBValue(c2);

    r       = funcR(i,j,r1,r2,param);
    g       = funcG(i,j,g1,g2,param);
    b       = funcB(i,j,b1,b2,param);

    c       = RGB(r,g,b);

  • pDest = c;
p1 ++; p2 ++; pDest ++; } } bmpInfo.bmih.bmiHeader.biSize = sizeof(bmpInfo.bmih.bmiHeader); bmpInfo.bmih.bmiHeader.biWidth = pInfo->cx; bmpInfo.bmih.bmiHeader.biHeight = -pInfo->cy; bmpInfo.bmih.bmiHeader.biPlanes = 1; bmpInfo.bmih.bmiHeader.biBitCount = 32; bmpInfo.bmih.bmiHeader.biCompression = BI_RGB; bmpInfo.bmih.bmiHeader.biSizeImage = pInfo->cx*pInfo->cy; bmpInfo.bmih.bmiHeader.biXPelsPerMeter = 1; bmpInfo.bmih.bmiHeader.biYPelsPerMeter = 1; bmpInfo.bmih.bmiHeader.biClrUsed = 3; bmpInfo.bmih.bmiHeader.biClrImportant = 0; if(0 == SetDIBits(GetHdc(hdc),hBmp,0,pInfo->cy,data,&bmpInfo.bmih,DIB_RGB_COLORS)) { Error((NULL)); } myPushBitmapIndirect(hdc,hBmp); Free(data); return TRUE; } // CombinBmp() //------------------------------------------------- // WND PROC //------------------------------------------------- typedef struct tagDATA { int kr,kg,kb; // 0-100 }DATA,*P_DATA,**PP_DATA; //------------------------------------------------- BYTE funcR(int i,int j,BYTE r1,BYTE r2,void *param) { P_DATA data; data = (P_DATA)param; return (BYTE)((data->kr * r1 + (100 - data->kr) * r2)/100); } // funcR() //------------------------------------------------- BYTE funcG(int i,int j,BYTE g1,BYTE g2,void *param) { P_DATA data; data = (P_DATA)param; return (BYTE)((data->kg * g1 + (100 - data->kg) * g2)/100); } // funcG() //------------------------------------------------- BYTE funcB(int i,int j,BYTE b1,BYTE b2,void *param) { P_DATA data; data = (P_DATA)param; return (BYTE)((data->kb * b1 + (100 - data->kb) * b2)/100); } // funcB() //------------------------------------------------- void SetData(HWND hwnd,P_DATA data,char r,char g,char b) { data->kr = r; data->kg = g; data->kb = b; SendMessage(hwnd,WM_USER,0,0); } // SetData() //------------------------------------------------- void SetDeltaData(HWND hwnd,P_DATA data,char dr,char dg,char db) { data->kr += dr; if(data->kr < 0) data->kr = 0; else if(data->kr > 100) data->kr = 100; data->kg += dg; if(data->kg < 0) data->kg = 0; else if(data->kg > 100) data->kg = 100; data->kb += db; if(data->kb < 0) data->kb = 0; else if(data->kb > 100) data->kb = 100; SendMessage(hwnd,WM_USER,0,0); } // SetDeltaData() //------------------------------------------------- int WndProc(P_MY_WINDOW myWindow,HWND hwnd,UINT iMsg,WPARAM wParam,LPARAM lParam) { static HWND hwndStatusBar; static SIZE info; static P_MY_HDC hdcBitmap1; static COLORREF *dataBitmap1; static P_MY_HDC hdcBitmap2; static COLORREF *dataBitmap2; static P_MY_HDC hdcBitmapCombin; static DATA data; switch(iMsg) { case WM_CREATE: { HDC hdc; SIZE info1,info2; HBITMAP hBmp1,hBmp2,hBmpCombin; int allWidth[4]; hdc = GetDC(hwnd); // style de fenetre myWindow->bResizedWindow = TRUE; myWindow->bUseBackBuffer = FALSE; myWindow->colorBackGround = COLOR_BACK_GROUND_NO_ERASE; // la bar hwndStatusBar = CreateStatusWindow(WS_VISIBLE | WS_CHILD,"",hwnd,100); allWidth[0] = 100; allWidth[1] = 200; allWidth[2] = 300; allWidth[3] = -1; SendMessage(hwndStatusBar,SB_SETPARTS,(WPARAM)COUNT(allWidth),(LPARAM)allWidth); SendMessage(hwndStatusBar,SB_SETTEXT,(WPARAM)(3 | 0),(LPARAM)"\ttouche ( + , - ) : ROUGE( a , q ) VERT( z , s ) BLEU( e , d )"); // les HDC hdcBitmap1 = myCreateDCIndirect(hwnd,TRUE); hdcBitmap2 = myCreateDCIndirect(hwnd,TRUE); hdcBitmapCombin = myCreateDCIndirect(hwnd,TRUE); // les bitmaps hBmp1 = LoadBitmap(myGetInst(hwnd),MAKEINTRESOURCE(IDB_BITMAP_1)); hBmp2 = LoadBitmap(myGetInst(hwnd),MAKEINTRESOURCE(IDB_BITMAP_2)); // les donnees de la bitmap dataBitmap1 = myGetDI32Bits(hdcBitmap1,hBmp1,&info1); dataBitmap2 = myGetDI32Bits(hdcBitmap2,hBmp2,&info2); ErrorIf((info1.cx != info2.cx || info1.cy != info2.cy,"Dimensions des deux bitmaps non-egales !")); info.cx = info1.cx; info.cy = info1.cy; hBmpCombin = CreateCompatibleBitmap(hdc,info.cx,info.cy); // on selectionne les bitmaps dans les HDC myPushBitmapIndirect(hdcBitmap1,hBmp1); myPushBitmapIndirect(hdcBitmap2,hBmp2); myPushBitmapIndirect(hdcBitmapCombin,hBmpCombin); data.kr = 50; data.kg = 50; data.kb = 50; SendMessage(hwnd,WM_USER,0,0); ReleaseDC(hwnd,hdc); break; } case WM_SIZE: { SendMessage(hwndStatusBar,iMsg,0,lParam); break; } case WM_KEYDOWN: { switch(wParam) { case 'A': SetDeltaData(hwnd,&data,+1,0,0); break; case 'Q': SetDeltaData(hwnd,&data,-1,0,0); break; case 'Z': SetDeltaData(hwnd,&data,0,+1,0); break; case 'S': SetDeltaData(hwnd,&data,0,-1,0); break; case 'E': SetDeltaData(hwnd,&data,0,0,+1); break; case 'D': SetDeltaData(hwnd,&data,0,0,-1); break; } break; } case WM_COMMAND: { switch(LOWORD(wParam)) { case ID_ABOUT: { myWarning(hwnd,"A propos du programme ...","Combinaisons de bitmaps\r\n\r\nCalcul d'une bitmap en fonction de pourcentages\r\nde chaque composante RGB de deux bitmaps\r\n\r\nProgrammé par JCDjcd"); break; } case ID_R100V100B100: SetData(hwnd,&data,100,100,100); break; case ID_R50V50B50: SetData(hwnd,&data,50,50,50); break; case ID_R0V0B0: SetData(hwnd,&data,0,0,0); break; case ID_R100V0B0: SetData(hwnd,&data,100,0,0); break; case ID_R0V100B0: SetData(hwnd,&data,0,100,0); break; case ID_R0V0B100: SetData(hwnd,&data,0,0,100); break; case ID_R0V100B100: SetData(hwnd,&data,0,100,100); break; case ID_R100V0B100: SetData(hwnd,&data,100,0,100); break; case ID_R100V100B0: SetData(hwnd,&data,100,100,0); break; } break; } case WM_USER: { char buf[64]; // rouge _snprintf(buf,COUNT(buf),"\tRouge %d%%",data.kr); SendMessage(hwndStatusBar,SB_SETTEXT,(WPARAM)(0 | 0),(LPARAM)buf); // vert _snprintf(buf,COUNT(buf),"\tVert %d%%",data.kg); SendMessage(hwndStatusBar,SB_SETTEXT,(WPARAM)(1 | 0),(LPARAM)buf); // bleu _snprintf(buf,COUNT(buf),"\tBleu %d%%",data.kb); SendMessage(hwndStatusBar,SB_SETTEXT,(WPARAM)(2 | 0),(LPARAM)buf); CombinBmp(hdcBitmapCombin,&info,dataBitmap1,dataBitmap2,funcR,funcG,funcB,&data); myRepaintWindow(hwnd); break; } // on dessine case WM_PAINT: { P_MY_HDC hdc; int cx,cy; RECT rcSrc,rcDest; RECT rcStatusBar; cx = LOWORD(lParam); cy = HIWORD(lParam); hdc = (P_MY_HDC)wParam; GetWindowRect(hwndStatusBar,&rcStatusBar); mySetRectWH(&rcSrc,0,0,info.cx,info.cy); mySetRectWH(&rcDest,0,0,cx,cy - 0*myHeightRect(&rcStatusBar)); myStretchBlt(hdc,&rcDest,hdcBitmapCombin,&rcSrc,SRCCOPY); break; } // destruction de la fenetre case WM_DESTROY: { // les donnees de la bitmap Free(dataBitmap1); Free(dataBitmap2); // les bitmaps myPopBitmapIndirect(hdcBitmap1,TRUE); myPopBitmapIndirect(hdcBitmap2,TRUE); myPopBitmapIndirect(hdcBitmapCombin,TRUE); // les HDC myDeleteDCIndirect(hdcBitmap1); myDeleteDCIndirect(hdcBitmap2); myDeleteDCIndirect(hdcBitmapCombin); // on quitte le programme PostQuitMessage(0); break; } } return 0; } // WndProc() //------------------------------------------------- // WIN MAIN //------------------------------------------------- int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpszCmdLine,int iCmdShow) { WNDCLASSEX wc; RECT rc; HWND hwnd; int wParamResult; // le programme vient de commencer, on initialise les librairies InitializationLibUtil(); InitializationLibWinutil(hInstance); mySetDefaultWindowClass(&wc,hInstance); wc.lpszClassName = "JCD_CombinBmp"; SetRect(&rc,0,0,800,600); hwnd = myCreateWindow(&wc, "Combinaison de bitmaps (JCD)", WS_OVERLAPPEDWINDOW | WS_VISIBLE, &rc, TRUE, NULL, LoadMenu(hInstance,MAKEINTRESOURCE(IDR_MENU)), 0, NULL, WndProc ); // on commence la boucle de messages SetDefaultHwnd(hwnd); wParamResult = myRunWindow(hwnd,SW_SHOW); SetDefaultHwnd(NULL); // on a fini le programme, on ferme les librairies CloseLibUtil(); CloseLibWinutil(); CheckingClosingLibUtil(); CheckingClosingLibWinutil(); return wParamResult; } // WinMain()

Conclusion :


//-------------------------------------------------
BYTE funcR(int i,int j,BYTE r1,BYTE r2,void *param)
{
if((i&1) ^ (j&1))
return r1;
else
return r2;
} // funcR()
//-------------------------------------------------
BYTE funcG(int i,int j,BYTE g1,BYTE g2,void *param)
{
if((i&1) ^ (j&1))
return g1;
else
return g2;
} // funcG()
//-------------------------------------------------
BYTE funcB(int i,int j,BYTE b1,BYTE b2,void *param)
{
if((i&1) ^ (j&1))
return b1;
else
return b2;
} // funcB()

Ces fonctions montrent comment faire comme la capture d'ecran. Un pixel sur deux sont de la premiere bitmap, les autres de la second. Ainsi on a un effet de superposition transparente.
Grace a ce code source generique, on peut faire d'autre operation que celle presentee.

Codes Sources

A voir également

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.