//    Copyright 2007 Ilan Pillemer

//    This program is free software; you can redistribute it and/or modify
//    it under the terms of the GNU General Public License as published by
//    the Free Software Foundation; either version 2 of the License, or
//    (at your option) any later version.

//    This program is distributed in the hope that it will be useful,
//    but WITHOUT ANY WARRANTY; without even the implied warranty of
//    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//    GNU General Public License for more details.

//    You should have received a copy of the GNU General Public License
//    along with this program; if not, write to the Free Software
//    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA

#include <stdio.h>
#define WIDTH 1024
#define HEIGHT 768

unsigned short bfType;           /* Magic number for file */

typedef struct                       /**** BMP file header structure ****/
{
  unsigned int bfSize;           /* Size of file */
  unsigned short bfReserved1;      /* Reserved */
  unsigned short bfReserved2;      /* ... */
  unsigned int  bfOffBits;       
 } BITMAPFILEHEADER;

typedef struct                       /**** BMP file info structure ****/
{
  unsigned int   biSize;           /* Size of info header */
  int            biWidth;          /* Width of image */
  int            biHeight;         /* Height of image */
  unsigned short biPlanes;         /* Number of color planes */
  unsigned short biBitCount;       /* Number of bits per pixel */
  unsigned int   biCompression;    /* Type of compression to use */
  unsigned int   biSizeImage;      /* Size of image data */
  int            biXPelsPerMeter;  /* X pixels per meter */
  int            biYPelsPerMeter;  /* Y pixels per meter */
  unsigned int   biClrUsed;        /* Number of colors used */
  unsigned int   biClrImportant;   /* Number of important colors */
} BITMAPINFOHEADER;

typedef struct
{
  unsigned char red;
  unsigned char green;
  unsigned char blue;
} Colour;

typedef struct
{
  unsigned char blue;
  unsigned char green;
  unsigned char red;
} Pixel;


typedef struct
{
  Pixel col[WIDTH];
} Column;

typedef struct
{
  Column row[HEIGHT];
} Picture;

typedef struct
{
  int x;
  int y;
} Point;



int rand();
//clears background in white
void clear (Picture * picture)
{
  int i,j;
  for (i = 0; i < HEIGHT; i++) 
    for (j = 0; j < WIDTH; j++) {
    
      (picture->row[i]).col[j].red = 255;
      (picture->row[i]).col[j].green =255;
      (picture->row[i]).col[j].blue = 255;
    }
}

// draws a point in specified colour.
void draw_point(Picture * src, Point * point, Colour * colour)
{
  
  src->row[point->y].col[point->x].red = colour->red;
  src->row[point->y].col[point->x].green = colour->green;
  src->row[point->y].col[point->x].blue = colour->blue;
  
}

void draw_test(Picture * picture) {

}


void draw_sierpinksi(Picture * picture, int width, int height) {

 
  /* A triangle */ 
  Point vertices[3];
  Colour colours[3];

  vertices[0].x = 0;
  vertices[0].y = 0;
  vertices[1].x = width/2;
  vertices[1].y= height;
  vertices[2].x = width;
  vertices[2].y = 0;

  colours[0].red = 255;
  colours[0].green = 0;
  colours[0].blue = 0;

  colours[1].red = 0;
  colours[1].green = 255;
  colours[1].blue = 0;

  colours[2].red = 0;
  colours[2].green = 0;
  colours[2].blue = 255;

  /* Choose a boring point somewhere */
  Point S;
  Colour S_Colour;
  S.x=width/2;
  S.y=height/2;
  S_Colour.red = 0;
  S_Colour.green = 0;
  S_Colour.blue = 0;

  int j,k;
  for (k=0; k<1000000; k++){
    j=rand()%3;
    S.x = (S.x + vertices[j].x) / 2;
    S.y = (S.y + vertices[j].y) / 2;
    S_Colour.red = (S_Colour.red + colours[j].red) / 2;
    S_Colour.green = (S_Colour.green + colours[j].green) / 2;
    S_Colour.blue = (S_Colour.blue + colours[j].blue) / 2;

    draw_point(picture,&S,&S_Colour);
  }
}

void saveBMP(){
  int i, j, rc, arraypos;
  
	FILE* bitfile;
	
	BITMAPFILEHEADER header;
	BITMAPINFOHEADER info;
	
	bfType = 19778; 	/* magic, magic, magic */
	header.bfReserved1 = 0;
       	header.bfReserved2 = 0;

	header.bfOffBits = 54; 
	info.biSize = 40;
	info.biWidth = WIDTH;
	info.biHeight = HEIGHT;
	info.biPlanes=1;
	info.biBitCount=24;
	info.biCompression=0;
	info.biSizeImage=0;
	info.biXPelsPerMeter=0;
	info.biYPelsPerMeter=0;
	info.biClrUsed=0;
	info.biClrImportant=0;
	
	unsigned int bytesPerPixel = (unsigned int)(info.biBitCount >> 3);
	unsigned int extraBytes = ((unsigned int)info.biWidth * bytesPerPixel) % 4;
	unsigned int adjustedLineSize = bytesPerPixel * ((unsigned int)info.biWidth + extraBytes);
	unsigned int sizeOfImageData = (unsigned int)(info.biHeight) * adjustedLineSize;
	header.bfSize = header.bfOffBits + sizeOfImageData;
	
	bitfile = fopen("sierpinski.bmp","wb");
	printf("size of header:%d\n",sizeof(BITMAPFILEHEADER));
	
	rc = fwrite(&bfType,2,1,bitfile);
        rc = fwrite(&header,sizeof(BITMAPFILEHEADER),1,bitfile);
	rc = fwrite(&info,sizeof(BITMAPINFOHEADER),1,bitfile);
	
	/* Note to make this code crossplatform simply call
	 malloc(WIDTH * HEIGHT * 3) I have used sbrk() for my own
	 amusement; but this will not work on non-*ix systems. If you
	 remove the sbrk() here; you will also need to comment out the
	 second reference*/

	Picture * picture = (Picture *) sbrk(WIDTH * HEIGHT * 3);
	clear(picture);
	for (i=555; i>0; i--) {
	draw_sierpinksi(picture,1024-i,768-i);
	}

	//write picture to file
	for (i = 0; i < HEIGHT; i++) 
	  fwrite (&(picture->row[i]),WIDTH*3,1,bitfile);
	fclose (bitfile);
	
	picture=0;
	sbrk(-(WIDTH * HEIGHT * 3)); /* remove this if you malloc; you
				      could replace it with the
				      relevant free() call if you feel
				      like it.
				     */
	
}


int main()
{
  saveBMP();
  printf("Hmmm...\n");
  return 0;
}
