6. Generate PBM

6.1. Write Block PBM

An initial PBM generator that writes a block to disk.

<<funcdefs>>=
void kuf_write_block_pbm(const char *filename,
                         uint16_t w, uint16_t x,
                         uint16_t y, uint16_t z);
<<funcs>>=
static void print_side(FILE *fp, uint8_t side)
{
    fputc((side & 1) ? '1' : '0', fp);
    fputc(' ', fp);
    fputc((side & 2) ? '1' : '0', fp);
    fputc(' ', fp);
}

void kuf_write_block_pbm(const char *filename,
                         uint16_t w, uint16_t x,
                         uint16_t y, uint16_t z)
{
    FILE *fp;
    uint8_t s_a[4];
    uint8_t s_b[4];

    fp = fopen(filename, "w");

    fprintf(fp, "P1\n# kuf block\n8 8\n");
    /* print w + x squares */

    s_a[0] = kuf_square_quad_get(w, KUF_QUAD_A);
    s_a[1] = kuf_square_quad_get(w, KUF_QUAD_B);
    s_a[2] = kuf_square_quad_get(w, KUF_QUAD_C);
    s_a[3] = kuf_square_quad_get(w, KUF_QUAD_D);

    s_b[0] = kuf_square_quad_get(x, KUF_QUAD_A);
    s_b[1] = kuf_square_quad_get(x, KUF_QUAD_B);
    s_b[2] = kuf_square_quad_get(x, KUF_QUAD_C);
    s_b[3] = kuf_square_quad_get(x, KUF_QUAD_D);

    /* row 1: W(A,N), W(B, N), X(A, N), X(B, N) */
    print_side(fp, kuf_quad_side_get(s_a[0], KUF_NORTH));
    print_side(fp, kuf_quad_side_get(s_a[1], KUF_NORTH));
    print_side(fp, kuf_quad_side_get(s_b[0], KUF_NORTH));
    print_side(fp, kuf_quad_side_get(s_b[1], KUF_NORTH));
    fprintf(fp, "\n");

    /* row 2: W(A,S), W(B, S), X(A, S), X(B, N) */
    print_side(fp, kuf_quad_side_get(s_a[0], KUF_SOUTH));
    print_side(fp, kuf_quad_side_get(s_a[1], KUF_SOUTH));
    print_side(fp, kuf_quad_side_get(s_b[0], KUF_SOUTH));
    print_side(fp, kuf_quad_side_get(s_b[1], KUF_SOUTH));
    fprintf(fp, "\n");

    /* row 3: W(C,N), W(D, N), X(C, N), X(D, N) */
    print_side(fp, kuf_quad_side_get(s_a[2], KUF_NORTH));
    print_side(fp, kuf_quad_side_get(s_a[3], KUF_NORTH));
    print_side(fp, kuf_quad_side_get(s_b[2], KUF_NORTH));
    print_side(fp, kuf_quad_side_get(s_b[3], KUF_NORTH));
    fprintf(fp, "\n");

    /* row 4: W(C,S), W(D, S), X(C, S), X(D, S) */
    print_side(fp, kuf_quad_side_get(s_a[2], KUF_SOUTH));
    print_side(fp, kuf_quad_side_get(s_a[3], KUF_SOUTH));
    print_side(fp, kuf_quad_side_get(s_b[2], KUF_SOUTH));
    print_side(fp, kuf_quad_side_get(s_b[3], KUF_SOUTH));
    fprintf(fp, "\n");

    /* print y + z squares */

    s_a[0] = kuf_square_quad_get(y, KUF_QUAD_A);
    s_a[1] = kuf_square_quad_get(y, KUF_QUAD_B);
    s_a[2] = kuf_square_quad_get(y, KUF_QUAD_C);
    s_a[3] = kuf_square_quad_get(y, KUF_QUAD_D);

    s_b[0] = kuf_square_quad_get(z, KUF_QUAD_A);
    s_b[1] = kuf_square_quad_get(z, KUF_QUAD_B);
    s_b[2] = kuf_square_quad_get(z, KUF_QUAD_C);
    s_b[3] = kuf_square_quad_get(z, KUF_QUAD_D);

    /* row 5: Y(A,N), Y(B, N), Z(A, N), Z(B, N) */
    print_side(fp, kuf_quad_side_get(s_a[0], KUF_NORTH));
    print_side(fp, kuf_quad_side_get(s_a[1], KUF_NORTH));
    print_side(fp, kuf_quad_side_get(s_b[0], KUF_NORTH));
    print_side(fp, kuf_quad_side_get(s_b[1], KUF_NORTH));
    fprintf(fp, "\n");

    /* row 6: Y(A,S), Y(B, S), Z(A, S), Z(B, N) */
    print_side(fp, kuf_quad_side_get(s_a[0], KUF_SOUTH));
    print_side(fp, kuf_quad_side_get(s_a[1], KUF_SOUTH));
    print_side(fp, kuf_quad_side_get(s_b[0], KUF_SOUTH));
    print_side(fp, kuf_quad_side_get(s_b[1], KUF_SOUTH));
    fprintf(fp, "\n");

    /* row 7: Y(C,N), Y(D, N), Z(C, N), Z(D, N) */
    print_side(fp, kuf_quad_side_get(s_a[2], KUF_NORTH));
    print_side(fp, kuf_quad_side_get(s_a[3], KUF_NORTH));
    print_side(fp, kuf_quad_side_get(s_b[2], KUF_NORTH));
    print_side(fp, kuf_quad_side_get(s_b[3], KUF_NORTH));
    fprintf(fp,"\n");

    /* row 8: Y(C,S), Y(D, S), Z(C, S), Z(D, S) */
    print_side(fp, kuf_quad_side_get(s_a[2], KUF_SOUTH));
    print_side(fp, kuf_quad_side_get(s_a[3], KUF_SOUTH));
    print_side(fp, kuf_quad_side_get(s_b[2], KUF_SOUTH));
    print_side(fp, kuf_quad_side_get(s_b[3], KUF_SOUTH));
    fprintf(fp, "\n");

    fclose(fp);
}

6.2. Write PBM

kuf_write_pbm an NxM array of kufic squares to a PBM file. This is the more generic pbm writer. n and m are the width and height of the tessellation in units of kufic squares. squares expects to be an array of n*m squares.

The resulting pbm file will have a width of n*4 pixels and a height of m*4 pixels.

<<funcdefs>>=
void kuf_write_pbm(const char *filename,
                   int n, int m,
                   uint16_t *squares);

The PBM file is written one square row at a time. The square row consists of two pixel rows, so the north row is written followed by the southern row.

<<funcs>>=
static void write_row(FILE *fp, uint8_t w)
{
    int i;

    for (i = 0; i < 4; i++) {
        if (i > 0) fprintf(fp, " ");
        fprintf(fp, "%d", (w >> i) & 1);
    }
}

void kuf_write_pbm(const char *filename,
                   int n, int m,
                   uint16_t *squares)
{
    int x, y, r;
    FILE *fp;

    fp = fopen(filename, "w");

    fprintf(fp, "P1\n# kuf block\n%d %d\n", n*4, m*4);

    for (y = 0; y < m; y++) {
        for (r = 0; r < 4; r++) {
            for (x = 0; x < n; x++) {
                uint8_t w;
                uint16_t s;

                w = 0;
                s = squares[y * n + x];

                if (r < 2) {
                    /* upper quads A + B */
                    uint8_t a, b;

                    a = kuf_square_quad_get(s, KUF_QUAD_A);
                    b = kuf_square_quad_get(s, KUF_QUAD_B);

                    if (r < 1) {
                        /* North side A + B */
                        w = kuf_quad_side_get(b, KUF_NORTH);
                        w <<= 2;
                        w |= kuf_quad_side_get(a, KUF_NORTH);
                    } else {
                        /* South side A + B */
                        w = kuf_quad_side_get(b, KUF_SOUTH);
                        w <<= 2;
                        w |= kuf_quad_side_get(a, KUF_SOUTH);
                    }
                } else {
                    /* lower quads C + D */
                    uint8_t c, d;

                    c = kuf_square_quad_get(s, KUF_QUAD_C);
                    d = kuf_square_quad_get(s, KUF_QUAD_D);

                    if (r <= 2) {
                        /* North side C + D */
                        w = kuf_quad_side_get(d, KUF_NORTH);
                        w <<= 2;
                        w |= kuf_quad_side_get(c, KUF_NORTH);
                    } else {
                        /* South side C + D */
                        w = kuf_quad_side_get(d, KUF_SOUTH);
                        w <<= 2;
                        w |= kuf_quad_side_get(c, KUF_SOUTH);
                    }
                }

                write_row(fp, w);

                if (x < (n - 1)) fprintf(fp, " ");
            }
            fprintf(fp, "\n");
        }
    }

    fclose(fp);
}



prev | home | next