When you search for "ant up-to-date" or "ant timestamp", you almost immediately find the <uptodate> Task. At first, it seems to be exactly suited for that purpose, and it can take a <mapper> as destination files, so it can look for the correct GIF filename for each JPG. However, the problem of <uptodate> is its granularity : it takes a (set of) source file(s) and a (set of) destination file(s), and sets a flag if something is out of date. If no source has changed, all is well, but if only some files changed, the only thing you can do is reprocess all the source files. (Alternatively, you can put one <uptodate> Task per file of course, but it's completely static and is thus not an option)

Finally, after much reading, is seems <uptodate> is not suitable for that case and no specific construct is needed at all. All you need is a simple target calling the Apply task. Apply, contrary to Exec, only executes if its destination file is out-of-date.

It's still much longer than the make syntax, but at least it does the job perfectly :

   <target name="makelogos">
       <echo message='converting logos .jpg -> .gif thumbnails'/>
       <apply failonerror='true' executable='${imagemagick.dir}/convert' dest='${out.dir}'>
           <arg value='-resize'/>
           <arg value='40x30>'/>
           <fileset dir='${web.src.dir}'>
               <include name='${img.subdir}/*.jpg'/>
                 <mapper type="flatten"/>
                 <mapper type='glob' from='*.jpg' to='*.gif'/>

And well, once it works, it looks pretty simple, but I guess it's not that easy to find unless you have RTFM a few times :-)