/* Function: rotateByNearestNeighbor Rotates the image a given angle by applying nearest neighbor method Parameters: image - Image to be rotated. width - The image's width. height - The image's height. depth - The image's color depth. angle - clockwise rotation angle new_width - New image's width new_height - New image's height Returns: ret - The image rotated counter-clockwise by an angle */ void rotateByNearestNeighbor (int *image, int *width, int *height, int *depth, double *angle, int *ret, int *new_width, int *new_height){ int x_center, y_center, x_diff, y_diff; int x, y, d; double x_src_d, y_src_d; int x_src, y_src; while (*angle >= 360){ *angle = *angle - 360; } x_center = *width/2; y_center = *height/2; x_diff = (*new_width - *width)/2; y_diff = (*new_height - *height)/2; for (y = -1*y_diff; y < (*new_height - y_diff); y++){ for (x = -1*x_diff; x < (*new_width - x_diff); x++){ x_src_d = (x - x_center) * cos(*angle) + (y - y_center) * sin(*angle) + x_center; y_src_d = (y - y_center) * cos(*angle) - (x - x_center) * sin(*angle) + y_center; x_src = (int) (x_src_d + 0.5); y_src = (int) (y_src_d + 0.5); for (d = 0; d < *depth; d++){ if (x_src < 0 || y_src < 0 || x_src > *width - 1 || y_src > *height - 1){ ret[IMGPOS(x + x_diff, y + y_diff, d, *new_width, *new_height)] = MIN_PIXEL_VALUE; }else{ ret[IMGPOS(x + x_diff, y + y_diff, d, *new_width, *new_height)] = image[IMGPOS(x_src, y_src, d, *width, *height)]; } } } } }
/* Function: crop Crops an image Parameters: image - Image to be cropped width - The image's width. height - The image's height. depth - The image's color depth. x_start - Upper left x coordinate of src block y_start - Upper left y coordinate of src block t_width - block's width t_height - block's height Returns: image - The cropped image */ void crop(int *image, int *width, int *height, int *depth, int *x_start, int *y_start, int *c_width, int *c_height, int *ret){ int i, j, k; for (i = 0; i < *c_width; i++){ for (j = 0 ; j < *c_height; j++){ for (k = 0; k < *depth; k++){ ret[IMGPOS(i, j, k, *c_width, *c_height)] = image[IMGPOS(*x_start + i, *y_start + j, k, *width, *height)]; } } } return; }
/* Function: padding Pad an image to the given dimensions (n, m); leave the image in the center Parameters: image - Complex matrix (image data) width - Width of the matrix height - Height of the matrix depth - Depth of the matrix n - New width m - New height ret - Padded image Returns: Image transformation */ void padding(int *image, int *width, int *height, int *depth, int *n, int *m, int *ret){ int i, j, d; int h_ini = (*n - *width) / 2, v_ini = (*m - *height) / 2; for (d = 0; d < *depth; d++){ for (j = h_ini; j < *width + h_ini; j++){ for (i = v_ini; i < *height + v_ini; i++){ ret[IMGPOS(j, i, d, *n, *m)] = image[IMGPOS(j - h_ini, i - v_ini, d, *width, *height)]; } } } }
/* Function: rotateBySpline Rotates the image a given angle by applying Spline method Parameters: image - Image to be rotated. width - The image's width. height - The image's height. depth - The image's color depth. angle - clockwise rotation angle new_width - New image's width new_height - New image's height Returns: ret - The image rotated counter-clockwise by an angle */ void rotateBySpline (int *image, int *width, int *height, int *depth, double *angle, int *ret, int *new_width, int *new_height){ int x_center, y_center, x_diff, y_diff; int x, y, d; double x_src_d, y_src_d; int x_src, y_src; double x_weight, y_weight; while (*angle >= 360){ *angle = *angle - 360; } x_center = *width/2; y_center = *height/2; x_diff = (*new_width - *width)/2; y_diff = (*new_height - *height)/2; for (y = -1*y_diff; y < (*new_height - y_diff); y++){ for (x = -1*x_diff; x < (*new_width - x_diff); x++){ x_src_d = (x - x_center) * cos(*angle) + (y - y_center) * sin(*angle) + x_center; y_src_d = (y - y_center) * cos(*angle) - (x - x_center) * sin(*angle) + y_center; x_src = (int) x_src_d; y_src = (int) y_src_d; x_weight = x_src_d - x_src; y_weight = y_src_d - y_src; for (d = 0; d < *depth; d++){ int src = IMGPOS(x_src, y_src, d, *width, *height); int next = IMGPOS(x + x_diff, y + y_diff, d, *new_width, *new_height); if (x_src_d < 0 || y_src_d < 0 || x_src_d >= *width || y_src_d >= *height){ ret[next] = 0; }else{ int a[4][4]; int m,n; for (n = 0; n < 4; n++){ for (m = 0; m < 4; m++){ int xs = x_src - 1 + m, ys = y_src - 1 + n; if (xs < 0 || ys < 0 || xs >= *width || ys >= *height){ a[n][m] = image[src]; }else{ a[n][m] = image[IMGPOS(xs, ys, d, *width, *height)]; } } } ret[next] = (int) spline(a, x_weight, y_weight); } } } } }
/* Function: rotate90CunterClockwise Rotates an image 90 degrees counter-clockwise Parameters: image - Image to be rotated. width - The image's width. height - The image's height. depth - The image's color depth. Returns: ret - The image rotated 90 degrees counter-clockwise */ void rotate90CounterClockwise(int *image, int *width, int *height, int *depth, int *ret){ int i, j, k, dest, src; int new_h = *width, new_w = *height; for (i = 0; i < new_w; i++){ for (j = 0; j < new_h; j++){ for (k = 0; k < *depth; k++){ dest = IMGPOS(i, j, k, new_w, new_h); src = IMGPOS(*width - 1 - j, i, k, *width, *height); ret[dest] = image[src]; } } } return; }
/* Function: fft_image_transform Apply a FFT image transformation (auxiliar function) Parameters: image - Complex matrix (image data) width - Width of the matrix height - Height of the matrix depth - Depth of the matrix direction - Forward or inverse? Returns: Image transformation */ void fft_image_transform(Rcomplex *image, int *width, int *height, int *depth, int direction){ int plane_size = *width * *height * *depth, rank = (*depth == 1) ? 2 : 3; int i = 0, j = 0, d = 0; int *n = calloc(3, sizeof(int)); fftw_complex *in, *out; fftw_plan p; in = (fftw_complex *) fftw_malloc(sizeof(fftw_complex) * plane_size); out = (fftw_complex *) fftw_malloc(sizeof(fftw_complex) * plane_size); for (d = 0; d < *depth; d++){ for (j = 0; j < *height; j++){ for (i = 0; i < *width; i++){ int row_major_pos = d + *depth * (j + *height * i), im_pos = IMGPOS(i, j, d, *width, *height); in[row_major_pos][0] = image[im_pos].r; in[row_major_pos][1] = image[im_pos].i; } } } n[0] = *width; n[1] = *height; n[2] = *depth; p = fftw_plan_dft(rank, n, in, out, direction, FFTW_ESTIMATE); fftw_execute(p); for (d = 0; d < *depth; d++){ for (j = 0; j < *height; j++){ for (i = 0; i < *width; i++){ int row_major_pos = d + *depth * (j + *height * i), im_pos = IMGPOS(i, j, d, *width, *height); image[im_pos].r = out[row_major_pos][0]; image[im_pos].i = out[row_major_pos][1]; } } } free(n); fftw_destroy_plan(p); fftw_free(in); fftw_free(out); }
void init_explosions (void) { int i; for (i = 0; i < 6; ++i) explosions[0][i] = compile_sprzcol (IMGPOS (vehicles_img, 65, (5 - i)*33), 0, 32, 32, vehicles_img.width, xbuf); for (; i < NBR_EXPLOSION_FRAMES; ++i) explosions[0][i] = compile_sprzcol (IMGPOS (vehicles_img, 32, (NBR_EXPLOSION_FRAMES - i - 1) * 33), 0, 32, 32, vehicles_img.width, xbuf); for (i = 0; i < 6; ++i) explosions[1][i] = compile_sprzcol (IMGPOS (vehicles_img, 131, (5 - i)*33), 0, 32, 32, vehicles_img.width, xbuf); for (; i < NBR_EXPLOSION_FRAMES; ++i) explosions[1][i] = compile_sprzcol (IMGPOS (vehicles_img, 98, (NBR_EXPLOSION_FRAMES - i - 1) * 33), 0, 32, 32, vehicles_img.width, xbuf); }
/* Function: rotateByBilinear Rotates the image a given angle by applying bilinear method Parameters: image - Image to be rotated. width - The image's width. height - The image's height. depth - The image's color depth. angle - clockwise rotation angle new_width - New image's width new_height - New image's height Returns: ret - The image rotated counter-clockwise by an angle */ void rotateByBilinear (int *image, int *width, int *height, int *depth, double *angle, int *ret, int *new_width, int *new_height){ int x_center, y_center, x_diff, y_diff; int x, y, d; double x_src_d, y_src_d; int x_src, y_src; double x_weight, y_weight; while (*angle >= 360){ *angle = *angle - 360; } x_center = *width/2; y_center = *height/2; x_diff = (*new_width - *width)/2; y_diff = (*new_height - *height)/2; for (y = -1*y_diff; y < (*new_height - y_diff); y++){ for (x = -1*x_diff; x < (*new_width - x_diff); x++){ x_src_d = (x - x_center) * cos(*angle) + (y - y_center) * sin(*angle) + x_center; y_src_d = (y - y_center) * cos(*angle) - (x - x_center) * sin(*angle) + y_center; x_src = (int) x_src_d; y_src = (int) y_src_d; x_weight = x_src_d - x_src; y_weight = y_src_d - y_src; for (d = 0; d < *depth; d++){ if (x_src_d < 0 || y_src_d < 0 || x_src_d >= *width || y_src_d >= *height){ ret[IMGPOS(x + x_diff, y + y_diff, d, *new_width, *new_height)] = 0; }else{ int a[4]; a[0] = image[IMGPOS(x_src, y_src, d, *width, *height)]; a[1] = (x_src == *width - 1) ? a[0] : image[IMGPOS(x_src + 1, y_src, d, *width, *height)]; a[2] = (y_src == *height - 1)? a[0] : image[IMGPOS(x_src, y_src + 1, d, *width, *height)]; a[3] = ((x_src == *width - 1) || (y_src == *height - 1)) ? a[0] : image[IMGPOS(x_src + 1, y_src + 1, d, *width, *height)]; ret[IMGPOS(x + x_diff, y + y_diff, d, *new_width, *new_height)] = (int) bilinear (a, x_weight, y_weight); } } } } }
/* Function: kdtree_kmeans_it K Means kdtree classification algorithm - One iteration Parameters: image - The image data width - Width of the image height - Heigth of the image depth - Color depth of the image k - Number of clusters in the classification clusters - Current clusters values mean_colors - Use the mean centroid values as cluster values? ret - The result image Returns: The clustered image */ int kdtree_kmeans_it(int *image, int width, int height, int depth, int k, int **clusters, int mean_colors, int *ret){ int i = 0, j = 0, d = 0; /* indexes iterators */ int min_dist = -1; /* distances */ int cluster = 0; /* current cluster class */ int *pixel_it = malloc(depth * sizeof(int)); /* pixel iterator */ int *pix_count = (int *) calloc(k, sizeof(int)); /* counts the pixel in each class */ int changed = 0; /* has centroids changed? */ float **new_clusters = (float **) malloc(k * sizeof(float *)); /* iterative cluster class mean */ int *hr_min = calloc(depth, sizeof(int)), *hr_max = calloc(depth, sizeof(int)); kdtree kd_nn = NULL; for (i = 0; i < depth; i++){ hr_min[i] = MIN_PIXEL_VALUE; hr_max[i] = MAX_PIXEL_VALUE; } kd_nn = kdtree_create(depth, hr_min, hr_max); /* allocate memory to keep cluster class means */ for (i = 0; i < k; i++){ for (d = 0; d < depth; d++){ hr_min[d] = MIN_PIXEL_VALUE; hr_max[d] = MAX_PIXEL_VALUE; } kd_nn = kdtree_add(kd_nn, i, clusters[i], hr_min, hr_max); new_clusters[i] = calloc(depth, sizeof(float)); } /* kmeans iteration */ for (i = 0; i < width; i++){ for (j = 0; j < height; j++){ /* for each pixel */ int l = 0; min_dist = -1; for (l = 0; l < depth; l++){ pixel_it[l] = image[IMGPOS(i, j, l, width, height)]; } cluster = kdtree_nearestneighbor_id(kd_nn, pixel_it); for (l = 0; l < depth; l++){ /* updates cluster centroids means and sets return image */ ret[IMGPOS(i, j, l, width, height)] = (mean_colors) ? clusters[cluster][l] : clusters[cluster][l]; new_clusters[cluster][l] = mean_it(new_clusters[cluster][l], pix_count[cluster], pixel_it[l]); } pix_count[cluster]++; } } /* update clusters and free used memory */ for (i = 0; i < k; i++){ for (d = 0; d < depth; d++){ if (clusters[i][d] != (int) new_clusters[i][d]){ clusters[i][d] = (int) (new_clusters[i][d]); changed = 1; } } free(new_clusters[i]); } free(new_clusters); free(pixel_it); free(hr_min); free(hr_max); kdtree_destroy(kd_nn); return changed; }