none
Getting Dimensions of images in a folder using Power Shell RRS feed

Answers

  • Function Get-Image
    {
        begin{        
             [void][System.Reflection.Assembly]::LoadWithPartialName("System.Drawing") |Out-Null 
        } 
         process{
              $fi=[System.IO.FileInfo]$_           
              if( $fi.Exists){
                   $img = [System.Drawing.Image]::FromFile($_)
                   $img.Clone()
                   $img.Dispose()       
              }else{
                   Write-Host "File not found: $_" -fore yellow       
              }   
         }    
        end{}
    }
    
    dir "C:\*.jpg" -Recurse | % {
        $image = $_ | Get-Image
        New-Object PSObject -Property  @{ 
            File = $_.name
            Fullname = $_.Fullname
            Height = $image.Height
            Width = $image.Width
        };
    }
    
    



    Oliver Lipkau
    [PowerShell enthusiast]
    http://oliver.lipkau.net/blog
    • Proposed as answer by Crazy Adam Friday, October 7, 2011 6:50 PM
    • Marked as answer by BSonPoshModerator Sunday, October 9, 2011 3:37 PM
    Friday, October 7, 2011 4:56 PM
    Moderator

All replies

  • What does that mean - "not completely successful"?

     


    jv
    Thursday, October 6, 2011 6:35 PM
  • I just retested the code and it woks perfectly.

    Function Get-Image{
        begin{        
             [void][System.Reflection.Assembly]::LoadWithPartialName("System.Drawing") |Out-Null 
        } 
         process{
              $fi=[System.IO.FileInfo]$_           
              if( $fi.Exists){
                   $img = [System.Drawing.Image]::FromFile($_)
                   $img.Clone()
                   $img.Dispose()       
              }else{
                   Write-Host "File not found: $_" -fore yellow       
              }   
         }    
        end{}
    }
    dir "C:\Projects\My Pictures\*.jpg" | Get-Image |select width, Height
    $images =  dir "C:\Projects\My Pictures\*.jpg" | Get-Image
    $images[0].HorizontalResolution
    $images| ft Height, Width -auto
    


    Perhaps you copied it wrong.

     


    jv
    Thursday, October 6, 2011 6:43 PM
  • Thanks JRV

    When I tried that script, it only gave me the Height and Width. So in my folder there are +5,000 images. all I got were Height and width for each of the 5000 without the filename for each.

    Thanks for the quick reply


    TimA
    Thursday, October 6, 2011 7:19 PM
  • Function Get-Image
    {
        begin{        
             [void][System.Reflection.Assembly]::LoadWithPartialName("System.Drawing") |Out-Null 
        } 
         process{
              $fi=[System.IO.FileInfo]$_           
              if( $fi.Exists){
                   $img = [System.Drawing.Image]::FromFile($_)
                   $img.Clone()
                   $img.Dispose()       
              }else{
                   Write-Host "File not found: $_" -fore yellow       
              }   
         }    
        end{}
    }
    
    dir "C:\*.jpg" -Recurse | % {
        $image = $_ | Get-Image
        New-Object PSObject -Property  @{ 
            File = $_.name
            Fullname = $_.Fullname
            Height = $image.Height
            Width = $image.Width
        };
    }
    
    



    Oliver Lipkau
    [PowerShell enthusiast]
    http://oliver.lipkau.net/blog
    • Proposed as answer by Crazy Adam Friday, October 7, 2011 6:50 PM
    • Marked as answer by BSonPoshModerator Sunday, October 9, 2011 3:37 PM
    Friday, October 7, 2011 4:56 PM
    Moderator
  • That worked magical, wanted to know if it can give the height and width of the images in a subfolder within a folder that too contains images. 
    Tuesday, October 2, 2012 10:09 AM
  • I have no idea what you mean.

    But since this thread has already been answered, please start a new question.


    If you found this post helpful, please "Vote as Helpful". If it answered your question, remember to "Mark as Answer"
    MCC & PowerShell enthusiast
    http://oliver.lipkau.net/blog

    Wednesday, October 3, 2012 1:03 AM
    Moderator
  • Unfortuately the code , as posted as an answer, does not really work outside of that one example.  It is a sort of best guess as to whether or not it is in a pipeline.  Sort of a shot at a hybrid of a filter and a function.

    I believe this is what was intended and I post it as a fix to the above chosen code.

    Function Get-Image{
        Param(
             [Parameter(ValueFromPipeline=$true)]
             [System.IO.FileINfo]$file
        )
        begin{        
             [void][System.Reflection.Assembly]::LoadWithPartialName("System.Drawing") |Out-Null 
        }
        process{
              if( $file.Exists){
                   $img=[System.Drawing.Image]::FromFile($file)
                   $image=$img.Clone()
                   $img.Dispose()
                   $image | Add-Member `
                                  -MemberType NoteProperty `
                                  -Name Filename `
                                  -Value $file.FUllname `
                                  -PassThru
              }else{
                   Write-Host "File not found: $file" -fore yellow       
              }   
         }    
        end{}
    }
    #
    dir e:\test3\*.jpg |get-IMage
    #
    dir e:\test3\*.jpg -Recurse |
         Get-Image  |
         select filename, Width, Height |
         ft -auto


    ¯\_(ツ)_/¯


    • Edited by jrv Wednesday, October 3, 2012 8:20 AM
    • Proposed as answer by jrv Wednesday, October 3, 2012 8:21 AM
    Wednesday, October 3, 2012 8:17 AM
  • Dead thread for a long time.

    The "Dispose" guarantees no lock issues.


    ¯\_(ツ)_/¯

    Wednesday, November 27, 2013 9:04 PM
  • I believe the the code above will create file locks while powershell is open. similar to http://support.microsoft.com/kb/309482. Use FileStream...

    if( $file.Exists){
       $fs = New-Object System.IO.FileStream ($file.FullName, [IO.FileMode]::Open, [IO.FileAccess]::Read, [IO.FileShare]::Read)
       $img=[System.Drawing.Image]::FromStream($fs)
       $fs.Dispose()
       $img | Add-Member `
                 -MemberType NoteProperty `
                 -Name Filename `
                 -Value $file.Fullname `
                 -PassThru


    Wednesday, November 27, 2013 10:05 PM
  • Dispose will unlock the file.

    The issue about file locks occurs only when two processes try to open the same file exclusively.

    This:

    $image=$img.Clone()
    $img
    .Dispose()

    Uses file stream.  Dispose releases the image handle.

    The article is referring to a PictureBox control.  PowerShell is NOT using a picturebox control and is not opening the image the same way.  I have tested this.  That is how the Dispose got into the code.  The original of this code was developed in response to a question about images staying locked after being opened in PowerShell.

    In this case we are getting alternate properties which are decoded when we open it as a file. They are not decoded when using the filestream.  That is what the question here was about.  The external values can be easily read without opening the file.  The internal values (EXIF) canonly be read by loading the image as a file, reading the values and then releasing the image.

    As best I remember early copies of the PicturBox control failed to call Dispose.


    Note the example from the KB:

    PictureBox1.Image = Image.FromFile("C:\WINNT\Web\Wallpaper\Fly Away.jpg")

    The example never calls dispose. 

    System.Drawing.Image img = Image.FromFile("C:\WINNT\Web\Wallpaper\Fly Away.jpg");
    PictureBox1.Image =img.Clone();
    img.Dispose();

    will also prevent the issue.

    Of course you can use filestream if you do not need all of the file items.


    ¯\_(ツ)_/¯


    • Edited by jrv Wednesday, November 27, 2013 11:04 PM
    Wednesday, November 27, 2013 11:04 PM
  • This worked for me, when I changed the following:

    dir "p:\*.jpg"

    and then added:

    $image = $_ | Get-Image | ? { $_.width -ne 105 -or $_.height -ne 105}


    TimA

    Tuesday, February 17, 2015 8:52 PM
  • I believe, in my original post, you thought the 'wasn't completely successful; was a comment to you. The not completely successful was when I followed the link in the original question.

    :)


    TimA

    • Proposed as answer by MartinGaciarz Saturday, March 2, 2019 1:47 AM
    • Unproposed as answer by MartinGaciarz Saturday, March 2, 2019 1:47 AM
    Tuesday, February 17, 2015 8:57 PM
  • Although this also seemed to work. Halfway down my results I received this:

    Exception calling "FromFile" with "1" argument(s): "Out of memory."
    At line:11 char:53
    +                $img=[System.Drawing.Image]::FromFile <<<< ($file)
        + CategoryInfo          : NotSpecified: (:) [], MethodInvocationException
        + FullyQualifiedErrorId : DotNetMethodException

    Exception calling "Clone" with "0" argument(s): "Parameter is not valid."
    At line:12 char:33
    +                $image=$img.Clone <<<< ()
        + CategoryInfo          : NotSpecified: (:) [], MethodInvocationException
        + FullyQualifiedErrorId : DotNetMethodException


    TimA

    Tuesday, February 17, 2015 9:04 PM
  • strange thing for me, as I was trying these 2 different options is, this option didn't give me the memory error, like the other Function. But this one did not report the dimensions on roughly half the images:

    P:\rr1rr.jp4              102    70 rr1rr.jp4
    P:\ru1irk.jp4                       ru1irk.jp4
    P:\brbc.jp4                         brbc.jp4
    P:\1ichae3f.jp4                     1ichae3f.jp4
    P:\2avi2can.jp4                     2avi2can.jp4
    P:\rr1rc.jp4              105    70 rr1rc.jp4
    P:\jre33e4.jp4                      jre33e4.jp4
    P:\4re4fe.jp4             106   105 4re4fe.jp4
    P:\1arniew.jp4                      1arniew.jp4


    TimA

    Tuesday, February 17, 2015 9:15 PM
  • Works fine for me:

    Function Get-Image{
        begin{        
             Add-Type -assembly System.Drawing
        } 
         process{
              $fi=[System.IO.FileInfo]$_           
              if( $fi.Exists){
                   $img = [System.Drawing.Image]::FromFile($_)
                   $img.Clone()
                   $img.Dispose()       
              }else{
                   Write-Host "File not found: $_" -fore yellow       
              }   
         }    
    }
    
     dir "$env:userprofile\onedrive\Pictures\*.jpg" -rec|Get-Image|select height,width|ft -auto
    


    ¯\_(ツ)_/¯

    Tuesday, February 17, 2015 9:23 PM
  • For those following with later versions of powershell - ie ver3 or above, remove the [void] from the above code snippets and they should work.

    Wednesday, June 19, 2019 1:06 PM