Snippet

Extrahování ikon z *.ico souboru

Přidáno: 6.8.2008       Kategorie: VB.NET - Soubory       Autor: Jan Novák

V tomto snippetu bych rád předvedl, jak lze jednoduše a rychle extrahovat ikony z *.ico souborů.
Článek je částečně založen na http://www.codeproject.com/KB/vb/MultiIcon.aspx .
Specifikaci *.ico formátu naleznete na http://www.daubnet.com/formats/ICO.html .
UPOZORNĚNÍ: Tento kód Vám neumožní extrahovat Vista ikony (255x255). Pokud takovou možnost hledáte, může pomoct tento článek: http://www.codeproject.com/KB/cs/IconLib.aspx

Imports System
Imports System.IO
Imports System.Collections.Generic

Public Class MultiIcon
    Shared stream As MemoryStream ' Tento stream obsahuje soubr, který předáme do konstruktoru. Je sdílený, aby do něj mohli přistupovat i třídy Header a Entry
    Private items As New List(Of Icon) ' Tento seznam bude obsahovat extrahované ikony. Deklarujeme jako privátní, přístup nastavíme vlastnostmi, aby nebylo možné 'zvenčí' přidávat ikony

    ' Třída, která přečte záhlaví *.ico souboru
    Private Class Header
        Public Reserved As Short ' Nepoužívané pole
        Public Type As Short ' Typ souboru. 0=bitmapa, 1=ikona, 2=kurzor
        Public Count As Short ' Počet ikon v souboru
        Public Sub New() ' Konstruktor přečtě z proměnné stream údaje o záhlaví souboru
            Dim br As New BinaryReader(stream)
            Me.Reserved = br.ReadInt16
            Me.Type = br.ReadInt16
            Me.Count = br.ReadInt16
        End Sub
    End Class
    ' Třída, která reprezentuje údaje o jedné ikoně v souboru
    Private Class Entry
        Public Width As Byte
        Public Height As Byte
        Public Colors As Byte ' Ikony s BitsPerPixel>8 vrací Colors=0
        Public Reserved As Byte
        Public Planes As Short
        Public BitsPerPixel As Short
        Public Length As Integer ' Délka resource ikony
        Public Offset As Integer ' Umístění ikony v souboru
        Public Sub New() ' Konstruktor opět přečte z stream údaje o záhlaví jedné ikony v souboru
            Dim br As New BinaryReader(stream)
            Me.Width = br.ReadByte
            Me.Height = br.ReadByte
            Me.Colors = br.ReadByte
            Me.Reserved = br.ReadByte
            Me.Planes = br.ReadInt16
            Me.BitsPerPixel = br.ReadInt16
            Me.Length = br.ReadInt32
            Me.Offset = br.ReadInt32
        End Sub
    End Class

    Public Sub New(ByVal path As String) ' Konstruktoru předáme cestu k ikoně
        Using fs As New FileStream(path, FileMode.Open, FileAccess.Read) ' Pomocí FileStream načtene ikonu do proměnné 'stream'
            Dim bytes(fs.Length) As Byte
            fs.Read(bytes, 0, fs.Length)
            stream = New MemoryStream(bytes)
            stream.Seek(0, SeekOrigin.Begin)
        End Using
        Dim header As Header = New Header ' Vytvořením nové instance se přečte záhlaví souboru
        Dim entries As New List(Of Entry) ' Přečteme záhlaví ikony tolikrát, kolik máme v souboru ikon
        For i As Integer = 0 To header.Count - 1
            entries.Add(New Entry())
        Next
        For i As Integer = 0 To header.Count - 1 ' Teď každou ikonu extrahujeme
            Dim entry As Entry = entries(i) ' Příslušná hlavička ke konkrétní ikoně
            Dim bytes(entry.Length) As Byte ' Délka resource ikony
            Using ms As New MemoryStream
                Using bw As New BinaryWriter(ms) ' Vytvoříme v paměti nový 'soubor' obsahující pouze jednu ikonu
                    stream.Seek(entry.Offset, SeekOrigin.Begin)
                    stream.Read(bytes, 0, entry.Length)
                    With bw
                        Dim count As Short = 1 ' Soubor obsahuje pouze jednu ikonu
                        Dim offset As Integer = 22 ' Zde končí hlavička a začíná resource ikony
                        .Write(header.Reserved)
                        .Write(header.Type)
                        .Write(count)
                        .Write(entry.Width)
                        .Write(entry.Height)
                        .Write(entry.Colors)
                        .Write(entry.Reserved)
                        .Write(entry.Planes)
                        .Write(entry.BitsPerPixel)
                        .Write(entry.Length)
                        .Write(offset)
                        .Write(bytes)
                    End With
                    ms.Seek(0, SeekOrigin.Begin)
                    items.Add(New Icon(ms, entry.Width, entry.Height)) ' Využijeme schopnosti třídy Icon otevřít ze Streamu a předáme Stream, který jsme vytvořili v paměti
                End Using
            End Using
        Next
        stream.Close() ' Po ukončení exekuce konstruktoru zavřeme stream
    End Sub

    Public ReadOnly Property Count() As Integer ' Vlastnost pouze pro čtení, udávající počet ikon v souboru
        Get
            Return items.Count
        End Get
    End Property
    Public ReadOnly Property Item(ByVal index As Integer) As Icon ' vlastnost, která vrací tu kterou ikonu z kolekce items
        Get
            Return items.Item(index)
        End Get
    End Property
End Class 
 

VBNET.CZ | © 2007 Tomáš Herceg, Tomáš Jecha | Kopírování a přejímání jakéhokoliv obsahu z tohoto webu je bez písemného svolení autorů zakázáno.