Recently, you need to write a bitmap operation code to paste a specific logo bitmap to each
One frame achieves the effect similar to the TV station logo. The limit is to filter the specific color in the small bitmap to avoid
Avoid the appearance of ugly rectangular blocks.
If you use GDI, you can do it with transparentblt, but the actual environment does not allow you to operate directly.
Bitmap data.
First, I found some implementation of transparent bitmap Superposition on the Internet. Most of them adopt the mask method, that is,
Logo bitmap, design a mask bitmap of the same size and color depth, set the color to black
Color, and then use bitblt twice, the first time the logo bitmap and mask and the second time the and
If the image is copied to the video frame.
This method is more common, but also cumbersome. If you do not consider bitblt, you can write bitmap by yourself.
The operation function skips a specific color. Assume that the color to be filtered is black (the RGB value is 0 ),
It is also assumed that the bitmap is 256 bits, that is, the color of each pixel can be expressed in one byte.
Use the following code to implement the basic functions of Bitmap superposition:
Void bitmapoverlay (...)
{
Byte * psource =.../* Source bitmap data, that is, the logo bitmap data */
DWORD dwsourceheight =.../* Height of the logo bitmap */
DWORD dwsourcewidth =.../* width of the logo bitmap */
Byte * pTARGET =.../* Target bitmap data, that is, the bitmap data of the video frame */
DWORD dwtargetheight =.../* Height of the target bitmap */
DWORD dwtargetwidth =.../* width of the target bitmap */
DWORD dwoffsetx =.../* x offset position of the logo bitmap on the target MAP */
DWORD dwoffsety =.../* y offset position of the logo bitmap on the target MAP */
For (DWORD dwsourceline = 0; dwsourceline <dwsourceheight; dwline ++ ){
For (DWORD dwsourcepixel = 0; dwsourcepixel <dwsourcewidth; dwsourcepixel ++ ){
DWORD dwsourcepos = dwsourceline * dwsourcewidth + dwsourcepixel;
If (psource [dwsourcepos]) {
DWORD dwtargetline = dwsourceline + dwoffsety;
DWORD dwtargetpixel = dwsourcepixel + dwoffsetx;
DWORD dwtargetpos = dwtargetline * dwtargetwidth + dwtargetpixel;
PTARGET [dwtargetpos] = psource [dwsourcepos];
}
}
}
}
The above code implements the bitmap Superposition Function, but the performance is too low.
Obviously, we need to optimize the multiplication in the loop and change it to addition implementation,
Void bitmapoverlay (...)
{
...
DWORD dwsourcepos = 0;/* current location of the logo bitmap pixel to be processed */
DWORD dwtargetpos = 0;/* current location of the target bitmap to be processed */
Dwtargetpos = dwoffsety * dwtargetwidth + dwoffsetx;
For (DWORD dwsourceline = 0; dwsourceline <dwsourceheight; dwline ++ ){
For (DWORD dwsourcepixel = 0; dwsourcepixel <dwsourcewidth; dwsourcepixel ++ ){
If (psource [dwsourcepos]) {
PTARGET [dwtargetpos] = psource [dwsourcepos];
}
Dwsourcepos ++;
Dwtargetpos ++;
}
/* Jump to the corresponding position of the next row of the target bitmap */
Dwtargetpos ++ = (dwtargetwidth-dwsourcewidth + dwoffsetx );
}
}
The performance of the above Code is much higher than that before optimization, but it is still based on the bitblt idea,
Bitblt itself is a common GDI function, and we need to deal with a specific scenario,
The data of the logo bitmap is constant, but the data of the target bitmap is constantly changing.
Since there is a constant data, we can use the preprocessing method to reduce the calculation workload in the future.
Typedef taglogodata {
Byte bycolor;
DWORD dwpos;
} Logodata;
Void preprocesssource (...)
{
Byte * psource =.../* Source bitmap data, that is, the logo bitmap data */
DWORD dwsourceheight =.../* Height of the logo bitmap */
DWORD dwsourcewidth =.../* width of the logo bitmap */
DWORD dwtargetheight =.../* Height of the target bitmap */
DWORD dwtargetwidth =.../* width of the target bitmap */
DWORD dwoffsetx =.../* x offset position of the logo bitmap on the target MAP */
DWORD dwoffsety =.../* y offset position of the logo bitmap on the target MAP */
DWORD dwsourcepos = 0;/* current location of the logo bitmap pixel to be processed */
DWORD dwtargetpos = 0;/* current location of the target bitmap to be processed */
Dwtargetpos = dwoffsety * dwtargetwidth + dwoffsetx;
Logodata * plogodata = new.../* allocate enough memory to the logo data array */;
DWORD dwlogodatasize = 0;
For (DWORD dwsourceline = 0; dwsourceline <dwsourceheight; dwline ++ ){
For (DWORD dwsourcepixel = 0; dwsourcepixel <dwsourcewidth; dwsourcepixel ++ ){
If (psource [dwsourcepos]) {
Plogodata-> bycolor = psource [dwsourcepos];
Plogodata-> dwpos = dwtargetpos;
Plogodata ++;
Dwlogodatasize ++;
}
Dwsourcepos ++;
Dwtargetpos ++;
}
/* Jump to the corresponding position of the next row of the target bitmap */
Dwtargetpos ++ = (dwtargetwidth-dwsourcewidth + dwoffsetx );
}
}
The bitmap Superposition Function becomes very simple.
Void bitmapoverlay (...)
{
Logodata * plogodata =.../* array of Logo data */;
DWORD dwlogodatasize =.../* length of the logo data array */;
For (DWORD dwindex = 0; dwindex <dwlogodatasize; dwindex ++ ){
PTARGET [plogodata-> dwpos] = plogodata-> bycolor;
}
}
If there is less effective data (such as text) in the logo bitmap, you can use preprocessing.
Effectively improve performance.
If it is a large image, there is still room for further optimization-all the above implementations are using
The byte value assignment method is used. In fact, for larger images, the number of valid bitmaps is continuous.
Data accounts for the vast majority, and only need to combine the effective contact bitmap data into memory blocks during preprocessing,
In addition, you can copy memory to further improve the performance.