Question

Quelqu'un a-t-il la formule secrète pour redimensionner les images transparentes (principalement les GIF) sans TOUTE perte de qualité - qu'en est-il ?

J'ai essayé un tas de trucs, le plus proche n'est pas assez bon.

Jetez un oeil à mon image principale:

http://www.thewallcompany.dk/test/main.gif

Et puis l'image mise à l'échelle :

http://www.thewallcompany.dk/test/ScaledImage.gif

//Internal resize for indexed colored images
void IndexedRezise(int xSize, int ySize)
{
  BitmapData sourceData;
  BitmapData targetData;

  AdjustSizes(ref xSize, ref ySize);

  scaledBitmap = new Bitmap(xSize, ySize, bitmap.PixelFormat);
  scaledBitmap.Palette = bitmap.Palette;
  sourceData = bitmap.LockBits(new Rectangle(0, 0, bitmap.Width, bitmap.Height),
    ImageLockMode.ReadOnly, bitmap.PixelFormat);
  try
  {
    targetData = scaledBitmap.LockBits(new Rectangle(0, 0, xSize, ySize),
      ImageLockMode.WriteOnly, scaledBitmap.PixelFormat);
    try
    {
      xFactor = (Double)bitmap.Width / (Double)scaledBitmap.Width;
      yFactor = (Double)bitmap.Height / (Double)scaledBitmap.Height;
      sourceStride = sourceData.Stride;
      sourceScan0 = sourceData.Scan0;
      int targetStride = targetData.Stride;
      System.IntPtr targetScan0 = targetData.Scan0;
      unsafe
      {
        byte* p = (byte*)(void*)targetScan0;
        int nOffset = targetStride - scaledBitmap.Width;
        int nWidth = scaledBitmap.Width;
        for (int y = 0; y < scaledBitmap.Height; ++y)
        {
          for (int x = 0; x < nWidth; ++x)
          {
            p[0] = GetSourceByteAt(x, y);
            ++p;
          }
          p += nOffset;
        }
      }
    }
    finally
    {
      scaledBitmap.UnlockBits(targetData);
    }
  }
  finally
  {
    bitmap.UnlockBits(sourceData);
  }
}

J'utilise le code ci-dessus pour effectuer le redimensionnement indexé.

Quelqu'un a-t-il des idées d'amélioration ?

Était-ce utile?

La solution

S'il n'est pas nécessaire de conserver le type de fichier après la mise à l'échelle, je recommanderais l'approche suivante.

using (Image src = Image.FromFile("main.gif"))
using (Bitmap dst = new Bitmap(100, 129))
using (Graphics g = Graphics.FromImage(dst))
{
   g.SmoothingMode = SmoothingMode.AntiAlias;
   g.InterpolationMode = InterpolationMode.HighQualityBicubic;
   g.DrawImage(src, 0, 0, dst.Width, dst.Height);
   dst.Save("scale.png", ImageFormat.Png);
}

Le résultat aura de très beaux bords anti-crénelés

  • image supprimée image de cabane qui avait été remplacée par une publicité

Si vous devez exporter l'image en gif, vous êtes prêt à faire un tour ;GDI+ ne fonctionne pas bien avec le gif.Voir ce billet de blog à ce sujet pour plus d'informations

Modifier: J'ai oublié de supprimer les bitmaps dans l'exemple ;c'est corrigé

Autres conseils

Il s'agit d'une fonction de redimensionnement de base que j'ai utilisée pour quelques-unes de mes applications et qui exploite GDI+.

/// <summary>
///    Resize image with GDI+ so that image is nice and clear with required size.
/// </summary>
/// <param name="SourceImage">Image to resize</param>
/// <param name="NewHeight">New height to resize to.</param>
/// <param name="NewWidth">New width to resize to.</param>
/// <returns>Image object resized to new dimensions.</returns>
/// <remarks></remarks>
public static Image ImageResize(Image SourceImage, Int32 NewHeight, Int32 NewWidth)
{
   System.Drawing.Bitmap bitmap = new System.Drawing.Bitmap(NewWidth, NewHeight, SourceImage.PixelFormat);

   if (bitmap.PixelFormat == Drawing.Imaging.PixelFormat.Format1bppIndexed | bitmap.PixelFormat == Drawing.Imaging.PixelFormat.Format4bppIndexed | bitmap.PixelFormat == Drawing.Imaging.PixelFormat.Format8bppIndexed | bitmap.PixelFormat == Drawing.Imaging.PixelFormat.Undefined | bitmap.PixelFormat == Drawing.Imaging.PixelFormat.DontCare | bitmap.PixelFormat == Drawing.Imaging.PixelFormat.Format16bppArgb1555 | bitmap.PixelFormat == Drawing.Imaging.PixelFormat.Format16bppGrayScale) 
   {
      throw new NotSupportedException("Pixel format of the image is not supported.");
   }

   System.Drawing.Graphics graphicsImage = System.Drawing.Graphics.FromImage(bitmap);

   graphicsImage.SmoothingMode = Drawing.Drawing2D.SmoothingMode.HighQuality;
   graphicsImage.InterpolationMode = Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
   graphicsImage.DrawImage(SourceImage, 0, 0, bitmap.Width, bitmap.Height);
   graphicsImage.Dispose();
   return bitmap; 
}

Je ne me souviens pas si cela fonctionnera avec les GIF, mais vous pouvez l'essayer.

Note:Je ne peux pas m'attribuer tout le mérite de cette fonction.J'ai reconstitué quelques éléments à partir d'autres échantillons en ligne et je les ai adaptés à mes besoins 8^D

Je pense que le problème est que vous effectuez un redimensionnement basé sur la ligne de balayage, ce qui entraînera des irrégularités, quelle que soit la force avec laquelle vous le modifiez.Une bonne qualité de redimensionnement d'image nécessite que vous fassiez un peu plus de travail pour déterminer la couleur moyenne des pixels pré-redimensionnés que couvre votre pixel redimensionné.

Le gars qui gère ce site Web a un article de blog qui traite de quelques algorithmes de redimensionnement d'images.Vous voulez probablement un algorithme de mise à l'échelle d'image bicubique.

Meilleur redimensionnement de l'image

Pour toute personne susceptible d'essayer d'utiliser la solution de Markus Olsson pour redimensionner dynamiquement des images et les écrire dans Response Stream.

Cela ne fonctionnera pas :

Response.ContentType = "image/png";
dst.Save( Response.OutputStream, ImageFormat.Png );

Mais cela va :

Response.ContentType = "image/png";
using (MemoryStream stream = new MemoryStream())
{
    dst.Save( stream, ImageFormat.Png );

    stream.WriteTo( Response.OutputStream );
}

Bien que PNG soit nettement meilleur que GIF, il existe parfois un cas d'utilisation nécessitant de rester au format GIF.

Avec le GIF ou le PNG 8 bits, vous devez résoudre le problème de la quantification.

La quantification vous permet de choisir les 256 couleurs (ou moins) qui préserveront et représenteront au mieux l'image, puis de reconvertir les valeurs RVB en index.Lorsque vous effectuez une opération de redimensionnement, la palette de couleurs idéale change à mesure que vous mélangez les couleurs et modifiez les équilibres.

Pour de légers redimensionnements, comme 10 à 30 %, vous pourrez peut-être conserver la palette de couleurs d'origine.

Cependant, dans la plupart des cas, vous devrez requantifier.

Les deux principaux algorithmes parmi lesquels choisir sont Octree et nQuant.Octree est très rapide et fait un très bon travail, surtout si vous pouvez superposer un algorithme de tramage intelligent.nQuant nécessite au moins 80 Mo de RAM pour effectuer un encodage (il crée un histogramme complet) et est généralement 20 à 30 fois plus lent (1 à 5 secondes par encodage sur une image moyenne).Cependant, il produit parfois une qualité d'image supérieure à celle d'Octree car il n'arrondit pas les valeurs pour maintenir des performances constantes.

Lors de la mise en œuvre du support GIF transparent et GIF animé dans le redimensionnement d'images.net projet, j'ai choisi Octree.La prise en charge de la transparence n'est pas difficile une fois que vous contrôlez la palette d'images.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top