master pita/pjw / pjwpfpg / pjw.c
  1#include <stdio.h>
  2#include <stdlib.h>
  3#include <math.h>
  4#include <time.h>
  5#include <string.h>
  6
  7typedef struct {
  8    int width;
  9    int height;
 10    unsigned char *data;
 11} Ppm;
 12
 13void
 14rotate_image(Ppm *src, Ppm *dst, double degrees)
 15{
 16    double radians = degrees * (3.1415926 / 180.0);
 17    double cos_t = cos(radians);
 18    double sin_t = sin(radians);
 19    int cx = src->width / 2;
 20    int cy = src->height / 2;
 21    int dst_y, dst_x;
 22    int dx, dy, src_x, src_y, dst_idx;
 23
 24    for (dst_y = 0; dst_y < dst->height; dst_y++) {
 25        for (dst_x = 0; dst_x < dst->width; dst_x++) {
 26
 27            /* make the center be 0,0 */
 28            dx = dst_x - cx;
 29            dy = dst_y - cy;
 30
 31            /* calulate rotation */
 32            src_x = (int)floor(dx * cos_t + dy * sin_t + 0.5) + cx;
 33            src_y = (int)floor(-dx * sin_t + dy * cos_t + 0.5) + cy;
 34
 35            /* 2d image to 1d array */
 36            dst_idx = (dst_y * dst->width + dst_x) * 3;
 37
 38            if (src_x >= 0 && src_x < src->width &&
 39                src_y >= 0 && src_y < src->height) {
 40
 41                int src_idx = (src_y * src->width + src_x) * 3;
 42
 43                dst->data[dst_idx]     = src->data[src_idx];
 44                dst->data[dst_idx + 1] = src->data[src_idx + 1];
 45                dst->data[dst_idx + 2] = src->data[src_idx + 2];
 46
 47            } else {
 48                dst->data[dst_idx]     = 255;
 49                dst->data[dst_idx + 1] = 255;
 50                dst->data[dst_idx + 2] = 255;
 51            }
 52        }
 53    }
 54}
 55
 56void
 57place_tile(Ppm *tile, Ppm *grid, int tile_col, int tile_row)
 58{
 59  int x, y, src_idx, dst_idx, dst_x, dst_y;
 60  unsigned char palette[9][3] = {
 61    {213, 62, 79},   {244, 109, 67}, {253, 174, 97},
 62    {254, 224, 139}, {255, 255, 191}, {230, 245, 152},
 63    {171, 221, 164}, {102, 194, 165}, {50, 136, 189}
 64  };
 65  unsigned char *color = palette[rand() % 9];
 66
 67  for (y = 0; y < tile->height; y++) {
 68    for (x = 0; x < tile->width; x++) {
 69      /* calculate index starting in the given col and row */
 70      dst_x = tile_col * tile->width + x;
 71      dst_y = tile_row * tile->height + y;
 72      /* 2d image to 1d array in the current image*/
 73      src_idx = (y * tile->width + x) * 3;
 74      /* 2d image to 1d array in the whole grid*/
 75      dst_idx = (dst_y * grid->width + dst_x) * 3;
 76
 77      /* move the pixels over */
 78      if (tile->data[src_idx] < 250 || tile->data[src_idx+1] < 250 || tile->data[src_idx+2] < 250) {
 79        grid->data[dst_idx]     = color[0];
 80        grid->data[dst_idx + 1] = color[1];
 81        grid->data[dst_idx + 2] = color[2];
 82      } else {
 83        grid->data[dst_idx]     = 255;
 84        grid->data[dst_idx + 1] = 255;
 85        grid->data[dst_idx + 2] = 255;
 86      }
 87    }
 88  }
 89}
 90
 91int
 92main(void)
 93{
 94    FILE *in, *out;
 95    char magic[3];
 96    int width, height, max_val;
 97    int i, val, cell;
 98    double degrees[9];
 99    Ppm src, rotated, grid;
100
101    srand((unsigned int)time(NULL));
102
103    for (cell = 0; cell < 9; cell++)
104        degrees[cell] = (double)(rand() % 3600) / 10.0;
105
106    in = fopen("pjw.ppm", "r");
107    if (!in) {
108        perror("failed to open file, pjw.ppm");
109        return 1;
110    }
111
112    fscanf(in, "%2s %d %d %d", magic, &width, &height, &max_val);
113
114    if (magic[0] != 'P' || magic[1] != '3') {
115        fprintf(stderr, "only P3 plx(ascii)\n");
116        fclose(in);
117        return 1;
118    }
119
120    src.width  = width;
121    src.height = height;
122    src.data   = (unsigned char *)malloc(width * height * 3);
123
124    rotated.width  = width;
125    rotated.height = height;
126    rotated.data   = (unsigned char *)malloc(width * height * 3);
127
128    grid.width  = width * 3;
129    grid.height = height * 3;
130
131    size_t src_size  = (size_t)width * height * 3;
132    size_t grid_size = (size_t)grid.width * grid.height * 3;
133
134    grid.data   = (unsigned char *)malloc(grid_size);
135
136    if (!src.data || !rotated.data || !grid.data) {
137        fprintf(stderr, "Memory allocation failed.\n");
138        return 1;
139    }
140
141    /* avoid garbage pixels */
142    memset(grid.data, 255, grid_size);
143
144    for (i = 0; i < src_size; i++) {
145        fscanf(in, "%d", &val);
146        src.data[i] = (unsigned char)val;
147    }
148    fclose(in);
149
150    for (cell = 0; cell < 9; cell++) {
151      rotate_image(&src, &rotated, degrees[cell]);
152      place_tile(&rotated, &grid, cell%3, cell/3);
153    }
154
155    out = fopen("output.ppm", "w");
156    if (!out) {
157        perror("failed to open the file output.ppm");
158        return 1;
159    }
160
161    /* write the header */
162    fprintf(out, "P3\n%d %d\n255\n", grid.width, grid.height);
163    /* write the rest */
164    for (i = 0; i < (int)grid_size; i+=3) {
165      if (grid.data[i] == 0 && grid.data[i + 1] == 0 && grid.data[i + 2] == 0)
166        switch (rand() % 4) {
167        case 0: fprintf(out, "0 0 0 "); break;
168        case 1: fprintf(out, "255 0 0 "); break;
169        case 2: fprintf(out, "0 255 0 "); break;
170        case 3: fprintf(out, "0 0 255 "); break;
171        }
172    else {
173      fprintf(out, "%d %d %d ",
174          grid.data[i],
175          grid.data[i + 1],
176          grid.data[i + 2]);
177    }
178
179        if ((i + 1) % (grid.width * 3) == 0) {
180            fprintf(out, "\n");
181        }
182    }
183
184    fclose(out);
185
186    free(src.data);
187    free(rotated.data);
188    free(grid.data);
189
190    printf("done %s (%dx%d)\n", "output.ppm", grid.width, grid.height);
191    return 0;
192}