Jump to content
Sign in to follow this  
jennico

1. how to display/extract all icons in an icongroup ? [solved with UDF]

Recommended Posts

jennico

i am working on something like an icon manager for autoit.

1. i would like to display all embedded versions within one icon group like reshacker does it. is there a way to find out the number of single icons packed in an icon group and how to extract them ?

2. i would like to build a (preferable) .icl file from selected icons. how could this be done with autoit means ?

any ideas welcome. i will put them together then.

j.

edit: i finally made it and added a little example script with _IconSplit UDF (remove the gui related lines if you only need the data):

_IconSplit UDF.au3

#Include <Array.au3>

Global Const $tagIconHeader = "ushort;ushort Type;ushort ImageCount;byte BitmapData[" 
Global Const $tagGRPIconDirEntry = "ubyte Width;ubyte Height;ubyte Colors;ubyte;ushort Planes;ushort BitPerPixel;dword BitmapSize;ushort BitmapOffset;" 
Global Const $tagIconStruct = "align 2;ushort;ushort Type;ushort ImageCount;ubyte Width;ubyte Height;ubyte Colors;ubyte;ushort Planes;ushort BitPerPixel;dword BitmapSize;dword BitmapOffset;byte BitmapData[" 

$filename = FileOpenDialog("Pick .ico file", @ScriptDir, "Icon files (*.ico)", 1)
If @error Then $filename = @ProgramFilesDir & "\Autoit3\Icons\au3.ico" 
$newfile = StringMid($filename, StringInStr($filename, "\", 2, -1) + 1)
FileChangeDir(@ScriptDir)

$aArray = _IconSplit($filename)
_ArrayDisplay($aArray, $newfile & " contains:")

Func _IconSplit($filename)
    
    $imageGUI = GUICreate("", 80, 80, Default, Default, -1, 128);$WS_EX_TOOLWINDOW)
    GUISetBkColor(0xFFFFFF)
    GUICtrlSetBkColor(GUICtrlCreateLabel("", 2, 0, 76, 78), 0xD4D0C8)
    GUICtrlSetResizing(-1, 102)
    GUICtrlSetState(-1, 128)
    Dim $pos = WinGetPos($imageGUI), $xborder = $pos[2] - 80, $yborder = $pos[3] - 80, $gWidth = 10, $gHeight = 0
    
    $fileopen = FileOpen($filename, 16);32
    $gBinary = FileRead($fileopen)
    FileClose($fileopen)

    $tBinary = DllStructCreate("byte[" & BinaryLen($gBinary) & "]")
    DllStructSetData($tBinary, 1, $gBinary)

    $tResource = DllStructCreate($tagIconHeader & DllStructGetSize($tBinary) - 6 & "]", DllStructGetPtr($tBinary))
    $iIconCount = DllStructGetData($tResource, "ImageCount")
    If $iIconCount = 0 Then Exit
    Dim $aIData[$iIconCount][7]

    For $i = 0 To $iIconCount - 1
        $tGrpIData = DllStructCreate($tagGRPIconDirEntry, DllStructGetPtr($tResource, "BitmapData") + $i * 16)
        $aIData[$i][0] = DllStructGetData($tGrpIData, "Width")
        $aIData[$i][1] = DllStructGetData($tGrpIData, "Height")
        $aIData[$i][2] = DllStructGetData($tGrpIData, "Colors")
        $aIData[$i][3] = DllStructGetData($tGrpIData, "Planes")
        $aIData[$i][4] = DllStructGetData($tGrpIData, "BitPerPixel")
        $aIData[$i][5] = DllStructGetData($tGrpIData, "BitmapSize")
        $aIData[$i][6] = DllStructGetData($tGrpIData, "BitmapOffset")

        $fBinary = DllStructCreate("byte[" & $aIData[$i][5] & "]")
        $tIcon = DllStructCreate($tagIconStruct & $aIData[$i][5] & "]")
        DllStructSetData($fBinary, 1, BinaryMid($gBinary, $aIData[$i][6] + 1, $aIData[$i][5]))
        DllStructSetData($tIcon, "Type", 1)
        DllStructSetData($tIcon, "ImageCount", 1)
        DllStructSetData($tIcon, "Width", $aIData[$i][0])
        DllStructSetData($tIcon, "Height", $aIData[$i][1])
        DllStructSetData($tIcon, "Colors", $aIData[$i][2])
        DllStructSetData($tIcon, "Planes", $aIData[$i][3])
        DllStructSetData($tIcon, "BitPerPixel", $aIData[$i][4])
        DllStructSetData($tIcon, "BitmapSize", $aIData[$i][5])
        DllStructSetData($tIcon, "BitmapOffset", 22)
        DllStructSetData($tIcon, "BitmapData", DllStructGetData($fBinary, 1))
        $fBinary = DllStructCreate("byte[" & DllStructGetSize($tIcon) & "]", DllStructGetPtr($tIcon))
        
        $iWidth = $aIData[$i][0] + 256 * ($aIData[$i][0] = 0)
        $iHeight = $aIData[$i][1] + 256 * ($aIData[$i][1] = 0)
        $iBits = $aIData[$i][4] + 4 * ($aIData[$i][4] = 0)
        $output = StringTrimRight($newfile, 4) & "_" & $i & "_" & $iWidth & "x" & $iHeight & "_" & $iBits & "bit.ico" 
        
        $open = FileOpen($output, 26)
        FileWrite($open, DllStructGetData($fBinary, 1))
        FileClose($open)
        
        $colorinfo = ""
        If $aIData[$i][4] = 0 And $aIData[$i][2] = 16 Then $colorinfo = "16 Colors" 
        If $aIData[$i][4] = 1 Then $colorinfo = "Monochrome" 
        If $aIData[$i][4] = 4 Then $colorinfo = "16 Colors" 
        If $aIData[$i][4] = 8 Then $colorinfo = "256 Colors" 
        If $aIData[$i][4] = 16 Then $colorinfo = "65535 Colors" 
        If $aIData[$i][4] = 24 Then $colorinfo = "RGB True Color (16 Mio)" 
        If $aIData[$i][4] = 32 Then $colorinfo = "XP Alpha Channel" 
        
        GUICtrlCreateIcon($output, 0, $gWidth, 8, $iWidth, $iHeight)
        GUICtrlSetTip(-1, "Size: " & $iWidth & "x" & $iHeight & " Pixel" & @CRLF & "Color: " & $iBits & " bit" & @CRLF & $colorinfo)
        GUICtrlSetResizing(-1, 802)
        $gWidth += $iWidth + 10
        If $iHeight > $gHeight Then $gHeight = $iHeight
    Next
    
    $gWidth += $xborder
    If $gWidth < 75 Then $gWidth = 75
    WinMove($imageGUI, "", Default, Default, $gWidth, $gHeight + $yborder + 18)
    WinSetTitle($imageGUI, "", " " & $iIconCount & StringTrimRight(" Images", $iIconCount = 1))
    GUISetState()
    WinSetOnTop($imageGUI, "", 1)

    Return $aIData
EndFunc   ;==>_IconSplit

cheers j. :)

Edited by jennico

Spoiler

I actively support Wikileaks | Freedom for Julian Assange ! | Defend freedom of speech ! | Fight censorship ! | I will not silence.OixB7.jpgDon't forget this IP: 213.251.145.96

 

Share this post


Link to post
Share on other sites
jennico

thx, but i mean it the other way round.

i want to know how to create an .icl file from several icons and not how to extract from .icl (i know this).

j. ^_^


Spoiler

I actively support Wikileaks | Freedom for Julian Assange ! | Defend freedom of speech ! | Fight censorship ! | I will not silence.OixB7.jpgDon't forget this IP: 213.251.145.96

 

Share this post


Link to post
Share on other sites
jennico

after months of searching i found something:

An .ICL file -- ICon Library, as used by icon editors

like Microangelo -- is a renamed 16-bit Windows .DLL

(an NE format executable) which typically contains

nothing but a resource section.

The ICL extension seems to be used by convention.

so, just make a resource dll and rename it to icl ???

j.


Spoiler

I actively support Wikileaks | Freedom for Julian Assange ! | Defend freedom of speech ! | Fight censorship ! | I will not silence.OixB7.jpgDon't forget this IP: 213.251.145.96

 

Share this post


Link to post
Share on other sites
ProgAndy

No. A "normal" resource-DLL is 32bits or, on x64 can be 64bt, too.

A 16bit-DLL can't be created with Win32 / Win64 API. You have to write all on your own. The format can is outlined here: Codeguru: IconLib

I propose we stay in this thread since the other is about extracting and not creating ICL-files

Edited by ProgAndy

*GERMAN* [note: you are not allowed to remove author / modified info from my UDFs]My UDFs:[_SetImageBinaryToCtrl] [_TaskDialog] [AutoItObject] [Animated GIF (GDI+)] [ClipPut for Image] [FreeImage] [GDI32 UDFs] [GDIPlus Progressbar] [Hotkey-Selector] [Multiline Inputbox] [MySQL without ODBC] [RichEdit UDFs] [SpeechAPI Example] [WinHTTP]UDFs included in AutoIt: FTP_Ex (as FTPEx), _WinAPI_SetLayeredWindowAttributes

Share this post


Link to post
Share on other sites
jennico

NE format. wow this problem is really heavy but i am on the way to get one foot on the ground. this (and your icl extractor and smashly's extractor) help a lot to understand it. but when it comes to vista, everything is different.

sigh j.


Spoiler

I actively support Wikileaks | Freedom for Julian Assange ! | Defend freedom of speech ! | Fight censorship ! | I will not silence.OixB7.jpgDon't forget this IP: 213.251.145.96

 

Share this post


Link to post
Share on other sites
jennico

@progAndy:

the number of images in an icon in NE format file is the idCount param in $tagGRPICONDIR. i can read it out with DllStructGetData ( tagGRPICONDIR, 3). ^_^ the dimensions are in $tagGRPICONDIRENTRY, element 1 and 2. i got it.

the first step is the hardest.... but now i begin to understand your icl extractor and why you have to write the data step by step.

otherwise, in PE format i have to use winapi (loadresource ...).

j.


Spoiler

I actively support Wikileaks | Freedom for Julian Assange ! | Defend freedom of speech ! | Fight censorship ! | I will not silence.OixB7.jpgDon't forget this IP: 213.251.145.96

 

Share this post


Link to post
Share on other sites
jennico

i finally figured it out and put it in the first post.

j.


Spoiler

I actively support Wikileaks | Freedom for Julian Assange ! | Defend freedom of speech ! | Fight censorship ! | I will not silence.OixB7.jpgDon't forget this IP: 213.251.145.96

 

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
Sign in to follow this  

×