J'ai un projet qui convertit un fichier de format d'image en un fichier d'icône. Cependant, après la conversion de l'image, la couleur de l'image change.
Voici mon code
Bitmap theBitmap = new Bitmap(theImage, new Size(width, height));
IntPtr Hicon = theBitmap.GetHicon();// Get an Hicon for myBitmap.
Icon newIcon = Icon.FromHandle(Hicon);// Create a new icon from the handle.
FileStream fs = new FileStream(@"c:\Icon\" + filename + ".ico", FileMode.OpenOrCreate);//Write Icon to File Stream
Quelqu'un sait comment résoudre ce problème?
Bitmap.GetHicon () est très bon pour créer des icônes qui fonctionnent bien sur toute version de Windows pouvant exécuter du code .NET. Y compris les anciens, Windows 98 et Windows 2000. Les systèmes d'exploitation qui ne prenaient pas encore en charge les icônes fantaisie.
Vous obtenez donc une icône avec seulement 16 couleurs, utilisant une palette précuite avec des couleurs de base. Cela tend à générer des résultats décevants, pour le dire gentiment.
Les classes Bitmap ou Icon n'ont pas d'option pour obtenir un meilleur résultat. En général, vous devrez utiliser un éditeur d'icônes pour créer de bonnes icônes. Ce qui devrait inclure plusieurs images de différentes tailles et profondeurs de couleurs afin qu'elles fonctionnent correctement avec tous les paramètres d'adaptateur vidéo et toute version de système d'exploitation. En particulier, la réduction des couleurs de 16 millions à 256 ou 16 couleurs est une opération non triviale avec de nombreuses façons de le faire, aucune d’elles n’est parfaite. Un bon éditeur d'icônes dispose des outils nécessaires pour que cela fonctionne bien.
Si vous n’avez besoin que d’icônes 32 bits, vous pouvez utiliser FreeImage http://freeimage.sourceforge.net
string icoFile = "C:\path\to\file.ico";
FreeImageBitmap fiBitmap = new FreeImageBitmap(theBitmap);
fiBitmap.Rescale(48, 48, FREE_IMAGE_FILTER.FILTER_BICUBIC);
fiBitmap.Save(icoFile);
fiBitmap.Rescale(32, 32, FREE_IMAGE_FILTER.FILTER_BICUBIC);
fiBitmap.SaveAdd(icoFile);
fiBitmap.Rescale(16, 16, FREE_IMAGE_FILTER.FILTER_BICUBIC);
fiBitmap.SaveAdd(icoFile);
Si vous souhaitez une prise en charge complète des icônes 32, 8, 4 et 1 bit, vous devez créer votre propre graveur de format ico. J'ai rencontré ce problème lors du développement de mon propre convertisseur png vers ico http://iconverticons.com
En réalité, ce n'est pas trop difficile. les spécifications de format de fichier ico dont vous aurez besoin sont les suivantes: http://msdn.Microsoft.com/en-us/library/ms997538.aspx
Vous aurez également besoin de la spécification d'en-tête Bitmap à partir d'ici, car ico est un sous-ensemble de bitmap: http://msdn.Microsoft.com/en-us/library/dd183376.aspx
Vous pouvez essayer ceci:
Bitmap theBitmap = new Bitmap(theImage, new Size(width, height));
theBitmap.Save(@"C:\Icon\" + filename + ".ico", System.Drawing.Imaging.ImageFormat.Icon);
Si vous devez générer dynamiquement des icônes (mon application a un numéro changeant), vous n'auriez pas de chance si vous deviez utiliser un éditeur de toute façon.
Ruiwei Bu (darkfall) a un github Gist montrant comment. Bien sûr, nous ne prenons pas en charge XP et cela nous a été utile.
Échantillon utilisant une classe, j'ai mis ce code dans:
Dim ico As New Icons With {.state = Iconstates.OK, .UpgradeNum = "123"}
Dim tempfile = "C:\file5.ico"
ico.GetIcon(tempfile)
Dim newicon As New Icon(tempfile)
La classe avec le code de darkfall:
Imports System.Drawing.Imaging
Imports System.IO
Public Class Icons
Property UpgradeNum As String
Property state As Iconstates
Function GetIcon(Optional OptionalSave As String = "") As Icon
Dim bmp As New Bitmap(16, 16)
Using g = Graphics.FromImage(bmp)
g.Clear(Color.Transparent)
g.SmoothingMode = Drawing2D.SmoothingMode.AntiAlias
Select Case state
Case Iconstates.OK
g.FillEllipse(Brushes.Green, 1, 1, 14, 14)
End Select
g.DrawString(UpgradeNum, New Font("Small Fonts", 6), Brushes.Aquamarine, 0, 0)
End Using
bmp.Save(OptionalSave & ".png")
Dim outputStream As New MemoryStream()
Dim size As Integer = bmp.Size.Width
If Not ConvertToIcon(bmp, outputStream, size) Then
Return Nothing
End If
If OptionalSave > "" Then
Using file = New FileStream(OptionalSave, FileMode.Create, System.IO.FileAccess.Write)
outputStream.WriteTo(file)
file.Close()
End Using
End If
outputStream.Seek(0, SeekOrigin.Begin)
Return New Icon(outputStream)
End Function
''' <summary>
''' Converts a PNG image to an icon (ico)
''' </summary>
''' <param name="inputBitmap">The input stream</param>
''' <param name="output">The output stream</param>
''' <param name="size">Needs to be a factor of 2 (16x16 px by default)</param>
''' <param name="preserveAspectRatio">Preserve the aspect ratio</param>
''' <returns>Wether or not the icon was succesfully generated</returns>
Public Shared Function ConvertToIcon(inputBitmap As Bitmap, output As Stream, Optional size As Integer = 16, Optional preserveAspectRatio As Boolean = False) As Boolean
Dim width As Single = size, height As Single = size
Dim newBitmap = New Bitmap(inputBitmap, New Size(CInt(width), CInt(height)))
If newBitmap Is Nothing Then
Return False
End If
' save the resized png into a memory stream for future use
Using memoryStream As New MemoryStream()
newBitmap.Save(memoryStream, ImageFormat.Png)
Dim iconWriter = New BinaryWriter(output)
If output Is Nothing OrElse iconWriter Is Nothing Then
Return False
End If
' 0-1 reserved, 0
iconWriter.Write(CByte(0))
iconWriter.Write(CByte(0))
' 2-3 image type, 1 = icon, 2 = cursor
iconWriter.Write(CShort(1))
' 4-5 number of images
iconWriter.Write(CShort(1))
' image entry 1
' 0 image width
iconWriter.Write(CByte(width))
' 1 image height
iconWriter.Write(CByte(height))
' 2 number of colors
iconWriter.Write(CByte(0))
' 3 reserved
iconWriter.Write(CByte(0))
' 4-5 color planes
iconWriter.Write(CShort(0))
' 6-7 bits per pixel
iconWriter.Write(CShort(32))
' 8-11 size of image data
iconWriter.Write(CInt(memoryStream.Length))
' 12-15 offset of image data
iconWriter.Write(CInt(6 + 16))
' write image data
' png data must contain the whole png data file
iconWriter.Write(memoryStream.ToArray())
iconWriter.Flush()
End Using
Return True
End Function
End Class
' https://Gist.github.com/darkfall/1656050
'=======================================================
'Service provided by Telerik (www.telerik.com)
'Conversion powered by NRefactory.
'Twitter: @telerik
'Facebook: facebook.com/telerik
'=======================================================
Il semble que .Net Framework
ne possède aucun encodeur d’icône; de sorte que vous ne pouvez PAS enregistrer un vrai fichier Icon. Le fichier enregistré est uniquement un fichier PNG.