how to save ico file?

Just starting out? Need help? Post your questions and find answers here.
AZJIO
Addict
Addict
Posts: 2140
Joined: Sun May 14, 2017 1:48 am

how to save ico file?

Post by AZJIO »

wiki
solution by @srod
solution by @idle

Code: Select all

EnableExplicit

UsePNGImageEncoder()

#Image = 0
Global tmp$
Global XXX = 16
Global YYY = 16

Procedure SaveICO(Path$)
	Protected *Buffer
	#File = 0
	If CreateFile(#File, Path$)
		WriteUnicodeCharacter(#File, 0)
		WriteUnicodeCharacter(#File, 1)
		WriteUnicodeCharacter(#File, 1)
		WriteByte(#File , XXX)
		WriteByte(#File , YYY)
		WriteByte(#File , 0)
		WriteByte(#File , 0)
		WriteUnicodeCharacter(#File, 0)
		WriteUnicodeCharacter(#File, 32)
		WriteLong(#File, XXX * YYY)
		WriteLong(#File, 16)
		*Buffer = EncodeImage(#Image, #PB_ImagePlugin_PNG, 10, 32)
		WriteData(#File, *Buffer, MemorySize(*Buffer))
		CloseFile(#File)
	EndIf
EndProcedure


tmp$ = SaveFileRequester("Select file to save", GetCurrentDirectory(), "*.ico|*.ico", 0)
If Asc(tmp$)
	If CreateImage(#Image, XXX, YYY, 32)
		If StartDrawing(ImageOutput(#Image))
			Box(0, 0, XXX, YYY, $00FF00) ; Green
			StopDrawing()
			If Right(tmp$, 4) <> ".ico"
				tmp$ + ".ico"
			EndIf
			SaveICO(tmp$)
		EndIf
	EndIf
EndIf
Edit: solution added by @idle. See the link at the beginning of the post
Last edited by AZJIO on Sat Jan 18, 2025 11:22 am, edited 4 times in total.
User avatar
HeX0R
Addict
Addict
Posts: 1187
Joined: Mon Sep 20, 2004 7:12 am
Location: Hell

Re: how to save ico file?

Post by HeX0R »

You seem to have serious problems understanding the board structure here.
Some of your applications are in General Discussion, why? (=> "Applications - Feedback and Discussion"?)
Some of your codes are in General Discussion, why? (=> "Tricks 'n' Tips"?)
Now you are adding a thread to coding questions, but answering it yourself in the first post? (=> "Tricks 'n' Tips"?)

Don't get me wrong, some of your provided stuff is pretty cool, but in the end no one will find it, because most of them are just misplaced.
AZJIO
Addict
Addict
Posts: 2140
Joined: Sun May 14, 2017 1:48 am

Re: how to save ico file?

Post by AZJIO »

Now you are adding a thread to coding questions, but answering it yourself in the first post?
I think you can guess. I post a question that I previously tested in my program for an hour, or maybe more, using different methods. I understand that I can’t do it and the search doesn’t give results, so I ask a question. But at the same time, why do you think that I should stop? I change the search methods, use the Google query "ico site:purebasic.fr/english" and look through 5 pages of results and finally I found the function. Of course, I try to save you from useless work by posting useful results. This function had just worked for me and I wanted to post the code using this function, but something broke again. Initially, I changed 24 to 32 and the function began to work. And now I'm reviewing the code in which I changed almost nothing and trying to understand why it doesn't work.

The function uses an icon descriptor, and I give it an image descriptor. So I haven't gotten the perfect answer yet and am tweaking the image to make it look like an icon handle.
Some of your applications are in General Discussion, why? (=> "Applications - Feedback and Discussion"?)
Some of your codes are in General Discussion, why? (=> "Tricks 'n' Tips"?)
What year is the message from? Previously, I posted it in the discussion section, but I was advised to post it in the applications section, since I am giving a ready-made application. On the other hand, the source code is not posted in the applications section, but only the executable file. In this case, my source code is more suitable for the “Tricks 'n' Tips” section. Attention, question, if you have a logic for where to put it, then just express it, but don’t make me guess your thoughts, I acted based on my understanding.

By the way, the "Tricks 'n' Tips" section is a bit of an unusual name to put the functionality in the section, perhaps this is a translation problem into Russian.

This code does not allow you to create an icon from an image

Code: Select all

If Not GetIconInfo_(hIcon, iconinfo)
	Debug 1
	ProcedureReturn 0
EndIf ; Not a valid icon handle.
infratec
Always Here
Always Here
Posts: 7575
Joined: Sun Sep 07, 2008 12:45 pm
Location: Germany

Re: how to save ico file?

Post by infratec »

But your code is wrong und buggy.

The offset is not 16, it is $16
Your size of the data is wrong.
You allocate memory but don't free it.
You use a fixed number as file but you can not be sure that an ohter code use already the same.

A corrected version:

Code: Select all

; https://www.purebasic.fr/english/viewtopic.php?t=82936
; https://en.wikipedia.org/wiki/ICO_(file_format)

EnableExplicit

UsePNGImageEncoder()




Procedure.i SaveICO(Filename$, Image.i)
  
  Protected Result.i, File.i, *Buffer
  
  
  If IsImage(Image)
    File = CreateFile(#PB_Any, Filename$)
    If File
      ; Header
      WriteUnicodeCharacter(File, 0)  ; Reserved. Must always be 0.
      WriteUnicodeCharacter(File, 1)  ; Specifies image type: 1 for icon (.ICO) image, 2 for cursor (.CUR) image. Other values are invalid.
      WriteUnicodeCharacter(File, 1)  ; Specifies number of images in the file.
      
      ; Directory
      WriteByte(File , ImageWidth(Image))   ; Width
      WriteByte(File , ImageHeight(Image))  ; Height
      WriteByte(File , 0)                   ; Specifies number of colors in the color palette. Should be 0 if the image does not use a color palette.
      WriteByte(File , 0)                   ; Reserved, should be 0
      WriteUnicodeCharacter(File, 0)        ; Specifies color planes. Should be 0 or 1
      WriteUnicodeCharacter(File, 32)       ; Specifies bits per pixel.
      
      *Buffer = EncodeImage(Image, #PB_ImagePlugin_PNG, 9, 32)
      If *Buffer
        
        WriteLong(File, MemorySize(*Buffer))      ; Size of the bitmap data in bytes.
        WriteLong(File, Lof(File) + SizeOf(Long)) ; Offset in the file.
        
        If WriteData(File, *Buffer, MemorySize(*Buffer)) = MemorySize(*Buffer)
          Result = #True
        EndIf
        FreeMemory(*Buffer)
      EndIf
      CloseFile(File)
      If Not Result
        DeleteFile(Filename$)
      EndIf
    EndIf
  EndIf
  
  ProcedureReturn Result
  
EndProcedure



#Image = 0
Define tmp$
Define XXX.i = 16
Define YYY.i = 16

tmp$ = SaveFileRequester("Select file to save", GetCurrentDirectory(), "*.ico|*.ico", 0)
If tmp$
  If Right(tmp$, 4) <> ".ico"
    tmp$ + ".ico"
  EndIf
  
  If CreateImage(#Image, XXX, YYY, 32, #PB_Image_Transparent)
    If StartDrawing(ImageOutput(#Image))
      DrawingMode(#PB_2DDrawing_AllChannels )
      Circle(XXX / 2, YYY / 2, XXX / 3 , RGBA(0,255,0,255))
      StopDrawing()
      
      SaveICO(tmp$, #Image)
    EndIf
  EndIf
EndIf
User avatar
Mijikai
Addict
Addict
Posts: 1517
Joined: Sun Sep 11, 2016 2:17 pm

Re: how to save ico file?

Post by Mijikai »

I would suggest to use structs.
Some old code with structs but limited functionality: http://forums.purebasic.com/german/view ... 2d#p350902
User avatar
HeX0R
Addict
Addict
Posts: 1187
Joined: Mon Sep 20, 2004 7:12 am
Location: Hell

Re: how to save ico file?

Post by HeX0R »

AZJIO wrote: Sat Nov 25, 2023 1:33 am Attention, question, if you have a logic for where to put it, then just express it, but don’t make me guess your thoughts, I acted based on my understanding.
Guess my thoughts?
I think I made pretty clear where all those threads should go to from my point of view (did you see those remarks in parentheses?)
Anyway, I don't care, I'm not a moderator, it was advice, nothing more.
Take it or leave it!

And a rhetorical question from my side, if you don't mind:
If everyone but you seems to know exactly where to place their topics, who has to "express" himself then?
AZJIO
Addict
Addict
Posts: 2140
Joined: Sun May 14, 2017 1:48 am

Re: how to save ico file?

Post by AZJIO »

HeX0R
Can make a separate topic for communication where to place the code?
User avatar
idle
Always Here
Always Here
Posts: 5834
Joined: Fri Sep 21, 2007 5:52 am
Location: New Zealand

Re: how to save ico file?

Post by idle »

make an png ico pack with sizes 16 to 256

Code: Select all

;make a ico pack out of a image image should be square 32 bit depth 

EnableExplicit 

Structure ICONDIR
  res.u
  type.u
  num.u
EndStructure

Structure ICONDIRECTORYENTRY
  width.a
  height.a
  numcolors.a 
  res.a
  colorplanes.u 
  bitsperpixel.u 
  size.l 
  offset.l  
EndStructure 

Structure ICONData
  header.ICONDIR 
  icons.ICONDIRECTORYENTRY[5] 
EndStructure 

Structure bufs
  *buffer[5] 
EndStructure   

UsePNGImageEncoder()
UsePNGImageDecoder()

Procedure CreateIconFile(file.s,image) 
  
  Protected ico.ICONData 
  Protected sz = 16  
  Protected buf.bufs 
  Protected timg,fn, offset,a,b 
  
  offset = SizeOf(ICONData)   
  ico\header\num=5 
  ico\header\type=1 
  offset = SizeOf(ICONData)   
  
  If file <> ""  
    fn = CreateFile(#PB_Any,file)
    If fn 
      Repeat    
        timg = CopyImage(image,#PB_Any) 
        If timg 
          If ResizeImage(timg,sz,sz,#PB_Image_Smooth) 
            buf\buffer[a] = EncodeImage(timg, #PB_ImagePlugin_PNG, 0, 32)
          EndIf 
        Else 
          For b = 0 To a
            If buf\buffer[a]
              FreeMemory(buf\buffer[a])
            EndIf   
          Next 
          CloseFile(fn)
          ProcedureReturn 0
        EndIf
        FreeImage(timg) 
        ico\icons[a]\width = sz 
        ico\icons[a]\height = sz 
        ico\icons[a]\colorplanes = 1 
        ico\icons[a]\bitsperpixel = 32
        ico\icons[a]\size = MemorySize(buf\buffer[a]) 
        ico\icons[a]\offset = offset 
        offset + ico\icons[a]\size     
        a+1 
        sz << 1 
      Until a = 5
      a=0 
      WriteData(fn,@ico,SizeOf(ICONData))   
      Repeat 
        WriteData(fn,Buf\buffer[a],ico\icons[a]\size) 
        FreeMemory(Buf\buffer[a])
        a+1
      Until a = 5
      CloseFile(fn) 
    EndIf  
    ProcedureReturn 1 
  EndIf 
  
EndProcedure 

Global image,file$ 

image = CreateImage(#PB_Any,512,512,32) 
StartDrawing(ImageOutput(image)) 
DrawingMode(#PB_2DDrawing_AllChannels )
Circle(512 / 2, 512 / 2, 512 / 3 , RGBA(0,255,0,255))
StopDrawing()

file$ = "e:\test.ico" 

CreateIconFile(file$,image) 


User avatar
Kuron
Addict
Addict
Posts: 1626
Joined: Sat Oct 17, 2009 10:51 pm
Location: Pacific Northwest

Re: how to save ico file?

Post by Kuron »

The criticism could have been handled better, or privately. He is not as bad as others who spam multiple forums with advertisements for their products.

He is a user who is very enthusiastic about PB, is willing to share what he learns, is willing to learn in general and has released some really nice little programs. He is not somebody who needs to be jumped on.

If you do NOT like somebody's posts, the forum has a wonderful ignore feature, put the person on your "foe" list and you will never see their posts again.

Keep in mind much gets lost in translation. RELAX! We are supposed to be on the same team here.
Best wishes to the PB community. Thank you for the memories. ♥️
User avatar
idle
Always Here
Always Here
Posts: 5834
Joined: Fri Sep 21, 2007 5:52 am
Location: New Zealand

Re: how to save ico file?

Post by idle »

I agree Kuron but this isn't the place to discuss it. So I will answer the question which nobody has actually done it yet.

And here's is a partial solution to create a png icon pack from a square image.

Code: Select all

;make a ico pack out of a image image should be square 32 bit depth 

EnableExplicit 

Structure ICONDIR
  res.u
  type.u
  num.u
EndStructure

Structure ICONDIRECTORYENTRY
  width.a
  height.a
  numcolors.a 
  res.a
  colorplanes.u 
  bitsperpixel.u 
  size.l 
  offset.l  
EndStructure 

Structure ICONData
  header.ICONDIR 
  icons.ICONDIRECTORYENTRY[5] 
EndStructure 

Structure bufs
  *buffer[5] 
EndStructure   

UsePNGImageEncoder()
UsePNGImageDecoder()

Procedure CreateIconFile(file.s,image) 
  
  Protected ico.ICONData 
  Protected sz = 16  
  Protected buf.bufs 
  Protected timg,fn, offset,a,b 
  
  offset = SizeOf(ICONData)   
  ico\header\num=5 
  ico\header\type=1 
  offset = SizeOf(ICONData)   
  
  If file <> ""  
    fn = CreateFile(#PB_Any,file)
    If fn 
      Repeat    
        timg = CopyImage(image,#PB_Any) 
        If timg 
          If ResizeImage(timg,sz,sz,#PB_Image_Smooth) 
            buf\buffer[a] = EncodeImage(timg, #PB_ImagePlugin_PNG, 0, 32)
          EndIf 
        Else 
          For b = 0 To a
            If buf\buffer[a]
              FreeMemory(buf\buffer[a])
            EndIf   
          Next 
          CloseFile(fn)
          ProcedureReturn 0
        EndIf
        FreeImage(timg) 
        ico\icons[a]\width = sz 
        ico\icons[a]\height = sz 
        ico\icons[a]\colorplanes = 1 
        ico\icons[a]\bitsperpixel = 32
        ico\icons[a]\size = MemorySize(buf\buffer[a]) 
        ico\icons[a]\offset = offset 
        offset + ico\icons[a]\size     
        a+1 
        sz << 1 
      Until a = 5
      a=0 
      WriteData(fn,@ico,SizeOf(ICONData))   
      Repeat 
        WriteData(fn,Buf\buffer[a],ico\icons[a]\size) 
        FreeMemory(Buf\buffer[a])
        a+1
      Until a = 5
      CloseFile(fn) 
    EndIf  
    ProcedureReturn 1 
  EndIf 
  
EndProcedure 

Global image,file$ 

image = CreateImage(#PB_Any,512,512,32) 
StartDrawing(ImageOutput(image)) 
DrawingMode(#PB_2DDrawing_AllChannels )
Circle(512 / 2, 512 / 2, 512 / 3 , RGBA(0,255,0,255))
StopDrawing()

file$ = "d:\test.ico" 

CreateIconFile(file$,image) 

Denis
Enthusiast
Enthusiast
Posts: 778
Joined: Fri Apr 25, 2003 5:10 pm
Location: Doubs - France

Re: how to save ico file?

Post by Denis »

Normally, icons with a size< 256/256 should not be compressed (Microsoft's compressed icon format is png).
see here

https://www.axialis.com/tutorials/windo ... s.html#t2

If I remember what I did with my PureIconManager utility, to recreate an icon by decompressing it, you need to extract the image and create the image mask, recalculate the sizes and modify the size and offset in the header.

I tested a lot of decompressed icons with different software (Axialis etc.) but for each software the mask was different during decompression, so I thought about and adopted a way of creating the mask.
A+
Denis
Post Reply