Get an imagemagick script (with brackets for a mask) to run as a script for every file in a folder? - batch-file

I have the script:
convert a.jpg ( -clone 0 -fill white -colorize 100 -fill black -draw "polygon 500,300 500,1500 1300,1500 1300,300" -alpha off -write mpr:mask +delete ) -mask mpr:mask +repage -threshold 50% -morphology open square:4 +mask c.jpg
which happily takes my image, makes a mask, and does what I need it to do, on a per image basis, using an original filename for the input, and a new filename for the output.
However, I'm trying to get this to run on every image in a folder, and I'm having zero luck...
I have tried many .bat files, such as:
#echo on
setlocal enabledelayedexpansion
set img_folder=C:\me\pics\
set output_folder=C:\me\pics\cropped
for /f "delims=" %%i in ('dir /b "%img_folder%\*.jpg"') do (
set input_file=%img_folder%\%%i
set output_file=%output_folder%\%%i
convert %input_file% ( -clone 0 -fill white -colorize 100 -fill black -draw "polygon 500,300 500,1500 1300,1500 1300,300" -alpha off -write mpr:mask +delete ) -mask mpr:mask +repage -threshold 50% -morphology open square:4 +mask %output_file%
)
pause
However, something about the brackets seems to be messing with everything else, as the bracket after +delete is pairing up in sublimetext with the bracket after "do" in the for loop.
I'm really stumped, I've tried everything I can think of, and could really use some help, if anyone can offer a simple solution, I'd be very much appreciative!

Instead of having a batch file looping on convert calls, you can have convert loop on the files. This requires a special syntax to create the output file name from the input file.
(untested, I don't run Windows)
convert -verbose C:\me\pics\*.jpg -set filename:out "c:\me\pics\cropped\%%[basename]" {your_filter_goes_here} "%%[filename:out].jpg"

What about this simpler version, which makes sure your command is not nested within parentheses?
#SetLocal EnableExtensions DisableDelayedExpansion
#Set "img_folder=C:\me\pics"
#Set "output_folder=C:\me\pics\cropped"
#For /F "EOL=? Delims=" %%G In ('Dir "%img_folder%\*.jpg" /A:-D /B 2^>NUL'
) Do #convert "%img_folder%\%%G" ( -clone 0 -fill white -colorize 100 -fill black -draw "polygon 500,300 500,1500 1300,1500 1300,300" -alpha off -write mpr:mask +delete ) -mask mpr:mask +repage -threshold 50%% -morphology open square:4 +mask "%output_folder%\%%G"
#Pause

Related

Trying to trim and fade multiple wav files in remote folder with SOX

I'm trying to create a file so that when I drag and drop a selection of wav files onto the batch script, it a. copies the wavs to a subdirectory (/webclips), replaces the spaces with underscores, then tries to trim all of the new wav files from the beginning to 45 seconds out. Eventually I'll fade them out...
Right now the script is copying fine but then giving a couple errors when it runs the trim command:
sox WARN wav: Premature EOF on .wav input file
sox WARN trim: Last 2 position(s) not reached (audio shorter than expected).
The new wavs files are (incorrectly) 1Kb in size. Any help would be appreciated.
Here's my script
set FOLDERPATH=%~dp0
set FILEPATH=%~dp1
mkdir "%FILEPATH%webclips"
FOR %%A IN (%*) DO (copy %%A "%FILEPATH%webclips")
cd "%FILEPATH%webclips"
for %%j in (*.*) do (
set filename=%%~nj
set filename=!filename:.=_!
set filename=!filename: =_!
if not "!filename!"=="%%~nj" ren "%%j" "!filename!%%~xj"
)
c:
cd/
CD "Program Files (x86)\sox-14-4-2"
for %%A in ("%FILEPATH%webclips\*.wav") do sox "%%A" "%FILEPATH%webclips\%%~nxA" trim 0 45
pause
In last line, sox overwrote the searched .wav file. For sox, it cannot do like that.
So the operation of copying original .wav file to subfolder can be removed.
!variable! is delayed format and have to be declared setlocal enabledelayedexpansion before it.
the batch file can also be simplified as the following,
#echo off
setlocal enabledelayedexpansion
for %%a in (%*) do (
if not exist "%%~dpawebclips\" md "%%~dpawebclips\"
set file_name=%%~na
set file_name=!file_name: =_!
set file_name=!file_name:.=_!
ren %%a !file_name!%%~xa
"%ProgramFiles(x86)%\sox-14-4-2\sox.exe" "%%~dpa!file_name!%%~xa" "%%~dpawebclips\!file_name!%%~xa" trim 0 45
)
pause
exit /b

Split into equal parts and convert many mp4 videos using ffmpeg

I have a ton of videos I need to convert from mp4 to wmv using ffmpeg and break up each file into 10 minute segments, but I am a total cmd scripting newb (in fact, I am a scripting newb :)
After spending six hours trying to find an answer, I thought I would bring it to you guys.
The code I have is working a little bit, but I need to be able to read data coming from the command line and send it back into the script for evaluation. I am not sure what code ffmpeg will spit out when it is done processing a video file (when the timestamp reaches an end), but this FOR loop just keeps on trying to create new file segments even though the video is over. This is what I saw when it tried to create a new file, so I think it might work to search for this:
frame= 0 fps=0.0 q=0.0 Lsize= 1kB time=00:00:00.00 bitrate=N/A
This is the code I have come up with so far (Don't laugh :)
#echo off
setlocal ENABLEEXTENSIONS
setlocal ENABLEDELAYEDEXPANSION
for %%a in ("*.mp4") do (
set hour=00
for /L %%i IN (1,1,10) do (
:Beginning
set /a start=%%i-1
set end=%%i
if !start! lss 10 set start=!start!0
if !end! lss 10 set end=!end!0
ffmpeg -ss !hour!:!start!:00 -i "%%a" -b:v 1500k -vcodec msmpeg4 -acodec wmav2 -t !hour!:!end!:00 "Converted\%%~na-!hour!-!start!-!end!.wmv"
if end==60 CALL :Increment
)
)
:Increment
set /a !hour!+1
set %%i=1
GOTO :Beginning
pause
Based on reading this thread was thinking something like this might go in the code, but not sure what to do with it:
set "dosstring=%*"
echo.!dosstring!|findstr /C:"frame= 0 fps=0.0 q=0.0 Lsize= 1kB time=00:00:00.00 bitrate=N/A" >nul 2>&1
Thanks so much for you help!
A more efficient method is to invoke ffmpeg just once per file and use its segmenting feature.
The segments will be numbered sequentially so if you absolutely need to include timestamps in the name we'll also generate a list of the segment's timestamps in CSV format:
tmp000.wmv,0.000000,60.281000
tmp001.wmv,60.281000,120.041000
Then parse it and rename the segments.
#echo off
for %%a in (*.mp4) do (
ffmpeg -i "%%a" ^
-f segment -segment_time 10:00 -segment_list tmp.csv -reset_timestamps 1 ^
-b:v 1500k -vcodec msmpeg4 -acodec wmav2 converted\tmp%%03d.wmv
setlocal enableDelayedExpansion
for /f "delims=, tokens=1-3" %%b in (tmp.csv) do (
set sec=%%c & set sec=!sec:.*=!
set /a hour="sec / 3600"
set /a mins1="sec / 60 %% 60" & set mins1=0!mins1!
set sec=%%d & set sec=!sec:.*=!
set /a mins2="sec / 60 %% 60" & set mins2=0!mins2!
ren "converted\%%b" "%%~na-!hour!-!mins1:~-2!-!mins2:~-2!.*"
)
endlocal
del tmp.csv
)
pause
This example won't rename files with ! in the name as I didn't want to overcomplicate the code to work around this case.

Batch split JPEG using ImageMagick

I use the following command to crop and split a jpg names page000.jpg in a folder producing two files
convert page000.jpg -crop 2x1# +repage -colorspace gray ^
+dither -colors 4 page000_%d.jpg
The two parts will be named page000_0.jpg and page000_1.jpg
It works well, but I would like to rewrite this code to work on every JPEG in a catalog.
I wrote this batch code for DOS (.bat):
mkdir split
FOR %%f IN (*.jpg) DO xcopy %%f split\
cd split
FOR %%f IN (*.jpg) DO convert %%f -crop 2x1# +repage -colorspace gray ^
+dither -colors 4 %%f_%d.jpg
However, it fails to work.
You need to escape the percent signs that need to be interpreted not by the batch parser but by the convert parser.
set "parameters=-crop 2x1# +repage -colorspace gray +dither -colors 4"
FOR %%f IN (*.jpg) DO convert "%%f" %parameters% "%%~nf_%%d.jpg"
^^ the escaped percent sign
BUT, as the for command does not use a static list of files (the list is retrieved while the for command iterates), the files generated in the process can be also processed. To solve it you can
1 - Use a static list changing your for command into an for /f command to first retrieve the list of files using a dir command
for /f "delims=" %%f in ('dir /b /a-d *.jpg') do .....
2 - Process the input files from original directory and place the output in the split directory. That way, as the generated files are not placed in the same folder being processed, they are not detected.
mkdir split
set "parameters=-crop 2x1# +repage -colorspace gray +dither -colors 4"
FOR %%f IN (*.jpg) DO convert "%%f" %parameters% "split\%%~nf_%%d.jpg"
You don't need to copy the files to the split subdirectory, you can get convert to read them from where they are:
for %f in (*.jpg) do convert %f -crop 2x1# +repage -colorspace gray +dither -colors 4 split/%~nf_%d.jpg

Pad filename based on for parameter in a batch file

I am making an image sequence fo a counter with ImageMagick in a batch script:
for /l %%g in (1,1,20) do imconvert.exe -background none -fill blue -font AVENIRLTSTD-LIGHT -pointsize 72 label:%%g output\%%g.png
This creates files in the output folder which are named as 1.png, 2.png, 3.png, etc...
Is it possible to pad the %%g parameter with zeros in the above command (in the output\%%g.png part)? The desired result is to get files with names like 001.png, 002.png, 003.png, etc...
Or can this only be done in a separate command after the files are generated?
#echo off
setlocal enableDelayedExpansion
for /l %%g in (1,1,20) do (
if %%g LSS 100 set name=0%%g
if %%g LSS 10 set name=00%%g
imconvert.exe -background none -fill blue -font AVENIRLTSTD-LIGHT -pointsize 72 label:!name! output\!name!.png
)
endlocal
Another way: Set a variable to the count, prefixed with enough zeros to guarantee the length is greater than or equal to the length you want. Then use a substring operation to keep the last N characters in the value (3 in your case).
#echo off
setlocal enableDelayedExpansion
for /l %%g in (1,1,20) do (
set "N=00%%g"
imconvert.exe -background none -fill blue -font AVENIRLTSTD-LIGHT -pointsize 72 label:!N:~-3! output\!N:~-3!.png
)
Just like npocmaka, I included the 0 prefix for the label as well. Adjust if needed.

If else not working within a loop and dos box closes before I can see any errors

I have very little experiance of batch files and have cobbled this together from other files I have written.
The batch file will have a folder of images dropped over the icon and should carry out different resizing depending on the photo oriantation.
The dos window closes before I can read any errors.
If I have the convert or identify lines only ( one at a time ) within the loop it works but with the if else it fails. With the IF ELSE activated the opening parentheses after the DO does not highlight the closing parenteses in my text editor.
Any help would be appreciated.
REM #echo off
REM Read all the png images from the directory
FOR %%f IN (%1\*.png) DO (
REM Set the variable width to the image width
SET width=identify -format "%%[fx:w]" %%f
REM Set the variable height to the image height
SET height=identify -format "%%[fx:h]" %%f
REM Check if the photo is portrate or landscape and run the relavant code
IF %width% LSS %height% (
convert "%%f" -trim -resize x740 "modified/%%~nf.jpg"
) ELSE (
convert "%%f" -trim -resize x740 -background blue -gravity center -extent 740x740 "modified/%%~nf.jpg"
)
)
PAUSE
ERRORS:
C:\>REM #echo off
C:\>REM Read all the png images from the directory
( was unexpected at this time.
C:\>IF LSS (
First of all, expand the argument and use blackquotes to evade error in spacenames.
And second, you can't set the output of a command into a variable in the way that you are trying to do it.
You need to get the output of the command with an FOR /F, no other way.
Try this:
(UPDATED)
Make sure you pass the correct argument to the script with \ slashes, not /
.
#echo off
Setlocal enabledelayedexpansion
:: Removes the last slash if given in argument %1
Set "Dir=%~1"
IF "%DIR:~-1%" EQU "\" (Set "Dir=%DIR:~0,-1%")
:: Read all the png images from the directory
FOR %%f IN ("%dir%\*.png") DO (
:: Set the variable width to the image width
For /F %%# in ('identify -format "%%[fx:w]" "%%f"') Do (SET /A "width=%%#")
:: Set the variable height to the image height
For /F %%# in ('identify -format "%%[fx:h]" "%%f"') Do (SET /A "height=%%#")
:: Create the output folder if don't exist
MKDIR ".\modified" 2>NUL
:: Check if the photo is portrate or landscape and run the relavant code
IF !width! LSS !height! (
convert "%%f" -trim -resize x740 "modified\%%~nf.jpg"
) ELSE (
convert "%%f" -trim -resize x740 -background blue -gravity center -extent 740x740 "modified\%%~nf.jpg"
)
)
PAUSE&EXIT

Resources