Jump to content
  • Advertisement
Sign in to follow this  
Dan Forever

Converting a function from VB to C++

This topic is 5022 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

"What madness is this?!" I hear you say? Well, I have some perfectly good VB code from days gone by that will rotate an image by a specified angle and place the rotated image in a picturebox. I want to try and copy it over to c++, and I'm almost, but not quite, successful. Heres what I've got: The original method for rotating images. They are first rotated into a pictureBox as an intermediary, and then the contents of the picture box is drawn to the window after this function is called.
Private Sub RotatePic(Theta As Single, ByVal Index As Integer)
Dim c1x As Integer, c1y As Integer
Dim c2x As Integer, c2y As Integer
Dim p1x As Integer, p1y As Integer
Dim p2x As Integer, p2y As Integer
Dim a As Single
Dim n As Integer, r As Integer
Dim P1Hdc As Long, P2Hdc As Long
' Get the device context - saves time in loop
P1Hdc = hdcSrc(Index)
P2Hdc = Transfer(Index).hdc
c1x = hdcWidth(Index) \ 2
c1y = hdcHeight(Index) \ 2
c2x = Transfer(Index).ScaleWidth \ 2
c2y = Transfer(Index).ScaleHeight \ 2
Dim c0 As Long, c1 As Long, c2 As Long, c3 As Long, xret As Long
If c2x < c2y Then n = c2y Else n = c2x
n = n - 1

Dim test As Long

For p2x = 0 To n
   For p2y = 0 To n
      If p2x = 0 Then a = Pi / 2 Else a = Atn(p2y / p2x)
      r = Sqr(1& * p2x * p2x + 1& * p2y * p2y)
      p1x = r * Cos(a + Theta)
      p1y = r * Sin(a + Theta)
      c0 = GetPixel(P1Hdc, c1x + p1x, c1y + p1y)
      c1 = GetPixel(P1Hdc, c1x - p1x, c1y - p1y)
      c2 = GetPixel(P1Hdc, c1x + p1y, c1y - p1x)
      c3 = GetPixel(P1Hdc, c1x - p1y, c1y + p1x)
      
      If c0 <> -1 Then xret = SetPixel(P2Hdc, c2x + p2x, c2y + p2y, c0)
      If c1 <> -1 Then xret = SetPixel(P2Hdc, c2x - p2x, c2y - p2y, c1)
      If c2 <> -1 Then xret = SetPixel(P2Hdc, c2x + p2y, c2y - p2x, c2)
      If c3 <> -1 Then xret = SetPixel(P2Hdc, c2x - p2y, c2y + p2x, c3)
   Next
Next

Transfer(Index).Refresh
End Sub


The same function, as I have attempted to write in C++ I've tried my best to copy the original vb function, but for some reason, there is something wrong with this. It is drawing to the screen, but the image is mangled into four seperate bits, each bit is close to what it should look like, but is slightly stretched/warped. There is also a clear line between each 'section'
inline ErrorType rotateImage(MyPicture* image, MyPicture* transfer, double angle)
	{
	if(!image || !transfer)
		return FAILURE;

	int imgHalfWidth	= image->width/2;
	int imgHalfHeight	= image->height/2;

	int transferHalfWidth	= transfer->width/2;
	int transferHalfHeight	= transfer->height/2;

	int x1;
	int y1;
	double a;
	int r;

	int c0, c1, c2, c3;
	int n;

	if(transferHalfWidth>transferHalfHeight)
		n = transferHalfWidth;
	else
		n = transferHalfHeight;

	image->LockBackSurface();
	transfer->LockBackSurface();
	for(int x2=0;x2<=n;++x2)
		{
		for(int y2=0;y2<=n;++y2)
			{
			if(x2==0)
				a = M_PI_2;
			else
				a = atan(double(y2 / x2));

			r = sqrt(double(x2*x2+y2*y2));
			x1 = r * cos(a+angle);
			y1 = r * sin(a+angle);

			c0 = image->GetPoint(imgHalfWidth+x1, imgHalfHeight+y1);
			c1 = image->GetPoint(imgHalfWidth-x1, imgHalfHeight-y1);
			c2 = image->GetPoint(imgHalfWidth+y1, imgHalfHeight-x1);
			c3 = image->GetPoint(imgHalfWidth-y1, imgHalfHeight+x1);

			if(c0!=-1) transfer->DrawPoint(transferHalfWidth+x2, transferHalfHeight+y2, c0);
			if(c1!=-1) transfer->DrawPoint(transferHalfWidth-x2, transferHalfHeight-y2, c1);
			if(c2!=-1) transfer->DrawPoint(transferHalfWidth+y2, transferHalfHeight-x2, c2);
			if(c3!=-1) transfer->DrawPoint(transferHalfWidth-y2, transferHalfHeight+x2, c3);

			}
		}
	transfer->UnlockBackSurface();
	image->UnlockBackSurface();

	return SUCCESS;
	}


Here are some images to better explain the difference: VB: C++: Can anyone see any discrepancies between how each function works that could be causing the c++ function to misbehave? GetPoint() and DrawPoint() are equivalent functions afaik. The VB functions are declared thusly:
Declare Function SetPixel Lib "gdi32" (ByVal hdc As Long, ByVal X As Long, ByVal Y As Long, ByVal crColor As Long) As Long
Declare Function GetPixel Lib "gdi32" (ByVal hdc As Long, ByVal X As Long, ByVal Y As Long) As Long


Share this post


Link to post
Share on other sites
Advertisement
One thing that may be causing your problems, is conversions - vb rounds values on conversions, while C++ truncates values, if I recall correctly - check on any place where you do operations that might result in floating point values and do explicit rounding in C++, and see if that fixes it.

Alex

Share this post


Link to post
Share on other sites
Quote:
Original post by alexmoura
One thing that may be causing your problems, is conversions - vb rounds values on conversions, while C++ truncates values, if I recall correctly - check on any place where you do operations that might result in floating point values and do explicit rounding in C++, and see if that fixes it.

Alex
Doesn't seem to fix it. I seem to recall that in VB the operator "\" is 'integer' division and "/" is, er, not. Browsing the MSDN though, it didn't actually seem to want to tell me what that actually means. :/

Share this post


Link to post
Share on other sites
to me it seems like your picture and transfer object in the c++ code are the same, what could cause these strange rotation view, while in vb this may be possible cause images get updated evry frame and keep their pixel values till the next update or what if the picture is drawn while the pixelvalues are changed, you would get an pretty ugly picture like what you get now

sry for my bad english, i hope it helped

Share this post


Link to post
Share on other sites
'\' gives you only the integer part, like 10 \ 3 = 3

'/' gives you a floating point result, like 10 / 3 = 3.333333 (normal division)

Share this post


Link to post
Share on other sites
\ in vb means that whenever you use it, the type of the result is an integer type (long, integer, etc) - I think it will also do the rounding instead of truncating - in any case, you have several other places where you cast floats to integers, have you tried also make those rounding? (especially the lines:
x1 = r * cos(a+angle);
y1 = r * sin(a+angle);
)

also, how are you doing the rounding?

Share this post


Link to post
Share on other sites

inline double roundNum(const double &num)
{
if(num-(int)num>=0.5)
{
return ceil(num);
}
else
{
return floor(num);
}
}

inline ErrorType rotateImage(MyPicture* image, MyPicture* transfer, double angle)
{
if(!image || !transfer)
return FAILURE;

int imgHalfWidth = image->width/2;
int imgHalfHeight = image->height/2;

int transferHalfWidth = transfer->width/2;
int transferHalfHeight = transfer->height/2;

int x1;
int y1;
double a;
int r;

int c0, c1, c2, c3;
int n;

if(transferHalfWidth>transferHalfHeight)
n = transferHalfWidth;
else
n = transferHalfHeight;

image->LockBackSurface();
transfer->LockBackSurface();
for(int x2=0;x2<=n;++x2)
{
for(int y2=0;y2<=n;++y2)
{
if(x2==0)
a = M_PI_2;
else
a = atan(double(y2 / x2));

r = (int)roundNum(sqrt(double(x2*x2+y2*y2)));
x1 = (int)roundNum(r * cos(a+angle));
y1 = (int)roundNum(r * sin(a+angle));

c0 = image->GetPoint(imgHalfWidth+x1, imgHalfHeight+y1);
c1 = image->GetPoint(imgHalfWidth-x1, imgHalfHeight-y1);
c2 = image->GetPoint(imgHalfWidth+y1, imgHalfHeight-x1);
c3 = image->GetPoint(imgHalfWidth-y1, imgHalfHeight+x1);

if(c0!=-1) transfer->DrawPoint(transferHalfWidth+x2, transferHalfHeight+y2, c0);
if(c1!=-1) transfer->DrawPoint(transferHalfWidth-x2, transferHalfHeight-y2, c1);
if(c2!=-1) transfer->DrawPoint(transferHalfWidth+y2, transferHalfHeight-x2, c2);
if(c3!=-1) transfer->DrawPoint(transferHalfWidth-y2, transferHalfHeight+x2, c3);

}
}
transfer->UnlockBackSurface();
image->UnlockBackSurface();

return SUCCESS;
}



I couldn't see any predefined round() function, so I made my own. Tested with rounding on and off the the *HalfWidth variables as well, doesn't appear to make any kind of noticable difference

Share this post


Link to post
Share on other sites
little trick for random function :) (yours works fine, but this one should be faster):
return cint(i + 0.5)

the only thing I can see that's different is that you're not setting n= n-1 on the C++ code, but I don't know if that's intentional - it would seem to imply that since both for cycles are zero based, you're going one extra point on the C++ cycles, but I've got a nagging feeling I'm missing something and that was intentional :)

Share this post


Link to post
Share on other sites
bah! I should have thought of that, I've seen it before as well, that little trick. Cheers :)

as for not setting n=n-1; I've tried that, no visible difference. I suspect in the vb code it's there before the for next goes from "0 to n", whereas the c++ for next is "while x<n" If you see what I mean.

Share this post


Link to post
Share on other sites
in vb, for x= o to n will go through all the values including n - the truth is that it probably doesn't change the end result, as long as it's inside the image - the original code might just not be translating the right edge of the picture.

there's one last thing that I could see being the issue, if for any reason on the C++ code you're invoking the method with different sized images, but that sounds unlikely.

What I'd suggest now would be to start printing values for identical inputs and find out where they differ :)

Sorry I couldn't be of more help.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!