Sat, 07 Mar 2015

I needed to turn some small black-on-white icons to blue-on-white.
Simple task, right? Except, not really. If there are intermediate
colors that are not pure white or pure black -- which you can see
if you magnify the image a lot, like this 800% view of a 20x20 icon --
it gets trickier.

You can't use anything like
Color to Alpha or Bucket Fill, because all those grey antialiased
pixels will stay grey, as you see in the image at left.

And the Hue-Saturation dialog, so handy for changing the hue of a sky,
a car or a dress, does nothing at all -- because changing hue
has no effect when saturation is zero, as for black, grey or white.
So what can you do?

I fiddled with several options, but the best way I've found is the
Screen layer mode. It works like this:

In the Layers dialog, click the New Layer button and accept the
defaults. You'll get a new, empty layer.

Set the foreground color to your chosen color.

Drag the foreground color into the image, or do Edit->Fill with
FG Color.

Now it looks like your whole image is the new color. But don't panic!

Use the menu at the top of the Layers dialog to change the top layer's
mode to Screen.

Layer modes specify how to combine two layers. (For a lot more information,
see my book, Beginning GIMP).
Multiply mode, for example, multiplies each pixel in the two layers,
which makes light colors a lot more intense while not changing dark
colors very much.
Screen mode is sort of the opposite of Multiply mode: GIMP inverts
each of the layers, multiplies them together, then inverts them again.
All those white pixels in the image, when inverted, are black (a value
of zero), so multiplying them doesn't change anything. They'll still be
white when they're inverted back. But black pixels, in Screen mode,
take on the color of the other layer -- exactly what I needed here.

Intensify the effect with contrast

One place I use this Screen mode trick is with pencil sketches.
For example, I've made a lot of
sketches of Mars
over the years, like this sketch of Lacus Solis, the "Eye of Mars".
But it's always a little frustrating: Mars is all shades
of reddish orange and brown, not grey like a graphite pencil.

Adding an orange layer in Screen mode helps, but it has another problem:
it washes out the image. What I need is to intensify the image underneath:
increase the contrast, make the lights lighter and the darks darker.

Fortunately, all you need to do is bump up the contrast of the sketch
layer -- and you can do that while keeping the orange Screen layer in
place.

Just click on the sketch layer in the Layers dialog, then run
Colors->Brightness/Contrast...

This sketch needed the brightness reduced a lot, plus a little more
contrast, but every image will be different. Experiment!

Thu, 06 Nov 2014

The split between Save and Export that GIMP introduced in version 2.8
has been a matter of much controversy. It's been over two years now,
and people are still complaining on the gimp-users list.

Early on, I wrote a simple Python plug-in called
Save-Export
Clean, which saved over an image's current save or export filename
regardless of whether the filename was XCF (save) or a different format
(export). The idea was that you could bind Ctrl-S to the plug-in and
not be pestered by needing to remember whether it was XCF, JPG or what.

Save-Export Clean has been widely cited, and I hope it's helped some
people who were bothered by the Save/Export split. But personally I
didn't like it very much. It wasn't very flexible -- there was no
way to change the filename, for one thing, and it was awfully easy
to overwrite an original image without knowing that you'd done it.
I went back to using GIMP's separate Save and Export, but in the
back of my mind I was turning over ideas, trying to understand
my workflow and what I really wanted out of a GIMP Save plug-in.

The result of that was a new Python plug-in called Saver.
I first wrote it a year ago, but I've been tweaking it and using it
since then, with Ctrl-S bound to Saverand Ctrl-Shift-S bound to
Saver as...).
I wanted to make sure that it was useful and working reliably ...
and somehow I never got around to writing it
up and announcing it formally ... until now.

Saver, like Save/Export Clean, will overwrite your chosen filename,
whether XCF or another format, and will mark the image as saved so
GIMP won't pester you when you exit.

What's different? Mainly, three things:

A Saver as... option so you can change the filename
or file type.

Merges multiple layers so they'll show up properly in your
JPG or PNG image.

An option to save as .xcf or .xcf.gz and, at the same time, export
a copy in another format, possibly scaled down. So you can maintain
your multi-layer XCF image but also update the JPG copy that you're
going to put on the web.

I've been using Saver for nearly all my saving for the past year.
If I'm just making a quick edit of a JPEG camera image, Ctrl-S
overwrites it without questioning me. If I'm editing an elaborate
multi-layer GIMP project, Ctrl-S overwrites the .xcf.gz. If I'm
planning to export that image for the web, I Ctrl-Shift-S to bring
up the Saver As... dialog, make sure the main filename is
.xcf.gz, set a name (ending in .jpg) for the exported copy; and
from then on, Ctrl-S will save both the XCF and the JPG copy.

Fri, 13 Sep 2013

Someone on the gimp-developers list asked whether there was
documentation of GIMP's menu hooks.

I wasn't sure what they meant by "hooks", but GIMP menus do have
an interesting feature that plug-in writers should know about:
placeholders.

Placeholders let you group similar types of actions together.
For instance, iever notice that in the image window's File menu,
all the things that Open images are grouped together? There's Open,
Open as Layers..., Open Location... and Open Recent. And then
there's a group of Save actions all grouped together -- Save, Save
As..., Save a Copy... and so forth. That's because there's a
placeholder for Open in the File menu, and another placeholder
for Save.

When you write your own plug-ins, you can take advantage of these
placeholders. For instance, I want my Save/Export clean plug-in to
show up next to the other Save menu items, not somewhere else down
near the bottom of the menu -- so when I register it, I pass
menu = "<Image>/File/Save/" so GIMP knows to group
it with the other Save actions, even though it's directly in the File
menu, not a submenu called Save..

Pretty slick, huh? But how do you know what placeholders are available?

I took a look at the source.
In the menus/ subdirectory are all the menu definitions in XML,
and they're pretty straightforward.
In image-menu.xml you'll see things like
<placeholder name="Open">, <placeholder name="Save">

So to get a list of all the menu placeholders, you just need to
find all the "
grep '<placeholder' menus/*.xml

That's not actually so useful, though, because it doesn't tell you
what submenu contains the placeholder. For instance, Acquire is a
placeholder but you need to know that it's actually
File->Create->Acquire. So let's be a little more clever.

We want to see <menu lines as well as <placeholders,
but not <menuitem since those are just individual menu entries.
egrep ' will do that.
Then pass it through some sed expressions to clean up the output,
loop over all the XML files, and I ended up with:

It isn't perfect: a few lines still show up that
shouldn't -- but it'll get you the list you need. Fortunately the
GIMP developers are very good about things like code formatting,
so the identation of the file shows
which placeholder is inside which submenu.

I only found placeholders in the image window menu, plus a single
placeholder, "Outline", in the selection menu popup.
I'm a little confused about that menu file: it seems to duplicate
the existing Select menu in the image-menu.xml, except that
the placeholder items in question -- feather, sharpen, shrink, grow,
and border -- are in a placeholder called Outline in
selection-menu.xml, but in a placeholder called Modify
in image-menu.xml.

Anyway, here's the full list of placeholders, cleaned up for readability.
Placeholders are in bold and followed with an asterisk *.

Wed, 27 Feb 2013

I was printing out a map for a new trail we wanted to hike.
I wanted to fill the paper with the map -- Google maps' print and
Firefox's print, while fine for most map printing, weren't what I wanted.

So I took a screenshot of the maximized browser window with the map in it
and imported it into GIMP. In the Crop tool, I constrained Aspect-ratio
to 11:8.5 and cropped the image so it would just fit on a page, in
landscape format -- wider in east-west than in north-south.
Then I chose File->Print.

Since printing defaults to Portrait orientation,
I went to the Page Setup tab and changed Orientation to Landscape.
(It's so nice to have that as part of the dialog. I'm forever amazed
at how some apps, like Firefox, make you use a separate dialog first
to change the print's orientation.
How can anyone possibly see that as sensible UI design?)

Unfortunately, When I went to the Image Settings tab to check ,
I discovered that GIMP hadn't adjusted the image size when I changed
to Landscape. It had Width listed as 8.500, Height as 6.567, and the
image only took up part of the page.

I went to the Width field and replaced 8.500 with 11, and hit
Tab. Whoops! The field reverted to 8.500. The same thing happened
if I tried typing 8.5 into the Height field.

These fields aren't plain text entries -- they're "spin boxes", with
a text entry plus up and down arrows.
It turned out that under GIMP 2.8 and earlier, round-off errors sometimes
prevent you from setting a spin box's maximum value. I could type 10.999
and it would work fine, but 11 or 11.0 failed.

Of course, 10.999 would have been fine -- I don't mind a little margin
on a printed map. It's also trivial in GIMP to rotate a landscape photo
90 degrees and print it in portrait orientation. But by this point
I was into stubborn mode -- by gosh, I wanted a way to fix this!

The best workaround, it turns out, is to use the spin box's up-arrow.
Holding the mouse down over the up arrow will eventually get to the
maximum value. But there's a faster way: right-clicking
on the up-arrow goes straight to the maximum value. A nice trick!

The problem doesn't exist in GIMP 2.9 -- I reported it as
bug 694477,
and the awesome GIMP team fixed it very quickly.
The spin boxes work beautifully now. (Thanks, Mitch!)
But as long as 2.8 is around, or for any other app using spin boxes,
I'm glad to know about right-clicking on the spin box arrows.

Sun, 02 Sep 2012

In a discussion on Google+arising from my
Save/Export
clean plug-in, someone said to the world in general

PLEASE provide an option to select the size of the export. Having to
scale the XCF then export then throw out the result without saving is
really awkward.

I thought, What a good idea! Suppose you're editing a large image, with
layers and text and other jazz, saving in GIMP's native XCF format,
but you want to export a smaller version for the web. Every time you
make a significant change, you have to: Scale (remembering the scale
size or percentage you're targeting);
Save a Copy (or Export in GIMP 2.8);
then Undo the Scale.
If you forget the Undo, you're in deep trouble and might end up
overwriting the XCF original with a scaled-down version.

If I had a plug-in that would export to another file type (such
as JPG) with a scale factor, remembering that scale factor
so I didn't have to, it would save me both effort and risk.

And that sounded pretty easy to write,
using some of the tricks I'd learned from my Save/Export Clean
and wallpaper
scripts.
So I wrote export-scaled.py

It's still brand new, so if anyone tries it, I'd appreciate knowing
if it's useful or if you have any problems with it.

Geeky programming commentary

(Folks not interested in the programming details can stop reading now.)

Linked input fields

One fun project was writing a set of linked text entries for the dialog:

Scale to:

Percentage 100 %

Width: 640

Height: 480

Change any one of the three, and the other two change automatically.
There's no chain link between width and height:
It's assumed that if you're exporting a scaled copy, you won't want
to change the image's aspect ratio, so any one of the three is enough.

That turned out to be surprisingly hard to do with GTK SpinBoxes:
I had to read their values as strings and parse them,
because the numeric values kept snapping back
to their original values as soon as focus went to another field.

Image parasites

Another fun challenge was how to save the scale ratio, so the second
time you call up the plug-in on the same image it uses whatever values
you used the first time. If you're going to scale to 50%, you don't
want to have to type that in every time. And of course, you want it
to remember the exported file path, so you don't have to navigate
there every time.

For that, I used GIMP parasites: little arbitrary pieces of data you
can attach to any image. I've known about parasites for a long time,
but I'd never had occasion to use them in a Python plug-in before.
I was pleased to find that they were documented in the
official GIMP
Python documentation, and they worked just as documented.
It was easy to test them, too: in the Python console
(Filters->Python->Console...), type something like

Not prompting for JPG settings

My plug-in was almost done. But when I ran it and told it to save to
filenamecopy.jpg, it prompted me with that annoying JPEG
settings dialog.
Okay, being prompted once isn't so bad. But then
when I exported a second time, it prompted me again,
and didn't remember the values from before.
So the question was, what controls whether the settings dialog is
shown, and how could I prevent it?

Of course, I could prompt the user for JPEG quality, then call
jpeg-save-file directly -- but what if you want to export to PNG
or GIF or some other format? I needed something more general

Turns out, nobody really remembers how this works, and it's not
documented anywhere. Some people thought that passing
run_mode=RUN_WITH_LAST_VALS when I called
pdb.gimp_file_save() would do the trick, but it didn't help.

So I guessed that there might be a parasite that was storing those
settings: if the JPEG save plug-in sees the parasite, it uses those
values and doesn't prompt. Using the Python console technique I just
mentioned, I tried checking the parasites on a newly created image
and on an image read in from an existing JPG file, then saving each
one as JPG and checking the parasite list afterward.

Bingo! When you read in a JPG file, it has a parasite called
'jpeg-settings'. (The new image doesn't have this, naturally).
But after you write a file to JPG from within GIMP, it has not
only 'jpeg-settings' but also a second parasite, 'jpeg-save-options'.

So I made the plug-in check the scaled image after saving it,
looking for any parasites with names ending in either -settings
or -save-options; any such parasites are copied to the
original image. Then, the next time you invoke Export Scaled, it does
the same search, and copies those parasites to the scaled image before
calling gimp-file-save.

That darned invisible JPG settings dialog

One niggling annoyance remained.
The first time you get the JPG settings dialog, it
pops up invisibly, under the Export dialog you're using. So if
you didn't know to look for it by moving the dialog, you'd think the
plug-in had frozen. GIMP 2.6 had a bug where that happened every time
I saved, so I assumed there was nothing I can do about it.

GIMP 2.8 has fixed that bug -- yet it still happened
when my plug-in called gimp_file_save: the JPG dialog popped
up under the currently active dialog, at least under Openbox.

There isn't any way to pass window IDs through gimp_file_save so
the JPG dialog pops up as transient to a particular window. But a few
days after I wrote the export-scaled, I realized there was still
something I could do: hide the dialog when the user clicks Save.
Then make sure that I show it again if any errors occur during saving.

Of course, it wasn't quite that simple. Calling chooser.hide()
by itself does nothing, because X is asynchronous and things don't happen
in any predictable order. But it's possible to force X to sync the display:
chooser.get_display().sync().

I'm not sure how robust this is going to be -- but it seems to work well
in the testing I've done so far, and it's really nice to get that huge
GTK file chooser dialog out of the way as soon as possible.

Tue, 21 Aug 2012

In GIMP 2.8, the developers changed the way you save files. "Save" is
now used only for GIMP's native format, XCF (and compressed variants
like .xcf.gz and .xcf.bz2). Other formats that may lose information on
layers, fonts and other aspects of the edited image must be "Exported"
rather than saved.

This has caused much consternation and flameage on the gimp-user
mailing list, especially from people who use GIMP primarily for
simple edits to JPEG or PNG files.

I don't particularly like the new model myself. Sometimes I use GIMP
in the way the developers are encouraging, adding dozens of layers,
fonts, layer masks and other effects. Much more often, I use GIMP
to crop and rescale a handful of JPG photos I took with my camera on a hike.
While I found it easy enough to adapt to using
Ctrl-E (Export) instead of Ctrl-S (Save), it was annoying that when I
exited the app, I'd always get am "Unsaved images" warning, and it was
impossible to tell from the warning dialog which images were safely
exported and which might not have been saved or exported at all.

But flaming on the mailing lists, much as some people seem to enjoy it
(500 messages on the subject and still counting!)
wasn't the answer. The developers have stated very clearly that they're
not going to change the model back. So is there another solution?

Yes -- a very simple solution, in fact. Write a plug-in that saves or
exports the current image back to its current file name, then marks it
as clean so GIMP won't warn about it when you quit.

It turned out to be extremely easy to write, and you can get it here:
GIMP: Save/export
clean plug-in. If it suits your GIMP workflow, you can even
bind it to Ctrl-S ... or any other key you like.

Warning: I deliberately did not add any "Are you sure you want
to overwrite?" confirmation dialogs. This plug-in will overwrite
your current file, without asking for permission. After all, that's its
job. So be aware of that.

How it's written

Here are some details about how it works.
Non software geeks can skip the rest of this article.

When I first looked into writing this, I was amazed at how simple it was:
really just two lines of Python (plus the usual plug-in registration
boilerplate).

The first line saves the image back to its current filename.
(The gimp-file-save PDB call still handles all types, not just XCF.)
The second line marks the image as clean.

Both of those are PDB calls, which means that people who don't have
GIMP Python could write script-fu to do this part.

So why didn't I use script-fu? Because I quickly found that if I bound
the plug-in to Ctrl-S, I'd want to use it for new images -- images that
don't have a filename yet. And for that, you need to pop up some sort
of "Save as" dialog -- something Python can do easily, and Script-fu
can't do at all.

A Save-as dialog with smart directory default

I couldn't use the
standard GIMP save-as dialog: as far as I can tell, there's
no way to call that dialog from a plug-in.
But it turned out the GTK save-as dialog has no default directory to
start in: you have to set the starting directory every time. So I
needed a reasonable initial directory.

I didn't want to come up with some desktop twaddle like ~/My Pictures
or whatever -- is there really anyone that model fits? Certainly not me.
I debated maintaining a preference you could set, or saving the last
used directory as a preference, but that complicates things and I
wasn't sure it's really that helpful for most people anyway.

So I thought about where I usually want to save images in a GIMP session.
Usually, I want to save them to the same directory where I've been saving
other images in the same session, right?

I can figure that out by looping through all currently open images
with for img in gimp.image_list() : and checking
os.path.dirname(img.filename) for each one.
Keep track of how many times each directory is being used;
whichever is used the most times is probably where the user wants
to store the next image.

Keeping count in Python

Looping through is easy, but what's the cleanest, most Pythonic way
of maintaining the count for each directory and finding the most
popular one? Naturally, Python has a class for that,
collections.Counter.

Once I've counted everything, I can ask for the most common path.
The code looks a bit complicated because
most_common(1) returns a one-item list of a tuple of the single
most common path and the number of times it's been used -- for instance,
[ ('/home/akkana/public_html/images/birds', 5) ].
So the path is the first element of the first element, or
most_common(1)[0][0]. Put it together:

Wed, 13 Apr 2011

Are you a GIMP user or Summer of Code student who's been
wanting to get involved,
but having trouble building, or a bit intimidated by the build process?

I'll be running a session on IRC to help anyone build GIMP
on Linux, as part of the
OpenHatch "Build it"
project.

The session will take place on #gimp on irc.gimp.org (also known as
GimpNet), on Fri, Apr 15, 0300 UTC -- that's Thursday
night in the Americas. To convert to your time zone,
run this command on your local machine:

This is a time that's usually fairly quiet on #gimp -- European users
don't fret, since it's pretty
easy to get help there during more Europe-friendly time zones.
I'll hang around for at least two hours; that should be plenty of
time to build GIMP and all its prerequisites.

For folks new to IRC, note that irc.gimp.org is its own server --
this is not the #gimp channel on Freenode. You can learn more about
IRC on the LinuxChix IRC for
Beginners page, or, if you have trouble getting an IRC client
configured, try this link for
mibbit
web chat.

Note: The #gimp IRC channel was recently under attack by trolls,
and it's possible that it may not be usable at the time of the session.
In that case, I will update this blog page with the name of an
alternate channel to use, and any other necessarily details.

Preparation

If you want to get your system set up ahead of time, I've put the
instructions needed to build on Ubuntu Lucid and other older Linux
distros here:
Gimp Building
Tips (for Linux).
I might be able to offer a little help with building on Macs,
but no guarantees.

Mac and Windows users, or people running a very old Linux distro
(more than a year old) might want to consider an alternate approach:
install Virtualbox or
VMware and install Ubuntu "Natty
Narwhal" (currently still in beta) in a virtual machine.

Of course, this isn't the only time you can get help with building GIMP.
There are folks around on #gimp most of the time who are happy to
help with problems. But if you've been meaning to get started and
want a good excuse, or you've been holding off on asking for help ...
come hang out with us and try it!

Sat, 19 Feb 2011

A couple of people recently have appeared on GIMP IRC channels
wondering why no filters or layer operations seemed to work in GIMP,
even though they had an image open.

In at least one case, it was a setting most of us had forgotten about:
the Auto button. It's easy to miss, but if you turn it on accidentally,
you may be unable to do anything in GIMP until you realize what's happened.

The Auto button is the one at the upper right of your Layers dialog.
It's on by default, and what it does is ensure that dialogs like Layers,
and GIMP's notion of the currently active layer, follow the active image.
Open a new image, or click in a different image window, and your Layers
dialog switches images -- so whatever you do next will apply to the
image you just chose.

If you turn Auto off, then by default, no image and no layer
is active. Notice, in the screenshot at left, how no image is shown
in the option menu just left of the Auto button.

Even if you open a new image, you can't do anything with it
until you explicitly choose an image from the menu.

I'm sure you can see why this could be confusing. So why have that
button at all?

Well, it's useful when you're working with lots of images -- for
instance, if you want to drag a layer from one image into another
image, you can use the menu to switch quickly among images and layers
without needing to bring those image windows to the front.
I don't find I need it, but for those who do, I guess it can
be a real time-saver.

Just to make it even more confusing, not everyone even has the
Auto button or the menu next to it. You can turn it off (and gain a
little extra vertical space for your layers dialog) with the tiny menu
button right above the mode menu. "Show Image Selection" controls
whether the image option menu, and the Auto button next to it, will
be displayed. "Auto Follow Active Image" is the same toggle as the
Auto button itself.

So if you ever get stuck and the Layers dialog doesn't seem to be
showing layers from your image, and you can't figure out why ...
remember that pesky Auto button. It might just be the problem.

(If not, try quitting GIMP and moving your profile aside. That works
for curing all manner of mysterious ills -- including this one.
Come to think of it, that deserves an article of its own. Coming soon!)