#include    <stdio.h>
#include    <stdlib.h>

#define     COLOR   256
#define     MASK    0x00FF
#define     XMAX    512
#define     YMAX    512

/* BMP-file headders */
unsigned short      bfType;     /* 'B', 'M' */

struct  {
    unsigned long   bfSize;     /* file size */
    unsigned long   reserved0;  /* reserved */
    unsigned long   hsize;      /* headder size */
    unsigned long   biSize;     /* size of BITMAPINFOHEADER; I don't use it */
    unsigned long   bmpX;       /* X size */
    unsigned long   bmpY;       /* Y size */
}   headder0;

unsigned short      biPlanes;   /* 0x0001 */
unsigned short      biBitCount; /* colors = 2^biBitCount */

struct  {
    unsigned long   biCompression;  /* compression type */
    unsigned long   biSizeImage;    /* image size */
    long            biXPixPerMeter; /* holizontal resolution */
    long            biYPixPerMeter; /* vertical resolution */
    unsigned long   biClrUsed;      /* recommended to be 0 */
    unsigned long   biClrImporant;  /* recommended to be 0 */
}   headder1;

unsigned long       irgb[COLOR];    /* color palette */

double              centR, centL, width;


unsigned short  initial(char *av1)
{
    unsigned short  maxRp;
    unsigned char   input[36];

    printf("\tCenter of the image; REAL PART      ==> ");
    fgets(input, 32, stdin);
    centR = atof(input);

    printf("\tCenter of the image; IMAGINARY PART ==> ");
    fgets(input, 32, stdin);
    centL = atof(input);

    printf("\tScreenwidth ==> ");
    fgets(input, 32, stdin);
    if(0.0 >= (width = atof(input)))
        {
    printf("\n\terror: screenwidth must be above zero");
    return 1;
    }

    printf("\tMaximum repeat(256 to 65535)==> ");
    fgets(input, 32, stdin);
    if(256 > (maxRp = atoi(input)))    maxRp = 256;

    if(centL < 0.0)
        {
    printf("\n\tcenter = %20.17f %20.17fi\n\tscreenwidth = %20.17f, max repeat = %d\n\n", centR, centL, width, maxRp);
    }
    else
        {
    printf("\n\tcenter = %20.17f +%20.17fi\n\tscreenwidth = %20.17f, max repeat = %d\n", centR, centL, width, maxRp);
    }

    return maxRp;
}



int     putHeadder(FILE *fp)
{
    int     i, j;

    biBitCount = 8;

    bfType = 0x4d42;    /* 'B', 'M' */
    if(-1 == fwrite(&bfType, sizeof(bfType), 1, fp))    return -1;

    headder0.hsize = sizeof(bfType) + sizeof(headder0) + sizeof(biPlanes) +
        sizeof(biBitCount) + sizeof(headder1) + sizeof(irgb);
    headder0.bfSize = headder0.hsize + XMAX*YMAX*biBitCount/8;
    headder0.biSize = sizeof(headder0.biSize) + sizeof(headder0.bmpX) +
        sizeof(headder0.bmpY) + sizeof(biPlanes) + sizeof(biBitCount) +
        sizeof(headder1);
    headder0.bmpX = XMAX;
    headder0.bmpY = YMAX;
    if(-1 == fwrite(&headder0, sizeof(headder0), 1, fp))    return -1;

    biPlanes = 0x0001;
    if(-1 == fwrite(&biPlanes, sizeof(biPlanes), 1, fp))    return -1;

    if(-1 == fwrite(&biBitCount, sizeof(biBitCount), 1, fp))    return -1;

    if(-1 == fwrite(&headder1, sizeof(headder1), 1, fp))    return -1;

    j = 0x00000000;
    for(i = 0; i < (2 << biBitCount); i++)
        {
        irgb[i] = j;
        j += 0x00010101;
        }

    return(fwrite(irgb, sizeof(irgb), 1, fp));
}


int main(int argc, char *argv[])
{
    unsigned short  maxRp, calc, xx, yy;
    unsigned char   *buff;      /* pointer for the buffer[] */
    unsigned char   buffer[XMAX];
    double          scale, rx, rx0, iy, real, real2, imag, imag2;
    FILE            *fp;

    if(2 != argc)
        {
        printf("Usage: %s filename.bmp\n", argv[0]);
        return -1;
        }

    if((maxRp = initial(argv[1])) < 256)    return -2;

    if(NULL == (fp = fopen(argv[1], "w")))
        {
        printf("cannot create this file: %s\n", argv[1]);
        return -2;
        }

    if(-1 == putHeadder(fp))
        {
        printf("BitMap headder write error: %s\n", argv[1]);
        return -3;
        }

    scale = width / YMAX;   /* size between each pixel */

    rx0 = centR - (XMAX/2)*(width/YMAX);  /* left under corner's real part */
    iy = centL - width/2.0 - scale;      /* left under corner's imaginary part */

    for(yy = 0; yy < YMAX; yy++)
        {
        rx = rx0;  iy += scale;
        buff = buffer;
        for(xx = 0; xx < XMAX; xx++)
            {
            real = rx;  imag = iy;
            for(calc = 0; calc < maxRp; calc++)
                {
                real2 = real*real;  imag2 = imag*imag;
                if(4.0 <= (real2 + imag2))
                    {
                    *buff = (char)(calc & MASK);
                    goto jump;
                    }
                imag *= (real+real);
                imag += iy;
                real = real2 - imag2 + rx;
                }
            *buff = 0;   /* if 'n' reached 'repeat max', set a black dot */

        jump:
            rx += scale;
            buff++;
            }
        fwrite(buffer, XMAX, 1, fp);
        }

    fclose(fp);
    return 0;
}