/*
 * PNG with "NG" inside a circle (clean version)
 */

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

#define PNG_DEBUG 3
#include <png.h>

#define OUT_FILE "initials.png"
#define WIDTH 600
#define HEIGHT 600
#define COLOR_TYPE PNG_COLOR_TYPE_RGB
#define BIT_DEPTH 8

int width = WIDTH, height = HEIGHT;
png_bytep *row_pointers;

/* ---------- BASIC ---------- */

void abort_(const char *s)
{
    fprintf(stderr, "%s\n", s);
    abort();
}

void write_pixel(int x, int y, png_byte r, png_byte g, png_byte b)
{
    if (x < 0 || x >= width || y < 0 || y >= height) return;

    png_byte *row = row_pointers[y];
    png_byte *ptr = &(row[x * 3]);

    ptr[0] = r;
    ptr[1] = g;
    ptr[2] = b;
}

/* gruby piksel */
void draw_thick_pixel(int x, int y, int t, png_byte r, png_byte g, png_byte b)
{
    for (int dx = -t; dx <= t; dx++)
        for (int dy = -t; dy <= t; dy++)
            write_pixel(x + dx, y + dy, r, g, b);
}

/* Bresenham */
void line(int x1, int y1, int x2, int y2, int t,
          png_byte r, png_byte g, png_byte b)
{
    int dx = abs(x2 - x1), dy = abs(y2 - y1);
    int sx = x1 < x2 ? 1 : -1;
    int sy = y1 < y2 ? 1 : -1;
    int err = dx - dy;

    while (1) {
        draw_thick_pixel(x1, y1, t, r, g, b);
        if (x1 == x2 && y1 == y2) break;

        int e2 = 2 * err;
        if (e2 > -dy) { err -= dy; x1 += sx; }
        if (e2 < dx)  { err += dx; y1 += sy; }
    }
}

/* ---------- DRAW ---------- */

void draw_circle(int cx, int cy, int radius,
                 png_byte r, png_byte g, png_byte b)
{
    for (int y = -radius; y <= radius; y++) {
        for (int x = -radius; x <= radius; x++) {
            if (x*x + y*y <= radius*radius) {
                write_pixel(cx + x, cy + y, r, g, b);
            }
        }
    }
}

/* litera N */
void draw_N(int x, int y, int h, int w,
            png_byte r, png_byte g, png_byte b)
{
    int t = 4;
    line(x, y, x, y + h, t, r, g, b);
    line(x + w, y, x + w, y + h, t, r, g, b);
    line(x, y, x + w, y + h, t, r, g, b);
}

/* litera G */
void draw_G(int x, int y, int h, int w,
            png_byte r, png_byte g, png_byte b)
{
    int t = 4;
    line(x, y, x, y + h, t, r, g, b);
    line(x, y, x + w, y, t, r, g, b);
    line(x, y + h, x + w, y + h, t, r, g, b);
    line(x + w, y + h/2, x + w, y + h, t, r, g, b);
    line(x + w/2, y + h/2, x + w, y + h/2, t, r, g, b);
}

void process_file(void)
{
    /* jednolite różowe tło */
    for (int y = 0; y < height; y++) {
        for (int x = 0; x < width; x++) {
            png_byte *ptr = &(row_pointers[y][x * 3]);
            ptr[0] = 255;  // R
            ptr[1] = 105;  // G
            ptr[2] = 180;  // B (hot pink)
        }
    }

    /* zielone koło */
    draw_circle(WIDTH/2, HEIGHT/2, 220, 0, 255, 0);

    /* kolor inicjałów (ciemniejszy jednolity) */
    png_byte r = 0;
    png_byte g = 120;
    png_byte b = 140;

    int h = 180;
    int w = 80;

    int startX = WIDTH/2 - 120;
    int startY = HEIGHT/2 - 90;

    draw_N(startX, startY, h, w, r, g, b);
    draw_G(startX + 140, startY, h, w, r, g, b);
}

/* ---------- PNG ---------- */

void create_png_file()
{
    row_pointers = (png_bytep*) malloc(sizeof(png_bytep) * height);
    for (int y = 0; y < height; y++)
        row_pointers[y] = (png_byte*) malloc(width * 3);
}

void write_png_file(char* filename)
{
    FILE *fp = fopen(filename, "wb");
    if (!fp) abort_("File open failed");

    png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
    if (!png_ptr) abort_("png_create_write_struct failed");

    png_infop info_ptr = png_create_info_struct(png_ptr);
    if (!info_ptr) abort_("png_create_info_struct failed");

    if (setjmp(png_jmpbuf(png_ptr)))
        abort_("Error during writing");

    png_init_io(png_ptr, fp);

    png_set_IHDR(png_ptr, info_ptr, width, height,
                 BIT_DEPTH, COLOR_TYPE, PNG_INTERLACE_NONE,
                 PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);

    png_write_info(png_ptr, info_ptr);
    png_write_image(png_ptr, row_pointers);
    png_write_end(png_ptr, NULL);

    for (int y = 0; y < height; y++)
        free(row_pointers[y]);
    free(row_pointers);

    fclose(fp);
}

int main()
{
    create_png_file();
    process_file();
    write_png_file(OUT_FILE);
    return 0;
}
