hubFS: THE place for F#

. . . are you on The Hub?
Welcome to hubFS: THE place for F# Sign in | Join | Help
in Search

Batch Resizing of Pictures

Last post 04-22-2008, 16:44 by Julien. 0 replies.
Sort Posts: Previous Next
  •  04-22-2008, 16:44 5815

    Batch Resizing of Pictures

    Edit:My apologies about the duplicate post. But I wasn't able to delete the other post. There's no difference aside from the title although I'm sure neither is correct anyway...

    Edit 2 : Addition of an option to include sub directories when resizing all pictures from a directory

    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 !



    //Compiler option flags :
    //--standalone --target-winexe

    #light

    open System
    open System.Drawing
    open System.Drawing.Drawing2D
    open System.IO
    open System.Windows.Forms

    let get_directory_files directory use_recursion =
      [|  yield! Directory.GetFiles(directory)
          if use_recursion then
            for dir in Directory.GetDirectories(directory)
              for file in Directory.GetFiles(dir) -> file
      |]
       

    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_include_subdirectory = new CheckBox(Checked=false, AutoSize=true)
    let directory_include_subdirectory_label = new Label(AutoSize=true, Text="Include sub-directories")
    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)
      directory_panel.Controls.Add(directory_include_subdirectory)
      directory_panel.Controls.Add(directory_include_subdirectory_label)
     
    //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)

    //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)

    //Long side
    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 get_directory_files directory.Text directory_include_subdirectory.Checked do
            process_file file dir prefix.Text (float updown.Value)   
      ) 
     
    [<STAThread>]
    do
      Application.EnableVisualStyles()
      Application.Run(form)

View as RSS news feed in XML
Powered by Community Server, by Telligent Systems