[gimp/gimp-2-10] JPEG XL import support
- From: Daniel Novomeský <dnovomesky src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gimp/gimp-2-10] JPEG XL import support
- Date: Wed, 1 Jun 2022 17:33:36 +0000 (UTC)
commit 17fd249394a4d69bb49e1366ca6f2ab435e0eba8
Author: Daniel Novomeský <dnovomesky gmail com>
Date: Tue May 31 18:23:50 2022 +0200
JPEG XL import support
JXL import is backported from GIMP 2.99
Added .jxl association for Windows installer
It was necessary to adjust plugin-defs.pl for HEIF plugin,
because necessary dependencies were missing there.
build/windows/installer/associations.list | 1 +
configure.ac | 30 ++
plug-ins/common/.gitignore | 2 +
plug-ins/common/Makefile.am | 29 +-
plug-ins/common/file-jpegxl.c | 568 ++++++++++++++++++++++++++++++
plug-ins/common/gimprc.common | 1 +
plug-ins/common/plugin-defs.pl | 3 +-
7 files changed, 631 insertions(+), 3 deletions(-)
---
diff --git a/build/windows/installer/associations.list b/build/windows/installer/associations.list
index 413913c27f..06f2818d6b 100755
--- a/build/windows/installer/associations.list
+++ b/build/windows/installer/associations.list
@@ -14,6 +14,7 @@ jp2
j2k
j2c
jpc
+jxl
pcx
pcc
pdf
diff --git a/configure.ac b/configure.ac
index 5c5719f5aa..eb0cb7f2bf 100644
--- a/configure.ac
+++ b/configure.ac
@@ -66,6 +66,7 @@ m4_define([json_glib_required_version], [1.2.6])
m4_define([lcms_required_version], [2.8])
m4_define([libgudev_required_version], [167])
m4_define([libheif_required_version], [1.3.2])
+m4_define([libjxl_required_version], [0.6.1])
m4_define([liblzma_required_version], [5.0.0])
m4_define([libmypaint_required_version], [1.3.0])
m4_define([libpng_required_version], [1.6.25])
@@ -176,6 +177,7 @@ PERL_REQUIRED_VERSION=perl_required_version
PYTHON2_REQUIRED_VERSION=python2_required_version
WEBP_REQUIRED_VERSION=webp_required_version
LIBHEIF_REQUIRED_VERSION=libheif_required_version
+LIBJXL_REQUIRED_VERSION=libjxl_required_version
LIBUNWIND_REQUIRED_VERSION=libunwind_required_version
XGETTEXT_REQUIRED_VERSION=xgettext_required_version
AC_SUBST(GLIB_REQUIRED_VERSION)
@@ -208,6 +210,7 @@ AC_SUBST(PERL_REQUIRED_VERSION)
AC_SUBST(PYTHON2_REQUIRED_VERSION)
AC_SUBST(WEBP_REQUIRED_VERSION)
AC_SUBST(LIBHEIF_REQUIRED_VERSION)
+AC_SUBST(LIBJXL_REQUIRED_VERSION)
AC_SUBST(LIBUNWIND_REQUIRED_VERSION)
AC_SUBST(XGETTEXT_REQUIRED_VERSION)
@@ -1865,6 +1868,32 @@ if test "x$have_libheif_1_4_0" = xyes; then
fi
+###################
+# Check for JPEG XL
+###################
+
+AC_ARG_WITH(jpegxl, [ --without-jpegxl build without JPEG XL support])
+
+have_jpegxl=no
+if test "x$with_jpegxl" != xno; then
+ PKG_CHECK_MODULES(JXL, libjxl >= libjxl_required_version,
+ [
+ PKG_CHECK_MODULES(JXL_THREADS, libjxl_threads >= libjxl_required_version,
+ [have_jpegxl=yes],
+ [have_jpegxl="no (libjxl_threads not found)"])
+ ],
+ [have_jpegxl="no (libjxl not found)"])
+fi
+
+if test "x$have_jpegxl" = xyes; then
+ MIME_TYPES="$MIME_TYPES;image/jxl"
+ FILE_JPEGXL='file-jpegxl$(EXEEXT)'
+fi
+
+AM_CONDITIONAL(HAVE_JPEGXL, test "x$have_jpegxl" = xyes)
+AC_SUBST(FILE_JPEGXL)
+
+
########################
# Check for libbacktrace
########################
@@ -3155,6 +3184,7 @@ Optional Plug-Ins:
Ghostscript: $have_gs
Help Browser: $have_webkit
JPEG 2000: $have_openjpeg
+ JPEG XL: $have_jpegxl
MNG: $have_libmng
OpenEXR: $have_openexr
WebP: $have_webp
diff --git a/plug-ins/common/.gitignore b/plug-ins/common/.gitignore
index dda0467dee..4870cebb8f 100644
--- a/plug-ins/common/.gitignore
+++ b/plug-ins/common/.gitignore
@@ -82,6 +82,8 @@
/file-html-table.exe
/file-jp2-load
/file-jp2-load.exe
+/file-jpegxl
+/file-jpegxl.exe
/file-mng
/file-mng.exe
/file-pat
diff --git a/plug-ins/common/Makefile.am b/plug-ins/common/Makefile.am
index 7b141734ce..6772f9d1ab 100644
--- a/plug-ins/common/Makefile.am
+++ b/plug-ins/common/Makefile.am
@@ -86,6 +86,7 @@ file_header_libexecdir = $(gimpplugindir)/plug-ins/file-header
file_heif_libexecdir = $(gimpplugindir)/plug-ins/file-heif
file_html_table_libexecdir = $(gimpplugindir)/plug-ins/file-html-table
file_jp2_load_libexecdir = $(gimpplugindir)/plug-ins/file-jp2-load
+file_jpegxl_libexecdir = $(gimpplugindir)/plug-ins/file-jpegxl
file_mng_libexecdir = $(gimpplugindir)/plug-ins/file-mng
file_pat_libexecdir = $(gimpplugindir)/plug-ins/file-pat
file_pcx_libexecdir = $(gimpplugindir)/plug-ins/file-pcx
@@ -177,6 +178,7 @@ file_header_libexec_PROGRAMS = file-header
file_heif_libexec_PROGRAMS = $(FILE_HEIF)
file_html_table_libexec_PROGRAMS = file-html-table
file_jp2_load_libexec_PROGRAMS = $(FILE_JP2_LOAD)
+file_jpegxl_libexec_PROGRAMS = $(FILE_JPEGXL)
file_mng_libexec_PROGRAMS = $(FILE_MNG)
file_pat_libexec_PROGRAMS = file-pat
file_pcx_libexec_PROGRAMS = file-pcx
@@ -232,6 +234,7 @@ EXTRA_PROGRAMS = \
file-aa \
file-heif \
file-jp2-load \
+ file-jpegxl \
file-mng \
file-pdf-save \
file-ps \
@@ -918,12 +921,12 @@ file_heif_LDADD = \
$(libgimpcolor) \
$(libgimpbase) \
$(GTK_LIBS) \
- $(GEXIV2_LIBS) \
$(GEGL_LIBS) \
$(LIBHEIF_LIBS) \
+ $(LCMS_LIBS) \
+ $(GEXIV2_LIBS) \
$(RT_LIBS) \
$(INTLLIBS) \
- $(LCMS_LIBS) \
$(file_heif_RC)
file_html_table_SOURCES = \
@@ -965,6 +968,28 @@ file_jp2_load_LDADD = \
$(INTLLIBS) \
$(file_jp2_load_RC)
+file_jpegxl_CFLAGS = $(JXL_CFLAGS)
+
+file_jpegxl_SOURCES = \
+ file-jpegxl.c
+
+file_jpegxl_LDADD = \
+ $(libgimpui) \
+ $(libgimpwidgets) \
+ $(libgimpmodule) \
+ $(libgimp) \
+ $(libgimpmath) \
+ $(libgimpconfig) \
+ $(libgimpcolor) \
+ $(libgimpbase) \
+ $(GTK_LIBS) \
+ $(GEGL_LIBS) \
+ $(JXL_THREADS_LIBS) \
+ $(JXL_LIBS) \
+ $(RT_LIBS) \
+ $(INTLLIBS) \
+ $(file_jpegxl_RC)
+
file_mng_CFLAGS = $(MNG_CFLAGS)
file_mng_SOURCES = \
diff --git a/plug-ins/common/file-jpegxl.c b/plug-ins/common/file-jpegxl.c
new file mode 100644
index 0000000000..4c31d98b48
--- /dev/null
+++ b/plug-ins/common/file-jpegxl.c
@@ -0,0 +1,568 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * file-jpegxl - JPEG XL file format plug-in for the GIMP
+ * Copyright (C) 2022 Daniel Novomesky
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include <glib/gstdio.h>
+
+#include <jxl/decode.h>
+#include <jxl/encode.h>
+#include <jxl/thread_parallel_runner.h>
+
+#include <libgimp/gimp.h>
+#include <libgimp/gimpui.h>
+
+#include "libgimp/stdplugins-intl.h"
+
+#define LOAD_PROC "file-jpegxl-load"
+#define PLUG_IN_BINARY "file-jpegxl"
+
+static void query (void);
+static void run (const gchar *name,
+ gint nparams,
+ const GimpParam *param,
+ gint *nreturn_vals,
+ GimpParam **return_vals);
+
+GimpPlugInInfo PLUG_IN_INFO = {
+ NULL, /* init_proc */
+ NULL, /* quit_proc */
+ query, /* query_proc */
+ run, /* run_proc */
+};
+
+MAIN ()
+
+static void
+query (void)
+{
+ static const GimpParamDef load_args[] = {
+ { GIMP_PDB_INT32, "run-mode", "The run mode { RUN-INTERACTIVE (0), RUN-NONINTERACTIVE (1) }"},
+ { GIMP_PDB_STRING, "filename", "The name of the file to load" },
+ { GIMP_PDB_STRING, "raw-filename", "The name of the file to load" }
+ };
+ static const GimpParamDef load_return_vals[] = {
+ {GIMP_PDB_IMAGE, "image", "Output image"}
+ };
+
+ gimp_install_procedure (LOAD_PROC,
+ "Loads files in the JPEG XL file format",
+ "Loads files in the JPEG XL file format",
+ "Daniel Novomesky",
+ "(C) 2022 Daniel Novomesky",
+ "2022",
+ N_("JPEG XL image"),
+ NULL,
+ GIMP_PLUGIN,
+ G_N_ELEMENTS (load_args),
+ G_N_ELEMENTS (load_return_vals),
+ load_args, load_return_vals);
+
+ gimp_register_file_handler_mime (LOAD_PROC, "image/jxl");
+ gimp_register_magic_load_handler (LOAD_PROC, "jxl", "",
"0,string,\xFF\x0A,0,string,\\000\\000\\000\x0CJXL\\040\\015\\012\x87\\012");
+ gimp_register_file_handler_priority (LOAD_PROC, 100);
+}
+
+static gint32
+load_image (const gchar *filename,
+ GError **error)
+{
+ FILE *inputFile = g_fopen (filename, "rb");
+
+ gsize inputFileSize;
+ gpointer memory;
+
+ JxlSignature signature;
+ JxlDecoder *decoder;
+ void *runner;
+ JxlBasicInfo basicinfo;
+ JxlDecoderStatus status;
+ JxlPixelFormat pixel_format;
+ JxlColorEncoding color_encoding;
+ size_t icc_size = 0;
+ GimpColorProfile *profile = NULL;
+ gboolean loadlinear = FALSE;
+ size_t channel_depth;
+ size_t result_size;
+ gpointer picture_buffer;
+ gint32 image = -1;
+ gint32 layer;
+ GeglBuffer *buffer;
+ GimpPrecision precision_linear;
+ GimpPrecision precision_non_linear;
+ size_t num_worker_threads = 1;
+
+ if (! inputFile)
+ {
+ g_set_error (error, G_FILE_ERROR, 0, "Cannot open file for read: %s\n", filename);
+ return -1;
+ }
+
+ fseek (inputFile, 0, SEEK_END);
+ inputFileSize = ftell (inputFile);
+ fseek (inputFile, 0, SEEK_SET);
+
+ if (inputFileSize < 1)
+ {
+ g_set_error (error, G_FILE_ERROR, 0, "File too small: %s\n", filename);
+ fclose (inputFile);
+ return -1;
+ }
+
+ memory = g_malloc (inputFileSize);
+ if (fread (memory, 1, inputFileSize, inputFile) != inputFileSize)
+ {
+ g_set_error (error, G_FILE_ERROR, 0, "Failed to read %zu bytes: %s\n",
+ inputFileSize, filename);
+ fclose (inputFile);
+ g_free (memory);
+ return -1;
+ }
+
+ fclose (inputFile);
+
+ signature = JxlSignatureCheck (memory, inputFileSize);
+ if (signature != JXL_SIG_CODESTREAM && signature != JXL_SIG_CONTAINER)
+ {
+ g_set_error (error, G_FILE_ERROR, 0,
+ "File %s is probably not in JXL format!\n", filename);
+ g_free (memory);
+ return -1;
+ }
+
+ decoder = JxlDecoderCreate (NULL);
+ if (! decoder)
+ {
+ g_set_error (error, G_FILE_ERROR, 0, "ERROR: JxlDecoderCreate failed");
+ g_free (memory);
+ return -1;
+ }
+
+ num_worker_threads = g_get_num_processors ();
+ if (num_worker_threads > 16)
+ {
+ num_worker_threads = 16;
+ }
+ runner = JxlThreadParallelRunnerCreate (NULL, num_worker_threads);
+ if (JxlDecoderSetParallelRunner (decoder, JxlThreadParallelRunner, runner) != JXL_DEC_SUCCESS)
+ {
+ g_set_error (error, G_FILE_ERROR, 0, "ERROR: JxlDecoderSetParallelRunner failed");
+ JxlThreadParallelRunnerDestroy (runner);
+ JxlDecoderDestroy (decoder);
+ g_free (memory);
+ return -1;
+ }
+
+ if (JxlDecoderSetInput (decoder, memory, inputFileSize) != JXL_DEC_SUCCESS)
+ {
+ g_set_error (error, G_FILE_ERROR, 0, "ERROR: JxlDecoderSetInput failed");
+ JxlThreadParallelRunnerDestroy (runner);
+ JxlDecoderDestroy (decoder);
+ g_free (memory);
+ return -1;
+ }
+
+ if (JxlDecoderSubscribeEvents (decoder, JXL_DEC_BASIC_INFO | JXL_DEC_COLOR_ENCODING | JXL_DEC_FULL_IMAGE)
+ != JXL_DEC_SUCCESS)
+ {
+ g_set_error (error, G_FILE_ERROR, 0, "ERROR: JxlDecoderSubscribeEvents failed");
+ JxlThreadParallelRunnerDestroy (runner);
+ JxlDecoderDestroy (decoder);
+ g_free (memory);
+ return -1;
+ }
+
+ status = JxlDecoderProcessInput (decoder);
+ if (status == JXL_DEC_ERROR)
+ {
+ g_set_error (error, G_FILE_ERROR, 0, "ERROR: JXL decoding failed");
+ JxlThreadParallelRunnerDestroy (runner);
+ JxlDecoderDestroy (decoder);
+ g_free (memory);
+ return -1;
+ }
+
+ if (status == JXL_DEC_NEED_MORE_INPUT)
+ {
+ g_set_error (error, G_FILE_ERROR, 0, "ERROR: JXL data incomplete");
+ JxlThreadParallelRunnerDestroy (runner);
+ JxlDecoderDestroy (decoder);
+ g_free (memory);
+ return -1;
+ }
+
+ status = JxlDecoderGetBasicInfo (decoder, &basicinfo);
+ if (status != JXL_DEC_SUCCESS)
+ {
+ g_set_error (error, G_FILE_ERROR, 0, "ERROR: JXL basic info not available");
+ JxlThreadParallelRunnerDestroy (runner);
+ JxlDecoderDestroy (decoder);
+ g_free (memory);
+ return -1;
+ }
+
+ if (basicinfo.xsize == 0 || basicinfo.ysize == 0)
+ {
+ g_set_error (error, G_FILE_ERROR, 0, "ERROR: JXL image has zero dimensions");
+ JxlThreadParallelRunnerDestroy (runner);
+ JxlDecoderDestroy (decoder);
+ g_free (memory);
+ return -1;
+ }
+
+ status = JxlDecoderProcessInput (decoder);
+ if (status != JXL_DEC_COLOR_ENCODING)
+ {
+ g_set_error (error, G_FILE_ERROR, 0,
+ "Unexpected event %d instead of JXL_DEC_COLOR_ENCODING", status);
+ JxlThreadParallelRunnerDestroy (runner);
+ JxlDecoderDestroy (decoder);
+ g_free (memory);
+ return -1;
+ }
+
+ if (basicinfo.uses_original_profile == JXL_FALSE)
+ {
+ if (basicinfo.num_color_channels == 3)
+ {
+ JxlColorEncodingSetToSRGB (&color_encoding, JXL_FALSE);
+ JxlDecoderSetPreferredColorProfile (decoder, &color_encoding);
+ }
+ else if (basicinfo.num_color_channels == 1)
+ {
+ JxlColorEncodingSetToSRGB (&color_encoding, JXL_TRUE);
+ JxlDecoderSetPreferredColorProfile (decoder, &color_encoding);
+ }
+ }
+
+ pixel_format.endianness = JXL_NATIVE_ENDIAN;
+ pixel_format.align = 0;
+
+ if (basicinfo.uses_original_profile == JXL_FALSE || basicinfo.bits_per_sample > 16)
+ {
+ pixel_format.data_type = JXL_TYPE_FLOAT;
+ channel_depth = 4;
+ precision_linear = GIMP_PRECISION_FLOAT_LINEAR;
+ precision_non_linear = GIMP_PRECISION_FLOAT_GAMMA;
+ }
+ else if (basicinfo.bits_per_sample <= 8)
+ {
+ pixel_format.data_type = JXL_TYPE_UINT8;
+ channel_depth = 1;
+ precision_linear = GIMP_PRECISION_U8_LINEAR;
+ precision_non_linear = GIMP_PRECISION_U8_GAMMA;
+ }
+ else
+ {
+ pixel_format.data_type = JXL_TYPE_UINT16;
+ channel_depth = 2;
+ precision_linear = GIMP_PRECISION_U16_LINEAR;
+ precision_non_linear = GIMP_PRECISION_U16_GAMMA;
+ }
+
+ if (basicinfo.num_color_channels == 1) /* grayscale */
+ {
+ if (basicinfo.alpha_bits > 0)
+ {
+ pixel_format.num_channels = 2;
+ }
+ else
+ {
+ pixel_format.num_channels = 1;
+ }
+ }
+ else /* RGB */
+ {
+
+ if (basicinfo.alpha_bits > 0) /* RGB with alpha */
+ {
+ pixel_format.num_channels = 4;
+ }
+ else /* RGB no alpha */
+ {
+ pixel_format.num_channels = 3;
+ }
+ }
+
+ result_size = channel_depth * pixel_format.num_channels
+ * (size_t) basicinfo.xsize * (size_t) basicinfo.ysize;
+
+ if (JxlDecoderGetColorAsEncodedProfile (decoder, &pixel_format,
+ JXL_COLOR_PROFILE_TARGET_DATA,
+ &color_encoding) == JXL_DEC_SUCCESS)
+ {
+ if (color_encoding.white_point == JXL_WHITE_POINT_D65)
+ {
+ switch (color_encoding.transfer_function)
+ {
+ case JXL_TRANSFER_FUNCTION_LINEAR:
+ loadlinear = TRUE;
+
+ switch (color_encoding.color_space)
+ {
+ case JXL_COLOR_SPACE_RGB:
+ profile = gimp_color_profile_new_rgb_srgb_linear ();
+ break;
+ case JXL_COLOR_SPACE_GRAY:
+ profile = gimp_color_profile_new_d65_gray_linear ();
+ break;
+ default:
+ break;
+ }
+ break;
+ case JXL_TRANSFER_FUNCTION_SRGB:
+ switch (color_encoding.color_space)
+ {
+ case JXL_COLOR_SPACE_RGB:
+ profile = gimp_color_profile_new_rgb_srgb ();
+ break;
+ case JXL_COLOR_SPACE_GRAY:
+ profile = gimp_color_profile_new_d65_gray_srgb_trc ();
+ break;
+ default:
+ break;
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ }
+
+ if (! profile)
+ {
+ if (JxlDecoderGetICCProfileSize (decoder, &pixel_format,
+ JXL_COLOR_PROFILE_TARGET_DATA,
+ &icc_size) == JXL_DEC_SUCCESS)
+ {
+ if (icc_size > 0)
+ {
+ gpointer raw_icc_profile = g_malloc (icc_size);
+
+ if (JxlDecoderGetColorAsICCProfile (decoder, &pixel_format, JXL_COLOR_PROFILE_TARGET_DATA,
+ raw_icc_profile, icc_size)
+ == JXL_DEC_SUCCESS)
+ {
+ profile = gimp_color_profile_new_from_icc_profile (raw_icc_profile,
+ icc_size, error);
+ if (profile)
+ {
+ loadlinear = gimp_color_profile_is_linear (profile);
+ }
+ else
+ {
+ g_printerr ("%s: Failed to read ICC profile: %s\n",
+ G_STRFUNC, (*error)->message);
+ g_clear_error (error);
+ }
+ }
+ else
+ {
+ g_printerr ("Failed to obtain data from JPEG XL decoder");
+ }
+
+ g_free (raw_icc_profile);
+ }
+ else
+ {
+ g_printerr ("Empty ICC data");
+ }
+ }
+ else
+ {
+ g_message ("no ICC, other color profile");
+ }
+ }
+
+ status = JxlDecoderProcessInput (decoder);
+ if (status != JXL_DEC_NEED_IMAGE_OUT_BUFFER)
+ {
+ g_set_error (error, G_FILE_ERROR,
+ 0, "Unexpected event %d instead of JXL_DEC_NEED_IMAGE_OUT_BUFFER", status);
+ if (profile)
+ {
+ g_object_unref (profile);
+ }
+ JxlThreadParallelRunnerDestroy (runner);
+ JxlDecoderDestroy (decoder);
+ g_free (memory);
+ return -1;
+ }
+
+ picture_buffer = g_try_malloc (result_size);
+ if (! picture_buffer)
+ {
+ g_set_error (error, G_FILE_ERROR, 0, "Memory could not be allocated.");
+ if (profile)
+ {
+ g_object_unref (profile);
+ }
+ JxlThreadParallelRunnerDestroy (runner);
+ JxlDecoderDestroy (decoder);
+ g_free (memory);
+ return -1;
+ }
+
+ if (JxlDecoderSetImageOutBuffer (decoder, &pixel_format, picture_buffer, result_size) != JXL_DEC_SUCCESS)
+ {
+ g_set_error (error, G_FILE_ERROR, 0, "ERROR: JxlDecoderSetImageOutBuffer failed");
+ if (profile)
+ {
+ g_object_unref (profile);
+ }
+ JxlThreadParallelRunnerDestroy (runner);
+ JxlDecoderDestroy (decoder);
+ g_free (memory);
+ return -1;
+ }
+
+ status = JxlDecoderProcessInput (decoder);
+ if (status != JXL_DEC_FULL_IMAGE)
+ {
+ g_set_error (error, G_FILE_ERROR, 0,
+ "Unexpected event %d instead of JXL_DEC_FULL_IMAGE", status);
+ g_free (picture_buffer);
+ if (profile)
+ {
+ g_object_unref (profile);
+ }
+ JxlThreadParallelRunnerDestroy (runner);
+ JxlDecoderDestroy (decoder);
+ g_free (memory);
+ return -1;
+ }
+
+ if (basicinfo.num_color_channels == 1) /* grayscale */
+ {
+ image = gimp_image_new_with_precision (basicinfo.xsize, basicinfo.ysize, GIMP_GRAY,
+ loadlinear ? precision_linear : precision_non_linear);
+
+ if (profile)
+ {
+ if (gimp_color_profile_is_gray (profile))
+ {
+ gimp_image_set_color_profile (image, profile);
+ }
+ }
+
+ layer = gimp_layer_new (image, "Background", basicinfo.xsize, basicinfo.ysize,
+ (basicinfo.alpha_bits > 0) ? GIMP_GRAYA_IMAGE : GIMP_GRAY_IMAGE,
+ 100, gimp_image_get_default_new_layer_mode (image));
+ }
+ else /* RGB */
+ {
+ image = gimp_image_new_with_precision (basicinfo.xsize, basicinfo.ysize, GIMP_RGB,
+ loadlinear ? precision_linear : precision_non_linear);
+
+ if (profile)
+ {
+ if (gimp_color_profile_is_rgb (profile))
+ {
+ gimp_image_set_color_profile (image, profile);
+ }
+ }
+
+ layer = gimp_layer_new (image, "Background", basicinfo.xsize, basicinfo.ysize,
+ (basicinfo.alpha_bits > 0) ? GIMP_RGBA_IMAGE : GIMP_RGB_IMAGE,
+ 100, gimp_image_get_default_new_layer_mode (image));
+ }
+
+ gimp_image_insert_layer (image, layer, -1, 0);
+
+ buffer = gimp_drawable_get_buffer (layer);
+
+ gegl_buffer_set (buffer, GEGL_RECTANGLE (0, 0, basicinfo.xsize, basicinfo.ysize),
+ 0, NULL, picture_buffer, GEGL_AUTO_ROWSTRIDE);
+
+ g_object_unref (buffer);
+
+ g_free (picture_buffer);
+ if (profile)
+ {
+ g_object_unref (profile);
+ }
+ JxlThreadParallelRunnerDestroy (runner);
+ JxlDecoderDestroy (decoder);
+ g_free (memory);
+ return image;
+}
+
+static void
+run (const gchar *name,
+ gint nparams,
+ const GimpParam *param,
+ gint *nreturn_vals,
+ GimpParam **return_vals)
+{
+ static GimpParam values[6];
+ GimpRunMode run_mode;
+ GimpPDBStatusType status = GIMP_PDB_SUCCESS;
+ gint32 image_ID;
+ GError *error = NULL;
+
+ run_mode = param[0].data.d_int32;
+
+ INIT_I18N ();
+ gegl_init (NULL, NULL);
+
+ *nreturn_vals = 1;
+ *return_vals = values;
+ values[0].type = GIMP_PDB_STATUS;
+ values[0].data.d_status = GIMP_PDB_EXECUTION_ERROR;
+
+ if (strcmp (name, LOAD_PROC) == 0)
+ {
+ switch (run_mode)
+ {
+ case GIMP_RUN_INTERACTIVE:
+ case GIMP_RUN_WITH_LAST_VALS:
+ gimp_ui_init (PLUG_IN_BINARY, FALSE);
+ break;
+ default:
+ break;
+ }
+
+ image_ID = load_image (param[1].data.d_string, &error);
+
+ if (image_ID != -1)
+ {
+ *nreturn_vals = 2;
+ values[1].type = GIMP_PDB_IMAGE;
+ values[1].data.d_image = image_ID;
+ }
+ else
+ {
+ status = GIMP_PDB_EXECUTION_ERROR;
+ }
+ }
+ else
+ {
+ status = GIMP_PDB_CALLING_ERROR;
+ }
+
+ if (status != GIMP_PDB_SUCCESS && error)
+ {
+ *nreturn_vals = 2;
+ values[1].type = GIMP_PDB_STRING;
+ values[1].data.d_string = error->message;
+ }
+
+ values[0].data.d_status = status;
+}
diff --git a/plug-ins/common/gimprc.common b/plug-ins/common/gimprc.common
index 96d04b6dfb..e8cbbd1947 100644
--- a/plug-ins/common/gimprc.common
+++ b/plug-ins/common/gimprc.common
@@ -38,6 +38,7 @@ file_header_RC = file-header.rc.o
file_heif_RC = file-heif.rc.o
file_html_table_RC = file-html-table.rc.o
file_jp2_load_RC = file-jp2-load.rc.o
+file_jpegxl_RC = file-jpegxl.rc.o
file_mng_RC = file-mng.rc.o
file_pat_RC = file-pat.rc.o
file_pcx_RC = file-pcx.rc.o
diff --git a/plug-ins/common/plugin-defs.pl b/plug-ins/common/plugin-defs.pl
index 488970ce29..b9d84d7ffa 100644
--- a/plug-ins/common/plugin-defs.pl
+++ b/plug-ins/common/plugin-defs.pl
@@ -36,9 +36,10 @@
'file-gih' => { ui => 1, gegl => 1 },
'file-glob' => {},
'file-header' => { ui => 1, gegl => 1 },
- 'file-heif' => { ui => 1, optional => 1, gegl => 1, libs => 'LIBHEIF_LIBS', cflags => 'LIBHEIF_CFLAGS' },
+ 'file-heif' => { ui => 1, optional => 1, gegl => 1, libdep => 'GEXIV2:LCMS', libs => 'LIBHEIF_LIBS',
cflags => 'LIBHEIF_CFLAGS' },
'file-html-table' => { ui => 1, gegl => 1 },
'file-jp2-load' => { ui => 1, optional => 1, gegl => 1, libs => 'OPENJPEG_LIBS', cflags =>
'OPENJPEG_CFLAGS' },
+ 'file-jpegxl' => { ui => 1, optional => 1, gegl => 1, libdep => 'JXL:JXL_THREADS', cflags =>
'JXL_CFLAGS' },
'file-mng' => { ui => 1, gegl => 1, optional => 1, libs => 'MNG_LIBS', cflags => 'MNG_CFLAGS' },
'file-pat' => { ui => 1, gegl => 1 },
'file-pcx' => { ui => 1, gegl => 1 },
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]