Skip to main content

WPF C#/VB.NET
Compress Images for Free

C#

// AZUL CODING ---------------------------------------
// WPF C#/VB.NET - Compress Images for Free
// https://youtu.be/XJ7n6QTjKcY


using System;
using System.Linq;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Windows;
using System.Windows.Controls;
using System.IO;
using System.Text;
using TinifyAPI;
using Microsoft.Win32;

namespace CompressImages
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        private readonly string APIKey = "[replace with an API key from tinypng.com/developers]";
        private readonly ObservableCollection<KeyValuePair<string, string>> ImageList = new();

        private static readonly OpenFileDialog OpenDialog = new()
        {
            Title = "Select image files",
            Filter = "Supported files (.jpg, .jpeg, .png)|*.jpg;*.jpeg;*.png",
            Multiselect = true
        };

        public MainWindow()
        {
            InitializeComponent();

            CompressItemsControl.ItemsSource = ImageList;
            CompressBtn.Visibility = Visibility.Collapsed;
            Tinify.Key = APIKey;
        }

        private void AddBtn_Click(object sender, RoutedEventArgs e)
        {
            if (OpenDialog.ShowDialog() == true)
                AddFiles(OpenDialog.FileNames);
        }

        private void AddFiles(string[] filenames)
        {
            foreach (var item in filenames)
            {
                if (!ImageList.Any(x => x.Key == item))
                    ImageList.Add(new KeyValuePair<string, string>(item, Path.GetFileName(item)));
            }

            if (ImageList.Count > 0)
                CompressBtn.Visibility = Visibility.Visible;
        }

        private void RemoveItemBtn_Click(object sender, RoutedEventArgs e)
        {
            var mi = (MenuItem)sender;
            RemoveFile((string)mi.Tag);
        }

        private void RemoveFile(string id)
        {
            ImageList.Remove(ImageList.Where(x => x.Key == id).First());

            if (ImageList.Count == 0)
                CompressBtn.Visibility = Visibility.Collapsed;
        }

        private async void CompressBtn_Click(object sender, RoutedEventArgs e)
        {
            AddBtn.IsEnabled = false;
            CompressBtn.IsEnabled = false;
            TitleLbl.Content = "Compression in progress...";

            try
            {
                StringBuilder sb = new();
                sb.AppendLine("All files compressed.");
                sb.AppendLine();

                foreach (var item in ImageList.ToList())
                {
                    string path = item.Key;
                    var source = Tinify.FromFile(path);

                    string pathWithoutExt = Path.Combine(Path.GetDirectoryName(path) ?? "", Path.GetFileNameWithoutExtension(path));
                    string ext = Path.GetExtension(path);
                    string newPath = string.Format("{0}-compressed{1}", pathWithoutExt, ext);
                    await source.ToFile(newPath);

                    long oldSize = new FileInfo(path).Length;
                    long newSize = new FileInfo(newPath).Length;
                    double percentage = Math.Round((oldSize - newSize) / (double)oldSize * 100);
                    sb.AppendLine(string.Format("{0} reduced by {1}%", item.Value, percentage));

                    RemoveFile(path);
                }

                MessageBox.Show(sb.ToString());
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
            finally
            {
                AddBtn.IsEnabled = true;
                CompressBtn.IsEnabled = true;
                TitleLbl.Content = "Image compressor";

                if (ImageList.Count == 0)
                    CompressBtn.Visibility = Visibility.Collapsed;
            }
        }
    }
}

Enjoying this tutorial?


VB.NET

' AZUL CODING ---------------------------------------
' WPF C#/VB.NET - Compress Images for Free
' https://youtu.be/XJ7n6QTjKcY


Imports System.IO
Imports System.Text
Imports TinifyAPI
Imports Microsoft.Win32
Imports System.Collections.ObjectModel

Class MainWindow

    Private ReadOnly APIKey As String = "[replace with an API key from tinypng.com/developers]"
    Private ReadOnly ImageList As New ObservableCollection(Of KeyValuePair(Of String, String))()

    Private Shared ReadOnly OpenDialog As New OpenFileDialog() With {
        .Title = "Select image files",
        .Filter = "Supported files (.jpg, .jpeg, .png)|*.jpg;*.jpeg;*.png",
        .Multiselect = True
    }

    Public Sub New()
        InitializeComponent()

        CompressItemsControl.ItemsSource = ImageList
        CompressBtn.Visibility = Visibility.Collapsed
        Tinify.Key = APIKey
    End Sub

    Private Sub AddBtn_Click(sender As Object, e As RoutedEventArgs)
        If OpenDialog.ShowDialog() = True Then AddFiles(OpenDialog.FileNames)
    End Sub

    Private Sub AddFiles(filenames As String())
        For Each item In filenames
            If Not ImageList.Any(Function(x) x.Key = item) Then
                ImageList.Add(New KeyValuePair(Of String, String)(item, Path.GetFileName(item)))
            End If
        Next

        If ImageList.Count > 0 Then CompressBtn.Visibility = Visibility.Visible
    End Sub

    Private Sub RemoveItemBtn_Click(sender As Object, e As RoutedEventArgs)
        Dim mi = CType(sender, MenuItem)
        RemoveFile(mi.Tag.ToString())
    End Sub

    Private Sub RemoveFile(id As String)
        ImageList.Remove(ImageList.Where(Function(x) x.Key = id).First())
        If ImageList.Count = 0 Then CompressBtn.Visibility = Visibility.Collapsed
    End Sub

    Private Async Sub CompressBtn_Click(sender As Object, e As RoutedEventArgs)
        AddBtn.IsEnabled = False
        CompressBtn.IsEnabled = False
        TitleLbl.Content = "Compression in progress..."

        Try
            Dim sb As New StringBuilder()
            sb.AppendLine("All files compressed.")
            sb.AppendLine()

            For Each item In ImageList.ToList()
                Dim path As String = item.Key
                Dim source = Tinify.FromFile(path)

                Dim pathWithoutExt As String = IO.Path.Combine(IO.Path.GetDirectoryName(path), IO.Path.GetFileNameWithoutExtension(path))
                Dim ext As String = IO.Path.GetExtension(path)
                Dim newPath As String = String.Format("{0}-compressed{1}", pathWithoutExt, ext)
                Await source.ToFile(newPath)

                Dim oldSize As Long = New FileInfo(path).Length
                Dim newSize As Long = New FileInfo(newPath).Length
                Dim percentage As Double = Math.Round((oldSize - newSize) / oldSize * 100)
                sb.AppendLine(String.Format("{0} reduced by {1}%", item.Value, percentage))

                RemoveFile(path)
            Next

            MessageBox.Show(sb.ToString())

        Catch ex As Exception
            MessageBox.Show(ex.Message)

        Finally
            AddBtn.IsEnabled = True
            CompressBtn.IsEnabled = True
            TitleLbl.Content = "Image compressor"
            If ImageList.Count = 0 Then CompressBtn.Visibility = Visibility.Collapsed

        End Try
    End Sub
End Class

XAML

<!-- AZUL CODING --------------------------------------- -->
<!-- WPF C#/VB.NET - Compress Images for Free -->
<!-- https://youtu.be/XJ7n6QTjKcY -->


<Window x:Class="CompressImages.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:CompressImages"
        mc:Ignorable="d"
        Title="Image Compressor - Azul Coding" Width="500" SizeToContent="Height" ResizeMode="CanMinimize">
    <StackPanel Background="White">
        <Label x:Name="TitleLbl" Content="Image compressor" Padding="5,0,5,5" Margin="20" FontWeight="SemiBold" FontSize="16" BorderBrush="DodgerBlue" BorderThickness="0,0,0,2"/>
        <ScrollViewer Margin="20,0" Height="200" HorizontalAlignment="Stretch" VerticalAlignment="Top">
            <ItemsControl x:Name="CompressItemsControl" Background="#f0f0f0">
                <ItemsControl.ItemsPanel>
                    <ItemsPanelTemplate>
                        <VirtualizingStackPanel/>
                    </ItemsPanelTemplate>
                </ItemsControl.ItemsPanel>
                <ItemsControl.ItemTemplate>
                    <DataTemplate>
                        <Button HorizontalContentAlignment="Stretch" BorderThickness="0" Background="#f0f0f0" ToolTip="{Binding Key}">
                            <Button.ContextMenu>
                                <ContextMenu>
                                    <MenuItem Click="RemoveItemBtn_Click" Header="Remove" Tag="{Binding Key}"/>
                                </ContextMenu>
                            </Button.ContextMenu>
                            <StackPanel Orientation="Vertical" Margin="3,3">
                                <TextBlock Text="{Binding Value}" FontSize="14" TextTrimming="CharacterEllipsis"/>
                            </StackPanel>
                        </Button>
                    </DataTemplate>
                </ItemsControl.ItemTemplate>
            </ItemsControl>
        </ScrollViewer>
        <StackPanel Margin="20" Orientation="Horizontal">
            <Button Name="AddBtn" Padding="10,5" Margin="0,0,10,0" Background="#f0f0f0" Click="AddBtn_Click">
                <StackPanel Orientation="Horizontal" VerticalAlignment="Center">
                    <Image Height="24" Width="24" Source="https://img.icons8.com/fluency/48/opened-folder.png"/>
                    <TextBlock Text="Add files" VerticalAlignment="Center" FontSize="14" Margin="10,0,5,2"/>
                </StackPanel>
            </Button>
            <Button Name="CompressBtn" Padding="10,5" Margin="0,0,10,0" Background="#f0f0f0" Click="CompressBtn_Click">
                <StackPanel Orientation="Horizontal" VerticalAlignment="Center">
                    <Image Height="24" Width="24" Source="https://img.icons8.com/fluency/48/ok.png"/>
                    <TextBlock Text="Compress files" FontWeight="SemiBold" VerticalAlignment="Center" FontSize="14" Margin="10,0,5,2"/>
                </StackPanel>
            </Button>
        </StackPanel>
    </StackPanel>
</Window>