|
By: Paul S Cilwa |
Posted: 4/10/2026 |
|
Page Views: 21 |
| Hashtags: #Namtira #VisualBasic #VBNET #ClassLibrary #NamtiraLib #SuperImages #Image #Crop #Stretch #Cover #Fit #EXIF |
| Extension methods for cropping, stretching, covering, and fitting images, plus EXIF property handling. |
| Estimated reading time: 12 minute(s) (2623 words) |
| Module SuperImages |
| Member | Parameters | Example |
| IsImage | aFile As FileInfo | If myFile.IsImage() Then ... |
| IsImage | aFilename As String | If "photo.jpg".IsImage() Then ... |
| Crop | anImage As Image, DesiredRect As Rectangle | img.Crop(rect) |
| Crop | anImage As Image, DesiredHeight, DesiredWidth | img.Crop(100, 200) |
| Crop | anImage As Image, FromX, FromY, DesiredHeight, DesiredWidth | img.Crop(10, 10, 100, 200) |
| Stretch | anImage As Image, DesiredHeight, DesiredWidth | img.Stretch(100, 200) |
| Stretch | anImage As Image, DesiredSize As Size | img.Stretch(mySize) |
| Cover | anImage As Image, DesiredHeight, DesiredWidth | img.Cover(100, 200) |
| Cover | anImage As Image, DesiredSize As Size | img.Cover(mySize) |
| Fit | anImage As Image, DesiredHeight, DesiredWidth | img.Fit(100, 200) |
| Fit | anImage As Image, DesiredSize As Size | img.Fit(mySize) |
| SaveAsIcon | anImage As Image, TargetPathname As String | img.SaveAsIcon("icon.ico") |
| CopyResized | aFile As FileInfo, TargetPath, NewHeight, NewWidth, RetainProperties (opt), Stretch (opt) | CopyResized(f, "out.jpg", 600, 800) |
| ScaleImage | OldImage As Image, TargetHeight, TargetWidth, Stretch (opt) | ScaleImage(img, 600, 800) |
| Class ImageScaleCalculator |
| Member | Parameters | Example |
| New | aSourceSize As Size (opt), aTargetSize As Size (opt), aMode As Modes (opt) | Dim c As New ImageScaleCalculator(src, tgt, Modes.Cover) |
| Modes | — | Stretch, Cover, Fit |
| AdjustedTargetRect | — | c.AdjustedTargetRect → Rectangle |
| Class ImageProperties |
| Member | Parameters | Example |
| New | Bitmap As System.Drawing.Bitmap | Dim ip As New ImageProperties(bmp) |
| New | FileName As String | Dim ip As New ImageProperties("photo.jpg") |
| IsPropertyDefined | ID As Int32 | ip.IsPropertyDefined(&H320) |
| CloneTo | Target As ImageProperties | oldProps.CloneTo(newProps) |
| Title | — | ip.Title → String |
| Description | — | ip.Description → String |
| Count | — | ip.Count → Int16 |
Imports System.IO
Imports System.Runtime.CompilerServices
Imports System.Runtime.Serialization
Imports System.Text
IsImage
Extension methods that check whether a file has a recognized image
extension (.jpg, .jpeg, .png, .bmp, .gif). The String
overload wraps the file path in a FileInfo and delegates
to the primary overload.
Public Module SuperImages
<Extension()>
Public Function IsImage(aFile As FileInfo) As Boolean
If aFile.Exists Then
Select Case aFile.Extension.LCase
' We can use any of these file types
Case ".jpg", ".jpeg", ".png", ".bmp", ".gif"
Return True
Case Else
Return False
End Select
Else
Return False
End If
End Function
<Extension()>
Public Function IsImage(aFilename As String) As Boolean
Return IsImage(New FileInfo(aFilename))
End Function
End Module
Crop
Three overloads for cropping an image. The Rectangle
overload clamps the crop area to the image bounds, then draws the
selected region into a new bitmap. The two-parameter form crops from
the origin; the four-parameter form crops from an arbitrary point.
<Extension()>
Public Function Crop(anImage As Image, DesiredRect As Rectangle) As Image
With DesiredRect
.Width = Math.Min(.Width, anImage.Width)
.Height = Math.Min(.Height, anImage.Height)
End With
Dim Result As New Bitmap(DesiredRect.Width, DesiredRect.Height)
Using grp = Graphics.FromImage(Result)
grp.DrawImage(anImage,
New Rectangle(0, 0, DesiredRect.Width, DesiredRect.Height),
DesiredRect,
GraphicsUnit.Pixel)
End Using
Return Result
End Function
<Extension()>
Public Function Crop(anImage As Image,
DesiredHeight As Int16,
DesiredWidth As Int16) As Image
Dim DesiredRect As New Rectangle(0, 0, DesiredHeight, DesiredWidth)
Return Crop(anImage, DesiredRect)
End Function
<Extension()>
Public Function Crop(anImage As Image,
FromX As Int16,
FromY As Int16,
DesiredHeight As Int16,
DesiredWidth As Int16) As Image
Dim DesiredRect As New Rectangle(FromX, FromY, DesiredHeight, DesiredWidth)
Return Crop(anImage, DesiredRect)
End Function
Stretch
Resizes an image to exact dimensions without preserving the aspect
ratio. The Int16 overload constructs a Size
and delegates to the Size overload.
<Extension()>
Public Function Stretch(anImage As Image, DesiredHeight As Int16, DesiredWidth As Int16) As Image
Dim DesiredSize As New Size(DesiredHeight, DesiredWidth)
Return Stretch(anImage, DesiredSize)
End Function
<Extension()>
Public Function Stretch(anImage As Image, DesiredSize As Size) As Image
Return New Bitmap(anImage, DesiredSize.Width, DesiredSize.Height)
End Function
Cover
Scales the image so it completely fills the target dimensions (like
CSS background-size: cover). The image is scaled up until
both axes meet or exceed the target, then centered so any overflow is
clipped evenly.
<Extension()>
Public Function Cover(anImage As Image, DesiredHeight As Int16, DesiredWidth As Int16) As Image
Dim DesiredSize As New Size(DesiredHeight, DesiredWidth)
Return Cover(anImage, DesiredSize)
End Function
<Extension()>
Public Function Cover(anImage As Image, DesiredSize As Size) As Image
Dim R As New ImageScaleCalculator(anImage.Size, DesiredSize, ImageScaleCalculator.Modes.Cover)
Dim Result = New Bitmap(DesiredSize.Width, DesiredSize.Height)
Using grp = Graphics.FromImage(Result)
grp.DrawImage(anImage,
R.AdjustedTargetRect.Left,
R.AdjustedTargetRect.Top,
R.AdjustedTargetRect.Width,
R.AdjustedTargetRect.Height)
End Using
Return Result
End Function
Fit
Scales the image to fit entirely within the target dimensions (like
CSS background-size: contain). The image is scaled down
until both axes fit within the target, then centered so any letterbox
area is even.
<Extension()>
Public Function Fit(anImage As Image, DesiredHeight As Int16, DesiredWidth As Int16) As Image
Dim DesiredSize As New Size(DesiredHeight, DesiredWidth)
Return Fit(anImage, DesiredSize)
End Function
<Extension()>
Public Function Fit(anImage As Image, DesiredSize As Size) As Image
Dim R As New ImageScaleCalculator(anImage.Size, DesiredSize, ImageScaleCalculator.Modes.Fit)
Dim Result = New Bitmap(DesiredSize.Width, DesiredSize.Height)
Using grp = Graphics.FromImage(Result)
grp.DrawImage(anImage,
R.AdjustedTargetRect.Left,
R.AdjustedTargetRect.Top,
R.AdjustedTargetRect.Width,
R.AdjustedTargetRect.Height)
End Using
Return Result
End Function
SaveAsIcon
Saves a clone of the image in ICO format at the specified path.
<Extension()>
Public Sub SaveAsIcon(anImage As Image, TargetPathname As String)
anImage.Clone().Save(TargetPathname, ImageFormat.Icon)
End Sub
CopyResized
Loads an image from disk, scales it via ScaleImage, optionally
copies EXIF properties from the original, and saves the result as a
JPEG.
Public Sub CopyResized(aFile As FileInfo,
TargetPath As String,
NewHeight As Int16,
NewWidth As Int16,
Optional RetainProperties As Boolean = True,
Optional Stretch As Boolean = False)
Dim Original As Image
Dim Duplicate As Image
Original = Image.FromFile(aFile.FullName)
Duplicate = ScaleImage(Original, NewHeight, NewWidth, Stretch)
If RetainProperties Then
Dim OldTags As New ImageProperties(Original)
Dim NewTags As New ImageProperties(Duplicate)
OldTags.CloneTo(NewTags)
End If
Duplicate.Save(TargetPath.Replace(".jpeg", ".jpg"),
ImageFormat.Jpeg)
Original.Dispose()
Duplicate.Dispose()
End Sub
ScaleImage
Proportionally scales an image to fit within the given height and
width, preserving the aspect ratio. If the proportional width exceeds
the target width, the calculation flips to width-first.
Public Function ScaleImage(ByVal OldImage As Image,
ByVal TargetHeight As Integer,
ByVal TargetWidth As Integer,
Optional Stretch As Boolean = False) As Image
Dim NewHeight As Integer = TargetHeight
Dim NewWidth As Integer = NewHeight / OldImage.Height * OldImage.Width
If NewWidth > TargetWidth Then
NewWidth = TargetWidth
NewHeight = NewWidth / OldImage.Width * OldImage.Height
End If
Return New Bitmap(OldImage, NewWidth, NewHeight)
End Function
ImageScaleCalculator
A helper class used by Cover and Fit. Given source and
target sizes plus a mode, it computes the correct scaling ratio and a
centered Rectangle for drawing. The Modes enum
selects between Stretch, Cover, and Fit behaviour.
Public Class ImageScaleCalculator
Public SourceSize As Size
Public TargetSize As Size
Public Enum Modes
Stretch
Cover
Fit
End Enum
Public Mode As Modes = Modes.Fit
Public Sub New(Optional aSourceSize As Size = Nothing,
Optional aTargetSize As Size = Nothing,
Optional aMode As Modes = Modes.Stretch)
SourceSize = aSourceSize
TargetSize = aTargetSize
Mode = aMode
End Sub
Private ReadOnly Property Ratio As Double
Get
Dim RatioX As Double, RatioY As Double
RatioX = TargetSize.Width / SourceSize.Width
RatioY = TargetSize.Height / SourceSize.Height
If Mode = Modes.Fit Then
Return Math.Min(RatioX, RatioY)
Else
Return Math.Max(RatioX, RatioY)
End If
End Get
End Property
Public ReadOnly Property AdjustedTargetRect As Rectangle
Get
Dim Result As Rectangle
Dim NewHeight As Integer, NewWidth As Integer
Select Case Mode
Case Modes.Stretch
Result = New Rectangle(0, 0, TargetSize.Width, TargetSize.Height)
Case Modes.Fit, Modes.Cover
NewHeight = SourceSize.Height * Ratio
NewWidth = SourceSize.Width * Ratio
Dim posX As Integer = (TargetSize.Width - (SourceSize.Width * Ratio)) / 2
Dim posY As Integer = (TargetSize.Height - (SourceSize.Height * Ratio)) / 2
Result = New Rectangle(posX, posY, NewWidth, NewHeight)
End Select
Return Result
End Get
End Property
End Class
ImageProperties
Wraps a Bitmap and provides read access to its EXIF
metadata. Two enums define the EXIF data types and the standard
property tag IDs. The CloneTo method copies all EXIF properties
from one image to another, handling each data type appropriately.
Public Class ImageProperties
Public Enum ExifDataTypes As Int16
Unknown = 0
UnsignedByte = 1
AsciiString = 2
UnsignedShort = 3
UnsignedLong = 4
UnsignedRational = 5
SignedByte = 6
Undefined = 7
SignedShort = 8
SignedLong = 9
SignedRational = 10
SingleFloat = 11
DoubleFloat = 12
End Enum
Public Enum ExifPropertyNames As Int32
ExifIFD = &H8769
GpsIFD = &H8825
NewSubfileType = &HFE
SubfileType = &HFF
ImageWidth = &H100
ImageHeight = &H101
BitsPerSample = &H102
ImageTitle = &H320
ImageDescription = &H10E
Copyright = &H8298
Compression = &H103
PhotometricInterp = &H106
ThreshHolding = &H107
CellWidth = &H108
CellHeight = &H109
FillOrder = &H10A
DocumentName = &H10D
EquipMake = &H10F
EquipModel = &H110
StripOffsets = &H111
Orientation = &H112
SamplesPerPixel = &H115
RowsPerStrip = &H116
StripBytesCount = &H117
MinSampleValue = &H118
MaxSampleValue = &H119
XResolution = &H11A
YResolution = &H11B
PlanarConfig = &H11C
PageName = &H11D
XPosition = &H11E
YPosition = &H11F
FreeOffset = &H120
FreeByteCounts = &H121
GrayResponseUnit = &H122
GrayResponseCurve = &H123
T4Option = &H124
T6Option = &H125
ResolutionUnit = &H128
PageNumber = &H129
TransferFuncition = &H12D
SoftwareUsed = &H131
DateTime = &H132
Artist = &H13B
HostComputer = &H13C
Predictor = &H13D
WhitePoint = &H13E
PrimaryChromaticities = &H13F
ColorMap = &H140
HalftoneHints = &H141
TileWidth = &H142
TileLength = &H143
TileOffset = &H144
TileByteCounts = &H145
InkSet = &H14C
InkNames = &H14D
NumberOfInks = &H14E
DotRange = &H150
TargetPrinter = &H151
ExtraSamples = &H152
SampleFormat = &H153
SMinSampleValue = &H154
SMaxSampleValue = &H155
TransferRange = &H156
JPEGProc = &H200
JPEGInterFormat = &H201
JPEGInterLength = &H202
JPEGRestartInterval = &H203
JPEGLosslessPredictors = &H205
JPEGPointTransforms = &H206
JPEGQTables = &H207
JPEGDCTables = &H208
JPEGACTables = &H209
YCbCrCoefficients = &H211
YCbCrSubsampling = &H212
YCbCrPositioning = &H213
REFBlackWhite = &H214
ICCProfile = &H8773
Gamma = &H301
ICCProfileDescriptor = &H302
SRGBRenderingIntent = &H303
ResolutionXUnit = &H5001
ResolutionYUnit = &H5002
ResolutionXLengthUnit = &H5003
ResolutionYLengthUnit = &H5004
PrintFlags = &H5005
PrintFlagsVersion = &H5006
PrintFlagsCrop = &H5007
PrintFlagsBleedWidth = &H5008
PrintFlagsBleedWidthScale = &H5009
HalftoneLPI = &H500A
HalftoneLPIUnit = &H500B
HalftoneDegree = &H500C
HalftoneShape = &H500D
HalftoneMisc = &H500E
HalftoneScreen = &H500F
JPEGQuality = &H5010
GridSize = &H5011
ThumbnailFormat = &H5012
ThumbnailWidth = &H5013
ThumbnailHeight = &H5014
ThumbnailColorDepth = &H5015
ThumbnailPlanes = &H5016
ThumbnailRawBytes = &H5017
ThumbnailSize = &H5018
ThumbnailCompressedSize = &H5019
ColorTransferFunction = &H501A
ThumbnailData = &H501B
ThumbnailImageWidth = &H5020
ThumbnailImageHeight = &H502
ThumbnailBitsPerSample = &H5022
ThumbnailCompression = &H5023
ThumbnailPhotometricInterp = &H5024
ThumbnailImageDescription = &H5025
ThumbnailEquipMake = &H5026
ThumbnailEquipModel = &H5027
ThumbnailStripOffsets = &H5028
ThumbnailOrientation = &H5029
ThumbnailSamplesPerPixel = &H502A
ThumbnailRowsPerStrip = &H502B
ThumbnailStripBytesCount = &H502C
ThumbnailResolutionX = &H502D
ThumbnailResolutionY = &H502E
ThumbnailPlanarConfig = &H502F
ThumbnailResolutionUnit = &H5030
ThumbnailTransferFunction = &H5031
ThumbnailSoftwareUsed = &H5032
ThumbnailDateTime = &H5033
ThumbnailArtist = &H5034
ThumbnailWhitePoint = &H5035
ThumbnailPrimaryChromaticities = &H5036
ThumbnailYCbCrCoefficients = &H5037
ThumbnailYCbCrSubsampling = &H5038
ThumbnailYCbCrPositioning = &H5039
ThumbnailRefBlackWhite = &H503A
ThumbnailCopyRight = &H503B
LuminanceTable = &H5090
ChrominanceTable = &H5091
FrameDelay = &H5100
LoopCount = &H5101
PixelUnit = &H5110
PixelPerUnitX = &H5111
PixelPerUnitY = &H5112
PaletteHistogram = &H5113
ExifExposureTime = &H829A
ExifFNumber = &H829D
ExifExposureProg = &H8822
ExifSpectralSense = &H8824
ExifISOSpeed = &H8827
ExifOECF = &H8828
ExifVer = &H9000
ExifDTOrig = &H9003
ExifDTDigitized = &H9004
ExifCompConfig = &H9101
ExifCompBPP = &H9102
ExifShutterSpeed = &H9201
ExifAperture = &H9202
ExifBrightness = &H9203
ExifExposureBias = &H9204
ExifMaxAperture = &H9205
ExifSubjectDist = &H9206
ExifMeteringMode = &H9207
ExifLightSource = &H9208
ExifFlash = &H9209
ExifFocalLength = &H920A
ExifMakerNote = &H927C
ExifUserComment = &H9286
ExifDTSubsec = &H9290
ExifDTOrigSS = &H9291
ExifDTDigSS = &H9292
ExifFPXVer = &HA000
ExifColorSpace = &HA001
ExifPixXDim = &HA002
ExifPixYDim = &HA003
ExifRelatedWav = &HA004
ExifInterop = &HA005
ExifFlashEnergy = &HA20B
ExifSpatialFR = &HA20C
ExifFocalXRes = &HA20E
ExifFocalYRes = &HA20F
ExifFocalResUnit = &HA210
ExifSubjectLoc = &HA214
ExifExposureIndex = &HA215
ExifSensingMethod = &HA217
ExifFileSource = &HA300
ExifSceneType = &HA301
ExifCfaPattern = &HA302
GpsVer = &H0
GpsLatitudeRef = &H1
GpsLatitude = &H2
GpsLongitudeRef = &H3
GpsLongitude = &H4
GpsAltitudeRef = &H5
GpsAltitude = &H6
GpsGpsTime = &H7
GpsGpsSatellites = &H8
GpsGpsStatus = &H9
GpsGpsMeasureMode = &HA
GpsGpsDop = &HB
GpsSpeedRef = &HC
GpsSpeed = &HD
GpsTrackRef = &HE
GpsTrack = &HF
GpsImgDirRef = &H10
GpsImgDir = &H11
GpsMapDatum = &H12
GpsDestLatRef = &H13
GpsDestLat = &H14
GpsDestLongRef = &H15
GpsDestLong = &H16
GpsDestBearRef = &H17
GpsDestBear = &H18
GpsDestDistRef = &H19
GpsDestDist = &H1A
ImageXPComment = 40092
ImageXPTitle = 40091
End Enum
The constructors accept either a Bitmap object or a file
path. IsPropertyDefined checks whether a given EXIF tag exists
in the image.
Private ReadOnly MyBitmap As Bitmap
Public Sub New(ByRef Bitmap As System.Drawing.Bitmap)
If Bitmap Is Nothing Then
Throw New ArgumentNullException(NameOf(Bitmap))
End If
MyBitmap = Bitmap
End Sub
Public Sub New(FileName As String)
MyBitmap = DirectCast(Image.FromFile(FileName), Bitmap)
End Sub
Public Function IsPropertyDefined(ID As Int32) As Boolean
Return [Array].IndexOf(MyBitmap.PropertyIdList, ID) > -1
End Function
CloneTo iterates every EXIF property in the source image and
copies it to the target, dispatching to type-specific helpers for each
data type.
Public Sub CloneTo(Target As ImageProperties)
Dim PropertyNames() As String = [Enum].GetNames(GetType(ExifPropertyNames))
For Each P As PropertyItem In MyBitmap.PropertyItems
Dim T As PropertyItem
If Target.IsPropertyDefined(P.Id) Then
T = Target.MyBitmap.GetPropertyItem(P.Id)
Else
T = DirectCast(FormatterServices.GetUninitializedObject(GetType(Imaging.PropertyItem)), Imaging.PropertyItem)
T.Id = P.Id
End If
Select Case P.Type
Case ExifDataTypes.UnsignedByte
If P.Id <> ExifPropertyNames.ImageXPComment Then
ClonePropertyByte(P, T)
Else
ClonePropertyString(P, T)
End If
Case ExifDataTypes.SignedByte
ClonePropertySByte(P, T)
Case ExifDataTypes.UnsignedShort
ClonePropertyUInt16(P, T)
Case ExifDataTypes.SignedShort
ClonePropertyInt16(P, T)
Case ExifDataTypes.UnsignedLong
ClonePropertyUInt32(P, T)
Case ExifDataTypes.SignedLong
ClonePropertyInt32(P, T)
Case ExifDataTypes.AsciiString, ExifDataTypes.Undefined
ClonePropertyString(P, T)
End Select
Target.MyBitmap.SetPropertyItem(T)
Next
End Sub
The private clone helpers handle each EXIF data type, copying the raw
bytes from the source property item to the target.
Private Sub ClonePropertyByte(OldItem As PropertyItem, ByVal NewItem As PropertyItem)
With NewItem
.Id = OldItem.Id
ReDim .Value(1)
.Value(0) = OldItem.Value(0)
.Len = 1
.Type = ExifDataTypes.UnsignedByte
End With
End Sub
Private Sub ClonePropertySByte(OldItem As PropertyItem, ByVal NewItem As PropertyItem)
With NewItem
.Id = OldItem.Id
ReDim .Value(1)
.Value(0) = CSByte(OldItem.Value(0))
.Len = 1
.Type = ExifDataTypes.SignedByte
End With
End Sub
Private Sub ClonePropertyInt16(OldItem As PropertyItem, ByVal NewItem As PropertyItem)
With NewItem
.Id = OldItem.Id
ReDim .Value(2)
.Value(0) = OldItem.Value(0) And &HFF
.Value(1) = OldItem.Value(1) And &HFF00 >> 8
.Len = 2
.Type = ExifDataTypes.SignedShort
End With
End Sub
Private Sub ClonePropertyUInt16(OldItem As PropertyItem, ByVal NewItem As PropertyItem)
ClonePropertyInt16(OldItem, NewItem)
NewItem.Type = ExifDataTypes.UnsignedShort
End Sub
Private Sub ClonePropertyInt32(OldItem As PropertyItem, ByVal NewItem As PropertyItem)
With NewItem
.Id = OldItem.Id
ReDim .Value(4)
For i As Byte = 0 To 3
.Value(i) = CByte(OldItem.Value(i))
Next
.Len = 4
.Type = ExifDataTypes.SignedLong
End With
End Sub
Private Sub ClonePropertyUInt32(OldItem As PropertyItem, ByVal NewItem As PropertyItem)
ClonePropertyInt32(OldItem, NewItem)
NewItem.Type = ExifDataTypes.UnsignedLong
End Sub
Private Sub ClonePropertyString(OldItem As PropertyItem, ByVal NewItem As PropertyItem)
Dim MyEncoding As Encoding = System.Text.Encoding.ASCII
With NewItem
.Value = MyEncoding.GetBytes(GetPropertyString(OldItem))
.Len = .Value.Length * 2
.Type = ExifDataTypes.AsciiString
End With
End Sub
Private getter helpers extract typed values from raw EXIF property
bytes.
Private Function GetPropertyUByte(Item As PropertyItem) As Byte
Return Item.Value(0)
End Function
Private Function GetPropertySByte(Item As PropertyItem) As SByte
Return Item.Value(0)
End Function
Private Function GetPropertyInt16(Item As PropertyItem) As Int16
Return Item.Value(1) << 8 Or Item.Value(0)
End Function
Private Function GetPropertyUInt16(Item As PropertyItem) As UInt16
Return Item.Value(1) << 8 Or Item.Value(0)
End Function
Private Function GetPropertyInt32(Item As PropertyItem) As Int32
Return Item.Value(1) << 8 Or Item.Value(0)
End Function
Private Function GetPropertyString(Item As PropertyItem) As String
If Item.Value Is Nothing Then Return String.Empty
Dim Encoder As System.Text.Encoding
If Item.Type = ExifDataTypes.AsciiString Then
Encoder = System.Text.Encoding.ASCII
Else
Encoder = System.Text.Encoding.Unicode
End If
Dim R As String = Encoder.GetString(Item.Value)
If R.EndsWith(vbNullChar) Then R = R.Substring(0, R.Length - 1)
Return R.ToString
End Function
Three public read-only properties expose the image's title (checking
multiple EXIF tags in priority order), description, and total property
count.
Public ReadOnly Property Title As String
Get
Dim Result As String
If IsPropertyDefined(ExifPropertyNames.ImageTitle) Then
Result = GetPropertyString(MyBitmap.GetPropertyItem(ExifPropertyNames.ImageTitle))
If Result.Length > 0 AndAlso Result <> Description Then Return Result
End If
If IsPropertyDefined(ExifPropertyNames.ImageXPTitle) Then
Result = GetPropertyString(MyBitmap.GetPropertyItem(ExifPropertyNames.ImageXPTitle))
If Result.Length > 0 AndAlso Result <> Description Then Return Result
End If
If IsPropertyDefined(ExifPropertyNames.ImageDescription) Then
Result = GetPropertyString(MyBitmap.GetPropertyItem(ExifPropertyNames.ImageDescription))
If Result > "" Then Return Result
End If
Return String.Empty
End Get
End Property
Public ReadOnly Property Description As String
Get
Dim Result As String
If IsPropertyDefined(ExifPropertyNames.ImageXPComment) Then
Result = GetPropertyString(MyBitmap.GetPropertyItem(ExifPropertyNames.ImageXPComment))
If Result > "" Then Return Result
End If
If IsPropertyDefined(ExifPropertyNames.ExifUserComment) Then
Result = GetPropertyString(MyBitmap.GetPropertyItem(ExifPropertyNames.ExifUserComment))
If Result > "" Then Return Result
End If
Return String.Empty
End Get
End Property
Public ReadOnly Property Count As Int16
Get
Return MyBitmap.PropertyItems.Count
End Get
End Property
End Class