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_frames,
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);
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 */

View File

@ -3315,7 +3315,7 @@ void dynamicPaint_outputSurfaceImage(DynamicPaintSurface *surface,
}
#endif
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 */
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 */
static bool do_add_image_extension(char *filepath,
const char imtype,
const ImageFormatData *im_format)
static int image_path_ext_from_imformat_impl(const char imtype,
const ImageFormatData *im_format,
const char *r_ext[BKE_IMAGE_PATH_EXT_MAX])
{
const char *extension = nullptr;
const char *extension_test;
int ext_num = 0;
(void)im_format; /* may be unused, depends on build options */
if (imtype == R_IMF_IMTYPE_IRIS) {
if (!BLI_path_extension_check(filepath, extension_test = ".rgb")) {
extension = extension_test;
}
r_ext[ext_num++] = ".rgb";
}
else if (imtype == R_IMF_IMTYPE_IRIZ) {
if (!BLI_path_extension_check(filepath, extension_test = ".rgb")) {
extension = extension_test;
}
r_ext[ext_num++] = ".rgb";
}
else if (imtype == R_IMF_IMTYPE_RADHDR) {
if (!BLI_path_extension_check(filepath, extension_test = ".hdr")) {
extension = extension_test;
}
r_ext[ext_num++] = ".hdr";
}
else if (ELEM(imtype,
R_IMF_IMTYPE_PNG,
@ -417,112 +410,113 @@ static bool do_add_image_extension(char *filepath,
R_IMF_IMTYPE_XVID,
R_IMF_IMTYPE_AV1))
{
if (!BLI_path_extension_check(filepath, extension_test = ".png")) {
extension = extension_test;
}
r_ext[ext_num++] = ".png";
}
else if (imtype == R_IMF_IMTYPE_DDS) {
if (!BLI_path_extension_check(filepath, extension_test = ".dds")) {
extension = extension_test;
}
r_ext[ext_num++] = ".dds";
}
else if (ELEM(imtype, R_IMF_IMTYPE_TARGA, R_IMF_IMTYPE_RAWTGA)) {
if (!BLI_path_extension_check(filepath, extension_test = ".tga")) {
extension = extension_test;
}
r_ext[ext_num++] = ".tga";
}
else if (imtype == R_IMF_IMTYPE_BMP) {
if (!BLI_path_extension_check(filepath, extension_test = ".bmp")) {
extension = extension_test;
}
r_ext[ext_num++] = ".bmp";
}
else if (imtype == R_IMF_IMTYPE_TIFF) {
if (!BLI_path_extension_check_n(filepath, extension_test = ".tif", ".tiff", nullptr)) {
extension = extension_test;
}
r_ext[ext_num++] = ".tif";
r_ext[ext_num++] = ".tiff";
}
else if (imtype == R_IMF_IMTYPE_PSD) {
if (!BLI_path_extension_check(filepath, extension_test = ".psd")) {
extension = extension_test;
}
r_ext[ext_num++] = ".psd";
}
#ifdef WITH_OPENEXR
else if (ELEM(imtype, R_IMF_IMTYPE_OPENEXR, R_IMF_IMTYPE_MULTILAYER)) {
if (!BLI_path_extension_check(filepath, extension_test = ".exr")) {
extension = extension_test;
}
r_ext[ext_num++] = ".exr";
}
#endif
#ifdef WITH_CINEON
else if (imtype == R_IMF_IMTYPE_CINEON) {
if (!BLI_path_extension_check(filepath, extension_test = ".cin")) {
extension = extension_test;
}
r_ext[ext_num++] = ".cin";
}
else if (imtype == R_IMF_IMTYPE_DPX) {
if (!BLI_path_extension_check(filepath, extension_test = ".dpx")) {
extension = extension_test;
}
r_ext[ext_num++] = ".dpx";
}
#endif
#ifdef WITH_OPENJPEG
else if (imtype == R_IMF_IMTYPE_JP2) {
if (im_format) {
if (im_format->jp2_codec == R_IMF_JP2_CODEC_JP2) {
if (!BLI_path_extension_check(filepath, extension_test = ".jp2")) {
extension = extension_test;
}
r_ext[ext_num++] = ".jp2";
}
else if (im_format->jp2_codec == R_IMF_JP2_CODEC_J2K) {
if (!BLI_path_extension_check(filepath, extension_test = ".j2c")) {
extension = extension_test;
}
r_ext[ext_num++] = ".j2c";
}
else {
BLI_assert_msg(0, "Unsupported jp2 codec was specified in im_format->jp2_codec");
}
}
else {
if (!BLI_path_extension_check(filepath, extension_test = ".jp2")) {
extension = extension_test;
}
r_ext[ext_num++] = ".jp2";
}
}
#endif
#ifdef WITH_WEBP
else if (imtype == R_IMF_IMTYPE_WEBP) {
if (!BLI_path_extension_check(filepath, extension_test = ".webp")) {
extension = extension_test;
}
r_ext[ext_num++] = ".webp";
}
#endif
else { // R_IMF_IMTYPE_AVIRAW, R_IMF_IMTYPE_AVIJPEG, R_IMF_IMTYPE_JPEG90 etc
if (!BLI_path_extension_check_n(filepath, extension_test = ".jpg", ".jpeg", nullptr)) {
extension = extension_test;
}
else {
/* Handles: #R_IMF_IMTYPE_AVIRAW, #R_IMF_IMTYPE_AVIJPEG, #R_IMF_IMTYPE_JPEG90 etc. */
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) {
/* prefer this in many cases to avoid .png.tga, but in certain cases it breaks */
/* remove any other known image extension */
int BKE_image_path_ext_from_imformat(const ImageFormatData *im_format,
const char *r_ext[BKE_IMAGE_PATH_EXT_MAX])
{
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)) {
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, FILE_MAX, extension);
return BLI_path_extension_ensure(filepath, filepath_maxncpy, ext_array[0]);
}
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],
@ -550,7 +544,7 @@ static void do_makepicstring(char filepath[FILE_MAX],
}
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")) {
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);
ibuf->planes = 24;
@ -1037,7 +1037,7 @@ bool BKE_image_render_write(ReportList *reports,
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;
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) {
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 */
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);

View File

@ -408,7 +408,7 @@ static std::string get_in_memory_texture_filename(Image *ima)
/* Use the image name for the file name. */
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;
}
@ -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 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];
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)
{
RenderData *rd = (RenderData *)ptr->data;
char ext[8];
ext[0] = '\0';
BKE_image_path_ensure_ext_from_imformat(ext, &rd->im_format);
return strlen(ext);
const RenderData *rd = (RenderData *)ptr->data;
const char *ext_array[BKE_IMAGE_PATH_EXT_MAX];
int ext_num = BKE_image_path_ext_from_imformat(&rd->im_format, ext_array);
return ext_num ? strlen(ext_array[0]) : 0;
}
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;
str[0] = '\0';
BKE_image_path_ensure_ext_from_imformat(str, &rd->im_format);
const RenderData *rd = (RenderData *)ptr->data;
const char *ext_array[BKE_IMAGE_PATH_EXT_MAX];
int ext_num = BKE_image_path_ext_from_imformat(&rd->im_format, ext_array);
strcpy(value, ext_num ? ext_array[0] : "");
}
# 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'. */
PropertyRNA *prop = RNA_struct_find_property(op->ptr, "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);
/* NOTE: we could check for and update 'filename' here,
* but so far nothing needs this. */