List of images exceeding 4M pixels with Powershell

4

I have folder with multiple image files and I want details of only three different formats (jpeg, png and gif). I need to find the images that are exceeding 4 million pixels, so the width multiplied by height can't exceed 4 million pixels. Basically, I just need a list of images that are exceeding the limit and possibly showing the total pixel amount. Is there a way to do it with Powershell? Feel free to recommend some other programs that are able to do this.

I found this question and edited it a bit for my purposes:

Add-Type -Assembly System.Drawing

function Get-Image { 
process {
          $file = $_
          [Drawing.Image]::FromFile($_.FullName) |
          ForEach-Object {           
            $_ | Add-Member -PassThru NoteProperty FullName ('{0}' -f $file.FullName)
          }
         }
}

Get-ChildItem -Path 'C:\imagefolder' -Filter *.jpg -Recurse | Get-Image | ? { ($_.Width * $_.Height) -gt 4000000 } | select -expa Fullname | get-item

Now, I receive a list of jpg images that exceed the 4-million pixel limit. If I don't use the filter, it goes through all the files in the folder and throws an error for all the non-image files. This is not actually a big problem but would be nice to check only jpg, png and gif files.

Also, I'm still not able to see the total pixel size of the image and not really know how to do that.

nqw1

Posted 2019-11-28T02:17:06.137

Reputation: 225

What have you tried so far? We aren't a script writing service. – music2myear – 2019-11-28T04:34:58.337

2That's the problem that I'm not familiar with Powershell. Of course, I'm able to google the Powershell commands and similar questions from StackExchange but didn't find anything that would solve my problem. I know it's possible to get the image width and height but I'm not able to put the pieces together. Would be just embarrassing to show what I have tried so far, hehe. – nqw1 – 2019-11-28T05:32:48.540

Please show what you have tried. You're asking us to put forth effort when you are unwilling to show the effort you've given yourself. Your problem is relatively simple: you need to go through a list of files, multiply the width and height pixel values, and flag those over a certain value. So, what have you tried? – music2myear – 2019-11-28T06:54:06.820

I have now added an example what I have tried so far. – nqw1 – 2019-11-28T08:16:53.013

Answers

3

First you want to select your file types as explained in this question so you would want something like this using -Include rather than -Filter

Get-ChildItem -Path 'C:\imagefolder' -Include('*.jpg','*.png','.gif') -Recurse

From these you want to select only those over 4 million pixels. You can use the Get-Image function in your question - if you Select * on its output you can see what it gives you.

PS C:\> Get-ChildItem -Path 'C:\imagefolder' -Include('*.jpg','*.png','.gif') -Recurse | Get-Image | Select *


FullName             : C:\imagefolder\DSC00237.JPG
Tag                  :
PhysicalDimension    : {Width=5152, Height=3864}
Size                 : {Width=5152, Height=3864}
Width                : 5152
Height               : 3864
HorizontalResolution : 350
VerticalResolution   : 350
Flags                : 77840
RawFormat            : [ImageFormat: b96b3cae-0728-11d3-9d7b-0000f81ef32e]
PixelFormat          : Format24bppRgb
Palette              : System.Drawing.Imaging.ColorPalette
FrameDimensionsList  : {7462dc86-6180-4c7e-8e3f-ee7333a7a483}
PropertyIdList       : {270, 271, 272, 274...}
PropertyItems        : {270, 271, 272, 274...}

So you see it has the Width and Height so (as in your question) you can work out number of pixels by multiplying and then select only those objects where this number is greater than 4m with Where { ($_.Width * $_.Height) -gt 4000000 }

Finally you want to Select what to display from the available properties. You can rename calculated fields as described here so for name and pixels you would want to Select Fullname, @{N='Pixels'; E={ ($_.Width * $_.Height) }} to give

Get-ChildItem -Path 'C:\imagefolder' -Include('*.jpg','*.png','.gif') -Recurse | `
Get-Image | Where { ($_.Width * $_.Height) -gt 4000000 } | `
Select Fullname, @{N='Pixels'; E={ ($_.Width * $_.Height) }}

After changing the path and number of pixels this gives output like this :

PS D:\> Add-Type -Assembly System.Drawing
PS D:\> function Get-Image{
>> process {
>>           $file = $_
>>           [Drawing.Image]::FromFile($_.FullName)  |
>>           ForEach-Object{
>>             $_ | Add-Member -PassThru NoteProperty FullName ('{0}' -f $file.FullName)
>>           }
>>          }
>> }
PS D:\> Get-ChildItem -Path 'D:\Hali\OneDrive\Pictures\2004' -Include('*.jpg','*.png','.gif') -Recurse | Get-Image | Where { ($_.Width * $_.Height) -gt 100000 } | Select Fullname, @{N='Pixels'; E={ ($_.Width * $_.Height)  }}    
FullName                                                                  Pixels
--------                                                                  ------
D:\Hali\OneDrive\Pictures\2004\06\PICT0262 (2014_05_15 20_48_01 UTC).jpg 5038848
D:\Hali\OneDrive\Pictures\2004\06\PICT0264 (2014_05_15 20_48_01 UTC).jpg 5038848
D:\Hali\OneDrive\Pictures\2004\06\PICT0265 (2014_05_15 20_48_01 UTC).jpg 5038848
D:\Hali\OneDrive\Pictures\2004\06\PICT0266 (2014_05_15 20_48_01 UTC).jpg 5038848

lx07

Posted 2019-11-28T02:17:06.137

Reputation: 1 415

0

Your script is pretty much complete. You're already filtering. Though Get-ChildItem only supports a single filter. But later on you're already using Where-Object with its shorthand (?{}). Just do that after the Get-ChildItem and filter for the extension. You can get information about objects using Get-Member.

Figure out what attributes contain the extension e.g. by running Get-ChildItem example.jpg | Get-Member and use that attribute in a Where-Object to filter it.

Seth

Posted 2019-11-28T02:17:06.137

Reputation: 7 657