caddr_t bif_im_CreateImageBlob (caddr_t * qst, caddr_t * err, state_slot_t ** args) { im_env_t env; char * szMe = "IM CreateImageBlob"; caddr_t res; long x_size = bif_long_arg (qst, args, 0, szMe); long y_size = bif_long_arg (qst, args, 1, szMe); caddr_t bg_color = (caddr_t)bif_string_arg (qst, args, 2, szMe); caddr_t fmt = (caddr_t)bif_string_arg (qst, args, 3, szMe); im_init (&env, qst, args, "IM CreateImageBlob"); if (x_size <= 0 || y_size <= 0) im_leave_with_error (&env, "22023", "IM001", "Negative image size"); if (x_size*y_size > 3333279) /* 10M / 3 color - 54byte */ im_leave_with_error (&env, "22023", "IM001", "Too large image image size requested"); im_set_background (&env, bg_color); env.ime_status = MagickNewImage (env.ime_magick_wand, x_size, y_size, env.ime_background); if (env.ime_status == MagickFalse) im_leave_with_error (&env, "22023", "IM001", "Cannot create image"); env.ime_status = MagickSetImageFormat (env.ime_magick_wand, fmt); if (env.ime_status == MagickFalse) im_leave_with_error (&env, "22023", "IM001", "Cannot set image format"); res = im_write (&env); im_leave (&env); return res; }
caddr_t bif_im_ConvertImageBlob (caddr_t * qst, caddr_t * err, state_slot_t ** args) { im_env_t env; caddr_t res; char out_name[64]; caddr_t format = bif_string_arg (qst, args, 2, "IM ConvertImageBlob"); im_init (&env, qst, args, "IM ConvertImageBlob"); im_env_set_input_blob (&env, 0); im_env_set_blob_ext (&env, 3, -1); im_read (&env); if (env.ime_input_ext != NULL) { if (strlen(format) < 30) { strcpy(out_name, "image."); strcat(out_name, format); } } MagickResetIterator (env.ime_magick_wand); while (MagickNextImage (env.ime_magick_wand) != MagickFalse) { env.ime_status = MagickSetImageFormat (env.ime_magick_wand, format); MagickSetFilename (env.ime_magick_wand, out_name); if (env.ime_status == MagickFalse) im_leave_with_error (&env, "22023", "IM001", "bif_im_ConvertImageBlob cannot convert image"); } res = im_write (&env); im_leave (&env); return res; }
caddr_t bif_im_CropAndResizeImageBlob(caddr_t * qst, caddr_t * err, state_slot_t ** args) { im_env_t env; caddr_t res; unsigned long width = bif_long_arg (qst, args, 2, "IM CropAndResizeImageBlob"); unsigned long height = bif_long_arg (qst, args, 3, "IM CropAndResizeImageBlob"); long x = bif_long_arg (qst, args, 4, "IM CropAndResizeImageBlob"); long y = bif_long_arg (qst, args, 5, "IM CropAndResizeImageBlob"); long h_size = bif_long_arg (qst, args, 6, "IM ResizeImageBlob"); long v_size = bif_long_arg (qst, args, 7, "IM ResizeImageBlob"); double blur = bif_double_arg (qst, args, 8, "IM ResizeImageBlob"); long filter = bif_long_arg (qst, args, 9, "IM ResizeImageBlob"); if (filter < 0 || filter > 15) filter = PointFilter; im_init (&env, qst, args, "IM CropAndResizeImageBlob"); im_env_set_input_blob (&env, 0); im_env_set_blob_ext (&env, 10, -1); im_read (&env); MagickResetIterator (env.ime_magick_wand); while (MagickNextImage (env.ime_magick_wand) != MagickFalse) { MagickCropImage (env.ime_magick_wand, width, height, x, y); MagickResizeImage (env.ime_magick_wand, h_size, v_size, filter, blur); } res = im_write (&env); im_leave (&env); return res; }
caddr_t bif_im_DeepZoom4to1 (caddr_t * qst, caddr_t * err, state_slot_t ** args) { im_env_t env; caddr_t res; int fmt_is_set = 0; int image_ctr; im_init (&env, qst, args, "IM DeepZoom4to1"); im_set_background (&env, "#000000"); env.ime_target_magick_wand = NewMagickWand (); if (MagickFalse == MagickNewImage (env.ime_target_magick_wand, 256, 256, env.ime_background)) im_leave_with_error (&env, "22023", "IM001", "Can not make new image"); if (MagickFalse == MagickSetImageType (env.ime_target_magick_wand, TrueColorType)) im_leave_with_error (&env, "22023", "IM001", "Can not set image type"); if (MagickFalse == MagickSetImageDepth (env.ime_target_magick_wand, 16)) im_leave_with_error (&env, "22023", "IM001", "Can not set image depth"); if (MagickFalse == MagickSetImageExtent (env.ime_target_magick_wand, 256, 256)) im_leave_with_error (&env, "22023", "IM001", "Can not set image extent"); if (MagickFalse == MagickSetImageBackgroundColor (env.ime_target_magick_wand, env.ime_background)) im_leave_with_error (&env, "22023", "IM001", "Can not set image background"); image_ctr = BOX_ELEMENTS (args) / 2; if (image_ctr > 4) image_ctr = 4; while (0 < image_ctr--) { if (DV_DB_NULL == DV_TYPE_OF (bif_arg (qst, args, image_ctr*2, "IM DeepZoom4to1"))) continue; im_env_set_input_blob (&env, image_ctr * 2); /*im_env_set_blob_ext (&env, 2);*/ im_read (&env); MagickResetIterator (env.ime_magick_wand); while (MagickNextImage (env.ime_magick_wand) != MagickFalse) { unsigned long v_size, h_size; if (!fmt_is_set) { if (MagickFalse == MagickSetImageFormat (env.ime_target_magick_wand, MagickGetImageFormat (env.ime_magick_wand))) im_leave_with_error (&env, "22023", "IM001", "Can not set image format"); fmt_is_set = 1; } h_size = MagickGetImageWidth (env.ime_magick_wand); v_size = MagickGetImageHeight (env.ime_magick_wand); if ((256 < h_size) || (256 < v_size)) continue; MagickResizeImage (env.ime_magick_wand, h_size/2, v_size/2, BoxFilter, 1.0); if (MagickFalse == MagickCompositeImage (env.ime_target_magick_wand, env.ime_magick_wand, OverCompositeOp, (image_ctr & 1) * 128, (image_ctr & 2) * 64)) im_leave_with_error (&env, "22023", "IM001", "Can not composite image"); } im_reset_read (&env); } MagickProfileImage (env.ime_target_magick_wand, "*", NULL, 0); DestroyMagickWand (env.ime_magick_wand); env.ime_magick_wand = env.ime_target_magick_wand; env.ime_target_magick_wand = NULL; res = im_write (&env); im_leave (&env); return res; }
caddr_t bif_im_ConvertImageFile (caddr_t * qst, caddr_t * err, state_slot_t ** args) { im_env_t env; bif_string_arg (qst, args, 1, "IM ConvertImageFile"); im_init (&env, qst, args, "IM ConvertImageFile"); im_env_set_filenames (&env, 0, 1); im_read (&env); im_write (&env); im_leave (&env); return(0); }
caddr_t bif_im_RotateImageFile (caddr_t * qst, caddr_t * err, state_slot_t ** args) { im_env_t env; double v_size = bif_double_arg (qst, args, 1, "IM RotateImageFile"); im_init (&env, qst, args, "IM RotateImageFile"); im_env_set_filenames (&env, 0, 2); im_read (&env); im_set_background (&env, "#000000"); MagickResetIterator (env.ime_magick_wand); while (MagickNextImage (env.ime_magick_wand) != MagickFalse) { MagickRotateImage (env.ime_magick_wand, env.ime_background, v_size); } im_write (&env); im_leave (&env); return (0); }
caddr_t bif_im_ThumbnailImageFile (caddr_t * qst, caddr_t * err, state_slot_t ** args) { im_env_t env; long v_size = bif_long_arg (qst, args, 1, "IM ThumbnailImageFile"); long h_size = bif_long_arg (qst, args, 2, "IM ThumbnailImageFile"); long filter = bif_long_arg (qst, args, 3, "IM ThumbnailImageFile"); im_init (&env, qst, args, "IM ThumbnailImageFile"); im_env_set_filenames (&env, 0, 4); im_read (&env); MagickResetIterator (env.ime_magick_wand); while (MagickNextImage (env.ime_magick_wand) != MagickFalse) { MagickResizeImage (env.ime_magick_wand,v_size, h_size,filter,1.0); MagickProfileImage (env.ime_magick_wand, "*", NULL, 0); } im_write (&env); im_leave (&env); return(0); }
caddr_t bif_im_RotateImageBlob (caddr_t * qst, caddr_t * err, state_slot_t ** args) { im_env_t env; caddr_t res; double v_size = bif_double_arg (qst, args, 2, "IM RotateImageBlob"); im_init (&env, qst, args, "IM RotateImageBlob"); im_env_set_input_blob (&env, 0); im_env_set_blob_ext (&env, 3, -1); im_read (&env); im_set_background (&env, "#000000"); MagickResetIterator (env.ime_magick_wand); while (MagickNextImage (env.ime_magick_wand) != MagickFalse) { MagickRotateImage (env.ime_magick_wand, env.ime_background, v_size); } res = im_write (&env); im_leave (&env); return res; }
caddr_t bif_im_CropImageFile (caddr_t * qst, caddr_t * err, state_slot_t ** args) { im_env_t env; unsigned long width = (unsigned long) bif_long_arg (qst, args, 1, "IM CropImageFile"); unsigned long height = (unsigned long) bif_long_arg (qst, args, 2, "IM CropImageFile"); long x = bif_long_arg (qst, args, 3, "IM CropImageFile"); long y = bif_long_arg (qst, args, 4, "IM CropImageFile"); im_init (&env, qst, args, "IM CropImageFile"); im_env_set_filenames (&env, 0, 5); im_read (&env); MagickResetIterator (env.ime_magick_wand); while (MagickNextImage (env.ime_magick_wand) != MagickFalse) { MagickCropImage (env.ime_magick_wand, width, height, x, y); } im_write (&env); im_leave (&env); return (0); }
caddr_t bif_im_AnnotateImageBlob (caddr_t * qst, caddr_t * err, state_slot_t ** args) { char * szMe = "IM AnnotateImageBlob"; caddr_t res; caddr_t blob = (caddr_t)bif_arg (qst, args, 0, szMe); long blob_size = box_length (blob) - 1; long x_pos = bif_long_arg (qst, args, 1, szMe); long y_pos = bif_long_arg (qst, args, 2, szMe); caddr_t text = bif_string_arg (qst, args, 3, szMe); int n_args = BOX_ELEMENTS(args); long angle = n_args > 4 ? bif_long_arg (qst, args, 4, szMe) : 0; long f_size = n_args > 5 ? bif_long_arg (qst, args, 5, szMe) : 12; char *text_color = n_args > 6 ? bif_string_arg (qst, args, 6, szMe) : "black" ; dtp_t dtp = DV_TYPE_OF (blob); im_env_t env; im_init (&env, qst, args, "IM AnnotateImageBlob"); if (IS_STRING_DTP (dtp)) blob_size = box_length (blob) - 1; else if (dtp == DV_BIN) blob_size = box_length (blob); else im_leave_with_error (&env, "22023", "IM001", "AnnotateImageBlob needs string or binary as 1-st argument"); im_env_set_blob_ext (&env, 7, -1); env.ime_drawing_wand = NewDrawingWand (); im_read (&env); im_set_background (&env, text_color); DrawSetFillColor (env.ime_drawing_wand, env.ime_background); DrawSetFontSize (env.ime_drawing_wand, f_size); MagickResetIterator (env.ime_magick_wand); while (MagickNextImage (env.ime_magick_wand) != MagickFalse) { env.ime_status = MagickAnnotateImage (env.ime_magick_wand, env.ime_drawing_wand, x_pos, y_pos, angle, text); if (env.ime_status == MagickFalse) im_leave_with_error (&env, "22023", "IM001", "Cannot annotate image"); } res = im_write (&env); im_leave (&env); return res; }
caddr_t bif_im_CropImageBlob(caddr_t * qst, caddr_t * err, state_slot_t ** args) { im_env_t env; caddr_t res; unsigned long width = bif_long_arg (qst, args, 2, "IM CropImageBlob"); unsigned long height = bif_long_arg (qst, args, 3, "IM CropImageBlob"); long x = bif_long_arg (qst, args, 4, "IM CropImageBlob"); long y = bif_long_arg (qst, args, 5, "IM CropImageBlob"); im_init (&env, qst, args, "IM CropImageBlob"); im_env_set_input_blob (&env, 0); im_env_set_blob_ext (&env, 6, -1); im_read (&env); MagickResetIterator (env.ime_magick_wand); while (MagickNextImage (env.ime_magick_wand) != MagickFalse) { MagickCropImage (env.ime_magick_wand, width, height, x, y); } res = im_write (&env); im_leave (&env); return res; }
caddr_t bif_im_ResizeImageFile (caddr_t * qst, caddr_t * err, state_slot_t ** args) { im_env_t env; long v_size = bif_long_arg (qst, args, 1, "IM ResizeImageFile"); long h_size = bif_long_arg (qst, args, 2, "IM ResizeImageFile"); double blur = bif_double_arg (qst, args, 3, "IM ResizeImageFile"); long filter = bif_long_arg (qst, args, 4, "IM ResizeImageFile"); if (filter < 0 || filter > 15) filter = PointFilter; im_init (&env, qst, args, "IM ResiseImageFile"); im_env_set_filenames (&env, 0, 5); im_read (&env); MagickResetIterator (env.ime_magick_wand); while (MagickNextImage (env.ime_magick_wand) != MagickFalse) { MagickResizeImage (env.ime_magick_wand,v_size, h_size,filter,blur); } im_write (&env); im_leave (&env); return(0); }
caddr_t bif_im_ThumbnailImageBlob (caddr_t * qst, caddr_t * err, state_slot_t ** args) { im_env_t env; caddr_t res; long v_size = bif_long_arg (qst, args, 2, "IM ThumbnailImageBlob"); long h_size = bif_long_arg (qst, args, 3, "IM ThumbnailImageBlob"); long filter = bif_long_arg (qst, args, 4, "IM ThumbnailImageBlob"); if (filter < 0 || filter > 15) filter = PointFilter; im_init (&env, qst, args, "IM ThumbnailImageBlob"); im_env_set_input_blob (&env, 0); im_env_set_blob_ext (&env, 5, -1); im_read (&env); MagickResetIterator (env.ime_magick_wand); while (MagickNextImage (env.ime_magick_wand) != MagickFalse) { MagickResizeImage (env.ime_magick_wand,v_size, h_size,filter,1.0); MagickProfileImage (env.ime_magick_wand, "*", NULL, 0); } res = im_write (&env); im_leave (&env); return res; }
caddr_t bif_im_ResampleImageBlob (caddr_t * qst, caddr_t * err, state_slot_t ** args) { im_env_t env; caddr_t res; double v_size = bif_double_arg (qst, args, 2, "IM ResampleImageBlob"); double h_size = bif_double_arg (qst, args, 3, "IM ResampleImageBlob"); double blur = bif_double_arg (qst, args, 4, "IM ResampleImageBlob"); long filter = bif_long_arg (qst, args, 5, "IM ResampleImageBlob"); if (filter < 0 || filter > 15) filter = PointFilter; im_init (&env, qst, args, "IM ResampleImageBlob"); im_env_set_input_blob (&env, 0); im_env_set_blob_ext (&env, 6, -1); im_read (&env); MagickResetIterator (env.ime_magick_wand); while (MagickNextImage (env.ime_magick_wand) != MagickFalse) { MagickResampleImage (env.ime_magick_wand,v_size, h_size,filter,blur); } res = im_write (&env); im_leave (&env); return res; }
/* CLI for 3D SIFT */ int main(int argc, char *argv[]) { Image im; SIFT3D sift3d; Keypoint_store kp; SIFT3D_Descriptor_store desc; char *im_path, *keys_path, *desc_path, *draw_path; int c, num_args; const struct option longopts[] = { {"keys", required_argument, NULL, KEYS}, {"desc", required_argument, NULL, DESC}, {"draw", required_argument, NULL, DRAW}, {0, 0, 0, 0} }; // Parse the GNU standard options switch (parse_gnu(argc, argv)) { case SIFT3D_HELP: puts(help_msg); print_opts_SIFT3D(); return 0; case SIFT3D_VERSION: return 0; case SIFT3D_FALSE: break; default: err_msgu("Unexpected return from parse_gnu \n"); return 1; } // Initialize the SIFT data if (init_SIFT3D(&sift3d)) { err_msgu("Failed to initialize SIFT data."); return 1; } // Parse the SIFT3D options and increment the argument list if ((argc = parse_args_SIFT3D(&sift3d, argc, argv, SIFT3D_FALSE)) < 0) return 1; // Parse the kpSift3d options opterr = 1; keys_path = desc_path = draw_path = NULL; while ((c = getopt_long(argc, argv, "", longopts, NULL)) != -1) { switch (c) { case KEYS: keys_path = optarg; break; case DESC: desc_path = optarg; break; case DRAW: draw_path = optarg; break; case '?': default: return 1; } } // Ensure we have at least one output if (keys_path == NULL && desc_path == NULL && draw_path == NULL) { err_msg("No outputs specified."); return 1; } // Parse the required arguments num_args = argc - optind; if (num_args < 1) { err_msg("Not enough arguments."); return 1; } else if (num_args > 1) { err_msg("Too many arguments."); return 1; } im_path = argv[optind]; // Initialize data init_Keypoint_store(&kp); init_SIFT3D_Descriptor_store(&desc); init_im(&im); // Read the image if (im_read(im_path, &im)) { err_msg("Could not read image."); return 1; } // Extract keypoints if (SIFT3D_detect_keypoints(&sift3d, &im, &kp)) { err_msgu("Failed to detect keypoints."); return 1; } // Optionally write the keypoints if (keys_path != NULL && write_Keypoint_store(keys_path, &kp)) { char msg[BUF_SIZE]; snprintf(msg, BUF_SIZE, "Failed to write the keypoints to " "\"%s\"", keys_path); err_msg(msg); return 1; } // Optionally extract descriptors if (desc_path != NULL) { // Extract descriptors if (SIFT3D_extract_descriptors(&sift3d, &kp,&desc)) { err_msgu("Failed to extract descriptors."); return 1; } // Write the descriptors if (write_SIFT3D_Descriptor_store(desc_path, &desc)) { char msg[BUF_SIZE]; snprintf(msg, BUF_SIZE, "Failed to write the " "descriptors to \"%s\"", desc_path); err_msg(msg); return 1; } } // Optionally draw the keypoints if (draw_path != NULL) { Image draw; Mat_rm keys; // Initialize intermediates init_im(&draw); if (init_Mat_rm(&keys, 0, 0, DOUBLE, SIFT3D_FALSE)) err_msgu("Failed to initialize keys matrix"); // Convert to matrices if (Keypoint_store_to_Mat_rm(&kp, &keys)) { err_msgu("Failed to convert the keypoints to " "a matrix."); return 1; } // Draw the points if (draw_points(&keys, SIFT3D_IM_GET_DIMS(&im), 1, &draw)) { err_msgu("Failed to draw the points."); return 1; } // Write the output if (im_write(draw_path, &draw)) { char msg[BUF_SIZE]; snprintf(msg, BUF_SIZE, "Failed to draw the keypoints " "to \"%s\"", draw_path); err_msg(msg); return 1; } // Clean up im_free(&draw); } return 0; }
/* This illustrates how to use SIFT3D within a function, and free all memory * afterwards. */ int demo(void) { Image im, draw; Mat_rm keys; SIFT3D sift3d; Keypoint_store kp; SIFT3D_Descriptor_store desc; // Initialize the intermediates init_Keypoint_store(&kp); init_SIFT3D_Descriptor_store(&desc); init_im(&im); init_im(&draw); if (init_Mat_rm(&keys, 0, 0, DOUBLE, SIFT3D_FALSE)) return 1; if (init_SIFT3D(&sift3d)) { cleanup_Mat_rm(&keys); return 1; } // Read the image if (im_read(im_path, &im)) goto demo_quit; // Detect keypoints if (SIFT3D_detect_keypoints(&sift3d, &im, &kp)) goto demo_quit; // Write the keypoints to a file if (write_Keypoint_store(keys_path, &kp)) goto demo_quit; printf("Keypoints written to %s. \n", keys_path); // Extract descriptors if (SIFT3D_extract_descriptors(&sift3d, &kp, &desc)) goto demo_quit; // Write the descriptors to a file if (write_SIFT3D_Descriptor_store(desc_path, &desc)) goto demo_quit; printf("Descriptors written to %s. \n", desc_path); // Convert the keypoints to a matrix if (Keypoint_store_to_Mat_rm(&kp, &keys)) goto demo_quit; // Draw the keypoints if (draw_points(&keys, im.dims, 1, &draw)) goto demo_quit; // Write the drawn keypoints to a file if (im_write(draw_path, &draw)) goto demo_quit; printf("Keypoints drawn in %s. \n", draw_path); // Clean up im_free(&im); im_free(&draw); cleanup_Mat_rm(&keys); cleanup_SIFT3D(&sift3d); cleanup_Keypoint_store(&kp); cleanup_SIFT3D_Descriptor_store(&desc); return 0; demo_quit: // Clean up and return an error im_free(&im); im_free(&draw); cleanup_Mat_rm(&keys); cleanup_SIFT3D(&sift3d); cleanup_Keypoint_store(&kp); cleanup_SIFT3D_Descriptor_store(&desc); return 1; }
/*---------------------------------------------------------------------------*/ int main(int argc, char *argv[]) { /* Image variables */ char Name1[50]; char Name2[50]; IM_TYPE *Image1; IM_TYPE *Image2; IM_TYPE *Image3; FLOAT_TYPE **Data1; SHORT_TYPE **Data2; FLOAT_TYPE **Data3; int PixType, Xdim, Ydim, Zdim, DimCnt; /* Program variables */ int Debug = FALSE; int Invert = FALSE; int Gradient = FALSE; int i = 0, x, y, X, Y; int MinCount; int MinIndex; float MinValue; int Count; float TotalCnt = 0; float Dx, Dy; /* Interpret program options */ printf("WATERSHED Program - KUIM Version 2.0\n\n"); while ((++i < argc) && (argv[i][0] == '-')) switch (argv[i][1]) { case 'i': Invert = TRUE; break; case 'g': Gradient = TRUE; break; case 'd': Debug = TRUE; break; default: Error("Invalid option encountered"); break; } /* Check number of file names */ if (argc - i != 2) { fprintf(stderr, "Usage: watershed [options] infile outfile\n"); fprintf(stderr, " [-d] Print debugging information\n"); fprintf(stderr, " [-i] Invert image before finding watersheds\n"); fprintf(stderr, " [-g] Calculate gradient watersheds\n"); exit(1); } /* Get image file names from argument list */ if (sscanf(argv[i++], "%s", Name1) == 0) Error("Could not get input file name"); if (sscanf(argv[i++], "%s", Name2) == 0) Error("Could not get output file name"); /* Read input image */ Image1 = im_open(Name1, &PixType, &Xdim, &Ydim, &Zdim, &DimCnt); if (DimCnt != 2) Error("Can not process 1D or 3D images"); Data1 = (FLOAT_TYPE **) im_alloc2D(Image1, FLOAT); im_read(Image1, FLOAT, (char *) &(Data1[0][0])); /* Create output image */ Image2 = im_create(Name2, SHORT, Xdim, Ydim, Zdim); Data2 = (SHORT_TYPE **) im_alloc2D(Image2, SHORT); Image3 = im_create("/dev/null", FLOAT, Xdim, Ydim, Zdim); Data3 = (FLOAT_TYPE **) im_alloc2D(Image3, FLOAT); /* Initialize output image */ for (y = 0; y < Ydim; y++) for (x = 0; x < Xdim; x++) Data2[y][x] = 0; /* Invert input image data */ if (Invert == TRUE) for (y = 0; y < Ydim; y++) for (x = 0; x < Xdim; x++) Data1[y][x] = -Data1[y][x]; /* Calculate gradient magnitude image */ if (Gradient == TRUE) { for (y = 1; y < (Ydim - 1); y++) for (x = 1; x < (Xdim - 1); x++) { Dx = (Data1[y + 1][x + 1] + 2 * Data1[y][x + 1] + Data1[y - 1][x + 1] - Data1[y + 1][x - 1] - 2 * Data1[y][x - 1] - Data1[y - 1][x - 1]) / 8; Dy = (Data1[y + 1][x + 1] + 2 * Data1[y + 1][x] + Data1[y + 1][x - 1] - Data1[y - 1][x + 1] - 2 * Data1[y - 1][x] - Data1[y - 1][x - 1]) / 8; Data3[y][x] = (float) sqrt((double) (Dx * Dx + Dy * Dy)); } for (y = 1; y < (Ydim - 1); y++) for (x = 1; x < (Xdim - 1); x++) Data1[y][x] = Data3[y][x]; for (x = 0; x < Xdim; x++) { Data1[0][x] = Data1[1][x]; Data1[Ydim - 1][x] = Data1[Ydim - 2][x]; } for (y = 0; y < Ydim; y++) { Data1[y][0] = Data1[y][1]; Data1[y][Xdim - 1] = Data1[y][Xdim - 2]; } } /* Mark boundary as pseudo-minima */ MinCount = 1; for (y = 0; y < Ydim; y++) Data2[y][0] = Data2[y][Xdim - 1] = MinCount; for (x = 0; x < Xdim; x++) Data2[0][x] = Data2[Ydim - 1][x] = MinCount; /* Find local minima and gradient for each pixel */ for (y = 1; y < (Ydim - 1); y++) for (x = 1; x < (Xdim - 1); x++) { MinValue = Data1[y][x]; MinIndex = 4; for (Y = 0; Y < 3; Y++) for (X = 0; X < 3; X++) if (Data1[y + Y - 1][x + X - 1] <= MinValue) { MinValue = Data1[y + Y - 1][x + X - 1]; MinIndex = Y * 3 + X; } if (MinIndex == 4) Data2[y][x] = (++MinCount); else Data2[y][x] = -MinIndex; } /* Follow gradient downhill for each pixel */ for (y = 1; y < (Ydim - 1); y++) for (x = 1; x < (Xdim - 1); x++) { X = x; Y = y; Count = 0; while (Data2[Y][X] <= 0) { switch (Data2[Y][X]) { case 0: X--; Y--; break; case -1: Y--; break; case -2: X++; Y--; break; case -3: X--; break; case -5: X++; break; case -6: X--; Y++; break; case -7: Y++; break; case -8: X++; Y++; break; } Count++; } Data2[y][x] = Data2[Y][X]; TotalCnt += Count; } /* Write information to output image */ if (Debug == TRUE) printf("mincount = %d\n", MinCount); if (Debug == TRUE) printf("ave count = %f\n", TotalCnt / ((Xdim - 1) * (Ydim - 1))); im_write(Image2, SHORT, (char *) &(Data2[0][0])); im_free2D((char **) Data1); im_free2D((char **) Data2); im_free2D((char **) Data3); return (0); }