Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJesse Yurkovich <jesse.y@gmail.com>2022-05-12 06:11:44 +0300
committerJesse Yurkovich <jesse.y@gmail.com>2022-05-12 06:11:44 +0300
commit578771ae4dcb8643214c69a7b9761ca154f40f63 (patch)
tree6f69d7ee0001034b7c6f7e359f1da80d80ae18d1 /source/blender
parent8d9d5da13706b668b9bd0d631e00c9b00b73f3ea (diff)
UDIM: Add support for packing inside .blend files
This completes support for tiled texture packing on the Blender / Cycles side of things. Most of these changes fall into one of three categories: - Updating Image handling code to pack/unpack tiled and multi-view images - Updating Cycles to handle tiled textures through BlenderImageLoader - Updating OSL to properly handle textures with multiple slots Differential Revision: https://developer.blender.org/D14395
Diffstat (limited to 'source/blender')
-rw-r--r--source/blender/blenkernel/intern/image.cc121
-rw-r--r--source/blender/blenkernel/intern/packedFile.c24
-rw-r--r--source/blender/blenloader/intern/versioning_300.c11
-rw-r--r--source/blender/editors/space_image/image_ops.c27
-rw-r--r--source/blender/makesdna/DNA_image_types.h5
-rw-r--r--source/blender/makesrna/intern/rna_image.c10
-rw-r--r--source/blender/makesrna/intern/rna_image_api.c5
7 files changed, 133 insertions, 70 deletions
diff --git a/source/blender/blenkernel/intern/image.cc b/source/blender/blenkernel/intern/image.cc
index dfa820519a5..27de9a37728 100644
--- a/source/blender/blenkernel/intern/image.cc
+++ b/source/blender/blenkernel/intern/image.cc
@@ -721,6 +721,9 @@ static void copy_image_packedfiles(ListBase *lb_dst, const ListBase *lb_src)
imapf_src = imapf_src->next) {
ImagePackedFile *imapf_dst = static_cast<ImagePackedFile *>(
MEM_mallocN(sizeof(ImagePackedFile), "Image Packed Files (copy)"));
+
+ imapf_dst->view = imapf_src->view;
+ imapf_dst->tile_number = imapf_src->tile_number;
STRNCPY(imapf_dst->filepath, imapf_src->filepath);
if (imapf_src->packedfile) {
@@ -1197,7 +1200,8 @@ Image *BKE_image_add_from_imbuf(Main *bmain, ImBuf *ibuf, const char *name)
}
/** Pack image buffer to memory as PNG or EXR. */
-static bool image_memorypack_imbuf(Image *ima, ImBuf *ibuf, const char *filepath)
+static bool image_memorypack_imbuf(
+ Image *ima, ImBuf *ibuf, int view, int tile_number, const char *filepath)
{
ibuf->ftype = (ibuf->rect_float) ? IMB_FTYPE_OPENEXR : IMB_FTYPE_PNG;
@@ -1219,6 +1223,8 @@ static bool image_memorypack_imbuf(Image *ima, ImBuf *ibuf, const char *filepath
imapf = static_cast<ImagePackedFile *>(MEM_mallocN(sizeof(ImagePackedFile), "Image PackedFile"));
STRNCPY(imapf->filepath, filepath);
imapf->packedfile = pf;
+ imapf->view = view;
+ imapf->tile_number = tile_number;
BLI_addtail(&ima->packedfiles, imapf);
ibuf->encodedbuffer = nullptr;
@@ -1234,42 +1240,47 @@ bool BKE_image_memorypack(Image *ima)
image_free_packedfiles(ima);
- if (BKE_image_is_multiview(ima)) {
- /* Store each view as a separate packed files with R_IMF_VIEWS_INDIVIDUAL. */
- ImageView *iv;
- int i;
+ const int tot_viewfiles = image_num_viewfiles(ima);
+ const bool is_tiled = (ima->source == IMA_SRC_TILED);
+ const bool is_multiview = BKE_image_is_multiview(ima);
- for (i = 0, iv = static_cast<ImageView *>(ima->views.first); iv;
- iv = static_cast<ImageView *>(iv->next), i++) {
- ImBuf *ibuf = image_get_cached_ibuf_for_index_entry(ima, i, 0, nullptr);
+ ImageUser iuser{};
+ BKE_imageuser_default(&iuser);
+ char tiled_filepath[FILE_MAX];
+ for (int view = 0; view < tot_viewfiles; view++) {
+ LISTBASE_FOREACH (ImageTile *, tile, &ima->tiles) {
+ int index = (is_multiview || is_tiled) ? view : IMA_NO_INDEX;
+ int entry = is_tiled ? tile->tile_number : 0;
+ ImBuf *ibuf = image_get_cached_ibuf_for_index_entry(ima, index, entry, nullptr);
if (!ibuf) {
ok = false;
break;
}
- /* if the image was a R_IMF_VIEWS_STEREO_3D we force _L, _R suffices */
- if (ima->views_format == R_IMF_VIEWS_STEREO_3D) {
- const char *suffix[2] = {STEREO_LEFT_SUFFIX, STEREO_RIGHT_SUFFIX};
- BLI_path_suffix(iv->filepath, FILE_MAX, suffix[i], "");
+ const char *filepath = ibuf->name;
+ if (is_tiled) {
+ iuser.tile = tile->tile_number;
+ BKE_image_user_file_path(&iuser, ima, tiled_filepath);
+ filepath = tiled_filepath;
+ }
+ else if (is_multiview) {
+ ImageView *iv = static_cast<ImageView *>(BLI_findlink(&ima->views, view));
+ /* if the image was a R_IMF_VIEWS_STEREO_3D we force _L, _R suffices */
+ if (ima->views_format == R_IMF_VIEWS_STEREO_3D) {
+ const char *suffix[2] = {STEREO_LEFT_SUFFIX, STEREO_RIGHT_SUFFIX};
+ BLI_path_suffix(iv->filepath, FILE_MAX, suffix[view], "");
+ }
+ filepath = iv->filepath;
}
- ok = ok && image_memorypack_imbuf(ima, ibuf, iv->filepath);
+ ok = ok && image_memorypack_imbuf(ima, ibuf, view, tile->tile_number, filepath);
IMB_freeImBuf(ibuf);
}
-
- ima->views_format = R_IMF_VIEWS_INDIVIDUAL;
}
- else {
- ImBuf *ibuf = image_get_cached_ibuf_for_index_entry(ima, IMA_NO_INDEX, 0, nullptr);
- if (ibuf) {
- ok = ok && image_memorypack_imbuf(ima, ibuf, ibuf->name);
- IMB_freeImBuf(ibuf);
- }
- else {
- ok = false;
- }
+ if (is_multiview) {
+ ima->views_format = R_IMF_VIEWS_INDIVIDUAL;
}
if (ok && ima->source == IMA_SRC_GENERATED) {
@@ -1284,27 +1295,24 @@ void BKE_image_packfiles(ReportList *reports, Image *ima, const char *basepath)
{
const int tot_viewfiles = image_num_viewfiles(ima);
- if (tot_viewfiles == 1) {
- ImagePackedFile *imapf = static_cast<ImagePackedFile *>(
- MEM_mallocN(sizeof(ImagePackedFile), "Image packed file"));
- BLI_addtail(&ima->packedfiles, imapf);
- imapf->packedfile = BKE_packedfile_new(reports, ima->filepath, basepath);
- if (imapf->packedfile) {
- STRNCPY(imapf->filepath, ima->filepath);
- }
- else {
- BLI_freelinkN(&ima->packedfiles, imapf);
- }
- }
- else {
- for (ImageView *iv = static_cast<ImageView *>(ima->views.first); iv; iv = iv->next) {
+ ImageUser iuser{};
+ BKE_imageuser_default(&iuser);
+ for (int view = 0; view < tot_viewfiles; view++) {
+ iuser.view = view;
+ LISTBASE_FOREACH (ImageTile *, tile, &ima->tiles) {
+ iuser.tile = tile->tile_number;
+ char filepath[FILE_MAX];
+ BKE_image_user_file_path(&iuser, ima, filepath);
+
ImagePackedFile *imapf = static_cast<ImagePackedFile *>(
MEM_mallocN(sizeof(ImagePackedFile), "Image packed file"));
BLI_addtail(&ima->packedfiles, imapf);
- imapf->packedfile = BKE_packedfile_new(reports, iv->filepath, basepath);
+ imapf->packedfile = BKE_packedfile_new(reports, filepath, basepath);
+ imapf->view = view;
+ imapf->tile_number = tile->tile_number;
if (imapf->packedfile) {
- STRNCPY(imapf->filepath, iv->filepath);
+ STRNCPY(imapf->filepath, filepath);
}
else {
BLI_freelinkN(&ima->packedfiles, imapf);
@@ -1323,11 +1331,16 @@ void BKE_image_packfiles_from_mem(ReportList *reports,
if (tot_viewfiles != 1) {
BKE_report(reports, RPT_ERROR, "Cannot pack multiview images from raw data currently...");
}
+ else if (ima->source == IMA_SRC_TILED) {
+ BKE_report(reports, RPT_ERROR, "Cannot pack tiled images from raw data currently...");
+ }
else {
ImagePackedFile *imapf = static_cast<ImagePackedFile *>(
MEM_mallocN(sizeof(ImagePackedFile), __func__));
BLI_addtail(&ima->packedfiles, imapf);
imapf->packedfile = BKE_packedfile_new_from_memory(data, data_len);
+ imapf->view = 0;
+ imapf->tile_number = 1001;
STRNCPY(imapf->filepath, ima->filepath);
}
}
@@ -2950,8 +2963,9 @@ void BKE_image_signal(Main *bmain, Image *ima, ImageUser *iuser, int signal)
/* try to repack file */
if (BKE_image_has_packedfile(ima)) {
const int tot_viewfiles = image_num_viewfiles(ima);
+ const int tot_files = tot_viewfiles * BLI_listbase_count(&ima->tiles);
- if (tot_viewfiles != BLI_listbase_count_at_most(&ima->packedfiles, tot_viewfiles + 1)) {
+ if (tot_files != BLI_listbase_count_at_most(&ima->packedfiles, tot_files + 1)) {
/* in case there are new available files to be loaded */
image_free_packedfiles(ima);
BKE_image_packfiles(nullptr, ima, ID_BLEND_PATH(bmain, &ima->id));
@@ -3926,18 +3940,23 @@ static ImBuf *load_image_single(Image *ima,
int flag = IB_rect | IB_multilayer;
*r_cache_ibuf = true;
+ const int tile_number = image_get_tile_number_from_iuser(ima, iuser);
/* is there a PackedFile with this image ? */
if (has_packed && !is_sequence) {
- ImagePackedFile *imapf = static_cast<ImagePackedFile *>(
- BLI_findlink(&ima->packedfiles, view_id));
- if (imapf->packedfile) {
- flag |= imbuf_alpha_flags_for_image(ima);
- ibuf = IMB_ibImageFromMemory((unsigned char *)imapf->packedfile->data,
- imapf->packedfile->size,
- flag,
- ima->colorspace_settings.name,
- "<packed data>");
+ flag |= imbuf_alpha_flags_for_image(ima);
+
+ LISTBASE_FOREACH (ImagePackedFile *, imapf, &ima->packedfiles) {
+ if (imapf->view == view_id && imapf->tile_number == tile_number) {
+ if (imapf->packedfile) {
+ ibuf = IMB_ibImageFromMemory((unsigned char *)imapf->packedfile->data,
+ imapf->packedfile->size,
+ flag,
+ ima->colorspace_settings.name,
+ "<packed data>");
+ }
+ break;
+ }
}
}
else {
@@ -3996,6 +4015,8 @@ static ImBuf *load_image_single(Image *ima,
BLI_addtail(&ima->packedfiles, imapf);
STRNCPY(imapf->filepath, filepath);
+ imapf->view = view_id;
+ imapf->tile_number = tile_number;
imapf->packedfile = BKE_packedfile_new(
nullptr, filepath, ID_BLEND_PATH_FROM_GLOBAL(&ima->id));
}
diff --git a/source/blender/blenkernel/intern/packedFile.c b/source/blender/blenkernel/intern/packedFile.c
index e7ed100ed03..7c96c463339 100644
--- a/source/blender/blenkernel/intern/packedFile.c
+++ b/source/blender/blenkernel/intern/packedFile.c
@@ -237,14 +237,14 @@ void BKE_packedfile_pack_all(Main *bmain, ReportList *reports, bool verbose)
for (ima = bmain->images.first; ima; ima = ima->id.next) {
if (BKE_image_has_packedfile(ima) == false && !ID_IS_LINKED(ima)) {
- if (ima->source == IMA_SRC_FILE) {
+ if (ELEM(ima->source, IMA_SRC_FILE, IMA_SRC_TILED)) {
BKE_image_packfiles(reports, ima, ID_BLEND_PATH(bmain, &ima->id));
tot++;
}
- else if (BKE_image_has_multiple_ibufs(ima) && verbose) {
+ else if (ELEM(ima->source, IMA_SRC_MOVIE, IMA_SRC_SEQUENCE) && verbose) {
BKE_reportf(reports,
RPT_WARNING,
- "Image '%s' skipped, movies, image sequences and packed files not supported",
+ "Image '%s' skipped, packing movies or image sequences not supported",
ima->id.name + 2);
}
}
@@ -494,15 +494,22 @@ static void unpack_generate_paths(const char *name,
if (tempname[0] == '\0') {
/* NOTE: we generally do not have any real way to re-create extension out of data. */
- BLI_strncpy(tempname, id->name + 2, sizeof(tempname));
+ const size_t len = BLI_strncpy_rlen(tempname, id->name + 2, sizeof(tempname));
printf("%s\n", tempname);
- /* For images we can add the file extension based on the file magic. */
+ /* For images ensure that the temporary filename contains tile number information as well as
+ * a file extension based on the file magic. */
if (id_type == ID_IM) {
- ImagePackedFile *imapf = ((Image *)id)->packedfiles.last;
+ Image *ima = (Image *)id;
+ ImagePackedFile *imapf = ima->packedfiles.last;
if (imapf != NULL && imapf->packedfile != NULL) {
const PackedFile *pf = imapf->packedfile;
enum eImbFileType ftype = IMB_ispic_type_from_memory((const uchar *)pf->data, pf->size);
+ if (ima->source == IMA_SRC_TILED) {
+ char tile_number[6];
+ BLI_snprintf(tile_number, sizeof(tile_number), ".%d", imapf->tile_number);
+ BLI_strncpy(tempname + len, tile_number, sizeof(tempname) - len);
+ }
if (ftype != IMB_FTYPE_NONE) {
const int imtype = BKE_ftype_to_imtype(ftype, NULL);
BKE_image_path_ensure_ext_from_imtype(tempname, imtype);
@@ -639,6 +646,11 @@ int BKE_packedfile_unpack_image(Main *bmain,
/* keep the new name in the image for non-pack specific reasons */
if (how != PF_REMOVE) {
BLI_strncpy(ima->filepath, new_file_path, sizeof(imapf->filepath));
+ if (ima->source == IMA_SRC_TILED) {
+ /* Ensure that the Image filepath is kept in a tokenized format. */
+ char *filename = (char *)BLI_path_basename(ima->filepath);
+ BKE_image_ensure_tile_token(filename);
+ }
}
MEM_freeN(new_file_path);
}
diff --git a/source/blender/blenloader/intern/versioning_300.c b/source/blender/blenloader/intern/versioning_300.c
index 7fd72fec3d0..de47fe49946 100644
--- a/source/blender/blenloader/intern/versioning_300.c
+++ b/source/blender/blenloader/intern/versioning_300.c
@@ -3034,5 +3034,16 @@ void blo_do_versions_300(FileData *fd, Library *UNUSED(lib), Main *bmain)
brush->curves_sculpt_settings->points_per_curve = 8;
}
}
+
+ /* UDIM Packing. */
+ if (!DNA_struct_elem_find(fd->filesdna, "ImagePackedFile", "int", "tile_number")) {
+ for (Image *ima = bmain->images.first; ima; ima = ima->id.next) {
+ int view;
+ LISTBASE_FOREACH_INDEX (ImagePackedFile *, imapf, &ima->packedfiles, view) {
+ imapf->view = view;
+ imapf->tile_number = 1001;
+ }
+ }
+ }
}
}
diff --git a/source/blender/editors/space_image/image_ops.c b/source/blender/editors/space_image/image_ops.c
index aa77aab2283..0cfb924e618 100644
--- a/source/blender/editors/space_image/image_ops.c
+++ b/source/blender/editors/space_image/image_ops.c
@@ -2316,6 +2316,14 @@ static bool image_has_valid_path(Image *ima)
return strchr(ima->filepath, '\\') || strchr(ima->filepath, '/');
}
+static bool image_should_pack_during_save_all(const Image *ima)
+{
+ /* Images without a filepath (implied with IMA_SRC_GENERATED) should
+ * be packed during a save_all operation. */
+ return (ima->source == IMA_SRC_GENERATED) ||
+ (ima->source == IMA_SRC_TILED && !BKE_image_has_filepath(ima));
+}
+
bool ED_image_should_save_modified(const Main *bmain)
{
ReportList reports;
@@ -2339,7 +2347,7 @@ int ED_image_save_all_modified_info(const Main *bmain, ReportList *reports)
bool is_format_writable;
if (image_should_be_saved(ima, &is_format_writable)) {
- if (BKE_image_has_packedfile(ima) || (ima->source == IMA_SRC_GENERATED)) {
+ if (BKE_image_has_packedfile(ima) || image_should_pack_during_save_all(ima)) {
if (!ID_IS_LINKED(ima)) {
num_saveable_images++;
}
@@ -2396,7 +2404,7 @@ bool ED_image_save_all_modified(const bContext *C, ReportList *reports)
bool is_format_writable;
if (image_should_be_saved(ima, &is_format_writable)) {
- if (BKE_image_has_packedfile(ima) || (ima->source == IMA_SRC_GENERATED)) {
+ if (BKE_image_has_packedfile(ima) || image_should_pack_during_save_all(ima)) {
BKE_image_memorypack(ima);
}
else if (is_format_writable) {
@@ -3040,9 +3048,8 @@ static bool image_pack_test(bContext *C, wmOperator *op)
return false;
}
- if (ELEM(ima->source, IMA_SRC_SEQUENCE, IMA_SRC_MOVIE, IMA_SRC_TILED)) {
- BKE_report(
- op->reports, RPT_ERROR, "Packing movies, image sequences or tiled images not supported");
+ if (ELEM(ima->source, IMA_SRC_SEQUENCE, IMA_SRC_MOVIE)) {
+ BKE_report(op->reports, RPT_ERROR, "Packing movies or image sequences not supported");
return false;
}
@@ -3110,9 +3117,8 @@ static int image_unpack_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
}
- if (ELEM(ima->source, IMA_SRC_SEQUENCE, IMA_SRC_MOVIE, IMA_SRC_TILED)) {
- BKE_report(
- op->reports, RPT_ERROR, "Unpacking movies, image sequences or tiled images not supported");
+ if (ELEM(ima->source, IMA_SRC_SEQUENCE, IMA_SRC_MOVIE)) {
+ BKE_report(op->reports, RPT_ERROR, "Unpacking movies or image sequences not supported");
return OPERATOR_CANCELLED;
}
@@ -3144,9 +3150,8 @@ static int image_unpack_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSE
return OPERATOR_CANCELLED;
}
- if (ELEM(ima->source, IMA_SRC_SEQUENCE, IMA_SRC_MOVIE, IMA_SRC_TILED)) {
- BKE_report(
- op->reports, RPT_ERROR, "Unpacking movies, image sequences or tiled images not supported");
+ if (ELEM(ima->source, IMA_SRC_SEQUENCE, IMA_SRC_MOVIE)) {
+ BKE_report(op->reports, RPT_ERROR, "Unpacking movies or image sequences not supported");
return OPERATOR_CANCELLED;
}
diff --git a/source/blender/makesdna/DNA_image_types.h b/source/blender/makesdna/DNA_image_types.h
index 4e66e2446f0..80f592bb66d 100644
--- a/source/blender/makesdna/DNA_image_types.h
+++ b/source/blender/makesdna/DNA_image_types.h
@@ -64,6 +64,11 @@ typedef struct ImageView {
typedef struct ImagePackedFile {
struct ImagePackedFile *next, *prev;
struct PackedFile *packedfile;
+
+ /* Which view and tile this ImagePackedFile represents. Normal images will use 0 and 1001
+ * respectively when creating their ImagePackedFile. Must be provided for each packed image. */
+ int view;
+ int tile_number;
/** 1024 = FILE_MAX. */
char filepath[1024];
} ImagePackedFile;
diff --git a/source/blender/makesrna/intern/rna_image.c b/source/blender/makesrna/intern/rna_image.c
index bd3b03add95..81708ac8e65 100644
--- a/source/blender/makesrna/intern/rna_image.c
+++ b/source/blender/makesrna/intern/rna_image.c
@@ -737,6 +737,16 @@ static void rna_def_image_packed_files(BlenderRNA *brna)
RNA_def_property_string_sdna(prop, NULL, "filepath");
RNA_def_struct_name_property(srna, prop);
+ prop = RNA_def_property(srna, "view", PROP_INT, PROP_NONE);
+ RNA_def_property_int_sdna(prop, NULL, "view");
+ RNA_def_property_ui_text(prop, "View Index", "");
+ RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+
+ prop = RNA_def_property(srna, "tile_number", PROP_INT, PROP_NONE);
+ RNA_def_property_int_sdna(prop, NULL, "tile_number");
+ RNA_def_property_ui_text(prop, "Tile Number", "");
+ RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+
RNA_api_image_packed_file(srna);
}
diff --git a/source/blender/makesrna/intern/rna_image_api.c b/source/blender/makesrna/intern/rna_image_api.c
index 897573f9fd9..7bd2040dab0 100644
--- a/source/blender/makesrna/intern/rna_image_api.c
+++ b/source/blender/makesrna/intern/rna_image_api.c
@@ -161,9 +161,8 @@ static void rna_Image_unpack(Image *image, Main *bmain, ReportList *reports, int
if (!BKE_image_has_packedfile(image)) {
BKE_report(reports, RPT_ERROR, "Image not packed");
}
- else if (BKE_image_has_multiple_ibufs(image)) {
- BKE_report(
- reports, RPT_ERROR, "Unpacking movies, image sequences or tiled images not supported");
+ else if (ELEM(image->source, IMA_SRC_MOVIE, IMA_SRC_SEQUENCE)) {
+ BKE_report(reports, RPT_ERROR, "Unpacking movies or image sequences not supported");
return;
}
else {