diff options
-rw-r--r-- | source/blender/blenkernel/BKE_image.h | 3 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/image.c | 77 | ||||
-rw-r--r-- | source/blender/makesrna/intern/rna_image_api.c | 12 | ||||
-rw-r--r-- | source/creator/tests/alltest.c | 181 |
4 files changed, 136 insertions, 137 deletions
diff --git a/source/blender/blenkernel/BKE_image.h b/source/blender/blenkernel/BKE_image.h index 052f7738f2b..56c58cdc6bf 100644 --- a/source/blender/blenkernel/BKE_image.h +++ b/source/blender/blenkernel/BKE_image.h @@ -156,8 +156,7 @@ struct Image *BKE_image_copy(struct Image *ima); void BKE_image_merge(struct Image *dest, struct Image *source); /* copy image file to a directory rebuilding subdirectory structure */ -int BKE_export_image(struct Image *im, const char *dest_dir, char *out_path, int out_path_len); - +int BKE_get_image_export_path(struct Image *im, const char *dest_dir, char *abs, int abs_size, char *rel, int rel_size); #ifdef __cplusplus } diff --git a/source/blender/blenkernel/intern/image.c b/source/blender/blenkernel/intern/image.c index f0b29f766ec..276d79b7e32 100644 --- a/source/blender/blenkernel/intern/image.c +++ b/source/blender/blenkernel/intern/image.c @@ -2117,41 +2117,51 @@ void BKE_image_user_calc_imanr(ImageUser *iuser, int cfra, int fieldnr) } /* - Copy an image to destination directory rebuilding subdirectory structure if needed. - Target image path is written to out_path. - Returns 1 on success, 0 otherwise. + Produce image export path. + + Fails returning 0 if image filename is empty or if destination path + matches image path (i.e. both are the same file). + + Trailing slash in dest_dir is optional. Logic: - - if an image is "below" current .blend file directory, rebuild the same dir structure in dest_dir + - if an image is "below" current .blend file directory, rebuild the + same dir structure in dest_dir - For example //textures/foo/bar.png becomes [dest_dir]/textures/foo/bar.png. + For example //textures/foo/bar.png becomes + [dest_dir]/textures/foo/bar.png. - - if an image is not "below" current .blend file directory, disregard it's path and copy it in the - same directory where 3D file goes. + - if an image is not "below" current .blend file directory, + disregard it's path and copy it in the same directory where 3D file + goes. For example //../foo/bar.png becomes [dest_dir]/bar.png. This logic will help ensure that all image paths are relative and that a user gets his images in one place. It'll also provide consistent behaviour across exporters. - */ -int BKE_export_image(Image *im, const char *dest_dir, char *out_path, int out_path_len) +int BKE_get_image_export_path(struct Image *im, const char *dest_dir, char *abs, int abs_size, char *rel, int rel_size) { char path[FILE_MAX]; char dir[FILE_MAX]; char base[FILE_MAX]; char blend_dir[FILE_MAX]; /* directory, where current .blend file resides */ char dest_path[FILE_MAX]; + char rel_dir[FILE_MAX]; int len; - out_path[0]= 0; + if (abs) + abs[0]= 0; + + if (rel) + rel[0]= 0; BLI_split_dirfile_basic(G.sce, blend_dir, NULL); - if (!strcmp(im->name, "") || im->type != IMA_TYPE_IMAGE) { - if (G.f & G_DEBUG) printf("invalid image type\n"); + if (!strlen(im->name)) { + if (G.f & G_DEBUG) printf("Invalid image type.\n"); return 0; } @@ -2160,61 +2170,48 @@ int BKE_export_image(Image *im, const char *dest_dir, char *out_path, int out_pa /* expand "//" in filename and get absolute path */ BLI_convertstringcode(path, G.sce); - /* proceed only if image file exists */ - if (!BLI_exists(path)) { - if (G.f & G_DEBUG) printf("%s doesn't exist\n", path); - return 0; - } - /* get the directory part */ BLI_split_dirfile_basic(path, dir, base); len= strlen(blend_dir); + rel_dir[0] = 0; + /* if image is "below" current .blend file directory */ if (!strncmp(path, blend_dir, len)) { /* if image is _in_ current .blend file directory */ if (!strcmp(dir, blend_dir)) { - /* copy to dest_dir */ BLI_join_dirfile(dest_path, dest_dir, base); } /* "below" */ else { - char rel[FILE_MAX]; - /* rel = image_path_dir - blend_dir */ - BLI_strncpy(rel, dir + len, sizeof(rel)); - - BLI_join_dirfile(dest_path, dest_dir, rel); - - /* build identical directory structure under dest_dir */ - BLI_recurdir_fileops(dest_path); + BLI_strncpy(rel_dir, dir + len, sizeof(rel_dir)); + BLI_join_dirfile(dest_path, dest_dir, rel_dir); BLI_join_dirfile(dest_path, dest_path, base); } } /* image is out of current directory */ else { - /* copy to dest_dir */ BLI_join_dirfile(dest_path, dest_dir, base); } - if (G.f & G_DEBUG) printf("copying %s to %s\n", path, dest_path); - - /* only copy if paths differ */ - if (strcmp(path, dest_path)) { - if (BLI_copy_fileops(path, dest_path) != 0) { - if (G.f & G_DEBUG) printf("couldn't copy %s to %s\n", path, dest_path); - return 0; - } - } - else if (G.f & G_DEBUG){ - printf("%s and %s are the same file\n", path, dest_path); + /* only return 1 if paths differ */ + if (!strcmp(path, dest_path)) { + if (G.f & G_DEBUG) printf("%s and %s are the same file\n", path, dest_path); + return 0; } - BLI_strncpy(out_path, dest_path, out_path_len); + if (abs) + BLI_strncpy(abs, dest_path, abs_size); + + if (rel) { + strncat(rel, rel_dir, rel_size); + strncat(rel, base, rel_size); + } return 1; } diff --git a/source/blender/makesrna/intern/rna_image_api.c b/source/blender/makesrna/intern/rna_image_api.c index 42ee2b64c7a..20770ef2957 100644 --- a/source/blender/makesrna/intern/rna_image_api.c +++ b/source/blender/makesrna/intern/rna_image_api.c @@ -41,12 +41,12 @@ #include "BKE_utildefines.h" #include "BKE_image.h" -static char *rna_Image_export(Image *image, char *dest_dir) +static char *rna_Image_get_export_path(Image *image, char *dest_dir, int rel) { int length = FILE_MAX; char *path= MEM_callocN(length, "image file path"); - if (!BKE_export_image(image, dest_dir, path, length)) { + if (!BKE_get_image_export_path(image, dest_dir, rel ? NULL : path, length, rel ? path : NULL, length )) { MEM_freeN(path); return NULL; } @@ -61,11 +61,13 @@ void RNA_api_image(StructRNA *srna) FunctionRNA *func; PropertyRNA *parm; - func= RNA_def_function(srna, "export", "rna_Image_export"); - RNA_def_function_ui_description(func, "Copy image file to a directory rebuilding subdirectory structure."); + func= RNA_def_function(srna, "export", "rna_Image_get_export_path"); + RNA_def_function_ui_description(func, "Produce image export path."); parm= RNA_def_string(func, "dest_dir", "", 0, "", "Destination directory."); RNA_def_property_flag(parm, PROP_REQUIRED); - parm= RNA_def_string(func, "path", "", 0, "", "Absolute file path of copied image."); + parm= RNA_def_boolean(func, "get_rel_path", 1, "", "Return relative path if True."); + RNA_def_property_flag(parm, PROP_REQUIRED); + parm= RNA_def_string(func, "path", "", 0, "", "Absolute export path."); RNA_def_function_return(func, parm); } diff --git a/source/creator/tests/alltest.c b/source/creator/tests/alltest.c index 8bb2b1a9bb0..99e0d2f5b26 100644 --- a/source/creator/tests/alltest.c +++ b/source/creator/tests/alltest.c @@ -19,48 +19,26 @@ char bprogname[FILE_MAXDIR+FILE_MAXFILE]; char btempdir[FILE_MAXDIR+FILE_MAXFILE]; +typedef struct ImageTestResult { + char *path; + char *rel; + int ret; +} ImageTestResult; + typedef struct ImageTestData { char *path; /* image filename */ - char *expect_path; /* file path that we expect */ - int type; /* image type */ - int ret; /* expected function return value */ - int create_file; /* whether the file should be created */ + ImageTestResult result[10]; } ImageTestData; -/* recursively deletes a directory only if it is under /tmp */ -static void delete_only_tmp(char *path, int dir) { -#ifdef WIN32 -#else - if (!strncmp(path, "/tmp/", 5) && BLI_exists(path)) { - BLI_delete(path, dir, 1); - } -#endif -} - -static void touch_only_tmp(char *path) { -#ifdef WIN32 -#else - if (!strncmp(path, "/tmp/", 5)) { - BLI_touch(path); - } -#endif -} - /* check that BKE_copy_images manipulates paths correctly */ START_TEST(test_copy_images) { char **dir; ImageTestData *test; + int i,j; - /* XXX Windows not tested */ #ifdef WIN32 - static ImageTestData test_data[] = { - {"//bar/image.png", "C:\\Temp\\bar\\image.png"}, - /* TODO add more */ - {NULL, NULL}, - }; - - BLI_strncpy(G.sce, "C:\\Temp\untitled.blend", sizeof(G.sce)); + /* TBD... */ #else /* XXX are these paths possible in image->name?: @@ -70,77 +48,100 @@ START_TEST(test_copy_images) if so, BKE_copy_images currently doesn't support them! */ + + const char *blend_dir = "/home/user/foo"; + char *dest_dir[] = {"/home/user/", "/home/user", "/home/user/export/", "/home/user/foo/", NULL}; + static ImageTestData test_data[] = { - {"//bar/image.png", "/tmp/blender/dest/bar/image.png", IMA_TYPE_IMAGE, 1, 1}, - {"//image.png", "/tmp/blender/dest/image.png", IMA_TYPE_IMAGE, 1, 1}, - {"//textures/test/foo/bar/image.png", "/tmp/blender/dest/textures/test/foo/bar/image.png", IMA_TYPE_IMAGE, 1, 1}, - {"//textures/test/foo/bar/image.png", "", IMA_TYPE_MULTILAYER, 0, 1}, - {"//./foo/bar/image.png", "/tmp/blender/dest/foo/bar/image.png", IMA_TYPE_IMAGE, 1, 1}, - {"//../foo/bar/image.png", "/tmp/blender/dest/image.png", IMA_TYPE_IMAGE, 1, 1}, - {"/tmp/blender/image.png", "/tmp/blender/dest/image.png", IMA_TYPE_IMAGE, 1, 1}, - /* expecting it to return 1 when src and dest are the same file */ - {"/tmp/blender/foo/bar/image.png", "/tmp/blender/dest/image.png", IMA_TYPE_IMAGE, 1, 1}, - {"/tmp/blender/dest/image.png", "/tmp/blender/dest/image.png", IMA_TYPE_IMAGE, 1, 1}, - /* expecting empty path and 0 return value for non-existing files */ - {"/tmp/blender/src/file-not-created", "", IMA_TYPE_IMAGE, 0, 0}, - {"", "", IMA_TYPE_IMAGE, 0, 0}, - {NULL, NULL}, - }; - char *dest_dir[] = {"/tmp/blender/dest/", "/tmp/blender/dest", NULL}; - const char *blend_dir = "/tmp/blender/src"; + /* image path | [expected output path | corresponding relative path | expected return value] */ + + /* relative, 0 level deep */ + {"//image.png", {{"/home/user/image.png", "image.png", 1}, + {"/home/user/image.png", "image.png", 1}, + {"/home/user/export/image.png", "image.png", 1}, + {"", "", 0},}}, + + /* relative, 1 level deep */ + {"//bar/image.png", {{"/home/user/bar/image.png", "bar/image.png", 1}, + {"/home/user/bar/image.png", "bar/image.png", 1}, + {"/home/user/export/bar/image.png", "bar/image.png", 1}, + {"", "", 0},}}, + + /* relative, 2 level deep */ + {"//bar/foo/image.png", {{"/home/user/bar/foo/image.png", "bar/foo/image.png", 1}, + {"/home/user/bar/foo/image.png", "bar/foo/image.png", 1}, + {"/home/user/export/bar/foo/image.png", "bar/foo/image.png", 1}, + {"", "", 0},}}, + + /* absolute, not under .blend dir */ + {"/home/user/bar/image.png", {{"/home/user/image.png", "image.png", 1}, + {"/home/user/image.png", "image.png", 1}, + {"/home/user/export/image.png", "image.png", 1}, + {"/home/user/foo/image.png", "image.png", 1},}}, + + /* absolute, under .blend dir, 0 level deep */ + {"/home/user/foo/image.png", {{"/home/user/image.png", "image.png", 1}, + {"/home/user/image.png", "image.png", 1}, + {"/home/user/export/image.png", "image.png", 1}, + {"", "", 0},}}, + + /* absolute, under .blend dir, 1 level deep */ + {"/home/user/foo/bar/image.png", {{"/home/user/bar/image.png", "bar/image.png", 1}, + {"/home/user/bar/image.png", "bar/image.png", 1}, + {"/home/user/export/bar/image.png", "bar/image.png", 1}, + {"", "", 0},}}, + + /* absolute, under .blend dir, 2 level deep */ + {"/home/user/foo/bar/foo/image.png", {{"/home/user/bar/foo/image.png", "bar/foo/image.png", 1}, + {"/home/user/bar/foo/image.png", "bar/foo/image.png", 1}, + {"/home/user/export/bar/foo/image.png", "bar/foo/image.png", 1}, + {"", "", 0},}}, + + /* empty image path, don't let these pass! */ + {"", {{"", 0}, + {"", 0}, + {"", 0}}}, + + {NULL}, + }; /* substitute G.sce */ BLI_snprintf(G.sce, sizeof(G.sce), "%s/untitled.blend", blend_dir); #endif - /* only delete files/directories under /tmp/ ! */ - delete_only_tmp(blend_dir, 1); - - for (dir = dest_dir; *dir; dir++) { - delete_only_tmp(*dir, 1); - } - - /* create files */ - BLI_recurdir_fileops(blend_dir); - - /* create fake empty source files */ - for (test= &test_data[0]; test->path; test++) { - char dir[FILE_MAX]; - char path[FILE_MAX]; - - if (!test->create_file) continue; - - /* expand "//" */ - BLI_strncpy(path, test->path, sizeof(path)); - BLI_convertstringcode(path, G.sce); - - /* create a directory */ - BLI_split_dirfile_basic(path, dir, NULL); - BLI_recurdir_fileops(dir); - - /* create a file */ - touch_only_tmp(path); - } - - for (dir = dest_dir; *dir; dir++) { + for (dir= dest_dir, i= 0; *dir; dir++, i++) { for (test= &test_data[0]; test->path; test++) { Image image; char path[FILE_MAX]; + char rel[FILE_MAX]; char part[200]; int ret; BLI_strncpy(image.name, test->path, sizeof(image.name)); - image.type= test->type; - ret= BKE_export_image(&image, *dir, path, sizeof(path)); + /* passing NULL as abs path or rel path or both shouldn't break it */ + int abs_rel_null[][2]= {{0, 0}, {1, 0}, {0, 1}, {1, 1}, {-1}}; + + for (j= 0; abs_rel_null[j][0] != -1; j++) { + + int *is_null= abs_rel_null[j]; + + ret= BKE_get_image_export_path(&image, *dir, + is_null[0] ? NULL : path, sizeof(path), + is_null[1] ? NULL : rel, sizeof(rel)); + + BLI_snprintf(part, sizeof(part), "For image at %s (output abs path is %s, rel path is %s)", + test->path, is_null[0] ? "NULL" : "non-NULL", is_null[1] ? "NULL" : "non-NULL"); + + /* we should get what we expect */ + ImageTestResult *res= &test->result[i]; + fail_if(ret != res->ret, "%s, expected to return %d got %d.", part, res->ret, ret); - /* check if we got correct output */ - BLI_snprintf(part, sizeof(part), "For image with filename %s and type %d", test->path, test->type); - fail_if(ret != test->ret, "%s, expected %d as return value got %d.", part, test->ret, ret); - fail_if(strcmp(path, test->expect_path), "%s, expected path %s got \"%s\".", part, test->expect_path, path); - if (test->ret == ret && ret == 1) { - fail_if(!BLI_exists(test->expect_path), "%s, expected %s to be created.", part, test->expect_path); + if (!is_null[0] && res->path) + fail_if(strcmp(path, res->path), "%s, expected absolute path \"%s\" got \"%s\".", part, res->path, path); + if (!is_null[1] && res->rel) + fail_if(strcmp(rel, res->rel), "%s, expected relative path \"%s\" got \"%s\".", part, res->rel, rel); } } } @@ -149,10 +150,10 @@ END_TEST static Suite *image_suite(void) { - Suite *s = suite_create("Image"); + Suite *s= suite_create("Image"); /* Core test case */ - TCase *tc_core = tcase_create("Core"); + TCase *tc_core= tcase_create("Core"); tcase_add_test(tc_core, test_copy_images); suite_add_tcase(s, tc_core); @@ -162,8 +163,8 @@ static Suite *image_suite(void) int run_tests() { int totfail; - Suite *s = image_suite(); - SRunner *sr = srunner_create(s); + Suite *s= image_suite(); + SRunner *sr= srunner_create(s); /* run tests */ srunner_run_all(sr, CK_VERBOSE); |