9

I am interested in file searching by custom properties. For example, I want to find all JPEG-images with certain dimensions. Something looks like

Get-ChildItem -Path C:\ -Filter *.jpg -Recursive | where-object { $_.Dimension -eq '1024x768' }

I suspect it's about using of System.Drawing. How it can be done? Thanks in advance

Oleg Svechkarenko
  • 2,508
  • 25
  • 30

2 Answers2

12

That's actually pretty easy to do and your gut feeling about System.Drawing was in fact correct:

Add-Type -Assembly System.Drawing

$input | ForEach-Object { [Drawing.Image]::FromFile($_) }

Save that as Get-Image.ps1 somewhere in your path and then you can use it.

Another option would be to add the following to your $profile:

Add-Type -Assembly System.Drawing

function Get-Image {
    $input | ForEach-Object { [Drawing.Image]::FromFile($_) }
}

which works pretty much the same. Of course, add fancy things like documentation or so as you see fit.

You can then use it like so:

gci -inc *.jpg -rec | Get-Image | ? { $_.Width -eq 1024 -and $_.Height -eq 768 }

Note that you should dispose the objects created this way after using them.

Of course, you can add a custom Dimension property so you could filter for that:

function Get-Image {
    $input |
        ForEach-Object { [Drawing.Image]::FromFile($_) } |
        ForEach-Object {
            $_ | Add-Member -PassThru NoteProperty Dimension ('{0}x{1}' -f $_.Width,$_.Height)
        }
}
Joey
  • 344,408
  • 85
  • 689
  • 683
  • 1
    You will you note in the answer, that the image should be disposed after the task finishes? Just to educate other scripters. Dispose method is often overlooked... – stej Jun 02 '10 at 14:12
  • 1
    @stej: Eep, ok. Any way of doing so properly or automatically except for attaching `%{$_.Dispose()}` to the end of the pipeline? – Joey Jun 02 '10 at 14:53
  • I don't think there is better way than doing it manually as you propose. Or wait until the end of Posh session. However, I typically open Posh console after I log in and close it before logging out, so that's not ideal. Try/Finally could help as well, but that's overhead. I think a note is enough and let the rest on the readers ;) – stej Jun 02 '10 at 15:57
3

Here's an alternative implementation as a (almost) one-liner:

Add-Type -Assembly System.Drawing

Get-ChildItem -Path C:\ -Filter *.jpg -Recursive | ForEach-Object { [System.Drawing.Image]::FromFile($_.FullName) } | Where-Object { $_.Width -eq 1024 -and $_.Height -eq 768 }

If you are going to need to run this command more than once, I would recommend Johannes' more complete solution instead.

Community
  • 1
  • 1
Enrico Campidoglio
  • 56,676
  • 12
  • 126
  • 154