James O'Neill's blog

Windows Platform, Virtualization and PowerShell with a little Photography for good measure.

A VB class for EXIF picture properties - and using it from Powershell.

A VB class for EXIF picture properties - and using it from Powershell.

  • Comments 7
  • Likes

I have been carrying on with my project to make EXIF data available in PowerShell.

When I searched for Powershell and EXIF it turned up this Blog post of Scott Hanselman's. He talks about a "nice little photo library" that extracts and interprets EXIF data from images, but when I tried to get hold of copy the link was dead, so I thought "How hard can it be ?" and looked the example in the VB Express's help. The answer was "Not very hard", and I built a class library I built goes like this.

Public Class ExifImage

' Declare Constants, variables, subs and functions

' - use PUBLIC to make them available to things which use the class.

Public BitMap As System.Drawing.Bitmap

 

' I have lots of constants and a couple of functions to process information - just one shown here

Public Const ExifIDDateTimeTaken As Integer = 36867

 

' NEW is invoked when an item of this class is instantiated. Here I want to get a BITMAP object

Public Sub New(ByVal s As String)

Me.BitMap = New System.Drawing.Bitmap(s)

End Sub

 

' Now declare code to return properties. I don't want to write properties, so I declare them read only

ReadOnly Property DateTimeTaken() As String

Get

DateTimeTaken = {what ever code you need}

End Get

End Property

 

End class

This probably the time to say that it should be possible to create a new class which inherits everything from an existing class but System.Drawing.Bitmap doesn't allow this. So I just created a new object which contained a system.drawing.bitmap object - and made it accessible for other code which wanted to do anything beyond providing access to the 40 or so properties I wanted.. Those 40 properties meant quite a lot of code, but it was very repetitive stuff: even where I needed long SELECT ... CASE constructs to output "Flash switched on, but did not fire" or whatever for each of 20 different numbers values, it was mostly cutting and pasting. Parsing the maker note field to get Pentax specific information took a bit more work. Having compiled my code it was simply a case of loading it with  
[reflection.assembly]::loadfile("C:\...longpath...\OneImage.dll") 

Now I can do something like this to get an image with my exif properties,

$foo = New-Object oneimage.exifimage -argumentlist "I:\DCIM\100PENTX\IMGP3797.JPG" 
The [Tab] Key will expand $foo's properties so I can do this
PS C:\Users\Jamesone\Pictures> $foo.Flash 

Flash off

That post of Scott's talks about "spot-welding" new properties on to existing objects. Not object inheritance, mind you, "super-gluing." Like it or hate it, like super-glue, you have to respect that it solves problems. I copied his XML wholesale replaced his type name with mine and loaded it with

Update-TypeData My.Types.PS1XML

Which let me get a directory with the DatePhotoTaken field. I got a bit more adventurous and build a different XML file which would show me bytes per pixel - a quick way to find out which files have been heavily compressed and which haven't

<Types>
     <Type>
        <Name>System.IO.FileInfo</Name>
        <Members>
           <ScriptProperty>
                <Name>BytesPerPixel</Name>
                <GetScriptBlock>
                if ($this.Extension -match "jpg|raw")
                 {
                  $photo = new-object oneimage.exifimage $this.FullName
                  $this.length / ($photo.Height * $photo.width)
                }
                </GetScriptBlock>
            </ScriptProperty>
          </Members>
     </Type>
</Types>

I've attached the VB code and DLL so you can experiment. Disclaimer . Like any code on my blog, this code is provided as an Example for illustration purposes is only. It comes with No support and No warranty that it is fit for any purpose whatsoever.
Update - the code has been revised, and the link below has changed

Technorati tags: , , ,
Attachment: http://blogs.technet.com/jamesone/attachment/2767612.ashx
Comments
  • FYI, .NET 3.0 includes a metadata API that supports multiple image metadata formats (Exchangeable image file (Exif), tEXt (PNG Textual Data), image file directory (IFD), International Press Telecommunications Council (IPTC), and Extensible Metadata Platform (XMP)).

    http://msdn2.microsoft.com/en-us/library/ms748873.aspx#_metadata

  • Good example of what can be achieved with PowerShell.  Could this be taken a step further into the PowerShell world and turned into one or moe cmdlets in a SnapIn?

  • n4cer

    Thanks for the link, but as far as I can see it only has a subset of the attributes I'm after. I only had a brief try but I couldn't seem to get VB Express to hook into it.

    Richard.

    Yes... er... Probably. I've yet to write my first snapin.

  • Omar Shahine, a MSFTie, is the author of that library, I'm sure he has it lying around somewhere.

  • I mailed Omar and he's going to sort it out - I duplicated his work mostly for my own education.

  • I keep thinking about GeoTagging photos. I've recently bought Efficasoft's GPS utilities for my phone.

  • I’ve been doing a ton of PowerShell recently, in which is part of the reason why the number of blog posts

Your comment has been posted.   Close
Thank you, your comment requires moderation so it may take a while to appear.   Close
Leave a Comment