Skip to content

Commit 89c09d4

Browse files
authored
Add improved GUI image converter with drag & drop support
Updated the GUI layout and improved user instructions. Added drag-and-drop functionality for folder selection and enhanced quality validation.
1 parent 2be80c1 commit 89c09d4

1 file changed

Lines changed: 176 additions & 118 deletions

File tree

image-converter-gui.ps1

Lines changed: 176 additions & 118 deletions
Original file line numberDiff line numberDiff line change
@@ -14,100 +14,171 @@ function Add-Log {
1414

1515
# ---------- main form ----------
1616
$form = New-Object System.Windows.Forms.Form
17-
$form.Text = "Image Converter (PNG/JPG/AVIF -> WebP / AVIF)"
17+
$form.Text = "PNG/JPG/AVIF -> WebP / AVIF Converter"
1818
$form.StartPosition = "CenterScreen"
19-
$form.Size = New-Object System.Drawing.Size(700, 520)
19+
$form.Size = New-Object System.Drawing.Size(780, 580)
2020
$form.FormBorderStyle = 'FixedDialog'
2121
$form.MaximizeBox = $false
22+
$form.AllowDrop = $true
23+
$form.Font = New-Object System.Drawing.Font("Segoe UI", 9)
24+
25+
# ---------- title ----------
26+
$labelTitle = New-Object System.Windows.Forms.Label
27+
$labelTitle.Text = "Image Converter for Web (PNG/JPG/AVIF -> WebP / AVIF)"
28+
$labelTitle.Location = New-Object System.Drawing.Point(15, 10)
29+
$labelTitle.AutoSize = $true
30+
$labelTitle.Font = New-Object System.Drawing.Font("Segoe UI Semibold", 11)
31+
$form.Controls.Add($labelTitle)
32+
33+
$labelSubtitle = New-Object System.Windows.Forms.Label
34+
$labelSubtitle.Text = "Select a folder with images, set quality and output format, then click Start."
35+
$labelSubtitle.Location = New-Object System.Drawing.Point(15, 35)
36+
$labelSubtitle.AutoSize = $true
37+
$labelSubtitle.ForeColor = [System.Drawing.Color]::Gray
38+
$form.Controls.Add($labelSubtitle)
2239

2340
# ---------- folder selection ----------
24-
$labelFolder = New-Object System.Windows.Forms.Label
25-
$labelFolder.Text = "Folder:"
26-
$labelFolder.Location = New-Object System.Drawing.Point(15, 20)
27-
$labelFolder.AutoSize = $true
28-
$form.Controls.Add($labelFolder)
29-
30-
$textFolder = New-Object System.Windows.Forms.TextBox
31-
$textFolder.Location = New-Object System.Drawing.Point(80, 15)
32-
$textFolder.Size = New-Object System.Drawing.Size(480, 25)
33-
$form.Controls.Add($textFolder)
34-
35-
$buttonBrowse = New-Object System.Windows.Forms.Button
36-
$buttonBrowse.Text = "Browse..."
37-
$buttonBrowse.Location = New-Object System.Drawing.Point(570, 13)
38-
$buttonBrowse.Size = New-Object System.Drawing.Size(90, 28)
39-
$form.Controls.Add($buttonBrowse)
40-
41-
$folderDialog = New-Object System.Windows.Forms.FolderBrowserDialog
41+
$groupFolder = New-Object System.Windows.Forms.GroupBox
42+
$groupFolder.Text = " Source folder "
43+
$groupFolder.Location = New-Object System.Drawing.Point(15, 65)
44+
$groupFolder.Size = New-Object System.Drawing.Size(740, 80)
45+
$form.Controls.Add($groupFolder)
46+
47+
$labelFolder = New-Object System.Windows.Forms.Label
48+
$labelFolder.Text = "Folder:"
49+
$labelFolder.Location = New-Object System.Drawing.Point(10, 30)
50+
$labelFolder.AutoSize = $true
51+
$groupFolder.Controls.Add($labelFolder)
52+
53+
$textFolder = New-Object System.Windows.Forms.TextBox
54+
$textFolder.Location = New-Object System.Drawing.Point(70, 27)
55+
$textFolder.Size = New-Object System.Drawing.Size(540, 24)
56+
$textFolder.AllowDrop = $true
57+
$groupFolder.Controls.Add($textFolder)
58+
59+
$buttonBrowse = New-Object System.Windows.Forms.Button
60+
$buttonBrowse.Text = "Browse..."
61+
$buttonBrowse.Location = New-Object System.Drawing.Point(620, 25)
62+
$buttonBrowse.Size = New-Object System.Drawing.Size(90, 28)
63+
$groupFolder.Controls.Add($buttonBrowse)
64+
65+
$folderDialog = New-Object System.Windows.Forms.FolderBrowserDialog
4266

4367
$buttonBrowse.Add_Click({
4468
if ($folderDialog.ShowDialog() -eq "OK") {
4569
$textFolder.Text = $folderDialog.SelectedPath
4670
}
4771
})
4872

49-
# ---------- quality ----------
50-
$labelQuality = New-Object System.Windows.Forms.Label
51-
$labelQuality.Text = "Quality (0-100):"
52-
$labelQuality.Location = New-Object System.Drawing.Point(15, 55)
53-
$labelQuality.AutoSize = $true
54-
$form.Controls.Add($labelQuality)
55-
56-
$textQuality = New-Object System.Windows.Forms.TextBox
57-
$textQuality.Location = New-Object System.Drawing.Point(120, 52)
58-
$textQuality.Size = New-Object System.Drawing.Size(50, 25)
59-
$textQuality.Text = "85"
60-
$form.Controls.Add($textQuality)
61-
62-
# ---------- output format ----------
63-
$labelFormat = New-Object System.Windows.Forms.Label
64-
$labelFormat.Text = "Output format:"
65-
$labelFormat.Location = New-Object System.Drawing.Point(200, 55)
66-
$labelFormat.AutoSize = $true
67-
$form.Controls.Add($labelFormat)
68-
69-
$comboFormat = New-Object System.Windows.Forms.ComboBox
70-
$comboFormat.Location = New-Object System.Drawing.Point(290, 52)
71-
$comboFormat.Size = New-Object System.Drawing.Size(80, 25)
72-
$comboFormat.DropDownStyle = 'DropDownList'
73+
# Drag & Drop to folder textbox
74+
$textFolder.Add_DragEnter({
75+
if ($_.Data.GetDataPresent([Windows.Forms.DataFormats]::FileDrop)) {
76+
$_.Effect = 'Copy'
77+
} else {
78+
$_.Effect = 'None'
79+
}
80+
})
81+
82+
$textFolder.Add_DragDrop({
83+
$paths = $_.Data.GetData([Windows.Forms.DataFormats]::FileDrop)
84+
if ($paths -and $paths.Length -gt 0) {
85+
$first = $paths[0]
86+
if (Test-Path $first -PathType Container) {
87+
$textFolder.Text = $first
88+
} else {
89+
$textFolder.Text = [System.IO.Path]::GetDirectoryName($first)
90+
}
91+
}
92+
})
93+
94+
# ---------- settings ----------
95+
$groupSettings = New-Object System.Windows.Forms.GroupBox
96+
$groupSettings.Text = " Settings "
97+
$groupSettings.Location = New-Object System.Drawing.Point(15, 155)
98+
$groupSettings.Size = New-Object System.Drawing.Size(740, 110)
99+
$form.Controls.Add($groupSettings)
100+
101+
# Quality
102+
$labelQuality = New-Object System.Windows.Forms.Label
103+
$labelQuality.Text = "Quality (0-100):"
104+
$labelQuality.Location = New-Object System.Drawing.Point(10, 30)
105+
$labelQuality.AutoSize = $true
106+
$groupSettings.Controls.Add($labelQuality)
107+
108+
$textQuality = New-Object System.Windows.Forms.TextBox
109+
$textQuality.Location = New-Object System.Drawing.Point(120, 27)
110+
$textQuality.Size = New-Object System.Drawing.Size(50, 24)
111+
$textQuality.Text = "85"
112+
$groupSettings.Controls.Add($textQuality)
113+
114+
$labelQualityHint = New-Object System.Windows.Forms.Label
115+
$labelQualityHint.Text = "(85 is a good default for web)"
116+
$labelQualityHint.Location = New-Object System.Drawing.Point(180, 30)
117+
$labelQualityHint.AutoSize = $true
118+
$labelQualityHint.ForeColor = [System.Drawing.Color]::Gray
119+
$groupSettings.Controls.Add($labelQualityHint)
120+
121+
# Output format
122+
$labelFormat = New-Object System.Windows.Forms.Label
123+
$labelFormat.Text = "Output format:"
124+
$labelFormat.Location = New-Object System.Drawing.Point(10, 65)
125+
$labelFormat.AutoSize = $true
126+
$groupSettings.Controls.Add($labelFormat)
127+
128+
$comboFormat = New-Object System.Windows.Forms.ComboBox
129+
$comboFormat.Location = New-Object System.Drawing.Point(120, 62)
130+
$comboFormat.Size = New-Object System.Drawing.Size(100, 24)
131+
$comboFormat.DropDownStyle = 'DropDownList'
73132
[void]$comboFormat.Items.Add("webp")
74133
[void]$comboFormat.Items.Add("avif")
75-
$comboFormat.SelectedIndex = 0
76-
$form.Controls.Add($comboFormat)
77-
78-
# ---------- checkboxes ----------
79-
$checkDelete = New-Object System.Windows.Forms.CheckBox
80-
$checkDelete.Text = "Delete original source files after conversion"
81-
$checkDelete.Location = New-Object System.Drawing.Point(15, 85)
82-
$checkDelete.AutoSize = $true
83-
$checkDelete.Checked = $true
84-
$form.Controls.Add($checkDelete)
85-
86-
$checkRecursive = New-Object System.Windows.Forms.CheckBox
87-
$checkRecursive.Text = "Include subfolders (recursive)"
88-
$checkRecursive.Location = New-Object System.Drawing.Point(15, 110)
89-
$checkRecursive.AutoSize = $true
90-
$checkRecursive.Checked = $false
91-
$form.Controls.Add($checkRecursive)
134+
$comboFormat.SelectedIndex = 0
135+
$groupSettings.Controls.Add($comboFormat)
136+
137+
# ---------- options ----------
138+
$groupOptions = New-Object System.Windows.Forms.GroupBox
139+
$groupOptions.Text = " Options "
140+
$groupOptions.Location = New-Object System.Drawing.Point(15, 275)
141+
$groupOptions.Size = New-Object System.Drawing.Size(740, 90)
142+
$form.Controls.Add($groupOptions)
143+
144+
$checkDelete = New-Object System.Windows.Forms.CheckBox
145+
$checkDelete.Text = "Delete original source files after successful conversion"
146+
$checkDelete.Location = New-Object System.Drawing.Point(10, 25)
147+
$checkDelete.AutoSize = $true
148+
$checkDelete.Checked = $true
149+
$groupOptions.Controls.Add($checkDelete)
150+
151+
$checkRecursive = New-Object System.Windows.Forms.CheckBox
152+
$checkRecursive.Text = "Include subfolders (recursive)"
153+
$checkRecursive.Location = New-Object System.Drawing.Point(10, 50)
154+
$checkRecursive.AutoSize = $true
155+
$groupOptions.Controls.Add($checkRecursive)
92156

93157
# ---------- start button ----------
94-
$buttonStart = New-Object System.Windows.Forms.Button
95-
$buttonStart.Text = "Start conversion"
96-
$buttonStart.Location = New-Object System.Drawing.Point(15, 140)
97-
$buttonStart.Size = New-Object System.Drawing.Size(150, 35)
158+
$buttonStart = New-Object System.Windows.Forms.Button
159+
$buttonStart.Text = "Start conversion"
160+
$buttonStart.Location = New-Object System.Drawing.Point(15, 380)
161+
$buttonStart.Size = New-Object System.Drawing.Size(160, 36)
162+
$buttonStart.Font = New-Object System.Drawing.Font("Segoe UI Semibold", 9)
98163
$form.Controls.Add($buttonStart)
99164

100-
# ---------- log textbox ----------
101-
$logBox = New-Object System.Windows.Forms.TextBox
102-
$logBox.Location = New-Object System.Drawing.Point(15, 190)
103-
$logBox.Size = New-Object System.Drawing.Size(645, 270)
104-
$logBox.Multiline = $true
105-
$logBox.ScrollBars = "Vertical"
106-
$logBox.ReadOnly = $true
107-
$logBox.Font = New-Object System.Drawing.Font("Consolas", 9)
165+
# ---------- log output ----------
166+
$labelLog = New-Object System.Windows.Forms.Label
167+
$labelLog.Text = "Log output:"
168+
$labelLog.Location = New-Object System.Drawing.Point(15, 425)
169+
$labelLog.AutoSize = $true
170+
$form.Controls.Add($labelLog)
171+
172+
$logBox = New-Object System.Windows.Forms.TextBox
173+
$logBox.Location = New-Object System.Drawing.Point(15, 445)
174+
$logBox.Size = New-Object System.Drawing.Size(740, 90)
175+
$logBox.Multiline = $true
176+
$logBox.ScrollBars = "Vertical"
177+
$logBox.ReadOnly = $true
178+
$logBox.Font = New-Object System.Drawing.Font("Consolas", 9)
108179
$form.Controls.Add($logBox)
109180

110-
# ---------- start button logic ----------
181+
# ---------- start logic ----------
111182
$buttonStart.Add_Click({
112183
$folder = $textFolder.Text.Trim()
113184
if ([string]::IsNullOrWhiteSpace($folder) -or -not (Test-Path $folder)) {
@@ -119,95 +190,82 @@ $buttonStart.Add_Click({
119190
$magickCmd = Get-Command magick -ErrorAction SilentlyContinue
120191
if (-not $magickCmd) {
121192
[System.Windows.Forms.MessageBox]::Show(
122-
"ImageMagick 'magick' command not found in PATH.`r`nPlease install ImageMagick.",
193+
"ImageMagick 'magick' command not found.`r`nPlease install ImageMagick.",
123194
"ImageMagick not found",
124195
"OK",
125196
"Error"
126197
)
127198
return
128199
}
129200

130-
# -------- FIXED QUALITY VALIDATION --------
201+
# Quality validation
131202
$qualityText = $textQuality.Text.Trim()
132-
133203
[int]$quality = 0
204+
134205
if (-not [int]::TryParse($qualityText, [ref]$quality)) {
135-
[System.Windows.Forms.MessageBox]::Show(
136-
"Quality must be an integer between 0 and 100.",
137-
"Error","OK","Error"
138-
)
206+
[System.Windows.Forms.MessageBox]::Show("Quality must be an integer between 0 and 100.","Error","OK","Error")
139207
return
140208
}
141209

142210
if ($quality -lt 0 -or $quality -gt 100) {
143-
[System.Windows.Forms.MessageBox]::Show(
144-
"Quality must be between 0 and 100.",
145-
"Error","OK","Error"
146-
)
211+
[System.Windows.Forms.MessageBox]::Show("Quality must be between 0 and 100.","Error","OK","Error")
147212
return
148213
}
149-
# ------------------------------------------
150214

151215
$format = $comboFormat.SelectedItem
152216
$deleteOriginals = $checkDelete.Checked
153217
$recursive = $checkRecursive.Checked
154218

155219
$logBox.Clear()
156-
Add-Log "Starting conversion to $format ..." $logBox
220+
Add-Log "Starting conversion..." $logBox
221+
Add-Log "Folder: $folder" $logBox
222+
Add-Log "Format: $format" $logBox
223+
Add-Log "Quality: $quality" $logBox
224+
Add-Log "Recursive: $recursive" $logBox
225+
Add-Log "Delete originals: $deleteOriginals" $logBox
157226
Add-Log "" $logBox
158227

159228
$buttonStart.Enabled = $false
160229

161230
try {
162231
if ($recursive) {
163232
$files = Get-ChildItem -Path $folder -File -Recurse | Where-Object {
164-
$_.Extension -in '.jpg', '.jpeg', '.png', '.avif', '.JPG', '.JPEG', '.PNG', '.AVIF'
233+
$_.Extension -in '.jpg','.jpeg','.png','.avif','.JPG','.JPEG','.PNG','.AVIF'
165234
}
166235
} else {
167236
$files = Get-ChildItem -Path $folder -File | Where-Object {
168-
$_.Extension -in '.jpg', '.jpeg', '.png', '.avif', '.JPG', '.JPEG', '.PNG', '.AVIF'
237+
$_.Extension -in '.jpg','.jpeg','.png','.avif','.JPG','.JPEG','.PNG','.AVIF'
169238
}
170239
}
171240

172241
$total = $files.Count
173242
$success = 0
174243
$fail = 0
175244

176-
if ($total -eq 0) {
177-
Add-Log "No PNG/JPG/JPEG/AVIF files found." $logBox
178-
} else {
179-
Add-Log "Found $total file(s)." $logBox
180-
Add-Log "" $logBox
245+
foreach ($file in $files) {
246+
$outPath = [System.IO.Path]::ChangeExtension($file.FullName, ".$format")
181247

182-
foreach ($file in $files) {
248+
Add-Log "Converting: $($file.Name)" $logBox
183249

184-
$outPath = [System.IO.Path]::ChangeExtension($file.FullName, ".$format")
250+
& magick $file.FullName -auto-orient -quality $quality $outPath
185251

186-
Add-Log "Converting: $($file.FullName)" $logBox
187-
Add-Log " --> $outPath" $logBox
188-
189-
& magick $file.FullName -auto-orient -quality $quality $outPath
190-
191-
if (Test-Path $outPath) {
192-
if ($deleteOriginals) {
193-
Remove-Item $file.FullName -ErrorAction SilentlyContinue
194-
}
195-
$success++
196-
Add-Log " OK" $logBox
197-
} else {
198-
$fail++
199-
Add-Log " ERROR: output not created." $logBox
252+
if (Test-Path $outPath) {
253+
if ($deleteOriginals) {
254+
Remove-Item $file.FullName -ErrorAction SilentlyContinue
200255
}
201-
202-
Add-Log "" $logBox
256+
$success++
257+
Add-Log " OK" $logBox
258+
} else {
259+
$fail++
260+
Add-Log " ERROR" $logBox
203261
}
204-
205-
Add-Log "-----------------------------" $logBox
206-
Add-Log "Done." $logBox
207-
Add-Log "Total: $total" $logBox
208-
Add-Log "Success: $success" $logBox
209-
Add-Log "Failed: $fail" $logBox
210262
}
263+
264+
Add-Log "" $logBox
265+
Add-Log "Done." $logBox
266+
Add-Log "Total: $total" $logBox
267+
Add-Log "Success: $success" $logBox
268+
Add-Log "Failed: $fail" $logBox
211269
}
212270
finally {
213271
$buttonStart.Enabled = $true

0 commit comments

Comments
 (0)