/* Mandelbrot generator! */

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

static const int width = 1080;
static const int height = 648;
static const double step = 0.0016;
static const double x_low = -2.0;
static const double x_high = 2.0;
static const double y_low = -1.2;
static const double y_high = 1.2;

void render_mandelbrot(float d, FILE *file)
{
    static int i, j, val;
    static double complex c;
    static double complex z;

    double x_diff = -x_low + x_high;
    double y_diff = -y_low + y_high;

    double dwidth = (double)width;
    double dheight = (double)height;

    struct tga_header
    {
        char id_length;
        char color_map_type;
        char image_type;
        char color_map_spec[5];
        char image_spec[10];
    }__attribute__((packed)) header = {
        0, 0, 2, {0, 0, 0, 0, 0},
        {
            0, 0, 0, 0, width % 256, width / 256,
            height % 256, height / 256, 24, 0
        }
    };

    fwrite(&header, sizeof(struct tga_header), 1, file);

    for (i = 0; i < height; ++i)
        for (j = 0; j < width; ++j)
        {
            c = x_low + x_diff * (j / dwidth) +
                ((y_low + y_diff * (i / dheight)) * I);
            z = c;

            for (val = 0; val < 256; ++val)
            {
                z = cpow(z, d) + c;
                if (cabs(z) >= 2.0)
                    break;
            }

            putc(val, file);
            putc(val, file);
            putc(val, file);
        }
}

int main(int argc, char *argv[])
{
    float from = 0.0;
    float to = 0.0;

    if (argc != 3)
    {
        fprintf(stderr, "Usage: mandelbrot from to\n");
        return EXIT_FAILURE;
    }

    sscanf(argv[1], "%f", &from);
    sscanf(argv[2], "%f", &to);

    printf("Generating from %.4f to %.4f ...\n", from, to);

    while (from <= to)
    {
        char filename[100];
        snprintf(filename, 100, "%.4f.tga", from);
        FILE *file = fopen(filename, "w");
        render_mandelbrot(from, file);
        fclose(file);
        from += step;
    }

    return EXIT_SUCCESS;
}

