Viewing ICON files
BlitzPlus Forums/BlitzPlus Beginners Area/Viewing ICON files
| ||
Hi. I am making an app at the moment that involves the user choosing an icon file using the RequestFile() dialog box to be used in the app. However, I want the icon they selected to be diplayed in a Canvas but the LoadImage() command doesn't work with proper ICON files. However if I open JPEG or BMP, it displays it fine so I know it's not the programming. Is there another function or work around I could use because the program really wouldn't be that good without it. I would prefer it if I didn't have to use DLLs but if I do, could you tell me what I have to do. I am a newbie in the DLL field. Thanks In Advance |
| ||
I can probably hack together a loader for you. Gimme a few hours. |
| ||
Oops, nevermind, instead of reinventing the wheel, I see you can use the FreeImage wrapper. Here: http://www.blitzcoder.com/cgi-bin/showcase/showcase_showentry.pl?id=snarty09252003024804&comments=no put all the files in the 'decls' and 'data' folder in your blitzplus 'userlibs' directory. Not sure how it deals with .ico files with multiple images... I may still finish writing my own routine cuz I'm a file format geek like that. |
| ||
That's great. However, I am making a program that involves reading & changing icons, and sometimes the icon is, an icon for an executable or DLL, like WINWORD.EXE. There isn't a winword.ico file so I need to somehow extract the icon in the resources of the executable. Any ideas Thanks Seb |
| ||
I don't know exactly which command it is but if you look at the Win API reference there is a command to get the icon from an executable. |
| ||
seb, ExtractIconA found in 'shell32.dll' checkout microsoft's msdn http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winui/winui/windowsuserinterface/resources/icons/iconreference/iconfunctions/extracticon.asp |
| ||
How would I actually implement this function into Blitz+(Ie.e. declerations in UserLibs) and how would I use this to display an image? Thanks for all you help Seb |
| ||
hi seb heres .decls put this in your blitzplus userlibs folder ; ; Blitz Basic Plus Mixed decls. ; .lib "kernel32.dll" kernel32_GetModuleHandle%(lpModuleName%):"GetModuleHandleA" .lib "user32.dll" user32_DestroyIcon%(hIcon%):"DestroyIcon" user32_DrawIcon%(hdc%,x%,y%,hIcon%):"DrawIcon" user32_GetDC%(hwnd%):"GetDC" .lib "shell32.dll" shell32_ExtractIcon%(hInst%,lpszExeFileName$,nIconIndex%):"ExtractIconA" and an example that open the icon inside the exe then draws it on the window. ; open icon in exe file. exe_icon = shell32_ExtractIcon(kernel32_GetModuleHandle(0),"test.exe",0) ; create window. window = CreateWindow("test icon example",200,200,400,300,0,11) ; get the windows device context window_hdc = user32_GetDC(QueryObject(window,1)) ; draw icon. user32_DrawIcon window_hdc,100,10,exe_icon ; wait until the user closes one of the windows Repeat If WaitEvent()=$803 Then Exit Forever ; free icon. If exe_icon > 0 Then user32_DestroyIcon exe_icon EndIf End kev |
| ||
Cheers, thanks alot. By the way, what is the window device content. Also, when you compile your program, do you have to put any DLL files packaged with it. Thanks for all your help Seb P.S: Will this work with normal icon files aswell? (*.ico) |
| ||
Hi Again, I have come accross a bit of a problem still. It draws the icon great (Thanks Kev) but I can't find a way to remove the icon off the screen. If you tell it to draw the icon again in the same place, the icon is drawn over it and you can see the previos icon underneath in the transparent parts. I tried DestroyImage but that just removes the icon from the memory but doesn't remove the icon drawn on the window. Any ideas??? Thanks Seb P.S: It works great with ICO files aswell. Thanks again, Kev. You've saved me a lot of late night hours. |
| ||
Hi Seb to remove the icon before redrawing a new one use a panel free it then recreate it. this works example below. ; open icon in exe file. exe_icon = shell32_ExtractIcon(kernel32_GetModuleHandle(0),"test.exe",0) ; create window. window = CreateWindow("test icon example",200,200,400,300,0,11) panel = CreatePanel(10,10,200,200,window) ; get the panels device context window_hdc = user32_GetDC(QueryObject(panel ,1)) exe_icon_1 = shell32_ExtractIcon(kernel32_GetModuleHandle(0),"test2.exe",0) ; draw icon. user32_DrawIcon window_hdc,100,10,exe_icon_1 MouseWait FreeGadget panel panel = CreatePanel(10,10,200,200,window) ; get the panels device context window_hdc = user32_GetDC(QueryObject(panel ,1)) ; draw icon. user32_DrawIcon window_hdc,100,10,exe_icon ; wait until the user closes one of the windows Repeat If WaitEvent()=$803 Then Exit Forever ; free icon. If exe_icon > 0 Then user32_DestroyIcon exe_icon EndIf ; free icon. If exe_icon_1 > 0 Then user32_DestroyIcon exe_icon_1 EndIf End some information on device contexts found on msdn http://msdn.microsoft.com/library/default.asp?url=/library/en-us/gdi/devcons_0g6r.asp kev |
| ||
Thanks Once Again! - Finally though, one other thing. You know the declerations file you supplied, it declares the "ExtractIconA" function whereas on the MSDN it refers to it symply as "ExtractIcon". Is there any difference between these 2 commands and if so what difference is there. Also, how do you specify a parameter as boolean in a decleration file. (Strings are specified using $, Integer with %, Floating Point with # Boolean ???) E.g. the RealDriveType function requires you to pass the drive number and also a reserved boolean value of 0. This value doesn't change. I have delcared it in the declarations file as: .lib "shell32.dll" DriveType%(DriveNumber%,0):"RealDriveType" But it doesn't work. Blitz+ won't open with this command and it comes up with an error. I tried the following, which works: .lib "shell32.dll" DriveType%(DriveNumber%,Reserved%):"RealDriveType" However, I don't know if I used the right variable type to specify a boolean value. (Are integar and boolean the same.) It just seems a bit pointless having to put a 0 every time the function is called when it's the same every time. Can it be done? Hope you understand what I mean. More information on this can be found at this MSDN link. Thanks Seb |
| ||
Well, in case it still might be useful to you, here is a blitz include that will load most icons into an image you can use all the normal blitz image functions on, however it won't extract the icons from .exe files. This routine can also load the mask information from the icon file as an image. A blitz plus example is included. ;loadICOfile.bb include ; ; for 4-bit,8-bit and 24-bit .ico files ; will load 16x16, 32x32 and 48x48 icon files ; ; ; by snarkbait snarkbait66@... ; Dim pallette256(255,2) Type icoinfo Field bCount,bWidth,bHeight,bColorCount,bReserved,wPlanes,wBitCount,dwBytesInRes,dwImageOffset End Type Global black = argb(0,0,0) Global white = argb(255,255,255) Function getICOinfo$(icon$) icofile = ReadFile(icon$) If Not icofile RuntimeError "file not found" ; icon header idReserved = ReadShort(icofile) ;should be 0 idType = ReadShort(icofile);should be 1 If idType <> 1 RuntimeError "Not a valid .ico file" idCount = ReadShort(icofile) ; number of icons in file info$ = "Icon file has " + idCount + " icons." For iconcount = 1 To idCount bWidth = ReadByte(icofile) bHeight = ReadByte(icofile) bColorCount = ReadByte(icofile) ;# entries in pallette table bReserved = ReadByte(icofile) ; should be 0 wPlanes = ReadShort(icofile) ;? wBitCount = ReadShort(icofile) ;bpp dwBytesInRes = ReadInt(icofile) ;total bytes of image including AND & XOR info dwImageOffset = ReadInt(icofile) ; offset to beginning of img data index$ = index$ + " Icon#" + iconcount + ":" + bWidth + "x" + bWidth + " - " + wBitCount + " bits per pixel :" Next CloseFile icofile info$ = info$ + index$ Return info$ End Function Function loadICOimage(icon$,icoImageNumber = 1,returnMask = False) icofile = ReadFile(icon$) If Not icofile RuntimeError "file not found" ; icon header idReserved = ReadShort(icofile) ;should be 0 idType = ReadShort(icofile);should be 1 If idType <> 1 RuntimeError "Not a valid .ico file" idCount = ReadShort(icofile) ; number of icons in file For iconcount = 1 To idCount ;Icon Dir Entry ico.icoinfo = New icoinfo ico\bCount = iconcount ico\bWidth = ReadByte(icofile) ico\bHeight = ReadByte(icofile) ico\bColorCount = ReadByte(icofile) ;# entries in pallette table ico\bReserved = ReadByte(icofile) ; should be 0 ico\wPlanes = ReadShort(icofile) ;? ico\wBitCount = ReadShort(icofile) ;bpp ico\dwBytesInRes = ReadInt(icofile) ;total bytes of image including AND & XOR info ico\dwImageOffset = ReadInt(icofile) ; offset to beginning of img data Next ; read image entries For ico.icoinfo = Each icoinfo If ico\bCount = icoImageNumber SeekFile(icofile,ico\dwImageOffset) biSize = ReadInt(icofile) biWidth = ReadInt(icofile) biHeight = ReadInt(icofile) ; x 2 biPlanes = ReadShort(icofile) biBitCount = ReadShort(icofile) biCompression = ReadInt(icofile) biSizeimage = ReadInt(icofile) ; go to bitmap info SeekFile(icofile,ico\dwImageOffset + biSize) Select biBitCount Case 4 ; 16-colour pallette ; read pallette For color_value = 0 To 15 For RGB = 0 To 2 readval = ReadByte(icofile) pallette256(color_value,RGB) = readval Next useless = ReadByte(icofile) ;reserved byte Next If Not returnMask newimage = CreateImage(biWidth,biHeight/2) SetBuffer ImageBuffer(newimage) LockBuffer For ycount = biHeight/2 To 1 Step -1 For xcount = 1 To biWidth Step 2 readval = ReadByte(icofile) leftbits = readval Shr 4 rtbits = readval And $f WritePixelFast xcount - 1,ycount - 1,argb(pallette256(leftbits,2),pallette256(leftbits,1),pallette256(leftbits,0)) WritePixelFast xcount,ycount - 1,argb(pallette256(rtbits,2),pallette256(rtbits,1),pallette256(rtbits,0)) Next Next UnlockBuffer Else SeekFile(icofile,ico\dwImageOffset + biSize + (2^biBitCount * 4) + (biWidth ^ 2/2)) newimage = CreateImage(biWidth,biHeight/2) SetBuffer ImageBuffer(newimage) LockBuffer If biWidth = 32 For ycount = biHeight/2 To 1 Step -1 For xcount = 0 To 3 readval = ReadByte(icofile) xpos = 0 For bits = 8 To 1 Step -1 readbit = (readval And (2^bits - 1)) Shr (bits - 1) If readbit WritePixelFast (xcount * 8) + xpos,ycount - 1,white Else WritePixelFast (xcount * 8) + xpos,ycount - 1,black EndIf xpos = xpos + 1 Next Next Next Else If biWidth = 16 For ycount = biHeight/2 To 1 Step -1 For xcount = 0 To 1 readval = ReadByte(icofile) xpos = 0 For bits = 8 To 1 Step -1 readbit = (readval And (2^bits - 1)) Shr (bits - 1) If readbit WritePixelFast (xcount * 8) + xpos,ycount - 1,white Else WritePixelFast (xcount * 8) + xpos,ycount - 1,black EndIf xpos = xpos + 1 Next Next skip = ReadShort(icofile) Next Else If biWidth = 48 For ycount = biHeight/2 To 1 Step -1 For xcount = 0 To 5 readval = ReadByte(icofile) xpos = 0 For bits = 8 To 1 Step -1 readbit = (readval And (2^bits - 1)) Shr (bits - 1) If readbit WritePixelFast (xcount * 8) + xpos,ycount - 1,white Else WritePixelFast (xcount * 8) + xpos,ycount - 1,black EndIf xpos = xpos + 1 Next Next skip = ReadShort(icofile) Next EndIf EndIf EndIf UnlockBuffer EndIf CloseFile icofile Return newimage Case 8 ;read pallette For color_value = 0 To 255 For RGB = 0 To 2 readval = ReadByte(icofile) pallette256(color_value,RGB) = readval Next useless = ReadByte(icofile) ;reserved byte Next ;draw image If Not returnMask newimage = CreateImage(biWidth,biHeight/2) SetBuffer ImageBuffer(newimage) LockBuffer For ycount = biHeight/2 To 1 Step -1 For xcount = 1 To biWidth readval = ReadByte(icofile) WritePixelFast xcount - 1,ycount - 1,argb(pallette256(readval,2),pallette256(readval,1),pallette256(readval,0)) Next Next UnlockBuffer ;read AND mask Else SeekFile(icofile,ico\dwImageOffset + biSize + (2^biBitCount * 4) + (biWidth ^ 2)) newimage = CreateImage(biWidth,biHeight/2) SetBuffer ImageBuffer(newimage) LockBuffer If biWidth = 32 For ycount = biHeight/2 To 1 Step -1 For xcount = 0 To 3 readval = ReadByte(icofile) xpos = 0 For bits = 8 To 1 Step -1 readbit = (readval And (2^bits - 1)) Shr (bits - 1) If readbit WritePixelFast (xcount * 8) + xpos,ycount - 1,white Else WritePixelFast (xcount * 8) + xpos,ycount - 1,black EndIf xpos = xpos + 1 Next Next Next Else If biWidth = 16 For ycount = biHeight/2 To 1 Step -1 For xcount = 0 To 1 readval = ReadByte(icofile) xpos = 0 For bits = 8 To 1 Step -1 readbit = (readval And (2^bits - 1)) Shr (bits - 1) If readbit WritePixelFast (xcount * 8) + xpos,ycount - 1,white Else WritePixelFast (xcount * 8) + xpos,ycount - 1,black EndIf xpos = xpos + 1 Next Next skip = ReadShort(icofile) Next Else If biWidth = 48 For ycount = biHeight/2 To 1 Step -1 For xcount = 0 To 5 readval = ReadByte(icofile) xpos = 0 For bits = 8 To 1 Step -1 readbit = (readval And (2^bits - 1)) Shr (bits - 1) If readbit WritePixelFast (xcount * 8) + xpos,ycount - 1,white Else WritePixelFast (xcount * 8) + xpos,ycount - 1,black EndIf xpos = xpos + 1 Next Next skip = ReadShort(icofile) Next EndIf EndIf EndIf UnlockBuffer EndIf CloseFile icofile Return newimage Case 24 If Not returnmask newimage = CreateImage(biWidth,biHeight/2) SetBuffer ImageBuffer(newimage) LockBuffer For ycount = biHeight/2 To 1 Step -1 For xcount = 1 To biWidth readblue = ReadByte(icofile) readgreen = ReadByte(icofile) readred = ReadByte(icofile) WritePixelFast xcount - 1,ycount - 1,argb(readred,readgreen,readblue) Next Next UnlockBuffer Else SeekFile(icofile,ico\dwImageOffset + biSize + (biWidth ^ 2 * 3)) newimage = CreateImage(biWidth,biHeight/2) SetBuffer ImageBuffer(newimage) LockBuffer If biWidth = 32 For ycount = biHeight/2 To 1 Step -1 For xcount = 0 To 3 readval = ReadByte(icofile) xpos = 0 For bits = 8 To 1 Step -1 readbit = (readval And (2^bits - 1)) Shr (bits - 1) If readbit WritePixelFast (xcount * 8) + xpos,ycount - 1,white Else WritePixelFast (xcount * 8) + xpos,ycount - 1,black EndIf xpos = xpos + 1 Next Next Next Else If biWidth = 16 For ycount = biHeight/2 To 1 Step -1 For xcount = 0 To 1 readval = ReadByte(icofile) xpos = 0 For bits = 8 To 1 Step -1 readbit = (readval And (2^bits - 1)) Shr (bits - 1) If readbit WritePixelFast (xcount * 8) + xpos,ycount - 1,white Else WritePixelFast (xcount * 8) + xpos,ycount - 1,black EndIf xpos = xpos + 1 Next Next skip = ReadShort(icofile) Next Else If biWidth = 48 For ycount = biHeight/2 To 1 Step -1 For xcount = 0 To 5 readval = ReadByte(icofile) xpos = 0 For bits = 8 To 1 Step -1 readbit = (readval And (2^bits - 1)) Shr (bits - 1) If readbit WritePixelFast (xcount * 8) + xpos,ycount - 1,white Else WritePixelFast (xcount * 8) + xpos,ycount - 1,black EndIf xpos = xpos + 1 Next Next skip = ReadShort(icofile) Next EndIf EndIf EndIf UnlockBuffer EndIf CloseFile icofile Return newimage End Select EndIf Next End Function Function argb(red,green,blue) Return (blue Or (green Shl 8) Or (red Shl 16) Or ($ff Shl 24)) End Function sample file (blitz plus) Include "loadicofile.bb" Global main = CreateWindow("ICO Loader",0,0,800,600,0,9) this$ = RequestFile$("Open ICO Image","ico") SetStatusText main,getICOinfo$(this$) starttime# = MilliSecs() convertedimage = loadicoimage(this$,1,False) MidHandle convertedimage ;ScaleImage convertedimage,5,5 endtime# = MilliSecs() - starttime canvas = CreateCanvas(100,100,200,200,main) canvas2 = CreateCanvas(400,100,200,200,main) SetBuffer CanvasBuffer(canvas) ClsColor 128,128,128 Cls DrawBlock convertedimage,100,100 Text 0,0,"Time to load:" + endtime + " msecs" FlipCanvas canvas imagemask = loadicoimage(this$,1,True) MidHandle imagemask ;ScaleImage imagemask,5,5 SetBuffer CanvasBuffer(canvas2) ClsColor 128,128,128 Cls DrawBlock imagemask,100,100 Text 0,0,"Time to load:" + endtime + " msecs" FlipCanvas canvas2 WaitKey() End |
| ||
Seb for example the declared function "ExtractIcon" is found within c header files. "ExtractIconA" or "ExtractIconEx" both these function calls can be found in "shell32.dll" the latter function enables extra params when making the call. in the blitz .decs we declare the function call. i dont think boolean values are supported i use ('integar' %) for them. Download ApiViewer for a good list of available api calls and what .dll these can be found in. http://www.activevb.de/rubriken/apiviewer/index-apiviewereng.html kev |
| ||
Thanks for all your help. (Kev & Snarkbait). My program is running fine. Found a bug that I managed to fix myself (shock, shock, horror, horror). When you draw the image using Kev's method onto the window, then minimize the window, when the window is restored, the icon disappears. I got around this by including the AppResume event in the program loop, which when it is triggered, redraws the image(s) on the screen. Snarkbait - I tried to follow your code through and succeeded mostly. - LOL. (I've made a Blitz Compression utility so my Bytes/Shorts/Integer stuff seems to be up to scratch). However, where did you manage to find the file structure of the ICON file. I used Wotsit's Format but it didn't have much stuff on it. Do you know of any other good websites? Thanks for all your help Seb P.S: Thanks for telling me about that ApiViewer, it will come in very handy. :-) |
| ||
I used here: http://www.awitness.org/delphi_pascal_tutorial/source2/icon_file_format.html and here: http://www.daubnet.com/formats/ICO.html Nobody had info on the 24-bit icon (i was testing with the GLET one) so I figured that one out on my own. Any part of my code you didn't get, let me know and I'll explain it... I didn't comment it enough lol. |
| ||
Seb: I put a better commented version in the code archives here: http://www.blitzbasic.com/codearcs/codearcs.php?code=1358 |
| ||
hi seb, ive uploaded this little file error.exe this returns information on errors returned by kernel32.dll GetLastError() this will help when debugging any api calls you make. http://members.aol.com/kev12340poole/error.exe kev |