As raised on social networks, the big label grows the horizontal size of
the dialog. Make the label wrappable and give it a smaller wanted size
(otherwise, just making it wrappable is not enough and the dialog is
still too big when first appearing, because of how GTK handles such
widgets :-/).
Actually I realized that using BigTIFF is not the only valid alternative
here. We can also try to use a better compression algorithm (or any if
"None" were selected) and try again to export as ClassicTIFF.
So don't check the option ourselves and don't set it insensitive. Let
one choose fully what they prefer to do.
… because we reached max TIFF size.
We detect the specific TIFF error (by string comparison so it's a bit
weak IMO yet it doesn't seem like libtiff provides anything better;
let's trust they don't change their error strings), then we reopen the
export dialog, pre-checking the BigTIFF checkbox newly created (and
making it insensitive). We still fail with error if an error happens the
second time (even for the same error).
Recent libtiff supports loading BigTiff automatically so we didn't have
anything to do there (as long as a recent libtiff was used). For
creating a BigTIFF though, we simply needed to add a "8" flag to
TIFFOpen/TIFFClientOpen when creating a new image (i.e. using "w8"
mode) as explained here in the "Implementation Strategy" section:
http://www.simplesystems.org/libtiff/BigTIFFProposal.html
What this commit does:
- Explicitly bump our libtiff requirement to version 4.0.0 or higher
(which is where BigTiff support appeared).
libtiff 4.0.0 was apparently released on 2011-12-22 and is available
on all current distributions, so it's probably not a problem.
- Switch to detect libtiff with a pkg-config test (added in libtiff
commit faf5f3eb before 4.0.0 release, so it's fine) instead of
function checks.
(Note: meson was already detecting for libtiff-4 with pkg-config,
which was obviously wrong since it should have mimicked autotools, but
well… then changes were minimal on meson)
- Add a new "bigtiff" boolean argument to the "file-tiff-save" PDB
procedure, FALSE by default. I set this as the first argument as I
figure that choosing the format you want is quite a major choice.
Unless I misunderstood something, since BigTIFF is really designed to
be an evolution of TIFF with a "minimum change strategy", i.e. mostly
using 64-bit instead of 32-bit offsets, everything which is possible
in TIFF will be in BigTIFF (and oppositely as well, except of course
having huge files) so there is no need to have 2 separate procedures.
- Adding this new argument to the GUI dialog as a checkbox.
- Tweak the load and export procedures' documentation strings to make
clear we support both TIFF and BigTIFF.
Note: interestingly there doesn't seem to be a separate mimetype for
BigTIFF so nothing to update on this side.
- Tweak the procedure labels too to mention BigTIFF. Since BigTIFF is
still a different format (though very closely resembling) from TIFF,
unlike some others which are just extensions embedded in a TIFF file
(like GeoTIFF we recently added), I figure it deserves to be
explicitly cited.
Since we increased our minimum version of gexiv2 to 0.12.3, several
functions used in the metadata-viewer plug-in have been deprecated.
Replace these functions with the "try_" versions, which include an
error parameter. If this returns non NULL then we print the error
message to the console.
The default for color properties (GimpRGB) is now to be editable. So
let's remove the formerly specific call for this.
Also fixing a clashing mnemonics ('c' both for '_Color' and '_Cancel').
Let's sync with the proposal in !571 after discussing with Jacob. The
shorter naming is fine and the '-info' suffix feels a bit redundant
anyway. Also since this arg never even existed in GIMP 2.10 (until !571
which is soon to be merged), there is really not even a historical
reason.
GLib has a specific type of NULL-terminated string arrays:
`G_TYPE_STRV`, which is the `GType` of `char**` aka `GStrv`.
By using this type, we can avoid having a `GimpStringArray` which is a
bit cumbersome to use for both the C API, as well as bindings. By using
`GStrv`, we allow other languages to pass on string lists as they are
used to, while the bindings will make sure to do the right thing.
In the end, it makes the API a little bit simpler for everyone, and
reduces confusion for people who are used to working with string arrays
in other C/GLib based code (and not having 2 different types to denote
the same thing).
Related: https://gitlab.gnome.org/GNOME/gimp/-/issues/5919
MR !565 was only a partial implementation as it was assuming all cursors
had the same hot spot coordinates in the file, which is false more often
than not (since usually it's several sizes for the same image, hence
coordinates move). I should have realized this before merging.
With this new commit, we actually loads the hot spot coordinates per
cursor, stores them as per-layer parasites, then exports with per-cursor
coordinates.
Also it makes the procedure API use int32 array (should be int16 but we
removed the support, now I think it may have been a mistake) which shows
the ugliness of our array support once again with additional size args
per array (even if it's the same size). Also I realize that our support
of arrays with config object is not good. This is also something we'll
have to look at.
- Fix return value in error case: s/GObject.Error/GLib.Error/ and anyway
in this form, the error should be a string. Using the easier form
procedure.new_return_values() instead.
- "file-png-load" uses a GFile now (like all load procedures).
This is the same issue as with IM000001.dcm mentioned in issue #313.
There are two problems: incorrect endian conversion for 16 bits per pixel,
and not handling photometric interpretation "MONOCHROME1", which means
minimum value is white instead of black.
The endian conversion was fixed as suggested in issue #313.
For "MONOCHROME1" we added a variable bw_inverted and we invert the pixel
value if that variable is true.
Exporting an image to TGA fails with a crash when it's an indexed image
with alpha channel. We were not taking into account that even though
the output is 1 byte per pixel, the input should allocate memory for
2 bytes per pixel (1 color index and 1 alpha channel).
There is no change for lossless images, where import precision
is directly related to bits_per_sample.
However, according JXL developers, for lossy images
(which generally use XYB color space), decoded data are not tightly
bound to bits_per_sample from header, import in 32bit
float precision can be used for better import quality
(libjxl works internally in 32bit float precision).
JPEG XL plug-in always imported all JXL images
in 32-bit float precision in the past.
Now it also supports direct import in 8-bit
and 16-bit integer precision too.
It was calling plug-in-gradmap with old single-layer API hence failing.
Also replacing all calls to (gimp-image-set-active-layer) and
(gimp-image-get-active-layer) in this file with
(gimp-image-set-selected-layers) and (gimp-image-get-selected-layers)
respectively.
This is an official way to declare these plug-ins as now
unmaintained/deprecated.
Relevant plug-ins are:
1) help-browser (Displaying the docs): nowadays every desktop machine
has a browser. Let's just use whatever is the person's default
browser.
2) web-page (Web screenshot): it looks to me like every browser has this
feature by default now (I use it all the time in Firefox to get a
full-page screenshot, never in GIMP), even on mobile, I am told. It's
nice to have it in GIMP too, but not like absolutely necessary.
On the other hand:
1. It's a hell to build, with a lot of issues. We have regular issues on
our Flatpak-s. We don't manage to build it on our CI (only locally
apparently). Also it takes a crazy amount of time (like 90% of CI
build-time would be webkit).
2. From what I gather, new versions don't work on Windows anymore. Even
MSYS2 seems to have dropped the ball and don't try anymore.
Basically we would have a feature disparity from GIMP 3.0 (most
platform but Windows). We don't know when it will be resolved (if
ever) as it's been like this for years.
Now why we are keeping the code around instead of just removing
everything is that the topic tree in the help browser is useful and
comfortable to use. Ideally we should get some equivalent to help
browsing the help efficiently in the web docs as well (so basically
menus, web search and alike?). So I am told to keep the code around at
least for now to see if we can figure something out or improve the
situation.
Except for this point, we can consider the WebkitGTK plug-ins as
deprecated from GIMP 3.0 on.
On recent KDE, the screenshot plug-in fails with an authorization error,
unless we add a desktop file with a special KDE-only desktop entry to
give the permission, which seems a bit over-the-top (if we were to add a
desktop file for every plug-in, and with dedicated entries to every
desktop environment out there, it's never-ending). Of course, we are not
against either, but nobody has contributed a patch doing this in the
last year anyway.
Also Méven (KDE dev) was telling us that KDE recommends to use the
Freedesktop portal nowadays. So maybe let's just move on from the
KDE-specific portal, just as we did recently for the GNOME portal too.
This should hopefully take care of all permission issues and in the same
time simplifies the code.
Note that the Freedesktop API might miss some of the features (this was
one of the reason we were avoiding putting it as priority implementation
until now, to avoid feature regression), but the more we go, the less we
have a choice. It's either this or always fighting against the current.
When a channel is selected as bumpmap, the bump_format can be different
than it was before. However, we always kept the first bump_format, which
could be RGB, in which case trying to use it with a channel caused a
crash in GIMP.
To fix this we always update the bump_format if bumpmap is enabled.
… rather than generic "gegl:load" and "gegl:save".
In particular, it means using "gegl:rgbe-load|save" for RGBE images and
"gegl:exr-save" for EXR exporting.
Without this, we could encounter weird run cases where for instance, we
would detect a RGBE image through the file magic number in GIMP,
redirect the load to file-gegl, but "gegl:load" only relies on file
extension. So if the file extension was not ".hdr", "gegl:load" could
redirect to a different handler operation meant for another format,
hence break proper loading. If no extension was matched, it could even
redirect to a fallback handler, such as Image Magick.
This breaks loading or saving images which we would be otherwise able to
load/save. And it could also have some security implications. So let's
fix this by setting the accurate operations to use for each specific
file formats we want to support through the file-gegl plug-in.
Note that the full magic should be "#?RADIANCE". Not sure why we only
use the first 2 characters. Do some software create these RGBE files
with just "#?" and we want to be able to read these? No other image
format use these 2 characters as the start of their own magic numbers?
Anyway let's keep like this for now. We'll see. If it makes a problem,
we might update to more accurate magic later.
Together with the previous commit this mostly fixes#5438.
PhotoShop handles clipping layers in a different way than GIMP. The only
way to have it look the same is by adding extra layer groups.
PSD layers that have clipping set, combined with the first non clipping
layer below it are grouped together in a new layer group.
Doing this results in the same image as the PSD merged image unless there
are other PSD elements in play that we don't handle yet.
See e.g. the NSFW image in the mentioned issue where the purple hair color
is a little darker than the merged image.
Certain PSD layers have a flag called clipping set to 1. We were not
handling this flag and had some reports about colors bleeding where
they were not supposed to.
We are going to set GIMP's layer composite_mode to
GIMP_LAYER_COMPOSITE_CLIP_TO_BACKDROP, which is the closest we can get
to PhotoShop's clipping. With this, the colors won't bleed anymore.
This isn't the whole solution since PS apparently stops compositing when
it encounters a layer without clipping set, while GIMP doesn't stop until
it reaches the bottom layer of a group or the image.
This is the first part of a fix for issue #5438.
… portal.
Otherwise, it first takes a screenshot and proposes to either share or
tweak the "Options" (in the GNOME shell implementation at least). Doing
the other way around is much more in line with how we had done it until
now with our custom dialogs.
GNOME Shell has started restricting access for it's Screenshot D-Bus API
to internal components only [1] for security reasons. In other words,
this will start failing, so remove it in favor of just using the
freedesktop portal, which should always work.
[1]: https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1970
This proved to be both an import and export issue.
Our import set expected format as RGB, causing garbled image output.
Our export for indexed images converted to grayscale first, although the
palette was correctly saved. This caused wrong palette indexes on import.
For indexed images, on import, we request the actual indexed format after
creating the layer with gimp_drawable_get_format, which gives us a correct
indexed Babl format.
Also added logic for indexed with alpha, although I have no sample images
to test this.
For indexed images on export we do the same: use gimp_drawable_get_format
to get an actual indexed Babl format.
Although there was code to load 32-bit per channel psd images. It is
unlikely that it ever worked, because:
- We tried to load them as u32 instead of float.
- While we did some decoding of the zip predictor data, for float values
we also need to restore the byte order from 111222333 to 123123123.
- We did the endian conversion first while it should be done on the
restored values.
With these things fixed I can load the few samples I have.
Due to starting with the highest index we were referencing layer data
out of bounds.
We need to decrease i with 1 before using it as index into the channel data
for the correct layer.
This caused a crash when exporting multi layer images.
psd-save was using a separate define for enabling debugging. Let's just
use the one define from psd.h.
IFDBG -> IFDBG(1)
IF_DEEP_DBG -> IFDBG(3)
Besides changing the define in psd-save we also change all the printf
statements used for debug output to g_debug. This allows us to view/hide
the debug output.
Handling of PSD merged images with alpha channel but where merged
transparency is not used is complicated.
We check the alpha_names resource for the presence of 'Transparency'. If
that is present, assume we have an alpha channel.
In case of a CMYKA PSD with layers the merged image actually is RGB with
the first three channels representing RGB and the Alpha in the fifth
channel. In this case we move the alpha data to the forth channel so
we can handle it as RGBA.
PSD images using CMYK as color mode and without layers didn't load
correctly (wrong colors).
When a PSD does not have any layers, CMYK color mode was not converted to
RGB.
Note that PSD color images that do have layers (e.g. CMYK and LAB) store
the merged image as RGB!
To do all this we added a conversion for CMYK PSD with 0 layers and added
code to correctly determine whether an alpha channel exists.
This also fixes the case where loading the merged image of a 16 bit per
channel RGBA psd loads with the alpha channel opaque.
Our psd plug-in checks for valid layer mask sizes. Apparently a psd
layer mask where the rendered flag is set can have invalid dimensions
0, 0, 0, -1.
We will skip the sanity checks for rendered layers and at the same time
move the debug statements up to have relevant debug info available even
if our sanity checks stop further processing.
libheif uses rav1e encoder by default to encode AVIF. However,
performance of AOM encoder got improved significantly, so
I think it is wiser to give preference to AOM, when both
AOM and Rav1e encoders are available.
Name of the used encoder is printed during export,
It can be: aom, rav1e, x265
Detected issues fixed here:
- Use GString and g_string_append since otherwise we need to add g_free
after every g_strconcat.
- No error checking.
- We need to g_free value_utf.
Not detected by coverity:
- Wrong quotes around utf-8.
- Remove unused includes.
Several resource leaks here were detected by coverity:
- Not freeing value_utf.
- Strings returned by g_strconcat should be g_free'd. To handle the string
concatenations easier we use GString and g_string_append instead.
Also introduce function get_list_elements to reduce the number of
repetetive elements.
While we were at it, also remove unused includes.
When writing metadata in the metadata-editor it did not check for empty
values. In combination with gexiv2 0.14.0 (which doesn't check in this
specific case for an empty list of gchar **) and trying to set a non
repeatable Iptc tag (Iptc.Application2.Headline) using
gexiv2_metadata_set_tag_multiple we get a crash.
This fix checks first for a non empty value before trying to save the
metadata tag.
Since the code is very similar also implemented this check for the Xmp
tags in addition to the Iptc and simplified some duplicate code.
See issue #7408 where this is causing a crash when using gexiv 0.14.0
in combination with trying to save it as a multiple tag with an empty list.
According to https://exiv2.org/iptc.html the tag Iptc.Application2.Headline
is not repeatable so we will set mode to "single.
In addition to that I added comments to explain the differences in the
meaning of "single" and "multi" between the list of Xmp tags and Iptc tags.
I had completely forgotten about Coverity Scan but today received an
email with some new scan results. This was one of the warnings that we
had a possible resource leak.
In truth, this is mostly a false positive since gimp_export_image() will
flatten the image. Yet why not be thorough…
Just like COLOR targa MAPPED (indexed) images with a size of 32 per
index should also have alphaBits set to 8 or else the images get
loaded incorrectly.
Loading of the merged image of a PSD was broken as mentioned by Massimo
in MR !476.
Instead of reverting the commit as suggested, we check first if loading
a merged image is requested. In case of an error we add a debug
message and then remove the error without stopping on it.
… multiple drawables as parameter.
Previous commit 7bb892f3 was "making it work" by making the API
inconsistent and also only using the first drawable, which is making the
logics meaningless.
Instead accept multiple drawables, and export only the selected drawable
(when alone) or the merged-down image containing only the selected
drawables (when many).
Note that in current implementation, this is not useful from GUI calls
because the fully merged image is always exported when run interactively
or with last vals (i.e. from the GUI) because gimp_export_image()
flattens the image. So this change would only work when called
non-interactively from other plug-ins. In such a case, multi-layer
images do no longer return an error and whatever items are selected
would change the export result.
See also #7370 for a discussion about how to handle the selected items
during export (because currently the `drawables` parameter of
GimpSaveProcedure's run function is clearly a mostly bogus parameter).
We currently cannot call gimp_pdb_run_procedure() for procedures
containing arrays because this C-type doesn't contain the size
information (which is in a second parameter but since the rule is not
hard-coded, our API can't know this).
See issue #7369.
strlcpy() only copies the specified number of bytes, but it also iterates over
the input string in order to return its length. We only populate the first
6 bytes of buf - the rest is uninitialised - hence strlcpy() will iterate
past the 3 bytes that we're trying to compare, and will only return after
reading an effectively random number of bytes (which could well be beyond
the end of buf). Since we ignore strlcpy()'s return value, program flow
is generally not affected (unless we hit a segfault I guess, which is unlikely
because we do 0-initialize some of our stack variables, meaning strlcpy() is
unlikely to go far). However, this iteration is wasteful, and triggers
complaints from code sanitizers.
Therefore we remove the strlcpy,() and switch to doing a strncmp() on just the
3 bytes that we care about (similar to what is done for the "GIF" check above).
This change has the nice benefit of avoiding an unneeded copy.
An example implementation of strlcpy can be found in glib, here's the line
where it iterates until the first NULL byte:
f763f2b7cb/glib/gstrfuncs.c (L1484)
See also ASAN output from when this was discovered below:
ERROR: AddressSanitizer: stack-buffer-overflow on address 0x7ffc776e03d0 at pc 0x7f909b615ba2 bp 0x7ffc776e0370 sp 0x7ffc776e0368
READ of size 1 at 0x7ffc776e03d0 thread T0
#0 0x7f909b615ba1 in g_strlcpy /home/ahunt/git/glib/_build/../glib/gstrfuncs.c:1484:14
#1 0x55dc5c in load_image /home/ahunt/git/gimp/plug-ins/common/file-gif-load.c:419:3
#2 0x561f20 in LLVMFuzzerTestOneInput /home/ahunt/git/gimp/plug-ins/common/file-gif-load_fuzzer.c:79:17
#3 0x460e44 in fuzzer::Fuzzer::ExecuteCallback(unsigned char const*, unsigned long) /home/abuild/rpmbuild/BUILD/llvm-12.0.0.src/build/../projects/compiler-rt/lib/fuzzer/FuzzerLoop.cpp:599:15
#4 0x46034a in fuzzer::Fuzzer::RunOne(unsigned char const*, unsigned long, bool, fuzzer::InputInfo*, bool, bool*) /home/abuild/rpmbuild/BUILD/llvm-12.0.0.src/build/../projects/compiler-rt/lib/fuzzer/FuzzerLoop.cpp:505:3
#5 0x462067 in fuzzer::Fuzzer::MutateAndTestOne() /home/abuild/rpmbuild/BUILD/llvm-12.0.0.src/build/../projects/compiler-rt/lib/fuzzer/FuzzerLoop.cpp:745:19
#6 0x462bf5 in fuzzer::Fuzzer::Loop(std::__Fuzzer::vector<fuzzer::SizedFile, fuzzer::fuzzer_allocator<fuzzer::SizedFile> >&) /home/abuild/rpmbuild/BUILD/llvm-12.0.0.src/build/../projects/compiler-rt/lib/fuzzer/FuzzerLoop.cpp:883:5
#7 0x450ea6 in fuzzer::FuzzerDriver(int*, char***, int (*)(unsigned char const*, unsigned long)) /home/abuild/rpmbuild/BUILD/llvm-12.0.0.src/build/../projects/compiler-rt/lib/fuzzer/FuzzerDriver.cpp:906:6
#8 0x47ae82 in main /home/abuild/rpmbuild/BUILD/llvm-12.0.0.src/build/../projects/compiler-rt/lib/fuzzer/FuzzerMain.cpp:20:10
#9 0x7f909a564349 in __libc_start_main (/lib64/libc.so.6+0x24349)
#10 0x424259 in _start /home/abuild/rpmbuild/BUILD/glibc-2.26/csu/../sysdeps/x86_64/start.S:120
Address 0x7ffc776e03d0 is located in stack of thread T0 at offset 48 in frame
#0 0x55d89f in load_image /home/ahunt/git/gimp/plug-ins/common/file-gif-load.c:375
This frame has 6 object(s):
[32, 48) 'buf' (line 378) <== Memory access at offset 48 overflows this variable
[64, 65) 'c' (line 379)
[80, 848) 'localColorMap' (line 380)
[976, 980) 'grayScale' (line 381)
[992, 996) 'version' (line 385)
[1008, 1016) 'image' (line 386)
HINT: this may be a false positive if your program uses some custom stack unwind mechanism, swapcontext or vfork
(longjmp and C++ exceptions *are* supported)
SUMMARY: AddressSanitizer: stack-buffer-overflow /home/ahunt/git/glib/_build/../glib/gstrfuncs.c:1484:14 in g_strlcpy
Shadow bytes around the buggy address:
0x10000eed4020: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x10000eed4030: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x10000eed4040: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x10000eed4050: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x10000eed4060: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
=>0x10000eed4070: 00 00 00 00 f1 f1 f1 f1 00 00[f2]f2 01 f2 00 00
0x10000eed4080: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x10000eed4090: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x10000eed40a0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x10000eed40b0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x10000eed40c0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
Shadow byte legend (one shadow byte represents 8 application bytes):
Addressable: 00
Partially addressable: 01 02 03 04 05 06 07
Heap left redzone: fa
Freed heap region: fd
Stack left redzone: f1
Stack mid redzone: f2
Stack right redzone: f3
Stack after return: f5
Stack use after scope: f8
Global redzone: f9
Global init order: f6
Poisoned by user: f7
Container overflow: fc
Array cookie: ac
Intra object redzone: bb
ASan internal: fe
Left alloca redzone: ca
Right alloca redzone: cb
Shadow gap: cc
==15243==ABORTING
This is untested on my side, because the bug only happens on native
builds with meson (our CI has cross-builds with meson and native builds
with autotools and I only do cross-builds locally) but I think/hope it
will work.
Basically we were using .full_path() because these rc files were also
used as input of some configure_file() calls which doesn't like custom
target objects as input (it wants strings or file objects). Yet a bug
in meson didn't like the colon used in native Windows full paths ('C:'
and such) when used in windows.compile_resources(). This has been fixed
by Luca Bacci in: https://github.com/mesonbuild/meson/pull/9368
Yet we just cannot depend on very early meson (or worse dev meson code).
On the other hand, if the input is a custom_tgt object, it uses the
object ID which we give as first parameter of custom_target() so we know
it's appropriately named without colons (such as 'gimp_plugins_rc').
Thus we should not bump into this issue again.
For the few usage in configure_file(), I just add a .full_path() only
when needed at call time.
Last but not least, I replace the bogus `meson --version` call by a
`python3 -c 'exit()'` as advised by Eli Schwartz:
2afa019c70 (note_1284951)
The reason is that it is apparently possible (or will be when some
reimplementation of meson will be done) that the `meson` executable
itself does not exist. On the other hand, `python3` should always be
there, as a mandatory dependency of the build tool.
In order to use an appropriate `python3`, I made the
pythonmod.find_installation() check required in our build (which should
not be a problem since it's a meson requirement as well), even when the
-Dpython option is false (this one depends on other requirements too
anyway, such as version and pygobject). This way I can call this meson
variable of discovered python in my bogus call, instead of calling a
(potentially different) python from PATH environment.
These warnings only happens on debug output, so it's not huge bugs, yet
it's always better not to have warnings at build time.
Most are printf format type warnings, and one is because of uncomplete
switch() cases.
While doing this cleanup, I found at least several other string leaks
in: file-compressor, file-gegl, file-pdf-save, file-raw-data, file-xwd,
jpeg-load, psd-save…
So it's quite worth it!
Note: in file-pdf-save, there is a global variable file_name which seems
to be happily leaked without caring (didn't look in details, but looks
so). I didn't fix this one which will require a bit more in-depth logics
care.
As explained in previous commits, the _peek_ call is advantageous
because:
- It is less bug-prone as we don't have to handle freeing the string. In
all the cases I changed, I even spotted at least 2 cases where we were
leaking a string (in file-mng, `temp_file_name` is never freed; and we
were also leaking in an error case of gfig).
- As a consequence of the previous point: simpler code with less lines.
- In local file cases, the _peek_ variant does not even need to allocate
an additional string.
- In other case, if we query several times the path, it is allocated
once and cached so it stays efficient.
- When possible, working on the GFile rather than on a path string may
be more robust. For instance I changed one g_unlink() into a
g_file_delete(). Actually most reading/writing should be done with the
GIO API when possible, but I didn't want to change too much code
logics on this commit.
- use g_file_peek_path() instead of g_file_get_path() in various places.
Less prone to memory management bugs (not forgetting to free in all
cases). Also it is often more efficient, especially for local files
where the _peek_ variant does not even need to allocate any memory as
path is already hanging around (and local files are the most common
use cases, I believe!).
- Also gets rid of one GFile creation with g_file_new_for_path() from
the path returned from another GFile! We can just use the same GFile
as it is not freed and perfectly usable.
Freeing the path immediately could lead to a free-after-use error as we
used it for an error message when the file pointer failed to be created,
as reported by Massimo (thanks again!).
Using g_file_peek_path() has also other advantages, such as being less
error-prone, but also possibly more efficient. First looking at the
implementation, for local files, we already have the path around, so no
additional memory allocation even needs to happen. As for the generic
code path, it would still allocate a new string, yet cache it and reuse
it when needed later. This makes the _peek_ call much better for quick
peek-use-discard usage.
- .gitignore and gimprc.common updated by manually running ./mkgen.pl.
- Coding style fixes in file-jpegxl:
* function names go to the line by themselves (return type on previous
line).
* avoid some overlong lines by breaking lines between parameters.
* fix some alignments.
XMP array tags of type BAG and SEQ can have multiple values, each of
which is on a separate line. However, we were reading and saving it as
just one value.
We change this by setting each line as a separate value with
gexiv2_metadata_set_tag_multiple.
In addition to that we found that setting the type of tag struct with
gexiv2_metadata_set_xmp_tag_struct caused arrays of multiple values per
tag to be set incorrectly: the last value in the list got added multiple
times. I'm not sure if we are using this function incorrectly, or that
there is a bug in gexiv2 or exiv2. Anyway, since it seems that all tags
and values I tested work without calling this function, let's just omit
this call.
XMP array tags of type BAG and SEQ can have multiple values, each of these
values needs to be on a separate line to be correctly recognized as a
different value in the tag array. We were incorrectly loading all values
on one line separated by a comma.
For those tags that have equivalent IPTC tags we were also comparing just
the one XMP value with the whole, possibly multiple lines, of the same
IPTC, which could cause a failure to recognize identical tags.
We changed this to now have each value in a tag array on a separate line
by adding \n between values.
Each IPTC equivalent tag value is now compared to each value in the XMP
tag array and only added when a different value is found.
XMP tags that have multiple values (usually of type XMpBag or XmpSeq) were
shown on one line. Which, especially for long text values, could make it
difficult to see the separate values for that tag.
Let's do the same as we do for IPTC tags that can occur multiple times and
show each value on a separate line.
In the metadata-viewer refactor the code that adds multiple values per tag
to the list store into a separate function.
Currently used for IPTC tags only but the intention is to reuse it for
XMP tags with multiple values.
If you first open a multi page TIFF, exiv2 generates EXIF tags for the
first 3 pages in the form of Exif.Image.<tags>, Exif.Image2.<tags>,
Exif.Image3.<tags>. When exporting with EXIF saving enabled, exiv2 thinks
it needs to save TIFF pages for the EXIF metadata of the second and third
page too. Those pages saved by exiv2 contain only metadata no real image
data and give warnings when loading.
The EXIF tags read from page 2 and 3 are only the basic image specs. We
don't use those, nor do we add tags to it. Until we support handling of
metadata for those pages and exiv2 has better support for all TIFF pages
beyond the first few, I see no reason to save this information.
So for now lets just delete all tags that start with Exif.Image followed
by a number.
On Windows there is a long standing issue in its File Explorer. When
GIMP exported as a multi page (multi-layer) TIFF with thumbnail saving
enabled, then the Windows thumbnailer apparently gets stuck and does not
close the TIFF file when browsing a folder. Because those files are not
closed it is impossible to delete them. This issue has been reported
many times over the years to Microsoft without any reaction.
Investigation showed us that this lock up only happens when we save the
thumbnail as a subifd. To resolve this issue we change this and now let
exiv2 handle our thumbnail saving, just as for other image formats. For
TIFF this means the thumbnail is saved as the second page of a TIFF.
Previous commits have made sure that it is now easier to recognize a TIFF
page as a thumbnail and to make sure we don't load thumbnail TIFF pages.
Since saving as a subifd is what made TIFF thumbnail saving different
from other formats, this commit consists of only removal of code.
TIFF image pages can specify what type of image that page represents.
If the page is marked as FILETYPE_REDUCEDIMAGE we will consider it to be
a thumbnail and filter that out of the list of pages that can be selected
to be loaded.
In addition to that we will try to recognize certain pages as thumbnail
that don't have the subfiletype tag set.
We will consider it a thumbnail if:
- It's the second page
- PhotometricInterpretation is YCbCr
- Compression is old style jpeg
- First page uses a different compression or PhotometricInterpretation
If these conditions are true the page will also be filtered out.
We could consider having an option whether to filter out thumbnail pages.
Since in the situation up until now we also don't load thumbnails, I think
this should be considered as a separate feature.
Since it appeared with GLib 2.68.0, we could not change this until we
bumped the dependency which has only become possible a few days ago
(since Debian testing is our baseline for dependency bumps). Cf.
previous commit.
As this is a drop-in replacement (just a guint parameter changed to
gsize to avoid integer overflow), search-and-replace with:
> sed -i 's/g_memdup\>/g_memdup2/g' `grep -rIl 'g_memdup\>' *`
… followed by a few manual alignment tweaks when necessary.
This gets rid of the many deprecation warnings which we had lately when
building with a recent GLib version.
After the change that allows multiple layers to be selected exporting to
a pattern fails.
Patch this as suggested by Lloyd Konneker by doing the same as for brushes:
do not allow multiple layers, instead only send the first drawable.
Due to differences between Windows and most other platforms Ghostscript
didn't correctly load files with special characters on Windows.
First we needed to make sure that the filenames we use are in utf-8
format and then tell gsapi that we use utf8 encoding.
When exporting to bmp using a script or plug-in we could not set the
parameters use-rle, write-color-space-info, and rgb-format when used
non-interactively.
This is discussed in issue #491. The patch there does not work for master,
so I came up with this.
When exporting a C source file with runtime length encoding, the
C-string's array size does not accomodate for the null byte. However,
GIMP accomodates for the NULL byte in it's NON-RLE export, suggesting
that this has been a mere oversight for RLE.
This can cause at the worst a compile-time error and at least a warning
from the compiler.
For 1-bit BMP export we did not show the save dialog, making it
impossible to change settings interactively.
We enable the save dialog for 1-bit too, making sure to disable RLE, which
is not available for 1-bit.
In addition, also set the RLE config option to false for all cases where
it can't be used.
… GimpUi.ProcedureDialog.new()
The old way is still working and acceptable as far as I am concerned.
Just switching to the recommended (by upstream) syntax to show it works
as expected and as a good example of code.
Our plug-in was not correctly handling DICOM images that use big endian
transfer syntax, which is deprecated.
We add support for that here, add a few g_debug statements to make future
debugging easier, and also return an error when we encounter a transfer
syntax that we can't handle instead of blindly continuing.
… source colors
Reviewer's (Jehan) note: a git blame shows this is a clear bug
introduced in commit 9d19bf2a3e, which was a cleanup patch, and the
BOUNDS() macro was not doing exactly the same thing as the code before
the change.
Added an option for exporting thumbnail in WebP Export dialogbox.
Additionally, introduced a function gimp_procedure_dialog_fill_expander.
The function is similar to gimp_procedure_dialog_fill_frame but allows
adding GtkExpander instead of GtkFrame.
I must have not been awake yet when I pushed the
fix for #6116 because it has two problems:
- Updating cur_progress caused by not editing the
for loop after a copy/paste, found thanks to
Stanislav Grinkov.
- Not using the correct drawable to determine the
drawable_type which I noticed while fixing the
above issue.
These issues are not present in the backported
version for 2.10.
GIF export was not taking into account that there can be
both grayscale layers with and without alpha in an image.
We make sure that the GEGL buffer knows the type of
drawable for the current layer.
We were loading 16-bit per sample SGI images as 8-bit
integer images even though we have had support for
16-bit integer for a long time now.
Changed to use 16-bit integer encoding now. Saw
this request a while ago on the gimp user mailing list.
Instead of only checking for the layer resources Lr16 and Lr32 make it
a loop and use the generic get_layer_resource_header to read all
resources.
We still need to figure out at a later time how to best handle these
resources.
For PSB images certain resources have 64-bit lengths.
Let's handle this transparently by adding a psd_version
parameter and depending on that and the type of
resource we decide if the length to read is 32 or 64-bit.
We also return the total header size. This way the
calling function can use that to determine the
remaining length.
Because we needed to check the signature when
loading the header we remove that check from
the load_layer_resource function since that
would be redundant.
Apparently layer height or width can be negative for certain
PSD layers that have the irrelevant flag set.
We move those checks down until after we have read that
flag and only validate if the irrelevant flag is not set.
Since the 1-bit conversion debug statements causes a huge amount
of info which can cause slowdowns when loading do it only when
explicitly setting it to IFDBG(4).
In certain places in a PSB file we need to read 64-bit
lengths where in a PSD we read a 32-bit length.
To make handling this easier we add a function that
determines if we need to read 4 or 8 bytes and
also handles converting the value from big endian.
Even though the current specs say max is 56 there
are sample files with more channels. Since there is
no reason why we can't handle more let's increase
the maximum to 99 for now.
Not taking a non zero length into consideration caused us to read from the
wrong location in certain cases and then fail loading.
Always use the specified length to go to the correct location. This is not
a guarantee that we will be able to correctly load the image but at least
we won't read wrong data from the wrong location.
Commit aba721ae68 fixed its intended bug but brought a new: each time
the preview was updated, a new display was created. This fixes this new
bug. Hopefully it's good now!
in Gimp and Photoshop- "Too many channels in layer: 4907"
To be better able to handle 64 bit offsets we switch to
using GInputStream/GOutputStream and its related
functions instead of using FILE functions like fseek.
In addition we changed several offsets and sizes to
64 bit instead of 32 bit to correctly handle large
image sizes and offsets.
I should probably have split this out in two parts
(the move to GInput/OutputStream, and the
changing to 64 bit variables) but don't feel like
it's worth the trouble at this point.
Exporting to psd could result in very large files which often failed to
load in both GIMP and PS when a group layer with a layer mask
was present.
Reported on our IRC channel with a sample xcf which made it
possible to figure out the problem.
The port had a slight error, because in gimp-2-10, the display_ID
actually had 3 states: 0 when gimp_export_image() kept the original
image to which we just add a preview layer, -1 when it created a new
image which we wanted to put in its own display, and the display ID
itself when created.
With the new API where display variable is an object, we can only have 2
cases. So I create an additional variable separate_display to make the
distinction.
So far all dds images were loaded as 8 bit per channel which makes
sense for most but not all dds formats.
This commit implements loading in 16 bit for "L16" - a 16 bit
luminance channel.
In addition to that we improve security a bit by not assuming
that L16 is the only left over case but instead explicitly
checking the correct value of rmask for L16.
For other cases we now set an error with enough details
to identify the type of DDS image that needs extra
handling.
When a selection exists, we are copying then pasting the selection
contents. In particular, with multi-layer selection, it means pasting a
merged result of the selected layers (like a sample merged but limited
to selected layers).
Yet when no selection exists, with a single layer selected, a cut in
particular would remove the layer fully, then a paste would copy it
elsewhere (in the same image or even on a different image). This was
still working, but not with multiple layers. This is now fixed and we
can now copy/cut then paste several layers (without merge), which is
sometimes a very practical way to move layers (sometimes simpler than
drag'n drop, especially between images).
As a consequence, the PDB function gimp_edit_paste() now also returns an
array of layers (not a single layer).
Let's increase the default size of the metadata viewer a bit.
Ideally we would add some logic to determine the width of
the first column since that one currently depends on the
length of the longest tag. However for now this change
will be enough for most cases.
The round corners script was assuming that the drawable always
was a layer, which is incorrect when a layer mask is selected.
We fix this by always requesting the active layer instead of
active drawable.
We also enable this script for RGB and GRAY with alpha
channel. Although it might not always make sense to
use this script when an alpha channel is present, there
can be use cases where it is perfectly fine.
So let the designer decide if this script is suited or not
instead of GIMP making that judgement.
This fixes the following error when building for Windows:
> error: too many arguments to function ‘mkdir’
On Windows, mkdir() is deprecated, it is an alias for _mkdir() which
doesn't have a mode parameter. The GLib version duplicates the POSIX
signature and is cross-platform (mode is simply ignored on Windows).
Closes: GNOME/gimp#541
Reviewer note: thanks to Stanislav Grinkov for cleaning up and reworking
a bit the patch, such as renaming the procedure to dir-make, as per
Kevin Cozens' review.
Looking at the documentation it is indeed red that should go
in the lowest bits and blue in the highest bits so just
reverse our code for red and blue.
We also update the version of our GIMP DDS plug-in,
this way we can catch and correct RGB10A2 images
written by older versions of our plug-in and correct
them.
Fixes:
> Calling error for procedure 'gimp-brush-get-pixels':
> Brush 'Circle (03)' not found
The data/brushes/Circle-3.vbr brush doesn't exist since commit
7aa12175a4 in 2012 as far as I can see.
- Now using multi-drawable run() signature, but sensitive only with a
single drawable.
- width|height() calls are now get_width|height().
- PDB call to 'plug-in-sel2path' now expects a drawable array as well.
Since we renamed a bunch of functions for consistency (the like of
gimp_image_width() to gimp_image_get_width() and others), most Scheme
scripts ended up broken. This is a simple bash fix with `sed` to at
least take care of these simple renaming cases.
Many scripts are still broken for other reasons after our API evolution
(to be continued).
The following changes were made:
- run() signature now moved to multi-drawables.
- sensitivity mask now enables the plug-in when one or several drawables
are selected. When several, a fog layer will be created over each
selected layer.
- Mnemonics added to properties.
- Color property finally used now that our API has support for boxed
parameters with GimpRGB value type.
- Use a config object instead of ordered GimpValueArray and use the
begin|en_run() API to store values between runs.
- Add a graphical interface generated with the new GimpProcedureDialog
API.
We did port it to the new API but we are doubting it is useful at all.
It might have been, historically, when foreground extract algorithm was
first introduced, but probably not anymore, even more as the algorithm
is now implemented mostly on GEGL side anyway. So if any benchmark were
to be done, it should probably be added as GEGL tests.
Also as we are planning to update even more the API lately, it feels
really like a waste of time to also fix this plug-in while we currently
believe it to be useless.
Still we move it to the gimp-data-extras repository for being able to
easily bring it back in case we missed some use.
This is the same as what we did for #5357
but in the reverse situation. The reason
for not doing the same at that time was
because I wasn't sure if that was valid
in all cases.
Looking at the documentation it does seem
to be the right solution and is working for
the supplied example image.
In PNG, JPEG and TIFF export plug-ins which use the new API, use our new
function to set widget sensitivity.
Note that part of it is similar to commit 6a2910bd3b on `gimp-2-10`,
making "Save GeoTIFF data" checkbox insensitive when there are no such
data available (this feature was late on the main branch as we rushed
for 2.10.24 release).
The gimp_drawable_type() is an issue though as gimp_drawable_get_type()
is already defined as a common GObject API.
Though I'm actually wondering if GimpImageType is well called. Rather
than Type, shouldn't we go with ColorModel?
sed -i 's/\<gimp_drawable_bpp\>/gimp_drawable_get_bpp/g' "$@"
sed -i 's/\<gimp_drawable_width\>/gimp_drawable_get_width/g' "$@"
sed -i 's/\<gimp_drawable_height\>/gimp_drawable_get_height/g' "$@"
sed -i 's/\<gimp_drawable_offsets\>/gimp_drawable_get_offsets/g' "$@"
s/gimp_image_base_type/gimp_image_get_base_type/
s/gimp_image_width/gimp_image_get_width/
s/gimp_image_height/gimp_image_get_height/
Sorry plug-in developers, more porting work! But really this seems like
the right thing to do in order not to get stuck with inconsistent naming
for many more years to come.
Also ".sun" is a possible (and common) file name extension for Sun
Raster images, according to various sources and samples I found (these
samples with .sun extension also opened fine in GIMP, so it's not just a
subvariant which we may not handle or something of the sort). This one
is not so important though as we also register magic bytes for detection
(which is the proper way), but it can still be useful, mostly for
exporting (as we will direct to the SunRaster plug-in if someone tried
to export a file with .sun extension, since no other file format uses
this extension AFAICS).
There is no functional change, I just had a look at this plug-in while
handling !428 and realized this format was not present in the MimeType
list (which is used to generate the desktop file, in order to have
proper mime types, not detection based on extension only, unlike
Windows in !428).
The saved value for Iptc.Application2.Caption is copied from Xmp.dc.description.
However the last one is multiline but the former should be single line. This
caused only the first line to be saved instead of all lines.
To fix this we set Iptc.Application2.Caption to single and use a different
conversion based on whether the tags from Xmp and Iptc are both
multiline or whether Iptc is single line.
The qbist plug-in shows a grid of 9 patterns, it was not clear at all
which one will be applied. Also it looked like selecting a pattern would
make it disappear and loading a same file twice would not create the
same patterns (as said in commit 7fb696206e).
Actually the plug-in works fine, but it is simply not clear at all what
is happening until we look at the code. The center pattern is the main
one: the one which will be applied and the only one which will be stored
or loaded in/from a file if we decide to save the pattern. Also when
selecting a pattern, it does not disappear, it is moved to the center
(but you don't necessarily realize it, especially as several will look
the same). And the reason why you get different result when loading a
saved pattern is that it only reimports the center pattern; all others
are indeed randomized from this stable source.
So my fix is attempting to have this center pattern standing out a bit
more by framing it with a "Pattern" title. It's not perfect, and I'm not
very happy with this design, but I don't find a nice widget for better
framing the center pattern, nor do I want to spend too much time on
this. It's better than before at least.
While testing the metadata-editor I noticed that certain values for
ModelReleaseStatus and PropertyReleaseStatus were incorrectly
read back.
Apparently while copy pasting some values were forgotten to be
updated which caused incorrect values to be saved.
There probably are not many users of these metadata tags
since in all these years there hasn't been a bug report about this.
The metadata-editor allowed Iptc tags to be set if an empty string was
used contrary to Xmp tags. In the case of DateCreated this cause an
invalid date "0-00-00" to be written.
We added a check to only write text Iptc metadata if the value is
not empty.
Fixes issue #3656 Empty metadata tags are written to XCF at least.
Xmp.plus.ModelReleaseStatus and Xmp.iptcExt.DigitalSourceType are
defined as combo boxes with a fixed number of possible values.
However there was no option to leave it empty so there always was
a value written when saving metadata in the metadata-editor.
We added a "select value" as default option and only write
metadata if a different value was chosen.
As a bonus we replaced the fixed loop numbers with
the current actual number of defined choices.
Contents of these arrays are assumed to be limited to a specific range.
While it did work sometimes (because a further processing would randomly
regenerate some of the indexes and correctly limit the range), it often
crashed.
This commit fixes the crash, but I am not sure this plug-in is working
exactly as expected regarding data load/save. It feels like you would
expect to always get the same patterns with a same source data. Yet
there is further randomization going on.
Oppositely when saving data, and re-loading it later, I would expect
once again to get back the exact same patterns I had when saving the
data. So it would be a way to save the result of randomization (as
chances to get back a pattern one liked are slim by definition when it's
created randomly).
Right now, it doesn't behave at all like this. Files are only used as
some kind of random seed, not as a way to save/load patterns. I feel
this was not the purpose of the file handling here.
We need to work around an issue in Exiv2 that saving to /Iptc4xmpExt bag
records fails which seems related to it registering /iptcExt. Unregistering
that and registering the first one doesn't work.
See: https://gitlab.gnome.org/GNOME/gexiv2/-/issues/24
So let's use /iptcExt for saving even though it's the less common form
for now. When loading metadata we try to load the most common
form first and if that fails we will load /iptcExt.
Set Xmp.iptc.CreatorContactInfo/Iptc4xmpCore:* last since the short
form Xmp.iptc.Ci* could have been used to set this information too.
Becausethe first (longer) form is the most common let that override the
shorter form in the (unlikely) case that both are present and also have
different values.
Due to a bug in the metadata-editor previously only the short form
was saved.
Reordered the strings in artworkorobject to be in the same
order as the columns.
Add write_metadata_tag_multiple function that handles most
of the previously duplicated code and check for special
handling of phonetype when necessary by adding
an enum and a get_phonetype function.
Use a separate function that can be reused and also get rid of
the large output_data array and strcat without length
checking. We will use GString instead.
There was a lot of duplicate code based on
whether or not value was NULL with for
some tags partially unreachable code.
We combine the parts and only test
value for NULL where needed.
Also rename the typos in enum
COL_REGSITRY_* to
COL_REGISTRY_*
There's a lot of duplicate code for adding string values
to the gui (liststore). This is another part of trying
to reduce that.
Besides that the copying code uses fixed size arrays
without length checking as pointed out by flawfinder.
We will instead use a function add_to_store to add a
comma or semicolon separated list of values stored in
value to add rows with values to the gui.
Only count a broken line once and only stop after at
least 10 consecutive broken lines since older fax
images are known for having bad lines.
This enables loading the image in issues #475.
- Miniswhite and Minisblack TIFF images with bps 1, 2 and 4 were loaded as
indexed. We change this to grayscale since that's what they are.
- Fix not handling of miniswhite for 8 bps.
Fixes issue #1838 Tiff image display wrong (tiff tags not interpreted), black
line instead of white line.
Fixes issue #2680 Failure to load 4-bit grayscale TIFF layers.
Testing some fuzzed TIFF images from the imagetestsuite
revealed we should add some more checks for valid input
and function returns.
We now stop whenever the reported bps is above 64.
Even if it is valid we can't handle it anyway and I'm not
aware of any actual valid image like that.
Make sure the image dimensions are valid and in the range
that GIMP can handle.
Return directly when TIFFReadRGBAImage fails instead
of doing further processing and improve the error message.
Check result of TIFFReadTile and return if it fails.
Certain broken tiff fax images can cause a huge amount of warnings
which on Windows eventually causes GIMP to run out of resources
and then crash.
Since the avarage user won't have much use for these warnings
let's just only send them to stderr.
The PNG specs says:
> The cHRM chunk is allowed in all PNG datastreams, although it is of
little value for greyscale images.
Though it doesn't say it's completely useless though. So let's still
extract the info and give it to Little-CMS.
As for the gAMA chunk, it doesn't say it's not usable for grayscale
images.
Note that if one of the 2 values is not set, it will use default values
for sRGB (i.e. default simili-sRGB gamma or d65 whitepoint). Not sure if
this is totally right.
See also issue #6501.
- Store the Layer ID (lyid) block. Use GIMP's layer tattoo as a PSD
layer ID, hence mirroring PSD load processing (we were already reading
this block into our layer tattoos but always exporting with no ID).
- Add support for the Layer Selection ID(s) block (0x042D) both on
import and export in order to store and restore the multi-layer
selection.
We were previously using the Layer state information block (0x0400) to
store the active layer, but it doesn't seem to be usable for multiple
layer selection. Actually it is even doubtful if this was working fine
even for single layer selection but I can't be sure (I could only test
in non-Photoshop software available to me). So the new logics is:
* If more than 1 layer is selected, store only the Layer Selection
ID(s) block.
* If exactly 1 layer is selected, store both the Layer Selection ID(s)
and Layer state information blocks.
* Otherwise (no layers selected) do not store any of these blocks.