708 lines
19 KiB
C
708 lines
19 KiB
C
|
/****************************************************************************
|
||
|
*
|
||
|
* cappal.c
|
||
|
*
|
||
|
* Palette processing module.
|
||
|
*
|
||
|
* Microsoft Video for Windows Sample Capture Class
|
||
|
*
|
||
|
* Copyright (c) 1992, 1993 Microsoft Corporation. All Rights Reserved.
|
||
|
*
|
||
|
* You have a royalty-free right to use, modify, reproduce and
|
||
|
* distribute the Sample Files (and/or any modified version) in
|
||
|
* any way you find useful, provided that you agree that
|
||
|
* Microsoft has no warranty obligations or liability for any
|
||
|
* Sample Application Files which are modified.
|
||
|
*
|
||
|
***************************************************************************/
|
||
|
|
||
|
#define INC_OLE2
|
||
|
#pragma warning(disable:4103)
|
||
|
#include <windows.h>
|
||
|
#include <windowsx.h>
|
||
|
#include <win32.h>
|
||
|
#include <mmsystem.h>
|
||
|
#include <msvideo.h>
|
||
|
#include <drawdib.h>
|
||
|
|
||
|
#include "ivideo32.h"
|
||
|
#include "avicap.h"
|
||
|
#include "avicapi.h"
|
||
|
#include "cappal.h"
|
||
|
#include "capdib.h"
|
||
|
#include "dibmap.h"
|
||
|
|
||
|
//
|
||
|
// Allocate and initialize palette resources at Window create time
|
||
|
//
|
||
|
BOOL PalInit (LPCAPSTREAM lpcs)
|
||
|
{
|
||
|
return (PalGetPaletteFromDriver (lpcs));
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// FreePaletteCache - free the RGB555 Xlate table
|
||
|
//
|
||
|
void FreePaletteCache (LPCAPSTREAM lpcs)
|
||
|
{
|
||
|
if (lpcs->lpCacheXlateTable) {
|
||
|
GlobalFreePtr (lpcs->lpCacheXlateTable);
|
||
|
lpcs->lpCacheXlateTable = NULL;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Release palette resources at Window destroy time
|
||
|
//
|
||
|
void PalFini (LPCAPSTREAM lpcs)
|
||
|
{
|
||
|
PalDeleteCurrentPalette (lpcs);
|
||
|
|
||
|
FreePaletteCache (lpcs);
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Delete our palette if it isn't the system default palette
|
||
|
//
|
||
|
void PalDeleteCurrentPalette (LPCAPSTREAM lpcs)
|
||
|
{
|
||
|
if (lpcs->hPalCurrent &&
|
||
|
(lpcs->hPalCurrent != GetStockObject(DEFAULT_PALETTE)))
|
||
|
DeleteObject (lpcs->hPalCurrent);
|
||
|
lpcs->hPalCurrent = NULL;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Get the current palette (from the driver)
|
||
|
// Returns: TRUE if the driver can supply a palette
|
||
|
//
|
||
|
|
||
|
BOOL PalGetPaletteFromDriver (LPCAPSTREAM lpcs)
|
||
|
{
|
||
|
FCLOGPALETTE pal;
|
||
|
|
||
|
PalDeleteCurrentPalette (lpcs);
|
||
|
|
||
|
pal.palVersion = 0x0300;
|
||
|
pal.palNumEntries = 256;
|
||
|
|
||
|
lpcs->sCapDrvCaps.fDriverSuppliesPalettes = FALSE; // assume the worst
|
||
|
|
||
|
if (lpcs->fHardwareConnected) {
|
||
|
if (videoConfigure (lpcs->hVideoIn,
|
||
|
DVM_PALETTE,
|
||
|
VIDEO_CONFIGURE_GET | VIDEO_CONFIGURE_CURRENT, NULL,
|
||
|
(LPVOID)&pal, sizeof(pal),
|
||
|
NULL, 0 ) == DV_ERR_OK) {
|
||
|
if (lpcs->hPalCurrent = CreatePalette ((LPLOGPALETTE) &pal))
|
||
|
lpcs->sCapDrvCaps.fDriverSuppliesPalettes = TRUE;
|
||
|
}
|
||
|
}
|
||
|
if (!lpcs->hPalCurrent)
|
||
|
lpcs->hPalCurrent = GetStockObject (DEFAULT_PALETTE);
|
||
|
|
||
|
DibNewPalette (lpcs, lpcs->hPalCurrent);
|
||
|
|
||
|
return (lpcs->sCapDrvCaps.fDriverSuppliesPalettes);
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Set the current palette used for capture by sending a copy to the driver
|
||
|
// and then copying the entries to out DIB.
|
||
|
// This may also be called when reconnecting a driver and using a cached
|
||
|
// copy of the palette.
|
||
|
// Returns TRUE on success, or FALSE on failure.
|
||
|
//
|
||
|
DWORD PalSendPaletteToDriver (LPCAPSTREAM lpcs, HPALETTE hpal, LPBYTE lpXlateTable)
|
||
|
{
|
||
|
short nColors;
|
||
|
FCLOGPALETTE pal;
|
||
|
HCURSOR hOldCursor;
|
||
|
|
||
|
// The following can take a while so repaint our parent
|
||
|
UpdateWindow (GetParent (lpcs-> hwnd));
|
||
|
UpdateWindow (lpcs->hwnd);
|
||
|
|
||
|
if (!hpal)
|
||
|
return FALSE;
|
||
|
|
||
|
// Allocate a xlate table cache?
|
||
|
if (lpXlateTable) {
|
||
|
if (lpcs->lpCacheXlateTable == NULL) {
|
||
|
lpcs->lpCacheXlateTable = GlobalAllocPtr (GHND, 0x8000l);
|
||
|
if (!lpcs->lpCacheXlateTable)
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
// If we're not using the cached table, update the cache
|
||
|
if (lpcs->lpCacheXlateTable != lpXlateTable)
|
||
|
_fmemcpy (lpcs->lpCacheXlateTable, lpXlateTable, (UINT) 0x8000l);
|
||
|
}
|
||
|
else {
|
||
|
FreePaletteCache (lpcs);
|
||
|
}
|
||
|
|
||
|
// Don't destroy the current palette when reconnecting...
|
||
|
if (hpal != lpcs->hPalCurrent) {
|
||
|
PalDeleteCurrentPalette (lpcs);
|
||
|
lpcs->hPalCurrent = hpal;
|
||
|
}
|
||
|
|
||
|
GetObject(hpal, sizeof(short), (LPVOID)&nColors);
|
||
|
|
||
|
if( nColors <= 1 ) { //!!>
|
||
|
return( FALSE );
|
||
|
}
|
||
|
|
||
|
nColors = min(256, nColors);
|
||
|
|
||
|
hOldCursor = SetCursor (lpcs-> hWaitCursor);
|
||
|
|
||
|
statusUpdateStatus (lpcs, IDS_CAP_STAT_PALETTE_BUILD);
|
||
|
|
||
|
pal.palVersion = 0x0300;
|
||
|
pal.palNumEntries = nColors;
|
||
|
|
||
|
GetPaletteEntries(hpal, 0, nColors, pal.palPalEntry);
|
||
|
|
||
|
if (lpcs-> fHardwareConnected) {
|
||
|
|
||
|
// first try to send both the xlate table and the palette
|
||
|
if ((!lpXlateTable) || (videoConfigure( lpcs->hVideoIn,
|
||
|
DVM_PALETTERGB555,
|
||
|
VIDEO_CONFIGURE_SET, NULL,
|
||
|
(LPLOGPALETTE)&pal, sizeof(pal),
|
||
|
lpXlateTable, (DWORD) 0x8000) != 0)) {
|
||
|
|
||
|
// else send just the palette and make the driver build the table
|
||
|
if (videoConfigure( lpcs->hVideoIn,
|
||
|
DVM_PALETTE,
|
||
|
VIDEO_CONFIGURE_SET, NULL,
|
||
|
(LPLOGPALETTE)&pal, sizeof(pal),
|
||
|
NULL, 0 )) {
|
||
|
// Scrncap doesn't support setting a palette, so
|
||
|
// delete the palette cache
|
||
|
FreePaletteCache (lpcs);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Supermac wants us to get the palette again, they might have
|
||
|
// mucked with it!
|
||
|
PalGetPaletteFromDriver (lpcs);
|
||
|
|
||
|
// Since the palette has changed, delete any existing compression
|
||
|
// output format; this forces a new output format to be selected
|
||
|
if (lpcs->CompVars.lpbiOut) {
|
||
|
GlobalFreePtr (lpcs->CompVars.lpbiOut);
|
||
|
lpcs->CompVars.lpbiOut = NULL;
|
||
|
}
|
||
|
if (lpcs->CompVars.hic) {
|
||
|
if (ICSeqCompressFrameStart(&lpcs->CompVars, lpcs->lpBitsInfo) == 0) {
|
||
|
errorUpdateError (lpcs, IDS_CAP_COMPRESSOR_ERROR);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
InvalidateRect (lpcs->hwnd, NULL, TRUE);
|
||
|
UpdateWindow (lpcs->hwnd);
|
||
|
|
||
|
SetCursor (hOldCursor);
|
||
|
statusUpdateStatus (lpcs, 0);
|
||
|
|
||
|
return (TRUE);
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// CopyPalette, makes a copy of a GDI logical palette
|
||
|
// Returns: a handle to the newly created palette, or NULL if error
|
||
|
//
|
||
|
|
||
|
HPALETTE CopyPalette (HPALETTE hpal)
|
||
|
{
|
||
|
LPLOGPALETTE lppal;
|
||
|
short nNumEntries;
|
||
|
|
||
|
if (!hpal)
|
||
|
return NULL;
|
||
|
|
||
|
GetObject (hpal,sizeof(short),(LPVOID)&nNumEntries);
|
||
|
|
||
|
if (nNumEntries == 0)
|
||
|
return NULL;
|
||
|
|
||
|
lppal = (LPLOGPALETTE) GlobalAllocPtr (GHND,
|
||
|
sizeof(LOGPALETTE) + nNumEntries * sizeof(PALETTEENTRY));
|
||
|
|
||
|
if (!lppal)
|
||
|
return NULL;
|
||
|
|
||
|
lppal->palVersion = 0x300;
|
||
|
lppal->palNumEntries = nNumEntries;
|
||
|
|
||
|
GetPaletteEntries(hpal,0,nNumEntries,lppal->palPalEntry);
|
||
|
|
||
|
hpal = CreatePalette(lppal);
|
||
|
|
||
|
GlobalFreePtr (lppal);
|
||
|
|
||
|
return hpal;
|
||
|
}
|
||
|
|
||
|
|
||
|
//
|
||
|
// Allocate resources needed for palette capture
|
||
|
// Returns DV_ERR_OK on success, or DV_ERR... on failure.
|
||
|
// Note: if Init fails, you MUST call the Fini function to
|
||
|
// release resources.
|
||
|
//
|
||
|
DWORD CapturePaletteInit (LPCAPSTREAM lpcs, LPCAPPAL lpcp)
|
||
|
{
|
||
|
DWORD dwError = DV_ERR_OK;
|
||
|
|
||
|
lpcp->lpBits = NULL;
|
||
|
lpcp->lp16to8 = NULL;
|
||
|
lpcp->lpHistogram = NULL;
|
||
|
lpcp->lpbiSave = NULL;
|
||
|
lpcp->wNumFrames = 0;
|
||
|
|
||
|
// Init an RGB16 header
|
||
|
lpcp->bi16.biSize = sizeof(BITMAPINFOHEADER);
|
||
|
lpcp->bi16.biWidth = lpcs->dxBits;
|
||
|
lpcp->bi16.biHeight = lpcs->dyBits;
|
||
|
lpcp->bi16.biPlanes = 1;
|
||
|
lpcp->bi16.biBitCount = 16;
|
||
|
lpcp->bi16.biCompression = BI_RGB;
|
||
|
lpcp->bi16.biSizeImage = DIBWIDTHBYTES(lpcp->bi16) * lpcp->bi16.biHeight;
|
||
|
lpcp->bi16.biXPelsPerMeter= 0;
|
||
|
lpcp->bi16.biYPelsPerMeter= 0;
|
||
|
lpcp->bi16.biClrUsed = 0;
|
||
|
lpcp->bi16.biClrImportant = 0;
|
||
|
|
||
|
// Allocate memory for the histogram, DIB, and XLate table
|
||
|
lpcp->lpBits = GlobalAllocPtr (GHND, lpcp->bi16.biSizeImage);
|
||
|
lpcp->lp16to8 = GlobalAllocPtr (GHND, 0x8000l);
|
||
|
lpcp->lpHistogram = InitHistogram(NULL);
|
||
|
|
||
|
if (!lpcp->lpBits || !lpcp->lp16to8 || !lpcp->lpHistogram) {
|
||
|
dwError = DV_ERR_NOMEM;
|
||
|
goto PalInitError;
|
||
|
}
|
||
|
|
||
|
// Init the video header
|
||
|
lpcp->vHdr.lpData = lpcp->lpBits;
|
||
|
lpcp->vHdr.dwBufferLength = lpcp->bi16.biSizeImage;
|
||
|
lpcp->vHdr.dwUser = 0;
|
||
|
lpcp->vHdr.dwFlags = 0;
|
||
|
|
||
|
// Save the current format
|
||
|
lpcp->lpbiSave = DibGetCurrentFormat (lpcs);
|
||
|
|
||
|
// Make sure we can set the format to 16 bit RGB
|
||
|
if(dwError = videoConfigure( lpcs->hVideoIn, DVM_FORMAT,
|
||
|
VIDEO_CONFIGURE_SET, NULL,
|
||
|
(LPBITMAPINFOHEADER)&lpcp->bi16, sizeof(BITMAPINFOHEADER),
|
||
|
NULL, 0 ) ) {
|
||
|
goto PalInitError;
|
||
|
}
|
||
|
|
||
|
// Put everything back the way it was
|
||
|
if (dwError = videoConfigure( lpcs->hVideoIn, DVM_FORMAT,
|
||
|
VIDEO_CONFIGURE_SET, NULL,
|
||
|
(LPBITMAPINFOHEADER)lpcp->lpbiSave, lpcp->lpbiSave->bmiHeader.biSize,
|
||
|
NULL, 0 )) {
|
||
|
goto PalInitError;
|
||
|
}
|
||
|
|
||
|
PalInitError:
|
||
|
return dwError;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Free resources used for palette capture
|
||
|
//
|
||
|
DWORD CapturePaletteFini (LPCAPSTREAM lpcs, LPCAPPAL lpcp)
|
||
|
{
|
||
|
if (lpcp->lpBits) {
|
||
|
GlobalFreePtr (lpcp->lpBits);
|
||
|
lpcp->lpBits = NULL;
|
||
|
}
|
||
|
if (lpcp->lp16to8) {
|
||
|
GlobalFreePtr (lpcp->lp16to8);
|
||
|
lpcp->lp16to8 = NULL;
|
||
|
}
|
||
|
if (lpcp->lpHistogram) {
|
||
|
FreeHistogram(lpcp->lpHistogram);
|
||
|
lpcp->lpHistogram = NULL;
|
||
|
}
|
||
|
if (lpcp->lpbiSave) {
|
||
|
GlobalFreePtr (lpcp->lpbiSave);
|
||
|
lpcp->lpbiSave = NULL;
|
||
|
}
|
||
|
return DV_ERR_OK;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// CapturePaletteFrames() The workhorse of capture palette.
|
||
|
//
|
||
|
DWORD CapturePaletteFrames (LPCAPSTREAM lpcs, LPCAPPAL lpcp, int nCount)
|
||
|
{
|
||
|
int j;
|
||
|
DWORD dwError;
|
||
|
|
||
|
// switch to RGB16 format
|
||
|
if (dwError = videoConfigure( lpcs->hVideoIn,
|
||
|
DVM_FORMAT,
|
||
|
VIDEO_CONFIGURE_SET, NULL,
|
||
|
(LPBITMAPINFOHEADER)&lpcp->bi16, sizeof(BITMAPINFOHEADER),
|
||
|
NULL, 0 ))
|
||
|
goto CaptureFramesError;
|
||
|
|
||
|
for (j = 0; j < nCount; j++){
|
||
|
// Get a frame
|
||
|
dwError = videoFrame(lpcs->hVideoIn, &lpcp->vHdr);
|
||
|
|
||
|
// Let the user see it
|
||
|
InvalidateRect (lpcs->hwnd, NULL, TRUE);
|
||
|
UpdateWindow (lpcs->hwnd);
|
||
|
|
||
|
// Histogram it
|
||
|
DibHistogram(&lpcp->bi16, lpcp->lpBits, 0, 0, -1, -1, lpcp->lpHistogram);
|
||
|
lpcp->wNumFrames++;
|
||
|
}
|
||
|
|
||
|
dwError = videoConfigure( lpcs->hVideoIn,
|
||
|
DVM_FORMAT,
|
||
|
VIDEO_CONFIGURE_SET, NULL,
|
||
|
(LPBITMAPINFOHEADER)lpcp->lpbiSave,
|
||
|
lpcp->lpbiSave->bmiHeader.biSize,
|
||
|
NULL, 0 );
|
||
|
|
||
|
// videoFrame( lpcs->hVideoIn, &lpcs->VidHdr );
|
||
|
|
||
|
CaptureFramesError:
|
||
|
return dwError;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// CapturePaletteAuto() capture a palette from the video source
|
||
|
// without user intervention.
|
||
|
// Returns TRUE on success, FALSE on error
|
||
|
//
|
||
|
BOOL CapturePaletteAuto (LPCAPSTREAM lpcs, int nCount, int nColors)
|
||
|
{
|
||
|
HPALETTE hpal;
|
||
|
HCURSOR hOldCursor;
|
||
|
DWORD dwError = DV_ERR_OK;
|
||
|
CAPPAL cappal;
|
||
|
LPCAPPAL lpcp;
|
||
|
|
||
|
lpcp = &cappal;
|
||
|
|
||
|
if (!lpcs->sCapDrvCaps.fDriverSuppliesPalettes)
|
||
|
return FALSE;
|
||
|
|
||
|
if (nColors <= 0 || nColors > 256)
|
||
|
return FALSE;
|
||
|
|
||
|
lpcp->wNumColors = max (nColors, 2); // at least 2 colors
|
||
|
|
||
|
if (nCount <= 0)
|
||
|
return FALSE;
|
||
|
|
||
|
if (dwError = CapturePaletteInit (lpcs, lpcp))
|
||
|
goto PalAutoExit;
|
||
|
|
||
|
hOldCursor = SetCursor(lpcs->hWaitCursor);
|
||
|
|
||
|
CapturePaletteFrames (lpcs, lpcp, nCount);
|
||
|
|
||
|
/* we grabbed a frame, time to compute a palette */
|
||
|
statusUpdateStatus(lpcs, IDS_CAP_STAT_OPTPAL_BUILD);
|
||
|
|
||
|
// The HPALETTE returned in the following becomes
|
||
|
// our "global" palette, hence is not deleted here.
|
||
|
hpal = HistogramPalette(lpcp->lpHistogram, lpcp->lp16to8, lpcp->wNumColors);
|
||
|
|
||
|
// Send driver both the pal and xlate table
|
||
|
PalSendPaletteToDriver(lpcs, hpal, (LPBYTE)lpcp->lp16to8 );
|
||
|
|
||
|
videoFrame( lpcs->hVideoIn, &lpcs->VidHdr ); // Update the display with a new image
|
||
|
|
||
|
SetCursor(hOldCursor);
|
||
|
|
||
|
InvalidateRect(lpcs->hwnd, NULL, TRUE);
|
||
|
UpdateWindow(lpcs->hwnd);
|
||
|
lpcs->fUsingDefaultPalette = FALSE;
|
||
|
|
||
|
PalAutoExit:
|
||
|
CapturePaletteFini (lpcs, lpcp);
|
||
|
statusUpdateStatus(lpcs, 0);
|
||
|
|
||
|
// If an error happened, display it
|
||
|
if (dwError)
|
||
|
errorDriverID (lpcs, dwError);
|
||
|
|
||
|
return (dwError == DV_ERR_OK);
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// CapturePaletteManual() capture a palette from the video source
|
||
|
// with user intervention.
|
||
|
// fGrab is TRUE on all but the last frame captured
|
||
|
// Returns TRUE on success, FALSE on error
|
||
|
//
|
||
|
BOOL CapturePaletteManual (LPCAPSTREAM lpcs, BOOL fGrab, int nColors)
|
||
|
{
|
||
|
HPALETTE hpal;
|
||
|
HCURSOR hOldCursor;
|
||
|
LPCAPPAL lpcp;
|
||
|
DWORD dwError = DV_ERR_OK;
|
||
|
|
||
|
if (!lpcs->sCapDrvCaps.fDriverSuppliesPalettes)
|
||
|
return FALSE;
|
||
|
|
||
|
hOldCursor = SetCursor(lpcs->hWaitCursor);
|
||
|
|
||
|
// We're initializing for the first time, so alloc everything
|
||
|
if (lpcs->lpCapPal == NULL) {
|
||
|
|
||
|
if (lpcp = (LPCAPPAL) GlobalAllocPtr (GHND, sizeof(CAPPAL))) {
|
||
|
lpcs->lpCapPal = lpcp;
|
||
|
|
||
|
if (nColors == 0)
|
||
|
nColors = 256;
|
||
|
lpcp->wNumColors = min (nColors, 256);
|
||
|
dwError = CapturePaletteInit (lpcs, lpcp);
|
||
|
}
|
||
|
else
|
||
|
dwError = IDS_CAP_OUTOFMEM;
|
||
|
}
|
||
|
lpcp = lpcs->lpCapPal;
|
||
|
|
||
|
if (dwError != DV_ERR_OK)
|
||
|
goto PalManualExit;
|
||
|
|
||
|
// Add a frame to the histogram
|
||
|
// Handle the case of telling us to stop before we ever started
|
||
|
if (fGrab || !fGrab && (lpcp->wNumFrames == 0)) {
|
||
|
CapturePaletteFrames (lpcs, lpcp, 1);
|
||
|
lpcs->fUsingDefaultPalette = FALSE;
|
||
|
}
|
||
|
// All done, send the new palette to the driver
|
||
|
if (!fGrab) {
|
||
|
statusUpdateStatus(lpcs, IDS_CAP_STAT_OPTPAL_BUILD);
|
||
|
|
||
|
// The HPALETTE returned in the following becomes
|
||
|
// our "global" palette, hence is not deleted here.
|
||
|
hpal = HistogramPalette(lpcp->lpHistogram,
|
||
|
lpcp->lp16to8, lpcp->wNumColors);
|
||
|
|
||
|
// Send driver both the pal and xlate table
|
||
|
PalSendPaletteToDriver(lpcs, hpal, (LPBYTE)lpcp->lp16to8 );
|
||
|
}
|
||
|
|
||
|
videoFrame( lpcs->hVideoIn, &lpcs->VidHdr ); // Update the display with a new image
|
||
|
InvalidateRect(lpcs->hwnd, NULL, TRUE);
|
||
|
UpdateWindow(lpcs->hwnd);
|
||
|
|
||
|
PalManualExit:
|
||
|
if (!fGrab || (dwError != DV_ERR_OK)) {
|
||
|
if (lpcp != NULL) {
|
||
|
CapturePaletteFini (lpcs, lpcp);
|
||
|
GlobalFreePtr (lpcp);
|
||
|
lpcs->lpCapPal = NULL;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
SetCursor(hOldCursor);
|
||
|
statusUpdateStatus(lpcs, 0);
|
||
|
|
||
|
// If an error happened, display it
|
||
|
if (dwError) {
|
||
|
errorUpdateError (lpcs, (UINT) dwError);
|
||
|
}
|
||
|
|
||
|
return (dwError == DV_ERR_OK);
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
/*--------------------------------------------------------------+
|
||
|
| fileSavePalette - save the current palette in a file |
|
||
|
| |
|
||
|
+--------------------------------------------------------------*/
|
||
|
BOOL FAR PASCAL fileSavePalette(LPCAPSTREAM lpcs, LPTSTR lpszFileName)
|
||
|
{
|
||
|
HPALETTE hpal;
|
||
|
HMMIO hmmio;
|
||
|
WORD w;
|
||
|
HCURSOR hOldCursor;
|
||
|
MMCKINFO ckRiff;
|
||
|
MMCKINFO ck;
|
||
|
short nColors;
|
||
|
FCLOGPALETTE pal;
|
||
|
BOOL fOK = FALSE;
|
||
|
|
||
|
if ((hpal = lpcs->hPalCurrent) == NULL)
|
||
|
return FALSE;
|
||
|
|
||
|
hmmio = mmioOpen(lpszFileName, NULL, MMIO_WRITE);
|
||
|
if( !hmmio ) {
|
||
|
/* try and create */
|
||
|
hmmio = mmioOpen(lpszFileName, NULL, MMIO_CREATE | MMIO_WRITE);
|
||
|
if( !hmmio ) {
|
||
|
/* find out if the file was read only or we are just */
|
||
|
/* totally hosed up here. */
|
||
|
hmmio = mmioOpen(lpszFileName, NULL, MMIO_READ);
|
||
|
if (hmmio){
|
||
|
/* file was read only, error on it */
|
||
|
errorUpdateError (lpcs, IDS_CAP_READONLYFILE, (LPTSTR) lpszFileName);
|
||
|
mmioClose(hmmio, 0);
|
||
|
return FALSE;
|
||
|
} else {
|
||
|
/* even weirder error has occured here, give CANTOPEN */
|
||
|
errorUpdateError (lpcs, IDS_CAP_CANTOPEN, (LPTSTR) lpszFileName);
|
||
|
return FALSE;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
hOldCursor = SetCursor( lpcs-> hWaitCursor );
|
||
|
|
||
|
/* Seek to beginning of file, so we can write the header. */
|
||
|
mmioSeek(hmmio, 0, SEEK_SET);
|
||
|
|
||
|
/* Create RIFF chunk */
|
||
|
ckRiff.fccType = mmioFOURCC('P','A','L',' ');
|
||
|
if(mmioCreateChunk (hmmio,&ckRiff,MMIO_CREATERIFF)) {
|
||
|
goto FileError;
|
||
|
}
|
||
|
|
||
|
/* Create Palette chunk */
|
||
|
ck.cksize = 0;
|
||
|
ck.ckid = mmioFOURCC('d','a','t','a');
|
||
|
if(mmioCreateChunk(hmmio,&ck,0)) {
|
||
|
goto FileError;
|
||
|
}
|
||
|
|
||
|
// Get the palette data here
|
||
|
GetObject(hpal, sizeof(short), (LPVOID)&nColors);
|
||
|
|
||
|
pal.palVersion = 0x0300;
|
||
|
pal.palNumEntries = nColors;
|
||
|
|
||
|
GetPaletteEntries(hpal, 0, nColors, pal.palPalEntry);
|
||
|
|
||
|
// Calc the size of the logpalette
|
||
|
// which is the sizeof palVersion + sizeof palNumEntries + colors
|
||
|
w = sizeof (WORD) + sizeof (WORD) + nColors * sizeof (PALETTEENTRY);
|
||
|
|
||
|
// Write out the palette
|
||
|
if(mmioWrite(hmmio, (LPBYTE)&pal, (DWORD) w) != (LONG) w) {
|
||
|
goto FileError;
|
||
|
}
|
||
|
|
||
|
if(mmioAscend(hmmio, &ck, 0)) {
|
||
|
goto FileError;
|
||
|
}
|
||
|
|
||
|
if(mmioAscend(hmmio, &ckRiff, 0)) {
|
||
|
goto FileError;
|
||
|
}
|
||
|
|
||
|
fOK = TRUE;
|
||
|
|
||
|
FileError:
|
||
|
mmioClose( hmmio, 0 );
|
||
|
|
||
|
SetCursor( hOldCursor );
|
||
|
|
||
|
if (!fOK)
|
||
|
errorUpdateError (lpcs, IDS_CAP_ERRORPALSAVE, (LPTSTR) lpszFileName);
|
||
|
|
||
|
return fOK;
|
||
|
}
|
||
|
|
||
|
|
||
|
/*--------------------------------------------------------------+
|
||
|
| fileOpenPalette - use a new palette from the specified file |
|
||
|
| |
|
||
|
+--------------------------------------------------------------*/
|
||
|
BOOL FAR PASCAL fileOpenPalette(LPCAPSTREAM lpcs, LPTSTR lpszFileName)
|
||
|
{
|
||
|
HPALETTE hpal;
|
||
|
HMMIO hmmio;
|
||
|
WORD w;
|
||
|
HCURSOR hOldCursor;
|
||
|
MMCKINFO ckRiff;
|
||
|
MMCKINFO ck;
|
||
|
FCLOGPALETTE pal;
|
||
|
BOOL fOK = FALSE;
|
||
|
|
||
|
if ((hpal = lpcs->hPalCurrent) == NULL)
|
||
|
return FALSE;
|
||
|
|
||
|
hmmio = mmioOpen(lpszFileName, NULL, MMIO_READ);
|
||
|
if( !hmmio ) {
|
||
|
errorUpdateError (lpcs, IDS_CAP_ERRORPALOPEN, (LPTSTR) lpszFileName);
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
hOldCursor = SetCursor( lpcs-> hWaitCursor );
|
||
|
|
||
|
/* Seek to beginning of file, so we can read the header. */
|
||
|
mmioSeek(hmmio, 0, SEEK_SET);
|
||
|
|
||
|
/* Find the RIFF chunk */
|
||
|
ckRiff.fccType = mmioFOURCC('P','A','L',' ');
|
||
|
if(mmioDescend (hmmio, &ckRiff, NULL, MMIO_FINDRIFF)) {
|
||
|
goto PalOpenError;
|
||
|
}
|
||
|
|
||
|
/* Find the data chunk */
|
||
|
ck.cksize = 0;
|
||
|
ck.ckid = mmioFOURCC('d','a','t','a');
|
||
|
if(mmioDescend (hmmio, &ck, &ckRiff, MMIO_FINDCHUNK)) {
|
||
|
goto PalOpenError;
|
||
|
}
|
||
|
|
||
|
// First read just the Version and number of entries
|
||
|
// which is the sizeof palVersion + sizeof palNumEntries
|
||
|
w = sizeof (WORD) + sizeof (WORD);
|
||
|
if(mmioRead(hmmio, (LPBYTE)&pal, (DWORD) w) != (LONG) w) {
|
||
|
goto PalOpenError;
|
||
|
}
|
||
|
|
||
|
// Do a bit of checking
|
||
|
if ((pal.palVersion != 0x0300) || (pal.palNumEntries > 256))
|
||
|
goto PalOpenError;
|
||
|
|
||
|
// Now get the actual palette data
|
||
|
// which is the sizeof palVersion + sizeof palNumEntries
|
||
|
w = pal.palNumEntries * sizeof (PALETTEENTRY);
|
||
|
if(mmioRead(hmmio, (LPBYTE)&pal.palPalEntry, (DWORD) w) != (LONG) w) {
|
||
|
goto PalOpenError;
|
||
|
}
|
||
|
|
||
|
if (hpal = CreatePalette ((LPLOGPALETTE) &pal)) {
|
||
|
PalSendPaletteToDriver (lpcs, hpal, NULL /*lpXlateTable */);
|
||
|
fOK = TRUE;
|
||
|
}
|
||
|
|
||
|
videoFrame( lpcs->hVideoIn, &lpcs->VidHdr ); // grab a new frame
|
||
|
|
||
|
PalOpenError:
|
||
|
mmioClose( hmmio, 0 );
|
||
|
|
||
|
SetCursor( hOldCursor );
|
||
|
InvalidateRect(lpcs->hwnd, NULL, TRUE);
|
||
|
UpdateWindow(lpcs->hwnd); // update the display with new frame
|
||
|
|
||
|
if (!fOK)
|
||
|
errorUpdateError (lpcs, IDS_CAP_ERRORPALOPEN, (LPTSTR) lpszFileName);
|
||
|
else
|
||
|
lpcs->fUsingDefaultPalette = FALSE;
|
||
|
|
||
|
return fOK;
|
||
|
}
|