예제 #1
0
void augment_image::rotate(const cv::Mat &input, std::vector<cv::Mat> &results) const
{
    cv::Mat temp;
    if(random_){
        rotate_image(input, temp, rotate_distribution_(gen_), border_type_);
    }else{
        rotate_image(input, temp, rotate_angle_, border_type_);
    }
    results.emplace_back(temp);
}
예제 #2
0
파일: mnist.c 프로젝트: JacoCronje/darknet
void test_mnist_multi(char *filename, char *weightfile)
{
    network net = parse_network_cfg(filename);
    if(weightfile){
        load_weights(&net, weightfile);
    }
    set_batch_network(&net, 1);
    srand(time(0));

    float avg_acc = 0;
    data test;
    test = load_mnist_data("data/mnist/t10k-images.idx3-ubyte", "data/mnist/t10k-labels.idx1-ubyte", 10000);

    int i;
    for(i = 0; i < test.X.rows; ++i){
        image im = float_to_image(28, 28, 1, test.X.vals[i]);

        float pred[10] = {0};

        float *p = network_predict(net, im.data);
        axpy_cpu(10, 1, p, 1, pred, 1);
      //  flip_image(im);
        image im1 = rotate_image(im, -2.0*3.1415926/180.0);
        image im2 = rotate_image(im, 2.0*3.1415926/180.0);
        image im3 = rotate_image(im, -3.0*3.1415926/180.0);
        image im4 = rotate_image(im, 3.0*3.1415926/180.0);
        p = network_predict(net, im1.data);
        axpy_cpu(10, 1, p, 1, pred, 1);
        p = network_predict(net, im2.data);
        axpy_cpu(10, 1, p, 1, pred, 1);
        p = network_predict(net, im3.data);
        axpy_cpu(10, 1, p, 1, pred, 1);
        p = network_predict(net, im4.data);
        axpy_cpu(10, 1, p, 1, pred, 1);

        int index = max_index(pred, 10);
        int class = max_index(test.y.vals[i], 10);
        if(index == class) avg_acc += 1;
        free_image(im);
        free_image(im1);
        free_image(im2);
        free_image(im3);
        free_image(im4);
        printf("%4d: %.2f%%\n", i, 100.*avg_acc/(i+1));
    }
    printf("%4d: %.2f%%\n", i, 100.*avg_acc/(i+1));
}
예제 #3
0
int main (int argc, char const *argv[])
{
	const int N = 7;
	int **im;
	
	im = allocate2D(im, N);
	generate_image(im, N);
	print_image(im, N);

	rotate_image(im, N);
	printf("\n");
	print_image(im, N);
	release2D(im, N);
	return 0;
}
예제 #4
0
int main(void) {
	printf("Enter N, followed by the NxN values\n");

	size_t dim;
	while (scanf("%zu", &dim) == 1) {
		unsigned image[dim][dim];
		size_t i, j;
		for (i = 0; i < dim; i++) {
			for (j = 0; j < dim; j++) {
				scanf("%u", &image[i][j]);
			}
		}

		printf("Before rotation:\n");
		print_image(dim, image);
		printf("After rotation:\n");
		rotate_image(dim, image);
		print_image(dim, image);
	}

	return 0;
}
예제 #5
0
파일: nightmare.c 프로젝트: imaami/darknet
void run_nightmare(int argc, char **argv)
{
    srand(0);
    if(argc < 4){
        fprintf(stderr, "usage: %s %s [cfg] [weights] [image] [layer] [options! (optional)]\n", argv[0], argv[1]);
        return;
    }

    char *cfg = argv[2];
    char *weights = argv[3];
    char *input = argv[4];
    int max_layer = atoi(argv[5]);

    int range = find_int_arg(argc, argv, "-range", 1);
    int norm = find_int_arg(argc, argv, "-norm", 1);
    int rounds = find_int_arg(argc, argv, "-rounds", 1);
    int iters = find_int_arg(argc, argv, "-iters", 10);
    int octaves = find_int_arg(argc, argv, "-octaves", 4);
    float zoom = find_float_arg(argc, argv, "-zoom", 1.);
    float rate = find_float_arg(argc, argv, "-rate", .04);
    float thresh = find_float_arg(argc, argv, "-thresh", 1.);
    float rotate = find_float_arg(argc, argv, "-rotate", 0);
    float momentum = find_float_arg(argc, argv, "-momentum", .9);
    float lambda = find_float_arg(argc, argv, "-lambda", .01);
    char *prefix = find_char_arg(argc, argv, "-prefix", 0);
    int reconstruct = find_arg(argc, argv, "-reconstruct");
    int smooth_size = find_int_arg(argc, argv, "-smooth", 1);

    network net = parse_network_cfg(cfg);
    load_weights(&net, weights);
    char *cfgbase = basecfg(cfg);
    char *imbase = basecfg(input);

    set_batch_network(&net, 1);
    image im = load_image_color(input, 0, 0);
    if(0){
        float scale = 1;
        if(im.w > 512 || im.h > 512){
            if(im.w > im.h) scale = 512.0/im.w;
            else scale = 512.0/im.h;
        }
        image resized = resize_image(im, scale*im.w, scale*im.h);
        free_image(im);
        im = resized;
    }

    float *features = 0;
    image update;
    if (reconstruct){
        resize_network(&net, im.w, im.h);

        int zz = 0;
        network_predict(net, im.data);
        image out_im = get_network_image(net);
        image crop = crop_image(out_im, zz, zz, out_im.w-2*zz, out_im.h-2*zz);
        //flip_image(crop);
        image f_im = resize_image(crop, out_im.w, out_im.h);
        free_image(crop);
        printf("%d features\n", out_im.w*out_im.h*out_im.c);


        im = resize_image(im, im.w, im.h);
        f_im = resize_image(f_im, f_im.w, f_im.h);
        features = f_im.data;

        int i;
        for(i = 0; i < 14*14*512; ++i){
            features[i] += rand_uniform(-.19, .19);
        }

        free_image(im);
        im = make_random_image(im.w, im.h, im.c);
        update = make_image(im.w, im.h, im.c);

    }

    int e;
    int n;
    for(e = 0; e < rounds; ++e){
        fprintf(stderr, "Iteration: ");
        fflush(stderr);
        for(n = 0; n < iters; ++n){  
            fprintf(stderr, "%d, ", n);
            fflush(stderr);
            if(reconstruct){
                reconstruct_picture(net, features, im, update, rate, momentum, lambda, smooth_size, 1);
                //if ((n+1)%30 == 0) rate *= .5;
                show_image(im, "reconstruction");
#ifdef OPENCV
                cvWaitKey(10);
#endif
            }else{
                int layer = max_layer + rand()%range - range/2;
                int octave = rand()%octaves;
                optimize_picture(&net, im, layer, 1/pow(1.33333333, octave), rate, thresh, norm);
            }
        }
        fprintf(stderr, "done\n");
        if(0){
            image g = grayscale_image(im);
            free_image(im);
            im = g;
        }
        char buff[256];
        if (prefix){
            sprintf(buff, "%s/%s_%s_%d_%06d",prefix, imbase, cfgbase, max_layer, e);
        }else{
            sprintf(buff, "%s_%s_%d_%06d",imbase, cfgbase, max_layer, e);
        }
        printf("%d %s\n", e, buff);
        save_image(im, buff);
        //show_image(im, buff);
        //cvWaitKey(0);

        if(rotate){
            image rot = rotate_image(im, rotate);
            free_image(im);
            im = rot;
        }
        image crop = crop_image(im, im.w * (1. - zoom)/2., im.h * (1.-zoom)/2., im.w*zoom, im.h*zoom);
        image resized = resize_image(crop, im.w, im.h);
        free_image(im);
        free_image(crop);
        im = resized;
    }
}
예제 #6
0
int main(int argc, char const *argv[])
{
	char *filename = NULL;
	char *new_filename = NULL;
	char *degrees = NULL;
	char *direction = NULL;

	int deg, dir;

	image *img = NULL;
	image *new_image = NULL;

	//rotate <source_image> <destination_image> <degrees>
	if (argc < 3)	
	{
		printf("%s\n", ERROR_NOT_ENOUGH_ARGUMENTS);
		return 1;
	} else 
	{
                filename = malloc(sizeof(char *));
		new_filename = malloc(sizeof(char *));
		degrees = malloc(sizeof(char *));
		direction = malloc(sizeof(char *));

		strcpy(filename, argv[1]);
		strcpy(new_filename, argv[2]);
		strcpy(degrees, argv[3]);
		strcpy(direction, argv[4]);

		/*DEBUG
		 * */
		//printf("string:%s\n",degrees);
		if (strcmp(degrees,"90") == 0)
		{
		    deg = 90;
		}
		else if (strcmp(degrees,"180") == 0)
		{
		    deg = 180;
		}
		else if (strcmp(degrees,"270") == 0)
		{
		    deg = 270;
		}
		else
		{
		    deg = 0;
		}
		//printf("integer:%d\n",deg);
		
		//printf("string:%s\n",direction);
		if (strcmp(direction,"CW") == 0)
		{
		    dir = CW;
		}
		else
		{
		    dir = CCW;
		}
		//printf("integer:%d\n",dir);

		img = load_image(filename);
		if (img == NULL)
			return 1;
		
		//print_px(img, 0);
		
		new_image = rotate_image(img, deg, dir);

		create_image(new_filename,new_image);

		//print_px(new_image, 0);
		if (img == NULL)
			return 1;
	}

	return 0;
}
예제 #7
0
/* decode hidim png file and write the torrent file */
int decode(const char *pngfilename) {
    FILE *fp;
    png_uint_32 height, width;
    png_bytep *row_pointers = NULL, *transpose = NULL;
    char *filename, *basefilename, *sha1sum;
    int start_row, start_column, line_length, c;
    unsigned int length, metadata_length, count, s;

    if ((fp = fopen(pngfilename, "rb")) == NULL) {
        fprintf(stderr, "%s: %s\n", pngfilename, strerror(errno));
        return 0;
    }
    if (config & CONFIG_VERBOSE) {
        printf(":: decoding %s\n", pngfilename);
    }

    if (!read_png(fp, &row_pointers, &width, &height)) {
        fclose(fp);
        fprintf(stderr, "Error: %s is not a png file.\n", pngfilename);
        return 0;
    }
    fclose(fp);

    /* rotate image */
    transpose = rotate_image(row_pointers, width, height);
    free_array(row_pointers, height);
    if (transpose == NULL) { // it can't be. already checked before
        exit(EXIT_FAILURE);
    }

    /* search for hidim key */
    if (!search_key(transpose, width, height, &start_row, &start_column)) {
        fprintf(stderr, "Error: %s is not a hidim or is corrupted.\n", pngfilename);
        free_array(transpose, width);
        return 0;
    } else if (config & CONFIG_MORE_VERBOSE) {
        printf("  hidim key found at (%d, %d)\n", start_row, (int)(height-start_column-1));
    }

    /* extract metadata */
    read_metadata(transpose, start_row, start_column, &line_length, &filename, &sha1sum, &metadata_length, &length);

    /* for security reason, only keep the basename of filename */
    basefilename = basename(filename);
    if (config & CONFIG_MORE_VERBOSE) {
        printf("==== metadata (%d bytes) ====\n", metadata_length);
        printf("  line_length: %d  sha1sum: %s  length: %d\n", line_length, sha1sum, length);
        printf("  filename   : %s\n", filename);
        printf("====\n");
        //printf(":: %d %s %s %d %d\n", line_length, basefilename, sha1sum, metadata_length, length);
    }
    /* get the torrent */
    unsigned char *torrent = calloc(length, sizeof(char));
    if (torrent == NULL) {
        fprintf(stderr, "Error: Can't allocate %d bytes.\n", length*sizeof(char));
        exit(EXIT_FAILURE);
    }

    count = c = s = 0;
    while (count < length+metadata_length) {
        if (count >= metadata_length) {
            torrent[count - metadata_length] = (unsigned char)transpose[start_row+s][3*start_column+c];
        }
        if (c == (line_length*3 -1) ) {
            c = 0;
            s++;
        } else {
            c++;
        }
        count++;
    }
    free_array(transpose, width);

    /* check the sha1sum of the torrent we extracted with sha1sum from metadata */
    unsigned char md[20];
    SHA1(torrent, length, md);
    char *sha1sum_comp = hexa_sha1sum(md);
    if (strcmp(sha1sum_comp, sha1sum) != 0) {
        if (config & CONFIG_MORE_VERBOSE) {
            printf("sha2sum: expected %s, got %s\n", sha1sum, sha1sum_comp);
        }
        fprintf(stderr, "%s: wrong sha1sum for extracted data.\n", filename);
        free(sha1sum_comp);
        free(sha1sum);
        free(torrent);
        free(filename);
        return 0;
    }
    free(sha1sum);
    free(sha1sum_comp);

    /* check if torrent file does not already exist */
    if (is_file(basefilename) && (!(config & CONFIG_OVERWRITE))) {
        fprintf(stderr, "%s already exists. nothing done.\n", basefilename);
        free(torrent);
        free(filename);
        return 0;
    }
    /* write torrent to file */
    FILE *fo = fopen(basefilename, "w");
    fwrite(torrent, sizeof(char), length, fo);
    fclose(fo);
    if (config & CONFIG_VERBOSE) {
        printf("%s has been saved.\n", basefilename);
    }

    free(torrent);
    free(filename);

    return 1;
}
예제 #8
0
void process_1_image (args cli_flags, char *files) {
	
	char *out_file_name = get_out_filename (files, cli_flags);
	
	if (file_exists (out_file_name)) {
		printf ("| Output file %s already exists. skipping... ", out_file_name);
		return;
	}
	
	// Origional Image Properties struct
	img_prop o = (img_prop) malloc (sizeof (image_properties));
	
	// set all the vales in the imapg properties struct to -1
	null_ip (o);
	
	// Create a data provider
	CGDataProviderRef source_image_provider = CGDataProviderCreateWithFilename (files);
	
	// Check for a null returned value
	if (source_image_provider == NULL) {
		
		// something went wrong 
		printf ("error: Couldn't create CGDataProvider from URL.\n"); 
		exit (0);
	}
	
	// get the information from the image exif here
	o->image_rot = get_exif_rot (source_image_provider);
	

	// Create the image in memory from the JPEG data
	CGImageRef source_image = CGImageCreateWithJPEGDataProvider (source_image_provider, NULL, no, kCGRenderingIntentDefault);
	
  /********************************************/
  /* Getting the colour space **/
  
  o->colorSpace = CGImageGetColorSpace(source_image);
  
  /********************************************/
  
	// populate the image info struct
	pop_img_props (source_image, o);
	
	// create a data provider from the decoded JPEG data
	CGDataProviderRef image_data_provider = CGImageGetDataProvider (source_image);
	
	// Create a pointer to the data section of the image in memory
	CFDataRef source_data_ptr = CGDataProviderCopyData (image_data_provider);

	// The vImage_Buffers we will use
	vImage_Buffer *vImage_source = (vImage_Buffer*) malloc (sizeof (vImage_Buffer));
	
	// Check for NULL
	if (NULL == vImage_source) {
		printf ("Cannot malloc vImage_source buffer\n");
		exit (0);
	}
	
	if (o->bits_ppixel == 24) {
		
		// convert from 24bit to 32bit by adding the alpha channel.
		source_data_ptr = convert24_32bit (source_data_ptr, o);
		
	}
	
	// Setup the vImage Buffer for the image
	setupBuffer (vImage_source, o->image_h, o->image_w, o->bytes_row);

	// Assign the data to the vImage Buffer for the source
	vImage_source->data = (void *) CFDataGetBytePtr (source_data_ptr);
	
	// Check for NULL
	if (vImage_source->data == NULL) 
		printf ("Unable to get the vimage.data pointer\n");

	if (o->image_rot != 1 && o->image_rot != 4 && o->image_rot != 2) // rotate the image
		rotate_image (vImage_source, o, NULL);
	
	// flip the image
	if (o->image_rot == 2  || o->image_rot == 4 || o->image_rot == 7 || o->image_rot == 5)
		flip_image (vImage_source, o, NULL);
	
  
	// Resize the images
	resize_image (vImage_source, o, cli_flags);

    // Create a colour space to be compared against
    CGColorSpaceRef rgb = CGColorSpaceCreateWithName(kCGColorSpaceSRGB);
    if (NULL == rgb) {
        fprintf(stderr, "Unable to create the reference colourspace.\n");
        exit(0);
    }
    
    // Convert the colourspace to RGB
    if (!CFEqual(rgb, o->colorSpace) && !cli_flags->disableCC) {
        vImage_source->data = convert_space(vImage_source->data, o->image_w, o->image_h);
        if (NULL == vImage_source->data) exit(0);
    }
    
    // release the reference colour space
    CGColorSpaceRelease(rgb);
    
	// save the image
	save_image (vImage_source, o, cli_flags->quality, out_file_name);
	
	// Release the source provider
	CGDataProviderRelease (source_image_provider);
	source_image_provider = NULL;
	
	// Release the source image
	CGImageRelease (source_image);
	source_image = NULL;
	
	free(source_data_ptr);
    
	// Free the filename created by get_out_filename ()
	free (out_file_name);
	out_file_name = NULL;
	
	// free the image properties
	free (o);
	o = NULL;
	
	// if there is info in the buffer
	if (vImage_source->data != NULL) {
		free (vImage_source->data);
		vImage_source->data = NULL;
	}
	
	// free the buffer
	free (vImage_source);
	vImage_source = NULL;

} // Process 1 image
예제 #9
0
void calc_measurements(int L,int Lmax, int numdir, int **ima, int ** varnum,double *yy,int *dir,int *size,int **vois,int *numvois,double **jj,double jcoup, int *Mtrue){
  int mu,sum,i,j,k;
  int N=L*L,n,bin[L*L+1],sizebin[2*L+1],indpix[2*L+1][2*L+1],ibin,ibinmax,indspin[2*L+1];
  double cpx[L*L+1],cpy[L*L+1],theta,ymin,ymax,xx[2*L+1];
  mu=0;
  for (k=1;k<=L*L;k++) numvois[k]=0;

  //
  for(theta=0;theta<PI-.00001;theta+=PI/numdir){
    pixel_pos(L,cpx,cpy);
    rotate_image(N,cpx,cpy,theta);
    calc_ybounds(N,cpy,&ymin,&ymax);
    printf("theta=%f ymin=%f ymax=%f\n",theta,ymin,ymax);
    for(ibin=0;ibin<=2*L;ibin++) sizebin[ibin]=0;
    for(n=1;n<=N;n++) {
      bin[n]=cpy[n]-ymin+1;// bin belongs to 1,...,(int)(ymax-ymin)+1;
      if(bin[n]>2*L) {printf("cata bin\n");exit(2);}
      sizebin[bin[n]]++;
      indpix[bin[n]][sizebin[bin[n]]]=n;
    }
    // For each bin, numbered as ibin, we have the number of spins in it, sizebin[ibin] and their list indpix[ibin,1]... indpix[ibin,sizebin[ibin]
    ibinmax= 1+ymax-ymin;
    if(verbose>8){
      for(ibin=1;ibin<=ibinmax;ibin++) {
	printf("bin number %i size %i list:",ibin,sizebin[ibin]);
	for(i=1;i<=sizebin[ibin];i++) printf(" %i ",indpix[ibin][i]);
	printf("\n");
      }
    }
    for(ibin=1;ibin<=ibinmax;ibin++) {
      if(sizebin[ibin]>0){
	mu++;
	size[mu]=sizebin[ibin];
	// build ordered list of the spins in the constraint mu, ordered by the value of their x coordinate
	for(i=1;i<=sizebin[ibin];i++) {
	  indspin[i]=indpix[ibin][i];
	  xx[i]=cpx[indpix[ibin][i]];
	}
	sort2_MM(sizebin[ibin],xx,indspin);
	if(verbose>15){
	  printf("bin number %i size %i ordered list:",ibin,sizebin[ibin]);
	  for(i=1;i<=sizebin[ibin];i++) printf(" %i %f ;",indspin[i],xx[i]);
	  printf("\n");
	}
	for(i=1;i<=size[mu];i++) varnum[mu][i]=indspin[i];// i-ieme voisin dans mu
	for(i=1;i<size[mu];i++) {
	  if(verbose>10) printf("...  measurement mu=%i. Compute the coupling between variables %i and %i\n",mu,varnum[mu][i],varnum[mu][i+1]);
	  jj[mu][i]=calcjeff(jcoup,cpx[varnum[mu][i]],cpx[varnum[mu][i+1]],cpy[varnum[mu][i]],cpy[varnum[mu][i+1]]);
	}
	sum=0;
	for(n=1;n<=size[mu];n++) {
	  k=varnum[mu][n];
	  numvois[k]++;
	  vois[k][numvois[k]]=mu;
	  //printf("TESTTEST mu=%i k=%i numvois=%i vois=%i\n",mu,k,numvois[k],vois[k][numvois[k]]);
	  matrixcoordinates(L,k,&i,&j);
	  sum+= ima[i][j];
	}
	yy[mu]=sum;
	dir[mu]=theta;
      }
    }
  }
  *Mtrue=mu;
  for(mu=1;mu<=*Mtrue;mu++){
    if(size[mu]>Lmax){
      printf("DESASTRE mu=%i size=%i Lmax=%i\n",mu,size[mu],Lmax);
    }
  }
  if(verbose>4){
    for(mu=1;mu<=*Mtrue;mu++){
      printf("Measurement mu=%i, size=%i, list=",mu,size[mu]);
      for(n=1;n<=size[mu];n++){
	printf("%i ",varnum[mu][n]);
	matrixcoordinates(L,varnum[mu][n],&i,&j);
	printf("ima(%i,%i)=%i ;",i,j,ima[i][j]);
      }
      printf("\n   couplings=");
      for(i=1;i<size[mu];i++) printf("%f ",jj[mu][i]);
      printf("   yy=%f\n",yy[mu]);
    }
    for(i=1;i<=L*L;i++){
      printf("  variable %i belongs to these %i checks :",i,numvois[i]);
      for(n=1;n<=numvois[i];n++) printf(" %i",vois[i][n]);
      printf("\n");
    }
  }
}
예제 #10
0
void RotatedDC::DrawImage(const Image& image, const RealPoint& pos, ImageCombine combine) {
    Image rotated = rotate_image(image, angle);
    DrawPreRotatedImage(rotated, RealRect(pos,trInvS(RealSize(image))), combine);
}
예제 #11
0
void run_nightmare(int argc, char **argv)
{
    srand(0);
    if(argc < 4){
        fprintf(stderr, "usage: %s %s [cfg] [weights] [image] [layer] [options! (optional)]\n", argv[0], argv[1]);
        return;
    }

    char *cfg = argv[2];
    char *weights = argv[3];
    char *input = argv[4];
    int max_layer = atoi(argv[5]);

    int range = find_int_arg(argc, argv, "-range", 1);
    int rounds = find_int_arg(argc, argv, "-rounds", 1);
    int iters = find_int_arg(argc, argv, "-iters", 10);
    int octaves = find_int_arg(argc, argv, "-octaves", 4);
    float zoom = find_float_arg(argc, argv, "-zoom", 1.);
    float rate = find_float_arg(argc, argv, "-rate", .04);
    float thresh = find_float_arg(argc, argv, "-thresh", 1.);
    float rotate = find_float_arg(argc, argv, "-rotate", 0);
    char *prefix = find_char_arg(argc, argv, "-prefix", 0);

    network net = parse_network_cfg(cfg);
    load_weights(&net, weights);
    char *cfgbase = basecfg(cfg);
    char *imbase = basecfg(input);

    set_batch_network(&net, 1);
    image im = load_image_color(input, 0, 0);
    if(0){
        float scale = 1;
        if(im.w > 512 || im.h > 512){
            if(im.w > im.h) scale = 512.0/im.w;
            else scale = 512.0/im.h;
        }
        image resized = resize_image(im, scale*im.w, scale*im.h);
        free_image(im);
        im = resized;
    }

    int e;
    int n;
    for(e = 0; e < rounds; ++e){
            fprintf(stderr, "Iteration: ");
            fflush(stderr);
        for(n = 0; n < iters; ++n){  
            fprintf(stderr, "%d, ", n);
            fflush(stderr);
            int layer = max_layer + rand()%range - range/2;
            int octave = rand()%octaves;
            optimize_picture(&net, im, layer, 1/pow(1.33333333, octave), rate, thresh);
        }
        fprintf(stderr, "done\n");
        if(0){
            image g = grayscale_image(im);
            free_image(im);
            im = g;
        }
        char buff[256];
        if (prefix){
            sprintf(buff, "%s/%s_%s_%d_%06d",prefix, imbase, cfgbase, max_layer, e);
        }else{
            sprintf(buff, "%s_%s_%d_%06d",imbase, cfgbase, max_layer, e);
        }
        printf("%d %s\n", e, buff);
        save_image(im, buff);
        //show_image(im, buff);
        //cvWaitKey(0);

        if(rotate){
            image rot = rotate_image(im, rotate);
            free_image(im);
            im = rot;
        }
        image crop = crop_image(im, im.w * (1. - zoom)/2., im.h * (1.-zoom)/2., im.w*zoom, im.h*zoom);
        image resized = resize_image(crop, im.w, im.h);
        free_image(im);
        free_image(crop);
        im = resized;
    }
}