AMVIDEO.CPP
//==========================================================================; 
// 
//  THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY 
//  KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE 
//  IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR 
//  PURPOSE. 
// 
//  Copyright (c) 1992 - 1997  Microsoft Corporation.  All Rights Reserved. 
// 
//--------------------------------------------------------------------------; 
 
// Helper functions for bitmap formats, March 1995 
 
#include <streams.h> 
#include <limits.h> 
 
// These are bit field masks for true colour devices 
 
const DWORD bits555[] = {0x007C00,0x0003E0,0x00001F}; 
const DWORD bits565[] = {0x00F800,0x0007E0,0x00001F}; 
const DWORD bits888[] = {0xFF0000,0x00FF00,0x0000FF}; 
 
// This maps bitmap subtypes into a bits per pixel value and also a name 
 
const struct { 
    const GUID *pSubtype; 
    WORD BitCount; 
    TCHAR *pName; 
} BitCountMap[] = { &MEDIASUBTYPE_RGB1,        1,   TEXT("RGB Monochrome"), 
                    &MEDIASUBTYPE_RGB4,        4,   TEXT("RGB VGA"), 
                    &MEDIASUBTYPE_RGB8,        8,   TEXT("RGB 8"), 
                    &MEDIASUBTYPE_RGB565,      16,  TEXT("RGB 565 (16 bit)"), 
                    &MEDIASUBTYPE_RGB555,      16,  TEXT("RGB 555 (16 bit)"), 
                    &MEDIASUBTYPE_RGB24,       24,  TEXT("RGB 24"), 
                    &MEDIASUBTYPE_RGB32,       32,  TEXT("RGB 32"), 
                    &MEDIASUBTYPE_Overlay,     0,   TEXT("Overlay"), 
                    &GUID_NULL,                0,   TEXT("UNKNOWN") }; 
 
 
// Return the size of the bitmap as defined by this header 
 
STDAPI_(DWORD) GetBitmapSize(const BITMAPINFOHEADER *pHeader) 
{ 
    return DIBSIZE(*pHeader); 
} 
 
 
// This is called if the header has a 16 bit colour depth and needs to work 
// out the detailed type from the bit fields (either RGB 565 or RGB 555) 
 
STDAPI_(const GUID) GetTrueColorType(const BITMAPINFOHEADER *pbmiHeader) 
{ 
    BITMAPINFO *pbmInfo = (BITMAPINFO *) pbmiHeader; 
    ASSERT(pbmiHeader->biBitCount == 16); 
 
    // If its BI_RGB then it's RGB 555 by default 
 
    if (pbmiHeader->biCompression == BI_RGB) { 
        return MEDIASUBTYPE_RGB555; 
    } 
 
    // Compare the bit fields with RGB 555 
 
    DWORD *pMask = (DWORD *) pbmInfo->bmiColors; 
    if (pMask[0] == bits555[0]) { 
        if (pMask[1] == bits555[1]) { 
            if (pMask[2] == bits555[2]) { 
                return MEDIASUBTYPE_RGB555; 
            } 
        } 
    } 
 
    // Compare the bit fields with RGB 565 
 
    pMask = (DWORD *) pbmInfo->bmiColors; 
    if (pMask[0] == bits565[0]) { 
        if (pMask[1] == bits565[1]) { 
            if (pMask[2] == bits565[2]) { 
                return MEDIASUBTYPE_RGB565; 
            } 
        } 
    } 
    return GUID_NULL; 
} 
 
 
// Given a BITMAPINFOHEADER structure this returns the GUID sub type that is 
// used to describe it in format negotiations. For example a video codec fills 
// in the format block with a VIDEOINFO structure, it also fills in the major 
// type with MEDIATYPE_VIDEO and the subtype with a GUID that matches the bit 
// count, for example if it is an eight bit image then MEDIASUBTYPE_RGB8 
 
STDAPI_(const GUID) GetBitmapSubtype(const BITMAPINFOHEADER *pbmiHeader) 
{ 
    ASSERT(pbmiHeader); 
 
    // If it's not RGB then create a GUID from the compression type 
 
    if (pbmiHeader->biCompression != BI_RGB) { 
        if (pbmiHeader->biCompression != BI_BITFIELDS) { 
            FOURCCMap FourCCMap(pbmiHeader->biCompression); 
            return (const GUID) FourCCMap; 
        } 
    } 
 
    // Map the RGB DIB bit depth to a image GUID 
 
    switch(pbmiHeader->biBitCount) { 
        case 1    :   return MEDIASUBTYPE_RGB1; 
        case 4    :   return MEDIASUBTYPE_RGB4; 
        case 8    :   return MEDIASUBTYPE_RGB8; 
        case 16   :   return GetTrueColorType(pbmiHeader); 
        case 24   :   return MEDIASUBTYPE_RGB24; 
        case 32   :   return MEDIASUBTYPE_RGB32; 
    } 
    return GUID_NULL; 
} 
 
 
// Given a video bitmap subtype we return the number of bits per pixel it uses 
// We return a WORD bit count as thats what the BITMAPINFOHEADER uses. If the 
// GUID subtype is not found in the table we return an invalid USHRT_MAX 
 
STDAPI_(WORD) GetBitCount(const GUID *pSubtype) 
{ 
    ASSERT(pSubtype); 
    const GUID *pMediaSubtype; 
    INT iPosition = 0; 
 
    // Scan the mapping list seeing if the source GUID matches any known 
    // bitmap subtypes, the list is terminated by a GUID_NULL entry 
 
    while (TRUE) { 
        pMediaSubtype = BitCountMap[iPosition].pSubtype; 
        if (IsEqualGUID(*pMediaSubtype,GUID_NULL)) { 
            return USHRT_MAX; 
        } 
        if (IsEqualGUID(*pMediaSubtype,*pSubtype)) { 
            return BitCountMap[iPosition].BitCount; 
        } 
        iPosition++; 
    } 
} 
 
 
// Given a bitmap subtype we return a description name that can be used for 
// debug purposes. In a retail build this function still returns the names 
// If the subtype isn't found in the lookup table we return string UNKNOWN 
 
STDAPI_(TCHAR *) GetSubtypeName(const GUID *pSubtype) 
{ 
    ASSERT(pSubtype); 
    const GUID *pMediaSubtype; 
    INT iPosition = 0; 
 
    // Scan the mapping list seeing if the source GUID matches any known 
    // bitmap subtypes, the list is terminated by a GUID_NULL entry 
 
    while (TRUE) { 
        pMediaSubtype = BitCountMap[iPosition].pSubtype; 
        if (IsEqualGUID(*pMediaSubtype,*pSubtype)) { 
            return BitCountMap[iPosition].pName; 
        } 
        if (IsEqualGUID(*pMediaSubtype,GUID_NULL)) { 
            return TEXT("UNKNOWN"); 
        } 
        iPosition++; 
    } 
} 
 
 
// The mechanism for describing a bitmap format is with the BITMAPINFOHEADER 
// This is really messy to deal with because it invariably has fields that 
// follow it holding bit fields, palettes and the rest. This function gives 
// the number of bytes required to hold a VIDEOINFO that represents it. This 
// count includes the prefix information (like the rcSource rectangle) the 
// BITMAPINFOHEADER field, and any other colour information on the end. 
// 
// WARNING If you want to copy a BITMAPINFOHEADER into a VIDEOINFO always make 
// sure that you use the HEADER macro because the BITMAPINFOHEADER field isn't 
// right at the start of the VIDEOINFO (there are a number of other fields), 
// 
//     CopyMemory(HEADER(pVideoInfo),pbmi,sizeof(BITMAPINFOHEADER)); 
// 
 
STDAPI_(LONG) GetBitmapFormatSize(const BITMAPINFOHEADER *pHeader) 
{ 
    // Everyone has this to start with this   
    LONG Size = SIZE_PREHEADER + pHeader->biSize; 
 
    ASSERT(pHeader->biSize >= sizeof(BITMAPINFOHEADER)); 
     
    // Does this format use a palette, if the number of colours actually used 
    // is zero then it is set to the maximum that are allowed for that colour 
    // depth (an example is 256 for eight bits). Truecolour formats may also 
    // pass a palette with them in which case the used count is non zero 
 
    // This would scare me. 
    ASSERT(pHeader->biBitCount <= iPALETTE || pHeader->biClrUsed == 0); 
 
    if (pHeader->biBitCount <= iPALETTE || pHeader->biClrUsed) { 
        LONG Entries = (DWORD) 1 << pHeader->biBitCount; 
        if (pHeader->biClrUsed) { 
            Entries = pHeader->biClrUsed; 
        } 
        Size += Entries * sizeof(RGBQUAD); 
    } 
 
    // Truecolour formats may have a BI_BITFIELDS specifier for compression 
    // type which means that room for three DWORDs should be allocated that 
    // specify where in each pixel the RGB colour components may be found 
 
    if (pHeader->biCompression == BI_BITFIELDS) { 
        Size += SIZE_MASKS; 
    } 
 
    // A BITMAPINFO for a palettised image may also contain a palette map that 
    // provides the information to map from a source palette to a destination 
    // palette during a BitBlt for example, because this information is only 
    // ever processed during drawing you don't normally store the palette map 
    // nor have any way of knowing if it is present in the data structure 
 
    return Size; 
} 
 
 
// Returns TRUE if the VIDEOINFO contains a palette 
 
STDAPI_(BOOL) ContainsPalette(const VIDEOINFOHEADER *pVideoInfo) 
{ 
    if (PALETTISED(pVideoInfo) == FALSE) { 
        if (pVideoInfo->bmiHeader.biClrUsed == 0) { 
            return FALSE; 
        } 
    } 
    return TRUE; 
} 
 
 
// Return a pointer to the first entry in a palette 
 
STDAPI_(const RGBQUAD *) GetBitmapPalette(const VIDEOINFOHEADER *pVideoInfo) 
{ 
    if (pVideoInfo->bmiHeader.biCompression == BI_BITFIELDS) { 
        return TRUECOLOR(pVideoInfo)->bmiColors; 
    } 
    return COLORS(pVideoInfo); 
}