430 lines
11 KiB
C
430 lines
11 KiB
C
|
/****************************************************************************
|
||
|
*
|
||
|
* PALMAP.C
|
||
|
*
|
||
|
* Stream handler to map to a palette.
|
||
|
*
|
||
|
* Copyright (c) 1992 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.
|
||
|
*
|
||
|
***************************************************************************/
|
||
|
|
||
|
#include <windows.h>
|
||
|
#include <windowsx.h>
|
||
|
#include <win32.h>
|
||
|
#include <mmsystem.h>
|
||
|
#include <vfw.h>
|
||
|
#include "dibmap.h"
|
||
|
#include "palmap.h"
|
||
|
|
||
|
|
||
|
LONG FAR PASCAL AVIStreamMakePalette(PAVISTREAM pavi, LONG lSkip,
|
||
|
HPALETTE FAR *lphpal,
|
||
|
LPBYTE lp16to8,
|
||
|
int nColors)
|
||
|
{
|
||
|
LPHISTOGRAM lpHist = NULL;
|
||
|
LONG l, lEnd;
|
||
|
LONG lRet = AVIERR_OK;
|
||
|
PGETFRAME pgf = NULL;
|
||
|
|
||
|
if (!pavi || !lphpal || nColors < 2 || nColors > 256)
|
||
|
return AVIERR_BADPARAM;
|
||
|
|
||
|
if (lSkip < 1)
|
||
|
lSkip = 1;
|
||
|
|
||
|
lpHist = InitHistogram(NULL);
|
||
|
if (!lpHist)
|
||
|
return AVIERR_MEMORY;
|
||
|
|
||
|
pgf = AVIStreamGetFrameOpen(pavi, NULL);
|
||
|
|
||
|
l = AVIStreamStart(pavi);
|
||
|
lEnd = l + AVIStreamLength(pavi);
|
||
|
for (l = AVIStreamStart(pavi), lEnd = l + AVIStreamLength(pavi);
|
||
|
l < lEnd;
|
||
|
l += lSkip) {
|
||
|
LPBITMAPINFOHEADER lpbi;
|
||
|
|
||
|
lpbi = AVIStreamGetFrame(pgf, l);
|
||
|
|
||
|
if (!lpbi) {
|
||
|
lRet = AVIERR_INTERNAL;
|
||
|
goto error;
|
||
|
}
|
||
|
|
||
|
DibHistogram(lpbi, NULL, 0, 0, -1, -1, lpHist);
|
||
|
}
|
||
|
|
||
|
*lphpal = HistogramPalette(lpHist, lp16to8, nColors);
|
||
|
|
||
|
if (!*lphpal)
|
||
|
lRet = AVIERR_MEMORY;
|
||
|
|
||
|
error:
|
||
|
if (pgf)
|
||
|
AVIStreamGetFrameClose(pgf);
|
||
|
|
||
|
if (lpHist)
|
||
|
FreeHistogram(lpHist);
|
||
|
|
||
|
return lRet;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
typedef struct {
|
||
|
IAVIStreamVtbl FAR * lpVtbl;
|
||
|
|
||
|
ULONG ulRefCount;
|
||
|
|
||
|
//
|
||
|
// instance data
|
||
|
//
|
||
|
PAVISTREAM pavi;
|
||
|
PGETFRAME pgf;
|
||
|
AVISTREAMINFO avistream;
|
||
|
HPALETTE hpal;
|
||
|
LPBYTE lp16to8;
|
||
|
LONG lLastFrame;
|
||
|
HANDLE hdibLast;
|
||
|
} PALMAPSTREAM, FAR*PPALMAPSTREAM;
|
||
|
|
||
|
///////////////////////////////////////////////////////////////////////////
|
||
|
///////////////////////////////////////////////////////////////////////////
|
||
|
|
||
|
HRESULT STDMETHODCALLTYPE PalMapStreamQueryInterface(PAVISTREAM ps, REFIID riid, LPVOID FAR* ppvObj);
|
||
|
HRESULT STDMETHODCALLTYPE PalMapStreamCreate (PAVISTREAM ps, LONG lParam1, LONG lParam2);
|
||
|
ULONG STDMETHODCALLTYPE PalMapStreamAddRef (PAVISTREAM ps);
|
||
|
ULONG STDMETHODCALLTYPE PalMapStreamRelease (PAVISTREAM ps);
|
||
|
HRESULT STDMETHODCALLTYPE PalMapStreamInfo (PAVISTREAM ps, AVISTREAMINFO FAR * psi, LONG lSize);
|
||
|
LONG STDMETHODCALLTYPE PalMapStreamFindKeyFrame (PAVISTREAM ps, LONG lPos, LONG lFlags);
|
||
|
HRESULT STDMETHODCALLTYPE PalMapStreamReadFormat (PAVISTREAM ps, LONG lPos, LPVOID lpFormat, LONG FAR *lpcbFormat);
|
||
|
HRESULT STDMETHODCALLTYPE PalMapStreamSetFormat (PAVISTREAM ps, LONG lPos, LPVOID lpFormat, LONG cbFormat);
|
||
|
HRESULT STDMETHODCALLTYPE PalMapStreamRead (PAVISTREAM ps, LONG lStart, LONG lSamples, LPVOID lpBuffer, LONG cbBuffer, LONG FAR * plBytes,LONG FAR * plSamples);
|
||
|
HRESULT STDMETHODCALLTYPE PalMapStreamWrite (PAVISTREAM ps, LONG lStart, LONG lSamples, LPVOID lpBuffer, LONG cbBuffer, DWORD dwFlags, LONG FAR *plSampWritten, LONG FAR *plBytesWritten);
|
||
|
HRESULT STDMETHODCALLTYPE PalMapStreamDelete (PAVISTREAM ps, LONG lStart, LONG lSamples);
|
||
|
HRESULT STDMETHODCALLTYPE PalMapStreamReadData (PAVISTREAM ps, DWORD fcc, LPVOID lp,LONG FAR *lpcb);
|
||
|
HRESULT STDMETHODCALLTYPE PalMapStreamWriteData (PAVISTREAM ps, DWORD fcc, LPVOID lp,LONG cb);
|
||
|
|
||
|
IAVIStreamVtbl PalMapStreamHandler = {
|
||
|
PalMapStreamQueryInterface,
|
||
|
PalMapStreamAddRef,
|
||
|
PalMapStreamRelease,
|
||
|
PalMapStreamCreate,
|
||
|
PalMapStreamInfo,
|
||
|
PalMapStreamFindKeyFrame,
|
||
|
PalMapStreamReadFormat,
|
||
|
PalMapStreamSetFormat,
|
||
|
PalMapStreamRead,
|
||
|
PalMapStreamWrite,
|
||
|
PalMapStreamDelete,
|
||
|
PalMapStreamReadData,
|
||
|
PalMapStreamWriteData
|
||
|
};
|
||
|
|
||
|
LONG FAR PASCAL AVICreateMappedStream(PAVISTREAM FAR *ppsMapped,
|
||
|
PAVISTREAM ps,
|
||
|
int nColors)
|
||
|
{
|
||
|
PPALMAPSTREAM pavi;
|
||
|
|
||
|
pavi = (PPALMAPSTREAM) GlobalAllocPtr(GHND, sizeof(PALMAPSTREAM));
|
||
|
if (pavi == NULL)
|
||
|
return AVIERR_MEMORY;
|
||
|
|
||
|
pavi->lpVtbl = &PalMapStreamHandler;
|
||
|
|
||
|
(pavi->lpVtbl->Create)((PAVISTREAM) pavi, (LONG) ps, nColors);
|
||
|
// !!! error check
|
||
|
|
||
|
*ppsMapped = (PAVISTREAM) pavi;
|
||
|
|
||
|
return AVIERR_OK;
|
||
|
|
||
|
|
||
|
}
|
||
|
|
||
|
///////////////////////////////////////////////////////////////////////////
|
||
|
//
|
||
|
// PalMapStreamOpen()
|
||
|
//
|
||
|
// open a single stream of a particular type from a AVI file.
|
||
|
//
|
||
|
// params:
|
||
|
// szFile - PAVISTREAM
|
||
|
// fccType - must be streamtypeVIDEO
|
||
|
// lParam - nColors
|
||
|
//
|
||
|
// returns:
|
||
|
// a PAVISTREAM for the specifed stream or NULL.
|
||
|
//
|
||
|
///////////////////////////////////////////////////////////////////////////
|
||
|
|
||
|
HRESULT STDMETHODCALLTYPE PalMapStreamCreate(PAVISTREAM ps, LONG lParam1, LONG lParam2)
|
||
|
{
|
||
|
PPALMAPSTREAM pavi = (PPALMAPSTREAM) ps;
|
||
|
|
||
|
LONG lRet = AVIERR_OK;
|
||
|
|
||
|
if (AVIStreamAddRef((PAVISTREAM) lParam1) != AVIERR_OK)
|
||
|
return ResultFromScode(AVIERR_FILEOPEN);
|
||
|
|
||
|
pavi->pavi = (PAVISTREAM) lParam1;
|
||
|
|
||
|
AVIStreamInfo(pavi->pavi, &pavi->avistream, sizeof(pavi->avistream));
|
||
|
|
||
|
if (pavi->avistream.fccType != streamtypeVIDEO) {
|
||
|
lRet = AVIERR_INTERNAL;
|
||
|
goto error;
|
||
|
}
|
||
|
|
||
|
pavi->pgf = AVIStreamGetFrameOpen(pavi->pavi, NULL);
|
||
|
|
||
|
if (!pavi->pgf) {
|
||
|
lRet = AVIERR_INTERNAL;
|
||
|
goto error;
|
||
|
}
|
||
|
|
||
|
pavi->avistream.fccHandler = 0;
|
||
|
|
||
|
if (lParam2 < 2 || lParam2 > 256)
|
||
|
lParam2 = 256;
|
||
|
|
||
|
pavi->lp16to8 = GlobalAllocPtr(GMEM_MOVEABLE, 32768L);
|
||
|
if (!pavi->lp16to8) {
|
||
|
lRet = AVIERR_MEMORY;
|
||
|
goto error;
|
||
|
}
|
||
|
|
||
|
lRet = AVIStreamMakePalette(pavi->pavi,
|
||
|
AVIStreamLength(pavi->pavi) / 30,
|
||
|
&pavi->hpal, pavi->lp16to8,
|
||
|
(int) lParam2);
|
||
|
|
||
|
pavi->lLastFrame = -1;
|
||
|
|
||
|
error:
|
||
|
return ResultFromScode(lRet);
|
||
|
}
|
||
|
|
||
|
///////////////////////////////////////////////////////////////////////////
|
||
|
//
|
||
|
// PalMapStreamAddRef()
|
||
|
//
|
||
|
// increase the reference count of the stream
|
||
|
//
|
||
|
///////////////////////////////////////////////////////////////////////////
|
||
|
|
||
|
ULONG STDMETHODCALLTYPE PalMapStreamAddRef(PAVISTREAM ps)
|
||
|
{
|
||
|
PPALMAPSTREAM pavi = (PPALMAPSTREAM) ps;
|
||
|
|
||
|
return ++pavi->ulRefCount;
|
||
|
}
|
||
|
|
||
|
///////////////////////////////////////////////////////////////////////////
|
||
|
//
|
||
|
// PalMapStreamRelease()
|
||
|
//
|
||
|
// close a PalMapStream stream
|
||
|
//
|
||
|
///////////////////////////////////////////////////////////////////////////
|
||
|
|
||
|
ULONG STDMETHODCALLTYPE PalMapStreamRelease(PAVISTREAM ps)
|
||
|
{
|
||
|
PPALMAPSTREAM pavi = (PPALMAPSTREAM) ps;
|
||
|
|
||
|
if (--pavi->ulRefCount)
|
||
|
return pavi->ulRefCount;
|
||
|
|
||
|
if (pavi->pgf)
|
||
|
AVIStreamGetFrameClose(pavi->pgf);
|
||
|
pavi->pgf = 0;
|
||
|
|
||
|
if (pavi->pavi)
|
||
|
AVIStreamClose(pavi->pavi);
|
||
|
pavi->pavi = 0;
|
||
|
|
||
|
if (pavi->lp16to8) {
|
||
|
GlobalFreePtr(pavi->lp16to8);
|
||
|
pavi->lp16to8 = 0;
|
||
|
}
|
||
|
|
||
|
if (pavi->hpal) {
|
||
|
DeleteObject(pavi->hpal);
|
||
|
pavi->hpal = 0;
|
||
|
}
|
||
|
|
||
|
if (pavi->hdibLast) {
|
||
|
GlobalFree(pavi->hdibLast);
|
||
|
pavi->hdibLast = 0;
|
||
|
}
|
||
|
|
||
|
GlobalFreePtr(pavi);
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
///////////////////////////////////////////////////////////////////////////
|
||
|
///////////////////////////////////////////////////////////////////////////
|
||
|
|
||
|
HRESULT STDMETHODCALLTYPE PalMapStreamReadFormat(PAVISTREAM ps, LONG lPos, LPVOID lpFormat, LONG FAR *lpcbFormat)
|
||
|
{
|
||
|
PPALMAPSTREAM pavi = (PPALMAPSTREAM) ps;
|
||
|
LPBITMAPINFOHEADER lpbi;
|
||
|
LONG lSize;
|
||
|
|
||
|
PalMapStreamRead(ps, lPos, 1, NULL, 0, NULL, NULL);
|
||
|
|
||
|
if (pavi->hdibLast == 0)
|
||
|
return ResultFromScode(AVIERR_INTERNAL);
|
||
|
|
||
|
lpbi = (LPBITMAPINFOHEADER) GlobalLock(pavi->hdibLast);
|
||
|
|
||
|
lSize = lpbi->biSize + lpbi->biClrUsed * sizeof(RGBQUAD);
|
||
|
|
||
|
if (lpFormat)
|
||
|
hmemcpy(lpFormat, lpbi, min(*lpcbFormat, lSize));
|
||
|
|
||
|
*lpcbFormat = lSize;
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
LONG STDMETHODCALLTYPE PalMapStreamFindKeyFrame(PAVISTREAM ps, LONG lPos, LONG lFlags)
|
||
|
{
|
||
|
PPALMAPSTREAM pavi = (PPALMAPSTREAM) ps;
|
||
|
|
||
|
return lPos;
|
||
|
}
|
||
|
|
||
|
|
||
|
///////////////////////////////////////////////////////////////////////////
|
||
|
///////////////////////////////////////////////////////////////////////////
|
||
|
|
||
|
HRESULT STDMETHODCALLTYPE PalMapStreamInfo(PAVISTREAM ps, AVISTREAMINFO FAR * psi, LONG lSize)
|
||
|
{
|
||
|
PPALMAPSTREAM pavi = (PPALMAPSTREAM) ps;
|
||
|
|
||
|
if (psi)
|
||
|
hmemcpy(psi, &pavi->avistream, min(lSize, sizeof(pavi->avistream)));
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
|
||
|
///////////////////////////////////////////////////////////////////////////
|
||
|
///////////////////////////////////////////////////////////////////////////
|
||
|
|
||
|
HRESULT STDMETHODCALLTYPE PalMapStreamRead(PAVISTREAM ps,
|
||
|
LONG lStart,
|
||
|
LONG lSamples,
|
||
|
LPVOID lpBuffer,
|
||
|
LONG cbBuffer,
|
||
|
LONG FAR * plBytes,
|
||
|
LONG FAR * plSamples)
|
||
|
{
|
||
|
PPALMAPSTREAM pavi = (PPALMAPSTREAM) ps;
|
||
|
|
||
|
LPBITMAPINFOHEADER lpbi;
|
||
|
LPVOID lp;
|
||
|
|
||
|
if (lStart != pavi->lLastFrame) {
|
||
|
pavi->lLastFrame = -1;
|
||
|
lpbi = AVIStreamGetFrame(pavi->pgf, lStart);
|
||
|
|
||
|
if (!lpbi)
|
||
|
goto ReadNothing;
|
||
|
|
||
|
if (pavi->hdibLast) {
|
||
|
GlobalFree(pavi->hdibLast);
|
||
|
pavi->hdibLast = 0;
|
||
|
}
|
||
|
|
||
|
pavi->hdibLast = DibReduce(lpbi, NULL, pavi->hpal, pavi->lp16to8);
|
||
|
pavi->lLastFrame = lStart;
|
||
|
}
|
||
|
|
||
|
lpbi = (LPBITMAPINFOHEADER) GlobalLock(pavi->hdibLast);
|
||
|
//
|
||
|
// a NULL buffer means return the size buffer needed to read
|
||
|
// the given sample.
|
||
|
//
|
||
|
lp = (LPBYTE) lpbi + lpbi->biSize + lpbi->biClrUsed * sizeof(RGBQUAD);
|
||
|
|
||
|
if (plBytes)
|
||
|
*plBytes = lpbi->biSizeImage;
|
||
|
|
||
|
if (plSamples)
|
||
|
*plSamples = 1;
|
||
|
|
||
|
if (lpBuffer) {
|
||
|
if (cbBuffer >= (LONG) lpbi->biSizeImage)
|
||
|
hmemcpy(lpBuffer, lp, lpbi->biSizeImage);
|
||
|
else
|
||
|
return ResultFromScode(AVIERR_BUFFERTOOSMALL);
|
||
|
}
|
||
|
|
||
|
return 0;
|
||
|
|
||
|
ReadNothing:
|
||
|
if (plBytes)
|
||
|
*plBytes = 0;
|
||
|
|
||
|
if (plSamples)
|
||
|
*plSamples = 0;
|
||
|
|
||
|
return ResultFromScode(AVIERR_BUFFERTOOSMALL);
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
//
|
||
|
//
|
||
|
// Extra unimplemented functions.....
|
||
|
//
|
||
|
//
|
||
|
//
|
||
|
HRESULT STDMETHODCALLTYPE PalMapStreamQueryInterface(PAVISTREAM ps, REFIID riid, LPVOID FAR* ppvObj)
|
||
|
{
|
||
|
PPALMAPSTREAM pavi = (PPALMAPSTREAM) ps;
|
||
|
return ResultFromScode(AVIERR_UNSUPPORTED);
|
||
|
}
|
||
|
|
||
|
HRESULT STDMETHODCALLTYPE PalMapStreamReadData (PAVISTREAM ps, DWORD fcc, LPVOID lp, LONG FAR *lpcb)
|
||
|
{
|
||
|
PPALMAPSTREAM pavi = (PPALMAPSTREAM) ps;
|
||
|
return ResultFromScode(AVIERR_UNSUPPORTED);
|
||
|
}
|
||
|
|
||
|
HRESULT STDMETHODCALLTYPE PalMapStreamSetFormat (PAVISTREAM ps, LONG lPos, LPVOID lpFormat, LONG cbFormat)
|
||
|
{
|
||
|
PPALMAPSTREAM pavi = (PPALMAPSTREAM) ps;
|
||
|
return ResultFromScode(AVIERR_UNSUPPORTED);
|
||
|
}
|
||
|
|
||
|
HRESULT STDMETHODCALLTYPE PalMapStreamWriteData (PAVISTREAM ps, DWORD fcc, LPVOID lp, LONG cb)
|
||
|
{
|
||
|
PPALMAPSTREAM pavi = (PPALMAPSTREAM) ps;
|
||
|
return ResultFromScode(AVIERR_UNSUPPORTED);
|
||
|
}
|
||
|
|
||
|
HRESULT STDMETHODCALLTYPE PalMapStreamWrite (PAVISTREAM ps, LONG lStart, LONG lSamples, LPVOID lpBuffer, LONG cbBuffer, DWORD dwFlags, LONG FAR *plSampWritten, LONG FAR *plBytesWritten)
|
||
|
{
|
||
|
PPALMAPSTREAM pavi = (PPALMAPSTREAM) ps;
|
||
|
return ResultFromScode(AVIERR_UNSUPPORTED);
|
||
|
}
|
||
|
|
||
|
HRESULT STDMETHODCALLTYPE PalMapStreamDelete (PAVISTREAM ps, LONG lStart, LONG lSamples)
|
||
|
{
|
||
|
PPALMAPSTREAM pavi = (PPALMAPSTREAM) ps;
|
||
|
return ResultFromScode(AVIERR_UNSUPPORTED);
|
||
|
}
|