ImageMagick identif.exe ничего не возвращает в параллельном проекте Apache Ant

Я использую проект Apache Ant, чтобы собрать некоторую информацию о текстурах. Здесь вы можете увидеть тестовый проект, который выполняет только чтение без каких-либо дополнительных действий. Это минимальный набор, который воспроизводит одну неприятную ошибку. Я обнаружил, что иногда ImageMagick's attribute.exe ничего не возвращает - я добавил код, который приводит к сбою сборки, если это так. Если я буду запускать этот проект несколько раз, у меня будет нестабильное поведение. Иногда проект строится успешно, иногда происходит сбой с несколькими сообщениями об ошибках. Разработчики ImageMagick говорят, что их инструменты поточно-ориентированы. Но если identif.exe не так, то что может быть? Мне действительно нужна помощь кого-то с предварительными знаниями об Apache Ant и 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>

1 ответ

Решение

Хорошо, я напишу здесь, как мне удалось решить мою проблему. Я надеюсь, что когда-нибудь это кому-нибудь поможет.

Первое, что я обнаружил, это то, что PHP-метод getimagesize намного быстрее, поэтому я решил переключиться на него, таким образом убив основную проблему. Я написал следующий макрос, чтобы получить ширину и высоту изображения:

<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=
                "&quot;$size=getimagesize('@{file}');
                echo($size[0].' '.$size[1]);&quot;"
            />
        </exec>
        <propertyregex 
            property="@{propertywidth}" 
            input="${output}" 
            regexp="(\d*) (\d*)" 
            replace="\1"
        />
        <propertyregex 
            property="@{propertyheight}" 
            input="${output}" 
            regexp="(\d*) (\d*)" 
            replace="\2"
        />
    </sequential>
</macrodef>

К сожалению, в этом макродефе точно такая же ошибка. Иногда во время параллельного запуска некоторые exec-задачи ничего не возвращали в вывод. Я был очень расстроен, поэтому я решил написать еще один макрос, который я сейчас использую, и, наконец, он работает нормально. Что я сделал, так это избежал чтения чего-либо из stdout exec-task и вместо этого использовал tempfile-task. Вот последний макрос:

<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="&quot;$size=getimagesize('@{file}');
                file_put_contents('${file_temp}', $size[0].' '.$size[1]);&quot;"/>
        </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>
Другие вопросы по тегам