Some little problem with Leunen's 32-bit Bitmap Rotate routine
Yesterday i implemented Leunen's Bitmap rotate routine and below follow
my results:
1. with 24-bit bitmap image i don't have any problem neither using large
image (about 60 MegaBytes - sixty)
2. with 32-bit bitmap image i saw random behaviour:
a) with little image (70KiloBytes - seventy) there was no problem
b) with size image of about 1 MegaBytes (one megabyte) more
precisely 509 x 509 = 259081 pixels the routine didn't ever worked;
c) with large image (about 60 MegaBytes - sixty) sometimes the
routine worked properly other times no!
From yesterday afternoon i tried to understand the problem but now i
give in!
many thanks in advance.
p.s.: The last code i tested follow below:
// START - UNIT.H
//---------------------------------------------------------------------------
#ifndef Unit1H
#define Unit1H
//---------------------------------------------------------------------------
#include <Classes.hpp>
#include <Controls.hpp>
#include <StdCtrls.hpp>
#include <Forms.hpp>
#include <ExtCtrls.hpp>
#include <math.h>
//---------------------------------------------------------------------------
class TForm1 : public TForm
{
__published: // IDE-managed Components
TScrollBox *ScrollBox1;
TImage *Image1;
TButton *Button1;
TLabel *Label1;
void __fastcall Button1Click(TObject *Sender);
private: // User declarations
public: // User declarations
void TestRotate01(void);
__fastcall TForm1(TComponent* Owner);
};
//---------------------------------------------------------------------------
extern PACKAGE TForm1 *Form1;
//---------------------------------------------------------------------------
#endif
// END - UNIT.H
// *****************************
// START - UNIT.C
//---------------------------------------------------------------------------
#include <vcl.h>
#pragma hdrstop
#include "Unit1.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
}
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
void TForm1::TestRotate01(void)
{
int temp01, temp02, temp03, temp04;
//Source Bitmap
Graphics::TBitmap *SrcBitmap=new Graphics::TBitmap;
//Destination bitmap
Graphics::TBitmap *DestBitmap=new Graphics::TBitmap;
SrcBitmap->LoadFromFile("MY FILE IMAGE NAME");
DestBitmap->PixelFormat=SrcBitmap->PixelFormat;
int angle=45; //45° for example
//Convert degrees to radians
float radians=(2*3.1416*angle)/360;
float cosine=(float)cos(radians);
float sine=(float)sin(radians);
float Point1x=(-SrcBitmap->Height*sine);
float Point1y=(SrcBitmap->Height*cosine);
float Point2x=(SrcBitmap->Width*cosine-SrcBitmap->Height*sine);
float Point2y=(SrcBitmap->Height*cosine+SrcBitmap->Width*sine);
float Point3x=(SrcBitmap->Width*cosine);
float Point3y=(SrcBitmap->Width*sine);
float minx=min((float) 0,min(Point1x,min(Point2x,Point3x)));
float miny=min((float) 0,min(Point1y,min(Point2y,Point3y)));
float maxx=max((float) 0,max(Point1x,max(Point2x,Point3x)));
float maxy=max((float) 0,max(Point1y,max(Point2y,Point3y)));
int DestBitmapWidth=(int)ceil(maxx-minx);
int DestBitmapHeight=(int)ceil(maxy-miny);
DestBitmap->Height=DestBitmapHeight;
DestBitmap->Width=DestBitmapWidth;
//create DIB for SrcBitmap
LPBITMAPINFO srcBmpi=(LPBITMAPINFO)new char[sizeof(BITMAPINFO)];
ZeroMemory(srcBmpi,sizeof(BITMAPINFO));
//init BitmapInfo struct
srcBmpi->bmiHeader.biSize=sizeof(BITMAPINFOHEADER);
srcBmpi->bmiHeader.biWidth=SrcBitmap->Width;
srcBmpi->bmiHeader.biHeight=SrcBitmap->Height;
srcBmpi->bmiHeader.biPlanes=1;
srcBmpi->bmiHeader.biCompression=BI_RGB;
switch(SrcBitmap->PixelFormat)
{
case pf24bit: srcBmpi->bmiHeader.biBitCount=24; break;
case pf32bit: srcBmpi->bmiHeader.biBitCount=32; break;
}
//Each row is zero padded so that the number of bytes
//per row is divisible by 4
int SrcNumberOfBytesPerRow=
((((SrcBitmap->Width*srcBmpi->bmiHeader.biBitCount)+31)&~31)/8);
//use screen DC for GetDIBits
HDC ScreenDC=GetDC(NULL);
//get image size
temp01 =
GetDIBits(ScreenDC,SrcBitmap->Handle,0,srcBmpi->bmiHeader.biHeight,
NULL,srcBmpi,DIB_RGB_COLORS);
//if the driver didn't give the size, calculate it yourselves
if(srcBmpi->bmiHeader.biSizeImage==0)
{
srcBmpi->bmiHeader.biSizeImage=
SrcNumberOfBytesPerRow*SrcBitmap->Height;
}
//Allocate memory for the bits
char* srcbits=new char[srcBmpi->bmiHeader.biSizeImage];
//get the bits
temp02 =
GetDIBits(ScreenDC,SrcBitmap->Handle,0,srcBmpi->bmiHeader.biHeight,
srcbits,srcBmpi,DIB_RGB_COLORS);
//create DIB for DestBitmap
LPBITMAPINFO destBmpi=(LPBITMAPINFO)new char[sizeof(BITMAPINFO)];
ZeroMemory(destBmpi,sizeof(BITMAPINFO));
//init BitmapInfo struct
destBmpi->bmiHeader.biSize=sizeof(BITMAPINFOHEADER);
destBmpi->bmiHeader.biWidth=DestBitmap->Width;
destBmpi->bmiHeader.biHeight=DestBitmap->Height;
destBmpi->bmiHeader.biPlanes=1;
destBmpi->bmiHeader.biCompression=BI_RGB;
destBmpi->bmiHeader.biBitCount=srcBmpi->bmiHeader.biBitCount;
//Each row is zero padded so that the number of bytes
//per row is divisible by 4
int DestNumberOfBytesPerRow=
((((DestBitmap->Width*destBmpi->bmiHeader.biBitCount)+31)&~31)/8);
//get image size
temp03 =
GetDIBits(ScreenDC,DestBitmap->Handle,0,destBmpi->bmiHeader.biHeight,
NULL,destBmpi,DIB_RGB_COLORS);
//if the driver didn't give the size, calculate it ourselves
if(destBmpi->bmiHeader.biSizeImage==0)
{
destBmpi->bmiHeader.biSizeImage=
DestNumberOfBytesPerRow*DestBitmap->Height;
}
//Allocate memory for the bits
char* destbits=new char[destBmpi->bmiHeader.biSizeImage];
//Set bits in destination buffer
//Perform the rotation
for(int y=0;y<DestBitmapHeight;y++)
{
for(int x=0;x<DestBitmapWidth;x++)
{
int SrcBitmapx=(int)((x+minx)*cosine+(y+miny)*sine);
int SrcBitmapy=(int)((y+miny)*cosine-(x+minx)*sine);
if(SrcBitmapx>=0&&SrcBitmapx<SrcBitmap->Width&&SrcBitmapy>=0&&
SrcBitmapy<SrcBitmap->Height)
{
for (int i=0;i<srcBmpi->bmiHeader.biBitCount/8;i++)
{
*(destbits+(DestNumberOfBytesPerRow*y)+
(x*srcBmpi->bmiHeader.biBitCount/8+i))=
*(srcbits+(SrcNumberOfBytesPerRow*SrcBitmapy)+
(SrcBitmapx*srcBmpi->bmiHeader.biBitCount/8+i));
}
}
}
}
//Set the bits in destination bitmap
//Convert destination DIB to a bitmap
temp04 = SetDIBits(ScreenDC,DestBitmap->Handle,0,
destBmpi->bmiHeader.biHeight,destbits,destBmpi,DIB_RGB_COLO RS);
Image1->Picture->Bitmap=DestBitmap;
Label1->Caption = AnsiString(temp01) +
" -- " + AnsiString(temp02) +
" -- " + AnsiString(temp03) +
" -- " + AnsiString(temp04);
delete DestBitmap;
delete SrcBitmap;
delete []srcbits;
delete []destbits;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
TestRotate01();
}
//---------------------------------------------------------------------------
// END - UNIT.C
// *****************************
// START - UNIT.DFM
object Form1: TForm1
Left = 192
Top = 114
Width = 870
Height = 640
Caption = 'Form1'
Color = clBtnFace
Font.Charset = DEFAULT_CHARSET
Font.Color = clWindowText
Font.Height = -11
Font.Name = 'MS Sans Serif'
Font.Style = []
OldCreateOrder = False
PixelsPerInch = 96
TextHeight = 13
object Label1: TLabel
Left = 80
Top = 8
Width = 32
Height = 13
Caption = 'Label1'
end
object ScrollBox1: TScrollBox
Left = 64
Top = 64
Width = 489
Height = 505
TabOrder = 0
object Image1: TImage
Left = 0
Top = 0
Width = 105
Height = 105
AutoSize = True
end
end
object Button1: TButton
Left = 648
Top = 64
Width = 75
Height = 25
Caption = 'Button1'
TabOrder = 1
OnClick = Button1Click
end
end
// END - UNIT.DFM
|