cappal.c
Upload User: caisha3
Upload Date: 2013-09-21
Package Size: 208739k
Code Size: 20k
Category:

Windows Develop

Development Platform:

Visual C++

  1. /****************************************************************************
  2.  *
  3.  *   cappal.c
  4.  *
  5.  *   Palette processing module.
  6.  *
  7.  *   Microsoft Video for Windows Sample Capture Class
  8.  *
  9.  *   Copyright (c) 1992, 1993 Microsoft Corporation.  All Rights Reserved.
  10.  *
  11.  *    You have a royalty-free right to use, modify, reproduce and
  12.  *    distribute the Sample Files (and/or any modified version) in
  13.  *    any way you find useful, provided that you agree that
  14.  *    Microsoft has no warranty obligations or liability for any
  15.  *    Sample Application Files which are modified.
  16.  *
  17.  ***************************************************************************/
  18. #define INC_OLE2
  19. #pragma warning(disable:4103)
  20. #include <windows.h>
  21. #include <windowsx.h>
  22. #include <win32.h>
  23. #include <mmsystem.h>
  24. #include <msvideo.h>
  25. #include <drawdib.h>
  26. #include "ivideo32.h"
  27. #include "avicap.h"
  28. #include "avicapi.h"
  29. #include "cappal.h"
  30. #include "capdib.h"
  31. #include "dibmap.h"
  32. //
  33. // Allocate and initialize palette resources at Window create time
  34. //
  35. BOOL PalInit (LPCAPSTREAM lpcs)
  36. {
  37.     return (PalGetPaletteFromDriver (lpcs));
  38. }
  39. //
  40. // FreePaletteCache - free the RGB555 Xlate table
  41. //
  42. void FreePaletteCache (LPCAPSTREAM lpcs)
  43. {
  44.     if (lpcs->lpCacheXlateTable) {
  45.         GlobalFreePtr (lpcs->lpCacheXlateTable);
  46. lpcs->lpCacheXlateTable = NULL;
  47.     }
  48. }
  49. //
  50. // Release palette resources at Window destroy time
  51. //
  52. void PalFini (LPCAPSTREAM lpcs)
  53. {
  54.     PalDeleteCurrentPalette (lpcs);
  55.     FreePaletteCache (lpcs);
  56. }
  57. //
  58. // Delete our palette if it isn't the system default palette
  59. //
  60. void PalDeleteCurrentPalette (LPCAPSTREAM lpcs)
  61. {
  62.     if (lpcs->hPalCurrent &&
  63.             (lpcs->hPalCurrent != GetStockObject(DEFAULT_PALETTE)))
  64.         DeleteObject (lpcs->hPalCurrent);
  65.     lpcs->hPalCurrent = NULL;
  66. }
  67. //
  68. // Get the current palette (from the driver)
  69. // Returns: TRUE if the driver can supply a palette
  70. //
  71. BOOL PalGetPaletteFromDriver (LPCAPSTREAM lpcs)
  72. {
  73.     FCLOGPALETTE        pal;
  74.     PalDeleteCurrentPalette (lpcs);
  75.     pal.palVersion = 0x0300;
  76.     pal.palNumEntries = 256;
  77.     lpcs->sCapDrvCaps.fDriverSuppliesPalettes = FALSE;  // assume the worst
  78.     if (lpcs->fHardwareConnected) {
  79.         if (videoConfigure (lpcs->hVideoIn,
  80.                 DVM_PALETTE,
  81.                 VIDEO_CONFIGURE_GET | VIDEO_CONFIGURE_CURRENT, NULL,
  82.                 (LPVOID)&pal, sizeof(pal),
  83.                 NULL, 0 ) == DV_ERR_OK) {
  84.             if (lpcs->hPalCurrent = CreatePalette ((LPLOGPALETTE) &pal))
  85.                 lpcs->sCapDrvCaps.fDriverSuppliesPalettes = TRUE;
  86.         }
  87.     }
  88.     if (!lpcs->hPalCurrent)
  89.         lpcs->hPalCurrent = GetStockObject (DEFAULT_PALETTE);
  90.     DibNewPalette (lpcs, lpcs->hPalCurrent);
  91.     return (lpcs->sCapDrvCaps.fDriverSuppliesPalettes);
  92. }
  93. //
  94. // Set the current palette used for capture by sending a copy to the driver
  95. // and then copying the entries to out DIB.
  96. // This may also be called when reconnecting a driver and using a cached
  97. // copy of the palette.
  98. // Returns TRUE on success, or FALSE on failure.
  99. //
  100. DWORD PalSendPaletteToDriver (LPCAPSTREAM lpcs, HPALETTE hpal, LPBYTE lpXlateTable)
  101. {
  102.     short               nColors;
  103.     FCLOGPALETTE        pal;
  104.     HCURSOR             hOldCursor;
  105.     // The following can take a while so repaint our parent
  106.     UpdateWindow (GetParent (lpcs-> hwnd));
  107.     UpdateWindow (lpcs->hwnd);
  108.     if (!hpal)
  109.         return FALSE;
  110.     // Allocate a xlate table cache?
  111.     if (lpXlateTable) {
  112.         if (lpcs->lpCacheXlateTable == NULL) {
  113.             lpcs->lpCacheXlateTable = GlobalAllocPtr (GHND, 0x8000l);
  114.             if (!lpcs->lpCacheXlateTable)
  115.                 return FALSE;
  116.         }
  117.         // If we're not using the cached table, update the cache
  118.         if (lpcs->lpCacheXlateTable != lpXlateTable)
  119.             _fmemcpy (lpcs->lpCacheXlateTable, lpXlateTable, (UINT) 0x8000l);
  120.     }
  121.     else {
  122.         FreePaletteCache (lpcs);
  123.     }
  124.     // Don't destroy the current palette when reconnecting...
  125.     if (hpal != lpcs->hPalCurrent) {
  126.         PalDeleteCurrentPalette (lpcs);
  127.         lpcs->hPalCurrent = hpal;
  128.     }
  129.     GetObject(hpal, sizeof(short), (LPVOID)&nColors);
  130.     if( nColors <= 1 ) {    //!!>
  131.         return( FALSE );
  132.     }
  133.     nColors = min(256, nColors);
  134.     hOldCursor = SetCursor (lpcs-> hWaitCursor);
  135.     statusUpdateStatus (lpcs, IDS_CAP_STAT_PALETTE_BUILD);
  136.     pal.palVersion = 0x0300;
  137.     pal.palNumEntries = nColors;
  138.     GetPaletteEntries(hpal, 0, nColors, pal.palPalEntry);
  139.     if (lpcs-> fHardwareConnected) {
  140.         // first try to send both the xlate table and the palette
  141.         if ((!lpXlateTable) || (videoConfigure( lpcs->hVideoIn,
  142.                     DVM_PALETTERGB555,
  143.                     VIDEO_CONFIGURE_SET, NULL,
  144.                     (LPLOGPALETTE)&pal, sizeof(pal),
  145.                     lpXlateTable, (DWORD) 0x8000) != 0)) {
  146.             // else send just the palette and make the driver build the table
  147.             if (videoConfigure( lpcs->hVideoIn,
  148.                     DVM_PALETTE,
  149.                     VIDEO_CONFIGURE_SET, NULL,
  150.                     (LPLOGPALETTE)&pal, sizeof(pal),
  151.                     NULL, 0 )) {
  152.                 // Scrncap doesn't support setting a palette, so
  153.                 // delete the palette cache
  154.                 FreePaletteCache (lpcs);
  155.             }
  156.         }
  157.     }
  158.     // Supermac wants us to get the palette again, they might have
  159.     // mucked with it!
  160.     PalGetPaletteFromDriver (lpcs);
  161.     // Since the palette has changed, delete any existing compression
  162.     // output format;  this forces a new output format to be selected
  163.     if (lpcs->CompVars.lpbiOut) {
  164.         GlobalFreePtr (lpcs->CompVars.lpbiOut);
  165.         lpcs->CompVars.lpbiOut = NULL;
  166.     }
  167.     if (lpcs->CompVars.hic) {
  168.         if (ICSeqCompressFrameStart(&lpcs->CompVars, lpcs->lpBitsInfo) == 0) {
  169.             errorUpdateError (lpcs, IDS_CAP_COMPRESSOR_ERROR);
  170.         }
  171.     }
  172.     InvalidateRect (lpcs->hwnd, NULL, TRUE);
  173.     UpdateWindow (lpcs->hwnd);
  174.     SetCursor (hOldCursor);
  175.     statusUpdateStatus (lpcs, 0);
  176.     return (TRUE);
  177. }
  178. //
  179. // CopyPalette, makes a copy of a GDI logical palette
  180. // Returns: a handle to the newly created palette, or NULL if error
  181. //
  182. HPALETTE CopyPalette (HPALETTE hpal)
  183. {
  184.     LPLOGPALETTE        lppal;
  185.     short               nNumEntries;
  186.     if (!hpal)
  187.         return NULL;
  188.     GetObject (hpal,sizeof(short),(LPVOID)&nNumEntries);
  189.     if (nNumEntries == 0)
  190.         return NULL;
  191.     lppal = (LPLOGPALETTE) GlobalAllocPtr (GHND,
  192.                 sizeof(LOGPALETTE) + nNumEntries * sizeof(PALETTEENTRY));
  193.     if (!lppal)
  194.         return NULL;
  195.     lppal->palVersion    = 0x300;
  196.     lppal->palNumEntries = nNumEntries;
  197.     GetPaletteEntries(hpal,0,nNumEntries,lppal->palPalEntry);
  198.     hpal = CreatePalette(lppal);
  199.     GlobalFreePtr (lppal);
  200.     return hpal;
  201. }
  202. //
  203. // Allocate resources needed for palette capture
  204. // Returns DV_ERR_OK on success, or DV_ERR... on failure.
  205. // Note: if Init fails, you MUST call the Fini function to
  206. // release resources.
  207. //
  208. DWORD CapturePaletteInit (LPCAPSTREAM lpcs, LPCAPPAL lpcp)
  209. {
  210.     DWORD dwError = DV_ERR_OK;
  211.     lpcp->lpBits = NULL;
  212.     lpcp->lp16to8 = NULL;
  213.     lpcp->lpHistogram = NULL;
  214.     lpcp->lpbiSave = NULL;
  215.     lpcp->wNumFrames = 0;
  216.     // Init an RGB16 header
  217.     lpcp->bi16.biSize         = sizeof(BITMAPINFOHEADER);
  218.     lpcp->bi16.biWidth        = lpcs->dxBits;
  219.     lpcp->bi16.biHeight       = lpcs->dyBits;
  220.     lpcp->bi16.biPlanes       = 1;
  221.     lpcp->bi16.biBitCount     = 16;
  222.     lpcp->bi16.biCompression  = BI_RGB;
  223.     lpcp->bi16.biSizeImage    = DIBWIDTHBYTES(lpcp->bi16) * lpcp->bi16.biHeight;
  224.     lpcp->bi16.biXPelsPerMeter= 0;
  225.     lpcp->bi16.biYPelsPerMeter= 0;
  226.     lpcp->bi16.biClrUsed      = 0;
  227.     lpcp->bi16.biClrImportant = 0;
  228.     // Allocate memory for the histogram, DIB, and XLate table
  229.     lpcp->lpBits  = GlobalAllocPtr (GHND, lpcp->bi16.biSizeImage);
  230.     lpcp->lp16to8 = GlobalAllocPtr (GHND, 0x8000l);
  231.     lpcp->lpHistogram = InitHistogram(NULL);
  232.     if (!lpcp->lpBits || !lpcp->lp16to8 || !lpcp->lpHistogram) {
  233.         dwError = DV_ERR_NOMEM;
  234.         goto PalInitError;
  235.     }
  236.     // Init the video header
  237.     lpcp->vHdr.lpData = lpcp->lpBits;
  238.     lpcp->vHdr.dwBufferLength = lpcp->bi16.biSizeImage;
  239.     lpcp->vHdr.dwUser = 0;
  240.     lpcp->vHdr.dwFlags = 0;
  241.     // Save the current format
  242.     lpcp->lpbiSave = DibGetCurrentFormat (lpcs);
  243.     // Make sure we can set the format to 16 bit RGB
  244.     if(dwError = videoConfigure( lpcs->hVideoIn, DVM_FORMAT,
  245.             VIDEO_CONFIGURE_SET, NULL,
  246.             (LPBITMAPINFOHEADER)&lpcp->bi16, sizeof(BITMAPINFOHEADER),
  247.             NULL, 0 ) ) {
  248.         goto PalInitError;
  249.     }
  250.     // Put everything back the way it was
  251.     if (dwError = videoConfigure( lpcs->hVideoIn, DVM_FORMAT,
  252.             VIDEO_CONFIGURE_SET, NULL,
  253.             (LPBITMAPINFOHEADER)lpcp->lpbiSave, lpcp->lpbiSave->bmiHeader.biSize,
  254.             NULL, 0 )) {
  255.         goto PalInitError;
  256.     }
  257. PalInitError:
  258.     return dwError;
  259. }
  260. //
  261. // Free resources used for palette capture
  262. //
  263. DWORD CapturePaletteFini (LPCAPSTREAM lpcs, LPCAPPAL lpcp)
  264. {
  265.     if (lpcp->lpBits) {
  266.         GlobalFreePtr (lpcp->lpBits);
  267.         lpcp->lpBits = NULL;
  268.     }
  269.     if (lpcp->lp16to8) {
  270.         GlobalFreePtr (lpcp->lp16to8);
  271.         lpcp->lp16to8 = NULL;
  272.     }
  273.     if (lpcp->lpHistogram) {
  274.         FreeHistogram(lpcp->lpHistogram);
  275.         lpcp->lpHistogram = NULL;
  276.     }
  277.     if (lpcp->lpbiSave) {
  278.         GlobalFreePtr (lpcp->lpbiSave);
  279.         lpcp->lpbiSave = NULL;
  280.     }
  281.     return DV_ERR_OK;
  282. }
  283. //
  284. //  CapturePaletteFrames() The workhorse of capture palette.
  285. //
  286. DWORD CapturePaletteFrames (LPCAPSTREAM lpcs, LPCAPPAL lpcp, int nCount)
  287. {
  288.     int j;
  289.     DWORD dwError;
  290.     // switch to RGB16 format
  291.     if (dwError = videoConfigure( lpcs->hVideoIn,
  292.                 DVM_FORMAT,
  293.                 VIDEO_CONFIGURE_SET, NULL,
  294.                 (LPBITMAPINFOHEADER)&lpcp->bi16, sizeof(BITMAPINFOHEADER),
  295.                 NULL, 0 ))
  296.         goto CaptureFramesError;
  297.     for (j = 0; j < nCount; j++){
  298.         // Get a frame
  299.         dwError = videoFrame(lpcs->hVideoIn, &lpcp->vHdr);
  300.         // Let the user see it
  301.         InvalidateRect (lpcs->hwnd, NULL, TRUE);
  302.         UpdateWindow (lpcs->hwnd);
  303.         // Histogram it
  304.         DibHistogram(&lpcp->bi16, lpcp->lpBits, 0, 0, -1, -1, lpcp->lpHistogram);
  305.         lpcp->wNumFrames++;
  306.     }
  307.     dwError = videoConfigure( lpcs->hVideoIn,
  308.                 DVM_FORMAT,
  309.                 VIDEO_CONFIGURE_SET, NULL,
  310.                 (LPBITMAPINFOHEADER)lpcp->lpbiSave,
  311.                 lpcp->lpbiSave->bmiHeader.biSize,
  312.                 NULL, 0 );
  313. //    videoFrame( lpcs->hVideoIn, &lpcs->VidHdr );
  314. CaptureFramesError:
  315.     return dwError;
  316. }
  317. //
  318. //  CapturePaletteAuto() capture a palette from the video source
  319. //  without user intervention.
  320. //  Returns TRUE on success, FALSE on error
  321. //
  322. BOOL CapturePaletteAuto (LPCAPSTREAM lpcs, int nCount, int nColors)
  323. {
  324.     HPALETTE    hpal;
  325.     HCURSOR     hOldCursor;
  326.     DWORD       dwError = DV_ERR_OK;
  327.     CAPPAL      cappal;
  328.     LPCAPPAL    lpcp;
  329.     lpcp = &cappal;
  330.     if (!lpcs->sCapDrvCaps.fDriverSuppliesPalettes)
  331.         return FALSE;
  332.     if (nColors <= 0 || nColors > 256)
  333.         return FALSE;
  334.     lpcp->wNumColors = max (nColors, 2);  // at least 2 colors
  335.     if (nCount <= 0)
  336.         return FALSE;
  337.     if (dwError = CapturePaletteInit (lpcs, lpcp))
  338.         goto PalAutoExit;
  339.     hOldCursor = SetCursor(lpcs->hWaitCursor);
  340.     CapturePaletteFrames (lpcs, lpcp, nCount);
  341.     /* we grabbed a frame, time to compute a palette */
  342.     statusUpdateStatus(lpcs, IDS_CAP_STAT_OPTPAL_BUILD);
  343.     // The HPALETTE returned in the following becomes
  344.     // our "global" palette, hence is not deleted here.
  345.     hpal = HistogramPalette(lpcp->lpHistogram, lpcp->lp16to8, lpcp->wNumColors);
  346.     // Send driver both the pal and xlate table
  347.     PalSendPaletteToDriver(lpcs, hpal, (LPBYTE)lpcp->lp16to8 );
  348.     videoFrame( lpcs->hVideoIn, &lpcs->VidHdr );  // Update the display with a new image
  349.     SetCursor(hOldCursor);
  350.     InvalidateRect(lpcs->hwnd, NULL, TRUE);
  351.     UpdateWindow(lpcs->hwnd);
  352.     lpcs->fUsingDefaultPalette = FALSE;
  353. PalAutoExit:
  354.     CapturePaletteFini (lpcs, lpcp);
  355.     statusUpdateStatus(lpcs, 0);
  356.    // If an error happened, display it
  357.    if (dwError)
  358.         errorDriverID (lpcs, dwError);
  359.     return (dwError == DV_ERR_OK);
  360. }
  361. //
  362. //  CapturePaletteManual() capture a palette from the video source
  363. //  with user intervention.
  364. //  fGrab is TRUE on all but the last frame captured
  365. //  Returns TRUE on success, FALSE on error
  366. //
  367. BOOL CapturePaletteManual (LPCAPSTREAM lpcs, BOOL fGrab, int nColors)
  368. {
  369.     HPALETTE    hpal;
  370.     HCURSOR     hOldCursor;
  371.     LPCAPPAL    lpcp;
  372.     DWORD       dwError = DV_ERR_OK;
  373.     if (!lpcs->sCapDrvCaps.fDriverSuppliesPalettes)
  374.         return FALSE;
  375.     hOldCursor = SetCursor(lpcs->hWaitCursor);
  376.     // We're initializing for the first time, so alloc everything
  377.     if (lpcs->lpCapPal == NULL) {
  378.         if (lpcp = (LPCAPPAL) GlobalAllocPtr (GHND, sizeof(CAPPAL))) {
  379.             lpcs->lpCapPal = lpcp;
  380.             if (nColors == 0)
  381.                 nColors = 256;
  382.             lpcp->wNumColors = min (nColors, 256);
  383.             dwError = CapturePaletteInit (lpcs, lpcp);
  384.         }
  385.         else
  386.             dwError = IDS_CAP_OUTOFMEM;
  387.     }
  388.     lpcp = lpcs->lpCapPal;
  389.     if (dwError != DV_ERR_OK)
  390.         goto PalManualExit;
  391.     // Add a frame to the histogram
  392.     // Handle the case of telling us to stop before we ever started
  393.     if (fGrab || !fGrab && (lpcp->wNumFrames == 0)) {
  394.         CapturePaletteFrames (lpcs, lpcp, 1);
  395.         lpcs->fUsingDefaultPalette = FALSE;
  396.     }
  397.     // All done, send the new palette to the driver
  398.     if (!fGrab) {
  399.         statusUpdateStatus(lpcs, IDS_CAP_STAT_OPTPAL_BUILD);
  400.         // The HPALETTE returned in the following becomes
  401.         // our "global" palette, hence is not deleted here.
  402.         hpal = HistogramPalette(lpcp->lpHistogram,
  403.                         lpcp->lp16to8, lpcp->wNumColors);
  404.         // Send driver both the pal and xlate table
  405.         PalSendPaletteToDriver(lpcs, hpal, (LPBYTE)lpcp->lp16to8 );
  406.     }
  407.     videoFrame( lpcs->hVideoIn, &lpcs->VidHdr );  // Update the display with a new image
  408.     InvalidateRect(lpcs->hwnd, NULL, TRUE);
  409.     UpdateWindow(lpcs->hwnd);
  410. PalManualExit:
  411.     if (!fGrab || (dwError != DV_ERR_OK)) {
  412.         if (lpcp != NULL) {
  413.             CapturePaletteFini (lpcs, lpcp);
  414.             GlobalFreePtr (lpcp);
  415.             lpcs->lpCapPal = NULL;
  416.         }
  417.     }
  418.     SetCursor(hOldCursor);
  419.     statusUpdateStatus(lpcs, 0);
  420.     // If an error happened, display it
  421.     if (dwError) {
  422.         errorUpdateError (lpcs, (UINT) dwError);
  423.     }
  424.     return (dwError == DV_ERR_OK);
  425. }
  426. /*--------------------------------------------------------------+
  427. | fileSavePalette - save the current palette in a file   |
  428. | |
  429. +--------------------------------------------------------------*/
  430. BOOL FAR PASCAL fileSavePalette(LPCAPSTREAM lpcs, LPTSTR lpszFileName)
  431. {
  432.     HPALETTE            hpal;
  433.     HMMIO               hmmio;
  434.     WORD         w;
  435.     HCURSOR             hOldCursor;
  436.     MMCKINFO            ckRiff;
  437.     MMCKINFO            ck;
  438.     short               nColors;
  439.     FCLOGPALETTE        pal;
  440.     BOOL                fOK = FALSE;
  441.     if ((hpal = lpcs->hPalCurrent) == NULL)
  442.         return FALSE;
  443.     hmmio = mmioOpen(lpszFileName, NULL, MMIO_WRITE);
  444.     if( !hmmio ) {
  445. /* try and create */
  446.         hmmio = mmioOpen(lpszFileName, NULL, MMIO_CREATE | MMIO_WRITE);
  447. if( !hmmio ) {
  448.     /* find out if the file was read only or we are just */
  449.     /* totally hosed up here.  */
  450.     hmmio = mmioOpen(lpszFileName, NULL, MMIO_READ);
  451.     if (hmmio){
  452. /* file was read only, error on it */
  453.                 errorUpdateError (lpcs, IDS_CAP_READONLYFILE, (LPTSTR) lpszFileName);
  454. mmioClose(hmmio, 0);
  455. return FALSE;
  456.     } else {
  457. /* even weirder error has occured here, give CANTOPEN */
  458.                 errorUpdateError (lpcs, IDS_CAP_CANTOPEN, (LPTSTR) lpszFileName);
  459. return FALSE;
  460.     }
  461. }
  462.     }
  463.     hOldCursor = SetCursor( lpcs-> hWaitCursor );
  464.     /* Seek to beginning of file, so we can write the header. */
  465.     mmioSeek(hmmio, 0, SEEK_SET);
  466.     /* Create RIFF chunk */
  467.     ckRiff.fccType = mmioFOURCC('P','A','L',' ');
  468.     if(mmioCreateChunk (hmmio,&ckRiff,MMIO_CREATERIFF)) {
  469.          goto FileError;
  470.     }
  471.     /* Create Palette chunk */
  472.     ck.cksize = 0;
  473.     ck.ckid = mmioFOURCC('d','a','t','a');
  474.     if(mmioCreateChunk(hmmio,&ck,0)) {
  475.          goto FileError;
  476.     }
  477.     // Get the palette data here
  478.     GetObject(hpal, sizeof(short), (LPVOID)&nColors);
  479.     pal.palVersion = 0x0300;
  480.     pal.palNumEntries = nColors;
  481.     GetPaletteEntries(hpal, 0, nColors, pal.palPalEntry);
  482.     // Calc the size of the logpalette
  483.     // which is the sizeof palVersion + sizeof palNumEntries + colors
  484.     w = sizeof (WORD) + sizeof (WORD) + nColors * sizeof (PALETTEENTRY);
  485.     // Write out the palette
  486.     if(mmioWrite(hmmio, (LPBYTE)&pal, (DWORD) w) != (LONG) w) {
  487.         goto FileError;
  488.     }
  489.     if(mmioAscend(hmmio, &ck, 0)) {
  490.         goto FileError;
  491.     }
  492.     if(mmioAscend(hmmio, &ckRiff, 0)) {
  493.         goto FileError;
  494.     }
  495.     fOK = TRUE;
  496. FileError:
  497.     mmioClose( hmmio, 0 );
  498.     SetCursor( hOldCursor );
  499.     if (!fOK)
  500.         errorUpdateError (lpcs, IDS_CAP_ERRORPALSAVE, (LPTSTR) lpszFileName);
  501.     return fOK;
  502. }
  503. /*--------------------------------------------------------------+
  504. | fileOpenPalette - use a new palette from the specified file   |
  505. | |
  506. +--------------------------------------------------------------*/
  507. BOOL FAR PASCAL fileOpenPalette(LPCAPSTREAM lpcs, LPTSTR lpszFileName)
  508. {
  509.     HPALETTE            hpal;
  510.     HMMIO               hmmio;
  511.     WORD         w;
  512.     HCURSOR             hOldCursor;
  513.     MMCKINFO            ckRiff;
  514.     MMCKINFO            ck;
  515.     FCLOGPALETTE        pal;
  516.     BOOL                fOK = FALSE;
  517.     if ((hpal = lpcs->hPalCurrent) == NULL)
  518.         return FALSE;
  519.     hmmio = mmioOpen(lpszFileName, NULL, MMIO_READ);
  520.     if( !hmmio ) {
  521.         errorUpdateError (lpcs, IDS_CAP_ERRORPALOPEN, (LPTSTR) lpszFileName);
  522.         return FALSE;
  523.     }
  524.     hOldCursor = SetCursor( lpcs-> hWaitCursor );
  525.     /* Seek to beginning of file, so we can read the header. */
  526.     mmioSeek(hmmio, 0, SEEK_SET);
  527.     /* Find the RIFF chunk */
  528.     ckRiff.fccType = mmioFOURCC('P','A','L',' ');
  529.     if(mmioDescend (hmmio, &ckRiff, NULL, MMIO_FINDRIFF)) {
  530.          goto PalOpenError;
  531.     }
  532.     /* Find the data chunk */
  533.     ck.cksize = 0;
  534.     ck.ckid = mmioFOURCC('d','a','t','a');
  535.     if(mmioDescend (hmmio, &ck, &ckRiff, MMIO_FINDCHUNK)) {
  536.          goto PalOpenError;
  537.     }
  538.     // First read just the Version and number of entries
  539.     // which is the sizeof palVersion + sizeof palNumEntries
  540.     w = sizeof (WORD) + sizeof (WORD);
  541.     if(mmioRead(hmmio, (LPBYTE)&pal, (DWORD) w) != (LONG) w) {
  542.         goto PalOpenError;
  543.     }
  544.     // Do a bit of checking
  545.     if ((pal.palVersion != 0x0300) || (pal.palNumEntries > 256))
  546.         goto PalOpenError;
  547.     // Now get the actual palette data
  548.     // which is the sizeof palVersion + sizeof palNumEntries
  549.     w = pal.palNumEntries * sizeof (PALETTEENTRY);
  550.     if(mmioRead(hmmio, (LPBYTE)&pal.palPalEntry, (DWORD) w) != (LONG) w) {
  551.         goto PalOpenError;
  552.     }
  553.     if (hpal = CreatePalette ((LPLOGPALETTE) &pal)) {
  554.         PalSendPaletteToDriver (lpcs, hpal, NULL /*lpXlateTable */);
  555.         fOK = TRUE;
  556.     }
  557.     videoFrame( lpcs->hVideoIn, &lpcs->VidHdr );  // grab a new frame
  558. PalOpenError:
  559.     mmioClose( hmmio, 0 );
  560.     SetCursor( hOldCursor );
  561.     InvalidateRect(lpcs->hwnd, NULL, TRUE);
  562.     UpdateWindow(lpcs->hwnd); // update the display with new frame
  563.     if (!fOK)
  564.         errorUpdateError (lpcs, IDS_CAP_ERRORPALOPEN, (LPTSTR) lpszFileName);
  565.     else
  566.     lpcs->fUsingDefaultPalette = FALSE;
  567.     return fOK;
  568. }