Reputation: 9876
I'm trying to write a oneliner that gets unique ids of tif files in a directory, and then runs ImageMajick's convert to combine them together into multipage tifs:
convert ..\image_data\ua-nws_00000991_001.tif ..\image_data\ua-nws_00000991_002.tif ..\image_data\ua-nws_00000991_003.tif ..\image_data\ua-nws_00000991_004.tif ua-nws_00000991_all.tif
This works, but I'm trying to automate it for a bunch of ids that have several tifs each. For now, I'm just using one id and using "echo" instead of convert:
echo "ua-nws_00000991" | % { $id=$_; ls ../image_data | ? { $_.FullName -match $id } | % {
echo $_.FullName } | Join-String -Separator '" "' | % { echo '"'$_'"' $id"_all.tif" }
}
But I'm having trouble turning the list of files into a list of arguments. I'm getting the following (I've manually made the paths relative for online posting):
"
.\image_data\ua-nws_00000991_001.tif" ".\image_data\ua-nws_00000991_002.tif" ".\image_data\ua-nws_00000991_003.tif" "C:\Daniels_Stuff\Classes\Current\grad_ai\project\repo\article-reconstruction\image_data\ua-nws_00000991_004.tif"
ua-nws_00000991_all.tif
Before I added the double quotes, convert was interpreting all of the final $_
as one argument. I'm adding quotes in order to force convert to see them as multiple arguments. But I can't seem to get rid of that newline. I think it might be caused by the final echo
, but if I replace it with convert, I get the following:
convert.exe: unable to open module file `C:\Program Files\ImageMagick-6.9.2-Q16\modules\coders\IM_MOD_RL_\ABSOLUTE\PATH\TO\MY\IMAGES\IMAGE_DATA\UA-NWS_00000991_001.TIF C_.dll': No such file or directory @ warning/module.c/GetMagickModulePath/674.
convert.exe: no decode delegate for this image format `\ABSOLUTE\PATH\TO\MY\IMAGES\IMAGE_DATA\UA-NWS_00000991_001.TIF C' @ error/constitute.c/ReadImage/501.
convert.exe: no images defined `ua-nws_00000991_all.tif' @ error/convert.c/ConvertImageCommand/3241.
Upvotes: 0
Views: 761
Reputation: 207445
Whilst I don't understand Powershell's mad syntax, there are two aspects to ImageMagick that may help you out...
Aspect 1 - Filenames on stdin
Firstly, you can pass a list of filenames to merge into a single TIF on ImageMagick's stdin rather than as parameters. So, if you have 3 pages of a book, in 3 files called p1.tif
, p2.tif
and p3.tif
, rather than do:
convert p*.tif book.tif
you can also do
dir /b/s p*tif | convert @- book.tif
Whilst I am generating the names above using DIR /B/S
, I expect you would want to replace that with your Powershell commands.
Aspect 2 - Multiple images down single pipe
Secondly, you can pipe multiple images from multiple invocations of convert
into a further final invocation of convert
using "Magick Image File Format" (MIFF
) streaming:
Here is one example, where two invocations of convert
both send an image each to a final convert
that joins the images from its MIFF input stream:
( convert p1.tif MIFF:- & convert p2.tif MIFF:- ) | convert MIFF:- book.tif
Here is a slightly different example of the same thing:
FOR files *.TIF; DO
IF this file has the correct id
convert $this MIFF:-
ENDIF
ENDDO | convert MIFF:- book.tif
Upvotes: 1
Reputation: 28983
I don't know where Join-String
comes from, but I can only guess that it's broken - because I can't see anywhere else the newline is coming from.
Put some test files in a folder:
Name
----
ua-nws_00000991_001.tif
ua-nws_00000991_002.tif
ua-nws_00000991_003.tif
ua-nws_00000991_004.tif
ua-nws_00000992_001.tif
ua-nws_00000992_002.tif
ua-nws_00000992_003.tif
ua-nws_00000992_004.tif
List them with Get-ChildItem
(gci
), and group them (Group-Object
, aka group
) by stripping off the trailing number from the filename:
PS D:\t\New folder> gci *.tif | group { $_.Name -replace '_\d+\.tif$' }
Count Name Group
----- ---- -----
4 ua-nws_00000991 {D:\t\New folder\ua-nws_00000991_001.tif, D:\t\New folder\ua-nws_00000991_002.tif, D:\t\New folder\ua-nws...
4 ua-nws_00000992 {D:\t\New folder\ua-nws_00000992_001.tif, D:\t\New folder\ua-nws_00000992_002.tif, D:\t\New folder\ua-nws...
Now we have groups, where the group name is the image ID, and the list of files for that ID is the group member. Neat. Now run convert once foreach
(%
) group by taking the full filenames as a parameter to convert, and generating a new filename from the group id ($_.name
) with _full.tif
on the end:
gci *.tif | group { $_.Name -replace '_\d+\.tif$' } |% { Start-Process convert -ArgumentList (@($_.group.fullname) + @("$($_.Name)_full.tif"))}
This probably won't work as is, I don't have convert
installed to try it, and you'll need to adjust the paths. But I think the approach will work.
Upvotes: 1
Reputation: 11254
You could try the following:
get-childitem "image_data" -recurse -filter ua-nws_00000991*.tif | % { convert $_.Fullname }
Returns all tif files in "image_data" directory and calls convert
for every found tif file.
hope that helps
Upvotes: -1