void Blob::eventBlit(SDL_Surface* surface, const PG_Rect& scr, const PG_Rect& dst){ PG_ThemeWidget::eventBlit(explosion_surface, scr, dst); if ( vmem1 != (unsigned char *)explosion_surface->pixels ) { p1= vmem1=(unsigned char *)explosion_surface->pixels; for (int i=0;i<YSIZE;i++) { mul640[i]=i*explosion_surface->pitch+vmem1; memset(p1,0,XSIZE); p1+=explosion_surface->pitch; } } now++; if(!flash) { if(explodenum>96 && explodenum<160 && !(rand()&511)) flash=60; } else --flash; explodenum=(now>>4)+1; if(explodenum==320) now=0; if(explodenum>256) explodenum=256; if(!(rand()&31)) addblob(); moveblobs(); putblobs(); p1=vmem1; p2=vmem2; int k=explosion_surface->pitch; for(int i=0;i<YSIZE;i++) { memcpy(p2,p1,XSIZE); p2+=XSIZE; p1+=k; } fire(vmem2,vmem1,k,flash ? remap2 :remap); }
void frameblob::calc_searchgrid() { // First calculate dimensions of the searchgrid array unsigned int xfull, yfull, xextra, yextra, xdim, ydim; xfull = xpix / grid; // # of full-sized cells yfull = ypix / grid; xextra = xpix % grid; // # extra pixels in small edge cells yextra = ypix % grid; xgrid = (xfull + (xextra>0)); // total # grid cells ygrid = (yfull + (yextra>0)); ngrid = (xgrid+xextra) * ygrid; // unallocate searchgrid and meangrid before we start in case we have // run this function several times delete searchgrid; delete meangrid; searchgrid = new double[ngrid]; // S/N of brightest pixel/grid cell meangrid = new double[ngrid]; // array of grid cell means // Allocate an array to contain all the GRID*GRID elements within this // grid cell of our input map MAPTYPE *cell; cell = new MAPTYPE[grid*grid]; MAPTYPE pix; // current pixel values MAPTYPE max; // the maximum value pixel in the cell int total; // running total elements in cell (big number) double meancell ; // cell mean double level; // max adjusted by centre value double sn; // signal to noise level of brightest pixel double x; // x and y pixel positions for brightest pixels double y; // for the large input map unsigned int i, j, k, l, mapindex, cellindex; int startx, endx, starty, endy; double thisflux; double M[D][D]; // small map centred over blob candidate double xcen, ycen, nap; int clip_startx, clip_endx, clip_starty, clip_endy; int count=0; clearblobs(); // Make sure we don't have old blobs sitting around for( i=0; i<xgrid; i++ ) for( j=0; j<ygrid; j++ ) { // Sum all the elements within this cell of the input map. // Also make a list of the elements in the cell cellindex = 0; total = 0; max = 0; // Pixel dimensions of grid cell. grix*grid unless edge if( i==xfull ) xdim = xextra; else xdim = grid; if( j==yfull ) ydim = yextra; else ydim = grid; for( k=0; k<xdim; k++ ) for( l=0; l<ydim; l++ ) { mapindex = (j*grid+l)*xpix + (i*grid+k); pix = map[mapindex]; cell[cellindex] = pix; total += pix; // Check for greatest pixel brightness if( pix > max ) { x = (double) (i*grid + k); // store pixel coordinates y = (double) (j*grid + l); // of brightest pixel max = pix; } cellindex ++; // end of loop = # pixels in cell } // Get the mean for this cell meancell = (double) total / (cellindex); // Level is the brightness of a pixel - the mean level for the cell level = (double) max - meancell; // Calculate the sample variance about the central value if( mapmean == 0 ) calc_mapstat(); // Calculate the map mean if( mapmean < readout_offset ) sigma = readout_noise; else sigma = (double)sqrt(gain*(mapmean-readout_offset) + readout_noise*readout_noise); // Poisson if( sigma < 1 ) sigma = 1; // prevent 0 sigmas sn = level/sigma; // Store information about this grid cell searchgrid[j*xgrid+i] = sn; // s/n brightest pixel in cell meangrid[j*xgrid+i] = meancell; // mean of this cell // If we got a pixel > threshold sigma, possibly a source if( sn >= threshold ) { //printf("%i ",count); //count ++; // -------------------------------------------------------------- // Decide if this is a single-point spike or a real source startx = (int) x - 1; // Aperture boundaries starty = (int) y - 1; endx = (int) x + 1; endy = (int) y + 1; if( startx < 0 ) startx = 0; // clipping map boundaries if( endx >= (int) xpix ) endx = xpix-1; if( starty < 0 ) starty = 0; if( endy >= (int) ypix ) endy = ypix-1; thisflux = 0.; nap = (double) (endx-startx+1)*(endy-starty+1); // pixels in ap. // add up flux centred over bright pixel for( k=startx; k<=endx; k++ ) for( l=starty; l<=endy; l++ ) thisflux += (double) map[l*xpix + k]; // remove flux centre pixel and check remaining flux // exceeds the theoretical flux from pure noise // (check extendedness) thisflux -= max; // remove the baseline for the remaining pixels thisflux -= ((nap-1)*meancell); // Extended case if( (thisflux/(sqrt(nap-1)*sigma)) >= threshold ) { // ------------------------------------------------------------ // Re-calculate the baseline over perimeter of a larger box startx = (int) x - D/2; // box boundary starty = (int) y - D/2; endx = startx + D-1; endy = starty + D-1; if( startx < 0 ) startx = 0; // clipping for boundaries if( endx >= (int) xpix ) endx = xpix-1; if( starty < 0 ) starty = 0; if( endy >= (int) ypix ) endy = ypix-1; meancell = 0; for( k=startx; k<=endx; k++ ) meancell += (double) map[starty*xpix + k] + (double) map[endy*xpix + k]; for( l=starty+1; l<=endy-1; l++ ) meancell += (double) map[l*xpix + startx] + (double) map[l*xpix + endx]; meancell /= ( 2*(endx-startx) + 2*(endy-starty) ); // ------------------------------------------------------------ // Centroid the blob startx = (int) x - D/2; starty = (int) y - D/2; endx = startx + D-1; endy = starty + D-1; if( startx < 0 ) clip_startx = 0; // clipping for boundaries else clip_startx = startx; if( endx >= (int) xpix ) clip_endx = xpix-1; else clip_endx = endx; if( starty < 0 ) clip_starty = 0; else clip_starty = starty; if( endy >= (int) ypix ) clip_endy = ypix-1; else clip_endy = endy; // boundary case if( (startx != clip_startx) || (starty != clip_starty) || (endx != clip_endx) || (endy != clip_endy) ) { // fill the sub-map with the mean value for( k=0; k<D; k++ ) for( l=0; l<D; l++ ) M[k][l] = (double) meancell; // paste in the useful part of the map for( k=clip_startx-startx; k<clip_endx-startx; k++ ) for( l=clip_starty-starty; l<clip_endy-starty; l++ ) M[k][l] = (double) map[(l+clip_starty)*xpix + k+clip_startx]; } // normal case else { for( k=0; k<D; k++ ) for( l=0; l<D; l++ ) M[k][l] = (double) map[(l+starty)*xpix + k+startx]; } // Find the centroid in this small map findCentre( &xcen, &ycen, &thisflux, M ); // Correct for the baseline and final check realness thisflux = thisflux - meancell; //printf("Flux: %lf Sigma: %lf\n", //thisflux,sqrt(convweight)*sigma); // Add to the list if significant if( thisflux/(sqrt(convweight)*sigma) >= threshold ) { addblob( (int)thisflux, x+xcen+0.5, y+ycen+0.5 ); thisblob->setmean(meancell); thisblob->setsnr( (double)thisflux / (sqrt(convweight)*sigma) ); } } // -------------------------------------------------------------- } } // clean up delete cell; }
main(int argc, char *argv[]) { int i,k; char *remap,*remap2; unsigned char *p1, *p2; long frames; int flash; int whichmap; int key; int ispaused; unsigned long videoflags; int done; int now; SDL_Event event; long starttime; int buttonstate; srand(time(NULL)); if ( SDL_Init(SDL_INIT_VIDEO) < 0 ) { fprintf(stderr, "Couldn't initialize SDL: %s\n",SDL_GetError()); exit(1); } videoflags = SDL_SWSURFACE|SDL_FULLSCREEN|SDL_HWPALETTE; thescreen = SDL_SetVideoMode(XSIZE, YSIZE, 8, videoflags); if ( thescreen == NULL ) { fprintf(stderr, "Couldn't set display mode: %s\n", SDL_GetError()); SDL_Quit(); exit(5); } vmem1=NULL; vmem2=malloc(XSIZE*YSIZE); if(!vmem2) nomem(); mul640=malloc(YSIZE*sizeof(char *)); if(!mul640) nomem(); remap=malloc(16384); if(!remap) nomem(); remap2=malloc(16384); if(!remap2) nomem(); blobs=malloc(MAXBLOBS*sizeof(struct blob)); if(!blobs) nomem(); puts("Fire demo by David Ashley ([email protected])"); puts("1 = Change color map"); puts("2 = Randomly change color map"); puts("p = Pause"); puts("spc = Fire"); puts("esc = Exit"); puts("Left mouse button = paint"); puts("Right mouse button, CR = ignite atmosphere"); freeblobs=activeblobs=0; for(i=0;i<MAXBLOBS;i++) { blobs[i].blobnext=freeblobs; freeblobs=blobs+i; } normal(remap); bright(remap2); flash=0; whichmap=0; loadcolors(whichmap); frames=0; ispaused=0; addblob(); done = 0; now=0; starttime=SDL_GetTicks(); buttonstate=0; mousex=mousey=0; while(!done) { if ( scrlock() < 0 ) continue; frames++; if ( vmem1 != (unsigned char *)thescreen->pixels ) { p1=vmem1=thescreen->pixels; for (i=0;i<YSIZE;i++) { mul640[i]=i*thescreen->pitch+vmem1; memset(p1,0,XSIZE); p1+=thescreen->pitch; } } if(!ispaused) { now++; if(!flash) { if(explodenum>96 && explodenum<160 && !(rand()&511) || (buttonstate&8)) flash=60; } else --flash; explodenum=(now>>4)+1;if(explodenum==320) now=0; if(explodenum>256) explodenum=256; if(!(rand()&31)) addblob(); moveblobs(); putblobs(); if(buttonstate&2) trydisk(); p1=vmem1; p2=vmem2; k=thescreen->pitch; for(i=0;i<YSIZE;i++) { memcpy(p2,p1,XSIZE); p2+=XSIZE; p1+=k; } fire(vmem2,vmem1,k,flash ? remap2 :remap); } scrunlock(); while(SDL_PollEvent(&event)) { switch (event.type) { case SDL_MOUSEBUTTONDOWN: case SDL_MOUSEBUTTONUP: if ( event.button.state == SDL_PRESSED ) buttonstate|=1<<event.button.button; else buttonstate&=~(1<<event.button.button); mousex=event.button.x; mousey=event.button.y; if(!ispaused && buttonstate&2) trydisk(); break; case SDL_MOUSEMOTION: mousex=event.motion.x; mousey=event.motion.y; if(!ispaused && buttonstate&2) trydisk(); break; case SDL_KEYDOWN: key=event.key.keysym.sym; if(key==SDLK_RETURN) {flash=60;break;} if(key==SDLK_1 || key==SDLK_2) { if(key==SDLK_1) ++whichmap; else whichmap=rand(); loadcolors(whichmap); break; } if(key==SDLK_ESCAPE) {done=1;break;} if(key==SDLK_SPACE && !ispaused) {addblob();break;} if(key==SDLK_p) {ispaused=!ispaused;break;} break; case SDL_QUIT: done = 1; break; default: break; } } }