Como salvar um arquivo .gif com uma nova tabela de cores usando GDI +

Traduções deste artigo Traduções deste artigo
ID do artigo: 315780 - Exibir os produtos aos quais esse artigo se aplica.
Expandir tudo | Recolher tudo

Neste artigo

Sumário

Para obter uma Microsoft Visual translation from VPE for Csharp .NET versão deste artigo, consulte 319061.
Para uma versão deste artigo do Microsoft Visual Basic. NET, consulte 319591.
GIF (CompuServe Graphics Interchange Format) destina-se com um máximo de 256 cores que são organizados em uma tabela de cores. Para fazer modificações comuns para um arquivo de imagem .gif, você deve alterar uma tabela de cores personalizado. No entanto, quando o GDI + edita um objeto de imagem e, em seguida, é solicitado a salvar a imagem com o codificador GIF, o arquivo .gif resultante contém uma tabela de cores de meio-tom.

Para salvar uma imagem com uma tabela de cores personalizado usando o codificador GIF, você deve trabalhar com uma cópia de 256 cores de imagem que GDI + não tenha modificado.

Mais Informações

O arquivo de imagem .gif pode expressar um máximo de 256 cores. Como cor é um recurso escasso no arquivo .gif, otimizar essas cores é uma tarefa comumente solicitada. Para afetar uma tabela de cores otimizado, você deve ser capaz de definir qualquer tabela arbitrário cor personalizada em um arquivo .gif.

Depois de GDI + modifica uma imagem e, em seguida, grava uma imagem em um arquivo usando o codificador GIF, GDI + grava o arquivo usando uma paleta de meio-tom para a qual bits do objeto Image foram cor reduzido. GDI + faz uma conversão de cores de 32 bits-por-pixel (32 BPP) quando ele grava a imagem para o arquivo todas as modificações para a imagem que são feitas com o mecanismo de gráficos de 32 BPP GDI +.

Embora GDI + oferece suporte à criação de imagens e Bitmaps de vários formatos de pixel e, portanto, pode carregar uma imagem .gif, o uso do mecanismo de elementos gráficos 32 BPP necessita a conversão para 32 BPP quando eles forem modificados pelo GDI +. No entanto, uma imagem ou um bitmap que é não modificado pelo GDI + mantém seu formato de pixel original e podem ser gravados em um arquivo usando o método Save com o codificador apropriado. Essa propriedade constitui a base para uma técnica que pode salvar uma imagem em um arquivo .gif com uma tabela de cores personalizado.

Você pode escrever um bitmap e não modificada com o codificador GIF e manter a tabela de cores do bitmap intactos; portanto, você pode usar esse método para salvar um arquivo .gif com uma nova tabela de cores.

O método é copiar os dados da imagem de um objeto de imagem original para um objeto bitmap temporário. Esse bitmap temporário é criado como um 8-BPP indexado bitmap , que é o formato de pixel que é usado para salvar um arquivo .gif. A tabela de cores do bitmap é definida usando o método SetPalette e, em seguida, a definição de imagem é copiada para o bitmap temporário. Depois de criar o bitmap temporário com uma definição duplicada, você pode usar o método Save para salvá-lo com o codificador GIF, que preserva a tabela de cores 8 BPP.

Para gravar uma imagem .gif em um arquivo com uma tabela de cores personalizado, execute estas etapas:
  1. Crie um objeto bitmap duplicado que é o mesmo tamanho que a fonte de imagem .
  2. Defina a tabela cor personalizada do objeto bitmap para a tabela de cores desejado.
  3. Use o método LockBits para obter acesso de gravação para os bits da imagem da cópia.
  4. Crie uma definição de imagem na cópia, escrevendo índices de cor para a memória que é obtida de LockBits que duplicar os pixels da imagem original.
  5. Use UnLockBits para liberar os bits da imagem.
  6. Use a cópia bitmap com a tabela de cores personalizado para salvar a imagem em um arquivo usando o codificador GIF e Salvar .
  7. Solte a cópia de imagem bitmap .

Usando o código de exemplo

O código de exemplo neste artigo demonstra como usar Bitmap.Save para gravar um arquivo .gif com uma tabela de cores personalizado de tamanho arbitrário. O código não está otimizado para desempenho porque sua finalidade é para demonstração somente. As melhores oportunidades de otimização estão em pixel processamento loops. GetPixel é uma abstração conveniente do formato de pixel, mas é bastante lenta. O código de exemplo seria muito mais rápido se você usou LockBits para acessar diretamente o formato de pixel. Para aumentar a velocidade, não use o método GetPixel e a abstração da classe de cor . Para melhorar o desempenho, reescreva a conversão de escala de cinza usando matemática inteiro, em vez de ponto flutuante.

A função de exemplo usa os seguintes cinco parâmetros:
  • Qualquer objeto GDI + imagem .
  • O nome de arquivo para o arquivo de destino.
  • O identificador de classe (CLSID) do codificador GIF.
  • O número de cores para o arquivo GIF.
  • Um sinalizador que indica se uma cor transparente é necessária.
Para obter mais informações sobre a função GDI + GetEncoderClsid e para baixar o código de exemplo, consulte a documentação MSDN Ajuda no seguinte link:

Platform SDK: GDI + - Image::Save (nome de arquivo, clsidEncoder, encoderParams)
http://msdn.microsoft.com/en-us/library/ms533843.aspx
A função primeiro cria um objeto bitmap que tem o formato de pixel do PixelFormat8BPPIndexed porque que é o objeto que é salvo para criar o arquivo .gif com nColors e, em seguida, é criada uma paleta de cores com cores personalizadas. O arquivo .gif obtém o tamanho e a entradas específicas para sua tabela de cores a partir ColorPalette do objeto bitmap . O código de exemplo cria uma escala de cinza para fins de demonstração porque esse algoritmo é fácil de estender por vários tamanhos de tabela de cores.

Para criar o arquivo .gif, você deve inicializar o objeto de bitmap BPP 8 com a definição de imagem que deve ser gravado no arquivo. No código de exemplo, um conjunto central de loops é usado para cor converter a imagem entrada essencialmente o espaço em preto-e-branco de cores TV.

Para fins de demonstração, os pixels de imagem de origem são acessados por meio do método GetPixel de um objeto bitmap que é uma cópia da imagem de origem. Uma cópia de bitmap é feita porque a classe Image não implementa o método GetPixel .

Você pode usar outras técnicas para acessar os pixels, como acesso direto aos pixels usando o método LockBits ou interoperabilidade com Windows GDI DIB seções . Quando você usa a função BitBlt para copiar um bitmap de um HDC GDI + para um controlador de domínio de memória de GDI DIB seção, as funções GBitBlt usa a capacidade de cor correspondente de GDI.

Depois de criar a cópia de bitmap , use o método Save com o CLSID GIF fornecido para gravar o bitmap para o arquivo de destino.

Arquivos GIF com menos de 256 cores

O codec GIF no GDI + versão 1.0 codifica somente GDI + imagens que são BPP 8. Todos os outros formatos de imagem são convertidos antes de codificação. Esse código usa o formato de bitmap BPP 8 para gravar arquivos .gif que têm menos de 256 cores porque o codec GIF reconhece 8 BPP bitmap objetos que contêm menos de 256 cores, a propriedade ColorPalette.Count .

Para obter mais informações sobre formatos de pixel do GIF codec, consulte a seção "References" deste artigo.

O código no loop processamento que copia as definições de pixel da imagem para o bitmap de 8 BPP leva em consideração o tamanho da paleta de quando o código calcula o valor de índice do pixel. O codec GIF limita o tamanho da paleta e restringe a imagem da definição do índice valores que são compatíveis com o tamanho de paleta (ou seja, o potencial GIF cor tabela) e, portanto, pode criar arquivos .gif com menos de 256 cores.

GIF transparência

No código de exemplo, a rotina de criação ColorPalette define a primeira entrada como a cor transparente GIF para demonstrar o uso do recurso de transparência. O código faz isso definindo o componente Alpha da entrada de cor como ZERO. O código de exemplo neste artigo é somente para fins de demonstração, portanto, a cor da transparência é uma opção arbitrária e pode ter resultados inesperados que dependem totalmente na fonte de imagem .

O codificador GIF identifica a primeira cor no ColorPalette que possui um valor de alfa de ZERO como cor transparente. Isso significa que a cor transparente não ter que ser a primeira entrada ColorPalette . Ele pode ser qualquer das 256 cores possíveis na paleta, no condition de todas as entradas de anterior contêm componentes Alpha com valores de zero. Todas as entradas posteriores com Alpha componente valores ZERO são ignoradas. Todas as entradas que têm de zero Alpha componentes são consideradas opacas.

Observação : quando você usa este código para substituir um arquivo existente, você poderá ver um problema com o tamanho do arquivo resultante. Isso ocorre devido a um bug no GDI + versão 1.0, que não truncar o arquivo.

Para obter mais informações sobre tamanhos de arquivo de imagem, consulte a seção "References" deste artigo. Embora o artigo mencionado não existe aborda o uso da classe bitmap no namespace System.Drawing do .NET Framework, o tópico se aplica a GDI + como System.Drawing é implementado pelo GDI +.

GIF/LZW questões de licenciamento

Microsoft obteve uma licença de Unisys para usar o formato de arquivo .gif e outras tecnologias LZW que são abordadas pela propriedade Unisys e patentes estrangeiras em um número de produtos da Microsoft. No entanto, essa licença não se estende para desenvolvedores de terceiros que usam produtos de desenvolvimento da Microsoft ou Kits de ferramentas para desenvolver aplicativos. Como um desenvolvedor de terceiros, você precisa determinar se você deve obter uma licença de Unisys para usar o formato GIF ou tecnologias LZW.

Para obter informações adicionais sobre licenças LZW e GIF, clique no número abaixo para ler o artigo na Base de dados de Conhecimento da Microsoft:
193543INFO: Unisys GIF e informações de licença de tecnologia LZW

Código de exemplo

Status SaveGIFWithNewColorTable(
  Image *pImage,
  const WCHAR* filename,
  const CLSID* clsidEncoder,
  DWORD nColors,
  BOOL fTransparent
)
{
    Status stat = GenericError;

    // GIF codec supports 256 colors maximum.
    if (nColors > 256)
        nColors = 256;
    if (nColors < 2)
        nColors = 2;

    // Make a new 8-BPP pixel indexed bitmap that is the same size as the source image.
    DWORD   dwWidth = pImage->GetWidth();
    DWORD   dwHeight = pImage->GetHeight();

    // Always use PixelFormat8BPPIndexed, because that is the color table
    // based interface to the GIF codec.
    Bitmap  bitmap(dwWidth, dwHeight, PixelFormat8BppIndexed); 

    stat = bitmap.GetLastStatus();

    if (stat != Ok)
        return stat;        // No point in continuing.

    // Allocate the new color table.
    DWORD   dwSizeColorPalette;
    dwSizeColorPalette = sizeof(ColorPalette);      // Size of core structure.
    dwSizeColorPalette += sizeof(ARGB)*(nColors-1);   // The other entries.

    // Allocate some raw space to back the ColorPalette structure pointer.
    ColorPalette *ppal = (ColorPalette *)new BYTE[dwSizeColorPalette];
    if (ppal == NULL) return OutOfMemory;

    ZeroMemory(ppal, dwSizeColorPalette);

    // Initialize a new color table with entries that are determined by
    // some optimal palette finding algorithm; for demonstration 
    // purposes, just do a grayscale. 
    if (fTransparent)
        ppal->Flags = PaletteFlagsHasAlpha;
    else
        ppal->Flags = 0; 
    ppal->Flags |= PaletteFlagsGrayScale;
    ppal->Count = nColors;
    for (UINT i = 0; i < nColors; i++)
    {
        int Alpha = 0xFF;       // Colors are opaque by default.
        int Intensity = i*0xFF/(nColors-1); // even distribution 

        // The GIF encoder makes the first entry in the palette with a
        // zero alpha the "transparent" color in the GIF.
        // For demonstration purposes, the first one is picked arbitrarily.

        if ( i == 0 && fTransparent) // Make this color index...
            Alpha = 0;          // Transparent
        
        // Create a gray scale for demonstration purposes.
        // Otherwise, use your favorite color reduction algorithm
        // and an optimum palette for that algorithm generated here.
        // For example, a color histogram, or a median cut palette.
        ppal->Entries[i] = Color::MakeARGB( Alpha, 
                                            Intensity, 
                                            Intensity, 
                                            Intensity );
    }

    // Set the palette into the new Bitmap object.
    bitmap.SetPalette(ppal);


    // Use GetPixel below to pull out the color data of Image.
    // Because GetPixel isn't defined on an Image, make a copy in a Bitmap 
    // instead. Make a new Bitmap that is the same size of the image that
    // you want to export. Otherwise, you might try to interpret the native 
    // pixel format of the image by using a LockBits call.
    // Use PixelFormat32BppARGB so that you can wrap a Graphics around it.
    Bitmap BmpCopy(dwWidth, dwHeight, PixelFormat32BppARGB); 
    stat = BmpCopy.GetLastStatus();
    if (stat == Ok)
    {
        Graphics g(&BmpCopy);

        // Transfer the Image to the Bitmap.
        stat = g.DrawImage(pImage, 0, 0, dwWidth, dwHeight);

        // g goes out of scope here and cleans up.
    }

    if (stat != Ok)
    {
        delete [] (LPBYTE) ppal;
        ppal = NULL;
        return stat;
    }

    // Lock the whole of the bitmap for writing.
    BitmapData  bitmapData;
    Rect        rect(0, 0, dwWidth, dwHeight);

    stat = bitmap.LockBits(
      &rect,
      ImageLockModeWrite,
      PixelFormat8BppIndexed,
      &bitmapData);

    if (stat == Ok)
    {
        // Write to the temporary buffer provided by LockBits.
        // Copy the pixels from the source image in this loop.
        // Because you want an index, convert RGB to the appropriate
        // palette index here.
        BYTE *pixels;
        if (bitmapData.Stride > 0)
            pixels = (BYTE*) bitmapData.Scan0;
        else
            // If the Stride is negative, Scan0 points to the last             // scanline in the buffer.
            // To normalize the loop, obtain the start of the buffer,
            // which is located (Height-1) scanlines previous.
            pixels = (BYTE*) bitmapData.Scan0 + bitmapData.Stride*(dwHeight-1);
        UINT stride = abs(bitmapData.Stride);

        // Top-down and bottom-up is not relevant to this algorithm.

        for(UINT row = 0; row < dwHeight; ++row)
        {
          for(UINT col = 0; col < dwWidth; ++col)
          {
              // Map palette indexes for a grayscale.
              // If you use some other technique to color convert,
              // put your favorite color reduction algorithm here.
              Color     pixel;
              UINT      i8BppPixel = row * stride + col;

              BmpCopy.GetPixel(col, row, &pixel);

              // Use luminance/chrominance conversion to get grayscale.
              // Basically, turn the image into black and white TV: YCrCb.
              // You do not have to to calculate Cr or Cb because you 
              // throw away the color anyway.
              // Y = Red * 0.299 + Green * 0.587 + Blue * 0.114

              // This expression is best as integer math for performance,
              // however, because GetPixel listed earlier is the slowest 
              // part of this loop, the expression is left as 
              // floating point for clarity.
              double luminance = (pixel.GetRed() * 0.299) +
                                (pixel.GetGreen() * 0.587) +
                                (pixel.GetBlue() * 0.114);

              // Gray scale is an intensity map from black to white.
              // Compute the index to the gray scale entry that  
              // approximates the luminance, and then round the index.      
              // Also, constrain the index choices by the number of colors to do
              pixels[i8BppPixel] = (BYTE)(luminance * (nColors-1)/255 +0.5);
          }
        }
    // To commit the changes, unlock the portion of the bitmap.  
        stat = bitmap.UnlockBits(&bitmapData);
    }

    // If destination work was successful, see whether the source was successful.
    if (stat == Ok) stat = BmpCopy.GetLastStatus();

    // See whether the code has been successful to this point.
    if (stat == Ok)
    {
    // Write it out to the disk.
        stat =  bitmap.Save(filename, clsidEncoder, NULL);
    }

    // Clean up after yourself.
    delete [] (LPBYTE) ppal;
    ppal = NULL;
    // BmpCopy goes away on its own when it falls out of scope.

    return stat;
}
				

Sobre o código de exemplo

Microsoft fornece exemplos de programação apenas para ilustração, sem garantia expressa ou implícita, incluindo, mas não se limitando às garantias implícitas de comercialização e/ou adequação a uma finalidade específica. Este artigo presume que você esteja familiarizado com a linguagem de programação demonstrada e as ferramentas usadas para criar e depurar procedimentos. Profissionais de suporte da Microsoft podem ajudar a explicar a funcionalidade de um determinado procedimento, mas eles não modificarão esses exemplos para fornecer funcionalidades adicionais ou construir procedimentos para atender às suas necessidades específicas.
Se você não tenha muita experiência de programação, talvez queira em contato com um Microsoft Certified Partner ou Microsoft Advisory Services. Para obter mais informações, visite da Microsoft:

Microsoft Certified Partners - https://partner.microsoft.com/global/30000104

Comunicado de Microsoft Services - http://support.microsoft.com/gp/advisoryservice

Para obter mais informações sobre as opções de suporte estão disponíveis e sobre como entrar em contato com a Microsoft, visite o seguinte site: http://support.microsoft.com/default.aspx?scid=fh;EN-US;CNTACTMS

Referências

Para obter informações adicionais sobre formatos de pixel de codec GIF, clique no número abaixo para ler o artigo na Base de dados de Conhecimento da Microsoft:
318343INFO: Arquivos GIF GDI + são salvos de usando o formato BPP 8
Para obter informações adicionais sobre tamanhos de arquivo de imagem, clique no número abaixo para ler o artigo na Base de dados de Conhecimento da Microsoft:
312119PROBLEMA: Salvar método da classe de bitmap não truncar tamanho do arquivo
Embora o artigo mencionada neste link aborda o uso da classe bitmap no namespace System.Drawing do .NET Framework, o tópico se aplica a GDI + como System.Drawing é implementado pelo GDI +.

Glossário

BPP
bits por pixel - o número de bits usados para representar o valor de cor de cada pixel em uma imagem digitalizada; descreve o layout físico da definição de cor de cada pixel em uma imagem. Formatos de pixel genericamente referenciado e comuns incluem 32 BPP, 24 BPP, 16 BPP, 8 BPP, BPP 4, 1 BPP.
BPP 8
O formato de pixel de imagem que é expresso como oito bits contidos em um byte. O valor de byte é usado como um índice em uma tabela de cores que contém as definições de cores do reais vermelho-verde-azul (RGB). Porque o índice é um byte de tamanho, a tabela de cores está limitada a 256 cores.
GIF
Elementos gráficos Interchange Format - um formato de arquivo de imagem streamable que foi criado pelo CompuServe.
RGB
Vermelho, verde e azul - cada comumente expresso como um byte e resulta em um triplo de 3 bytes de cor.

Propriedades

ID do artigo: 315780 - Última revisão: segunda-feira, 12 de fevereiro de 2007 - Revisão: 3.5
A informação contida neste artigo aplica-se a:
  • Microsoft GDI+ 1.0
  • Microsoft Windows XP Professional
  • the operating system: Microsoft Windows XP 64-Bit Edition
Palavras-chave: 
kbmt kbdswgdi2003swept kbbitmap kbgdiplus kbhowto KB315780 KbMtpt
Tradução automática
IMPORTANTE: Este artigo foi traduzido por um sistema de tradução automática (também designado por Machine Translation ou MT), não tendo sido portanto traduzido ou revisto por pessoas. A Microsoft possui artigos traduzidos por aplicações (MT) e artigos traduzidos por tradutores profissionais, com o objetivo de oferecer em português a totalidade dos artigos existentes na base de dados de suporte. No entanto, a tradução automática não é sempre perfeita, podendo conter erros de vocabulário, sintaxe ou gramática. A Microsoft não é responsável por incoerências, erros ou prejuízos ocorridos em decorrência da utilização dos artigos MT por parte dos nossos clientes. A Microsoft realiza atualizações freqüentes ao software de tradução automática (MT). Obrigado.
Clique aqui para ver a versão em Inglês deste artigo: 315780

Submeter comentários

 

Contact us for more help

Contact us for more help
Connect with Answer Desk for expert help.
Get more support from smallbusiness.support.microsoft.com