Thread: mandelbrot set program improvements

  1. #1
    Registered User
    Join Date
    Aug 2006
    Posts
    54

    mandelbrot set program improvements

    I wrote a mandelbrot set progam in c a while back and posted it here at cprogramming .. one of the comments I got was there were too many global variables ..

    having problems with a new install of linux as well as trying to fix my program I rewrote it and it works like it used too .. Im using debian lenny amd64 2.6.26-2-amd64 kernel and gcc ( debian 4.3.2-1.1 ) 4.3.2

    however 1 ) Im not sure what I wrote is an improvement and .. 2 ) I would like to use color smoothing but even after reading a lot of forums I still not sure how to implement it ..

    so heres my code any hints appreciated regards improvements even if it means starting from scratch ..

    first program
    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include <SDL/SDL.h>
    struct foo{
    	int xscreen,yscreen,Nxscreen,Nyscreen;
    	int base,max,a,b,c,d,x,y,z;
    	
    	Uint32 color;
    	long double s,t,u,v;
    	long double real,imaginary,ximage,yimage,xoff,yoff;
    	}bar;
    
    SDL_Surface *screen;
    SDL_Event event;
    
    	int number_base();
    	void change_color ( int count );
    	void sdl_screen_size();
    	void image();
    	void mousebutton_event();
    	void putpixel();
    	void iterate();
    	void real_imaginary();
    	void lock_screen();
    	void unlock_screen();
    	void set_sdl();
    	void set_struct();
    
    void sdl_screen_size(){
    	struct foo *p;
    	p = &bar;
    
    	int t;
    
    	p->Nxscreen = p->a - p->c;
    	p->Nyscreen = p->b - p->d;
    
    	if( p->Nxscreen > p->Nyscreen ){
    		t = p->xscreen / p->Nxscreen;
    		}
    	else{
    		t = p->yscreen / p->Nyscreen;
    		}
    	if( t > 1 ){
    		p->Nxscreen = p->Nxscreen * t;
    		p->Nyscreen = p->Nyscreen * t;
    		}
    	printf("sdl_screen_size\n Nxscreen = %i Nyscreen %i\n"
    		,p->Nxscreen,p->Nyscreen );
    }
    void image(){
    	struct foo *p;
    	p = &bar;
    
    	p->s = (( p->ximage * p->c ) / p->Nxscreen ) - p->xoff;
    	p->u = (( p->ximage * p->a ) / p->Nxscreen ) - p->xoff;
    
    	p->t = p->yoff - (( p->yimage * p->d ) / p->Nyscreen );
    	p->v = p->yoff - (( p->yimage * p->b ) / p->Nyscreen );
    
    	p->ximage = p->u - p->s;
    	p->yimage = p->t - p->v;
    
    	p->xoff = -p->s;
    	p->yoff = p->t;
    
    	printf("s = %Lf\n t = %Lf\n u = %Lf\n v = %Lf\n"
    		,p->s,p->t,p->u,p->v );
    	printf("ximage = %Lf\n yimage = %Lf\n xoff = %Lf\n yoff %Lf\n"
    		,p->ximage,p->yimage,p->xoff, p->yoff );
    }
    void mousebutton_event(){
    	struct foo *p;
    	p = &bar;
    
    	if( p->z % 2 == 1 ){
    		p->c = event.button.x;
    		p->d = event.button.y;
    
    		printf("1 ) mousebutton_event z = %i\n",p->z );
    		}
    	if( p->z % 2 == 0 ){
    		p->a = event.button.x;
    		p->b = event.button.y;
    
    		printf("2 ) mousebutton_event z = %i\n",p->z );
    		}
    	printf("%i %i %i %i\n",p->c,p->d,p->a,p->b );
    }
    void putpixel(){
    	struct foo *p;
    	p = &bar;
    
    	Uint32 *bufp;
    	bufp = ( Uint32 *)screen->pixels + p->y*screen->pitch / 4 + p->x;
    	*bufp = p->color;
    }
    int number_base( int c ){
         	struct foo *p;
         	p = &bar;
    
         	int d, r, red = 0, green = 0, blue = 0, count = 1;
    
         	while(( c % p->base ) != 0 ){
              	d = c / p->base;
              	r = c % p->base;
    
              	switch( count ){
         	    		case 1: red = r;
    	        		break;
         	    		case 2: green = r;
    	        		break;
                  		case 3: blue = r;
                   			break;
    	    	default:printf("........ happens\n");
             	}
         	c = d;
    	++count;
         	}
         	p->color = SDL_MapRGB(screen->format,
         		(( red ) * 16 ),(( green ) * 32 ),(( blue ) * 64 ));
    }
    void change_color( int count ){
         	struct foo *p;
         	p = &bar;
    
            if ( count < p->max ){
            	putpixel( p->color = number_base( count ));
          	}
            if ( count == p->max ){
            	putpixel( p->color = SDL_MapRGB(screen->format,0,0,0));
         	}
    }
    void iterate(){
    	struct foo *p;
    	p = &bar;
    
    	int count;
    
    	long double xx,yy,tempr = p->real,tempi = p->imaginary;
    
    	for( count = 1; count < p->max &&
    		abs( tempr * tempr + tempi * tempi ) < 4;
    			count++){
    			xx = ( tempr * tempr ) - ( tempi * tempi );
    			yy = 2 * tempr * tempi;
    			tempr = p->real + xx;
    			tempi = p->imaginary + yy;
    	}
    	change_color( count );
    }
    void real_imaginary(){
    	struct foo *p;
    	p = &bar;
    
    	printf("real_imaginary\n");
    
    	for( p->x = 1; p->x < p->Nxscreen; p->x = p->x + 1 ){
    		for( p->y = 1; p->y < p->Nyscreen; p->y = p->y + 1 ){
    			p->real = (( p->x * p->ximage ) / p->Nxscreen
    				- p->xoff);
    			p->imaginary = p->yoff - (( p->y * p->yimage )
    				/ p->Nyscreen );
    			iterate();
    		}SDL_UpdateRect( screen,0,0,p->Nxscreen,p->Nyscreen );
    	}
    }
    void lock_screen(){
    	printf("lock_screen\n");
    
    	if( SDL_MUSTLOCK( screen )){
    		if( SDL_LockSurface( screen ) < 0 ){
    			return;
    		}
    	}
    	real_imaginary();
    
    	printf("unlock_screen\n");
    
    	if( SDL_MUSTLOCK( screen )){	
    		SDL_UnlockSurface( screen );
    	}
    }
    void set_sdl(){
    	printf("set_sdl\n");
    
    	struct foo *p;
    	p = &bar;
    
    	SDL_Init( SDL_INIT_VIDEO | SDL_INIT_NOPARACHUTE );
    	SDL_WM_SetCaption("tp.c",NULL);
    	screen = SDL_SetVideoMode( p->Nxscreen,p->Nyscreen,
    		32,SDL_SWSURFACE );
    	}
    void set_struct(){
    	struct foo *p;
    	p = &bar;
    
    	p->xscreen = 809;
    	p->yscreen = 500;
    	
    	p->Nxscreen = 809;
    	p->Nyscreen = 500;
    
    	p->max = 32768;
    	p->base = 32;
    	p->z = 1;
    
    	p->ximage = 3.2;
    	p->yimage = 2.0;
    	p->xoff = 2.2;
    	p->yoff = 1.0;
    }
    int main( int argc, char * argv[] ){
    	struct foo *p;
    	p = &bar;
    
    	printf("main\n");
    
    	set_struct();
    	set_sdl();
    	lock_screen();
    
    	while( SDL_WaitEvent( &event )){
    		switch( event.type ){
    			case SDL_MOUSEBUTTONDOWN:{
    				mousebutton_event();
    				if( p->z % 2 == 0 ){
    					image();
    					sdl_screen_size();
    					set_sdl();
    					lock_screen();
    					}
    				p->z = p->z + 1;
    				break;
    				}
    			case SDL_KEYDOWN:{
    				if( event.key.keysym.sym == SDLK_ESCAPE ){
    					SDL_Quit();
    					}
    				if( event.key.keysym.sym == SDLK_s ){
    					SDL_SaveBMP( screen, "shot.bmp" );
    					}
    				break;
    			}
    //			default: printf("........ happens\n");
    		}
    	}
    	return ( 0 );
    	}

    and the second time around
    Code:
    #include<stdio.h>
    #include<stdlib.h>
    #include<SDL/SDL.h>
     
    #define xscreen 1618
    #define yscreen 1000
    #define MAX 4096
    #define BASE 16
    
    SDL_Surface *screen;
    SDL_Event event;
    
    struct sdl_window{
      int Nxscreen, Nyscreen;
    };
    
    struct sdl_image{
      long double ximage,yimage,xoff,yoff;
    };
    
    struct sdl_button{
      int a,b,c,d;
    };
    
    int image_size( struct sdl_button* button,
    		struct sdl_window* window,struct sdl_image* image );
    int window_size( struct sdl_button* button, struct sdl_window* window );
    int mouse( int z, struct sdl_button* button );
    void putpixel( int x, int y, Uint32 colors );
    Uint32 color( int count );
    int multiply(long double real, long double imaginary );
    int multiply(long double real, long double imaginary );
    void numbers( struct sdl_window* window, struct sdl_image* image );
    void unlock();
    void lock();
    void sdl( struct sdl_window* window );
    
    // image size used to find new images size so it fits new sdl window
    
    int image_size(  struct sdl_button* button,
    		 struct sdl_window* window,struct sdl_image* image ){
    
      printf("image_size\n");
    
      long double s,t,u,v; // four corners
    
      s = (( image->ximage * button->c ) / window->Nxscreen ) - image->xoff;
      u = (( image->ximage * button->a ) / window->Nxscreen ) - image->xoff;
      
      t = image->yoff - (( image->yimage * button->d ) / window->Nyscreen );
      v = image->yoff - (( image->yimage * button->b ) / window->Nyscreen );
      
      image->ximage = u - s;
      image->yimage = t - v;
      image->xoff = -s;
      image->yoff = t;
             
      printf("s = %Lf\n t = %Lf\n u = %Lf\n v = %Lf\n"
    	 ,s,t,u,v);
      printf("ximage = %Lf\n yimage = %Lf\n xoff = %Lf\n yoff %Lf\n"
    	 ,image->ximage,image->yimage,image->xoff, image->yoff );
    
      return image;
    }
    // window size used to find new dimensions of sdl window when zooming in
    
    int window_size( struct sdl_button* button, struct sdl_window* window ){
    
      printf("window_size\n");
      int t;
       
      window->Nxscreen = button->a - button->c;
      window->Nyscreen = button->b - button->d;
         
      
      if( window->Nxscreen > window->Nyscreen ){
        t = xscreen / window->Nxscreen;
      }
      else{
        t = yscreen / window->Nyscreen;
      }
      if( t > 1 ){
        window->Nxscreen = window->Nxscreen * t;
        window->Nyscreen = window->Nyscreen * t;
      }
      printf(" Nxscreen = %i Nyscreen %i\n",window->Nxscreen,window->Nyscreen );
      return window;
    }
    // mouse uses sdl to return mousebutton events. I am using two events high left // to low right so I can zoom in.
    
    int mouse( int z,struct sdl_button* button ){
      
      printf("mouse\n");
    
      if( z == 1 ){
        button->c = event.button.x;
        button->d = event.button.y;
        printf("c = %i d = %i\n",button->c,button->d);
      }
      if( z != 1 ){
        button->a = event.button.x;
        button->b = event.button.y;
        printf("a = %i b = %i\n",button->a,button->b);
      }
      return button;  
    }
    void putpixel( int x, int y, Uint32 colors ){
    
      Uint32 *bufp;
      bufp = ( Uint32 *)screen->pixels + y*screen->pitch / 4 + x;
      *bufp = colors;
    }
    Uint32 color( int count ){
      int d, r, c = 1,  red = 0, green = 0, blue = 0;
      Uint32 colors;
    
      while(( count % BASE ) != 0 ){
        d = count / BASE;
        r = count % BASE;
        
        switch( c ){
        case 1: red = r;
          break;
        case 2: green = r;
          break;
        case 3: blue = r;
          break;
        default:printf("........ happens\n");
        }
        count = d;
        ++c;
      }
      return colors = SDL_MapRGB(screen->format,
    			( red  * 16 ),( green  * 32 ),( blue  * 64 ));
    
    }
    
    // multiply is an iterative process returns a count which is 
    // converted into a color.
    
    int multiply(long double real, long double imaginary ){
    
      int count;
      long double xx,yy,tempr = real,tempi = imaginary;
     
      for( count = 1; count < MAX &&
    	 abs( tempr * tempr + tempi * tempi ) < 4;
           count++){
        xx = ( tempr * tempr ) - ( tempi * tempi );
        yy = 2 * tempr * tempi;
        tempr = real + xx;
        tempi = imaginary + yy;
      }
      return count;
    }
    // numbers takes sdl window and gives an imaginary number for each pixel. 
    
    void numbers( struct sdl_window* window, struct sdl_image* image ){
    
      int x,y;
      long double real,imaginary;
      printf("numbers\n");
    
      for( x = 1; x < window->Nxscreen; x++ ){
        for( y = 1; y < window->Nyscreen; y++ ){
          real = (( x * image->ximage ) / window->Nxscreen
    	      - image->xoff);
          imaginary = image->yoff - (( y * image->yimage )
    				 / window->Nyscreen );
     
          putpixel(x, y, ( color( multiply(real,imaginary ))));
        }SDL_UpdateRect( screen,0,0,window->Nxscreen,window->Nyscreen );
      }
    }
    
    void unlock(){
    
      printf("unlock\n");
    
      if( SDL_MUSTLOCK( screen )){   
        SDL_UnlockSurface( screen );
      }
    }
    void lock(){
    
      printf("lock\n");
                  
      if( SDL_MUSTLOCK( screen )){
        if( SDL_LockSurface( screen ) < 0 ){
          return;
        }
      }
    }
    void sdl( struct sdl_window* window ){
    
      printf("sdl\n");
    
      SDL_Init( SDL_INIT_VIDEO | SDL_INIT_NOPARACHUTE );
      SDL_WM_SetCaption("schmatic-4.c",NULL);
     
                  screen = SDL_SetVideoMode
    		( window->Nxscreen,window->Nyscreen,
    		  32,SDL_SWSURFACE );  
    }
    
    int main( int argc, char * argv[] ){
    
      printf("main\n");
    
      struct sdl_window wdw;
      struct sdl_window *window;
      window = &wdw;
      
      struct sdl_image img;
      struct sdl_image *image;
      image = &img;
    
      struct sdl_button bttn;
      struct sdl_button *button;
      button = &bttn;
    
      int z = 1;
    
      window->Nxscreen = xscreen;
      window->Nyscreen = yscreen;
    
      image->ximage = 3.2;
      image->yimage = 2.0;
      image->xoff = 2.2;
      image->yoff = 1.0;
    
      printf("start\n");
      sdl( window );
      lock();
      numbers( window,image );
      unlock();
    
    
      while( SDL_WaitEvent( &event )){
        switch( event.type ){
        case SDL_MOUSEBUTTONDOWN:{
          mouse( z,button );
          if( z != 1 ){
    	image_size( button,window,image );
    	window_size( button,window );
    	sdl( window );
    	lock();
    	numbers( window,image);
    	unlock();
          }
             z = -z;
    	 break;
          }
        case SDL_KEYDOWN:{
          if( event.key.keysym.sym == SDLK_ESCAPE ){
    	SDL_Quit();
          }
          if( event.key.keysym.sym == SDLK_s ){
    	SDL_SaveBMP( screen, "shot.bmp" );
          }
          break;
        }
        }}      
      getchar();
      return;
    }
    thanks for taking the time to read al.
    Last edited by mad_muppet; 06-26-2010 at 01:36 PM.

  2. #2
    Just a pushpin. bernt's Avatar
    Join Date
    May 2009
    Posts
    426
    Nice!

    To get this to work well on my machine I made a few adjustments; you might consider making them as well.

    First the compiler gave errors on these:
    int image_size( struct sdl_button* button,
    struct sdl_window* window,struct sdl_image* image );
    int window_size( struct sdl_button* button, struct sdl_window* window );
    int mouse( int z, struct sdl_button* button );
    I realize that you're probably using a C compiler and I used a C++ one but you should still change the return types to match what's actually being returned.

    Then I switched the screen size to something more manageable, 800x600. I think you ought to consider basing the first window's size on the dimensions of the display rather than being hard-coded in the program.

    Lastly I was able to shave a few seconds off by switching from long double to double (my machine is 32 bit so I figured it would better support double but if the improvement is solely from moving data around that's fine too.) I also stored the result from tempr*tempr and tempi*tempi in the multiply() routine rather than calculating them twice each loop, and that seemed to help somewhat.

    I noticed that there was no option to zoom out - it would be much appreciated. And on a side not, I lowered the max iterations from 4096 to 512 (xaos uses 170). 4096 is overkill unless you're zoomed in really far and lowering that value made the program a lot more tolerable on my slow computer. Maybe having the option to change that value after you've zoomed in would be nice.
    Also I think it might be a neat feature to be able to save the current viewing rectangle, either in a file or by printing the values out (and allowing the user to explicitly set the rectangle later). So, for example, the user presses 'F5' and the console spits out x, y, w, h into a file. And when he presses 'F6' it'll ask to load a file and reset the view. So it's like making a screen shot except you can continue to zoom in and continue your exploration from that point.

    Speaking of screenshots I included one. Unfortunately I had to convert to a pretty bad jpg to meet size requirements.
    Consider this post signed

  3. #3
    Registered User
    Join Date
    Aug 2006
    Posts
    54

    thanks

    appreciate the advice .. already had a play with reducing screen size and number of iterations .. also changed to double .. its very fast now ..

    I did fix the return types as well ..

    I will definitely have a look at zooming out and the idea of saving an image and being able to continue from there is interesting ..

    one thing I am looking at is smooth coloring if I can get my head around it.

  4. #4
    Registered User rogster001's Avatar
    Join Date
    Aug 2006
    Location
    Liverpool UK
    Posts
    1,472
    if you mean by 'smooth' colouring something that goes through hues of say blue, then what i did was increment the blue portion of the colouring depending on the iterations, you can start it with blue set to a low value then add the number of iterations to it whenever you are drawing a coloured pixel, this works up to a point as your values (and hence iterations strictly speaking) are limited to 255, messing around with this will get you some nice 'palettes' my avatar was created from my mandlebrot version in this way.
    Thought for the day:
    "Are you sure your sanity chip is fully screwed in sir?" (Kryten)
    FLTK: "The most fun you can have with your clothes on."

    Stroustrup:
    "If I had thought of it and had some marketing sense every computer and just about any gadget would have had a little 'C++ Inside' sticker on it'"

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Client-server system with input from separate program
    By robot-ic in forum Networking/Device Communication
    Replies: 3
    Last Post: 01-16-2009, 03:30 PM
  2. help
    By hellBOY in forum C Programming
    Replies: 4
    Last Post: 01-13-2009, 11:59 AM
  3. How to complete program. Any probs now?
    By stehigs321 in forum C Programming
    Replies: 7
    Last Post: 11-19-2003, 04:03 PM
  4. write a program that will set the time to 5:58
    By jupimako in forum C++ Programming
    Replies: 2
    Last Post: 11-05-2003, 03:51 AM
  5. Replies: 5
    Last Post: 09-03-2001, 09:45 PM