Avoid double CM in saved WebPs

This commit is contained in:
Přemysl Eric Janouch 2021-12-26 01:24:09 +01:00
parent e37acf365a
commit e5b1a1861c
Signed by: p
GPG Key ID: A0420B94F92B9493
4 changed files with 50 additions and 15 deletions

View File

@ -5,8 +5,8 @@ fastiv
raw photos, HEIC, AVIF, WebP, SVG, X11 cursors and TIFF, or whatever gdk-pixbuf raw photos, HEIC, AVIF, WebP, SVG, X11 cursors and TIFF, or whatever gdk-pixbuf
loads. loads.
Its development status can be summarized as '`beta`'. E.g., colour management Its development status can be summarized as '`beta`'.
is a bit incomplete, and certain GIFs animate wrong. E.g., certain GIFs animate wrong.
Non-goals Non-goals
--------- ---------

View File

@ -206,6 +206,24 @@ fiv_io_profile_new_from_bytes(GBytes *bytes)
return fiv_io_profile_new(p, len); return fiv_io_profile_new(p, len);
} }
static GBytes *
fiv_io_profile_to_bytes(FivIoProfile profile)
{
#ifdef HAVE_LCMS2
cmsUInt32Number len = 0;
(void) cmsSaveProfileToMem(profile, NULL, &len);
gchar *data = g_malloc0(len);
if (!cmsSaveProfileToMem(profile, data, &len)) {
g_free(data);
return NULL;
}
return g_bytes_new_take(data, len);
#else
(void) profile;
return NULL;
#endif
}
void void
fiv_io_profile_free(FivIoProfile self) fiv_io_profile_free(FivIoProfile self)
{ {
@ -2490,10 +2508,8 @@ encode_webp_animation(WebPMux *mux, cairo_surface_t *page)
} }
static gboolean static gboolean
transfer_metadata(WebPMux *mux, const char *fourcc, cairo_surface_t *page, set_metadata(WebPMux *mux, const char *fourcc, GBytes *data)
const cairo_user_data_key_t *kind)
{ {
GBytes *data = cairo_surface_get_user_data(page, kind);
if (!data) if (!data)
return TRUE; return TRUE;
@ -2504,8 +2520,8 @@ transfer_metadata(WebPMux *mux, const char *fourcc, cairo_surface_t *page,
} }
gboolean gboolean
fiv_io_save(cairo_surface_t *page, cairo_surface_t *frame, const gchar *path, fiv_io_save(cairo_surface_t *page, cairo_surface_t *frame, FivIoProfile target,
GError **error) const gchar *path, GError **error)
{ {
g_return_val_if_fail(page != NULL, FALSE); g_return_val_if_fail(page != NULL, FALSE);
g_return_val_if_fail(path != NULL, FALSE); g_return_val_if_fail(path != NULL, FALSE);
@ -2519,9 +2535,16 @@ fiv_io_save(cairo_surface_t *page, cairo_surface_t *frame, const gchar *path,
else else
ok = encode_webp_animation(mux, page); ok = encode_webp_animation(mux, page);
ok = ok && transfer_metadata(mux, "EXIF", page, &fiv_io_key_exif); ok = ok && set_metadata(mux, "EXIF",
ok = ok && transfer_metadata(mux, "ICCP", page, &fiv_io_key_icc); cairo_surface_get_user_data(page, &fiv_io_key_exif));
ok = ok && transfer_metadata(mux, "XMP ", page, &fiv_io_key_xmp); ok = ok && set_metadata(mux, "ICCP",
cairo_surface_get_user_data(page, &fiv_io_key_icc));
ok = ok && set_metadata(mux, "XMP ",
cairo_surface_get_user_data(page, &fiv_io_key_xmp));
GBytes *iccp = NULL;
if (ok && target && (iccp = fiv_io_profile_to_bytes(target)))
ok = set_metadata(mux, "ICCP", iccp);
WebPData assembled = {}; WebPData assembled = {};
WebPDataInit(&assembled); WebPDataInit(&assembled);
@ -2531,6 +2554,9 @@ fiv_io_save(cairo_surface_t *page, cairo_surface_t *frame, const gchar *path,
ok = g_file_set_contents( ok = g_file_set_contents(
path, (const gchar *) assembled.bytes, assembled.size, error); path, (const gchar *) assembled.bytes, assembled.size, error);
if (iccp)
g_bytes_unref(iccp);
WebPMuxDelete(mux); WebPMuxDelete(mux);
WebPDataClear(&assembled); WebPDataClear(&assembled);
return ok; return ok;

View File

@ -79,7 +79,7 @@ int fiv_io_filecmp(GFile *f1, GFile *f2);
/// Requires libwebp. /// Requires libwebp.
/// If no exact frame is specified, this potentially creates an animation. /// If no exact frame is specified, this potentially creates an animation.
gboolean fiv_io_save(cairo_surface_t *page, cairo_surface_t *frame, gboolean fiv_io_save(cairo_surface_t *page, cairo_surface_t *frame,
const gchar *path, GError **error); FivIoProfile target, const gchar *path, GError **error);
// --- Metadata ---------------------------------------------------------------- // --- Metadata ----------------------------------------------------------------

View File

@ -779,9 +779,18 @@ print(FivView *self)
} }
static gboolean static gboolean
save_as(FivView *self, gboolean frame) save_as(FivView *self, cairo_surface_t *frame)
{ {
GtkWindow *window = get_toplevel(GTK_WIDGET(self)); GtkWindow *window = get_toplevel(GTK_WIDGET(self));
FivIoProfile target = NULL;
if (self->enable_cms && (target = self->screen_cms_profile)) {
GtkWidget *dialog = gtk_message_dialog_new(window, GTK_DIALOG_MODAL,
GTK_MESSAGE_WARNING, GTK_BUTTONS_CLOSE, "%s",
"Color management overrides attached color profiles.");
gtk_dialog_run(GTK_DIALOG(dialog));
gtk_widget_destroy(dialog);
}
GtkWidget *dialog = gtk_file_chooser_dialog_new( GtkWidget *dialog = gtk_file_chooser_dialog_new(
frame ? "Save frame as" : "Save page as", frame ? "Save frame as" : "Save page as",
window, GTK_FILE_CHOOSER_ACTION_SAVE, window, GTK_FILE_CHOOSER_ACTION_SAVE,
@ -834,7 +843,7 @@ save_as(FivView *self, gboolean frame)
GError *error = NULL; GError *error = NULL;
#ifdef HAVE_LIBWEBP #ifdef HAVE_LIBWEBP
if (gtk_file_chooser_get_filter(chooser) == webp_filter) if (gtk_file_chooser_get_filter(chooser) == webp_filter)
fiv_io_save(self->page, frame ? self->frame : NULL, path, &error); fiv_io_save(self->page, frame, target, path, &error);
else else
#endif // HAVE_LIBWEBP #endif // HAVE_LIBWEBP
fiv_io_save_metadata(self->page, path, &error); fiv_io_save_metadata(self->page, path, &error);
@ -1027,7 +1036,7 @@ fiv_view_key_press_event(GtkWidget *widget, GdkEventKey *event)
case GDK_KEY_s: case GDK_KEY_s:
return command(self, FIV_VIEW_COMMAND_SAVE_PAGE); return command(self, FIV_VIEW_COMMAND_SAVE_PAGE);
case GDK_KEY_S: case GDK_KEY_S:
return save_as(self, TRUE); return save_as(self, self->frame);
} }
} }
if (state == GDK_MOD1_MASK) { if (state == GDK_MOD1_MASK) {
@ -1320,7 +1329,7 @@ fiv_view_command(FivView *self, FivViewCommand command)
break; case FIV_VIEW_COMMAND_PRINT: break; case FIV_VIEW_COMMAND_PRINT:
print(self); print(self);
break; case FIV_VIEW_COMMAND_SAVE_PAGE: break; case FIV_VIEW_COMMAND_SAVE_PAGE:
save_as(self, FALSE); save_as(self, NULL);
break; case FIV_VIEW_COMMAND_INFO: break; case FIV_VIEW_COMMAND_INFO:
info(self); info(self);