home *** CD-ROM | disk | FTP | other *** search
- //==========================================================================;
- //
- // 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 - 1996 Microsoft Corporation. All Rights Reserved.
- //
- //--------------------------------------------------------------------------;
- //
- // EZrgb24
- //
- // A Transform filter for simple 24 bit RGB image FX
- //
-
- #include <windows.h>
- #include <streams.h>
-
- #include <initguid.h>
- #include <olectl.h>
- #include <olectlid.h>
-
- #include "EZuids.h"
- #include "iEZ.h"
- #include "EZprop.h"
- #include "EZrgb24.h"
- #include "resource.h"
-
- // setup
-
- AMOVIESETUP_MEDIATYPE sudPinTypes = { &MEDIATYPE_Video // clsMajorType
- , &MEDIASUBTYPE_NULL }; // clsMinorType
-
- AMOVIESETUP_PIN sudpPins [] =
- {
- { L"Input" // strName
- , FALSE // bRendered
- , FALSE // bOutput
- , FALSE // bZero
- , FALSE // bMany
- , &CLSID_NULL // clsConnectsToFilter
- , NULL // strConnectsToPin
- , 1 // nTypes
- , &sudPinTypes // lpTypes
- },
- { L"Output" // strName
- , FALSE // bRendered
- , TRUE // bOutput
- , FALSE // bZero
- , FALSE // bMany
- , &CLSID_NULL // clsConnectsToFilter
- , NULL // strConnectsToPin
- , 1 // nTypes
- , &sudPinTypes // lpTypes
- }
- };
-
-
- AMOVIESETUP_FILTER sudEZrgb24 = { &CLSID_EZrgb24 // clsID
- , L"ImageFX: Easy RGB24" // strName
- , MERIT_DO_NOT_USE // dwMerit
- , 2 // nPins
- , sudpPins }; // lpPin
-
-
-
- // COM Global table of objects in this dll
- CFactoryTemplate g_Templates[] = {
-
- {L"ImageFX: Easy RGB24", &CLSID_EZrgb24, CEZrgb24::CreateInstance},
- {L"Easy RGB24 Property Page", &CLSID_EZrgb24PropertyPage, CEZrgb24Properties::CreateInstance}
- };
- // Count of objects listed in g_cTemplates
- int g_cTemplates = sizeof(g_Templates) / sizeof(g_Templates[0]);
-
-
- // exported entry points for registration and unregistration (in this case they
- // only call through to default implmentations).
- //
-
- HRESULT DllRegisterServer()
- {
- return AMovieDllRegisterServer();
- }
-
- HRESULT DllUnregisterServer()
- {
- return AMovieDllUnregisterServer();
- }
-
-
- //
- // CEZrgb24::Constructor
- //
- CEZrgb24::CEZrgb24(TCHAR *tszName, LPUNKNOWN punk, HRESULT *phr)
- : CTransformFilter(tszName, punk, CLSID_EZrgb24, phr)
- , m_effect(IDC_RED)
- , m_lBufferRequest(1)
- , CPersistStream(punk, phr)
- {
- char sz[60];
- GetProfileStringA("Quartz", "EffectStart", "2.0", sz, 60);
- m_effectStartTime = COARefTime(atof(sz));
- GetProfileStringA("Quartz", "EffectLength", "5.0", sz, 60);
- m_effectTime = COARefTime(atof(sz));
- }
-
-
- //
- // CreateInstance
- //
- // Provide the way for COM to create a EZrgb24 object
- CUnknown *CEZrgb24::CreateInstance(LPUNKNOWN punk, HRESULT *phr) {
-
- CEZrgb24 *pNewObject = new CEZrgb24(NAME("ImageFX: Easy RGB24 Transform"), punk, phr);
- if (pNewObject == NULL) {
- *phr = E_OUTOFMEMORY;
- }
-
- return pNewObject;
-
- }
-
- //
- // GetSetupData
- //
-
- LPAMOVIESETUP_FILTER CEZrgb24::GetSetupData()
- {
- return &sudEZrgb24;
- }
-
-
- //
- // NonDelegatingQueryInterface
- //
- // Reveals IIPEffect & ISpecifyPropertyPages
- STDMETHODIMP CEZrgb24::NonDelegatingQueryInterface(REFIID riid, void ** ppv) {
-
- if (riid == IID_IIPEffect) {
- return GetInterface((IIPEffect *) this, ppv);
- }
- else if (riid == IID_ISpecifyPropertyPages) {
- return GetInterface((ISpecifyPropertyPages *) this, ppv);
- }
- else {
- return CTransformFilter::NonDelegatingQueryInterface(riid, ppv);
- }
- }
-
-
- //
- // Transform
- //
- // Copy the input sample into thee output sample. Then transform
- // the output sample 'in place'.
- HRESULT CEZrgb24::Transform(IMediaSample *pIn, IMediaSample *pOut) {
-
-
- /**********************
- if we have all keyframes, then we shouldn't copy.
- if we have cinepak or indeo and are decompressing frame N, we need to have
- a decompressed frame N-1 available to calculate it, unless we are at a keyframe.
- So with keyframed codecs, you can't get away with applying the transform to
- change the frames in place, because you'll screw up the next frames decompression.
- *************************/
-
-
- HRESULT hr = Copy(pIn, pOut);
- if (FAILED(hr)) {
- return hr;
- }
-
- // check to see if it is time to do the sample.
- CRefTime tStart, tStop ;
- pIn->GetTime((REFERENCE_TIME *) &tStart, (REFERENCE_TIME *) &tStop);
-
- if ((tStart >= m_effectStartTime)
- && (tStop <= (m_effectStartTime+m_effectTime)))
- {
- return Transform(pOut);
- }
- else // not the time to do the effect
- return NOERROR;
- }
-
-
- //
- // Copy
- //
- // make Dest an identical copy of Source
- HRESULT CEZrgb24::Copy(IMediaSample *pSource, IMediaSample *pDest) const {
-
- {
- // Copy the sample data
-
- BYTE *pSourceBuffer, *pDestBuffer;
- long lSourceSize = pSource->GetSize();
- long lDestSize = pDest->GetSize();
-
- ASSERT(lDestSize >= lSourceSize);
-
- pSource->GetPointer(&pSourceBuffer);
- pDest->GetPointer(&pDestBuffer);
-
- CopyMemory( (PVOID) pDestBuffer
- , (PVOID) pSourceBuffer
- , lSourceSize
- );
- }
- {
- // copy the sample time
-
- REFERENCE_TIME TimeStart, TimeEnd;
-
- pSource->GetTime((REFERENCE_TIME *) &TimeStart,
- (REFERENCE_TIME *) &TimeEnd);
- pDest->SetTime(&TimeStart, &TimeEnd);
- }
- {
- // Copy the Sync point property
-
- HRESULT hr = pSource->IsSyncPoint();
- if (hr == S_OK) {
- pDest->SetSyncPoint(TRUE);
- }
- else if (hr == S_FALSE) {
- pDest->SetSyncPoint(FALSE);
- }
- else { // an unexpected error has occured...
- return E_UNEXPECTED;
- }
- }
- {
- // Copy the media type
-
- AM_MEDIA_TYPE *pMediaType;
- pSource->GetMediaType(&pMediaType);
- pDest->SetMediaType(pMediaType);
- DeleteMediaType(pMediaType);
- }
- {
- // Copy the preroll property
-
- HRESULT hr = pSource->IsPreroll();
- if (hr == S_OK) {
- pDest->SetPreroll(TRUE);
- }
- else if (hr == S_FALSE) {
- pDest->SetPreroll(FALSE);
- }
- else { // an unexpected error has occured...
- return E_UNEXPECTED;
- }
- }
- {
- // Copy the discontinuity property
-
- HRESULT hr = pSource->IsDiscontinuity();
- if (hr == S_OK) {
- pDest->SetDiscontinuity(TRUE);
- }
- else if (hr == S_FALSE) {
- pDest->SetDiscontinuity(FALSE);
- }
- else { // an unexpected error has occured...
- return E_UNEXPECTED;
- }
- }
- {
- // Copy the actual data length
-
- long lDataLength = pSource->GetActualDataLength();
- pDest->SetActualDataLength(lDataLength);
- }
-
- return NOERROR;
- }
-
-
- //
- // Transform
- //
- // 'In place' apply Image FX to this sample
- HRESULT CEZrgb24::Transform(IMediaSample *pMediaSample) {
-
- AM_MEDIA_TYPE* pType = &m_pInput->CurrentMediaType();
-
- VIDEOINFO *pvi = (VIDEOINFO *) pType->pbFormat;
-
-
- BYTE *pData;
- long lDataLen;
- unsigned int grey,grey2;
-
- pMediaSample->GetPointer(&pData);
- lDataLen = pMediaSample->GetSize();
-
- int iPixel;
- int iPixelSize = pvi->bmiHeader.biBitCount / 8;
- int cxImage = pvi->bmiHeader.biWidth;
- int cyImage = pvi->bmiHeader.biHeight;
- int cbImage = cyImage * cxImage * iPixelSize;
- int numPixels = pvi->bmiHeader.biWidth * pvi->bmiHeader.biHeight;
- int x,y;
- int temp;
- RGBTRIPLE* prgb;
-
- // CAutoLock lShared(&m_cSharedState);
-
- switch (m_effect)
- {
- case IDC_NONE:
- break ;
- case IDC_RED: // Zero out the green & blue components to leave only the red.
- // For better visual results, compute a greyscale value for the pixel
- // and stuff that into the red component.
- prgb = (RGBTRIPLE*) pData;
- for (iPixel=0; iPixel < numPixels; iPixel++, prgb++)
- {
- prgb->rgbtGreen = 0;
- prgb->rgbtBlue = 0;
- }
- break;
-
- case IDC_GREEN:
- prgb = (RGBTRIPLE*) pData;
- for (iPixel=0; iPixel < numPixels; iPixel++, prgb++)
- {
- prgb->rgbtRed = 0;
- prgb->rgbtBlue = 0;
- }
- break;
-
- case IDC_BLUE:
- prgb = (RGBTRIPLE*) pData;
- for (iPixel=0; iPixel < numPixels; iPixel++, prgb++)
- {
- prgb->rgbtRed = 0;
- prgb->rgbtGreen = 0;
- }
- break;
-
- case IDC_DARKEN: // bitwise shift each component to the right by 2.
- // this results in the image getting much darker.
- prgb = (RGBTRIPLE*) pData;
- for (iPixel=0; iPixel < numPixels; iPixel++, prgb++)
- {
- prgb->rgbtRed = prgb->rgbtRed >> 2;
- prgb->rgbtGreen = prgb->rgbtGreen >> 2;
- prgb->rgbtBlue = prgb->rgbtBlue >> 2;
- }
- break;
-
-
- case IDC_XOR: // Toggle each bit. This gives a sort of X-ray effect.
- prgb = (RGBTRIPLE*) pData;
- for (iPixel=0; iPixel < numPixels; iPixel++, prgb++)
- {
- prgb->rgbtRed = prgb->rgbtRed ^ 0xff;
- prgb->rgbtGreen = prgb->rgbtGreen ^ 0xff;
- prgb->rgbtBlue = prgb->rgbtBlue ^ 0xff;
- }
- break;
-
- case IDC_POSTERIZE: // zero out the 5 LSB per each component
- prgb = (RGBTRIPLE*) pData;
- for (iPixel=0; iPixel < numPixels; iPixel++, prgb++)
- {
- prgb->rgbtRed = prgb->rgbtRed & 0xe0;
- prgb->rgbtGreen = prgb->rgbtGreen & 0xe0;
- prgb->rgbtBlue = prgb->rgbtBlue & 0xe0;
- }
- break;
-
- case IDC_BLUR: // take pixel and its neighbor two pixles to the right.
- // average them.
- // this blurs them and produces a subtle motion effect.
- prgb = (RGBTRIPLE*) pData;
- for (y = 0 ; y < pvi->bmiHeader.biHeight; y++)
- {
- for (x = 2 ; x < pvi->bmiHeader.biWidth; x++,prgb++)
- {
- prgb->rgbtRed = (prgb->rgbtRed + prgb[2].rgbtRed) >> 1;
- prgb->rgbtGreen = (prgb->rgbtGreen + prgb[2].rgbtGreen) >> 1;
- prgb->rgbtBlue = (prgb->rgbtBlue + prgb[2].rgbtBlue) >> 1;
- }
- prgb +=2;
- }
- break;
-
- case IDC_GREY: // An excellent greyscale calculation is:
- // grey = (30 * red + 59 * green + 11 * blue) / 100.
- // This is a bit too slow. A faster calculation is:
- // grey = (red + green) / 2.
- prgb = (RGBTRIPLE*) pData;
- for (iPixel=0; iPixel < numPixels ; iPixel++, prgb++)
- {
- grey = (prgb->rgbtRed + prgb->rgbtGreen) >> 1;
- prgb->rgbtRed = prgb->rgbtGreen = prgb->rgbtBlue = (BYTE) grey;
- }
- break;
-
- case IDC_EMBOSS:// Really sleazy emboss.
- // Rather than using a nice 3x3 convulution matrix,
- // we compare the greyscale values of two neighbors.
- // If they are not different, then a mid grey (128, 128, 128)
- // is supplied. Large differences get father away from the mid grey.
- prgb = (RGBTRIPLE*) pData;
- for (y = 0 ; y < pvi->bmiHeader.biHeight; y++)
- {
- grey2 = (prgb->rgbtRed + prgb->rgbtGreen) >> 1;
- prgb->rgbtRed = prgb->rgbtGreen = prgb->rgbtBlue = (BYTE) 128;
- prgb++;
- for (x = 1 ; x < pvi->bmiHeader.biWidth; x++)
- {
- grey = (prgb->rgbtRed + prgb->rgbtGreen) >> 1;
- temp = grey - grey2;
- if (temp > 127) temp = 127;
- if (temp < -127) temp = -127;
- temp += 128;
- prgb->rgbtRed = prgb->rgbtGreen = prgb->rgbtBlue = (BYTE) temp;
- grey2 = grey;
- prgb++;
- }
- }
- break;
- }
- return NOERROR;
- }
-
-
- //
- // CheckInputType
- //
- // check the input type is OK.
- // return an error otherwise
- HRESULT CEZrgb24::CheckInputType(const CMediaType *mtIn) {
-
- // check this is a VIDEOINFO type
- if (*mtIn->FormatType() != FORMAT_VideoInfo) {
- return E_INVALIDARG;
- }
-
- if (CanPerformEZrgb24(mtIn)) {
- return NOERROR;
- }
- else {
- return E_FAIL;
- }
- }
-
-
- //
- // CheckTransform
- //
- // If these types are OK as input and output (I can transform them
- // and they are the same) return NOERROR. Otherwise return an
- // error code
- HRESULT CEZrgb24::CheckTransform(const CMediaType *mtIn, const CMediaType *mtOut) {
-
- if ( CanPerformEZrgb24(mtIn)
- && (*mtIn == *mtOut)
- ) {
-
- return NOERROR;
- }
- else {
-
- return E_FAIL;
- }
- }
-
-
- //
- // DecideBufferSize
- //
- // Tell the output pin's allocator what size buffers we
- // require. Can only do this when the input is connected
- HRESULT CEZrgb24::DecideBufferSize(IMemAllocator *pAlloc,
- ALLOCATOR_PROPERTIES *pProperties) {
-
- if (!m_pInput->IsConnected()) {
- return E_UNEXPECTED;
- }
- else {
-
- ALLOCATOR_PROPERTIES Request, Actual;
- Request.cBuffers = 1;
- Request.cbBuffer = m_pInput->CurrentMediaType().GetSampleSize();
- Request.cbAlign = 1;
- Request.cbPrefix = 0;
-
- HRESULT hr = pAlloc->SetProperties( &Request, &Actual );
- if (FAILED(hr)) {
- return hr;
- }
-
- if ( (Request.cBuffers > Actual.cBuffers)
- || (Request.cbBuffer > Actual.cbBuffer)
- || (Request.cbAlign != Actual.cbAlign)
- ) {
-
- return E_FAIL;
- }
- }
-
- return NOERROR;
- }
-
-
- //
- // GetMediaType
- //
- // I support 1 type, namely the type of the input pin. This
- // is only available if my input is connected.
- HRESULT CEZrgb24::GetMediaType(int iPosition, CMediaType *pMediaType) {
-
- if (m_pInput->IsConnected()) {
- if (iPosition<0) {
- return E_INVALIDARG;
- }
- if (iPosition>0) {
- return VFW_S_NO_MORE_ITEMS;
- }
-
- *pMediaType = m_pInput->CurrentMediaType();
-
- return NOERROR;
- }
- else {
- return E_UNEXPECTED;
- }
- }
-
- #define WRITEOUT(var) hr = pStream->Write(&var, sizeof(var), NULL); \
- if (FAILED(hr)) return hr;
-
- #define READIN(var) hr = pStream->Read(&var, sizeof(var), NULL); \
- if (FAILED(hr)) return hr;
-
- STDMETHODIMP CEZrgb24::GetClassID(CLSID *pClsid)
- {
- *pClsid = CLSID_EZrgb24;
- return NOERROR;
- }
-
- HRESULT CEZrgb24::ScribbleToStream(IStream *pStream)
- {
- HRESULT hr;
- WRITEOUT(m_effect);
- WRITEOUT(m_effectStartTime);
- WRITEOUT(m_effectTime);
- return NOERROR;
- }
-
-
- HRESULT CEZrgb24::ReadFromStream(IStream *pStream)
- {
- HRESULT hr;
- READIN(m_effect);
- READIN(m_effectStartTime);
- READIN(m_effectTime);
- return NOERROR;
- }
-
-
- //
- // --- ISpecifyPropertyPages ---
- //
-
-
- //
- // GetPages
- //
- // Returns the clsid's of the property pages we support
- STDMETHODIMP CEZrgb24::GetPages(CAUUID *pPages) {
-
- pPages->cElems = 1;
- pPages->pElems = (GUID *) CoTaskMemAlloc(sizeof(GUID));
- if (pPages->pElems == NULL) {
- return E_OUTOFMEMORY;
- }
- *(pPages->pElems) = CLSID_EZrgb24PropertyPage;
-
- return NOERROR;
- }
-
-
- //
- // CanPerformEZrgb24
- //
- // Check if this is a paletised format
- BOOL CEZrgb24::CanPerformEZrgb24(const CMediaType *pMediaType) const {
-
- VIDEOINFO *pvi;
-
-
-
- if ( (IsEqualGUID(*pMediaType->Type(), MEDIATYPE_Video))
- && (IsEqualGUID(*pMediaType->Subtype(), MEDIASUBTYPE_RGB24)) )
- {
- pvi = (VIDEOINFO *) pMediaType->Format();
- return (pvi->bmiHeader.biBitCount == 24); // media type & videoinfo agree
- }
-
- else { // can't process this
- return FALSE;
- }
- }
-
-
- //
- // --- IIPEffect ---
- //
-
-
- //
- // get_IPEffect
- //
- STDMETHODIMP CEZrgb24::get_IPEffect(int *IPEffect, REFTIME *start, REFTIME *length)
- {
-
- CAutoLock l(&m_EZrgb24Lock);
-
- *IPEffect = m_effect;
- *start = COARefTime(m_effectStartTime);
- *length = COARefTime(m_effectTime);
-
- DbgLog((LOG_TRACE, 1, TEXT("get_IPEffect: %d"), *IPEffect));
-
- return NOERROR;
- }
-
-
- //
- // put_IPEffect
- //
- STDMETHODIMP CEZrgb24::put_IPEffect(int IPEffect, REFTIME start, REFTIME length)
- {
-
- CAutoLock l(&m_EZrgb24Lock);
-
- m_effect = IPEffect;
- m_effectStartTime = COARefTime(start);
- m_effectTime = COARefTime(length);
-
- SetDirty(TRUE);
-
- DbgLog((LOG_TRACE, 1, TEXT("put_IPEffect: %d"), m_effect));
-
- return NOERROR;
- }
-
-
-
-