Pergunta

Alguém tem a fórmula secreta para o redimensionamento de imagens transparentes (principalmente GIFs) sem QUALQUER perda de qualidade - de modo que nunca?

Eu tentei um monte de coisas, o mais próximo que eu começar não é bom o suficiente.

Dê uma olhada na minha imagem principal:

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

E, em seguida, a escala da imagem:

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);
  }
}

Eu estou usando o código acima, para fazer o indexadas redimensionamento.

Alguém tem ideias de melhoria?

Foi útil?

Solução

Se não há nenhuma exigência em preservar o tipo de arquivo após a escala, eu recomendo a seguinte abordagem.

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);
}

O resultado será realmente bom anti-aliased bordas

  • removido imagem shack imagem que tinha sido substituído por um anúncio

Se você deve exportar a imagem em formato gif que você está em um passeio;GDI+ não jogar bem com o gif.Ver este post de blog sobre ele para obter mais informações

Editar: Eu esqueci de dispor de mapas de bits no exemplo;foi corrigido

Outras dicas

Esse é um função de redimensionamento que eu usei para alguns dos meus aplicativos que aproveita a 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; 
}

Eu não me lembro em cima da minha cabeça se ele vai trabalhar com GIFs, mas você pode experimentá-lo.

Nota:Eu não posso levar todo o crédito para esta função.Eu remendado algumas coisas juntos a partir de alguns outros exemplos on-line e fizemos o trabalho para as minhas necessidades 8^D

Eu acho que o problema é que você está fazendo uma varredura de linha de base redimensionar, que vai levar a jaggies não importa o quão duro você ajustá-lo.Boa imagem redimensionar qualidade exige que você faça mais algum trabalho para descobrir a cor média do pré-redimensionado pixels que seu redimensionada pixel cobre.

O cara que administra este site tem um post no blog que discute alguns redimensionamento de imagem algoritmos.Você provavelmente quer um bicubic imagem algoritmo de escala.

Melhor Redimensionamento De Imagem

Para alguém que poderá estar a tentar utilizar Markus Olsson solução para redimensionar dinamicamente imagens e escrevê-los para o Fluxo de Resposta.

Isso não vai funcionar:

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

Mas o que será:

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

    stream.WriteTo( Response.OutputStream );
}

Enquanto o PNG é definitivamente melhor do que o GIF, às vezes, há um caso de uso para a necessidade de permanecer no formato GIF.

Com GIF ou PNG de 8 bits, você tem que tratar o problema da quantização.

A quantização é onde você escolhe quais 256 (ou menos) cores vai preservar melhor e representar a imagem e, em seguida, vire os valores RGB de volta em índices.Quando você executar uma operação de redimensionamento, o ideal alterações da paleta de cores, como você está misturando as cores e a mudança de saldos.

Leve redimensiona, como 10% a 30%, você pode ser OK, preservando o original paleta de cores.

No entanto, na maioria dos casos você vai precisar re-quantize.

O principal dois algoritmos para escolher a partir de são Octree e nQuant.Octree é muito rápido e faz um trabalho muito bom, especialmente se você pode sobrepor um smart algoritmo de pontilhamento.nQuant requer pelo menos 80 MB de RAM para executar um encode (ele cria uma completa histograma), e normalmente é de 20-30X mais lenta (1 a 5 segundos por codificar em uma média de imagem).No entanto, às vezes produz uma qualidade de imagem superior que Octree, pois não 'round' valores para manter a consistência do desempenho.

Ao implementar GIF transparente e suporte a GIF animado no imageresizing.net projeto, eu escolhi Octree.Suporte a transparência não é difícil uma vez que você tem o controle da imagem da paleta.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top