Cómo mantener la estructura de carpetas al convertir, cambiar el tamaño y mover imágenes usando powershell

usuario11755772

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{}
}
Seguir

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-ImageSizefunció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 $SourcePathpará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 Destinationcarpeta.

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 -Destinationapunte 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-ImgageTypefunció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

Editado en
0

Déjame decir algunas palabras

0Comentarios
Iniciar sesiónRevisión de participación posterior

Artículos relacionados

TOP Lista

CalienteEtiquetas

Archivo