decoder.cpp
Upload User: xhy777
Upload Date: 2007-02-14
Package Size: 24088k
Code Size: 15k
Category:

Windows Kernel

Development Platform:

Visual C++

  1. #include "stdafx.h"
  2. #include "ctngen.h"
  3. LPDIRECTDRAW g_lpDD=NULL;
  4. HBITMAP ImgCreateDib(LONG xWid, LONG yHei, BOOL fPal, int cBitsPerPix,
  5.     int cEnt, PALETTEENTRY * ppe, BYTE ** ppbBits, int * pcbRow);
  6. void DrawImage(HDC hwnd, FILTERINFO *pFilter, RECT *prc);
  7. RGBQUAD g_rgbBgColor = { 0, 0, 0, 0 };
  8. RGBQUAD g_rgbFgColor = { 255, 255, 255, 0 };
  9. PALETTEENTRY g_peVga[16] =
  10. {
  11.     { 0x00, 0x00, 0x00, 0x00 }, // Black
  12.     { 0x80, 0x00, 0x00, 0x00 }, // Dark red
  13.     { 0x00, 0x80, 0x00, 0x00 }, // Dark green
  14.     { 0x80, 0x80, 0x00, 0x00 }, // Dark yellow
  15.     { 0x00, 0x00, 0x80, 0x00 }, // Dark blue
  16.     { 0x80, 0x00, 0x80, 0x00 }, // Dark purple
  17.     { 0x00, 0x80, 0x80, 0x00 }, // Dark aqua
  18.     { 0xC0, 0xC0, 0xC0, 0x00 }, // Light grey
  19.     { 0x80, 0x80, 0x80, 0x00 }, // Dark grey
  20.     { 0xFF, 0x00, 0x00, 0x00 }, // Light red
  21.     { 0x00, 0xFF, 0x00, 0x00 }, // Light green
  22.     { 0xFF, 0xFF, 0x00, 0x00 }, // Light yellow
  23.     { 0x00, 0x00, 0xFF, 0x00 }, // Light blue
  24.     { 0xFF, 0x00, 0xFF, 0x00 }, // Light purple
  25.     { 0x00, 0xFF, 0xFF, 0x00 }, // Light aqua
  26.     { 0xFF, 0xFF, 0xFF, 0x00 }  // White
  27. };
  28. #define Assert(x)
  29. #define ReleaseMemoryDC(x)              DeleteObject(x)
  30. #define GetMemoryDC()                   CreateCompatibleDC(NULL)
  31. #define MulDivQuick                     MulDiv
  32. #define Verify(x)                       x
  33. HRESULT decoderDDrawInitialize()
  34. {
  35.     HRESULT retVal;
  36.     //
  37.     // DirectDraw initialization fails on systems with 16 colors.  In such cases, we don't want to
  38.     // pop up the "You must be running in 256 color mode or higher" message because thumbnail generation
  39.     // can happen in the background.  Instead we will silently fail.
  40.     //
  41.     UINT uMode = SetErrorMode(SEM_FAILCRITICALERRORS);
  42.     //
  43.     // Can get an exception because ddraw.dll is delay loaded
  44.     //
  45.     _try
  46.     {
  47.         if (((retVal=DirectDrawCreate(NULL, &g_lpDD, NULL)) == DD_OK) &&
  48.             ((retVal=g_lpDD->SetCooperativeLevel(NULL, DDSCL_NORMAL)) == DD_OK))
  49.         {
  50.             retVal = ERROR_SUCCESS;
  51.         }
  52.     }
  53.     _except(EXCEPTION_EXECUTE_HANDLER)
  54.     {
  55.         //
  56.         // Most likely we failed to load ddraw.dll.  Fail gracefully.
  57.         //
  58.         retVal = E_FAIL;
  59.     }
  60.     //
  61.     // Restore previous error mode
  62.     //
  63.     
  64.     SetErrorMode(uMode);
  65.     
  66.     return retVal;
  67. }
  68. HRESULT decoderInitialize(VOID)
  69. {
  70.     return ERROR_SUCCESS;
  71. }
  72. VOID decoderUninitialize(VOID)
  73. {
  74.     if (g_lpDD)
  75.     {
  76.         g_lpDD->Release();
  77.         g_lpDD = NULL;
  78.     }
  79.     
  80.     return;
  81. }
  82. STDMETHODIMP CThumbnailFCNContainer::InitializeEventSink(VOID)
  83. {
  84.     ZeroMemory(&m_Filter, sizeof(m_Filter));
  85.         ZeroMemory(&m_rcProg, sizeof(m_rcProg));
  86.         m_pDDrawSurface=NULL;
  87.         m_dwLastTick=0;
  88.         return ERROR_SUCCESS;
  89. }
  90. STDMETHODIMP CThumbnailFCNContainer::OnBeginDecode(DWORD* pdwEvents, 
  91.    ULONG* pnFormats, GUID** ppFormats)
  92. {
  93.     GUID* pFormats;
  94.     if (pdwEvents != NULL)
  95.     {
  96.         *pdwEvents = 0;
  97.     }
  98.     if (pnFormats != NULL)
  99.     {
  100.         *pnFormats = 0;
  101.     }
  102.     if (ppFormats != NULL)
  103.     {
  104.         *ppFormats = NULL;
  105.     }
  106.     if (pdwEvents == NULL)
  107.     {
  108.         return (E_POINTER);
  109.     }
  110.     if (pnFormats == NULL)
  111.     {
  112.         return (E_POINTER);
  113.     }
  114.     if (ppFormats == NULL)
  115.     {
  116.         return (E_POINTER);
  117.     }
  118.     pFormats = (GUID*)CoTaskMemAlloc(6*sizeof(GUID));
  119.     if(pFormats == NULL)
  120.     {
  121.         return (E_OUTOFMEMORY);
  122.     }
  123.         
  124.     pFormats[0] = BFID_RGB_24;
  125.     pFormats[1] = BFID_INDEXED_RGB_8;
  126.     pFormats[2] = BFID_RGB_555;
  127.     pFormats[3] = BFID_RGB_565;
  128.     pFormats[4] = BFID_INDEXED_RGB_4;
  129.     pFormats[5] = BFID_INDEXED_RGB_1;
  130.     *pnFormats = 6;
  131.     *ppFormats = pFormats;
  132.     *pdwEvents = IMGDECODE_EVENT_PALETTE|IMGDECODE_EVENT_BITSCOMPLETE;
  133.     *pdwEvents |= IMGDECODE_EVENT_USEDDRAW;
  134.     m_Filter.dwEvents = *pdwEvents;
  135.     m_dwLastTick = GetTickCount();
  136.     return (S_OK);
  137. }
  138. STDMETHODIMP CThumbnailFCNContainer::OnBitsComplete()
  139. {
  140.     return (S_OK);
  141. }
  142. STDMETHODIMP CThumbnailFCNContainer::OnDecodeComplete(HRESULT hrStatus)
  143. {
  144.     // Deliver NULL data for failures cases
  145.     deliverDecompressedImage(NULL, 0, 0);
  146.     if (FAILED(hrStatus))
  147.     {
  148.         // Release ddraw surface if allocated
  149. if (m_pDDrawSurface) 
  150. {
  151.     m_pDDrawSurface.Release();
  152.     m_pDDrawSurface = NULL;
  153. }
  154.         return S_OK; // Decode failed for some reason--abort.
  155.     }
  156.     
  157.     if (m_pDDrawSurface != NULL)
  158.     {
  159.         DDSURFACEDESC    ddsd;
  160.         DDCOLORKEY      ddKey;
  161.         RECT    rcDest;
  162.         LPDIRECTDRAWPALETTE    pPal;
  163.         PALETTEENTRY    ape[256];
  164.         int    cbRow;
  165.         BYTE *pbSrc, *pbDst;
  166.         LONG i;
  167.         // HACK
  168.         m_pDDrawSurface->GetColorKey(DDCKEY_SRCBLT, &ddKey);
  169.         m_Filter._lTrans = ddKey.dwColorSpaceLowValue;
  170.         rcDest.left = rcDest.top = 0;
  171.         rcDest.right = m_Filter._xWidth;
  172.         rcDest.bottom = m_Filter._yHeight;
  173.         ddsd.dwSize = sizeof(ddsd);
  174.         if (SUCCEEDED(m_pDDrawSurface->Lock(&rcDest, &ddsd, DDLOCK_SURFACEMEMORYPTR | DDLOCK_WAIT, NULL)))
  175.         {
  176.             if (SUCCEEDED(m_pDDrawSurface->GetPalette(&pPal)))
  177.             {
  178.                 pPal->GetEntries(0, 0, 256, ape);
  179.                 pPal->Release();
  180.             }
  181.             m_Filter._hbmDib = ImgCreateDib(
  182.                 m_Filter._xWidth,
  183.                 -m_Filter._yHeight,
  184.                 m_Filter._colorMode == 8 && m_Filter.m_nBitsPerPixel == 8, 
  185.                 m_Filter.m_nBitsPerPixel,
  186.                 (m_Filter.m_nBitsPerPixel <= 4) ? 0 : 256, 
  187.                 ape,
  188.                 &m_Filter.m_pbBits, 
  189.                 &cbRow);
  190.             pbSrc = (BYTE *)ddsd.lpSurface;
  191.             pbDst = m_Filter.m_pbBits;
  192.             if (pbSrc && pbDst)
  193.             {
  194.                 for (i = 0; i < m_Filter._yHeight; ++i)
  195.                 {
  196.                     memcpy(pbDst, pbSrc, cbRow);
  197.                     pbDst += cbRow;
  198.                     pbSrc += ddsd.lPitch;
  199.                 }
  200.                 deliverDecompressedImage(m_Filter._hbmDib, m_Filter._xWidth, m_Filter._yHeight);
  201.             }
  202.             m_pDDrawSurface->Unlock(ddsd.lpSurface);
  203.         }
  204.         m_pDDrawSurface.Release();
  205.         m_pDDrawSurface = NULL;
  206.     }
  207.     return S_OK; // Always return S_OK
  208. }
  209. void CopyColorsFromPaletteEntries(RGBQUAD *prgb, const PALETTEENTRY *ppe,
  210.     UINT uCount)
  211. {
  212.     while (uCount--)
  213.     {
  214.         prgb->rgbRed   = ppe->peRed;
  215.         prgb->rgbGreen = ppe->peGreen;
  216.         prgb->rgbBlue  = ppe->peBlue;
  217.         prgb->rgbReserved = 0;
  218.         prgb++;
  219.         ppe++;
  220.     }
  221. }
  222. HBITMAP ImgCreateDib(LONG xWid, LONG yHei, BOOL fPal, int cBitsPerPix,
  223.     int cEnt, PALETTEENTRY * ppe, BYTE ** ppbBits, int * pcbRow)
  224. {
  225.     HDC hdcMem = NULL;
  226.     HBITMAP hbm = NULL;
  227.     struct {
  228.         BITMAPINFOHEADER bmih;
  229.         union {
  230.             RGBQUAD argb[256];
  231.             WORD aw[256];
  232.         } u;
  233.     } bmi;
  234.     BYTE * pbBits;
  235.     int cbRow;
  236.     int i;
  237.     
  238.     Assert(cBitsPerPix == 1 || cBitsPerPix == 4 ||
  239.         cBitsPerPix == 8 || cBitsPerPix == 24 || cBitsPerPix == 32);
  240.     Assert(xWid > 0 && yHei > 0);
  241.     bmi.bmih.biSize          = sizeof(BITMAPINFOHEADER);
  242.     bmi.bmih.biWidth         = xWid;
  243.     bmi.bmih.biHeight        = yHei;
  244.     bmi.bmih.biPlanes        = 1;
  245.     bmi.bmih.biBitCount      = (WORD)cBitsPerPix;
  246.     bmi.bmih.biCompression   = BI_RGB;
  247.     bmi.bmih.biSizeImage     = 0;
  248.     bmi.bmih.biXPelsPerMeter = 0;
  249.     bmi.bmih.biYPelsPerMeter = 0;
  250.     bmi.bmih.biClrUsed       = 0;
  251.     bmi.bmih.biClrImportant  = 0;
  252.         fPal = FALSE;
  253.     if (cBitsPerPix == 1)
  254.     {
  255.         bmi.bmih.biClrUsed = 2;
  256.         if (cEnt > 2)
  257.             cEnt = 2;
  258.         if (cEnt > 0)
  259.         {
  260.             bmi.bmih.biClrImportant = cEnt;
  261.             CopyColorsFromPaletteEntries(bmi.u.argb, ppe, cEnt);
  262.         }
  263.         else
  264.         {
  265.             bmi.u.argb[0] = g_rgbBgColor;
  266.             bmi.u.argb[1] = g_rgbFgColor;
  267.         }
  268.         cbRow = (((xWid + 7) / 8) + 3) & ~3;
  269.     }
  270.     else if (cBitsPerPix == 4)
  271.     {
  272.         bmi.bmih.biClrUsed = 16;
  273.         if (cEnt > 16)
  274.             cEnt = 16;
  275.         if (cEnt > 0)
  276.         {
  277.             bmi.bmih.biClrImportant = cEnt;
  278.             CopyColorsFromPaletteEntries(bmi.u.argb, ppe, cEnt);
  279.         }
  280.         else
  281.         {
  282.             bmi.bmih.biClrImportant = 16;
  283.             CopyColorsFromPaletteEntries(bmi.u.argb, g_peVga, 16);
  284.         }
  285.         cbRow = (((xWid + 1) / 2) + 3) & ~3;
  286.     }
  287.     else if (cBitsPerPix == 8)
  288.     {
  289.         if (fPal)
  290.         {
  291.             bmi.bmih.biClrUsed = 256;
  292.             for (i = 0; i < 256; ++i)
  293.                 bmi.u.aw[i] = (WORD)i;
  294.         }
  295.         else
  296.         {
  297.             if (cEnt > 0 && cEnt < 256)
  298.             {
  299.                 bmi.bmih.biClrUsed = cEnt;
  300.                 bmi.bmih.biClrImportant = cEnt;
  301.             }
  302.             else
  303.                 bmi.bmih.biClrUsed = 256;
  304.             if (cEnt && ppe)
  305.             {
  306.                 CopyColorsFromPaletteEntries(bmi.u.argb, ppe, cEnt);
  307.             }
  308.         }
  309.         cbRow = (xWid + 3) & ~3;
  310.     }
  311.     else if (cBitsPerPix == 24)
  312.     {
  313.         cbRow = ((xWid * 3) + 3) & ~3;
  314.     }
  315.     else
  316.     {
  317.         Assert(cBitsPerPix == 32);
  318.         cbRow = ((xWid * 4) + 3) & ~3;
  319.     }
  320.     if (pcbRow)
  321.     {
  322.         *pcbRow = cbRow;
  323.     }
  324.     hdcMem = GetMemoryDC();
  325.     if (hdcMem == NULL)
  326.         goto Cleanup;
  327.     hbm = CreateDIBSection(hdcMem, (BITMAPINFO *)&bmi,
  328.             fPal ? DIB_PAL_COLORS : DIB_RGB_COLORS,
  329.             (void **)&pbBits, NULL, 0);
  330.     if (hbm && ppbBits)
  331.     {
  332.         *ppbBits = pbBits;
  333.     }
  334.     // Fill the bits with garbage so that the client doesn't assume that
  335.     // the DIB gets created cleared (on WinNT it does, on Win95 it doesn't).
  336.     #if DBG==1
  337.     if (hbm && pbBits)
  338.         for (int c = cbRow * yHei; --c >= 0; ) pbBits[c] = (BYTE)c;
  339.     #endif
  340. Cleanup:
  341.     if (hdcMem)
  342.         ReleaseMemoryDC(hdcMem);
  343.     return(hbm);
  344. }
  345. #define LINEBYTES(_wid,_bits) ((((_wid)*(_bits) + 31) / 32) * 4)
  346. STDMETHODIMP CThumbnailFCNContainer::GetSurface(LONG nWidth, LONG nHeight, 
  347.     REFGUID bfid, ULONG nPasses, DWORD dwHints, IUnknown ** ppSurface)
  348. {
  349.     DDSURFACEDESC ddsd;
  350.     HRESULT retVal;
  351.     if (!g_lpDD)
  352.     {
  353.         retVal = decoderDDrawInitialize();
  354.         if (FAILED(retVal))
  355.         {
  356.             return retVal;
  357.         }
  358.     }
  359.     (void)nPasses;
  360.     (void)dwHints;
  361.     
  362.     if (ppSurface != NULL)
  363.     {
  364.         *ppSurface = NULL;
  365.     }
  366.     if (ppSurface == NULL)
  367.     {
  368.         return (E_POINTER);
  369.     }
  370.     ddsd.dwSize = sizeof(DDSURFACEDESC);
  371.     ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT;
  372.     ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY;
  373.     ddsd.dwHeight = nHeight;
  374.     ddsd.dwWidth = nWidth;
  375.     ddsd.ddpfPixelFormat.dwSize = sizeof(DDPIXELFORMAT);
  376.     if (IsEqualGUID(bfid, BFID_INDEXED_RGB_8))
  377.     {
  378.         m_Filter.m_nBitsPerPixel = 8;
  379.         ddsd.ddpfPixelFormat.dwFlags = DDPF_PALETTEINDEXED8 | DDPF_RGB;
  380.         ddsd.ddpfPixelFormat.dwRGBBitCount = 8;
  381.         ddsd.ddpfPixelFormat.dwRBitMask = 0;
  382.         ddsd.ddpfPixelFormat.dwGBitMask = 0;
  383.         ddsd.ddpfPixelFormat.dwBBitMask = 0;
  384.         ddsd.ddpfPixelFormat.dwRGBAlphaBitMask = 0;
  385.     }
  386.     else if (IsEqualGUID(bfid, BFID_RGB_24))
  387.     {
  388.         m_Filter.m_nBitsPerPixel = 24;
  389.         ddsd.ddpfPixelFormat.dwFlags = DDPF_RGB;
  390.         ddsd.ddpfPixelFormat.dwRGBBitCount = 24;
  391.         ddsd.ddpfPixelFormat.dwRBitMask = 0x00FF0000L;
  392.         ddsd.ddpfPixelFormat.dwGBitMask = 0x0000FF00L;
  393.         ddsd.ddpfPixelFormat.dwBBitMask = 0x000000FFL;
  394.     }
  395.     else if (IsEqualGUID(bfid, BFID_INDEXED_RGB_4))
  396.     {
  397.         m_Filter.m_nBitsPerPixel = 4;
  398.     
  399.         ddsd.ddpfPixelFormat.dwFlags = DDPF_PALETTEINDEXED4 | DDPF_RGB;
  400.         ddsd.ddpfPixelFormat.dwRGBBitCount = 4;
  401.         ddsd.ddpfPixelFormat.dwRBitMask = 0;
  402.         ddsd.ddpfPixelFormat.dwGBitMask = 0;
  403.         ddsd.ddpfPixelFormat.dwBBitMask = 0;
  404.         ddsd.ddpfPixelFormat.dwRGBAlphaBitMask = 0;
  405.     }
  406.     else if (IsEqualGUID(bfid, BFID_INDEXED_RGB_1))
  407.     {
  408.         m_Filter.m_nBitsPerPixel = 1;
  409.     
  410.         ddsd.ddpfPixelFormat.dwFlags = DDPF_PALETTEINDEXED1 | DDPF_RGB;
  411.         ddsd.ddpfPixelFormat.dwRGBBitCount = 1;
  412.         ddsd.ddpfPixelFormat.dwRBitMask = 0;
  413.         ddsd.ddpfPixelFormat.dwGBitMask = 0;
  414.         ddsd.ddpfPixelFormat.dwBBitMask = 0;
  415.         ddsd.ddpfPixelFormat.dwRGBAlphaBitMask = 0;
  416.     }
  417.     else
  418.     {
  419.         return (E_NOINTERFACE);
  420.     }
  421.     m_Filter._xWidth = nWidth;
  422.     m_Filter._yHeight = nHeight;
  423.     m_Filter.m_nPitch = -LONG( LINEBYTES( m_Filter._xWidth, 
  424.     m_Filter.m_nBitsPerPixel ) );
  425.     m_Filter.m_pbBits = NULL;
  426.     m_Filter.m_pbFirstScanLine = NULL;
  427.     // Don't create surfaces that require more than 4M (MAX_IMAGE_SIZE) of memory.
  428.     // The computation below could still overflow for really large surfaces, but dividing
  429.     // by 8 (bits per byte) before multiplying by the BPP allows us to handle reasonably
  430.     // large images.
  431.     if ((((nWidth * nHeight) / 8) * m_Filter.m_nBitsPerPixel) > MAX_IMAGE_SIZE)
  432.     {
  433.         return E_OUTOFMEMORY;
  434.     }
  435.     if (FAILED(g_lpDD->CreateSurface(&ddsd, &m_pDDrawSurface, NULL)))
  436.         return (E_OUTOFMEMORY);
  437.     // If this is a palette surface create/attach a palette to it.
  438.     if (m_Filter.m_nBitsPerPixel == 8)
  439.     {
  440.     PALETTEENTRY ape[256];
  441.         LPDIRECTDRAWPALETTE pDDPalette;
  442.     g_lpDD->CreatePalette(DDPCAPS_8BIT | DDPCAPS_ALLOW256, ape, &pDDPalette, NULL);
  443.         m_pDDrawSurface->SetPalette(pDDPalette);
  444.         pDDPalette->Release();
  445.     }
  446. //    m_Filter.m_pDDrawSurface = m_pDDrawSurface;
  447. //    m_pDDrawSurface->AddRef();
  448.     *ppSurface = (IUnknown *)m_pDDrawSurface;
  449.     (*ppSurface)->AddRef();
  450.     
  451.     return S_OK;
  452. }
  453. STDMETHODIMP CThumbnailFCNContainer::OnPalette()
  454. {
  455.     LONG nColors;
  456.     RGBQUAD argb[256];
  457.     HDC hdcMem;
  458.     
  459.     if (m_pDDrawSurface)
  460.     {
  461.         LPDIRECTDRAWPALETTE pDDPalette;
  462.         PALETTEENTRY        ape[256];
  463.         HRESULT             hResult;
  464.         hResult = m_pDDrawSurface->GetPalette(&pDDPalette);
  465.         if (SUCCEEDED(hResult))
  466.         {
  467.             pDDPalette->GetEntries(0, 0, 256, ape);
  468.             pDDPalette->Release();
  469.             CopyColorsFromPaletteEntries(argb, ape, 256);
  470.         }
  471.     }
  472.     
  473.     return (S_OK);
  474. }
  475. STDMETHODIMP CThumbnailFCNContainer::OnProgress(RECT* pBounds, BOOL bComplete)
  476. {
  477.     return (S_OK);
  478. }