【ChatGPT 出張嘴寫程式】全程紀錄:GIF 動圖尺寸縮放 (搭配 Magick)

現在不用當上架構或主管,出一張嘴就能寫程式了
不過還是要知道一些術語,不然和 AI 也有可能會花不少溝通成本。
前後大約對話了快要一小時,可能都會有人吐槽,這樣還不如自己寫比較快www
但是出一張嘴就是爽啦 結果還不是要打字

給程式小白

這是什麼? 這是幫你改變 GIF 動圖大小的軟體~很適合拿來做 Discord 的 Emoji 或 Source 遊戲噴漆前置作業。

比起網路上抓不知名的軟體,這個程式安全一百倍,不用怕中毒! (除非你不相信 ImageMagick)

只想要一個可以在 Windows 執行的 Gif 動畫尺寸調整軟體的人,只要這樣做:

  1. 下載安裝 https://imagemagick.org/archive/binaries/ImageMagick-7.1.1-7-Q16-HDRI-x64-dll.exe
  2. 勾選 Add to system path
  3. 打開記事本,複製完整程式碼,儲存為 gif_resizer.ps1
  4. gif_resizer.ps1 點滑鼠右鍵,點選 以 Powershell 執行
  5. 開始使用!

有遇到問題的人,不需要註冊或登入帳號,直接在下方留言。

完整程式碼

Add-Type -AssemblyName System.Windows.Forms
Add-Type -TypeDefinition @"
using System;
using System.Windows.Forms;

public class FileDropLabel : Label
{
    public FileDropLabel()
    {
        AllowDrop = true;
        DragEnter += (s, e) =>
        {
            if (e.Data.GetDataPresent(DataFormats.FileDrop)) e.Effect = DragDropEffects.Copy;
        };
    }
}
"@ -ReferencedAssemblies @('System.Windows.Forms.dll', 'System.Drawing.dll')

$global:originalWidth = [ref]0
$global:originalHeight = [ref]0
$global:inputImagePath = New-Object System.Management.Automation.PSReference("")

function UpdateAspectRatio {
    if ($checkboxMaintainAspectRatio.Checked -and $global:originalWidth.Value -gt 0 -and $global:originalHeight.Value -gt 0) {
        if ($textboxWidth.Focused) {
            if ([int32]::TryParse($textboxWidth.Text, [ref]$null)) {
                $height = [int]($textboxWidth.Text) * $global:originalHeight.Value / $global:originalWidth.Value
                $textboxHeight.Text = [string]$height
            }
        } elseif ($textboxHeight.Focused) {
            if ([int32]::TryParse($textboxHeight.Text, [ref]$null)) {
                $width = [int]($textboxHeight.Text) * $global:originalWidth.Value / $global:originalHeight.Value
                $textboxWidth.Text = [string]$width
            }
        }
    }
}

$mainForm = New-Object System.Windows.Forms.Form
$mainForm.Text = 'Image Resizer'
$mainForm.Width = 400
$mainForm.Height = 250

$labelDropImage = New-Object FileDropLabel
$labelDropImage.Text = 'Drag and drop an image here'
$labelDropImage.Size = New-Object System.Drawing.Size(350, 50)
$labelDropImage.Location = New-Object System.Drawing.Point(20, 20)
$labelDropImage.BackColor = [System.Drawing.SystemColors]::ControlLight
$labelDropImage.TextAlign = [System.Drawing.ContentAlignment]::MiddleCenter
$labelDropImage.BorderStyle = [System.Windows.Forms.BorderStyle]::FixedSingle
$labelDropImage.Add_DragDrop({
    $files = $_.Data.GetData([Windows.Forms.DataFormats]::FileDrop)
    if ($files.Count -eq 1 -and [System.IO.File]::Exists($files[0])) {
        $imageExtensions = @('.jpg', '.jpeg', '.png', '.bmp', '.gif')
        $fileExtension = [System.IO.Path]::GetExtension($files[0]).ToLower()
        if ($imageExtensions -contains $fileExtension) {
            $originalImage = [System.Drawing.Image]::FromFile($files[0])
            $global:originalWidth.Value = $originalImage.Width
            $global:originalHeight.Value = $originalImage.Height
            $textboxWidth.Text = $global:originalWidth.Value
            $textboxHeight.Text = $global:originalHeight.Value
            $global:inputImagePath.Value = $files[0].ToString()
            $labelDropImage.Text = $global:inputImagePath.Value
        } else {
            [System.Windows.Forms.MessageBox]::Show('Unsupported image format.', 'Error', [System.Windows.Forms.MessageBoxButtons]::OK, [System.Windows.Forms.MessageBoxIcon]::Error)
        }
    }
})

$mainForm.Controls.Add($labelDropImage)

$labelWidth = New-Object System.Windows.Forms.Label
$labelWidth.Text = 'Width:'
$labelWidth.Location = New-Object System.Drawing.Point(20, 80)
$labelWidth.Size = New-Object System.Drawing.Size(50, 20)
$mainForm.Controls.Add($labelWidth)

$textboxWidth = New-Object System.Windows.Forms.TextBox
$textboxWidth.Location = New-Object System.Drawing.Point(80, 80)
$textboxWidth.Size = New-Object System.Drawing.Size(50, 20)
# $textboxWidth.Add_Leave({ UpdateAspectRatio })
$textboxWidth.Add_TextChanged({ UpdateAspectRatio })
$mainForm.Controls.Add($textboxWidth)

$labelHeight = New-Object System.Windows.Forms.Label
$labelHeight.Text = 'Height:'
$labelHeight.Location = New-Object System.Drawing.Point(150, 80)
$labelHeight.Size = New-Object System.Drawing.Size(50, 20) 

$mainForm.Controls.Add($labelHeight)

$textboxHeight = New-Object System.Windows.Forms.TextBox
$textboxHeight.Location = New-Object System.Drawing.Point(210, 80)
$textboxHeight.Size = New-Object System.Drawing.Size(50, 20)
# $textboxHeight.Add_Leave({ UpdateAspectRatio })
$textboxHeight.Add_TextChanged({ UpdateAspectRatio })
$mainForm.Controls.Add($textboxHeight)

$checkboxMaintainAspectRatio = New-Object System.Windows.Forms.CheckBox
$checkboxMaintainAspectRatio.Text = 'Maintain Aspect Ratio'
$checkboxMaintainAspectRatio.Location = New-Object System.Drawing.Point(20, 110)
$checkboxMaintainAspectRatio.Checked = $true
$mainForm.Controls.Add($checkboxMaintainAspectRatio)

$buttonResize = New-Object System.Windows.Forms.Button
$buttonResize.Text = 'Resize Image'
$buttonResize.Location = New-Object System.Drawing.Point(20, 140)
$buttonResize.Size = New-Object System.Drawing.Size(100, 30)
$buttonResize.Add_Click({
    if (-not [string]::IsNullOrEmpty($global:inputImagePath)) {
        $outputImagePath = [System.IO.Path]::ChangeExtension($global:inputImagePath.Value, '_resized' + [System.IO.Path]::GetExtension($global:inputImagePath.Value))

        $resizeCommand = "magick `"$($global:inputImagePath.Value)`" -resize $($textboxWidth.Text)`x$($textboxHeight.Text) `"$($outputImagePath)`""
        try {
            $resizeResult = Invoke-Expression -Command $resizeCommand
            [System.Windows.Forms.MessageBox]::Show("Image resized and saved as `n$outputImagePath", 'Success', [System.Windows.Forms.MessageBoxButtons]::OK, [System.Windows.Forms.MessageBoxIcon]::Information)
        } catch {
            $errorMessage = $_.Exception.Message
            [System.Windows.Forms.MessageBox]::Show("Error occurred during resizing: `n$errorMessage", 'Error', [System.Windows.Forms.MessageBoxButtons]::OK, [System.Windows.Forms.MessageBoxIcon]::Error)
        }
    } else {
        [System.Windows.Forms.MessageBox]::Show('Please drag and drop an image to be resized.', 'Error', [System.Windows.Forms.MessageBoxButtons]::OK, [System.Windows.Forms.MessageBoxIcon]::Error)
    }
})

$mainForm.Controls.Add($buttonResize)

$mainForm.Add_Closing({
    $mainForm.Dispose()
})
[void][System.Windows.Forms.Application]::EnableVisualStyles()
[void][System.Windows.Forms.Application]::Run($mainForm)

完整對話

Hollen9

我想要你幫我做一個 powershell 的 gui 程式,不用和我解釋原理,我只要程式碼,做出來的程式介面要英文,程式的註解也用英文寫;但是你和我的回答必須全程使用台灣繁體中文。

拖曳圖片到 gui,圖片尺寸按照使用者需求縮放,使用者可勾選是否保留長寬比,若保留,長或寬的欄位其中一邊會自動調整成對應原比例的直。

我希望可以支援所有主流圖片格式,不過最主要是要能夠保留 gif 動畫的前提下,縮放後並儲存到來源文件夾。

GPT4

好的,請查看以下的 PowerShell GUI 程式碼。這個程式將根據您的要求製作一個圖片縮放工具,並支援保留 GIF 動畫。注意,需要安裝 ImageMagick 來處理圖像縮放和保留動畫。

請先安裝 ImageMagick,並將其添加到您的系統環境變量中。

Add-Type -AssemblyName System.Windows.Forms
Add-Type -TypeDefinition @"
using System;
using System.Windows.Forms;

public class FileDropLabel : Label
{
    public FileDropLabel()
    {
        AllowDrop = true;
        DragEnter += (s, e) =>
        {
            if (e.Data.GetDataPresent(DataFormats.FileDrop)) e.Effect = DragDropEffects.Copy;
        };
    }
}
"@

function UpdateAspectRatio {
    if ($checkboxMaintainAspectRatio.Checked) {
        if ($textboxWidth.Focused) {
            $height = [int]($textboxWidth.Text) * $originalHeight / $originalWidth
            $textboxHeight.Text = [math]::Round($height)
        } elseif ($textboxHeight.Focused) {
            $width = [int]($textboxHeight.Text) * $originalWidth / $originalHeight
            $textboxWidth.Text = [math]::Round($width)
        }
    }
}

$mainForm = New-Object System.Windows.Forms.Form
$mainForm.Text = 'Image Resizer'
$mainForm.Width = 400
$mainForm.Height = 250

$labelDropImage = New-Object FileDropLabel
$labelDropImage.Text = 'Drag and drop an image here'
$labelDropImage.Size = New-Object System.Drawing.Size(350, 50)
$labelDropImage.Location = New-Object System.Drawing.Point(20, 20)
$labelDropImage.BackColor = [System.Drawing.SystemColors]::ControlLight
$labelDropImage.TextAlign = [System.Drawing.ContentAlignment]::MiddleCenter
$labelDropImage.BorderStyle = [System.Windows.Forms.BorderStyle]::FixedSingle
$labelDropImage.Add_DragDrop({
    $files = $_.Data.GetData([Windows.Forms.DataFormats]::FileDrop)
    if ($files.Count -eq 1 -and [System.IO.File]::Exists($files[0])) {
        $imageExtensions = @('.jpg', '.jpeg', '.png', '.bmp', '.gif')
        $fileExtension = [System.IO.Path]::GetExtension($files[0]).ToLower()
        if ($imageExtensions -contains $fileExtension) {
            $originalImage = [System.Drawing.Image]::FromFile($files[0])
            $originalWidth = $originalImage.Width
            $originalHeight = $originalImage.Height
            $textboxWidth.Text = $originalWidth
            $textboxHeight.Text = $originalHeight
            $inputImagePath = $files[0]
            $labelDropImage.Text = $inputImagePath
        } else {
            [System.Windows.Forms.MessageBox]::Show('Unsupported image format.', 'Error', [System.Windows.Forms.MessageBoxButtons]::OK, [System.Windows.Forms.MessageBoxIcon]::Error)
        }
    }
})
$mainForm.Controls.Add($labelDropImage)

$labelWidth = New-Object System.Windows.Forms.Label
$labelWidth.Text = 'Width:'
$labelWidth.Location = New-Object System.Drawing.Point(20, 80)
$mainForm.Controls.Add($labelWidth)

$text

Hollen9

請繼續,從
‵‵‵
$mainForm.Controls.Add($labelDropImage)

$labelWidth = New-Object System.Windows.Forms.Label
$labelWidth.Text = 'Width:'
$labelWidth.Location = New-Object System.Drawing.Point(20, 80)
$mainForm.Controls.Add($labelWidth)
‵‵‵
接續

GPT4

好的,請參考以下程式碼:

$textboxWidth = New-Object System.Windows.Forms.TextBox
$textboxWidth.Location = New-Object System.Drawing.Point(80, 80)
$textboxWidth.Size = New-Object System.Drawing.Size(50, 20)
$textboxWidth.Add_Leave({ UpdateAspectRatio })
$mainForm.Controls.Add($textboxWidth)

$labelHeight = New-Object System.Windows.Forms.Label
$labelHeight.Text = 'Height:'
$labelHeight.Location = New-Object System.Drawing.Point(150, 80)
$mainForm.Controls.Add($labelHeight)

$textboxHeight = New-Object System.Windows.Forms.TextBox
$textboxHeight.Location = New-Object System.Drawing.Point(210, 80)
$textboxHeight.Size = New-Object System.Drawing.Size(50, 20)
$textboxHeight.Add_Leave({ UpdateAspectRatio })
$mainForm.Controls.Add($textboxHeight)

$checkboxMaintainAspectRatio = New-Object System.Windows.Forms.CheckBox
$checkboxMaintainAspectRatio.Text = 'Maintain Aspect Ratio'
$checkboxMaintainAspectRatio.Location = New-Object System.Drawing.Point(20, 110)
$checkboxMaintainAspectRatio.Checked = $true
$mainForm.Controls.Add($checkboxMaintainAspectRatio)

$buttonResize = New-Object System.Windows.Forms.Button
$buttonResize.Text = 'Resize Image'
$buttonResize.Location = New-Object System.Drawing.Point(20, 140)
$buttonResize.Size = New-Object System.Drawing.Size(100, 30)
$buttonResize.Add_Click({
    if (-not [string]::IsNullOrEmpty($inputImagePath)) {
        $outputImagePath = [System.IO.Path]::ChangeExtension($inputImagePath, '_resized' + [System.IO.Path]::GetExtension($inputImagePath))
        $resizeCommand = "magick `"$inputImagePath`" -resize $textboxWidth.Text`x$textboxHeight.Text `"$outputImagePath`""
        try {
            $resizeResult = Invoke-Expression -Command $resizeCommand
            [System.Windows.Forms.MessageBox]::Show("Image resized and saved as `n$outputImagePath", 'Success', [System.Windows.Forms.MessageBoxButtons]::OK, [System.Windows.Forms.MessageBoxIcon]::Information)
        } catch {
            [System.Windows.Forms.MessageBox]::Show('Error occurred during resizing.', 'Error', [System.Windows.Forms.MessageBoxButtons]::OK, [System.Windows.Forms.MessageBoxIcon]::Error)
        }
    } else {
        [System.Windows.Forms.MessageBox]::Show('Please drag and drop an image to be resized.', 'Error', [System.Windows.Forms.MessageBoxButtons]::OK, [System.Windows.Forms.MessageBoxIcon]::Error)
    }
})
$mainForm.Controls.Add($buttonResize)

$mainForm.Add_Closing({
    $mainForm.Dispose()
})
[void][System.Windows.Forms.Application]::Run($mainForm)

這段程式碼將繼續創建圖形界面,包括寬度、高度的標籤和文本框,保持長寬比的複選框以及用於執行縮放操作的按鈕。當用戶拖曳圖像到界面並點擊“Resize Image”按鈕時,將使用 ImageMagick 對圖像進行縮放,並將結果保存到源文件夾中。

Hollen9

程式執行我可以看到視窗 GUI,但是 powershell 的 console 有報錯:

PS C:\Users\Hollen9> . 'c:\Program Files (Portable)\SomePowershell\ImageResize - DEV.ps1'
Add-Type : c:\Users\Hollen9\AppData\Local\Temp\gsrfdomm.0.cs(2) : The type or namespace name 'Forms' does not exist in the namespace 'System.Windows' (are you missing an assembly reference?)
c:\Users\Hollen9\AppData\Local\Temp\gsrfdomm.0.cs(1) : using System;
c:\Users\Hollen9\AppData\Local\Temp\gsrfdomm.0.cs(2) : >>> using System.Windows.Forms;
c:\Users\Hollen9\AppData\Local\Temp\gsrfdomm.0.cs(3) :
At C:\Program Files (Portable)\SomePowershell\ImageResize - DEV.ps1:2 char:1
+ Add-Type -TypeDefinition @"
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidData: (Microsoft.Power...peCompilerError:AddTypeCompilerError) [Add-Type], Exception
    + FullyQualifiedErrorId : SOURCE_CODE_ERROR,Microsoft.PowerShell.Commands.AddTypeCommand

Add-Type : c:\Users\Hollen9\AppData\Local\Temp\gsrfdomm.0.cs(4) : The type or namespace name 'Label' could not be found (are you missing a using directive or an assembly reference?)
c:\Users\Hollen9\AppData\Local\Temp\gsrfdomm.0.cs(3) :
c:\Users\Hollen9\AppData\Local\Temp\gsrfdomm.0.cs(4) : >>> public class FileDropLabel : Label
c:\Users\Hollen9\AppData\Local\Temp\gsrfdomm.0.cs(5) : {
At C:\Program Files (Portable)\SomePowershell\ImageResize - DEV.ps1:2 char:1
+ Add-Type -TypeDefinition @"
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidData: (Microsoft.Power...peCompilerError:AddTypeCompilerError) [Add-Type], Exception
    + FullyQualifiedErrorId : SOURCE_CODE_ERROR,Microsoft.PowerShell.Commands.AddTypeCommand

Add-Type : Cannot add type. Compilation errors occurred.
At C:\Program Files (Portable)\SomePowershell\ImageResize - DEV.ps1:2 char:1
+ Add-Type -TypeDefinition @"
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidData: (:) [Add-Type], InvalidOperationException
    + FullyQualifiedErrorId : COMPILER_ERRORS,Microsoft.PowerShell.Commands.AddTypeCommand

New-Object : Cannot find type [FileDropLabel]: verify that the assembly containing this type is loaded.
At C:\Program Files (Portable)\SomePowershell\ImageResize - DEV.ps1:36 char:19
+ $labelDropImage = New-Object FileDropLabel
+                   ~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidType: (:) [New-Object], PSArgumentException
    + FullyQualifiedErrorId : TypeNotFound,Microsoft.PowerShell.Commands.NewObjectCommand

The property 'Text' cannot be found on this object. Verify that the property exists and can be set.
At C:\Program Files (Portable)\SomePowershell\ImageResize - DEV.ps1:37 char:1
+ $labelDropImage.Text = 'Drag and drop an image here'
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidOperation: (:) [], RuntimeException
    + FullyQualifiedErrorId : PropertyNotFound

The property 'Size' cannot be found on this object. Verify that the property exists and can be set.
At C:\Program Files (Portable)\SomePowershell\ImageResize - DEV.ps1:38 char:1
+ $labelDropImage.Size = New-Object System.Drawing.Size(350, 50)
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidOperation: (:) [], RuntimeException
    + FullyQualifiedErrorId : PropertyNotFound

The property 'Location' cannot be found on this object. Verify that the property exists and can be set.
At C:\Program Files (Portable)\SomePowershell\ImageResize - DEV.ps1:39 char:1
+ $labelDropImage.Location = New-Object System.Drawing.Point(20, 20)
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidOperation: (:) [], RuntimeException
    + FullyQualifiedErrorId : PropertyNotFound

The property 'BackColor' cannot be found on this object. Verify that the property exists and can be set.
At C:\Program Files (Portable)\SomePowershell\ImageResize - DEV.ps1:40 char:1
+ $labelDropImage.BackColor = [System.Drawing.SystemColors]::ControlLig ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidOperation: (:) [], RuntimeException
    + FullyQualifiedErrorId : PropertyNotFound

The property 'TextAlign' cannot be found on this object. Verify that the property exists and can be set.
At C:\Program Files (Portable)\SomePowershell\ImageResize - DEV.ps1:41 char:1
+ $labelDropImage.TextAlign = [System.Drawing.ContentAlignment]::Middle ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidOperation: (:) [], RuntimeException
    + FullyQualifiedErrorId : PropertyNotFound

The property 'BorderStyle' cannot be found on this object. Verify that the property exists and can be set.
At C:\Program Files (Portable)\SomePowershell\ImageResize - DEV.ps1:42 char:1
+ $labelDropImage.BorderStyle = [System.Windows.Forms.BorderStyle]::Fix ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidOperation: (:) [], RuntimeException
    + FullyQualifiedErrorId : PropertyNotFound

You cannot call a method on a null-valued expression.
At C:\Program Files (Portable)\SomePowershell\ImageResize - DEV.ps1:43 char:1
+ $labelDropImage.Add_DragDrop({
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidOperation: (:) [], RuntimeException
    + FullyQualifiedErrorId : InvokeMethodOnNull

GPT4

抱歉之前的回答中出現了問題。請使用以下修正後的程式碼:

Add-Type -AssemblyName System.Windows.Forms
Add-Type -TypeDefinition @"
using System;
using System.Windows.Forms;

public class FileDropLabel : Label
{
    public FileDropLabel()
    {
        AllowDrop = true;
        DragEnter += (s, e) =>
        {
            if (e.Data.GetDataPresent(DataFormats.FileDrop)) e.Effect = DragDropEffects.Copy;
        };
    }
}
"@ -ReferencedAssemblies @('System.Windows.Forms.dll', 'System.Drawing.dll')

# 省略與上一段程式碼相同的部分...

[void][System.Windows.Forms.Application]::EnableVisualStyles()
[void][System.Windows.Forms.Application]::Run($mainForm)

這個修正將在 Add-Type 指令中添加了參數 -ReferencedAssemblies 以引用所需的組件,並在最後一行添加了 [void][System.Windows.Forms.Application]::EnableVisualStyles() 以應用主題樣式。請確保在 PowerShell 中以管理員身份運行此程式,以避免出現權限問題。

Hollen9

Weight 和 Height 的 Label 寬度太寬了,把右側的 Textbox 蓋住了

GPT4

抱歉造成困擾,請將 $labelWidth$labelHeightSize 屬性進行調整,以避免覆蓋相鄰的控件。請參考以下修改後的程式碼:

$labelWidth = New-Object System.Windows.Forms.Label
$labelWidth.Text = 'Width:'
$labelWidth.Location = New-Object System.Drawing.Point(20, 80)
$labelWidth.Size = New-Object System.Drawing.Size(50, 20)  # 修改後的 Size 屬性
$mainForm.Controls.Add($labelWidth)

$labelHeight = New-Object System.Windows.Forms.Label
$labelHeight.Text = 'Height:'
$labelHeight.Location = New-Object System.Drawing.Point(150, 80)
$labelHeight.Size = New-Object System.Drawing.Size(50, 20)  # 修改後的 Size 屬性
$mainForm.Controls.Add($labelHeight)

# 省略與上一段程式碼相同的部分...

這樣應該能避免覆蓋問題。請確保根據需要調整其他控件的位置和大小。

Hollen9

我發現當我還沒拖曳圖片進去時,去修改尺寸會出現以下錯誤:

Attempted to divide by zero.
At C:\Program Files (Portable)\SomePowershell\ImageResize - DEV.ps1:25 char:13
+             $width = [int]($textboxHeight.Text) * $originalWidth / $o ...
+             ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (:) [], RuntimeException
    + FullyQualifiedErrorId : RuntimeException

程式還是可以繼續執行就是了

GPT4

抱歉造成困擾。這是因為在拖曳圖片之前, $originalWidth$originalHeight 的值為零。要解決這個問題,可以在 UpdateAspectRatio 函數開頭添加一個條件,檢查 $originalWidth$originalHeight 是否大於零。請參考以下修改後的程式碼:

function UpdateAspectRatio {
    if ($checkboxMaintainAspectRatio.Checked -and $originalWidth -gt 0 -and $originalHeight -gt 0) {
        if ($textboxWidth.Focused) {
            $height = [int]($textboxWidth.Text) * $originalHeight / $originalWidth
            $textboxHeight.Text = [string]$height
        } elseif ($textboxHeight.Focused) {
            $width = [int]($textboxHeight.Text) * $originalWidth / $originalHeight
            $textboxWidth.Text = [string]$width
        }
    }
}

# 省略與上一段程式碼相同的部分...

這樣在尚未拖曳圖片時,修改尺寸不會觸發錯誤。

Hollen9

我發現 $originalWidth 和 $originalHeight 在圖片拖曳進去的時候的確有正確數值,但當我在讓 長或 寬的 textbox 去 focus 的時候,$originalWidth 和 $originalHeight 都是 ""

GPT4

抱歉,這是因為 $originalWidth$originalHeightUpdateAspectRatio 函數內部作為局部變量使用,導致在 UpdateAspectRatio 函數中無法訪問它們的值。為了解決這個問題,請將 $originalWidth$originalHeight 定義為全局變量,並在 Add_DragDrop 事件處理程序中更新它們的值。以下是修改後的程式碼:

$originalWidth = 0
$originalHeight = 0

$labelDropImage.Add_DragDrop({
    $files = $_.Data.GetData([System.Windows.Forms.DataFormats]::FileDrop)
    if ($files -and $files.Count -gt 0) {
        $filePath = $files[0]
        $image = [System.Drawing.Image]::FromFile($filePath)
        $originalWidth = $image.Width
        $originalHeight = $image.Height
        $textboxWidth.Text = [string]$originalWidth
        $textboxHeight.Text = [string]$originalHeight
    }
})

# 省略與上一段程式碼相同的部分...

這樣應該可以解決 $originalWidth$originalHeightUpdateAspectRatio 函數中無法訪問的問題。

Hollen9

總之我程式現在如下所示,到了 UpdateAspectRatio 那兩個變數還是恆為 0。

Add-Type -AssemblyName System.Windows.Forms
Add-Type -TypeDefinition @"
using System;
using System.Windows.Forms;

public class FileDropLabel : Label
{
    public FileDropLabel()
    {
        AllowDrop = true;
        DragEnter += (s, e) =>
        {
            if (e.Data.GetDataPresent(DataFormats.FileDrop)) e.Effect = DragDropEffects.Copy;
        };
    }
}
"@ -ReferencedAssemblies @('System.Windows.Forms.dll', 'System.Drawing.dll')

$originalWidth = 0
$originalHeight = 0

function UpdateAspectRatio {
    if ($checkboxMaintainAspectRatio.Checked -and $originalWidth -gt 0 -and $originalHeight -gt 0) {
        if ($textboxWidth.Focused) {
            $height = [int]($textboxWidth.Text) * $originalHeight / $originalWidth
            $textboxHeight.Text = [string]$height
        } elseif ($textboxHeight.Focused) {
            $width = [int]($textboxHeight.Text) * $originalWidth / $originalHeight
            $textboxWidth.Text = [string]$width
        }
    }
}

$mainForm = New-Object System.Windows.Forms.Form
$mainForm.Text = 'Image Resizer'
$mainForm.Width = 400
$mainForm.Height = 250

$labelDropImage = New-Object FileDropLabel
$labelDropImage.Text = 'Drag and drop an image here'
$labelDropImage.Size = New-Object System.Drawing.Size(350, 50)
$labelDropImage.Location = New-Object System.Drawing.Point(20, 20)
$labelDropImage.BackColor = [System.Drawing.SystemColors]::ControlLight
$labelDropImage.TextAlign = [System.Drawing.ContentAlignment]::MiddleCenter
$labelDropImage.BorderStyle = [System.Windows.Forms.BorderStyle]::FixedSingle
$labelDropImage.Add_DragDrop({
    $files = $_.Data.GetData([Windows.Forms.DataFormats]::FileDrop)
    if ($files.Count -eq 1 -and [System.IO.File]::Exists($files[0])) {
        $imageExtensions = @('.jpg', '.jpeg', '.png', '.bmp', '.gif')
        $fileExtension = [System.IO.Path]::GetExtension($files[0]).ToLower()
        if ($imageExtensions -contains $fileExtension) {
            $originalImage = [System.Drawing.Image]::FromFile($files[0])
            $originalWidth = $originalImage.Width
            $originalHeight = $originalImage.Height
            $textboxWidth.Text = $originalWidth
            $textboxHeight.Text = $originalHeight
            $inputImagePath = $files[0]
            $labelDropImage.Text = $inputImagePath
        } else {
            [System.Windows.Forms.MessageBox]::Show('Unsupported image format.', 'Error', [System.Windows.Forms.MessageBoxButtons]::OK, [System.Windows.Forms.MessageBoxIcon]::Error)
        }
    }
})
$mainForm.Controls.Add($labelDropImage)

$labelWidth = New-Object System.Windows.Forms.Label
$labelWidth.Text = 'Width:'
$labelWidth.Location = New-Object System.Drawing.Point(20, 80)
$labelWidth.Size = New-Object System.Drawing.Size(50, 20)
$mainForm.Controls.Add($labelWidth)

$textboxWidth = New-Object System.Windows.Forms.TextBox
$textboxWidth.Location = New-Object System.Drawing.Point(80, 80)
$textboxWidth.Size = New-Object System.Drawing.Size(50, 20)
$textboxWidth.Add_Leave({ UpdateAspectRatio })
$mainForm.Controls.Add($textboxWidth)

$labelHeight = New-Object System.Windows.Forms.Label
$labelHeight.Text = 'Height:'
$labelHeight.Location = New-Object System.Drawing.Point(150, 80)
$labelHeight.Size = New-Object System.Drawing.Size(50, 20) 

$mainForm.Controls.Add($labelHeight)

$textboxHeight = New-Object System.Windows.Forms.TextBox
$textboxHeight.Location = New-Object System.Drawing.Point(210, 80)
$textboxHeight.Size = New-Object System.Drawing.Size(50, 20)
$textboxHeight.Add_Leave({ UpdateAspectRatio })
$mainForm.Controls.Add($textboxHeight)

$checkboxMaintainAspectRatio = New-Object System.Windows.Forms.CheckBox
$checkboxMaintainAspectRatio.Text = 'Maintain Aspect Ratio'
$checkboxMaintainAspectRatio.Location = New-Object System.Drawing.Point(20, 110)
$checkboxMaintainAspectRatio.Checked = $true
$mainForm.Controls.Add($checkboxMaintainAspectRatio)

$buttonResize = New-Object System.Windows.Forms.Button
$buttonResize.Text = 'Resize Image'
$buttonResize.Location = New-Object System.Drawing.Point(20, 140)
$buttonResize.Size = New-Object System.Drawing.Size(100, 30)
$buttonResize.Add_Click({
    if (-not [string]::IsNullOrEmpty($inputImagePath)) {
        $outputImagePath = [System.IO.Path]::ChangeExtension($inputImagePath, '_resized' + [System.IO.Path]::GetExtension($inputImagePath))
        $resizeCommand = "magick `"$inputImagePath`" -resize $textboxWidth.Text`x$textboxHeight.Text `"$outputImagePath`""
        try {
            $resizeResult = Invoke-Expression -Command $resizeCommand
            [System.Windows.Forms.MessageBox]::Show("Image resized and saved as `n$outputImagePath", 'Success', [System.Windows.Forms.MessageBoxButtons]::OK, [System.Windows.Forms.MessageBoxIcon]::Information)
        } catch {
            [System.Windows.Forms.MessageBox]::Show('Error occurred during resizing.', 'Error', [System.Windows.Forms.MessageBoxButtons]::OK, [System.Windows.Forms.MessageBoxIcon]::Error)
        }
    } else {
        [System.Windows.Forms.MessageBox]::Show('Please drag and drop an image to be resized.', 'Error', [System.Windows.Forms.MessageBoxButtons]::OK, [System.Windows.Forms.MessageBoxIcon]::Error)
    }
})
$mainForm.Controls.Add($buttonResize)

$mainForm.Add_Closing({
    $mainForm.Dispose()
})
[void][System.Windows.Forms.Application]::EnableVisualStyles()
[void][System.Windows.Forms.Application]::Run($mainForm)

GPT4

謝謝您的反饋。我注意到您使用 Add_Leave 事件,但是它在離開輸入框時才會觸發。為了解決這個問題,請將原本的 Add_Leave 事件更改為 Add_TextChanged 事件。這樣一來,在您修改寬度或高度的時候,它就會立即更新另一個數值,保持寬高比。

修改後的程式碼:

$textboxWidth.Add_TextChanged({ UpdateAspectRatio })
$mainForm.Controls.Add($textboxWidth)

# ...

$textboxHeight.Add_TextChanged({ UpdateAspectRatio })
$mainForm.Controls.Add($textboxHeight)

這樣修改後,應該可以在輸入框中修改寬度或高度時立即更新另一個數值,並且保持寬高比。請注意,如果您在輸入框中輸入非數字字符,可能會導致錯誤。如果需要防止非數字字符的輸入,可以進一步修改腳本以檢查輸入值。

Hollen9

這個修改不錯是不錯,我也有想做。但你沒有討懂我的問題:
我說恆為零,是因為 Drop 事件中存取的 $originalWidth 和 $originalHeight 是區域變數的樣子,在不同 Scope 的 UpdateAspectRatio() 沒辦法獲得變數的新值,才會一直都是最初宣告的 0

GPT4

抱歉,我理解錯誤。請將 $originalWidth$originalHeight 放在全局變量的位置,可以將它們定義為 [ref] 類型,以便在多個範疇中存取和修改它們。

請將以下程式碼:

$originalWidth = 0
$originalHeight = 0

替換為:

$global:originalWidth = [ref]0
$global:originalHeight = [ref]0

然後,在 UpdateAspectRatio 函數和拖放事件中,用 $global:originalWidth.Value$global:originalHeight.Value 替換 $originalWidth$originalHeight

以下是修改後的 UpdateAspectRatio 函數和拖放事件:

function UpdateAspectRatio {
    if ($checkboxMaintainAspectRatio.Checked -and $global:originalWidth.Value -gt 0 -and $global:originalHeight.Value -gt 0) {
        if ($textboxWidth.Focused) {
            $height = [int]($textboxWidth.Text) * $global:originalHeight.Value / $global:originalWidth.Value
            $textboxHeight.Text = [string]$height
        } elseif ($textboxHeight.Focused) {
            $width = [int]($textboxHeight.Text) * $global:originalWidth.Value / $global:originalHeight.Value
            $textboxWidth.Text = [string]$width
        }
    }
}

$labelDropImage.Add_DragDrop({
    $files = $_.Data.GetData([Windows.Forms.DataFormats]::FileDrop)
    if ($files.Count -eq 1 -and [System.IO.File]::Exists($files[0])) {
        $imageExtensions = @('.jpg', '.jpeg', '.png', '.bmp', '.gif')
        $fileExtension = [System.IO.Path]::GetExtension($files[0]).ToLower()
        if ($imageExtensions -contains $fileExtension) {
            $originalImage = [System.Drawing.Image]::FromFile($files[0])
            $global:originalWidth.Value = $originalImage.Width
            $global:originalHeight.Value = $originalImage.Height
            $textboxWidth.Text = $global:originalWidth.Value
            $textboxHeight.Text = $global:originalHeight.Value
            $inputImagePath = $files[0]
            $labelDropImage.Text = $inputImagePath
        } else {
            [System.Windows.Forms.MessageBox]::Show('Unsupported image format.', 'Error', [System.Windows.Forms.MessageBoxButtons]::OK, [System.Windows.Forms.MessageBoxIcon]::Error)
        }
    }
})

現在,當您修改寬度或高度時,UpdateAspectRatio 函數應該能夠正確地讀取和更新 $global:originalWidth.Value$global:originalHeight.Value

Hollen9

長寬問題解決了,但我發現 $inputImagePath 等變數也有類似的問題

GPT4

對於 $inputImagePath,您可以採用與 $originalWidth$originalHeight 相同的解決方案。將 $inputImagePath 定義為全局 [ref] 變量,並在需要時使用 $global:inputImagePath.Value 存取和修改它。

首先,將以下程式碼:

$inputImagePath = ""

替換為:

$global:inputImagePath = [ref]""

然後在拖放事件和按鈕點擊事件中,使用 $global:inputImagePath.Value 替換 $inputImagePath

以下是修改後的拖放事件和按鈕點擊事件:

$labelDropImage.Add_DragDrop({
    $files = $_.Data.GetData([Windows.Forms.DataFormats]::FileDrop)
    if ($files.Count -eq 1 -and [System.IO.File]::Exists($files[0])) {
        $imageExtensions = @('.jpg', '.jpeg', '.png', '.bmp', '.gif')
        $fileExtension = [System.IO.Path]::GetExtension($files[0]).ToLower()
        if ($imageExtensions -contains $fileExtension) {
            $originalImage = [System.Drawing.Image]::FromFile($files[0])
            $global:originalWidth.Value = $originalImage.Width
            $global:originalHeight.Value = $originalImage.Height
            $textboxWidth.Text = $global:originalWidth.Value
            $textboxHeight.Text = $global:originalHeight.Value
            $global:inputImagePath.Value = $files[0]
            $labelDropImage.Text = $global:inputImagePath.Value
        } else {
            [System.Windows.Forms.MessageBox]::Show('Unsupported image format.', 'Error', [System.Windows.Forms.MessageBoxButtons]::OK, [System.Windows.Forms.MessageBoxIcon]::Error)
        }
    }
})

$buttonResize.Add_Click({
    if (-not [string]::IsNullOrEmpty($global:inputImagePath.Value)) {
        $outputImagePath = [System.IO.Path]::ChangeExtension($global:inputImagePath.Value, '_resized' + [System.IO.Path]::GetExtension($global:inputImagePath.Value))
        $resizeCommand = "magick `"$global:inputImagePath.Value`" -resize $textboxWidth.Text`x$textboxHeight.Text `"$outputImagePath`""
        try {
            $resizeResult = Invoke-Expression -Command $resizeCommand
            [System.Windows.Forms.MessageBox]::Show("Image resized and saved as `n$outputImagePath", 'Success', [System.Windows.Forms.MessageBoxButtons]::OK, [System.Windows.Forms.MessageBoxIcon]::Information)
        } catch {
            [System.Windows.Forms.MessageBox]::Show('Error occurred during resizing.', 'Error', [System.Windows.Forms.MessageBoxButtons]::OK, [System.Windows.Forms.MessageBoxIcon]::Error)
        }
    } else {
        [System.Windows.Forms.MessageBox]::Show('Please drag and drop an image to be resized.', 'Error', [System.Windows.Forms.MessageBoxButtons]::OK, [System.Windows.Forms.MessageBoxIcon]::Error)
    }
})

現在,$global:inputImagePath.Value 應該在需要時正確地存取和修改。

Hollen9

catch {

    }

我要怎麼改成 能夠顯示錯誤訊息的 像是 e.Message 之類的

GPT4

要在錯

Hollen9

剛剛 OpenAI 出現錯誤,我看到你的回答長這樣:

要在錯

GPT4

抱歉剛才的回答被截斷了。以下是完整的回答:

要在錯誤對話框中顯示特定的錯誤訊息,您可以使用 $_ 變量來獲取當前錯誤的詳細信息。在 catch 塊中,您可以使用 Exception.Message 屬性來獲取有關異常的更多信息。您可以通過修改 catch 塊中的代碼來顯示錯誤訊息,如下所示:

catch {
    $errorMessage = $_.Exception.Message
    [System.Windows.Forms.MessageBox]::Show("Error occurred during resizing: `n$errorMessage", 'Error', [System.Windows.Forms.MessageBoxButtons]::OK, [System.Windows.Forms.MessageBoxIcon]::Error)
}

這將在錯誤對話框中顯示當前異常的錯誤訊息。

Hollen9

我看到顯示成功的 MsgBox,但是沒有真的成功 (沒有新的圖片檔)
且 Console 印出以下訊息:

magick.exe: unable to open image 'System.Management.Automation.PSReference1[System.String].Value': No such file or directory @ error/blob.c/OpenBlob/3569.
magick.exe: unable to open module file 'C:\Program Files\ImageMagick\modules\coders\IM_MOD_RL_VALUE_.dll': No such file or directory @ warning/module.c/GetMagickModulePath/677.
magick.exe: no decode delegate for this image format `VALUE' @ error/constitute.c/ReadImage/746.

GPT4

這個錯誤是因為在命令行中的變量引用不正確。您需要將 $inputImagePath$outputImagePath 變量的值直接傳遞給 magick 命令。請修改 $buttonResize.Add_Click 腳本塊如下:

$buttonResize.Add_Click({
    if (-not [string]::IsNullOrEmpty($global:inputImagePath)) {
        $outputImagePath = [System.IO.Path]::ChangeExtension($global:inputImagePath, '_resized' + [System.IO.Path]::GetExtension($global:inputImagePath))
        $resizeCommand = "magick `"$($global:inputImagePath)`" -resize $($textboxWidth.Text)`x$($textboxHeight.Text) `"$($outputImagePath)`""
        try {
            $resizeResult = Invoke-Expression -Command $resizeCommand
            [System.Windows.Forms.MessageBox]::Show("Image resized and saved as `n$outputImagePath", 'Success', [System.Windows.Forms.MessageBoxButtons]::OK, [System.Windows.Forms.MessageBoxIcon]::Information)
        } catch {
            $errorMessage = $_.Exception.Message
            [System.Windows.Forms.MessageBox]::Show("Error occurred during resizing: `n$errorMessage", 'Error', [System.Windows.Forms.MessageBoxButtons]::OK, [System.Windows.Forms.MessageBoxIcon]::Error)
        }
    } else {
        [System.Windows.Forms.MessageBox]::Show('Please drag and drop an image to be resized.', 'Error', [System.Windows.Forms.MessageBoxButtons]::OK, [System.Windows.Forms.MessageBoxIcon]::Error)
    }
})

這樣應該可以解決問題。請確保您使用的是 global: 修飾符來訪問全局變量。

Hollen9

Cannot convert value "\" to type "System.Int32". Error: "Input string was not in a correct format."
At C:\Program Files (Portable)\SomePowershell\ImageResize - DEV.ps1:27 char:13
+             $height = [int]($textboxWidth.Text) * $global:originalHei ...
+             ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidArgument: (:) [], RuntimeException
    + FullyQualifiedErrorId : InvalidCastFromStringToInteger

Cannot convert value "\" to type "System.Int32". Error: "Input string was not in a correct format."
At C:\Program Files (Portable)\SomePowershell\ImageResize - DEV.ps1:27 char:13
+             $height = [int]($textboxWidth.Text) * $global:originalHei ...
+             ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidArgument: (:) [], RuntimeException
    + FullyQualifiedErrorId : InvalidCastFromStringToInteger

magick.exe: unable to open image 'System.Management.Automation.PSReference1[System.String]': No such file or directory @ error/blob.c/OpenBlob/3569.
magick.exe: no decode delegate for this image format `' @ error/constitute.c/ReadImage/746.

我現在全部的程式長這樣:

Add-Type -AssemblyName System.Windows.Forms
Add-Type -TypeDefinition @"
using System;
using System.Windows.Forms;

public class FileDropLabel : Label
{
    public FileDropLabel()
    {
        AllowDrop = true;
        DragEnter += (s, e) =>
        {
            if (e.Data.GetDataPresent(DataFormats.FileDrop)) e.Effect = DragDropEffects.Copy;
        };
    }
}
"@ -ReferencedAssemblies @('System.Windows.Forms.dll', 'System.Drawing.dll')

$global:originalWidth = [ref]0
$global:originalHeight = [ref]0
$global:inputImagePath = [ref]""

function UpdateAspectRatio {
    if ($checkboxMaintainAspectRatio.Checked -and $global:originalWidth.Value -gt 0 -and $global:originalHeight.Value -gt 0) {
        if ($textboxWidth.Focused) {
            $height = [int]($textboxWidth.Text) * $global:originalHeight.Value / $global:originalWidth.Value
            $textboxHeight.Text = [string]$height
        } elseif ($textboxHeight.Focused) {
            $width = [int]($textboxHeight.Text) * $global:originalWidth.Value / $global:originalHeight.Value
            $textboxWidth.Text = [string]$width
        }
    }
}

$mainForm = New-Object System.Windows.Forms.Form
$mainForm.Text = 'Image Resizer'
$mainForm.Width = 400
$mainForm.Height = 250

$labelDropImage = New-Object FileDropLabel
$labelDropImage.Text = 'Drag and drop an image here'
$labelDropImage.Size = New-Object System.Drawing.Size(350, 50)
$labelDropImage.Location = New-Object System.Drawing.Point(20, 20)
$labelDropImage.BackColor = [System.Drawing.SystemColors]::ControlLight
$labelDropImage.TextAlign = [System.Drawing.ContentAlignment]::MiddleCenter
$labelDropImage.BorderStyle = [System.Windows.Forms.BorderStyle]::FixedSingle
$labelDropImage.Add_DragDrop({
    $files = $_.Data.GetData([Windows.Forms.DataFormats]::FileDrop)
    if ($files.Count -eq 1 -and [System.IO.File]::Exists($files[0])) {
        $imageExtensions = @('.jpg', '.jpeg', '.png', '.bmp', '.gif')
        $fileExtension = [System.IO.Path]::GetExtension($files[0]).ToLower()
        if ($imageExtensions -contains $fileExtension) {
            $originalImage = [System.Drawing.Image]::FromFile($files[0])
            $global:originalWidth.Value = $originalImage.Width
            $global:originalHeight.Value = $originalImage.Height
            $textboxWidth.Text = $global:originalWidth.Value
            $textboxHeight.Text = $global:originalHeight.Value
            $global:inputImagePath.Value = $files[0]
            $labelDropImage.Text = $global:inputImagePath.Value
        } else {
            [System.Windows.Forms.MessageBox]::Show('Unsupported image format.', 'Error', [System.Windows.Forms.MessageBoxButtons]::OK, [System.Windows.Forms.MessageBoxIcon]::Error)
        }
    }
})

$mainForm.Controls.Add($labelDropImage)

$labelWidth = New-Object System.Windows.Forms.Label
$labelWidth.Text = 'Width:'
$labelWidth.Location = New-Object System.Drawing.Point(20, 80)
$labelWidth.Size = New-Object System.Drawing.Size(50, 20)
$mainForm.Controls.Add($labelWidth)

$textboxWidth = New-Object System.Windows.Forms.TextBox
$textboxWidth.Location = New-Object System.Drawing.Point(80, 80)
$textboxWidth.Size = New-Object System.Drawing.Size(50, 20)
# $textboxWidth.Add_Leave({ UpdateAspectRatio })
$textboxWidth.Add_TextChanged({ UpdateAspectRatio })
$mainForm.Controls.Add($textboxWidth)

$labelHeight = New-Object System.Windows.Forms.Label
$labelHeight.Text = 'Height:'
$labelHeight.Location = New-Object System.Drawing.Point(150, 80)
$labelHeight.Size = New-Object System.Drawing.Size(50, 20) 

$mainForm.Controls.Add($labelHeight)

$textboxHeight = New-Object System.Windows.Forms.TextBox
$textboxHeight.Location = New-Object System.Drawing.Point(210, 80)
$textboxHeight.Size = New-Object System.Drawing.Size(50, 20)
# $textboxHeight.Add_Leave({ UpdateAspectRatio })
$textboxHeight.Add_TextChanged({ UpdateAspectRatio })
$mainForm.Controls.Add($textboxHeight)

$checkboxMaintainAspectRatio = New-Object System.Windows.Forms.CheckBox
$checkboxMaintainAspectRatio.Text = 'Maintain Aspect Ratio'
$checkboxMaintainAspectRatio.Location = New-Object System.Drawing.Point(20, 110)
$checkboxMaintainAspectRatio.Checked = $true
$mainForm.Controls.Add($checkboxMaintainAspectRatio)

$buttonResize = New-Object System.Windows.Forms.Button
$buttonResize.Text = 'Resize Image'
$buttonResize.Location = New-Object System.Drawing.Point(20, 140)
$buttonResize.Size = New-Object System.Drawing.Size(100, 30)
$buttonResize.Add_Click({
    if (-not [string]::IsNullOrEmpty($global:inputImagePath)) {
        $outputImagePath = [System.IO.Path]::ChangeExtension($global:inputImagePath, '_resized' + [System.IO.Path]::GetExtension($global:inputImagePath))
        $resizeCommand = "magick `"$($global:inputImagePath)`" -resize $($textboxWidth.Text)`x$($textboxHeight.Text) `"$($outputImagePath)`""
        try {
            $resizeResult = Invoke-Expression -Command $resizeCommand
            [System.Windows.Forms.MessageBox]::Show("Image resized and saved as `n$outputImagePath", 'Success', [System.Windows.Forms.MessageBoxButtons]::OK, [System.Windows.Forms.MessageBoxIcon]::Information)
        } catch {
            $errorMessage = $_.Exception.Message
            [System.Windows.Forms.MessageBox]::Show("Error occurred during resizing: `n$errorMessage", 'Error', [System.Windows.Forms.MessageBoxButtons]::OK, [System.Windows.Forms.MessageBoxIcon]::Error)
        }
    } else {
        [System.Windows.Forms.MessageBox]::Show('Please drag and drop an image to be resized.', 'Error', [System.Windows.Forms.MessageBoxButtons]::OK, [System.Windows.Forms.MessageBoxIcon]::Error)
    }
})

$mainForm.Controls.Add($buttonResize)

$mainForm.Add_Closing({
    $mainForm.Dispose()
})
[void][System.Windows.Forms.Application]::EnableVisualStyles()
[void][System.Windows.Forms.Application]::Run($mainForm)

GPT4

對不起,我看到問題了。問題出在將文字框中的值轉換為整數時,可能會有不允許的字符導致轉換失敗。為了解決這個問題,我們可以在進行轉換之前檢查文字框中的值是否為有效的整數。請將UpdateAspectRatio函數更改為以下:

function UpdateAspectRatio {
    if ($checkboxMaintainAspectRatio.Checked -and $global:originalWidth.Value -gt 0 -and $global:originalHeight.Value -gt 0) {
        if ($textboxWidth.Focused) {
            if ([int32]::TryParse($textboxWidth.Text, [ref]$null)) {
                $height = [int]($textboxWidth.Text) * $global:originalHeight.Value / $global:originalWidth.Value
                $textboxHeight.Text = [string]$height
            }
        } elseif ($textboxHeight.Focused) {
            if ([int32]::TryParse($textboxHeight.Text, [ref]$null)) {
                $width = [int]($textboxHeight.Text) * $global:originalWidth.Value / $global:originalHeight.Value
                $textboxWidth.Text = [string]$width
            }
        }
    }
}

這樣應該可以解決輸入的轉換問題。

Hollen9

MsgBox:

Image resized and saved as
System.Management.Automation.PSReference`1[System._resized.String]

Console:

magick.exe: unable to open image 'System.Management.Automation.PSReference1[System.String]': No such file or directory @ error/blob.c/OpenBlob/3569.
magick.exe: no decode delegate for this image format `' @ error/constitute.c/ReadImage/746.

還是失敗

GPT4

對不起,我犯了一個錯誤。我們需要去掉$global:inputImagePath$outputImagePath的引用([ref])。請將以下兩行更改為:

$global:inputImagePath = ""

並將:

$outputImagePath = [System.IO.Path]::ChangeExtension($global:inputImagePath, '_resized' + [System.IO.Path]::GetExtension($global:inputImagePath))

更新為:

$outputImagePath = [System.IO.Path]::ChangeExtension($global:inputImagePath.Value, '_resized' + [System.IO.Path]::GetExtension($global:inputImagePath.Value))

這樣應該可以解決問題。請再試一次,看看這是否有效。

Hollen9

改完之後,我只是拖曳圖片進去,就出錯了,本來還正常的:

The property 'Value' cannot be found on this object. Verify that the property exists and can be set.
At C:\Program Files (Portable)\SomePowershell\ImageResize - DEV.ps1:64 char:13
+             $global:inputImagePath.Value = $files[0]
+             ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidOperation: (:) [], RuntimeException
    + FullyQualifiedErrorId : PropertyAssignmentException

我現在的整體程式長這樣:

Add-Type -AssemblyName System.Windows.Forms
Add-Type -TypeDefinition @"
using System;
using System.Windows.Forms;

public class FileDropLabel : Label
{
    public FileDropLabel()
    {
        AllowDrop = true;
        DragEnter += (s, e) =>
        {
            if (e.Data.GetDataPresent(DataFormats.FileDrop)) e.Effect = DragDropEffects.Copy;
        };
    }
}
"@ -ReferencedAssemblies @('System.Windows.Forms.dll', 'System.Drawing.dll')

$global:originalWidth = [ref]0
$global:originalHeight = [ref]0
$global:inputImagePath = ""

function UpdateAspectRatio {
    if ($checkboxMaintainAspectRatio.Checked -and $global:originalWidth.Value -gt 0 -and $global:originalHeight.Value -gt 0) {
        if ($textboxWidth.Focused) {
            if ([int32]::TryParse($textboxWidth.Text, [ref]$null)) {
                $height = [int]($textboxWidth.Text) * $global:originalHeight.Value / $global:originalWidth.Value
                $textboxHeight.Text = [string]$height
            }
        } elseif ($textboxHeight.Focused) {
            if ([int32]::TryParse($textboxHeight.Text, [ref]$null)) {
                $width = [int]($textboxHeight.Text) * $global:originalWidth.Value / $global:originalHeight.Value
                $textboxWidth.Text = [string]$width
            }
        }
    }
}

$mainForm = New-Object System.Windows.Forms.Form
$mainForm.Text = 'Image Resizer'
$mainForm.Width = 400
$mainForm.Height = 250

$labelDropImage = New-Object FileDropLabel
$labelDropImage.Text = 'Drag and drop an image here'
$labelDropImage.Size = New-Object System.Drawing.Size(350, 50)
$labelDropImage.Location = New-Object System.Drawing.Point(20, 20)
$labelDropImage.BackColor = [System.Drawing.SystemColors]::ControlLight
$labelDropImage.TextAlign = [System.Drawing.ContentAlignment]::MiddleCenter
$labelDropImage.BorderStyle = [System.Windows.Forms.BorderStyle]::FixedSingle
$labelDropImage.Add_DragDrop({
    $files = $_.Data.GetData([Windows.Forms.DataFormats]::FileDrop)
    if ($files.Count -eq 1 -and [System.IO.File]::Exists($files[0])) {
        $imageExtensions = @('.jpg', '.jpeg', '.png', '.bmp', '.gif')
        $fileExtension = [System.IO.Path]::GetExtension($files[0]).ToLower()
        if ($imageExtensions -contains $fileExtension) {
            $originalImage = [System.Drawing.Image]::FromFile($files[0])
            $global:originalWidth.Value = $originalImage.Width
            $global:originalHeight.Value = $originalImage.Height
            $textboxWidth.Text = $global:originalWidth.Value
            $textboxHeight.Text = $global:originalHeight.Value
            $global:inputImagePath.Value = $files[0]
            $labelDropImage.Text = $global:inputImagePath.Value
        } else {
            [System.Windows.Forms.MessageBox]::Show('Unsupported image format.', 'Error', [System.Windows.Forms.MessageBoxButtons]::OK, [System.Windows.Forms.MessageBoxIcon]::Error)
        }
    }
})

$mainForm.Controls.Add($labelDropImage)

$labelWidth = New-Object System.Windows.Forms.Label
$labelWidth.Text = 'Width:'
$labelWidth.Location = New-Object System.Drawing.Point(20, 80)
$labelWidth.Size = New-Object System.Drawing.Size(50, 20)
$mainForm.Controls.Add($labelWidth)

$textboxWidth = New-Object System.Windows.Forms.TextBox
$textboxWidth.Location = New-Object System.Drawing.Point(80, 80)
$textboxWidth.Size = New-Object System.Drawing.Size(50, 20)
# $textboxWidth.Add_Leave({ UpdateAspectRatio })
$textboxWidth.Add_TextChanged({ UpdateAspectRatio })
$mainForm.Controls.Add($textboxWidth)

$labelHeight = New-Object System.Windows.Forms.Label
$labelHeight.Text = 'Height:'
$labelHeight.Location = New-Object System.Drawing.Point(150, 80)
$labelHeight.Size = New-Object System.Drawing.Size(50, 20) 

$mainForm.Controls.Add($labelHeight)

$textboxHeight = New-Object System.Windows.Forms.TextBox
$textboxHeight.Location = New-Object System.Drawing.Point(210, 80)
$textboxHeight.Size = New-Object System.Drawing.Size(50, 20)
# $textboxHeight.Add_Leave({ UpdateAspectRatio })
$textboxHeight.Add_TextChanged({ UpdateAspectRatio })
$mainForm.Controls.Add($textboxHeight)

$checkboxMaintainAspectRatio = New-Object System.Windows.Forms.CheckBox
$checkboxMaintainAspectRatio.Text = 'Maintain Aspect Ratio'
$checkboxMaintainAspectRatio.Location = New-Object System.Drawing.Point(20, 110)
$checkboxMaintainAspectRatio.Checked = $true
$mainForm.Controls.Add($checkboxMaintainAspectRatio)

$buttonResize = New-Object System.Windows.Forms.Button
$buttonResize.Text = 'Resize Image'
$buttonResize.Location = New-Object System.Drawing.Point(20, 140)
$buttonResize.Size = New-Object System.Drawing.Size(100, 30)
$buttonResize.Add_Click({
    if (-not [string]::IsNullOrEmpty($global:inputImagePath)) {
        $outputImagePath = [System.IO.Path]::ChangeExtension($global:inputImagePath.Value, '_resized' + [System.IO.Path]::GetExtension($global:inputImagePath.Value))

        $resizeCommand = "magick `"$($global:inputImagePath)`" -resize $($textboxWidth.Text)`x$($textboxHeight.Text) `"$($outputImagePath)`""
        try {
            $resizeResult = Invoke-Expression -Command $resizeCommand
            [System.Windows.Forms.MessageBox]::Show("Image resized and saved as `n$outputImagePath", 'Success', [System.Windows.Forms.MessageBoxButtons]::OK, [System.Windows.Forms.MessageBoxIcon]::Information)
        } catch {
            $errorMessage = $_.Exception.Message
            [System.Windows.Forms.MessageBox]::Show("Error occurred during resizing: `n$errorMessage", 'Error', [System.Windows.Forms.MessageBoxButtons]::OK, [System.Windows.Forms.MessageBoxIcon]::Error)
        }
    } else {
        [System.Windows.Forms.MessageBox]::Show('Please drag and drop an image to be resized.', 'Error', [System.Windows.Forms.MessageBoxButtons]::OK, [System.Windows.Forms.MessageBoxIcon]::Error)
    }
})

$mainForm.Controls.Add($buttonResize)

$mainForm.Add_Closing({
    $mainForm.Dispose()
})
[void][System.Windows.Forms.Application]::EnableVisualStyles()
[void][System.Windows.Forms.Application]::Run($mainForm)

GPT4

抱歉剛才的更改導致問題。現在我明白了問題所在。請將以下代碼:

$global:inputImagePath = ""

更改為:

$global:inputImagePath = New-Object System.Management.Automation.PSReference("")

然後將:

$global:inputImagePath.Value = $files[0]

更新為:

$global:inputImagePath.Value = $files[0].ToString()

這樣應該可以解決您遇到的問題。請再次嘗試執行腳本。

Hollen9

MsgBox 正常了。
但是關鍵的圖片產出還是失敗:
Console

magick.exe: unable to open image 'System.Management.Automation.PSReference': No such file or directory @ error/blob.c/OpenBlob/3569.
magick.exe: unable to open module file 'C:\Program Files\ImageMagick\modules\coders\IM_MOD_RL_PSREFERENCE_.dll': No such file or directory @ warning/module.c/GetMagickModulePath/677.
magick.exe: no decode delegate for this image format `PSREFERENCE' @ error/constitute.c/ReadImage/746.

GPT4

請將以下代碼:

$resizeCommand = "magick `"$($global:inputImagePath)`" -resize $($textboxWidth.Text)`x$($textboxHeight.Text) `"$($outputImagePath)`""

更改為:

$resizeCommand = "magick `"$($global:inputImagePath.Value)`" -resize $($textboxWidth.Text)`x$($textboxHeight.Text) `"$($outputImagePath)`""

這樣應該可以解決您遇到的問題。請再次嘗試執行腳本。

Hollen9

成功了!

GPT4

(當掉沒有回應)

Facebook 留言

Posted in 桌面軟體開發, 生成式 AI 筆記, 研究與開發 and tagged , , .

Leave a Reply

Your email address will not be published. Required fields are marked *