March 28, 2024, 11:08:51 AM

News:

Own IWBasic 2.x ? -----> Get your free upgrade to 3.x now.........


has anyone ported SaveBitmap from EBasic?

Started by John S, December 20, 2007, 03:38:00 AM

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

John S

Has anyone ported SaveBitmap from EBasic?  I'd like to use it.
John Siino, Advanced Engineering Services and Software

John S

O.K., I've ported the savebitmap stuff and have gotten it to compile and run. 

However, when I try to save a bitmap (.bmp), the program does nothing.  I know that I have the pointers screwed up.

I have uploaded the source file.  To simplify my life a little, all the code is in one file (no includes).  The code includes debug info and breaks.

Can anyone please help me?  I think I'm close - it's just been a while since I worked with pointers and there are some GDI stuff I'm not familiar with.
John Siino, Advanced Engineering Services and Software

Ionic Wind Support Team

I'll look at it this evening when I am in my programming session.

Paul.
Ionic Wind Support Team

Ionic Wind Support Team

Here you go.  There was so much wrong with your conversion that it took me some time to repair it ;)

Really there wasn't THAT many pointers in use in the original, but you declared many variables as pointers when they were supposed to be structures, used LEN() on a pointer which of course returns 4, and not the 'size' of the memory it may point to, Many of the functions were declare extern, when they needed to be declare import, the ",1" is needed on the BITMAPFILEHEADER struture,  etc. 

To see all of the changes you should use a 'diff' utility, or compare them side by side. 


// simple paint
// simplepaint_2.src
// modified by John Siino to include SaveBitmap method
// 12/20/07

// #include "SaveBitmap.inc"

#ifdef DEBUG
declare import, OutputDebugStringA(string *str);
#endif


DECLARE IMPORT, GetSystemMetrics(int nIndex), int;

declare import, GlobalAlloc(flags as unsigned int, size as int), pointer;
              // flags = 0x00 Fixed Memory, = 0x40 initializes memory to zero
              // size: (amount of storage required) times (double = 8, float = int = 4)
              // returns pointer/handle to memory location

declare import, GlobalReAlloc(handle as unsigned int, newsize as int, flags as unsigned int),pointer;
              // flags = 0x40 initializes memory to zero
              // newsize: (amount of storage required) times (double = 8, float = int = 4)
              // returns pointer/handle to memory location

declare import, GlobalFree(handle as unsigned int), int;
              // returns null if successful
              // pointer/handle to memory location

declare import, RtlMoveMemory(dest as pointer, source as pointer, size as int);
              // dest = pointer to the starting address of the move destination
              // source = pointer to the starting address of the block of memory to be moved
              // size: (amount of storage required) times (double = 8, float, int = 4)
              // returns pointer/handle to memory location


// SaveBitmap stuff
struct BITMAP
{
int  bmType;
int  bmWidth;
int  bmHeight;
int  bmWidthCHARs;
WORD bmPlanes;
WORD bmBitsPixel;
int  bmBits;
}

struct BITMAPINFOHEADER
{
int  biSize;
int  biWidth;
int  biHeight;
WORD biPlanes;
WORD biBitCount;
int  biCompression;
int  biSizeImage;
int  biXPelsPerMeter;
int  biYPelsPerMeter;
int  biClrUsed;
int  biClrImportant;
}

struct BITMAPFILEHEADER, 1
{
WORD bfType;
int  bfSize;
WORD bfReserved1;
WORD bfReserved2;
int  bfOffBits;
}

CONST BI_RGB = 0;
CONST BI_RLE8 = 1;
CONST BI_RLE4 = 2;
CONST BI_bitfields = 3;

// SaveBitmap stuff
// API functions for dealing with the bitmaps
DECLARE import,  BitBlt(unsigned int HDCDest, int destx, int desty, int destw, int desth,
int HDCSrc, int srcx, int srcy, int rop), int;

// The CreateCompatibleDC function creates a memory device context (DC) compatible with the specified device.
//
DECLARE import,  CreateCompatibleBitmap(unsigned int HDC, int width, int height), int;

DECLARE import,  CreateCompatibleDC( unsigned int HDC ), int;
DECLARE import,  SelectObject(unsigned int HDC, int Handle), int;
DECLARE import,  DeleteDC( unsigned int HDC ), int;
DECLARE import,  DeleteObject( unsigned int handle ), int;
DECLARE import,  GetObjectA(unsigned int handle, int size, pointer mem), int;

DECLARE import,  GetDIBits(unsigned int HDC, unsigned int hbitmap, int start, int lines,
pointer bits, pointer info, int usage), int;

DECLARE import, RtlZeroMemory(pointer pvoid, int length), int;


class DrawWnd : CWindow
{
declare OnCreate(), int;
declare OnClose(), int;

declare OnMouseMove(int x, int y, int flags), int;
declare OnLButtonDown(int x, int y, int flags), int;
declare OnLButtonUp(int x, int y, int flags), int;
declare OnRButtonUp(int x, int y, int flags), int;

declare OnMenuPick(int nID), int;
declare OnMenuInit(unsigned int hMenu), int;

declare OnTimer(int nIDEvent), int;

// SaveBitmap stuff
DECLARE SaveBitmap(string filename, int left, int top, int width, int height);
DECLARE CreateInfoStructure(int hbitmap, BITMAPINFOHEADER info), int;
//end of SaveBitmap stuff

int drawcolor, l, t, w, h, tempx, tempy, linesize, mode;
}

int run;

global sub main()
{
run = 1;

DrawWnd win;

CMenu m;

win.Create(0,0,640,480,AWS_CAPTION|AWS_SYSMENU|AWS_BORDER|AWS_SIZE|AWS_MINIMIZEBOX|
AWS_MAXIMIZEBOX|AWS_MAXIMIZE|AWS_AUTODRAW,0,"Simple Paint 2",0);
m.BeginMenu();
m.MenuTitle( "&File");
m.MenuItem( "Print",0,101);
m.MenuItem( "&Save",0,102);
m.MenuItem( "&Load",0,103);
m.MenuItem( "Quit",0,100);
m.MenuTitle( "Options");
m.MenuItem( "Color",0,99);
m.MenuItem( "Clear",0,1);
m.BeginPopup( "Line Size");
m.MenuItem( "1",AMF_CHECKED,2);
m.MenuItem( "2",0,3);
m.MenuItem( "3",0,4);
m.MenuItem( "4",0,5);
m.EndPopup();
m.MenuTitle( "Tools");
m.MenuItem( "Line",AMF_CHECKED,6);
m.MenuItem( "Rectangle",0,7);
m.MenuItem( "Circle",0,8);
m.MenuItem( "Spray",0,9);
m.MenuItem( "FILL",0,10);
m.EndMenu();

win.SetMenu(m.Detach());

do {wait(); }until run = 0;

return 0;
}

//our windows message handlers
DrawWnd::OnCreate(), int
{
drawcolor = 0; linesize = 1;
FrontPen(drawcolor);
mode = 0;
return true;
}

DrawWnd::OnClose(), int
{
run = 0;
return true;
}

DrawWnd::OnMouseMove(int x, int y, int flags), int
{
tempx = x; tempy = y;

if(flags = 1)
{
select mode
{
case 1:
SetRasterOp(RMXORPEN);
DrawRect(l, t, w, h, RGB(255,255,255));
SetRasterOp(RMCOPYPEN);

case 2:
SetRasterOp(RMXORPEN);
Ellipse(l, t, w, h, RGB(255,255,255));
SetRasterOp(RMCOPYPEN);
}

w = x - l; h = y - t;

#ifdef DEBUG
OutputDebugStringA("DrawWnd::OnMouseMove() Line 200");
OutputDebugStringA(" w, h = " + NumToStr(w) + ", " + NumToStr(h) );

#endif

SELECT mode
{
case 0:
LineTo(x, y);
case 1:
SetRasterOp(RMXORPEN);
DrawRect(l, t, w, h, RGB(255,255,255));
SetRasterOp(RMCOPYPEN);

case 2:
SetRasterOp(RMXORPEN);
Ellipse(l, t, w, h, RGB(255,255,255));
SetRasterOp(RMCOPYPEN);
}
}
return true;
}

DrawWnd::OnLButtonDown(int x, int y, int flags), int
{
l = x; t = y; w = 0; h = 0;

#ifdef DEBUG
OutputDebugStringA("DrawWnd::OnLButtonDown() Line 228");
OutputDebugStringA(" w, h = " + NumToStr(w) + ", " + NumToStr(h) );

#endif

Move(l, t);

IF mode = 3
StartTimer(10);
IF mode = 4
FloodFill(l, t, drawcolor);

return true;
}

DrawWnd::OnLButtonUp(int x, int y, int flags), int
{
Select mode
{
CASE 1:
DrawRect(l, t, x-l, y-t, drawcolor, drawcolor);

CASE 2:
Ellipse(l, t, x-l, y-t, drawcolor, drawcolor);

CASE 3:
StopTimer();
}

return true;
}

DrawWnd::OnRButtonUp(int x, int y, int flags), int
{
CMenu m;
m.BeginContextMenu();
m.MenuItem("Color",0,99);
m.MenuItem( "Clear",0,1);
m.BeginPopup( "Line Size");
m.MenuItem( "1",(linesize = 1) * AMF_CHECKED,2);
m.MenuItem( "2",(linesize = 2) * AMF_CHECKED,3);
m.MenuItem( "3",(linesize = 3) * AMF_CHECKED,4);
m.MenuItem( "4",(linesize = 4) * AMF_CHECKED,5);
m.EndPopup();
m.EndMenu();

ShowContextMenu(m.Detach(), x, y);

return true;
}

DrawWnd::OnMenuPick(int nID), int
{
int w, h;
unsigned int hBitmap;

string filter, filename;

rect rcClient;

//clear the window
IF(nID = 1)
{
//GETSCREENSIZE w,h
w = GetSystemMetrics(0);
h = GetSystemMetrics(1);
DrawRect(0, 0, w, h, RGB(255,255,255), RGB(255,255,255));
}

//set line size
IF(nID > 1 & nID < 6)
{
SetLineStyle(LSSOLID, nID - 1);
linesize = nID - 1;
}

//pick a tool
IF(nID > 5 & nID < 11)
{
mode = nID - 6;
}

//'pick a color
IF(nID = 99)
{
temp = drawcolor;
drawcolor = ColorRequest(this,drawcolor);
IF(drawcolor = -1)
drawcolor = temp;
FrontPen(drawcolor);
}

//quit
IF nID = 100
{
run = 0;
}

//print
IF nID = 101
{
PrintWindow();
}

//save the image
IF nID = 102
{
filter = "Bitmap Files (*.bmp)|*.bmp||";
filename = FileRequest("Save Bitmap", this, 0, filter, "bmp");

if len(filename)
{
rcClient = GetClientRect();
SaveBitmap(filename, rcClient.left, rcClient.top, rcClient.right-rcClient.left, rcClient.bottom-rcClient.top);
}
}

//load a btimap
IF nID = 103
{
filter = "Bitmap Files (*.bmp)|*.bmp||";
filename = FILEREQUEST("Load Bitmap", this, 1, filter, "bmp");
if len(filename)
{
CBitmap bmp;
if bmp.LoadFromFile(filename,0)
{
w = GetSystemMetrics(0);
h = GetSystemMetrics(1);
DrawRect( 0, 0, w, h, RGB(255,255,255), RGB(255,255,255) );
size = bmp.GetSize();
bmp.Render(this, 0, 0, size.x, size.y);
}
else
MessageBox(this, "Unable to load image", "Error");
}
}
return true;
}


DrawWnd::OnMenuInit(unsigned int hMenu),int
{
CMenu m;
m.Attach(hMenu);
m.CheckMenuItem(6,(mode = 0));
m.CheckMenuItem(7,(mode = 1));
m.CheckMenuItem(8,(mode = 2));
m.CheckMenuItem(9,(mode = 3));
m.CheckMenuItem(10,(mode = 4));
m.CheckMenuItem(2,(linesize = 1));
m.CheckMenuItem(3,(linesize = 2));
m.CheckMenuItem(4,(linesize = 3));
m.CheckMenuItem(5,(linesize = 4));
m.Detach();
return false;
}


DrawWnd::OnTimer(int nIDEvent), int
{
float temp, temp2, out1, out2;
int x;

for( x = 0; x < 10;x++)
{
temp = RND(360) * (3.1415/180.0);
temp2 = RND(10);
out1 = SIN(temp) * temp2;
out2 = COS(temp) * temp2;
SetPixel(tempx+out1,tempy+out2);
}

return true;
}

// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// methods for saving bitmap files
DrawWnd::SaveBitmap(string filename, int left, int top, int width, int height)
{
int hdcWin;
int hdcComp, hbitmap, hbitmapold, quadsize;

BITMAPINFOHEADER info;

BITMAPFILEHEADER fileheader;

unsigned int *lpbits; // memory
unsigned int *lpbminfo; // memory

unsigned int fileb; //bfile

RtlZeroMemory( info, len( BITMAPINFOHEADER ));
RtlZeroMemory( fileheader, len( BITMAPFILEHEADER ));

hdcWin = GetHDC();  // virtual IntPtr GetHdc() Gets the handle to the device context associated with this Graphics

hdcComp = CreateCompatibleDC(hdcWin);

if (hdcComp = 0)
{
messagebox(this, "Couldn't create DC", "Error");
ReleaseHDC(hdcWin);
return;
}
hbitmap = CreateCompatibleBitmap(hdcwin, width, height);

if (hbitmap = 0)
{
messagebox( this, "Couldn't create bitmap", "Error");
ReleaseHDC( hdcWin );
return;
}

hbitmapold = SelectObject(hdcComp, hbitmap);

BitBlt(hdcComp, 0, 0, width, height, hdcWin, left, top, 0x00CC0020);
SelectObject(hdcComp, hbitmapold);
DeleteDC(hdcComp);

// at this point hbitmap contains a valid bitmap handle.
// fill in the BITMAPINFOHEADER and compute the color data
quadsize = CreateInfoStructure( hbitmap, info );
// allocate memory and get the 'bits' of the bitmap
lpbits = GlobalAlloc(0x40, info.biSizeImage );       // allocmem( lpbits, 1, info.biSizeImage );
lpbminfo = GlobalAlloc(0x40,  len(info) + quadsize ); // allocmem( lpbminfo, 1, len(info) + quadsize );

RtlMoveMemory( lpbminfo, &info, len(info));  // writemem( lpbminfo, 1, info );
// RtlMoveMemory(dest as int, source as int, size as int);

GetDIBits( hdcWin, hbitmap, 0, info.biHeight, lpbits, lpbminfo, 0 );

// open a binary file and write the header, color data and bitmap bits
fileb = openfile(filename, MODE_CREATE | MODE_WRITE);
if(fileb <> 0)
{
fileheader.bfType = 0x4d42;
fileheader.bfSize = len(fileheader) + info.biSize + quadsize + info.biSizeImage;
fileheader.bfOffBits = len(fileheader) + info.biSize + quadsize;
write( fileb, fileheader, len(fileheader) );
write( fileb, lpbminfo, len(info) + quadsize );
write( fileb, lpbits, info.biSizeImage );
closefile( fileb );
}

GlobalFree( lpbminfo );
GlobalFree( lpbits );

ReleaseHDC( hdcWin );
DeleteObject( hbitmap );

return;
}


DrawWnd::CreateInfoStructure(int hbitmap, BITMAPINFOHEADER info),int
{
bitmap bmp;

word cClrBits;
int quadsize = 0;

GetObjectA(hbitmap, len(bmp), &bmp);

cClrBits = bmp.bmPlanes * bmp.bmBitsPixel;

    if (cClrBits = 1)
{
cClrBits = 1;
}
    else if (cClrBits <= 4)
{
cClrBits = 4;
}
    else if (cClrBits <= 8)
{
cClrBits = 8;
}
    else if (cClrBits <= 16)
{
cClrBits = 16;
}
    else if (cClrBits <= 24)
{
cClrBits = 24;
}
    else
        {
cClrBits = 32;
}

    info.biSize = len( info );
    info.biWidth = bmp.bmWidth;
    info.biHeight = bmp.bmHeight;
    info.biPlanes = bmp.bmPlanes;
    info.biBitCount = bmp.bmBitsPixel;

    if (cClrBits < 24) { info.biClrUsed = 2^cClrBits; }

info.biCompression = 0;
info.biSizeImage = (info.biWidth + 7.0) / 8.0 * (info.biHeight) * cClrBits;

if(cClrBits < 24) { quadsize = 4 * (2^cClrBits); }

return quadsize;
}
Ionic Wind Support Team

John S

Thanks Paul,
My original version (which compiled)  didn't use pointers, but it didn't work.  When I reviewed some of the MSDN info, it looked like there was some pointers required, but I didn't have time to get it all straight.  I probably should have uploaded the original port.

It's really late here, so I'll look at it and apply it tomorrow.

Thanks again and Merry Christmas!
John Siino, Advanced Engineering Services and Software