mirror of
https://gitlab.gnome.org/GNOME/gimp.git
synced 2025-10-06 01:12:40 +02:00
plug-ins: new JPEG export option to value file size over encoding speed.
This uses MozJPEG from Mozilla and is dependent on this patch to be merged: https://github.com/mozilla/mozjpeg/pull/383 This is an optional option (standard libjpeg API, e.g. with jpeg-turbo, is still used when MozJPEG is not detected at build time). When using MozJPEG, we have access to both the standard algorithm used by libjpeg-turbo, since MozJPEG is a patched version of libjpeg-turbo, and their own encoding algorithm. We can switch from one to another with a single call. Here is what the maintainer says about MozJPEG goal: > The point of MozJPEG is to improve quality/filesize ratio. It's a win-win: you > get better quality for the same file size, or better file size for the same > quality, or both. There is no downside in either quality or file size. MozJPEG > tunes for these two aspects over speed. libjpeg-turbo's maintainer values speed > over the other two variables. > > MozJPEG has a few techniques. Improved splitting of progressive scans gives > smaller file size while being 100% visually identical with libjpeg-turbo. > > But MozJPEG also has trellis quantization and tuned quantization tables that > give better visual quality, but on a microscopic scale they make different > choices than libjpeg-turbo, so some pixels differ. The differences are > relatively small and predictable, so there's no risk of unexpectedly ruining > an image (especially that on average, you get better quality). Cf. https://github.com/mozilla/mozjpeg/issues/382#issuecomment-730544796 Note that after several testing, I could indeed confirm that it seems to always produce smaller files (as far as my testing went) for similarly looking quality, but the speed cost can actually be quite important: on my computer, for some random files where encoding would take 0.7 second, it took 3.5 secs with mozjpeg; for much bigger file (~25MiB) where export with jpeg-turbo takes about 3.9 secs, it takes 30+ seconds with MozJPEG which is a huge difference and can be very frustrating. For small files only, this is less of a problem (I still timed an important difference, but from 0.05 to 0.15 secs is actually bearable). This is why this cannot be an option checked by default. About naming: I hesitated to call it "Export for Web" because it's clearly one of the big use cases (optimizing file size for images on websites), but I just decided to go with a much more explicit name (even though it may resonate less that the basic "Export for Web" which everyone asks for).
This commit is contained in:
@@ -667,7 +667,13 @@ libtiff = dependency('libtiff-4', version: '>=' + libtiff_minver)
|
||||
MIMEtypes += 'image/tiff'
|
||||
|
||||
|
||||
libjpeg = dependency('libjpeg')
|
||||
mozjpeg = dependency('mozjpeg', required: get_option('mozjpeg'))
|
||||
if mozjpeg.found()
|
||||
libjpeg = mozjpeg
|
||||
else
|
||||
libjpeg = dependency('libjpeg')
|
||||
endif
|
||||
conf.set('HAVE_MOZJPEG', mozjpeg.found())
|
||||
MIMEtypes += 'image/jpeg'
|
||||
|
||||
|
||||
@@ -1952,6 +1958,7 @@ final_message = [
|
||||
''' Detailed backtraces: @0@'''.format(detailed_backtraces),
|
||||
''' Binary symlinks: @0@'''.format(enable_default_bin),
|
||||
''' OpenMP: @0@'''.format(have_openmp),
|
||||
''' MozJPEG: @0@'''.format(mozjpeg.found()),
|
||||
'',
|
||||
'''Optional Plug-Ins:''',
|
||||
''' Ascii Art: @0@'''.format(libaa.found()),
|
||||
|
@@ -44,6 +44,7 @@ option('ilbm', type: 'feature', value: 'auto', description: 'Amiga
|
||||
option('jpeg2000', type: 'feature', value: 'auto', description: 'Jpeg-2000 support')
|
||||
option('jpeg-xl', type: 'feature', value: 'auto', description: 'JPEG XL support')
|
||||
option('mng', type: 'feature', value: 'auto', description: 'Mng support')
|
||||
option('mozjpeg', type: 'feature', value: 'auto', description: 'Build JPEG support with mozjpeg specifically')
|
||||
option('openexr', type: 'feature', value: 'auto', description: 'Openexr support')
|
||||
option('openmp', type: 'feature', value: 'auto', description: 'OpenMP support')
|
||||
option('print', type: 'boolean', value: true, description: 'Print support')
|
||||
|
@@ -198,6 +198,7 @@ save_image (GFile *file,
|
||||
GimpImage *image,
|
||||
GimpDrawable *drawable,
|
||||
GimpImage *orig_image,
|
||||
GimpRunMode run_mode,
|
||||
gboolean preview,
|
||||
GError **error)
|
||||
{
|
||||
@@ -236,6 +237,7 @@ save_image (GFile *file,
|
||||
gint orig_num_quant_tables = -1;
|
||||
gboolean use_arithmetic_coding = FALSE;
|
||||
gboolean use_restart = FALSE;
|
||||
gboolean mozjpeg = FALSE;
|
||||
gchar *comment;
|
||||
|
||||
g_object_get (config,
|
||||
@@ -248,6 +250,7 @@ save_image (GFile *file,
|
||||
"baseline", &baseline,
|
||||
"restart", &restart,
|
||||
"dct", &dct,
|
||||
"use-mozjpeg", &mozjpeg,
|
||||
|
||||
/* Original quality settings. */
|
||||
"use-original-quality", &use_orig_quality,
|
||||
@@ -262,6 +265,16 @@ save_image (GFile *file,
|
||||
|
||||
NULL);
|
||||
|
||||
if (run_mode == GIMP_RUN_NONINTERACTIVE && mozjpeg)
|
||||
{
|
||||
#ifndef HAVE_MOZJPEG
|
||||
g_set_error_literal (error, GIMP_PLUG_IN_ERROR, 0,
|
||||
_("GIMP was not compiled with MozJPEG. "
|
||||
"The argument 'use-mozjpeg' cannot be set to TRUE."));
|
||||
return FALSE;
|
||||
#endif
|
||||
}
|
||||
|
||||
quality = (gint) (dquality * 100.0 + 0.5);
|
||||
|
||||
drawable_type = gimp_drawable_type (drawable);
|
||||
@@ -489,6 +502,13 @@ save_image (GFile *file,
|
||||
drawable_type == GIMP_RGBA_IMAGE)
|
||||
? JCS_RGB : JCS_GRAYSCALE;
|
||||
}
|
||||
|
||||
#ifdef HAVE_MOZJPEG
|
||||
if (! mozjpeg)
|
||||
/* Disable mozjpeg code path (upstream jpeg-turbo normal algorithm). */
|
||||
jpeg_c_set_int_param (&cinfo, JINT_COMPRESS_PROFILE, JCP_FASTEST);
|
||||
#endif
|
||||
|
||||
/* Now use the library's routine to set default compression parameters.
|
||||
* (You must set at least cinfo.in_color_space before calling this,
|
||||
* since the defaults depend on the source color space.)
|
||||
@@ -795,6 +815,7 @@ make_preview (GimpProcedureConfig *config)
|
||||
preview_image,
|
||||
drawable_global,
|
||||
orig_image_global,
|
||||
GIMP_RUN_NONINTERACTIVE,
|
||||
TRUE, NULL);
|
||||
|
||||
g_object_unref (file);
|
||||
@@ -995,6 +1016,9 @@ save_dialog (GimpProcedure *procedure,
|
||||
"restart-frame",
|
||||
"sub-sampling",
|
||||
"dct",
|
||||
#ifdef HAVE_MOZJPEG
|
||||
"use-mozjpeg",
|
||||
#endif
|
||||
NULL);
|
||||
gimp_procedure_dialog_fill_frame (GIMP_PROCEDURE_DIALOG (dialog),
|
||||
"advanced-frame", "advanced-title", FALSE,
|
||||
|
@@ -24,10 +24,11 @@ extern GimpDrawable *drawable_global;
|
||||
|
||||
|
||||
gboolean save_image (GFile *file,
|
||||
GimpProcedureConfig *config,
|
||||
GimpProcedureConfig *config,
|
||||
GimpImage *image,
|
||||
GimpDrawable *drawable,
|
||||
GimpImage *orig_image,
|
||||
GimpRunMode run_mode,
|
||||
gboolean preview,
|
||||
GError **error);
|
||||
gboolean save_dialog (GimpProcedure *procedure,
|
||||
|
@@ -301,6 +301,11 @@ jpeg_create_procedure (GimpPlugIn *plug_in,
|
||||
_("Use restart mar_kers"),
|
||||
NULL, FALSE,
|
||||
G_PARAM_READWRITE);
|
||||
GIMP_PROC_AUX_ARG_BOOLEAN (procedure, "use-mozjpeg",
|
||||
_("Value file size over encoding speed (using MozJPEG)"),
|
||||
_("Use MozJPEG optimizations for better quality/filesize ratio, with slower encoding."),
|
||||
FALSE,
|
||||
G_PARAM_READWRITE);
|
||||
|
||||
gimp_save_procedure_set_support_exif (GIMP_SAVE_PROCEDURE (procedure), TRUE);
|
||||
gimp_save_procedure_set_support_iptc (GIMP_SAVE_PROCEDURE (procedure), TRUE);
|
||||
@@ -597,8 +602,8 @@ jpeg_save (GimpProcedure *procedure,
|
||||
if (status == GIMP_PDB_SUCCESS)
|
||||
{
|
||||
if (! save_image (file, config,
|
||||
image, drawables[0], orig_image, FALSE,
|
||||
&error))
|
||||
image, drawables[0], orig_image,
|
||||
run_mode, FALSE, &error))
|
||||
{
|
||||
status = GIMP_PDB_EXECUTION_ERROR;
|
||||
}
|
||||
|
Reference in New Issue
Block a user