English 中文(简体)
.NET Framework and Gif transparency
原标题:
  • 时间:2009-11-25 11:45:52
  •  标签:
  • .net
  • gdi+
  • wic

Before Windows 7 (and the new image codecs: WIC) I used the following (very fast but dirty) method to create a Gif encoded image with white as the transparent color:

MemoryStream target = new memoryStream(4096);
image.Save(target, imageFormat.Gif);
byte[] data = target.ToArray();

// Set transparency
// Check Graphic Control Extension signature (0x21 0xF9)
if (data[0x30D] == 0x21 && data[0x30E] == 0xF9)
   data[0x313] = 0xFF; // Set palette index 255 (=white) as transparent

This method worked because .NET used to encode Gif with a standard palette in which index 255 was the color white.

In Windows 7 however this method is not working anymore. It seems the standard palette is changed and now the index 251 is the color white. I am however not sure. Maybe the new Gif encoder is dynamically generating a palette based on the used colors?

My question: Does anybody have insight in the new Gif encoder of Windows 7 and what would be a good and fast way to make the color white transparent?

最佳回答

I have found a better way to set the color white as the transparent color for a gif encoded image. It seems to work for Gif s that are encoded by both GDI+ and WIC (Windows 7) encoders. The following code searches for the index of the color white in the Global Image Table of the Gif and uses this index to set the transparent color in the Graphic Control Extension block.

 byte[] data;

// Save image to byte array
using (MemoryStream target = new MemoryStream(4096))
{
    image.Save(target, imageFormat.Gif);
    data = target.ToArray();
}

// Find the index of the color white in the Global Color Table and set this index as the transparent color
byte packedFields = data[0x0A]; // <packed fields> of the logical screen descriptor
if ((packedFields & 80) != 0 && (packedFields & 0x07) == 0x07) // Global color table is present and has 3 bytes per color
{
    int whiteIndex = -1;
    // Start at last entry of Global Color Table (bigger chance to find white?)
    for (int index = 0x0D + (3 * 255); index > 0x0D; index -= 3)
    {
        if (data[index] == 0xFF && data[index + 1] == 0xFF && data[index + 2] == 0xFF)
        {
            whiteIndex = (int) ((index - 0xD) / 3);
            break;
        }
    }

    if (whiteIndex != -1)
    {
        // Set transparency
        // Check Graphic Control Extension signature (0x21 0xF9)
        if (data[0x30D] == 0x21 && data[0x30E] == 0xF9)
            data[0x313] = (byte)whiteIndex;
    }
}

// Now the byte array contains a Gif image with white as the transparent color
问题回答

Are you sure this is a Windows 7 issue and not a problem elsewhere with your code?

The GIF specification suggests that any index could be used for transparency. You may want to check your image to ensure that the appropriate bit enabling transparency is set on. If it isn t, then the palette index you ve selected will be ignored.





相关问题
Manually implementing high performance algorithms in .NET

As a learning experience I recently tried implementing Quicksort with 3 way partitioning in C#. Apart from needing to add an extra range check on the left/right variables before the recursive call, ...

Anyone feel like passing it forward?

I m the only developer in my company, and am getting along well as an autodidact, but I know I m missing out on the education one gets from working with and having code reviewed by more senior devs. ...

How do I compare two decimals to 10 decimal places?

I m using decimal type (.net), and I want to see if two numbers are equal. But I only want to be accurate to 10 decimal places. For example take these three numbers. I want them all to be equal. 0....

Exception practices when creating a SynchronizationContext?

I m creating an STA version of the SynchronizationContext for use in Windows Workflow 4.0. I m wondering what to do about exceptions when Post-ing callbacks. The SynchronizationContext can be used ...

Show running instance in single instance application

I am building an application with C#. I managed to turn this into a single instance application by checking if the same process is already running. Process[] pname = Process.GetProcessesByName("...

How to combine DataTrigger and EventTrigger?

NOTE I have asked the related question (with an accepted answer): How to combine DataTrigger and Trigger? I think I need to combine an EventTrigger and a DataTrigger to achieve what I m after: when ...

热门标签