Estoy tratando de escribir un script de PowerShell que tomará un parámetro de un directorio de origen, lo iterará y convertirá todas las imágenes a .jpg, cambiará su tamaño y luego las moverá a un nuevo directorio, mientras mantiene su estructura de subdirectorio.
En este momento tengo un script que hará todo menos mantener la estructura de carpetas.
param([String]$src)
#param([String]$src, [string]$dest)
#param([String]$src, [string]$dest, [switch]$keepSubFolders)
Import-Module '\Convert-ImgageType.ps1'
Import-Module '\Set-ImageSize.ps1'
Get-ChildItem "$src\*" -include *.tif -Recurse | Convert-ImgageType -Destination $src\* -Verbose
Start-Sleep -Seconds 5
Get-ChildItem "$src\*.jpg" | Set-ImageSize -Destination $src -WidthPx 9000 -HeightPx 6000 -Verbose
Start-Sleep -Seconds 5
Remove-Item "$src\*.jpg" -Verbose
Set-ImageSize.ps1
Function Set-ImageSize
{
<#
.SYNOPSIS
Resize image file.
.DESCRIPTION
The Set-ImageSize cmdlet to set new size of image file.
.PARAMETER Image
Specifies an image file.
.PARAMETER Destination
Specifies a destination of resized file. Default is current location (Get-Location).
.PARAMETER WidthPx
Specifies a width of image in px.
.PARAMETER HeightPx
Specifies a height of image in px.
.PARAMETER DPIWidth
Specifies a vertical resolution.
.PARAMETER DPIHeight
Specifies a horizontal resolution.
.PARAMETER Overwrite
Specifies a destination exist then overwrite it without prompt.
.PARAMETER FixedSize
Set fixed size and do not try to scale the aspect ratio.
.PARAMETER RemoveSource
Remove source file after conversion.
.EXAMPLE
PS C:\> Get-ChildItem 'P:\test\*.jpg' | Set-ImageSize -Destination "p:\test2" -WidthPx 300 -HeightPx 375 -Verbose
VERBOSE: Image 'P:\test\00001.jpg' was resize from 236x295 to 300x375 and save in 'p:\test2\00001.jpg'
VERBOSE: Image 'P:\test\00002.jpg' was resize from 236x295 to 300x375 and save in 'p:\test2\00002.jpg'
VERBOSE: Image 'P:\test\00003.jpg' was resize from 236x295 to 300x375 and save in 'p:\test2\00003.jpg'
.NOTES
Author: Michal Gajda
Blog : http://commandlinegeeks.com/
#>
[CmdletBinding(
SupportsShouldProcess=$True,
ConfirmImpact="Low"
)]
Param
(
[parameter(Mandatory=$true,
ValueFromPipeline=$true,
ValueFromPipelineByPropertyName=$true)]
[Alias("Image")]
[String[]]$FullName,
[String]$Destination = $(Get-Location),
[Switch]$Overwrite,
[Int]$WidthPx,
[Int]$HeightPx,
[Int]$DPIWidth,
[Int]$DPIHeight,
[Switch]$FixedSize,
[Switch]$RemoveSource
)
Begin
{
[void][reflection.assembly]::LoadWithPartialName("System.Windows.Forms")
#[void][reflection.assembly]::loadfile( "C:\Windows\Microsoft.NET\Framework\v2.0.50727\System.Drawing.dll")
}
Process
{
Foreach($ImageFile in $FullName)
{
If(Test-Path $ImageFile)
{
$OldImage = new-object System.Drawing.Bitmap $ImageFile
$OldWidth = $OldImage.Width
$OldHeight = $OldImage.Height
if($WidthPx -eq $Null)
{
$WidthPx = $OldWidth
}
if($HeightPx -eq $Null)
{
$HeightPx = $OldHeight
}
if($FixedSize)
{
$NewWidth = $WidthPx
$NewHeight = $HeightPx
}
else
{
if($OldWidth -lt $OldHeight)
{
$NewWidth = $WidthPx
[int]$NewHeight = [Math]::Round(($NewWidth*$OldHeight)/$OldWidth)
if($NewHeight -gt $HeightPx)
{
$NewHeight = $HeightPx
[int]$NewWidth = [Math]::Round(($NewHeight*$OldWidth)/$OldHeight)
}
}
else
{
$NewHeight = $HeightPx
[int]$NewWidth = [Math]::Round(($NewHeight*$OldWidth)/$OldHeight)
if($NewWidth -gt $WidthPx)
{
$NewWidth = $WidthPx
[int]$NewHeight = [Math]::Round(($NewWidth*$OldHeight)/$OldWidth)
}
}
}
$ImageProperty = Get-ItemProperty $ImageFile
$SaveLocation = Join-Path -Path $Destination -ChildPath ($ImageProperty.Name)
If(!$Overwrite)
{
If(Test-Path $SaveLocation)
{
$Title = "A file already exists: $SaveLocation"
$ChoiceOverwrite = New-Object System.Management.Automation.Host.ChoiceDescription "&Overwrite"
$ChoiceCancel = New-Object System.Management.Automation.Host.ChoiceDescription "&Cancel"
$Options = [System.Management.Automation.Host.ChoiceDescription[]]($ChoiceCancel, $ChoiceOverwrite)
If(($host.ui.PromptForChoice($Title, $null, $Options, 1)) -eq 0)
{
Write-Verbose "Image '$ImageFile' exist in destination location - skiped"
Continue
} #End If ($host.ui.PromptForChoice($Title, $null, $Options, 1)) -eq 0
} #End If Test-Path $SaveLocation
} #End If !$Overwrite
$NewImage = new-object System.Drawing.Bitmap $NewWidth,$NewHeight
$Graphics = [System.Drawing.Graphics]::FromImage($NewImage)
$Graphics.InterpolationMode = [System.Drawing.Drawing2D.InterpolationMode]::HighQualityBicubic
$Graphics.DrawImage($OldImage, 0, 0, $NewWidth, $NewHeight)
$ImageFormat = $OldImage.RawFormat
$OldImage.Dispose()
if($DPIWidth -and $DPIHeight)
{
$NewImage.SetResolution($DPIWidth,$DPIHeight)
} #End If $DPIWidth -and $DPIHeight
$NewImage.Save($SaveLocation,$ImageFormat)
$NewImage.Dispose()
Write-Verbose "Image '$ImageFile' was resize from $($OldWidth)x$($OldHeight) to $($NewWidth)x$($NewHeight) and save in '$SaveLocation'"
If($RemoveSource)
{
Remove-Item $Image -Force
Write-Verbose "Image source '$ImageFile' was removed"
} #End If $RemoveSource
}
}
} #End Process
End{}
}
Para que haga lo que quiere, es decir, mantener la estructura de carpetas de las imágenes de origen en el directorio de destino, he editado la Set-ImageSize
función. Ahora tiene un parámetro adicional (opcional) llamado $SourcePath
.
Usando eso, es posible determinar la estructura de carpetas para el destino. Dado que el $SourcePath
parámetro es opcional, al no usar ese parámetro en la llamada a la función, las imágenes redimensionadas resultantes se guardan en la misma Destination
carpeta.
Esto también significa que debe cambiar un poco la llamada de la función para que eso suceda. En primer lugar, debe asegurarse de que -Destination
apunte a otra carpeta que no sea la fuente de los archivos. Realmente nada nuevo, pero ese es un error que cometiste originalmente.
De todos modos, primero la función adaptada
function Set-ImageSize {
<#
.SYNOPSIS
Resize image file.
.DESCRIPTION
The Set-ImageSize cmdlet to set new size of image file.
.PARAMETER FullName
Specifies an image file.
.PARAMETER SourcePath
Optional. If used, the function creates the same folder structure in the Destination path
to save the resized images. When not used, the resized images are all saved in the Destination folder.
.PARAMETER Destination
Specifies a destination of resized file. Default is current location (Get-Location).
.PARAMETER WidthPx
Specifies a width of image in px.
.PARAMETER HeightPx
Specifies a height of image in px.
.PARAMETER DPIWidth
Specifies a vertical resolution.
.PARAMETER DPIHeight
Specifies a horizontal resolution.
.PARAMETER Overwrite
Specifies a destination exist then overwrite it without prompt.
.PARAMETER FixedSize
Set fixed size and do not try to scale the aspect ratio.
.PARAMETER RemoveSource
Remove source file after conversion.
.EXAMPLE
PS C:\> Get-ChildItem 'P:\test\*.jpg' | Set-ImageSize -Destination "p:\test2" -WidthPx 300 -HeightPx 375 -Verbose
VERBOSE: Image 'P:\test\00001.jpg' was resize from 236x295 to 300x375 and save in 'p:\test2\00001.jpg'
VERBOSE: Image 'P:\test\00002.jpg' was resize from 236x295 to 300x375 and save in 'p:\test2\00002.jpg'
VERBOSE: Image 'P:\test\00003.jpg' was resize from 236x295 to 300x375 and save in 'p:\test2\00003.jpg'
.NOTES
Author: Michal Gajda
Edited: Theo
Blog : http://commandlinegeeks.com/
#>
[CmdletBinding(
SupportsShouldProcess=$True,
ConfirmImpact="Low"
)]
Param
(
[parameter(Mandatory=$true, ValueFromPipeline=$true, ValueFromPipelineByPropertyName=$true)]
[Alias("Image")]
[String[]]$FullName,
[string]$SourcePath = $null,
[String]$Destination = $(Get-Location),
[Switch]$Overwrite,
[Int]$WidthPx,
[Int]$HeightPx,
[Int]$DPIWidth,
[Int]$DPIHeight,
[Switch]$FixedSize,
[Switch]$RemoveSource
)
Begin {
Add-Type -AssemblyName System.Windows.Forms
Add-Type -AssemblyName System.Drawing
}
Process {
foreach($ImageFile in $FullName) {
if (Test-Path $ImageFile -PathType Leaf) {
$OldImage = New-Object System.Drawing.Bitmap $ImageFile
$OldWidth = $OldImage.Width
$OldHeight = $OldImage.Height
if (!$WidthPx) { $WidthPx = $OldWidth }
if (!$HeightPx) { $HeightPx = $OldHeight }
if ($FixedSize) {
$NewWidth = $WidthPx
$NewHeight = $HeightPx
}
else {
if($OldWidth -lt $OldHeight) {
$NewWidth = $WidthPx
[int]$NewHeight = [Math]::Round(($NewWidth*$OldHeight)/$OldWidth)
if($NewHeight -gt $HeightPx) {
$NewHeight = $HeightPx
[int]$NewWidth = [Math]::Round(($NewHeight*$OldWidth)/$OldHeight)
}
}
else {
$NewHeight = $HeightPx
[int]$NewWidth = [Math]::Round(($NewHeight*$OldWidth)/$OldHeight)
if($NewWidth -gt $WidthPx) {
$NewWidth = $WidthPx
[int]$NewHeight = [Math]::Round(($NewWidth*$OldHeight)/$OldWidth)
}
}
}
# most changes made here
$imageFileName = [System.IO.Path]::GetFileName($ImageFile)
if ([string]::IsNullOrWhiteSpace($SourcePath)) {
# save in the destination path
$SaveFilePath = $Destination
$SaveFileName = Join-Path -Path $Destination -ChildPath $imageFileName
}
else {
# keep directory structure
$imageFilePath = [System.IO.Path]::GetDirectoryName($ImageFile).Substring($SourcePath.Length)
$SaveFilePath = Join-Path -Path $Destination -ChildPath $imageFilePath
$SaveFileName = Join-Path -Path $SaveFilePath -ChildPath $imageFileName
}
# create the destination in $SaveFilePath if it does not already exist
if (!(Test-Path -Path $SaveFilePath)) {
New-Item -Path $SaveFilePath -ItemType Directory | Out-Null
}
if (!$Overwrite) {
if (Test-Path $SaveFileName -PathType Leaf) {
# are you sure you want to get this confirmation dialog every time?
$Title = "A file already exists: $SaveFileName"
$ChoiceOverwrite = New-Object System.Management.Automation.Host.ChoiceDescription "&Overwrite"
$ChoiceCancel = New-Object System.Management.Automation.Host.ChoiceDescription "&Cancel"
$Options = [System.Management.Automation.Host.ChoiceDescription[]]($ChoiceCancel, $ChoiceOverwrite)
if (($host.ui.PromptForChoice($Title, $null, $Options, 1)) -eq 0) {
Write-Verbose "Image '$ImageFile' already exist in destination location - skipped"
Continue
}
}
}
$NewImage = New-Object System.Drawing.Bitmap $NewWidth,$NewHeight
$Graphics = [System.Drawing.Graphics]::FromImage($NewImage)
$Graphics.InterpolationMode = [System.Drawing.Drawing2D.InterpolationMode]::HighQualityBicubic
$Graphics.DrawImage($OldImage, 0, 0, $NewWidth, $NewHeight)
$ImageFormat = $OldImage.RawFormat
$OldImage.Dispose()
if ($DPIWidth -and $DPIHeight){
$NewImage.SetResolution($DPIWidth,$DPIHeight)
}
$NewImage.Save($SaveFileName, $ImageFormat)
$NewImage.Dispose()
Write-Verbose "Image '$ImageFile' was resized from $($OldWidth)x$($OldHeight) to $($NewWidth)x$($NewHeight) and saved as '$SaveFileName'"
if ($RemoveSource) {
Remove-Item $ImageFile -Force
Write-Verbose "Image source file '$ImageFile' was removed"
}
}
}
}
End{}
}
Ahora para la llamada a la función:
param([String]$src, [string]$dest, [switch]$keepSubFolders)
Import-Module '\Convert-ImgageType.ps1'
Import-Module '\Set-ImageSize.ps1'
Get-ChildItem "$src\*" -include *.tif -Recurse | Convert-ImgageType -Destination $src\* -Verbose
Start-Sleep -Seconds 5
if ($keepSubFolders) {
# to keep the folder structure, you need to use the -SourcePath parameter
Get-ChildItem "$src\*.jpg" -File -Recurse | Set-ImageSize -SourcePath $src -Destination $dest -WidthPx 9000 -HeightPx 6000 -Verbose
}
else {
Get-ChildItem "$src\*.jpg" -File -Recurse | Set-ImageSize -Destination $dest -WidthPx 9000 -HeightPx 6000 -Verbose
}
Start-Sleep -Seconds 5
# you could also use the -RemoveSource switch on the Set-ImageSize function..
Remove-Item "$src\*.jpg" -Verbose
Nota: no he probado la Convert-ImgageType
función.
Este artículo se recopila de Internet, indique la fuente cuando se vuelva a imprimir.
En caso de infracción, por favor [email protected] Eliminar
Déjame decir algunas palabras