The following code copies a large bitmap blends it with the correct background and then draws a semi transparent image with a clipped region to save draw time... Images are in an array and prescaled...
This has been through several levels of optimization based on my limited knowledge of C++ and the Builder graphics...
Edit: Updated code... blend();
void blend(Graphics::TBitmap *dst,int x,int y,Graphics::TBitmap *src,BYTE
alpha)
{
const int n=3; // pixel align [Bytes]
int dx0,dy0,dx1,dy1, // dst BBOX
sx0,sy0,sx1,sy1, // src BBOX
dx,dy,sx,sy,i;
BYTE *dp,*sp;
WORD a,_a,sc,dc,da[256],sa[256];
// compute BBOX (handle clipping)
dx=src->Width; dy=src->Height;
dx0=x; sx0=0; dx1=x+dx; sx1=dx;
dy0=y; sy0=0; dy1=y+dy; sy1=dy;
// blend
a=alpha; _a=255-a;
for (i=0;i<256;i++){ da[i]=_a*i; sa[i]=a*i; } // precompute BYTE*a and
BYTE*_a LUTs
for (dy=dy0,sy=sy0;dy<dy1;dy++,sy++) // ScanLines
{
dp=(BYTE*)dst->ScanLine[dy]+(n*dx0);
sp=(BYTE*)src->ScanLine[sy]+(n*sx0);
for (dx=dx0,sx=sx0;dx<dx1;dx++,sx++) // single ScanLine
for (i=0;i<n;i++,dp++,sp++) // RGB
*dp=WORD((sa[*sp]+da[*dp])>>8); // blend function
}
}
//--------------------------------------------------------------------------
det1maps.push_back( new Graphics::TBitmap() );
for (int i = 1; i < 176; i++)
{
det1maps.push_back( new Graphics::TBitmap() );
det1maps[i]->SetSize(t,t);
det1maps[i]->Canvas->StretchDraw(Rect(0, 0, t, t), Det1_bmp.get()); // scale
t = t + 24;
}
//------------------EDIT 3 Current version 1/18
det1maps[ss]->Transparent = true;
Form1->imgTemp->Picture->Assign(layer0_bmap.get()); //why background first?
HRGN MyRgn;
MyRgn = ::CreateRectRgn(0,0,Sw,Sh);
::SelectClipRgn(Form1->imgTemp->Canvas->Handle,MyRgn); //clip
Form1->imgTemp->Canvas->Draw(X3,Y3,det1maps[ss]); // draw det
blend(layer0_bmap.get(),0,0,Form1->imgTemp->Picture->Bitmap,int(obj[index]));
Here small simple C++/VCL
ScanLineAlpha Blend example I just put together:I just process the image on per pixel/channel basis and for each channel (R,G,B) compute:
where channels and alpha are 8 bit unsigned integers... For speed I used 24 bit pixel format (usually I use 32bit instead).
To avoid
*,/in teh Blending I precomputed 2 LUTs with all posible combinations ofnumber*alphaandnumber*(255-alpha). The division is done by bit shift>>8.To improve speed you can remember all
ScanLine[]of thedstimage into your array once and then use that as the target image will be used many times ...When I tested this on blending 2
1024x768images together it took<=9mson mine setup. The slowest operation is theScanLine[]access, and images where formated to the pixel format prior to blending...Here GIF preview (scaled down 1/4 and dithered by my capturer so it fits to imgur 2MByte limit):
This is the code I used for this (single timer VCL App):
And here the images (first nice 1024x768 images I found on Google images):
Here preview of Blending result:
For more info about the ScanLine see:
If you need even more speed then you should go for GPU Blending (OpenGL or DirectX).
[Edit2] array + rectangle example
After your edited your question its now obvious:
your array of bitmaps is not an array at all
its rather some kind of list template like
vector<Graphics::TBitmap*>or similar... So you do not have access to linear array of the bmps like I do. To make your life easier I used mine template with similar properties so you can see how to handle those (sorry I can not share the template code but you just need to changeList<T>intoVector<T>or whatever you are using ...This is the reason why the array pointer did not work for you as you do not have one. Its possibly your template expose it with some member. Mine does it like
map.datso yours might have something similar or not at all if not stored linearly.You are blending just 2 images not the whole array
so you can use the first example and add the ScanLine preloading as your images are static... Do the same for backbuffer image as that changes only after resize.
When I put all together here the result:
The blending is done in less than
0.5mson my setup for teh rectangle I choosed. As you can see its way faster than original9ms... Because if you are using cliping region you will still blend whole image just not copy the result. This approach only Blends and copy what is needed.Beware I removed the range checks so make sure the rectangle is inside of images ...
If you want to measure the time in the same way I do I am using this code of mine:
Performance.h: