BMP turns graph

xiaoxiao2021-03-19  192

Pomelowu original, reprinted

It is easy to use the MFC to intercept the current screen and display it on the UI of your program. Take the dialog as an example, you can do the following functions in the execution of the plotted unit (such as onpaint):

Bool csrnshotdlg :: getMyscreen

CDC * PDC //

aims

DC

)

{

CDC DC;

Dc.created ("Display", NULL, NULL, NULL); //

screen

DC

CRECT ClientRect;

GetClientRect (ClientRect); //

Dialog rectangular area

PDC-> Bitblt (0, 0, //

starting point

ClientRect.Width (), clientRect.height (), //

Width Height

& DC, //

source

CDC

Object

0, 0,

//

Source location

Srcopy //

Replication method

);

Dc.deletedc (); return true;

}

Next, the screenshot of the screen is first converted to the grayscale map, and then display it. The formula of the conversion grayscale map is that the RGB value, R, G, and B are 3 color components, calculated:

Gray = r * 0.299 g * 0.587 b * 0.114

The gray then replaces the original 3 color component separately. To this place, I naturally think of using setpixel / getpixel. Because the DC is to be operated, of course, it cannot be directly operating directly on the DC inside above getMyScreen. For this purpose, the GetMyscreen is transformed, and for the ability to readability, add a CONVERTTOGRAY function to be responsible for conversion (different from the above code) The place is divided into red):

Void ConvertTograming (CDC * PDC)

{

For (int xx = 0; xx

For (int yy = 0; yy

{

ColorRef crTemp = PDC-> GetPixel (XX, YY);

Byte Pixelr = GtrValue (CRTEMP);

BYTE PIXELG = GETGVALUE (CRTEMP);

BYTE PIXELB = GetBValue (CRTEMP);

Byte gray = (Byte) (Pixelr * 0.299 Pixelg * 0.587 Pixelb * 0.114);

PDC-> SetPixelv (XX, YY, RGB (GRAY, GRAY, GRAY);

}

}

Bool csrnshotdlg :: getMyscreen

CDC * PDC //

aims

DC

)

{

CDC DC;

Dc.created ("Display", NULL, NULL, NULL); //

screen

DC

CRECT ClientRect;

GetClientRect (ClientRect); //

Dialog rectangular area

CDC * Pmemdc = null; //

compatible

DC

Pmemdc = New CDC;

IF (! pmemdc)

Return False;

Pmemdc-> CreateCompatiPLEDC (& DC);

ShowWindow (SW_HIDE);

Pmemdc-> Bitblt (0, 0,

ClientRect.Width (), clientRect.height (),

& DC, 0, 0, SRCCOPY;

Converttograming; PMEMDC);

PDC-> Bitblt (0, 0, //

starting point

ClientRect.Width (), clientRect.height (), //

Width Height

Pmemdc

//

source

CDC

Object

0, 0,

//

Source location

Srcopy //

Replication method

);

Pmemdc-> deletedc ();

DELETE PMEMDC;

dc.deletedc ();

Return True;

}

The effect is out, but it is not perfect. In fact, I used SetPixelv to replace SetPixel, but the speed of display is still very slow, and the CPU usage is also very high. How to improve efficiency? Directly changed the bitmap data attached to the DC seems to be a good way. Below to the CBITMAP class object.

Because it is a direct screen capture, you need to get the screen color depth with the cdc :: getDevicecaps with the Bitspixel parameter, because the storage mode of the bitmap of different color depths is different. Briefly illustrate: 16-bit color bitmap, each pixel for 2 bytes; 24-bit color, each pixel for 3 bytes; 32-bit color, each pixel for 4-byte storage space. We can use the cbitmap :: getBitmapBits function to get bitmap data, which is actually an array of BYTE. The structure of this array is the simplest of 24-bit color. As far as I have said 3 bytes per pixel, the subscript is b, g, r from low to high, and 32-bit color is similar, 4 bytes. There is only one alpha value. Below is the CONVERTTOGRAY24 for 24-bit color deep.

#define bits24 (int) (1024 * 768 * 3)

Void ConvertTograming24 (CBITMAP * PBMP)

{

LPBYTE LPBITS = NULL;

LPBITS = new byte [bits24];

IF (! lpbits)

Return;

ZeromeMory (lpbits, bits24);

PBMP-> GetBitmapBits (Bits24, LPBITS);

For (int index = 0, j = 0, k = 0; index

{

Lpbits [index] = (byte) (0.114 * lpbits [index]); j = index 1; k = index 2;

LPBITS [J] = (BYTE) (0.587 * lpbits [j]);

LPBITS [K] = (Byte) (0.299 * lpbits [k]);

LPBITS [INDEX] = LPBITS [J] LPBITS [K];

LPBITS [J] = LPBITS [INDEX];

LPBITS [K] = LPBITS [INDEX];

INDEX = K;

}

PBMP-> setBitmapbits (Bits24, LPBITS);

DELETE [] lpbits;

}

When GetDeviceCaps (Bitspixel) returns 16, there are two cases: 16-bit color and 15 color. In the case of 16-bit color, the bitmap array uses 2 bytes to save data, where the low to the low position is B, G, R this 3 color component bits 5: 6: 5. Need to use the bit operation to get the color value of each component:

#define getRvaluex (RGB) ((Byte) (RGB) & 0x1f)

#define getgvaluex ((Byte) (((RGB) & 0x07E0 >> 5))

#define getBvaluex (RGB) ((BYTE) ((RGB) & 0xF800) >> 11))

#define RGBX (R, G, B) /

((Word) | ((Word) ((BYTE)) << 5)) | ((Word) (B)) << 11)))

It is to be noted because the green component occupies 6bit, and its storage accuracy is twice the other two components, so the factor of the formula will change when performing successive calculations. (In addition, the use of 15-bit adapters is relatively small, and its storage rules are also occupied by 2 bytes, but the highest bit is meaningless, and the remaining 15 bits are assigned by 5: 5: 5, which is not discussed in detail.)

#define bits16 (int) (1024 * 768 * 2)

Void ConvertTogray16 (CBitmap * PBMP)

{

LPBYTE LPBITS = NULL;

Word * wbits;

LPBITS = New byte [bits16];

IF (! lpbits)

Return;

ZeromeMory (LPDIBITS, BITS16);

PBMP-> GetBitmapBits (Bits16, LPBITS);

For (int index = 0, j = 0, k = 0; index

{

WBITS = (Word *) (LPBITS INDEX);

BYTE PIXELR = GETRVALUEX (* WBITS) * 2;

BYTE PIXELG = GETGVALUEX (* WBITS); //

Pay attention

BYTE PIXELB = GetBValuex (* wbits) * 2;

Byte gray = (Byte) (Pixelr * 0.299 Pixelg * 0.587 Pixelb * 0.114);

* WBITS = RGBX (Gray / (Byte) 2, Gray, Gray / (Byte) 2);

INDEX ;

}

PBMP-> setBitmapbits (BITS16, LPBITS); delete [] lpbits;

}

Finally, the third transformation getMyscreen:

Bool csrnshotdlg :: getMyscreen

CDC * PDC //

aims

DC

)

{

CDC DC;

Dc.created ("Display", NULL, NULL, NULL); //

screen

DC

CRECT ClientRect;

GetClientRect (ClientRect); //

Dialog rectangular area

CDC * Pmemdc = null; //

compatible

DC

CBitMap * pbmp = null; //

Compatible bitmap

Pmemdc = New CDC;

IF (! pmemdc)

Return False;

Pmemdc-> CreateCompatiPLEDC (& DC);

PBMP = New CBITMAP;

IF (! PBMP)

{

Pmemdc-> deletedc ();

DELETE PMEMDC;

Return False;

}

PBMP-> CreateCompatibleBitmap (& DC, ClientRect.Width (), ClientRect.Height ());

PMEMDC-> SelectObject (PBMP);

ShowWindow (SW_HIDE);

Pmemdc-> Bitblt (0, 0,

ClientRect.Width (), clientRect.height (),

& DC, 0, 0, SRCCOPY;

Switch (Pmemdc-> getDeviceCaps (Bitspixel))

{

Case: 16

ConvertTograY16 (PBMP);

Break;

Case: 24

ConvertTograY24 (PBMP);

Break;

Case: 32

ConvertTograY32 (PBMP);

//

Not given

Break;

DEFAULT:

PBMP-> deleteObject ();

Pmemdc-> deletedc ();

Delete PBMP;

DELETE PMEMDC;

dc.deletedc ();

Return False;

}

PDC-> Bitblt (0, 0, //

starting point

ClientRect.Width (), clientRect.height (), //

Width Height

Pmemdc, //

source

CDC

Object

0, 0,

//

Source location

Srcopy //

Replication method

);

PBMP-> deleteObject ();

Pmemdc-> deletedc ();

Delete PBMP;

DELETE PMEMDC;

dc.deletedc ();

Return True;

}

-------------------------------------------------- -

Readable

CONVERTBMP24TOBMP256 {file * fp = fopen ("test.bmp", "rb"); if (! Fp) return; BitmapFileHeader HDR; FREAD (& HDR, 1, SizeOf (HDR), FP);

IF ((((((((((HDr.BFTYPE & 0xFF) == 'b') && ((hdr.bfType >> 8) == 'm'))) {fclose (fp); return;}

BitmapInfoheader Bih;

Fread (& BIH, 1, SIZEOF (BIH), FP);

IF (BiH.BIBITCOUNT! = 24 || BiH.Bicompression! = 0) {fclose (fp); Return;}

Unsigned char * pbuf = new unsigned char [bih.bisizeImage];

Fread (Pbuf, Bih.bisizeImage, Sizeof (unsigned char), fp);

FILE * OUT = FOPEN ("Testout.BMP", "WB"); if (! Out) {delete [] PBUF; fclose (fp); Return;}

unsigned char * pOutBuf = new unsigned char [bih.biWidth * bih.biHeight]; unsigned char * tmp = pBuf; unsigned char * tmp2 = pOutBuf; for (unsigned int i = 0; i

Rgbquad q [256]; for (i = 0; i <256; i ) {q [i] .RGBRED = q [i] .RGBGreen = q [i] .RGBBBLUE = I; Q [i] .RGBRESERSERVED = 0 }

Bih.biBitcount = 8; bih.bisizeImage = bih.biwidth * bih.biheight;

Hdr.bfsize = sizeof (bitmapfileHeader) sizeof (bitmapinfoheader) sizeof (q) bih.bisizeImeimage; hdr.bfoffbits = sizeof (q);

FWRITE (HDR, 1, SIZEOF (HDR), OUT); FWRITE (& BIH, 1, SIZEOF (BIH), OUT); FWRITE (q, 256, sizeof (rgbquad), OUT); FWRITE (Poutbuf, Bih.bisizeImage, SizeOf (unsigned char), out)

DELETE [] Poutbuf; fclose (out); delete [] PBUF; fclose (fp);

转载请注明原文地址:https://www.9cbs.com/read-130275.html

New Post(0)