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 } } }
/***************************** 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); }