From 19c57a9765ac3451c9cde94ccb06bec5ae06fbd8 Mon Sep 17 00:00:00 2001 From: Advance Software Date: Sun, 25 May 2025 22:32:20 -0400 Subject: [PATCH] plug-ins: Add support for JPEG 2000 export --- .../common/{file-jp2-load.c => file-jp2.c} | 623 ++++++++++++++++++ plug-ins/common/meson.build | 2 +- po-plug-ins/POTFILES.in | 2 +- 3 files changed, 625 insertions(+), 2 deletions(-) rename plug-ins/common/{file-jp2-load.c => file-jp2.c} (61%) diff --git a/plug-ins/common/file-jp2-load.c b/plug-ins/common/file-jp2.c similarity index 61% rename from plug-ins/common/file-jp2-load.c rename to plug-ins/common/file-jp2.c index 19b5e6c455..7a2b5be4b6 100644 --- a/plug-ins/common/file-jp2-load.c +++ b/plug-ins/common/file-jp2.c @@ -90,6 +90,8 @@ #define LOAD_JP2_PROC "file-jp2-load" #define LOAD_J2K_PROC "file-j2k-load" +#define EXPORT_JP2_PROC "file-jp2-export" +#define EXPORT_J2K_PROC "file-j2k-export" #define PLUG_IN_BINARY "file-jp2-load" #define PLUG_IN_ROLE "gimp-file-jp2-load" @@ -124,6 +126,14 @@ static GimpValueArray * jp2_load (GimpProcedure *procedure, GimpMetadataLoadFlags *flags, GimpProcedureConfig *config, gpointer run_data); +static GimpValueArray * jp2_export (GimpProcedure *procedure, + GimpRunMode run_mode, + GimpImage *image, + GFile *file, + GimpExportOptions *options, + GimpMetadata *metadata, + GimpProcedureConfig *config, + gpointer run_data); static GimpImage * load_image (GimpProcedure *procedure, GObject *config, @@ -133,6 +143,13 @@ static GimpImage * load_image (GimpProcedure *procedure, gboolean interactive, gboolean *profile_loaded, GError **error); +static GimpPDBStatusType export_image (GFile *file, + GimpImage *image, + GimpDrawable *drawable, + GimpRunMode run_mode, + GimpProcedure *procedure, + GObject *config, + GError **error); static OPJ_COLOR_SPACE open_dialog (GimpProcedure *procedure, GObject *config, @@ -140,6 +157,12 @@ static OPJ_COLOR_SPACE open_dialog (GimpProcedure *procedure, OPJ_CODEC_FORMAT format, gint num_components, GError **error); +static gboolean export_dialog (GimpProcedure *procedure, + GimpProcedureConfig *config, + GimpImage *image); + +/* Helper Method */ +static gint get_bpc (GimpImage *image); G_DEFINE_TYPE (Jp2, jp2, GIMP_TYPE_PLUG_IN) @@ -170,6 +193,8 @@ jp2_query_procedures (GimpPlugIn *plug_in) list = g_list_append (list, g_strdup (LOAD_JP2_PROC)); list = g_list_append (list, g_strdup (LOAD_J2K_PROC)); + list = g_list_append (list, g_strdup (EXPORT_JP2_PROC)); + list = g_list_append (list, g_strdup (EXPORT_J2K_PROC)); return list; } @@ -273,6 +298,182 @@ jp2_create_procedure (GimpPlugIn *plug_in, "unknown", G_PARAM_READWRITE); } + else if (! strcmp (name, EXPORT_JP2_PROC)) + { + procedure = gimp_export_procedure_new (plug_in, name, + GIMP_PDB_PROC_TYPE_PLUGIN, + FALSE, jp2_export, NULL, NULL); + + gimp_procedure_set_image_types (procedure, "GRAY, RGB*"); + + gimp_procedure_set_menu_label (procedure, _("JPEG 2000 image")); + gimp_file_procedure_set_format_name (GIMP_FILE_PROCEDURE (procedure), + _("JPEG 2000")); + + gimp_procedure_set_documentation (procedure, + _("Exports files in JPEG 2000 file format"), + _("Exports files in JPEG 2000 file format"), + name); + gimp_procedure_set_attribution (procedure, + "Advance Software", + "Advance Software", + "2025"); + + gimp_file_procedure_set_mime_types (GIMP_FILE_PROCEDURE (procedure), + "image/jp2"); + gimp_file_procedure_set_extensions (GIMP_FILE_PROCEDURE (procedure), + "jp2"); + + gimp_export_procedure_set_capabilities (GIMP_EXPORT_PROCEDURE (procedure), + GIMP_EXPORT_CAN_HANDLE_RGB | + GIMP_EXPORT_CAN_HANDLE_GRAY | + GIMP_EXPORT_CAN_HANDLE_ALPHA, + NULL, NULL, NULL); + + gimp_procedure_add_double_argument (procedure, "quality", + _("_Quality"), + _("Quality of exported image"), + 0.0, 1.0, 0.9, + G_PARAM_READWRITE); + + gimp_procedure_add_boolean_argument (procedure, "ict", + _("IC_T compression"), + _("Use Irreversible Color Transformation " + "compression"), + FALSE, + G_PARAM_READWRITE); + + gimp_procedure_add_int_argument (procedure, "resolution", + _("_Number of resolutions"), + _("Equivalent to the number of " + "DWT decompositions plus one"), + 1, 12, 6, + G_PARAM_READWRITE); + + gimp_procedure_add_choice_argument (procedure, "progression-order", + _("Pro_gression order"), + NULL, + gimp_choice_new_with_values ("lrcp", OPJ_LRCP, _("LRCP"), NULL, + "rlcp", OPJ_RLCP, _("RLCP"), NULL, + "rpcl", OPJ_RPCL, _("RPCL"), NULL, + "pcrl", OPJ_PCRL, _("PCRL"), NULL, + "cprl", OPJ_CPRL, _("CPRL"), NULL, + NULL), + "lrcp", + G_PARAM_READWRITE); + + gimp_procedure_add_choice_argument (procedure, "compliance", + _("Co_mpliance Profile"), + _("Set to ensure compliance with Digital Cinema Specifications"), + gimp_choice_new_with_values ("standard", 0, _("Standard Profile"), NULL, + "cinema-2k-24", OPJ_CINEMA2K_24, _("Cinema2K (24 FPS)"), NULL, + "cinema-2k-48", OPJ_CINEMA2K_48, _("Cinema2K (48 FPS)"), NULL, + "cinema-4k-24", OPJ_CINEMA4K_24, _("Cinema4K (24 FPS)"), NULL, + NULL), + "standard", + G_PARAM_READWRITE); + + /* CMYK JPEG 2000 export support was added in OpenJPEG 2.5.3 */ +#if ((OPJ_VERSION_MAJOR == 2 && OPJ_VERSION_MINOR == 5 && OPJ_VERSION_BUILD >= 3) || \ + (OPJ_VERSION_MAJOR == 2 && OPJ_VERSION_MINOR > 5) || OPJ_VERSION_MAJOR > 2) + gimp_procedure_add_boolean_argument (procedure, "cmyk", + _("E_xport as CMYK"), + _("Create a CMYK JPEG 2000 image using the " + "soft-proofing color profile"), + FALSE, + G_PARAM_READWRITE); +#endif + + gimp_export_procedure_set_support_comment (GIMP_EXPORT_PROCEDURE (procedure), TRUE); + } + else if (! strcmp (name, EXPORT_J2K_PROC)) + { + procedure = gimp_export_procedure_new (plug_in, name, + GIMP_PDB_PROC_TYPE_PLUGIN, + FALSE, jp2_export, NULL, NULL); + + gimp_procedure_set_image_types (procedure, "GRAY, RGB*"); + + gimp_procedure_set_menu_label (procedure, _("JPEG 2000 codestream")); + gimp_file_procedure_set_format_name (GIMP_FILE_PROCEDURE (procedure), + _("JPEG 2000 codestream")); + + gimp_procedure_set_documentation (procedure, + _("Exports files in JPEG 2000 codestream format"), + _("Exports files in JPEG 2000 codestream format"), + name); + gimp_procedure_set_attribution (procedure, + "Advance Software", + "Advance Software", + "2025"); + + gimp_file_procedure_set_mime_types (GIMP_FILE_PROCEDURE (procedure), + "image/x-jp2-codestream"); + gimp_file_procedure_set_extensions (GIMP_FILE_PROCEDURE (procedure), + "j2k,j2c,jpc"); + + gimp_export_procedure_set_capabilities (GIMP_EXPORT_PROCEDURE (procedure), + GIMP_EXPORT_CAN_HANDLE_RGB | + GIMP_EXPORT_CAN_HANDLE_GRAY | + GIMP_EXPORT_CAN_HANDLE_ALPHA, + NULL, NULL, NULL); + + gimp_procedure_add_double_argument (procedure, "quality", + _("_Quality"), + _("Quality of exported image"), + 0.0, 1.0, 0.9, + G_PARAM_READWRITE); + + gimp_procedure_add_boolean_argument (procedure, "ict", + _("IC_T compression"), + _("Use Irreversible Color Transformation " + "compression"), + FALSE, + G_PARAM_READWRITE); + + gimp_procedure_add_int_argument (procedure, "resolution", + _("_Number of Resolutions"), + _("Equivalent to the number of " + "DWT decompositions plus one"), + 1, 12, 6, + G_PARAM_READWRITE); + + gimp_procedure_add_choice_argument (procedure, "progression-order", + _("Pro_gression order"), + NULL, + gimp_choice_new_with_values ("lrcp", OPJ_LRCP, _("LRCP"), NULL, + "rlcp", OPJ_RLCP, _("RLCP"), NULL, + "rpcl", OPJ_RPCL, _("RPCL"), NULL, + "pcrl", OPJ_PCRL, _("PCRL"), NULL, + "cprl", OPJ_CPRL, _("CPRL"), NULL, + NULL), + "lrcp", + G_PARAM_READWRITE); + + gimp_procedure_add_choice_argument (procedure, "compliance", + _("Co_mpliance Profile"), + _("Set to ensure compliance with Digital Cinema Specifications"), + gimp_choice_new_with_values ("standard", 0, _("Standard Profile"), NULL, + "cinema-2k-24", OPJ_CINEMA2K_24, _("Cinema2K (24 FPS)"), NULL, + "cinema-2k-48", OPJ_CINEMA2K_48, _("Cinema2K (48 FPS)"), NULL, + "cinema-4k-24", OPJ_CINEMA4K_24, _("Cinema4K (24 FPS)"), NULL, + NULL), + "standard", + G_PARAM_READWRITE); + + /* CMYK JPEG 2000 export support was added in OpenJPEG 2.5.3 */ +#if ((OPJ_VERSION_MAJOR == 2 && OPJ_VERSION_MINOR == 5 && OPJ_VERSION_BUILD >= 3) || \ + (OPJ_VERSION_MAJOR == 2 && OPJ_VERSION_MINOR > 5) || OPJ_VERSION_MAJOR > 2) + gimp_procedure_add_boolean_argument (procedure, "cmyk", + _("E_xport as CMYK"), + _("Create a CMYK JPEG 2000 image using the " + "soft-proofing color profile"), + FALSE, + G_PARAM_READWRITE); +#endif + + gimp_export_procedure_set_support_comment (GIMP_EXPORT_PROCEDURE (procedure), TRUE); + } return procedure; } @@ -344,6 +545,49 @@ jp2_load (GimpProcedure *procedure, return return_vals; } +static GimpValueArray * +jp2_export (GimpProcedure *procedure, + GimpRunMode run_mode, + GimpImage *image, + GFile *file, + GimpExportOptions *options, + GimpMetadata *metadata, + GimpProcedureConfig *config, + gpointer run_data) +{ + GimpPDBStatusType status = GIMP_PDB_SUCCESS; + GimpExportReturn export = GIMP_EXPORT_IGNORE; + GError *error = NULL; + GList *drawables; + + gegl_init (NULL, NULL); + + if (run_mode == GIMP_RUN_INTERACTIVE) + { + gimp_ui_init (PLUG_IN_BINARY); + + if (! export_dialog (procedure, config, image)) + status = GIMP_PDB_CANCEL; + } + + if (status != GIMP_PDB_CANCEL) + { + export = gimp_export_options_get_image (options, &image); + drawables = gimp_image_list_layers (image); + + status = export_image (file, image, drawables->data, run_mode, + procedure, G_OBJECT (config), + &error); + + if (export == GIMP_EXPORT_EXPORT) + gimp_image_delete (image); + + g_list_free (drawables); + } + + return gimp_procedure_new_return_values (procedure, status, error); +} + static void sycc_to_rgb (int offset, int upb, @@ -1028,6 +1272,73 @@ open_dialog (GimpProcedure *procedure, return color_space; } +static gboolean +export_dialog (GimpProcedure *procedure, + GimpProcedureConfig *config, + GimpImage *image) +{ + GtkWidget *dialog; + GtkWidget *profile_label; + GimpColorProfile *cmyk_profile = NULL; + gboolean run; + + dialog = gimp_export_procedure_dialog_new (GIMP_EXPORT_PROCEDURE (procedure), + GIMP_PROCEDURE_CONFIG (config), + image); + + /* Quality as a GimpScaleEntry. */ + gimp_procedure_dialog_get_spin_scale (GIMP_PROCEDURE_DIALOG (dialog), + "quality", 100.0); + + gimp_procedure_dialog_fill (GIMP_PROCEDURE_DIALOG (dialog), "quality", "ict", + NULL); + +#if ((OPJ_VERSION_MAJOR == 2 && OPJ_VERSION_MINOR == 5 && OPJ_VERSION_BUILD >= 3) || \ + (OPJ_VERSION_MAJOR == 2 && OPJ_VERSION_MINOR > 5) || OPJ_VERSION_MAJOR > 2) + /* Profile label. */ + profile_label = gimp_procedure_dialog_get_label (GIMP_PROCEDURE_DIALOG (dialog), + "profile-label", _("No soft-proofing profile"), + FALSE, FALSE); + gtk_label_set_xalign (GTK_LABEL (profile_label), 0.0); + gtk_label_set_ellipsize (GTK_LABEL (profile_label), PANGO_ELLIPSIZE_END); + gimp_label_set_attributes (GTK_LABEL (profile_label), + PANGO_ATTR_STYLE, PANGO_STYLE_ITALIC, + -1); + gimp_help_set_help_data (profile_label, + _("Name of the color profile used for CMYK export."), NULL); + gimp_procedure_dialog_fill_frame (GIMP_PROCEDURE_DIALOG (dialog), + "cmyk-frame", "cmyk", FALSE, + "profile-label"); + cmyk_profile = gimp_image_get_simulation_profile (image); + if (cmyk_profile) + { + if (gimp_color_profile_is_cmyk (cmyk_profile)) + { + gchar *label_text; + + label_text = g_strdup_printf (_("Profile: %s"), + gimp_color_profile_get_label (cmyk_profile)); + gtk_label_set_text (GTK_LABEL (profile_label), label_text); + gimp_label_set_attributes (GTK_LABEL (profile_label), + PANGO_ATTR_STYLE, PANGO_STYLE_NORMAL, + -1); + g_free (label_text); + } + g_object_unref (cmyk_profile); + } + + gimp_procedure_dialog_fill (GIMP_PROCEDURE_DIALOG (dialog), "cmyk-frame", NULL); +#endif + + gimp_procedure_dialog_fill (GIMP_PROCEDURE_DIALOG (dialog), "resolution", + "progression-order", "compliance", NULL); + + run = gimp_procedure_dialog_run (GIMP_PROCEDURE_DIALOG (dialog)); + gtk_widget_destroy (dialog); + + return run; +} + static GimpImage * load_image (GimpProcedure *procedure, GObject *config, @@ -1345,3 +1656,315 @@ load_image (GimpProcedure *procedure, return gimp_image; } + +static GimpPDBStatusType +export_image (GFile *file, + GimpImage *image, + GimpDrawable *drawable, + GimpRunMode run_mode, + GimpProcedure *procedure, + GObject *config, + GError **error) +{ + /* OpenJPEG parameters */ + opj_cparameters_t parameters; + opj_codec_t *codec; + opj_image_t *jp2_image; + opj_image_cmptparm_t cmptparm[4]; + opj_stream_t *stream = NULL; + OPJ_BOOL success; + OPJ_COLOR_SPACE color_space; + /* GIMP variables */ + GimpPDBStatusType status = GIMP_PDB_SUCCESS; + guchar *pixels = NULL; + GeglBuffer *buffer = NULL; + const Babl *format; + gchar *path; + gint channels; + GimpImageType type; + gint width; + gint height; + gint precision; + gint bpc; + gint tile_height; + /* Plug-in parameters */ + gdouble quality; + gboolean ict; + gint resolution; + gint prog_order; + gint compliance; + gboolean save_comment; + gchar *comment = NULL; + gboolean cmyk = FALSE; + + g_object_get (config, + "quality", &quality, + "ict", &ict, + "resolution", &resolution, + "include-comment", &save_comment, + "gimp-comment", &comment, +#if ((OPJ_VERSION_MAJOR == 2 && OPJ_VERSION_MINOR == 5 && OPJ_VERSION_BUILD >= 3) || \ + (OPJ_VERSION_MAJOR == 2 && OPJ_VERSION_MINOR > 5) || OPJ_VERSION_MAJOR > 2) + "cmyk", &cmyk, +#endif + NULL); + compliance = + gimp_procedure_config_get_choice_id (GIMP_PROCEDURE_CONFIG (config), + "compliance"); + prog_order = + gimp_procedure_config_get_choice_id (GIMP_PROCEDURE_CONFIG (config), + "progression-order"); + + buffer = gimp_drawable_get_buffer (drawable); + tile_height = gimp_tile_height (); + + type = gimp_drawable_type (drawable); + width = gimp_drawable_get_width (drawable); + height = gimp_drawable_get_height (drawable); + precision = get_bpc (image); + + switch (type) + { + case GIMP_RGBA_IMAGE: + if (precision == 8) + format = babl_format ("R'G'B'A u8"); + else + format = babl_format ("R'G'B'A u16"); + + channels = 4; + color_space = OPJ_CLRSPC_SRGB; + break; + + case GIMP_RGB_IMAGE: + if (precision == 8) + format = babl_format ("R'G'B' u8"); + else + format = babl_format ("R'G'B' u16"); + + channels = 3; + color_space = OPJ_CLRSPC_SRGB; + break; + + case GIMP_GRAYA_IMAGE: + if (precision == 8) + format = babl_format ("Y'A u8"); + else + format = babl_format ("Y'A u16"); + + channels = 2; + color_space = OPJ_CLRSPC_GRAY; + break; + + case GIMP_GRAY_IMAGE: + if (precision == 8) + format = babl_format ("Y' u8"); + else + format = babl_format ("Y' u16"); + + channels = 1; + color_space = OPJ_CLRSPC_GRAY; + break; + + default: + g_assert_not_reached (); + } + + if (cmyk) + { + if (precision == 8) + format = babl_format ("CMYK u8"); + else + format = babl_format ("CMYK u16"); + + channels = 4; + color_space = OPJ_CLRSPC_CMYK; + } + + gimp_progress_init_printf (_("Exporting '%s'"), + gimp_file_get_utf8_name (file)); + + /* fetch the image */ + bpc = precision / 8; + pixels = g_new0 (guchar, tile_height * width * channels * bpc); + + /* Initialize OpenJPEG */ + opj_set_default_encoder_parameters (¶meters); + + if (! strcmp (gimp_procedure_get_name (procedure), EXPORT_JP2_PROC)) + { + parameters.cod_format = 1; + codec = opj_create_compress (OPJ_CODEC_JP2); + } + else + { + parameters.cod_format = 0; + codec = opj_create_compress (OPJ_CODEC_J2K); + } + + memset (&cmptparm[0], 0, 4 * sizeof (opj_image_cmptparm_t)); + + for (gint i = 0; i < channels; i++) + { + cmptparm[i].prec = precision; + cmptparm[i].sgnd = 0; + cmptparm[i].dx = parameters.subsampling_dx; + cmptparm[i].dy = parameters.subsampling_dy; + cmptparm[i].w = width; + cmptparm[i].h = height; + } + + jp2_image = opj_image_create (channels, &cmptparm[0], color_space); + + if (! jp2_image) + { + status = GIMP_PDB_EXECUTION_ERROR; + goto out; + } + + jp2_image->x0 = parameters.image_offset_x0; + jp2_image->y0 = parameters.image_offset_y0; + jp2_image->x1 = jp2_image->x0 + (width - 1) * parameters.subsampling_dx + 1; + jp2_image->y1 = jp2_image->y0 + (height - 1) * parameters.subsampling_dy + 1; + + for (gint i = 0; i < height; i += tile_height) + { + gint tile_pixels; + gint rect_height = (tile_height < (height - i)) ? + tile_height : (height - i); + + gegl_buffer_get (buffer, + GEGL_RECTANGLE (0, i, width, rect_height), 1.0, + format, pixels, + GEGL_AUTO_ROWSTRIDE, GEGL_ABYSS_NONE); + + tile_pixels = rect_height * width; + for (gint j = 0; j < tile_pixels; j++) + { + gint index = (i * width) + j; + gint offset = j * (channels * bpc); + guint16 pix16; + + for (gint k = 0; k < (channels * bpc); k += bpc) + { + if (precision == 8) + { + jp2_image->comps[k].data[index] = pixels[offset + k]; + } + else if (precision == 16) + { + pix16 = ((gushort) pixels[offset + k + 1] << 8) | + pixels[offset + k]; + + jp2_image->comps[k / bpc].data[index] = pix16; + } + } + } + } + + /* Other parameters */ + parameters.irreversible = (gint) ict; + parameters.numresolution = resolution; + parameters.prog_order = prog_order; + + if (compliance == OPJ_CINEMA2K_24) + { + parameters.rsiz = OPJ_PROFILE_CINEMA_2K; + parameters.max_comp_size = OPJ_CINEMA_24_COMP; + parameters.max_cs_size = OPJ_CINEMA_24_CS; + } + else if (compliance == OPJ_CINEMA2K_48) + { + parameters.rsiz = OPJ_PROFILE_CINEMA_2K; + parameters.max_comp_size = OPJ_CINEMA_48_COMP; + parameters.max_cs_size = OPJ_CINEMA_48_CS; + } + else if (compliance == OPJ_CINEMA4K_24) + { + parameters.rsiz = OPJ_PROFILE_CINEMA_4K; + } + + if (save_comment && comment && strlen (comment)) + { + parameters.cp_comment = g_malloc0 (strlen (comment) + 1); + strncpy (parameters.cp_comment, comment, strlen (comment)); + } + + if (! cmyk) + parameters.tcp_mct = (channels >= 3) ? 1 : 0; + + /* Quality of 0 is lossless */ + parameters.tcp_distoratio[0] = (quality == 100.0) ? 0 : quality; + parameters.tcp_numlayers = 1; + + /* Encoding */ + if (! opj_setup_encoder (codec, ¶meters, jp2_image)) + { + status = GIMP_PDB_EXECUTION_ERROR; + goto out; + } + + path = g_file_get_path (file); + memcpy (parameters.outfile, path, strlen (path)); + + stream = opj_stream_create_default_file_stream (parameters.outfile, + OPJ_FALSE); + if (! stream) + { + status = GIMP_PDB_EXECUTION_ERROR; + goto out; + } + + success = opj_start_compress (codec, jp2_image, stream); + if (! success) + { + status = GIMP_PDB_EXECUTION_ERROR; + goto out; + } + + success = success && opj_encode (codec, stream); + if (! success) + { + status = GIMP_PDB_EXECUTION_ERROR; + goto out; + } + + success = success && opj_end_compress (codec, stream); + if (! success) + { + status = GIMP_PDB_EXECUTION_ERROR; + goto out; + } + + out: + if (stream) + opj_stream_destroy (stream); + if (codec) + opj_destroy_codec (codec); + if (jp2_image) + opj_image_destroy (jp2_image); + + if (buffer) + g_object_unref (buffer); + if (pixels) + g_free (pixels); + + return status; +} + +/* Helper Methods */ + +static gint +get_bpc (GimpImage *image) +{ + /* OpenJPEG only supports up to 16 bpc */ + switch (gimp_image_get_precision (image)) + { + case GIMP_PRECISION_U8_LINEAR: + case GIMP_PRECISION_U8_NON_LINEAR: + case GIMP_PRECISION_U8_PERCEPTUAL: + return 8; + + default: + return 16; + } +} diff --git a/plug-ins/common/meson.build b/plug-ins/common/meson.build index 84cc77b364..2803c29b5d 100644 --- a/plug-ins/common/meson.build +++ b/plug-ins/common/meson.build @@ -97,7 +97,7 @@ if have_heif endif if openjpeg.found() - common_plugins_list += { 'name': 'file-jp2-load', + common_plugins_list += { 'name': 'file-jp2', 'deps': [ gtk3, gegl, gdk_pixbuf, openjpeg, ], } endif diff --git a/po-plug-ins/POTFILES.in b/po-plug-ins/POTFILES.in index 27db85990b..844ae7436c 100644 --- a/po-plug-ins/POTFILES.in +++ b/po-plug-ins/POTFILES.in @@ -42,7 +42,7 @@ plug-ins/common/file-header.c plug-ins/common/file-heif.c plug-ins/common/file-html-table.c plug-ins/common/file-iff.c -plug-ins/common/file-jp2-load.c +plug-ins/common/file-jp2.c plug-ins/common/file-jpegxl.c plug-ins/common/file-lnk.c plug-ins/common/file-mng.c