2009-03-23 6 views
6

D'accord, une image provenant d'une application externe arrive dans un format indexé 8 bits. J'ai besoin de cette image convertie en un format 24 bits de la même taille exacte.Conversion d'un Format8bppIndexed en Format24bppRgb en C#/GDI +

J'ai essayé de créer un nouveau bitmap de la même taille et de type Format24bppRgb, puis d'utiliser un objet Graphics pour dessiner l'image 8 bits avant de l'enregistrer en tant que Bmp. Cette approche ne fait pas erreur mais quand j'ouvre l'image résultante, l'en-tête BMP a toutes sortes de valeurs funky. La hauteur et la largeur sont énormes et, en plus, il y a des valeurs amusantes (et grandes) pour les drapeaux de compression et quelques autres. Malheureusement, mes exigences particulières sont de passer ce fichier à un pilote d'imprimante spécifique qui exige une image 24 bits avec des valeurs d'en-tête spécifiques (que j'essaye d'obtenir via GDI +).

convertir "un fichier indexé en un fichier 24-bit non-indexé? Si ce n'est pas un exemple, quel chemin dois-je commencer à écrire le mien?

-Kevin Grossnicklaus [email protected]

Répondre

0

Il semble étrange que vous créez un bitmap de la même largeur et hauteur que votre entrée, mais le BMP généré est beaucoup plus grande. Pouvez-vous poster du code?

0

Le problème est probablement la différence entre la résolution verticale et la résolution horizontale de votre image source et de votre image de sortie. Si vous chargez un bitmap indexé 8bpp avec une résolution de 72 DPI, puis créez un nouveau bitmap 24bpp (la résolution par défaut sera de 96 DPI ... au moins, il est sur mon système), puis utilisez Graphics.DrawImage pour passer au nouveau bitmap, votre image apparaîtra légèrement agrandie et rognée. Cela dit, je ne sais pas du haut de ma tête comment correctement créer créer l'objet Bitmap et/ou graphique de sortie pour mettre à l'échelle correctement lors de l'enregistrement. Je soupçonne que cela aura quelque chose à voir avec la création des images en utilisant une échelle commune comme des pouces au lieu de pixels.

11

J'ai utilisé le code ci-dessous pour "convertir" une image de 8bpp à 24bpp. Inspecter le fichier 24bpp généré avec un éditeur hexadécimal et comparer avec le fichier 8bpp ne montre aucune différence de hauteur et de largeur dans les deux fichiers. C'est-à-dire que l'image 8bpp était 1600x1200 et que l'image 24bpp avait les mêmes valeurs.

private static void ConvertTo24(string inputFileName, string outputFileName) 
    { 
     Bitmap bmpIn = (Bitmap)Bitmap.FromFile(inputFileName); 

     Bitmap converted = new Bitmap(bmpIn.Width, bmpIn.Height, PixelFormat.Format24bppRgb); 
     using (Graphics g = Graphics.FromImage(converted)) 
     { 
      // Prevent DPI conversion 
      g.PageUnit = GraphicsUnit.Pixel 
      // Draw the image 
      g.DrawImageUnscaled(bmpIn, 0, 0); 
     } 
     converted.Save(outputFileName, ImageFormat.Bmp); 
    } 

Tout le reste dans les en-têtes semble raisonnable, et les images sont identiques sur mon système. Quelles "valeurs géniales" voyez-vous?

+1

Vous pouvez inclure g.PageUnit = GraphicsUnit.Pixel pour qu'il tire pixel pour pixel plutôt que de faire la conversion DPI (qui DrawImage fait par défaut). –

+0

@Chris: Merci pour le conseil. Je vais l'ajouter. –

+0

@Jim: Je voudrais ajouter que la suggestion d'erlando pour définir la résolution est parfois nécessaire pour s'assurer que le résultat est vraiment inchangé (je frappe un tel cas aujourd'hui). –

4

Ceci est mon code de conversion. Notez la correspondance de la résolution entre l'image source et l'image résultante.

private void ConvertTo24bppPNG(Stream imageDataAsStream, out byte[] data) 
    { 
     using (Image img = Image.FromStream(imageDataAsStream)) 
     { 
      using (Bitmap bmp = new Bitmap(img.Width, img.Height, PixelFormat.Format24bppRgb)) 
      { 
       // ensure resulting image has same resolution as source image 
       // otherwise resulting image will appear scaled 
       bmp.SetResolution(img.HorizontalResolution, img.VerticalResolution); 

       using (Graphics gfx = Graphics.FromImage(bmp)) 
       { 
        gfx.DrawImage(img, 0, 0); 
       } 

       using (MemoryStream ms = new MemoryStream()) 
       { 
        bmp.Save(ms, ImageFormat.Png); 
        data = new byte[ms.Length]; 
        ms.Position = 0; 
        ms.Read(data, 0, (int) ms.Length); 
       } 
      } 
     } 
    }