ilteris kaplan blog

Archive of blog posts since 2005

April 5, 2008

Wiki

Threshold

#wiki

Threshold

Step by Step

*Reference Link Basically threshold works like this, if the R+G+B values of a pixel is above a threshold value we set them white, and if they are below we set them to black. In our application, our threshold value is our mouse location in y axis. So when we change this, we see a gradual shift in the bit-map. Here is the code for this:


for(x=0;x<640;x++){	
     for(y=0;y<480;y++){
          ourGetPixel(x,y,&R,&G,&B,imageRowBytes,imageBaseAddress); 
         // geting the color value of a pixel in our image buffer,
          // note that we need to pass 
          if (R+G+B > mousepoint.h ){
         ourSetPixel(x,y,0,0,0,bufferRowBytes,bufferBaseAddress);
         // calling our method that set individual pixels and expects
         // : X coordinate of the pixel,
         // y coordinate of the pixel, R value, G value, B value, the 
        // number of bytes in each row of the pixel map, the base   
         }else{	
             ourSetPixel(x,y,255,255,255,bufferRowBytes,bufferBaseAddress);
            // address in memory of the begining of the pixel data
             }	
        }
  }

Source Code



/*****************************         Threshold.c Mac   *************************/


void 	Initialize(void);											// function prototypes
void	DrawLine( void );
void	doEventLoop( void );
void 	DrawToBuffer(void);
void 	CopyToWindow (void);
int 	ourRandom(  int min,  int max );
void ourSetPixel(unsigned short horizontal,unsigned short vertical,unsigned char R,unsigned char G,unsigned char B,unsigned short rowbytes,Ptr pixbase);
void ourGetPixel(unsigned short horizontal,unsigned short vertical,unsigned char* R,unsigned char* G,unsigned char* B,unsigned short rowbytes,Ptr pixbase);
void ImportFile(GWorldPtr destWorld,int left,int top,int right, int bottom);



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

void DrawToBuffer(void)   												// this is where the interesting stuff happens, this is where we actually set our pixels
{
	long x , y,temp,distance;
	Point mousepoint;
	unsigned short bufferRowBytes,imageRowBytes ;
	Ptr bufferBaseAddress,imageBaseAddress;
	PixMapHandle bufferPixmap, imagePixmap;
	unsigned char R,G,B;
	count++;
	GetMouse(&mousepoint);			
	
	bufferPixmap=GetGWorldPixMap(ourBuffer);									// getting the pixel map of our buffer GWorld so that we can access the pixels
	bufferRowBytes  = ((*(bufferPixmap))->rowBytes) & 0x7fff;						* getting the number of bytes in each row of the pixel map. This is then used to																			* calculate the location in memory of specific pixels
	bufferBaseAddress   = GetPixBaseAddr(bufferPixmap );								// getting the base address in memory of the begining of the pixel data

	imagePixmap=GetGWorldPixMap(ourImage);									// getting the pixel map of our buffer GWorld so that we can access the pixels
	imageRowBytes  = ((*(imagePixmap))->rowBytes) & 0x7fff;						* getting the number of bytes in each row of the pixel map. This is then used to																			* calculate the location in memory of specific pixels
	imageBaseAddress   = GetPixBaseAddr(imagePixmap );				

	distance = (mousepoint.v-320);
	for(x=0;x<640;x++){														 
		for(y=0;y<480;y++){												
			ourGetPixel(x,y,&R,&G,&B,imageRowBytes,imageBaseAddress);			// geting the color value of a pixel in our image buffer , note that we need to pass 
			if (R+G+B > mousepoint.h ){															
				ourSetPixel(x,y,0,0,0,bufferRowBytes,bufferBaseAddress);
* calling our method that set individual pixels and expects : X coordinate of the pixel,																			* y coordinate of the pixel, R value, G value, B value, the number of bytes in each row of the pixel map, the base 
			}else{	
			ourSetPixel(x,y,255,255,255,bufferRowBytes,bufferBaseAddress);															// address in memory of the begining of the pixel data
			}	
		}																
	}																																		
}




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,  "\pThreshold", 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();
	error =NewGWorld(&ourImage, 32, &windRect, nil, nil,0 );	
		if (error != noErr ) ExitToShell();
	
	ImportFile(ourImage,0,0,640,480);												// Calling our method that opens a picture file and returns a picture handle
	
	
}

/*************** 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 );
					}
				}
				else if (clickArea == inGoAway)
					if (TrackGoAway( evtWind, anEvent.where ))
						return;
			}
		}
		DrawToBuffer();														// after checking for various events we call our drawing finctions
		CopyToWindow();
	}
}



int ourRandom(  int min,  int max ){										// method that returns a random number between min and max						
	return( (Random()+32768) /((32768*2/) (max-min)))+ min;

}


void ourSetPixel(unsigned short horizontal,unsigned short vertical,unsigned char R,unsigned char G,unsigned char B,unsigned short rowbytes,Ptr pixbase){
	Ptr AdressOfRed;
	AdressOfRed = rowbytes * vertical +pixbase+horizontal*4+1;
*(AdressOfRed)=R;
*(AdressOfRed+1)=G;
*(AdressOfRed+2)=B;
}

void ourGetPixel(unsigned short horizontal,unsigned short vertical,unsigned char* R,unsigned char* G,unsigned char* B,unsigned short rowbytes,Ptr pixbase){
	Ptr AdressOfRed;
	AdressOfRed = rowbytes * vertical +pixbase+horizontal*4+1;
*R=*(AdressOfRed);
*G=*(AdressOfRed+1);
*B=*(AdressOfRed+2);
}



void ImportFile(GWorldPtr destWorld,int left,int top,int right, int bottom){							// this method imports a file and returns a picture handle . it uses Quicktime so it can
																										//	import almost any file format including JPG , Pict, Photoshop, EPS, BMP, GIF and many more.
	Rect				recti;																			// you must have the QuickTime.lib in your project to compile, and have Quicktime installed to run
	PicHandle			theNewPic;
	OSErr myError;
	ComponentInstance gi;
	FSSpec fsp;
	Point where;
	AEKeyword  myKeyword;
	DescType  myActualType;
	Size   myActualSize ;
	NavReplyRecord navreply;
	where.h=200; where.v=100;    									 /* where the  Standard File dialog window goes */

	NavGetFile (NULL, &navreply,NULL,NULL,NULL,NULL,NULL,NULL);
	if (AEGetNthPtr(&(navreply.selection), 1, typeFSS, &myKeyword, &myActualType, &fsp, sizeof(fsp), &myActualSize)!= noErr) SysBeep(10);

	myError=GetGraphicsImporterForFile(&fsp,&gi);
	myError=GraphicsImportGetAsPicture (gi,&theNewPic);		
	CloseComponent(gi);	

	SetRect(&recti,left,top,right,bottom);
	SetPort((GrafPtr)destWorld);		
	DrawPicture(theNewPic,&recti);										// drawing the imported picture onto the second buffer 
	KillPicture(theNewPic);
}

Continue Reading

Back to Archive