I wrote these few lines to resize a bunch of pictures all at once (emailing (usually large) pics from numeric cameras isn't always fun...).
Note that the output directory and the prefix for output images are both optional...
Also note that you can combine both directory-wide and specific files selections. I guess I could have used a used a delete button for each specific file, but I went for laziness!
I hope some may find it useful !
#light
open System
open System.Drawing
open System.Drawing.Drawing2D
open System.IO
open System.Windows.Forms
let process_file file output_dir prefix long_side =
if File.Exists(file)
then
try
let img = new Bitmap(file)
let ratio = float (if img.Width > img.Height then img.Width else img.Height) / long_side
let w = int <| Math.Round(float img.Width / ratio)
let h = int <| Math.Round(float img.Height / ratio)
let dst = new Bitmap(w, h)
use g = Graphics.FromImage(dst)
g.SmoothingMode <- SmoothingMode.HighQuality
g.InterpolationMode <- InterpolationMode.HighQualityBicubic
let img_rect = new RectangleF(0.0f, 0.0f, single img.Width, single img.Height)
let dst_rect = new RectangleF(0.0f, 0.0f, single w, single h)
g.DrawImage(img, dst_rect, img_rect, GraphicsUnit.Pixel)
let dir = match output_dir with Some d -> d | None -> Filename.dirname file
let path = Filename.concat dir (prefix + Filename.basename file)
dst.Save(path, img.RawFormat)
with
e -> ()
//Form
let form = new Form(Visible=true, AutoSize=true, AutoSizeMode=AutoSizeMode.GrowAndShrink, Text="Resize Pictures", BackColor=Color.White)
let panel = new FlowLayoutPanel(AutoSize=true, AutoSizeMode=AutoSizeMode.GrowAndShrink, Dock = DockStyle.Fill, FlowDirection = FlowDirection.TopDown)
let run = new Button(AutoSize=true, Enabled=false, Text="Run")
//Select Files
let files = new Label(AutoSize=true)
let files_browse = new Button(AutoSize=true, Text="Select files...")
let files_browser = new OpenFileDialog(Multiselect=true, Title="Select files to shrink", Filter="Image Files(*.BMP;*.JPG;*.GIF;*.PNG)|*.BMP;*.JPG;*.GIF;*.PNG|All files (*.*)|*.*")
let files_set : ref<Set<string>> = ref Set.empty
let files_clear = new Button(AutoSize=true, Text="Clear", Enabled=false)
let files_panel = new FlowLayoutPanel(AutoSize=true)
do
files_browse.Click.Add(fun _ ->
if files_browser.ShowDialog() = DialogResult.OK
then
if not run.Enabled then run.Enabled <- true
for file in files_browser.FileNames do
if not <| Set.mem file !files_set
then
files_set := Set.add file !files_set
files.Text <- files.Text + "\n" + file
files_clear.Enabled <- true
)
files_clear.Click.Add(fun _ ->
files.Text <- ""
files_clear.Enabled <- false
files_set := Set.empty
)
files_panel.Controls.Add(files_browse)
files_panel.Controls.Add(files_clear)
//Select directories
let directory = new Label(AutoSize=true)
let directory_browse = new Button(AutoSize=true, Text="Select directory...")
let directory_browser = new FolderBrowserDialog()
let directory_clear = new Button(AutoSize=true, Text="Clear", Enabled=false)
let directory_panel = new FlowLayoutPanel(AutoSize=true)
do
directory_browse.Click.Add(fun _ ->
if directory_browser.ShowDialog() = DialogResult.OK
then
if not run.Enabled then run.Enabled <- true
directory.Text <- directory_browser.SelectedPath
directory_clear.Enabled <- true
)
directory_clear.Click.Add(fun _ ->
directory.Text <- ""
directory_clear.Enabled <- false
)
directory_panel.Controls.Add(directory_browse)
directory_panel.Controls.Add(directory_clear)
//Output directory
let output_dir = new Label(Width = form.Width / 2, AutoSize=true)
let output_browser = new FolderBrowserDialog()
let output_browse = new Button(AutoSize=true, Text="Select output directory...")
let output_clear = new Button(AutoSize=true, Text="Clear", Enabled=false)
let output_panel = new FlowLayoutPanel(AutoSize=true)
do
output_browse.Click.Add(fun _ ->
if output_browser.ShowDialog() = DialogResult.OK
then
output_dir.Text <- output_browser.SelectedPath
output_clear.Enabled <- true
)
output_clear.Click.Add(fun _ ->
output_dir.Text <- ""
output_clear.Enabled <- false
)
output_panel.Controls.Add(output_browse)
output_panel.Controls.Add(output_clear)
//Output Images Prefix
let prefix = new TextBox(Text="resized_", Width=75)
let prefix_label = new Label(AutoSize=true, Text="Prefix for output files")
let prefix_panel = new FlowLayoutPanel(AutoSize=true)
do
prefix_panel.Controls.Add(prefix)
prefix_panel.Controls.Add(prefix_label)
//Longest side size
let updown =
let v = Convert.ToDecimal(800)
let min = Convert.ToDecimal(1)
let inc = Convert.ToDecimal(50)
new NumericUpDown(ThousandsSeparator=true, Minimum=min, Maximum=System.Decimal.MaxValue, Value=v, DecimalPlaces=0, Increment=inc, Width=75)
let updown_label = new Label(AutoSize=true, Text="Longest side size in pixels")
let updown_panel = new FlowLayoutPanel(AutoSize=true)
do
updown_panel.Controls.Add(updown)
updown_panel.Controls.Add(updown_label)
do
panel.Controls.Add(files)
panel.Controls.Add(files_panel)
panel.Controls.Add(directory)
panel.Controls.Add(directory_panel)
panel.Controls.Add(output_dir)
panel.Controls.Add(output_panel)
panel.Controls.Add(prefix_panel)
panel.Controls.Add(updown_panel)
panel.Controls.Add(run)
form.Controls.Add(panel)
run.Click.Add(fun _ ->
let dir = if String.length output_dir.Text > 0 then Some output_dir.Text else None
for file in files_browser.FileNames do
process_file file dir prefix.Text (float updown.Value)
if String.length directory.Text > 0
then
for file in Directory.GetFiles(directory.Text) do
process_file file dir prefix.Text (float updown.Value)
)
#if COMPILED
// Run the main code. The attribute marks the startup application thread as "Single
// Thread Apartment" mode, which is necessary for GUI applications.
[<STAThread>]
do
Application.EnableVisualStyles()
Application.Run(form)
#endif