1

I have a series of PNG images (ABC_a.png, ABC_b.png, XYZ_a.png, XYZ_b.png, BCA_a.png, BCA_b.png etc.) and would like to compose every image of the same code (i.e. the name of an image without _a or _b) within a folder.

Manually, the code would look like this:

magick composite ABC_b.png ABC_a.png ABC.png
magick composite XYZ_b.png XYZ_a.png XYZ.png
magick composite BCA_b.png BCA_a.BCA BCA.png
...

... where a partly transparent image _b would be placed "on top of" _a and the name of the output file losing its _a/_b suffix.

I looked around and tried several apporaches via mogrify or for loops (FOR %i IN (*.png) DO magick composite ...) but couldn't get it automated. Perhaps it would help to use two separate folders and working with the same image names (without the suffix), but I'm not sure...

I appreciate any tips. Please be aware that I'd need to work within the Windows CMD or PowerShell to make it happen.

sparani
  • 31
  • 4
  • 1
    I don't use Windows, but in general it's simpler to iterate over `*_a.png` and then work out the name of the corresponding `*_b.png` file. I mean `FOR %i IN (*_a.png) DO ...` – Mark Setchell Oct 25 '22 at 14:18
  • I tried that too, but I have no idea how the correct expression for `DO ...` would actually look like – sparani Oct 25 '22 at 14:45
  • You should be able to do something similar to https://stackoverflow.com/questions/74133845/imagemagick-merging-pair-of-images-the-same-file-name-with-different-extensi/74134390#74134390 – fmw42 Oct 25 '22 at 16:26

1 Answers1

2

There can be used the following batch file for this task:

@echo off
setlocal EnableExtensions DisableDelayedExpansion
set "ImageMagick=magick.exe"
if exist "*!*_a.png" goto ExtendedVersion

setlocal EnableDelayedExpansion
for %%I in (*_a.png) do (
    set "FileNameA=%%~nI"
    set "FileName=!FileNameA:~0,-2!%%~xI"
    if not exist "!FileName!" "!ImageMagick!" composite "!FileNameA:~0,-1!b%%~xI" "!FileNameA!%%~xI" "!FileName!"
)
endlocal
goto EndBatch

:ExtendedVersion
echo INFO: Extended version required because of a PNG file with exclamation marks.
for %%I in (*_a.png) do (
    set "FileNameA=%%~nI"
    setlocal EnableDelayedExpansion
    set "FileName=!FileNameA:~0,-2!%%~xI"
    if not exist "!FileName!" "!ImageMagick!" composite "!FileNameA:~0,-1!b%%~xI" "!FileNameA!%%~xI" "!FileName!"
    endlocal
)

:EndBatch
endlocal

There is defined first the required execution environment with the first two command lines.

Next the environment variable ImageMagick is defined with the file name of this program. It would be best to add the full path because in this case cmd.exe would not need to search for magick.exe in current directory and next in all directories in string value of environment variable PATH using the file extensions in string value of environment variable PATHEXT before each execution of ImageMagick. The usage of the fully qualified file name of ImageMagick would avoid hundreds or even thousands of file system accesses on more than ten PNG files to process.

The IF condition in the fourth command line quickly checks if there is any PNG file with case-insensitive _a in the file name before the file extension .png containing one or more exclamation marks in the file name. The extended version of the processing loop is required if this condition is true.

The standard version enables first required delayed expansion. Then a FOR loop is used to process one PNG file after the other with case-insensitive _a in the file name before the file extension .png.

The current file name without file extension .png is assigned first to the environment variable FileNameA.

Next a string substitution is used to get from the string value of the environment variable FileNameA the file name without the last two characters _a concatenated with the file extension .png assigned to the environment variable FileName.

If there is not already a PNG file not ending with _a in the file name before the file extension, there is next executed ImageMagick with first argument being the corresponding _b.png file determined by using again a string substitution with using the file name string assigned to the environment variable FileName without last character a concatenated with b and the file extension .png and the_a.png file with the file extension as second argument and the file name without _a as third argument.

The command ENDLOCAL after the loop restores the previous environment before enabling delayed expansion and the command GOTO instructs the Windows Command Processor to continue processing the batch file with the command line below the label EndBatch which contains one more ENDLOCAL to restore the environment on starting the batch file processing.

The extended version is nearly the same as the standard version. The difference is that delayed variable expansion is not enabled on assigning the file name of the current _a.png file without the file extension to the environment variable FileNameA. That avoids interpreting the exclamation mark(s) in the file name as beginning/end of a delayed expanded variable reference resulting in a manipulation of the file name string before assigning it to the environment variable as it would happen with delayed expansion already enabled.

The extended version enables next delayed variable expansion inside the loop, does the same as the standard version and restores finally the previous environment before processing the next _a.png file.

The extended version is slower because of the environment variables list copy and the other operations made in background by every execution of SETLOCAL as explained in full details in this answer. The command ENDLOCAL in the loop is required to avoid a stack overflow on processing lots of PNG files.

To understand the commands used and how they work, open a command prompt window, execute there the following commands, and read the displayed help pages for each command, entirely and carefully.

  • echo /?
  • endlocal /?
  • for /?
  • goto /?
  • if /?
  • set /?
  • setlocal /?
Mofi
  • 46,139
  • 17
  • 80
  • 143