Refactor: add a function to access images extensions from it's format

Previously accessing the extension needed to ensure an extension
on an empty path.

This conflicted with DEBUG_STRSIZE as it was assumed the input was
FILE_MAX, where as it was a small buffer with RNA, see: !107602.

Resolve by separating the function that ensures the extension
with the function that finds valid extensions for a format.

Also pass the size of the filepath to functions that ensure the
extension.
This commit is contained in:
Campbell Barton 2023-05-05 12:40:27 +10:00
parent f15889a9f9
commit 6796cce11d
9 changed files with 99 additions and 87 deletions

View File

@ -45,9 +45,27 @@ void BKE_image_path_from_imtype(char *filepath,
bool use_ext, bool use_ext,
bool use_frames, bool use_frames,
const char *suffix); const char *suffix);
int BKE_image_path_ensure_ext_from_imformat(char *filepath,
/**
* The number of extensions an image may have (`.jpg`, `.jpeg` for example).
* Add 1 as the array is nil terminated.
*/
#define BKE_IMAGE_PATH_EXT_MAX 3
/**
* Fill in an array of acceptable image extensions for the image format.
*
* \note In the case a file has no valid extension,
* the first extension should be used (`r_ext[0]`).
* \return the number of extensions assigned to `r_ext`, 0 for unsupported formats.
*/
int BKE_image_path_ext_from_imformat(const struct ImageFormatData *im_format,
const char *r_ext[BKE_IMAGE_PATH_EXT_MAX]);
int BKE_image_path_ext_from_imtype(const char imtype, const char *r_ext[BKE_IMAGE_PATH_EXT_MAX]);
int BKE_image_path_ext_from_imformat_ensure(char *filepath,
size_t filepath_maxncpy,
const struct ImageFormatData *im_format); const struct ImageFormatData *im_format);
int BKE_image_path_ensure_ext_from_imtype(char *filepath, char imtype); int BKE_image_path_ext_from_imtype_ensure(char *filepath, size_t filepath_maxncpy, char imtype);
/* File Types */ /* File Types */

View File

@ -3315,7 +3315,7 @@ void dynamicPaint_outputSurfaceImage(DynamicPaintSurface *surface,
} }
#endif #endif
BLI_strncpy(output_file, filepath, sizeof(output_file)); BLI_strncpy(output_file, filepath, sizeof(output_file));
BKE_image_path_ensure_ext_from_imtype(output_file, format); BKE_image_path_ext_from_imtype_ensure(output_file, sizeof(output_file), format);
/* Validate output file path */ /* Validate output file path */
BLI_path_abs(output_file, BKE_main_blendfile_path_from_global()); BLI_path_abs(output_file, BKE_main_blendfile_path_from_global());

View File

@ -386,28 +386,21 @@ char BKE_imtype_from_arg(const char *imtype_arg)
/* File Paths */ /* File Paths */
static bool do_add_image_extension(char *filepath, static int image_path_ext_from_imformat_impl(const char imtype,
const char imtype, const ImageFormatData *im_format,
const ImageFormatData *im_format) const char *r_ext[BKE_IMAGE_PATH_EXT_MAX])
{ {
const char *extension = nullptr; int ext_num = 0;
const char *extension_test;
(void)im_format; /* may be unused, depends on build options */ (void)im_format; /* may be unused, depends on build options */
if (imtype == R_IMF_IMTYPE_IRIS) { if (imtype == R_IMF_IMTYPE_IRIS) {
if (!BLI_path_extension_check(filepath, extension_test = ".rgb")) { r_ext[ext_num++] = ".rgb";
extension = extension_test;
}
} }
else if (imtype == R_IMF_IMTYPE_IRIZ) { else if (imtype == R_IMF_IMTYPE_IRIZ) {
if (!BLI_path_extension_check(filepath, extension_test = ".rgb")) { r_ext[ext_num++] = ".rgb";
extension = extension_test;
}
} }
else if (imtype == R_IMF_IMTYPE_RADHDR) { else if (imtype == R_IMF_IMTYPE_RADHDR) {
if (!BLI_path_extension_check(filepath, extension_test = ".hdr")) { r_ext[ext_num++] = ".hdr";
extension = extension_test;
}
} }
else if (ELEM(imtype, else if (ELEM(imtype,
R_IMF_IMTYPE_PNG, R_IMF_IMTYPE_PNG,
@ -417,112 +410,113 @@ static bool do_add_image_extension(char *filepath,
R_IMF_IMTYPE_XVID, R_IMF_IMTYPE_XVID,
R_IMF_IMTYPE_AV1)) R_IMF_IMTYPE_AV1))
{ {
if (!BLI_path_extension_check(filepath, extension_test = ".png")) { r_ext[ext_num++] = ".png";
extension = extension_test;
}
} }
else if (imtype == R_IMF_IMTYPE_DDS) { else if (imtype == R_IMF_IMTYPE_DDS) {
if (!BLI_path_extension_check(filepath, extension_test = ".dds")) { r_ext[ext_num++] = ".dds";
extension = extension_test;
}
} }
else if (ELEM(imtype, R_IMF_IMTYPE_TARGA, R_IMF_IMTYPE_RAWTGA)) { else if (ELEM(imtype, R_IMF_IMTYPE_TARGA, R_IMF_IMTYPE_RAWTGA)) {
if (!BLI_path_extension_check(filepath, extension_test = ".tga")) { r_ext[ext_num++] = ".tga";
extension = extension_test;
}
} }
else if (imtype == R_IMF_IMTYPE_BMP) { else if (imtype == R_IMF_IMTYPE_BMP) {
if (!BLI_path_extension_check(filepath, extension_test = ".bmp")) { r_ext[ext_num++] = ".bmp";
extension = extension_test;
}
} }
else if (imtype == R_IMF_IMTYPE_TIFF) { else if (imtype == R_IMF_IMTYPE_TIFF) {
if (!BLI_path_extension_check_n(filepath, extension_test = ".tif", ".tiff", nullptr)) { r_ext[ext_num++] = ".tif";
extension = extension_test; r_ext[ext_num++] = ".tiff";
}
} }
else if (imtype == R_IMF_IMTYPE_PSD) { else if (imtype == R_IMF_IMTYPE_PSD) {
if (!BLI_path_extension_check(filepath, extension_test = ".psd")) { r_ext[ext_num++] = ".psd";
extension = extension_test;
}
} }
#ifdef WITH_OPENEXR #ifdef WITH_OPENEXR
else if (ELEM(imtype, R_IMF_IMTYPE_OPENEXR, R_IMF_IMTYPE_MULTILAYER)) { else if (ELEM(imtype, R_IMF_IMTYPE_OPENEXR, R_IMF_IMTYPE_MULTILAYER)) {
if (!BLI_path_extension_check(filepath, extension_test = ".exr")) { r_ext[ext_num++] = ".exr";
extension = extension_test;
}
} }
#endif #endif
#ifdef WITH_CINEON #ifdef WITH_CINEON
else if (imtype == R_IMF_IMTYPE_CINEON) { else if (imtype == R_IMF_IMTYPE_CINEON) {
if (!BLI_path_extension_check(filepath, extension_test = ".cin")) { r_ext[ext_num++] = ".cin";
extension = extension_test;
}
} }
else if (imtype == R_IMF_IMTYPE_DPX) { else if (imtype == R_IMF_IMTYPE_DPX) {
if (!BLI_path_extension_check(filepath, extension_test = ".dpx")) { r_ext[ext_num++] = ".dpx";
extension = extension_test;
}
} }
#endif #endif
#ifdef WITH_OPENJPEG #ifdef WITH_OPENJPEG
else if (imtype == R_IMF_IMTYPE_JP2) { else if (imtype == R_IMF_IMTYPE_JP2) {
if (im_format) { if (im_format) {
if (im_format->jp2_codec == R_IMF_JP2_CODEC_JP2) { if (im_format->jp2_codec == R_IMF_JP2_CODEC_JP2) {
if (!BLI_path_extension_check(filepath, extension_test = ".jp2")) { r_ext[ext_num++] = ".jp2";
extension = extension_test;
}
} }
else if (im_format->jp2_codec == R_IMF_JP2_CODEC_J2K) { else if (im_format->jp2_codec == R_IMF_JP2_CODEC_J2K) {
if (!BLI_path_extension_check(filepath, extension_test = ".j2c")) { r_ext[ext_num++] = ".j2c";
extension = extension_test;
}
} }
else { else {
BLI_assert_msg(0, "Unsupported jp2 codec was specified in im_format->jp2_codec"); BLI_assert_msg(0, "Unsupported jp2 codec was specified in im_format->jp2_codec");
} }
} }
else { else {
if (!BLI_path_extension_check(filepath, extension_test = ".jp2")) { r_ext[ext_num++] = ".jp2";
extension = extension_test;
}
} }
} }
#endif #endif
#ifdef WITH_WEBP #ifdef WITH_WEBP
else if (imtype == R_IMF_IMTYPE_WEBP) { else if (imtype == R_IMF_IMTYPE_WEBP) {
if (!BLI_path_extension_check(filepath, extension_test = ".webp")) { r_ext[ext_num++] = ".webp";
extension = extension_test;
}
} }
#endif #endif
else { // R_IMF_IMTYPE_AVIRAW, R_IMF_IMTYPE_AVIJPEG, R_IMF_IMTYPE_JPEG90 etc else {
if (!BLI_path_extension_check_n(filepath, extension_test = ".jpg", ".jpeg", nullptr)) { /* Handles: #R_IMF_IMTYPE_AVIRAW, #R_IMF_IMTYPE_AVIJPEG, #R_IMF_IMTYPE_JPEG90 etc. */
extension = extension_test; r_ext[ext_num++] = ".jpg";
} r_ext[ext_num++] = ".jpeg";
} }
BLI_assert(ext_num < BKE_IMAGE_PATH_EXT_MAX);
r_ext[ext_num] = nullptr;
return ext_num;
}
if (extension) { int BKE_image_path_ext_from_imformat(const ImageFormatData *im_format,
/* prefer this in many cases to avoid .png.tga, but in certain cases it breaks */ const char *r_ext[BKE_IMAGE_PATH_EXT_MAX])
/* remove any other known image extension */ {
return image_path_ext_from_imformat_impl(im_format->imtype, im_format, r_ext);
}
int BKE_image_path_ext_from_imtype(const char imtype, const char *r_ext[BKE_IMAGE_PATH_EXT_MAX])
{
return image_path_ext_from_imformat_impl(imtype, nullptr, r_ext);
}
static bool do_ensure_image_extension(char *filepath,
const size_t filepath_maxncpy,
const char imtype,
const ImageFormatData *im_format)
{
const char *ext_array[BKE_IMAGE_PATH_EXT_MAX];
int ext_array_num = image_path_ext_from_imformat_impl(imtype, im_format, ext_array);
if (ext_array_num && !BLI_path_extension_check_array(filepath, ext_array)) {
/* Removing *any* extension may remove part of the user defined name (if they include '.')
* however in the case there is already a known image extension,
* remove it to avoid`.png.tga`, for example. */
if (BLI_path_extension_check_array(filepath, imb_ext_image)) { if (BLI_path_extension_check_array(filepath, imb_ext_image)) {
return BLI_path_extension_replace(filepath, FILE_MAX, extension); return BLI_path_extension_replace(filepath, filepath_maxncpy, ext_array[0]);
} }
return BLI_path_extension_ensure(filepath, filepath_maxncpy, ext_array[0]);
return BLI_path_extension_ensure(filepath, FILE_MAX, extension);
} }
return false; return false;
} }
int BKE_image_path_ensure_ext_from_imformat(char *filepath, const ImageFormatData *im_format) int BKE_image_path_ext_from_imformat_ensure(char *filepath,
const size_t filepath_maxncpy,
const ImageFormatData *im_format)
{ {
return do_add_image_extension(filepath, im_format->imtype, im_format); return do_ensure_image_extension(filepath, filepath_maxncpy, im_format->imtype, im_format);
} }
int BKE_image_path_ensure_ext_from_imtype(char *filepath, const char imtype) int BKE_image_path_ext_from_imtype_ensure(char *filepath,
const size_t filepath_maxncpy,
const char imtype)
{ {
return do_add_image_extension(filepath, imtype, nullptr); return do_ensure_image_extension(filepath, filepath_maxncpy, imtype, nullptr);
} }
static void do_makepicstring(char filepath[FILE_MAX], static void do_makepicstring(char filepath[FILE_MAX],
@ -550,7 +544,7 @@ static void do_makepicstring(char filepath[FILE_MAX],
} }
if (use_ext) { if (use_ext) {
do_add_image_extension(filepath, imtype, im_format); do_ensure_image_extension(filepath, FILE_MAX, imtype, im_format);
} }
} }

View File

@ -978,7 +978,7 @@ bool BKE_image_render_write(ReportList *reports,
if (BLI_path_extension_check(filepath, ".exr")) { if (BLI_path_extension_check(filepath, ".exr")) {
filepath[strlen(filepath) - 4] = 0; filepath[strlen(filepath) - 4] = 0;
} }
BKE_image_path_ensure_ext_from_imformat(filepath, &image_format); BKE_image_path_ext_from_imformat_ensure(filepath, sizeof(filepath), &image_format);
ImBuf *ibuf = RE_render_result_rect_to_ibuf(rr, &image_format, dither, view_id); ImBuf *ibuf = RE_render_result_rect_to_ibuf(rr, &image_format, dither, view_id);
ibuf->planes = 24; ibuf->planes = 24;
@ -1037,7 +1037,7 @@ bool BKE_image_render_write(ReportList *reports,
filepath[strlen(filepath) - 4] = 0; filepath[strlen(filepath) - 4] = 0;
} }
BKE_image_path_ensure_ext_from_imformat(filepath, &image_format); BKE_image_path_ext_from_imformat_ensure(filepath, sizeof(filepath), &image_format);
ibuf_arr[2]->planes = 24; ibuf_arr[2]->planes = 24;
ok = image_render_write_stamp_test( ok = image_render_write_stamp_test(

View File

@ -512,7 +512,7 @@ static void unpack_generate_paths(const char *filepath,
} }
if (ftype != IMB_FTYPE_NONE) { if (ftype != IMB_FTYPE_NONE) {
const int imtype = BKE_ftype_to_imtype(ftype, NULL); const int imtype = BKE_ftype_to_imtype(ftype, NULL);
BKE_image_path_ensure_ext_from_imtype(temp_filename, imtype); BKE_image_path_ext_from_imtype_ensure(temp_filename, sizeof(temp_filename), imtype);
} }
} }
} }

View File

@ -68,7 +68,7 @@ void ImagesExporter::export_UV_Image(Image *image, bool use_copies)
/* make absolute destination path */ /* make absolute destination path */
BLI_strncpy(export_file, name.c_str(), sizeof(export_file)); BLI_strncpy(export_file, name.c_str(), sizeof(export_file));
BKE_image_path_ensure_ext_from_imformat(export_file, &imageFormat); BKE_image_path_ext_from_imformat_ensure(export_file, sizeof(export_file), &imageFormat);
BLI_path_join(export_path, sizeof(export_path), export_dir, export_file); BLI_path_join(export_path, sizeof(export_path), export_dir, export_file);

View File

@ -408,7 +408,7 @@ static std::string get_in_memory_texture_filename(Image *ima)
/* Use the image name for the file name. */ /* Use the image name for the file name. */
strcpy(file_name, ima->id.name + 2); strcpy(file_name, ima->id.name + 2);
BKE_image_path_ensure_ext_from_imformat(file_name, &imageFormat); BKE_image_path_ext_from_imformat_ensure(file_name, &imageFormat);
return file_name; return file_name;
} }
@ -442,7 +442,7 @@ static void export_in_memory_texture(Image *ima,
* So we have to export it. The export will keep the image state intact, * So we have to export it. The export will keep the image state intact,
* so the exported file will not be associated with the image. */ * so the exported file will not be associated with the image. */
BKE_image_path_ensure_ext_from_imformat(file_name, &imageFormat); BKE_image_path_ext_from_imformat_ensure(file_name, &imageFormat);
char export_path[FILE_MAX]; char export_path[FILE_MAX];
BLI_path_join(export_path, FILE_MAX, export_dir.c_str(), file_name); BLI_path_join(export_path, FILE_MAX, export_dir.c_str(), file_name);

View File

@ -1513,18 +1513,18 @@ static void rna_ImageFormatSettings_color_management_set(PointerRNA *ptr, int va
static int rna_SceneRender_file_ext_length(PointerRNA *ptr) static int rna_SceneRender_file_ext_length(PointerRNA *ptr)
{ {
RenderData *rd = (RenderData *)ptr->data; const RenderData *rd = (RenderData *)ptr->data;
char ext[8]; const char *ext_array[BKE_IMAGE_PATH_EXT_MAX];
ext[0] = '\0'; int ext_num = BKE_image_path_ext_from_imformat(&rd->im_format, ext_array);
BKE_image_path_ensure_ext_from_imformat(ext, &rd->im_format); return ext_num ? strlen(ext_array[0]) : 0;
return strlen(ext);
} }
static void rna_SceneRender_file_ext_get(PointerRNA *ptr, char *str) static void rna_SceneRender_file_ext_get(PointerRNA *ptr, char *value)
{ {
RenderData *rd = (RenderData *)ptr->data; const RenderData *rd = (RenderData *)ptr->data;
str[0] = '\0'; const char *ext_array[BKE_IMAGE_PATH_EXT_MAX];
BKE_image_path_ensure_ext_from_imformat(str, &rd->im_format); int ext_num = BKE_image_path_ext_from_imformat(&rd->im_format, ext_array);
strcpy(value, ext_num ? ext_array[0] : "");
} }
# ifdef WITH_FFMPEG # ifdef WITH_FFMPEG

View File

@ -1228,7 +1228,7 @@ bool WM_operator_filesel_ensure_ext_imtype(wmOperator *op, const struct ImageFor
/* Don't NULL check prop, this can only run on ops with a 'filepath'. */ /* Don't NULL check prop, this can only run on ops with a 'filepath'. */
PropertyRNA *prop = RNA_struct_find_property(op->ptr, "filepath"); PropertyRNA *prop = RNA_struct_find_property(op->ptr, "filepath");
RNA_property_string_get(op->ptr, prop, filepath); RNA_property_string_get(op->ptr, prop, filepath);
if (BKE_image_path_ensure_ext_from_imformat(filepath, im_format)) { if (BKE_image_path_ext_from_imformat_ensure(filepath, sizeof(filepath), im_format)) {
RNA_property_string_set(op->ptr, prop, filepath); RNA_property_string_set(op->ptr, prop, filepath);
/* NOTE: we could check for and update 'filename' here, /* NOTE: we could check for and update 'filename' here,
* but so far nothing needs this. */ * but so far nothing needs this. */