制作的一個程式中需要一個替換位圖某個顏色為另一個顏色的機制,使用了setpixel和getpixel卻發現效率慘不忍睹,有什么方法可以提高效率嗎?
下面是我的一部分代碼
for (int x = 200; x < 260; x++)
{
for (int y = 200; y < 294; y++)
{
hdc=GetDC(hWnd);
COLORREF pixelColor = GetPixel(hdc,x,y);
if (pixelColor == RGB(190, 225, 245))
SetPixel(hdc, x, y, RGB(155,125,105));
}
}
ReleaseDC(NULL, hdc);
uj5u.com熱心網友回復:
一般這種情況, 使用位圖吧, GetPixel/SetPixel 變成直接讀寫記憶體, 寫完再輸入到某位圖上. 用D2D/D3D就簡單多了, 一個PS就搞定了, 而且效率基本不變
uj5u.com熱心網友回復:
GetDibBits將圖片資料加載到記憶體修改資料
SetDibBits將圖片寫回
uj5u.com熱心網友回復:
以前做下位機GUI模擬器的時候碰到過,你把所有Get/SetPixel邏輯均放在記憶體DC處理,最終只呼叫貼圖函式畫出來
這樣效率會有很大提升
uj5u.com熱心網友回復:
參考OpenCV源代碼片斷。uj5u.com熱心網友回復:
int ReadBmp(const char* szFileName, BITMAPINFOHEADER *bih, BYTE **Buffer)
{
FILE *file;
WORD bfh[7];
long dpixeladd;
if (NULL == (file = fopen(szFileName, "rb")))
{
return 0;
}
printf("%s\n", szFileName);
fread(&bfh, sizeof(WORD), 7, file);
if (bfh[0] != (WORD)(((WORD)'B') | ('M' << 8)))
{
fclose(file);
return 0;
}
BITMAPINFOHEADER mbin;
fread(&mbin, sizeof(BITMAPINFOHEADER), 1, file);
if (mbin.biBitCount < 24)
{
fclose(file);
return 0;
}
dpixeladd = mbin.biBitCount / 8;
long LineByteWidth = mbin.biWidth * (dpixeladd);
if ((LineByteWidth % 4) != 0)
LineByteWidth += 4 - (LineByteWidth % 4);
BYTE* mBuffer;
if ((mBuffer = (BYTE*)malloc(sizeof(BYTE)* LineByteWidth * mbin.biHeight)) != NULL)
{
*bih = mbin;
fread(mBuffer, LineByteWidth * mbin.biHeight, 1, file);
*Buffer = mBuffer;
fclose(file);
return 1;
}
fclose(file);
return 0;
}
int GetDIBColor(int X, int Y, BITMAPINFOHEADER bih, BYTE *Buffer, BYTE *r, BYTE *g, BYTE *b)
{
int dpixeladd;
BYTE *ptr;
if (X < 0 || X >= bih.biWidth || Y < 0 || Y >= bih.biHeight)
{
return 0;
}
dpixeladd = bih.biBitCount / 8;
long LineByteWidth = bih.biWidth * (dpixeladd);
ptr = Buffer + X * dpixeladd + (bih.biHeight - 1 - Y) * LineByteWidth;
*b = *ptr;
*g = *(ptr + 1);
*r = *(ptr + 2);
return 1;
}
int GetDIBColor(int X, int Y, BITMAPINFOHEADER bih, BYTE *Buffer, BYTE *rgb, int type)
{
int dpixeladd;
BYTE *ptr;
if (X < 0 || X >= bih.biWidth || Y < 0 || Y >= bih.biHeight)
{
return 0;
}
dpixeladd = bih.biBitCount / 8;
long LineByteWidth = bih.biWidth * (dpixeladd);
ptr = Buffer + X * dpixeladd + (bih.biHeight - 1 - Y) * LineByteWidth;
switch (type)
{
case 0: *rgb = *ptr;; break;
case 1: *rgb = *(ptr + 1);; break;
case 2: *rgb = *(ptr + 2);; break;
default:
break;
}
return 1;
}
int SetDIBColor(int X, int Y, BITMAPINFOHEADER bih, BYTE *Buffer, BYTE r, BYTE g, BYTE b)
{
int dpixeladd;
BYTE *ptr;
if (X < 0 || X >= bih.biWidth || Y < 0 || Y >= bih.biHeight)
{
return 0;
}
dpixeladd = bih.biBitCount / 8;
long LineByteWidth = bih.biWidth * (dpixeladd);
ptr = Buffer + X * dpixeladd + (bih.biHeight - 1 - Y) * LineByteWidth;
*ptr = r;
*(ptr + 1) = g;
*(ptr + 2) = b;
return 1;
}
int SetDIBColor_RGB(int X, int Y, BITMAPINFOHEADER bih, BYTE *Buffer, BYTE rgb, int type)
{
int dpixeladd;
BYTE *ptr;
if (X < 0 || X >= bih.biWidth || Y < 0 || Y >= bih.biHeight)
{
return 0;
}
dpixeladd = bih.biBitCount / 8;
long LineByteWidth = bih.biWidth * (dpixeladd);
ptr = Buffer + X * dpixeladd + (bih.biHeight - 1 - Y) * LineByteWidth;
switch (type)
{
case 0: *ptr = rgb; break;
case 1: *(ptr + 1) = rgb; break;
case 2: *(ptr + 2) = rgb; break;
default:
break;
}
return 1;
}
//創建位圖檔案
int SaveBitmap(const char* bmpPath, BYTE * pBuffer, int lWidth, int lHeight, int nByte)
{
// 生成bmp檔案
HANDLE hf = CreateFileA(bmpPath, GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, NULL, NULL);
if (hf == INVALID_HANDLE_VALUE)
return 0;
// 寫檔案頭
BITMAPFILEHEADER bfh;
memset(&bfh, 0, sizeof(bfh));
bfh.bfType = 'MB';
bfh.bfSize = sizeof(bfh) + lWidth * lHeight * nByte + sizeof(BITMAPINFOHEADER);
bfh.bfOffBits = sizeof(BITMAPINFOHEADER) + sizeof(BITMAPFILEHEADER);
DWORD dwWritten = 0;
WriteFile(hf, &bfh, sizeof(bfh), &dwWritten, NULL);
// 寫位圖格式
BITMAPINFOHEADER bih;
memset(&bih, 0, sizeof(bih));
bih.biSize = sizeof(bih);
bih.biWidth = lWidth;
bih.biHeight = lHeight;// -lHeight;
bih.biPlanes = 1;
bih.biBitCount = nByte * 8;
WriteFile(hf, &bih, sizeof(bih), &dwWritten, NULL);
// 寫位圖資料
WriteFile(hf, pBuffer, lWidth*lHeight*nByte, &dwWritten, NULL);
CloseHandle(hf);
return 0;
}
uj5u.com熱心網友回復:
將位圖BitBlt到DibSection中,直接操作記憶體,然后再BitBlt回去uj5u.com熱心網友回復:
從記憶體到顯存要走那個很擁擠的北橋總線,所以一次傳的影像資料越多越好。一次傳一個點是最沒有效率的做法。提高效率有兩種方法
1 使用256色和調色板 ,這樣要把所有190, 225, 245的像素改成155,125,105,只需要改調色板里面對應顏色的值
2 高彩和真彩,把整個區域在記憶體DC里重新畫一遍然后bitblt到顯示的DC。
轉載請註明出處,本文鏈接:https://www.uj5u.com/gongcheng/63991.html
標籤:圖形處理/算法
