web-dev-qa-db-fra.com

Convertir l'image en icône en c #

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

enter image description here

Quelqu'un sait comment résoudre ce problème?

13
r.vengadesh

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.

8
Hans Passant

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

5
Mathew Eis

Vous pouvez essayer ceci:

Bitmap theBitmap = new Bitmap(theImage, new Size(width, height));

theBitmap.Save(@"C:\Icon\" + filename + ".ico", System.Drawing.Imaging.ImageFormat.Icon);
1
Andy

Résolu pour Vista et supérieur

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
'=======================================================
0
FastAl

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.

0
Gholamalih