I use Apache Ant project to gather some information about textures. Here you can see a test project that does only reading without any further actions. This is a minimal set that reproduces one nasty bug. I have found that sometimes ImageMagick's identify.exe does not return anything – I've added a code that forces build to fail if so. If I run this project multiple times I will get unstable behavior. Sometimes project build successfully, sometimes it fails with several fail-messages. Developers of ImageMagick say that their tools are thread safe. But if identify.exe is not the case then what can be? I really need help of someone with advance knowledge about Apache Ant and ImageMagick.
<project default="default">
<taskdef resource="net/sf/antcontrib/antlib.xml"/>
<property name="image_magick_path" location="c:\Program Files\ImageMagick-6.8.9-Q8\"/>
<property name="images_path" location="path\to\folder\with\png\images"/>
<target name="default">
<for param="item" parallel="true">
<path>
<fileset dir="${images_path}">
<patternset id="pattern_images">
<include name="**\*.png"/>
<include name="**\*.jpg"/>
<include name="**\*.gif"/>
<include name="**\*.bmp"/>
</patternset>
</fileset>
</path>
<sequential>
<local name="image_width"/>
<tex_width file="@{item}" property="image_width"/>
<local name="image_height"/>
<tex_width file="@{item}" property="image_height"/>
<if>
<or>
<equals arg1="${image_width}" arg2=""/>
<equals arg1="${image_height}" arg2=""/>
</or>
<then>
<fail message="Got nothing. But why? Image: @{item}"/>
</then>
</if>
</sequential>
</for>
</target>
<macrodef name="tex_width">
<attribute name="file"/>
<attribute name="property"/>
<sequential>
<exec executable="${image_magick_path}\identify.exe" outputproperty="@{property}">
<arg value="-format"/>
<arg value="%w"/>
<arg value="@{file}"/>
</exec>
</sequential>
</macrodef>
<macrodef name="tex_height">
<attribute name="file"/>
<attribute name="property"/>
<sequential>
<exec executable="${image_magick_path}\identify.exe" outputproperty="@{property}">
<arg value="-format"/>
<arg value="%h"/>
<arg value="@{file}"/>
</exec>
</sequential>
</macrodef>
</project>
Ok, I will write here how I managed to solve my problem. I hope it will help someone someday.
First thing I found is that PHP method 'getimagesize' is much faster so I decided to switch to it thus killing the main problem. I wrote following macrodef to get both image width and height:
<macrodef name="getimagesize">
<attribute name="file"/>
<attribute name="propertywidth"/>
<attribute name="propertyheight"/>
<sequential>
<local name="output"/>
<exec executable="php" outputproperty="output">
<arg value="-r"/>
<arg value=
""$size=getimagesize('@{file}');
echo($size[0].' '.$size[1]);""
/>
</exec>
<propertyregex
property="@{propertywidth}"
input="${output}"
regexp="(\d*) (\d*)"
replace="\1"
/>
<propertyregex
property="@{propertyheight}"
input="${output}"
regexp="(\d*) (\d*)"
replace="\2"
/>
</sequential>
</macrodef>
Unfortunately this macrodef has abosutely same bug. Sometimes during parallel run some exec-tasks returned nothing in output. I was very upset so I decided to write another macrodef which I use now and finally it works fine. What I did was avoid reading anything from exec-task's 'stdout' and use tempfile-task instead. Here's final macrodef:
<macrodef name="getimagesize">
<attribute name="file"/>
<attribute name="propertywidth"/>
<attribute name="propertyheight"/>
<sequential>
<local name="file_dirname"/>
<dirname property="file_dirname" file="@{file}"/>
<local name="file_temp"/>
<tempfile property="file_temp" destdir="${file_dirname}" createfile="true"/>
<exec executable="php">
<arg value="-r"/>
<arg value=""$size=getimagesize('@{file}');
file_put_contents('${file_temp}', $size[0].' '.$size[1]);""/>
</exec>
<local name="file_temp_content"/>
<loadfile property="file_temp_content" srcfile="${file_temp}"/>
<delete file="${file_temp}"/>
<propertyregex
property="@{propertywidth}"
input="${file_temp_content}"
regexp="(\d*) (\d*)"
replace="\1"
/>
<propertyregex
property="@{propertyheight}"
input="${file_temp_content}"
regexp="(\d*) (\d*)"
replace="\2"
/>
</sequential>
</macrodef>