Hi,all
One of our customers proposed a issue that pictures with big size, such as
2M or more, are inserted in the impress slide, when we press F5 to show this
slide, it is too slow so that he can not accept it.
Then I tracked the code, I found that the bitmap drawn on the screen has the
original size from the cache. I thought it might be way to improve the
performance, so I scale the bitmap to a smaller size before drawing it. Even if
I have not used some tools to test the performance, I think it should be better
than before.
As a test in Windows OS, I scaled the bitmap in the drawVCLBitmapEx method
which is in canvas\source\directx\dx_vcltools.cxx. I found that if the bitmap
is scaled to 1/4 of the original size, such as from 100*100 to 50*50, the
rectangle where the bitmap will be drawn is also scaled to 1/4 of the size it
should be. I think the reason is that we used the DrawImage of DirectX to draw
the bitmap to screen. The error is occurred because the DrawImage function is
related to the screen resolution and the bitmap size.
The following codes are the difference in the dx_vcltools.cxx. In this test,
I set 1000 pixels as the limitation of width and height and it is only for the
bitmap without transparence.
@@ -85,7 +85,8 @@ namespace dxcanvas
/// Draw DI bits to given Graphics
bool drawDIBits( const ::boost::shared_ptr< Gdiplus::Graphics >&
rGraphics,
- const void*
hDIB )
+ const void*
hDIB,
+ int
scale )
{
bool bRet( false );
BitmapSharedPtr pBitmap;
@@ -100,7 +101,7 @@ namespace dxcanvas
// forward to outsourced GDI+ rendering method
// (header clashes)
- bRet = tools::drawDIBits( rGraphics, *pBI, (void*)pBits );
+ bRet = tools::drawDIBits( rGraphics,
*pBI, (void*)pBits, scale );
GlobalUnlock( (HGLOBAL)hDIB );
}
@@ -115,7 +116,8 @@ namespace dxcanvas
that it will hold a DIB after a successful function call.
*/
bool drawVCLBitmap( const ::boost::shared_ptr< Gdiplus::Graphics
>& rGraphics,
- ::Bitmap&
rBmp )
+ ::Bitmap&
rBmp,
+ int
scale )
{
BitmapSystemData aBmpSysData;
@@ -138,7 +140,7 @@ namespace dxcanvas
aBmpSysData.pDIB )
{
return drawDIBits( rGraphics,
- aBmpSysData.pDIB );
+ aBmpSysData.pDIB,scale );
}
rBmp.ReleaseAccess( pReadAcc );
@@ -147,7 +149,7 @@ namespace dxcanvas
else
{
return drawDIBits( rGraphics,
- aBmpSysData.pDIB );
+ aBmpSysData.pDIB,scale );
}
// failed to generate DIBits from vcl bitmap
@@ -495,8 +497,22 @@ namespace dxcanvas
{
if( !rBmpEx.IsTransparent() )
{
- Bitmap aBmp( rBmpEx.GetBitmap() );
- return drawVCLBitmap( rGraphics, aBmp );
+ BitmapEx scalebitmapex(rBmpEx);
+ int scale = 1;
+ Bitmap oriBmp = rBmpEx.GetBitmap();
+ BitmapReadAccess* poriReadAcc =
oriBmp.AcquireReadAccess();
+ int height = poriReadAcc->Height();
+ int width = poriReadAcc->Width();
+ if(height > 1000 || width > 1000)
+ {
+ int scaleH = height / 1000;
+ int scaleW = width / 1000;
+ scale = scaleH >= scaleW ?
scaleH : scaleW;
+ scalebitmapex.Scale(
1.0/scale,1.0/scale , 1);
+ }
+
+ Bitmap aBmp( scalebitmapex.GetBitmap()
);
+ return drawVCLBitmap( rGraphics,
aBmp,scale );
}
else
{
I added the two interfaces of drawDIBits and drawGdiPlusBitmap in
dx_impltools.cxx to pass the scale parameter to the DrawImage of DirectX, so we
can let the DrawImage to draw the bitmap to the original rectangle. The
following codes are the difference in the dx_impltools.cxx.
return (Gdiplus::Ok == rGraphics->DrawImage( rBitmap.get(),
aPoint ) );
}
+ bool drawGdiPlusBitmap( const GraphicsSharedPtr& rGraphics,
+ const BitmapSharedPtr& rBitmap,
+ int scale)
+ {
+ Gdiplus::PointF aPoint;
+
+ return (Gdiplus::Ok == rGraphics->DrawImage(
rBitmap.get(),
+ 0,0,rBitmap.get()->GetWidth()*scale,
rBitmap.get()->GetHeight()*scale ) );
+ }
bool drawDIBits( const GraphicsSharedPtr& rGraphics,
const BITMAPINFO& rBI,
@@ -486,6 +495,18 @@ namespace dxcanvas
return drawGdiPlusBitmap( rGraphics,
pBitmap );
}
+ bool drawDIBits( const GraphicsSharedPtr& rGraphics,
+ const BITMAPINFO& rBI,
+ const void* pBits ,
+ int scale)
+ {
+ BitmapSharedPtr pBitmap(
+ Gdiplus::Bitmap::FromBITMAPINFO( &rBI,
+ (void*)pBits ) );
+
+ return drawGdiPlusBitmap( rGraphics,
+ pBitmap,scale );
+ }
bool drawRGBABits( const GraphicsSharedPtr& rGraphics,
const RawRGBABitmap& rRawRGBAData )
The result is good.
But the modification merely works for Windows platform. As I discussed with
Mr. Herbert of Sun. He advised that we can do it in the BitmapAction::render
method which is in cppcanvas\source\mtfrenderer\bitmapaction.cxx. At and before
this layer, the codes are not related with any OS, such as Mac, Linux etc. It
might be a good way, but there also has a trouble for us.
Because these are modifications in a higher layer rather than the way I
tested, many interface changes are needed in order to pass the scale parameter
to the DrawImage method. It is be done only for Windows. Sorry for not knowing
how for other OS, I am not sure if we should also pass the parameter to the
"draw" function in other OS. If we really want to do this, we have to change
too many files. It might not be a good solution. If the Windows Os is only
considered, the change might be acceptable.
It might not be right solution by passing the parameter to the DrawImage
method, but I could not find another way. any suggestions?
Thanks and Regards,
2008-11-14
sunyinan
---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]