ilteris kaplan blog

Archive of blog posts since 2005

April 5, 2008

Wiki

Slow Setting Pixels

#wiki

Slow Setting Pixels

Step by Step

In this example what we see is, if we use native function of quickdraw which sets pixels, it is going to be slower. The reason for this, we are using too much calculations all at once and also we are not even using direct memory access to the pixels. Thus giving us a poor performance.



void DrawToBuffer(void)   {
	long x , y;
	Point mousepoint;
	unsigned short distance;
	unsigned char R,G,B;
	RGBColor ourColor;
	count++;
	SetPortWindowPort(ourWindow);	
         GetMouse(&mousepoint);
         SetPort(ourBuffer);
	for(x=0;x<640;x++){
             for(y=0;y<480;y++){
             distance = sqrt((x-mousepoint.h)*(x-mousepoint.h)+(y-mousepoint.v)*(y-mousepoint.v));
              // x minus xmouse and square root in the end. this is slowing down since we are using so much calculations.
              R = distance+mousepoint.h+count;
              // giving R,G and B some values that change with the distance from the mouse
              G = distance+mousepoint.v+count;
              B = mousepoint.h;
              ourColor.red = 	R*256;
              // an RGBColor expects numbers in the range of an unsigned short
              ourColor.green =G*256;
              //  so we need to make our numbers bigger 
              ourColor.blue = B*256;
              SetCPixel(x,y,&ourColor);  // drawing through this function, this is coming from quickdraw. 
		/* but it is very slow, what that means to us is, if we use operating system's native 
drawing functions it will  be still so slow. In order to bypass that, we should low level, 
and getting colors for the pixels directly from the memory. 
*/	
		}					
	}																						
}

In order to make this faster we are going to use our SetPixel function in the next example.

Source Code


void 	Initialize(void);											// function prototypes
void	DrawLine( void );
void	doEventLoop( void );
void 	DrawToBuffer(void);
void 	CopyToWindow (void);

																	//globals
WindowPtr	ourWindow;
Rect		windRect;
GWorldPtr	ourBuffer;
int			count=0;

void DrawToBuffer(void)   												// this is where the interesting stuff happens, this is where we actually set our pixels
{
	long x , y;
	Point mousepoint;
	unsigned short distance;
	unsigned char R,G,B;
	RGBColor ourColor;
	
	count++;
	SetPortWindowPort(ourWindow);													
	GetMouse(&mousepoint);
	
	SetPort(ourBuffer);
	for(x=0;x<640;x++){														 
		for(y=0;y<480;y++){					
			
			 distance = sqrt((x-mousepoint.h)*(x-mousepoint.h)+(y-mousepoint.v)*(y-mousepoint.v));	
			// x minus xmouse and square root in the end. this is slowing down since we are using so much calculations. 
			 R = distance+mousepoint.h+count;										// giving R,G and B some values that change with the distance from the mouse
			 G = distance+mousepoint.v+count;
			 B = mousepoint.h;
			 
			ourColor.red = 	R*256;												// an RGBColor expects numbers in the range of an unsigned short,
			ourColor.green =G*256;												//  so we need to make our numbers bigger 
			ourColor.blue = B*256;							
			SetCPixel(x,y,&ourColor);  // drawing through this function, this is coming from quickdraw. 
									// but it is very slow, what that means to us is, if we use operating system's native drawing functions it will
			// be still so slow. In order to bypass that, we should low level, and getting colors for the pixels directly from the memory. 
			
		}																	
	}																																		
}

void CopyToWindow (void){													//  copy all our buffer to the window, completely replaceing 
																			//  everything that was there
	Rect sourceRect,destRect;
	SetPortWindowPort(ourWindow);
	GetPortBounds( GetWindowPort(ourWindow), &destRect ); 
	GetPortBounds( ourBuffer, &sourceRect ); 
	 CopyBits( GetPortBitMapForCopyBits( ourBuffer ), GetPortBitMapForCopyBits(GetWindowPort(ourWindow)),
                &sourceRect, &destRect, srcCopy, NULL );
																
}
	
	
	
void	main( void )

{
	Initialize();
	doEventLoop();
	
}


void 	Initialize(void){

	OSErr		error;
	SetRect(&windRect,100,100,740,580);
	InitCursor();
	ourWindow = NewCWindow( 0L, &windRect,  "\pSlow Setting Pixels", true, noGrowDocProc,(WindowPtr)-1L, true, 0L ); 
	if ( ourWindow == nil )	ExitToShell();
	
	ShowWindow( ourWindow );
	SetPortWindowPort( ourWindow );
	SetRect(&windRect,0,0,640,480);
	error =NewGWorld(&ourBuffer, 32, &windRect, nil, nil,0 );					// creating our offscreen buffer
	if (error != noErr ) ExitToShell();
	
}

/*************** The Event Loop ***************/
void doEventLoop()
{
	EventRecord anEvent;
	WindowPtr   evtWind;
	short       clickArea;
	Rect        screenRect;
	Point		thePoint;

	for (;;)
	{

		if (WaitNextEvent( everyEvent, &anEvent, 0, nil ))
		{
			if (anEvent.what == mouseDown)
			{
				clickArea = FindWindow( anEvent.where, &evtWind );
				
				if (clickArea == inDrag)
				{
					GetRegionBounds( GetGrayRgn(), &screenRect );
					DragWindow( evtWind, anEvent.where, &screenRect );
				}
				else if (clickArea == inContent)
				{
					if (evtWind != FrontWindow())
						SelectWindow( evtWind );
					else
					{
						thePoint = anEvent.where;
						GlobalToLocal( &thePoint );
						//Handle click in window content here
					}
				}
				else if (clickArea == inGoAway)
					if (TrackGoAway( evtWind, anEvent.where ))
						return;
			}
		}
		DrawToBuffer();														// after checking for various events we call our drawing finctions
		CopyToWindow();
	}
}

Continue Reading

Back to Archive