Using Palettes With Indeo® Video
This document describes how Indeo video interactive and Indeo video Release 3.2 use palettes to play back video clips. Read this document if you plan to use Indeo video to produce multimedia applications on a PC. This paper assumes that you have installed on your PC the latest Indeo video drivers and software for programming your application and producing your video and other artwork. This document is divided into three sections:
What Is a Palette? A palette is a means by which Windows 3.x, Windows 95, or Windows NT determines the colors in which to render pixels on computer monitors in 8-bit color mode. The number of colors you can view simultaneously on a computer monitor is determined by the number of bits used to describe each pixel. A graphics card in 24-bit color mode uses 24 bits to describe the color of each pixel: eight bits each for the red, green, and blue color values. With so many bits per pixel, you can view 224 or over 16.7 million colors simultaneously. A graphics card in 16-bit color mode uses at least five bits each for the red, green, and blue color values, and can display 216 or 65,536 colors at once. A graphics card in 8-bit color mode, however, can display only 28 (256) colors at once. Rather than try to encode these colors directly with so few bits per pixel, Windows uses a lookup table containing 256 entries. Each entry in the color lookup table contains a set of red, green, and blue color values that define a color. Pixels do not contain these values directly; instead, they contain indexes into the lookup table. A pixel whose value is a given index is rendered in the color described at that index in the table. These color lookup tables are called palettes. When a Windows video application runs in 8-bit color mode, the application and the operating system must share the limited number of colors available in the palette. They do so in a specific way:
For further information on palettes in Windows, see the October 1995 Microsoft Developer Network Developer Library CD, Technical Articles/Windows Articles/GDI and OpenGL Articles/The Palette Manager: How and Why.
How Does Indeo Video Use Palettes? The Indeo video driver needs a palette with which to play video in 8-bit mode. Three distinct palette modes have been defined to meet the competing needs of the operating system, the application, and the video driver:
Each of these palette modes is described below.
Default Palette Mode
In default palette mode, the Indeo video codec provides a standard palette using 236 default colors. As previously mentioned, the first and last ten palette colors are reserved for Windows. The default palette is stored internally by the codec, rather than being associated with a file, and is therefore the same for all files compressed by the same version of Indeo video. Developers have taken advantage of this consistency by using the Indeo video default palette for their applications' background graphics. The default palette for Indeo video interactive is somewhat different than the palette for Indeo video Release 3.2. It uses a few different colors, and the colors have been reordered. The new colors were chosen to improve the rendering of a broader range of images, and the order was changed to make color lookup more efficient, further improving playback performance. Figure 1 shows the default palette for Indeo video Release 3.2. NOTE: Depending on the color mode in which you are viewing this document, the colors in these figures might be dithered and could therefore appear muddy or impure. The actual palette uses pure, undithered colors. Figure 1. The Indeo Video Release 3.2 Default Palette
Figure 2 shows the default palette for Indeo video interactive. Figure 2. The Indeo Video Interactive Default Palette
Active Palette Mode
One solution is to redo your application graphics using the Indeo video default palette. If the default palette is for some reason undesirable, however, Indeo video allows you to play a video using a palette of your own design. In active palette mode, you must create a palette suitable for your application graphics and for displaying the video, and then pass the codec a handle to that palette in your program. The first and last ten entries of the active palette must contain the Windows system colors; however, the codec uses these colors as well as the middle 236 to render the video image. In active palette mode, the Indeo video codec accepts a palette provided by the application and dithers the video colors into that palette. Typically, the application sends to the codec the palette being used to display the background graphics, so that the video plays using the existing background colors without causing palette flashing. An additional benefit of active palette mode is that the video codec uses all 256 palette entries (including the twenty reserved Windows colors) to display video, sometimes resulting in improved image quality, although playback performance is slowed. Active palette mode has the following drawbacks:
Video signals divide color space using components labeled Y, U, and V. The Y component corresponds to the brightness of a given color. The U and V components correspond approximately to its hue and saturation. You can think of the universe of possible colors defined by YUV as the YUV color cube, as shown in Figure 3. Figure 3. The YUV Color Cube
Because the human eye is most sensitive to brightness, Indeo video divides the color space as finely as possible along the Y axis. However, to use limited bandwidth most efficiently, the U and V components are divided more coarsely, limiting the colors that the codec can use. It is as though the cube were cut into slices several units thick along the U and V axes: the only colors that can be rendered are those on the corners of the resulting cubes. When you provide the codec with an active palette, it converts each color into YUV coordinates and then searches for the nearest equivalent possible color. A palette entry is never used if another entry is closer in the YUV space to its nearest equivalent. For example, Figure 4 shows a portion of the U and V color space containing various colors defined in an active palette. In Figure 4, a, b, c, d and e represent palette colors. For any UV combination that maps to point X, color a is chosen because it is the nearest. Likewise, c is closest to Q, e is closest to Y, and d is closest to Z. But b is unused because other palette colors are closer to the grid points in every direction. Figure 4. Unused Colors
This affects not only colors rendered purely, but also dithered colors. If the desired VU color is in square XYZQ, the dithering algorithm will emit a mix of palette colors c, e, and d (and possibly a). b remains unused because no grid point maps to it.
Configurable Palette Mode
The configurable palette, therefore, divides the 256-entry lookup table as follows:
Figure 5 shows the Indeo video interactive configurable palette. Figure 5. The Indeo Video Interactive Configurable
Palette
How Palette Modes Are Chosen
Indeo video Release 3.2 uses the following logic to determine the required palette mode:
Using Nondefault Palettes If you have determined that the Indeo video default palette is inappropriate for your application, then you can follow the steps outlined in this section to provide the codec with your own palette, or with the configurable palette. First, however, you must obtain an optimal palette for your application (or define the 41 optimal palette colors to use with the configurable palette). Creating palettes is beyond the scope of this document. Tools such as DeBabelizer* or VidEdit* can help you create your palette; see the documentation that came with your tool for details. However, here are some tips:
After you have created a palette, here's how you can use it.
Activating a Palette SETVIDEO <alias> PALETTE HANDLE TO <palette-handle> The alias is the name you give a clip when you open it. The palette handle refers to the palette you want to use as the active palette. You can also implement active palette at a lower programming level using the DrawDibSetPalette() function call; however, you'll need to do a lot more coding. It is also possible to activate a palette without entering any MCI commands. Indeo video clips will use any palette that is forced to the foreground. A video clip normally stays in the foreground while it plays. However, if another window is forced to the foreground during playback, the clip automatically switches to the foreground window's palette. You can test this last method using Media Player:
MCITest Example The Indeo video clip in this example is called indeo.avi. Rather than using its default palette, indeo.avi is forced to use an external palette stored in another file called gray.avi. (The gray.avi file is used to supply the external palette because MCI does not support opening .PAL palette files.) gray.avi contains one video frame and a 236-color palette consisting entirely of shades of gray, making it easy to detect when its palette is active. Depending on the video content, some colors may still appear because the twenty system colors are still available. gray.avi is a Microsoft Video 1 clip included with this document. The indeo.avi file is not included; use any Indeo video Release 3.2 or interactive clip instead. NOTE: Execute the SETVIDEO command before the WINDOW command; otherwise, the external palette is not activated properly. Example 1. MCI Commands open gray.avi alias pal status pal palette handleopen indeo.avi alias movie setvideo movie palette handle to XXXX window movie state show play movie close movie close pal
Implementing Active Palette Example 2. SETVIDEO Within a C++ Program HPALETTE hpal; // palette handle wsprintf(achCommand, "setvideo clip palette handle to %d", hpal); mciSendString((LPSTR((achCommand, NULL, 0, NULL); Examples 3 and 4 are based on the MOVPLAY2 movie player sample and use source code from the Video for Windows Developer's Kit. Example 3 modifies movplay2.c to allocate a palette and activate it when playing an Indeo video clip. Example 3. Allocate and Activate an External Gray Palette // hpal is the palette that will be asserted. It is initialized // to 236 gray colors in a new function called initPalette(). // hpal is later asserted in fileOpenMovie(). HPALETTE hpal; // new global variable // initPalette - creates the desired palette for the movie clip void initPalette() // new function { LOGPALETTE *plgpl; int I; HANDLE hDC; // Allocate the logical palette. plgpl = (LOGPALETTE*) LocalAlloc(LPTR, sizeof(LOGPALETTE) + 236 * sizeof(PALETTEENTRY)); plgpl->palVersion = 0x300; plgpl->palNumEntries = 236; // set each entry to gray color values for (i = 0; i < 236; i++){ plgpl->palPalEntry[i].peRed = i + 10; plgpl->palPalEntry[i].peGreen = i + 10; plgpl->palPalEntry[i].peBlue = i + 10; plgpl->palPalEntry[i].peFlags = PC_NOCOLLAPSE; } // Create the palette object and get a handle to it. hpal = CreatePalette(plgpl); LocalFree((HLOCAL) plgpl); } ... void fileOpenMovie(HWND hWnd) { ... wsprintf((LPSTR)achCommand,"open %s alias mov style child parent %d", ofn.lpstrFile,hWnd); /* try to open the file */ if (mciSendString((LPSTR)achCommand, NULL, 0, NULL) == 0){ fMovieOpen = TRUE; //****** begin new codeinitPalette(); wsprintf(achCommand, "setvideo mov palette handle to%d", hpal); if (mciSendString((LPSTR)achCommand, NULL, 0, NULL) != 0){ MessageBox(hWnd, "Unable to set palette handle", NULL, MB_ICONEXCLAMATION|MB_OK); } //****** end new code /* we opened the file successfully, now set up to play it */ mciSendString("window mov state show", NULL, 0, NULL); ... } Rather than allocate and initialize a palette as in Example 3, Example 4 gets a handle to an external palette on Window's clipboard, which it uses as the active palette. The executable for this example is provided with this article as the file palplay.exe. You can test palplay.exe using the gray palette supplied with gray.avi. To do so:
Any Indeo video clips that are then played with palplay.exe will use the gray palette. Example 4. Activate Palette on Window's Clipboard ... void fileOpenMovie(HWND hWnd) { HPALETTE hClip_palette; // add this new variable ... wsprintf((LPSTR)achCommand,"open %s alias mov style child parent %d", ofn.lpstrFile,hWnd); /* try to open the file */ if (mciSendString((LPSTR)achCommand, NULL, 0, NULL) == 0){ fMovieOpen = TRUE; //**** begin new code // get palette from Clipboard if (OpenClipboard(hWnd)){ if (hClip_palette = GetClipboardData(CF_PALETTE)){ wsprintf((LPSTR)achCommand,"setvideo mov palette handle to %d", hClip_palette); mciSendString((LPSTR)achCommand, NULL, 0, NULL); } CloseClipboard(); } //**** end new code /* The file was opened successfully, now set up to play it. */ mciSendString("window mov state show", NULL, 0, NULL); ... To play a video clip in configurable palette mode:
Examples 5 and 6 load a palette from a Windows-format palette file-a logical palette-and then set up the bitmap information header as required by the Indeo video codec. Example 5. Loading a Palette from a File BOOL LoadPalette(HWND hwnd, LOGPALETTE* pLogPal) { HMMIO hmmio; /* file handle for open file */ MMCKINFO mmckinfoParent; /* parent chunk information */ MMCKINFO mmckinfoSubchunk; /* subchunk information structure */ DWORD dwDataSize; /* size of "data" chunk */ OPENFILENAME ofn = {0}; char szFileName[_MAX_PATH] = ""; char szFilter[128] = "Palette Files\0*.pal\0\0"; /* Set up Common Dialog structure. */ ofn.lStructSize = sizeof(OPENFILENAME); ofn.hwndOwner = NULL; ofn.lpstrTitle = "Select Palette File"; ofn.lpstrFilter = szFilter; ofn.lpstrFile = szFileName; ofn.nMaxFile = sizeof(szFileName); ofn.Flags = OFN_PATHMUSTEXIST | OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT; /* Prompt the user. */ if( !GetOpenFileName( &ofn ) ) { return FALSE; } /* Open the file for reading. */ if(!(hmmio = mmioOpen(szFileName,NULL, MMIO_READ))) { return FALSE; } /* Locate a "RIFF" chunk with a "PAL " form type to make * sure the file is a palette file. */ mmckinfoParent.fccType = mmioFOURCC('P', 'A', 'L', ''); if (mmioDescend(hmmio, (LPMMCKINFO) &mmckinfoParent, NULL, MMIO_FINDRIFF)) { mmioClose(hmmio, 0); return FALSE; } /* Find the data subchunk. */ if (mmioDescend(hmmio, &mmckinfoSubchunk, &mmckinfoParent, MMIO_FINDCHUNK)) { mmioClose(hmmio, 0); return FALSE; } /* Get the size of the data subchunk. */ dwDataSize = mmckinfoSubchunk.cksize; if (dwDataSize == 0L) { mmioClose(hmmio, 0); return FALSE; } /* Read the palette data subchunk. */ if((DWORD)mmioRead(hmmio, (HPSTR) pLogPal, dwDataSize) != dwDataSize) { mmioClose(hmmio, 0); return FALSE; } mmioClose(hmmio, 0); return TRUE; } The Indeo video codec, however, requires palette information in a different format than Windows does. If you use the Installable Compression Manager to give the codec access to a palette, you need to set up the bitmap information header appropriately, as illustrated in Example 6. NOTE: The following example assumes that the Windows system colors have already been loaded into the bitmap information header. Example 6. Using ICM to Provide the Codec With Access to a Palette HIC gHic; /* Handle to an open codec */ BITMAPINFOHEADER gpbiDst; /* Destination header */ BOOL SetPalette( LOGPALETTE* pLogPal ) { PALETTEENTRY* ppe; RGBQUAD* pquad; long rval; int iNumEntries, i; if(pLogPal == NULL) { return FALSE; } ppe = pLogPal->palPalEntry; pquad = (RGBQUAD *) (((char *)pbiDst) + sizeof (BITMAPINFOHEADER)); /* * For active palette use only the first 236 entries of the * given palette */ iNumEntries = (pLogPal->palNumEntries > 236) ? 236 : pLogPal->palNumEntries; /* Copy the new palette info to the bitmap */ for( i=0; i < iNumEntries; i++ ) { pquad[i+10].rgbRed = ppe[i].peRed; pquad[i+10].rgbGreen = ppe[i].peGreen; pquad[i+10].rgbBlue = ppe[i].peBlue; } /*The offset of 10 ensures the first ten system colors won't be overwritten. */ gpbiDst->biClrUsed = 256; /* Inform the codec of the new palette. */ rval = ICDecompressSetPalette (gHic, pbiDst); /* ICM call passes address of bitmapinfoheader. */ return (rval == 0); } For further help using palettes with Indeo video, and to obtain the latest software updates and technical information, contact the customer support group for Indeo video development. |
* Legal Stuff © 1997 Intel Corporation