/*	julia2bmp.c
	===========

This code generates a green julia-set as 24bit BMP.
Neccesary parameter is C in the form of real and imaginary part.

Example: ./julia2bmp -0.7 0.2

The math library needs the -lm gcc option, so compile it as following:

gcc julia2bmp.c -lm -o julia2bmp
   
If you convert (e.g. with ImageMagick) it to an jpg you can estimate 
on the file-size, if it looks nice (e.g. bigger than 70KB). For automated 
random creation of nice jpg-negatives, you can use following shell script:

#!/bin/bash
while [ true ]; do ./julia2bmp `echo -0.$RANDOM -0.$RANDOM`; convert juliaset.bmp -negate juliaset.jpg; echo "Size of juliaset.jpg is $(stat -c%s "juliaset.jpg") bytes"; if [ $(stat -c%s "juliaset.jpg") -gt 70000 ]; then break; fi; done

Philip, November 2014
*/

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <malloc.h>
#include <math.h>	// compile with gcc source.c -lm

#define _height 1000
#define _width 1000
#define _bitsperpixel 24
#define _planes 1
#define _compression 0
#define _pixelbytesize _height*_width*_bitsperpixel/8
#define _filesize _pixelbytesize+sizeof(bitmap)
#define _xpixelpermeter 0x130B //2835 , 72 DPI
#define _ypixelpermeter 0x130B //2835 , 72 DPI

#pragma pack(push,1)
typedef struct{
    uint8_t signature[2];
    uint32_t filesize;
    uint32_t reserved;
    uint32_t fileoffset_to_pixelarray;
} fileheader;
typedef struct{
    uint32_t dibheadersize;
    uint32_t width;
    uint32_t height;
    uint16_t planes;
    uint16_t bitsperpixel;
    uint32_t compression;
    uint32_t imagesize;
    uint32_t ypixelpermeter;
    uint32_t xpixelpermeter;
    uint32_t numcolorspallette;
    uint32_t mostimpcolor;
} bitmapinfoheader;
typedef struct {
    fileheader fileheader;
    bitmapinfoheader bitmapinfoheader;
} bitmap;
#pragma pack(pop)


int createbmp (unsigned char feld[], char name[]) {
    	FILE *fp = fopen(name,"wb");
    	bitmap *pbitmap  = (bitmap*)calloc(1,sizeof(bitmap));
    	uint8_t *pixelbuffer = (uint8_t*)malloc(_pixelbytesize);
    	strcpy(pbitmap->fileheader.signature,"BM");
    	pbitmap->fileheader.filesize = _filesize;
    	pbitmap->fileheader.fileoffset_to_pixelarray = sizeof(bitmap);
    	pbitmap->bitmapinfoheader.dibheadersize =sizeof(bitmapinfoheader);
    	pbitmap->bitmapinfoheader.width = _width;
    	pbitmap->bitmapinfoheader.height = _height;
	pbitmap->bitmapinfoheader.planes = _planes;
    	pbitmap->bitmapinfoheader.bitsperpixel = _bitsperpixel;
    	pbitmap->bitmapinfoheader.compression = _compression;
    	pbitmap->bitmapinfoheader.imagesize = _pixelbytesize;
    	pbitmap->bitmapinfoheader.ypixelpermeter = _ypixelpermeter ;
    	pbitmap->bitmapinfoheader.xpixelpermeter = _xpixelpermeter ;
    	pbitmap->bitmapinfoheader.numcolorspallette = 0;
    	fwrite (pbitmap, 1, sizeof(bitmap),fp);
      	fwrite (feld, 1, _pixelbytesize,fp);
    	fclose(fp);
    	free(pbitmap);
    	free(pixelbuffer);
	//printf ("createbmp: %s \n", name);	
}


int main (int argc, char *argv[]) {
	unsigned char bmpdata[_height*_width*3+1];
	unsigned char bmpdata2[_height*_width*3+1];
	int bmperror;
	int xpix; 		// pixel position
	int ypix;
	int pix = 1;
	float xmin = -2;
	float xmax = 2;
	float ymin = -2;
	float ymax = 2;
	float xstep = (xmax - xmin) / _width;
	float ystep = (ymax - ymin) / _height;
	float x;		// x(0) with this will be calculated
	float y;
	float xn;		// x(n+1) with this will be calculated
	float yn;
	int n;
	int it = 160;			// max iterations, 255 would be max for full green
	float xh; 			// helper
	int zaehler = 0;
	char filename[] = "juliaset.bmp";
	float juliacr;
	float juliaci;
	float julialimit;

	if(argc < 3){
		printf("ERROR no parameter for C. Please use it like \n julia2bmp 0.3 -0.6 \n");
		return 1;
	}

	juliacr = atof(argv[1]);
	juliaci = atof(argv[2]);
	julialimit = (2 + sqrt(juliacr * juliacr + juliaci * juliaci));
	julialimit = julialimit * julialimit;
	printf("C=%f+%fi, julialimit: %f \n", juliacr, juliaci, julialimit);

   	for(ypix = 0; ypix < _height; ypix++)
	{
		y = ymin + ypix * ystep;
   		for(xpix = 0; xpix < _width; xpix++)
		{
			x = xmin + xpix * xstep;		

			xn = x;	// start-value z0
			yn = y;
			for(n = 0; n < it; n++) 
			{
				xh = xn * xn - yn * yn + juliacr;	// helper
				yn = 2 * xn * yn + juliaci;
				xn =xh;
				if(xn * xn + yn * yn > julialimit)
					break;
				bmpdata2[pix] = n;			
			}
			pix = pix + 3;		// just every 3rd, for green
		}
	}
	bmperror = createbmp (bmpdata2, filename);
	printf ("BMP %s created with %d pixels %d Errors\n", filename, (pix-1)/3, bmperror);

     return 0;
}

