Click here to Skip to main content
Click here to Skip to main content

Extracting and displaying icons with VB.NET

, 21 Mar 2007
Rate this:
Please Sign up or sign in to vote.
Uses pure VB.NET code to extract and display icons as bitmap objects.

Screenshot - 32bitIcon.jpg

Introduction

One of the first 'bugs' that users of the .NET framework find is that lack of support for 32bit Icons with an alpha channel. This has to be one of the most annoying bugs because 32bit icons add that extra swishness and professionalism to user interfaces thanks to their semi-transparency enabling them to blend with whatever background you or the end user of your application may have. This article explains how icons are stored in .ico files and provides code that is able to take 4, 8, 24 and 32 bit Icons and display them properly with an alpha channel on 32bit.

Further Reading

Further information on icons can be found:

Using the code

Including In Your Application

The link above provides you with Source Code and an example application testing the code. You can either reference Icons.dll in your project, add the Icons Project to your solution or add IconFile.vb, IconImage.vb and IconImageCollection.vb to a project. The default namespace for the Icons project and Icons.dll is System.Drawing, so the namespaces are kept nice and neat and tidy.

Overview of Objects

The project consists of five classes: three Public and two Friend. The Public Classes are:

  • IconFile
    Represents an icon file. Takes either a filename, FileInfo or Stream as constructor parameters from which icon information is loaded. Includes a GetIcon function, which returns the icon most closely matching the specified size and pixelformat. Also includes an Entries property that returns an IconImageCollection.
  • IconImage
    Represents an individual Icon Image within an icon file. Uses a Friend constructor that takes the stream used to create the parent IconFile. Exposes an Icon Property that returns the Icon Image as a Bitmap so it can be edited easily by your application if necessary. IconImages should not be instantiated from your code.
  • IconImageCollection
    A collection of IconImages in an IconFile. Normal collection methods, functions and properties are exposed.

Friend Classes are:

  • SizeCollection
    A collection of sizes used to find the best icon in IconFile.GetIcon
  • PixelFormatCollection
    A collection of pixelformats used to find the best icon in IconFile.GetIcon

Points of Interest

I want to take the time to explain the Icon File Format, because I only found the information that let me complete the project in one place (despite numerous intensive searches in Google), and I can't find it anymore. Each Icon File has a header, the IconDir structure, which contains the following members:

Name

Size

Purpose

Reserved

Int16/Short/Word

Two reserved bytes, both should be zero

Type

Int16/Short/Word

Two bytes that specifies what type of resource this is as the icon file format and cursor file format are very similar. Should be 1 for icons.

Count

Int16/Short/Word

Specifies the number of icons within the icon file

Entries

IconDirEntry

Specifies information for each icon within the file

As mentioned above, for each icon there is a corresponding IconDirEntry which specifies size and where in the file the Icon is:

Name

Size

Purpose

Width

Byte

The Width of the Icon

Height

Byte

The Height of the Icon. Occasionally I've found this value to be double the height of the icon, but this hasn't been a regular occurance and hence my code ignores this value.

ColourCount

Byte

The number of colours used in the icon. This value is zero if all 256 or more colours are used (ie. 8bpp+)

Reserved

Byte

Another Reserved Byte

Planes

Int16/Short/Word

The number of planes in the Icon Image

BitCount

Int16/Short/Word

The number of bits used to encode each pixel

BytesInRes

Int32/Integer/DWord

The number of bytes that the icon plus it's Bitmap Header occupy

ImageOffset

Int32/Integer/DWord

The address of the first byte of the icon in the file

Once information for all of the icons has been specified, the file moves straight in to the first icon. Each Icon has a BitmapInfoHeader, a colour table and an XOR and an AND mask. For anyone who knows anything about the Bitmap file format this may look familiar, but for the unacquainted I will explain:

Name

Size

Purpose

Size

Int32/Integer/DWord

The Size (in bytes) of the BitmapInfoHeader (usually 40)

Width

Int32/Integer/DWord

The Width of the icon

Height

Int32/Integer/DWord

The Height of the icon. The value actually located here is twice the height of the icon because Windows needs to be told the height of both the XOR and AND masks

Planes

Int16/Short/Word

The number of planes in the icon

BitCount

Int16/Short/Word

The number of bits used to encode each pixel

Compression

Int32/Integer/DWord

In a bitmap file this DWord describes what compression is used on the image. In Icons this is always 0 for no compression

SizeImage

Int32/Integer/DWord

The Size (in bytes) of the image

XPelsPerMeter, YPelsPerMeter, ColoursUsed, ColoursRequired

Int32/Integer/DWord

These DWords are not used in icons and should be zero.

We then move into the RGB Table, XOR and AND masks. Here a number of different things happen depending upon the BitCount of the icon Image.

  • In a 4bpp Icon and an 8bpp Icon, the RGB Table has a number of different colours and then the XOR table provides an array of numbers that are indicies to the colour in the RGB Table that that pixel should be.
  • In a 24bpp Icon, there is effectively no RGB Table and the XOR numbers are the Blue, Green and Red values of the colour that the corresponding pixels should be.
  • In a 32bpp Icon, there is effectively no XOR mask and the RGB Table provides separate RgbQuads for each pixel.

The RGB Table uses RgbQuads to specify it's colours:

Name

Size

Purpose

Blue

Byte

The Blue value of the pixel

Green

Byte

The Green value of the pixel

Red

Byte

The Red value of the pixel

Reserved

Byte

Either 0 for 4 and 8bpp, not included in 24bpp or the Alpha value of the pixel in 32bpp

The AND mask specifies which pixels show colours and which pixels are transparent. It is basically a 1bpp XOR mask of opaque and transparent. This originally gave me problems because I couldn't get the AND mask to line up on 16x16 and 48x48 icons. This is because the indices in the XOR and AND masks are padded out so that each row ends on a 32bit boundary. For the XOR mask this is usually fine because the rows end up ending on a 32bit boundary (16x4=64, which divides exactly into 32).

Once the AND mask is read, you have reached the end of the icon and are ready to convert the bytes into their correct index numbers and use them to build a bitmap of the icon.

Reading in the file is simply done by using a Binary Reader. Converting bytes into four bit blocks is done by converting the byte into two digit hexadecimal and using the first digit for the first pixel and the second digit for the second pixel.

Conclusion

This code now allows developers to enhance the professionalism of their applications while maintaining cross-platform capability by enabling them to use 32bit icons in their work.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here

About the Author

Pixa
Business Analyst MGM Assurance
United Kingdom United Kingdom
I began programming by learning VBA for Excel a few years ago and progressed quickly through VB6 to VB.NET. I'm currently studying A Level Computing, Physics and Maths with Mechanics.

Comments and Discussions

 
GeneralMy vote of 2 PinmemberMark Hurd7-Feb-10 2:57 
GeneralFile missing Pinmembersprice8624-Jul-08 3:18 
QuestionHow do I get the code working? PinmemberShahpour28-Apr-07 17:54 
AnswerRe: How do I get the code working? PinmemberPixa29-Apr-07 3:21 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Mobile
Web03 | 2.8.140721.1 | Last Updated 22 Mar 2007
Article Copyright 2007 by Pixa
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid