Cómo guardar un archivo .gif con una nueva tabla de color utilizando GDI +

Seleccione idioma Seleccione idioma
Id. de artículo: 315780 - Ver los productos a los que se aplica este artículo
Expandir todo | Contraer todo

En esta página

Resumen

Para obtener una versión de Microsoft Visual C# .NET de este artículo, consulte 319061.
Para obtener una versión de Microsoft Visual Basic .NET de este artículo, consulte 319591.
El formato de intercambio de gráficos de CompuServe (GIF) está diseñado con un máximo de 256 colores que se organizan en una tabla de colores. Para realizar modificaciones comunes en un archivo de imagen .gif, debe cambiar una tabla de colores personalizada. Sin embargo, cuando GDI + modifica un objeto Image y luego se le pedirá que guarde la imagen con el codificador GIF, el archivo .gif resultante contiene una tabla de color de semitonos.

Para guardar una imagen con una tabla de colores personalizada utilizando el codificador GIF, debe trabajar con una copia de 256 colores de la imagen que GDI + no ha modificado.

Más información

El archivo de imagen .gif puede expresar un máximo de 256 colores. Puesto que color es un recurso escaso en el archivo .gif, la optimización de esos colores es una tarea solicitada habitualmente. Para modificar una tabla de colores optimizado, debe poder establecer cualquier tabla arbitrario color personalizado en un archivo .gif.

Después de GDI + modifica una imagen y, a continuación, escribe una imagen en un archivo utilizando el codificador GIF, GDI + escribe el archivo mediante una paleta de semitonos que bits del objeto de imagen han sido reducido de color. GDI + realiza una conversión de color de 32 bits por píxel (BPP 32) cuando escribe la imagen en el archivo porque se realizan todas las modificaciones a la imagen con el motor de gráficos 32 de GDI +.

Aunque GDI + admite la creación de imágenes y los mapas de bits de varios formatos de píxel y, por lo tanto, puede cargar una imagen .gif, el uso del motor de gráficos 32 necesita la conversión a 32 BPP cuando se modifican por GDI +. Sin embargo, una imagen o mapa de bits que es no modificado por GDI + conserva el formato de píxel original y pueden escribirse en un archivo mediante el método Guardar con el codificador adecuado. Esta propiedad constituye la base de una técnica que puede guardar una imagen en un archivo .gif con una tabla de colores personalizada.

Puede escribir un mapa de bits no modificada con el codificador GIF y mantener intacta la tabla de color del mapa de bits ; por lo tanto, se puede utilizar este método para guardar un archivo .gif con una nueva tabla de colores.

El método es copiar los datos de imagen de un objeto de imagen original a un objeto Bitmap temporal. Este mapa de bits temporal se crea como un 8 BPP indizado mapa de bits , que es el formato de píxel se utiliza para guardar un archivo .gif. La tabla de color del mapa de bits se establece mediante el método SetPalette y, a continuación, se copia la definición de imagen en el mapa de bits temporal. Después de crear el mapa de bits temporal con una definición duplicada, puede utilizar el método Save para guardarlo con el codificador GIF, que conserva la tabla de color 8 BPP.

Para escribir una imagen .gif en un archivo con una tabla de color personalizado, siga estos pasos:
  1. Crear un objeto duplicado de mapa de bits que tiene el mismo tamaño que el origen de imagen .
  2. Establezca la tabla de colores personalizada del objeto de mapa de bits en la tabla de color que desee.
  3. Utilice el método LockBits acceso de escritura a los bits de imagen de la copia.
  4. Crear una definición de imagen en la copia escribiendo los índices de color a la memoria que se obtiene de LockBits duplicar los píxeles en la imagen original.
  5. Utilice UnLockBits para liberar los bits de imagen.
  6. Utilice la copia de mapa de bits con la tabla de colores personalizada para guardar la imagen a un archivo utilizando el codificador GIF y Guardar .
  7. Liberar la copia de mapa de bits de la imagen .

Mediante el código de ejemplo

El código de ejemplo en este artículo muestra cómo utilizar Bitmap.Save para escribir un archivo .gif con una tabla de colores personalizada de tamaño arbitrario. El código no está optimizado para el rendimiento porque su propósito es sólo de demostración. Las mejores oportunidades de optimización están en el procesamiento de bucles de píxel. GetPixel es una práctica abstracción del formato de píxel, pero es realmente lenta. El código de ejemplo sería mucho más rápido si utiliza LockBits para tener acceso al formato de píxel de directamente. Para aumentar la velocidad, no utilice el método GetPixel y la abstracción de clase de color . Para mejorar el rendimiento, vuelva a escribir la conversión de escala de grises mediante matemático de entero, en lugar de punto flotante.

La función de ejemplo toma los siguientes cinco parámetros:
  • Cualquier objeto GDI + imagen .
  • Nombre de archivo para el archivo de destino.
  • Identificador de clase (CLSID) del codificador GIF.
  • El número de colores para el archivo .gif.
  • Indicador que indica si se necesita un color transparente.
Para obtener más información acerca de la función GDI + GetEncoderClsid y descargar el código de ejemplo, consulte la documentación Ayuda de MSDN en el siguiente vínculo:

SDK de la plataforma: GDI + - Image::Save (filename, clsidEncoder encoderParams)
http://msdn.microsoft.com/en-us/library/ms533843.aspx
La función primero crea un objeto Bitmap que tiene el formato de píxel de PixelFormat8BPPIndexed ya que es el objeto que se guarda para crear el archivo .gif con nColors y a continuación, se crea una paleta de colores con los colores personalizados. El archivo .gif, obtiene el tamaño y entradas específicas de su tabla de colores de ColorPalette del objeto Bitmap . El código de ejemplo crea una escala de grises para la demostración porque ese algoritmo es fácil ampliar a través de varios tamaños de tabla de color.

Para crear el archivo .gif, se debe inicializar el objeto de mapa de bits de 8 BPP con la definición de imagen que se escribirán en el archivo. En el código de ejemplo, se utiliza para un conjunto central de bucles color convierta la imagen entrante a esencialmente el espacio en blanco y negro de la color TV.

Para fines de demostración, son tener acceso a los píxeles de imagen de origen por medio del método GetPixel de un objeto de mapa de bits que es una copia de la imagen de origen. Se realiza una copia de mapa de bits porque la clase Image no implementa el método GetPixel .

Puede utilizar otras técnicas para tener acceso a los píxeles, como el acceso directo a los píxeles utilizando el método LockBits o interoperabilidad con Secciones de DIB de GDI de Windows . Cuando se utiliza la función BitBlt para copiar un mapa de bits de HDC de GDI + a un controlador de dominio de memoria GDI DIB sección, las funciones de GBitBlt utiliza las capacidades de coincidencia de color de GDI.

Después de crear la copia de mapa de bits , utilice el método Save con el CLSID GIF proporcionado para escribir el mapa de bits en el archivo de destino.

Archivos GIF con menos de 256 colores

El códec GIF en GDI + versión 1.0 codifica sólo GDI + imágenes que son 8 BPP. Se convierten todos los otros formatos de imagen antes de codificación. Este código utiliza el formato de mapa de bits de 8 BPP para escribir archivos .gif que tienen menos de 256 colores porque el códec GIF reconoce objetos Bitmap a 8 BPP que contengan menos de 256 colores por la propiedad ColorPalette.Count .

Para obtener más información acerca de formatos de píxel de códec GIF, consulte la sección "References" de este artículo.

El código en el bucle de procesamiento que copia las definiciones de píxel de la imagen en el mapa de bits de 8 BPP tiene en cuenta el tamaño de la paleta cuando el código calcula el valor de índice del píxel. El códec GIF limita el tamaño de la paleta y restringe la definición de imagen para valores de índice que son compatibles con el tamaño de paleta (es decir, la potencial GIF color tabla) y, por lo tanto, puede crear archivos .gif con menos de 256 colores.

Transparencia GIF

En el código de ejemplo, la rutina de creación de ColorPalette establece la primera entrada sea el color transparente de GIF para demostrar el uso de la característica de transparencia. Para ello, el código establece el componente alfa de la entrada de color en cero. El código de ejemplo de este artículo es sólo con fines de demostración, por lo tanto, el color de transparencia es una elección arbitraria y puede tener resultados inesperados que dependen completamente del imagen de origen.

El codificador GIF identifica el primer color de ColorPalette que tiene un valor alfa de cero como el color transparente. Esto significa que el color transparente no es necesario que la primera entrada en el ColorPalette . Puede ser cualquiera de los 256 colores posibles en la paleta, en la condición de que todas las entradas anterior contienen componentes de Alpha con valores distintos de cero. Se omiten las entradas posteriores con valores de componente alfa de cero. Las entradas de todos los que tienen componentes de alfa distinto de cero se consideran opacas.

Nota : cuando utiliza este código para sobrescribir un archivo existente, puede ver un problema con el tamaño del archivo resultante. Esto se produce por un error en GDI + versión 1.0 no trunca el archivo.

Para obtener más información sobre tamaños de archivo de imagen, consulte la sección "References" de este artículo. Aunque el artículo hace referencia existe trata el uso de la clase Bitmap del espacio de nombres System.Drawing de .NET Framework, el tema se aplica a GDI + porque System.Drawing se implementa mediante GDI +.

El GIF/LZW emisión de licencias

Microsoft ha obtenido una licencia de Unisys para utilizar el formato de archivo .gif y otras tecnologías LZW están cubiertas por propiedad Unisys EE.UU. y patentes externas en un número de productos de Microsoft. Sin embargo, esta licencia no se extiende a los desarrolladores de terceros que utilicen productos de desarrollo de Microsoft o de Kits de herramientas para desarrollar aplicaciones. Como desarrollador de terceros, deberá determinar si debe obtener una licencia de Unisys para utilizar el formato GIF o las tecnologías LZW.

Para obtener información adicional acerca de licencias LZW y GIF, haga clic en el número de artículo siguiente para verlo en Microsoft Knowledge Base:
193543INFORMACIÓN: Unisys GIF e información de licencia de tecnología LZW

Código de ejemplo

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

Acerca de código de ejemplo

Microsoft proporciona ejemplos de programación con fines ilustrativos únicamente, sin ninguna garantía tanto expresa como implícita, incluyendo, pero sin limitarse a, las garantías implícitas de comerciabilidad e idoneidad para un propósito determinado. En este artículo se supone que está familiarizado con el lenguaje de programación que se muestra y las herramientas utilizadas para crear y depurar procedimientos. Los profesionales de soporte técnico de Microsoft pueden explicarle la funcionalidad de un determinado procedimiento, pero no modificarán estos ejemplos para ofrecer mayor funcionalidad ni crearán procedimientos a necesidades específicas.
Si tiene poca experiencia en programación, desea póngase en contacto con un Microsoft Certified Partner o servicios de consultoría de Microsoft. Para obtener más información, visite estos sitios Web de Microsoft:

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

Servicios de asesoramiento de Microsoft - http://support.microsoft.com/gp/advisoryservice

Para obtener más información acerca de las opciones de soporte técnico que están disponibles y cómo ponerse en contacto con Microsoft, visite el siguiente sitio Web de Microsoft: http://support.microsoft.com/default.aspx?scid=fh;EN-US;CNTACTMS

Referencias

Para obtener información adicional sobre formatos de píxel GIF códec, haga clic en el número de artículo siguiente para verlo en Microsoft Knowledge Base:
318343INFORMACIÓN: Archivos GIF de GDI + se guardan con el formato de 8 BPP
Para obtener información adicional sobre tamaños de archivo de imagen, haga clic en el número de artículo siguiente para verlo en Microsoft Knowledge Base:
312119PRB: Forma de guardar de la clase de mapa de bits no truncar el tamaño del archivo
Aunque el artículo que se hace referencia en este vínculo trata el uso de la clase Bitmap del espacio de nombres System.Drawing de .NET Framework, el tema se aplica a GDI + porque System.Drawing se implementa mediante GDI +.

Glosario

BPP
bits por píxel - el número de bits se utiliza para representar el valor de color de cada píxel de una imagen digitalizada; se describe el diseño físico de definición de color de cada píxel en una imagen. Formatos de píxel referencia genéricamente y comunes incluyen 32 BPP, 24 BPP, 16 BPP, 8 BPP, BPP 4, 1 BPP.
8 BPP
El formato de píxel de imagen que se expresa como ocho bits dentro de un byte. El valor de byte se utiliza como un índice en una tabla de colores que contiene las color definiciones reales de rojo, verde y azul (RGB). Dado que el índice es un byte en tamaño, la tabla de colores está limitada a 256 colores.
GIF
Formato de intercambio de gráficos un formato de archivo de imagen streamable creada por CompuServe.
RGB
Rojo, verde y azul - cada normalmente expresado como un byte y lo un terna de 3 bytes de color.

Propiedades

Id. de artículo: 315780 - Última revisión: lunes, 12 de febrero de 2007 - Versión: 3.5
La información de este artículo se refiere a:
  • Microsoft GDI+ 1.0
  • Microsoft Windows XP Professional
  • the operating system: Microsoft Windows XP 64-Bit Edition
Palabras clave: 
kbmt kbdswgdi2003swept kbbitmap kbgdiplus kbhowto KB315780 KbMtes
Traducción automática
IMPORTANTE: Este artículo ha sido traducido por un software de traducción automática de Microsoft (http://support.microsoft.com/gp/mtdetails) en lugar de un traductor humano. Microsoft le ofrece artículos traducidos por un traductor humano y artículos traducidos automáticamente para que tenga acceso en su propio idioma a todos los artículos de nuestra base de conocimientos (Knowledge Base). Sin embargo, los artículos traducidos automáticamente pueden contener errores en el vocabulario, la sintaxis o la gramática, como los que un extranjero podría cometer al hablar el idioma. Microsoft no se hace responsable de cualquier imprecisión, error o daño ocasionado por una mala traducción del contenido o como consecuencia de su utilización por nuestros clientes. Microsoft suele actualizar el software de traducción frecuentemente.
Haga clic aquí para ver el artículo original (en inglés): 315780

Enviar comentarios

 

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