Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions data/darktableconfig.xml.in
Original file line number Diff line number Diff line change
Expand Up @@ -2907,6 +2907,13 @@
<shortdescription/>
<longdescription/>
</dtconfig>
<dtconfig>
<name>plugins/imageio/format/avif/subsample</name>
<type min="0" max="3">int</type>
<default>0</default>
<shortdescription>AVIF chroma subsampling</shortdescription>
<longdescription/>
</dtconfig>
<dtconfig>
<name>plugins/imageio/format/xcf/bpp</name>
<type>
Expand Down
100 changes: 86 additions & 14 deletions src/imageio/format/avif.c
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,14 @@ enum avif_tiling_e
AVIF_TILING_OFF
};

enum avif_subsample_e
{
AVIF_SUBSAMPLE_AUTO = 0,
AVIF_SUBSAMPLE_444,
AVIF_SUBSAMPLE_422,
AVIF_SUBSAMPLE_420
};

enum avif_color_mode_e
{
AVIF_COLOR_MODE_RGB = 0,
Expand All @@ -65,6 +73,7 @@ typedef struct dt_imageio_avif_t
uint32_t compression_type;
uint32_t quality;
uint32_t tiling;
uint32_t subsample;
} dt_imageio_avif_t;

typedef struct dt_imageio_avif_gui_t
Expand All @@ -74,6 +83,7 @@ typedef struct dt_imageio_avif_gui_t
GtkWidget *compression_type;
GtkWidget *quality;
GtkWidget *tiling;
GtkWidget *subsample;
} dt_imageio_avif_gui_t;

static const struct
Expand Down Expand Up @@ -207,6 +217,28 @@ void init(dt_imageio_module_format_t *self)
dt_imageio_avif_t,
quality,
int);

/* subsample */
luaA_enum(darktable.lua_state.state,
enum avif_subsample_e);
luaA_enum_value(darktable.lua_state.state,
enum avif_subsample_e,
AVIF_SUBSAMPLE_AUTO);
luaA_enum_value(darktable.lua_state.state,
enum avif_subsample_e,
AVIF_SUBSAMPLE_444);
luaA_enum_value(darktable.lua_state.state,
enum avif_subsample_e,
AVIF_SUBSAMPLE_422);
luaA_enum_value(darktable.lua_state.state,
enum avif_subsample_e,
AVIF_SUBSAMPLE_420);

dt_lua_register_module_member(darktable.lua_state.state,
self,
dt_imageio_avif_t,
subsample,
enum avif_subsample_e);
#endif
}

Expand Down Expand Up @@ -250,17 +282,33 @@ int write_image(struct dt_imageio_module_data_t *data,
format = AVIF_PIXEL_FORMAT_YUV444;
break;
case AVIF_COMP_LOSSY:
if(d->quality > 90)
// Determine pixel format based on subsample setting
switch(d->subsample)
{
case AVIF_SUBSAMPLE_AUTO:
// Auto mode: use quality thresholds
if(d->quality > 90)
{
format = AVIF_PIXEL_FORMAT_YUV444;
}
else if(d->quality > 80)
{
format = AVIF_PIXEL_FORMAT_YUV422;
}
else
{
format = AVIF_PIXEL_FORMAT_YUV420;
}
break;
case AVIF_SUBSAMPLE_444:
format = AVIF_PIXEL_FORMAT_YUV444;
}
else if(d->quality > 80)
{
break;
case AVIF_SUBSAMPLE_422:
format = AVIF_PIXEL_FORMAT_YUV422;
}
else
{
format = AVIF_PIXEL_FORMAT_YUV420;
break;
case AVIF_SUBSAMPLE_420:
format = AVIF_PIXEL_FORMAT_YUV420;
break;
}
break;
}
Expand Down Expand Up @@ -703,6 +751,7 @@ void *get_params(dt_imageio_module_format_t *self)
}

d->tiling = !dt_conf_get_bool("plugins/imageio/format/avif/tiling");
d->subsample = dt_conf_get_int("plugins/imageio/format/avif/subsample");

return d;
}
Expand All @@ -721,6 +770,7 @@ int set_params(dt_imageio_module_format_t *self,
dt_bauhaus_combobox_set(g->tiling, d->tiling);
dt_bauhaus_combobox_set(g->compression_type, d->compression_type);
dt_bauhaus_slider_set(g->quality, d->quality);
dt_bauhaus_combobox_set(g->subsample, d->subsample);

return 0;
}
Expand Down Expand Up @@ -818,6 +868,12 @@ static void quality_changed(GtkWidget *slider, gpointer user_data)
dt_conf_set_int("plugins/imageio/format/avif/quality", quality);
}

static void subsample_changed(GtkWidget *widget, gpointer user_data)
{
const enum avif_subsample_e subsample = dt_bauhaus_combobox_get(widget);
dt_conf_set_int("plugins/imageio/format/avif/subsample", subsample);
}

void gui_init(dt_imageio_module_format_t *self)
{
dt_imageio_avif_gui_t *gui = malloc(sizeof(dt_imageio_avif_gui_t));
Expand Down Expand Up @@ -904,17 +960,31 @@ void gui_init(dt_imageio_module_format_t *self)
dt_bauhaus_widget_set_label(gui->quality, NULL, N_("quality"));

gtk_widget_set_tooltip_text(gui->quality,
_("the quality of an image, less quality means fewer details.\n"
"\n"
"pixel format is controlled by quality:\n"
"\n"
"5-80: YUV420, 81-90: YUV422, 91-100: YUV444"));
_("the quality of an image, less quality means fewer details"));

dt_bauhaus_slider_set(gui->quality, quality);

gtk_widget_set_visible(gui->quality, compression_type != AVIF_COMP_LOSSLESS);
gtk_widget_set_no_show_all(gui->quality, TRUE);

/*
* Chroma subsampling combo box
*/
const enum avif_subsample_e subsample = dt_conf_get_int("plugins/imageio/format/avif/subsample");

DT_BAUHAUS_COMBOBOX_NEW_FULL(gui->subsample, self, NULL, N_("chroma subsampling"),
_("chroma subsampling setting for AVIF encoder.\n"
"auto - use subsampling determined by the quality value\n"
" (5-80: YUV420, 81-90: YUV422, 91-100: YUV444)\n"
"4:4:4 - no chroma subsampling\n"
"4:2:2 - color sampling rate halved horizontally\n"
"4:2:0 - color sampling rate halved horizontally and vertically"),
subsample, subsample_changed, self,
N_("auto"), N_("4:4:4"), N_("4:2:2"), N_("4:2:0"));

dt_bauhaus_combobox_set_default(gui->subsample,
dt_confgen_get_int("plugins/imageio/format/avif/subsample", DT_DEFAULT));

g_signal_connect(G_OBJECT(gui->bit_depth),
"value-changed",
G_CALLBACK(bit_depth_changed),
Expand All @@ -929,7 +999,7 @@ void gui_init(dt_imageio_module_format_t *self)
NULL);

self->widget = dt_gui_vbox(gui->bit_depth, gui->color_mode, gui->tiling,
gui->compression_type, gui->quality);
gui->compression_type, gui->quality, gui->subsample);
}

void gui_cleanup(dt_imageio_module_format_t *self)
Expand All @@ -946,6 +1016,7 @@ void gui_reset(dt_imageio_module_format_t *self)
const enum avif_tiling_e tiling = !dt_confgen_get_bool("plugins/imageio/format/avif/tiling", DT_DEFAULT);
const enum avif_compression_type_e compression_type = dt_confgen_get_int("plugins/imageio/format/avif/compression_type", DT_DEFAULT);
const uint32_t quality = dt_confgen_get_int("plugins/imageio/format/avif/quality", DT_DEFAULT);
const enum avif_subsample_e subsample = dt_confgen_get_int("plugins/imageio/format/avif/subsample", DT_DEFAULT);

size_t idx = 0;
for(size_t i = 0; avif_bit_depth[i].name != NULL; ++i)
Expand All @@ -961,6 +1032,7 @@ void gui_reset(dt_imageio_module_format_t *self)
dt_bauhaus_combobox_set(gui->tiling, tiling);
dt_bauhaus_combobox_set(gui->compression_type, compression_type);
dt_bauhaus_slider_set(gui->quality, quality);
dt_bauhaus_combobox_set(gui->subsample, subsample);
}

// clang-format off
Expand Down
Loading