Como guardar um ficheiro .gif com uma nova tabela de cores utilizando GDI +

Traduções de Artigos Traduções de Artigos
Artigo: 315780 - Ver produtos para os quais este artigo se aplica.
Expandir tudo | Reduzir tudo

Nesta página

Sumário

Para obter uma Microsoft Visual C# .NET versão deste artigo, consulte 319061.
Para obter uma Microsoft Visual Basic .NET versão deste artigo, consulte 319591.
A CompuServe formato GIF (Graphics Interchange) destina-se com um máximo de 256 cores são dispostas numa tabela de cores. Para efectuar modificações comuns para um ficheiro de imagem .gif, tem de alterar uma tabela de cores personalizado. No entanto, quando o GDI + edita um objecto de imagem e, em seguida, é solicitado para guardar a imagem com o codificador GIF, o ficheiro .gif resultante contém uma tabela de cores de meio-tom.

Para guardar uma imagem com uma tabela de cores personalizado utilizando o codificador GIF, tem de trabalhar com uma cópia de 256 cores da imagem que GDI + não foi modificado.

Mais Informação

O ficheiro de imagem .gif pode expressar um máximo de 256 cores. Porque cor é um recurso no ficheiro .gif escassa, optimizar essas cores é uma tarefa pedida frequentemente. Para afectar uma tabela de cores optimizada, tem de ser possível definir qualquer tabela de cores personalizado arbitrário num ficheiro GIF.

Depois de GDI + modifica uma imagem e, em seguida, escreve uma imagem num ficheiro utilizando o codificador GIF, GDI + escreve o ficheiro utilizando uma paleta de meios-tons ao qual bits o objecto de imagem de tem sido reduzido de cores. GDI + é uma conversão de cores de 32 bits-por-pixels (32 BPP) quando escreve a imagem o ficheiro porque todas as modificações à imagem são efectuadas com o motor de gráficos de 32-BPP GDI +.

Apesar de GDI + suporta a criação de imagens e os mapas de bits de vários formatos de pixel e, por isso, é possível carregar uma imagem .gif, a utilização do motor de gráficos 32 BPP necessita a conversão para 32 BPP quando estes forem modificados por GDI +. No entanto, uma imagem ou um mapa de bits que é não modificados por GDI + mantém o formato de pixel original e pode ser escrito num ficheiro utilizando o método Guardar com o codificador adequado. Esta propriedade é a base para uma técnica que pode guardar uma imagem de um ficheiro .gif com uma tabela de cores personalizado.

Pode escrever um mapa de bits não tendo sido modificados com o codificador GIF e manter a tabela de cores do mapa de bits intactos; assim, pode utilizar este método para guardar um ficheiro .gif com uma nova tabela de cores.

O método é copiar os dados de imagem de um objecto de imagem original para um objecto temporário do mapa de bits . Este mapa de bits temporário é criado como um BPP 8 indexado mapa de bits , que é o formato pixel é utilizado para guardar um ficheiro .gif. A tabela de cores do mapa de bits é definida pelo utilizando o método SetPalette e, em seguida, a definição de imagem é copiada para o mapa de bits temporário. Depois de criar o mapa de bits temporário com uma definição de duplicados, pode utilizar o método Guardar para guardar com o codificador GIF, que mantém a tabela de cores 8 BPP.

Para escrever uma imagem .gif para um ficheiro com uma tabela de cores personalizado, siga estes passos:
  1. Crie um objecto mapa de bits duplicado é o mesmo tamanho que a imagem de origem.
  2. Defina tabela do objecto de mapa de bits de cor personalizada para a tabela de cores pretendido.
  3. Utilize o método LockBits para ter acesso de escrita aos bits de imagem da cópia.
  4. Criar uma definição de imagem na cópia escrevendo índices de cor para a memória que é obtida a partir do LockBits duplicar os pixels na imagem original.
  5. Utilize UnLockBits para libertar os bits de imagem.
  6. Utilize a cópia de mapa de bits com a tabela de cores personalizado para guardar a imagem para um ficheiro utilizando o codificador GIF e Guardar .
  7. Liberte a cópia de mapa de bits da imagem .

Utilizar o código de exemplo

O código de exemplo neste artigo demonstra como utilizar Bitmap.Save para escrever um ficheiro .gif com uma tabela de cores personalizado de tamanho arbitrário. O código não está optimizado para desempenho porque é o objectivo de demonstração apenas. As oportunidades melhores para optimização estão a ser o pixel ciclos de processamento. GetPixel é uma abstracção conveniente do formato de pixels, mas é reconhecidamente lenta. O código de exemplo seria muito mais rápido se LockBits que utilizou para aceder directamente o formato de pixel. Para aumentar a velocidade, não utilize o método GetPixel e de abstracção de classe de cor . Para melhorar o desempenho, rescreva a conversão de escala de cinzentos utilizando matemático de número inteiro, em vez de vírgula flutuante.

A função de exemplo utiliza os seguintes cinco parâmetros:
  • Qualquer objecto de imagem de GDI +.
  • O nome de ficheiro para o ficheiro de destino.
  • O identificador de classe (CLSID) do codificador GIF.
  • O número de cores para o ficheiro .gif.
  • Um sinalizador que indica se é necessária uma cor transparente.
Para mais informações sobre a função GDI + GetEncoderClsid e para transferir o código de exemplo, consulte a documentação da MSDN ajuda na seguinte hiperligação:

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

Para criar o ficheiro .gif, terá de inicializar o objecto de mapa de bits BPP 8 com a definição de imagem que está a ser escrito no ficheiro. No código de exemplo, um conjunto central de ciclos é utilizado para cor converter a imagem de entrada essencialmente a preto e branca TV colorimetria.

Para fins de demonstração, os pixels de imagem de origem são acedidos por meio do método GetPixel de um objecto de mapa de bits que é uma cópia da imagem de origem. É efectuada uma cópia de mapa de bits porque a classe de imagem não implementa o método GetPixel .

Pode utilizar outras técnicas para acessar os pixels, tal como o acesso directo aos pixels utilizando o método LockBits ou interoperabilidade com Windows GDI DIB secções . Quando utilizar a função de BitBlt para copiar um mapa de bits de HDC GDI + para um controlador de domínio de memória GDI DIB secção, as funções GBitBlt utiliza as capacidades correspondentes de cor de GDI.

Depois de criar a cópia de mapa de bits , utilize o método Guardar com o CLSID GIF fornecido para escrever o mapa de bits no ficheiro de destino.

Ficheiros GIF com menos de 256 cores

O codec GIF na GDI + versão 1.0 codifica apenas GDI + imagens que são BPP 8. Todos os outros formatos de imagem são convertidos antes de codificação. Este código utiliza o formato de mapa de bits BPP 8 para escrever ficheiros .gif que têm menos de 256 cores, porque o codec GIF reconhece 8 BPP mapa de bits objectos com menos de 256 cores pela propriedade ColorPalette.Count .

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

O código do ciclo de processamento que copia definições de pixel a imagem para a 8 BPP mapa de bits tem em consideração o tamanho da paleta quando o código calcula o valor de índice de um pixel. O codec GIF limita o tamanho da paleta e restringe a definição da imagem valores de índice que são compatíveis com o tamanho de paleta (ou seja, a tabela de cores GIF potencial) e, por isso, pode criar ficheiros .gif com menos de 256 cores.

GIF transparência

No código de exemplo, a rotina de criação ColorPalette define a primeira entrada seja a cor transparente GIF para demonstram a utilização da funcionalidade de transparência. O código faz isso configurando o componente Alpha da entrada de cor para ZERO. O código de exemplo neste artigo é para fins de demonstração, por conseguinte, a cor de transparência é uma opção arbitrária e pode ter resultados inesperados que dependem totalmente a imagem de origem.

O codificador GIF identifica a primeira cor ColorPalette que tem um valor Alpha de ZERO como a cor transparente. Isto significa que a cor transparente não terá de ser a primeira entrada ColorPalette . Pode ser qualquer um dos possíveis 256 cores na paleta de cores, o desde que todas as entradas anteriores contêm componentes alfa com valores de zero. Quaisquer entradas posteriores com alfa componente valores de ZERO serão ignoradas. Todas as entradas de zero alfa componentes são consideradas opacas.

Nota : quando utilizar este código para substituir um ficheiro existente, poderá ver um problema com o tamanho do ficheiro resultante. Isto ocorre devido a um erro de GDI + versão 1.0 não truncar o ficheiro.

Para obter mais informações sobre tamanhos de ficheiro de imagem, consulte a secção "References" deste artigo. Apesar do artigo referenciado existe explica como utilizar a classe de mapa de bits no espaço de nomes System.Drawing do .NET Framework, o tópico se aplica a GDI + porque System.Drawing é implementado através da GDI +.

GIF/LZW licenciamento problema

Microsoft obteve uma licença de Unisys para utilizar o formato de ficheiro .gif e outras tecnologias LZW abrangidos pela propriedade Unisys dos Estados Unidos e patentes estrangeiras numa variedade de produtos da Microsoft. No entanto, esta licença não expande para os programadores de outros fabricantes que utilizam produtos de desenvolvimento da Microsoft ou conjuntos de ferramentas para desenvolver aplicações. Como programador de outros fabricantes, terá de determinar se tem de obter uma licença a partir do Unisys para utilizar o formato GIF ou tecnologias LZW.

Para obter informações adicionais sobre licenças LZW e GIF, clique no número de artigo existente abaixo para visualizar o artigo na base de dados de conhecimento da Microsoft:
193543INFO: Unisys GIF e informações de licença LZW Technology

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 códigos de exemplo

Microsoft fornece exemplos de programação ilustração só, sem garantia expressa ou implícita, incluindo, sem limitação, garantias implícitas de comercialização e/ou adequação a um fim específico. Este artigo pressupõe que está familiarizado com a linguagem de programação apresentada e as ferramentas utilizadas para criar e depurar procedimentos. Profissionais de suporte da Microsoft podem ajudar a explicar a funcionalidade de um determinado procedimento, mas não modificarão estes exemplos para proporcionarem funcionalidades adicionais nem criarão procedimentos adaptados às necessidades específicas.
Se dispõe de limitada experiência de programação, poderá contactar um Microsoft Certified Partner ou a serviços de aviso. Para obter mais informações, visite estes Web sites da Microsoft:

Microsoft certificado Partner - https://partner.microsoft.com/global/30000104

Serviços Microsoft aviso - http://support.microsoft.com/gp/advisoryservice

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

Referências

Para obter informações adicionais sobre formatos de pixel GIF codec, clique no número de artigo existente abaixo para visualizar o artigo na base de dados de conhecimento da Microsoft:
318343INFO: Ficheiros GDI + GIF são guardados com o formato de 8-BPP
Para obter informações adicionais sobre tamanhos de ficheiro de imagem, clique no número de artigo existente abaixo para visualizar o artigo na base de dados de conhecimento da Microsoft:
312119PROBLEMA: Guardar o método de classe de mapa de bits não truncar tamanho do ficheiro
Apesar do artigo é referenciado nesta ligação explica como utilizar a classe de mapa de bits no espaço de nomes System.Drawing do .NET Framework, o tópico se aplica a GDI + porque System.Drawing é implementado através da GDI +.

Glossário

BPP
bits por pixel - o número de bits utilizado para representar o valor de cor de cada pixel numa imagem digitalizada; descreve o esquema físico da definição de cor de cada pixel numa imagem. Formatos de pixel comuns e genericamente referenciadas incluem BPP 32, 24 BPP, 16 BPP, BPP 8, BPP 4, 1 BPP.
BPP 8
O formato de pixels de imagem é expressa em oito bits contidos um byte. O valor de byte é utilizado como um índice numa tabela de cores que contém as definições de cor (RGB) de vermelho-verde-azul reais. Uma vez que o índice é um byte de tamanho, a tabela de cores é limitada a 256 cores.
GIF
Graphics Interchange Format - formato de ficheiro streamable imagem que foi criado por CompuServe.
RGB
Vermelho, verde e azul - cada normalmente expresso como um byte e resulta numa triplo de 3 byte cor.

Propriedades

Artigo: 315780 - Última revisão: 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 Edition
  • 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 revisto ou traduzido por humanos. A Microsoft tem artigos traduzidos por aplicações (MT) e artigos traduzidos por tradutores profissionais. O objectivo é simples: oferecer em Português a totalidade dos artigos existentes na base de dados do suporte. Sabemos no entanto que a tradução automática não é sempre perfeita. Esta pode conter erros de vocabulário, sintaxe ou gramática? erros semelhantes aos que um estrangeiro realiza ao falar em Português. A Microsoft não é responsável por incoerências, erros ou estragos realizados na sequência da utilização dos artigos MT por parte dos nossos clientes. A Microsoft realiza actualizações frequentes 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