2 * Implements Color Space Converter(CLSID_Colour).
4 * Copyright (C) Hidenori TAKESHIMA <hidenori@a2.ctktv.ne.jp>
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
36 #include "wine/debug.h"
37 WINE_DEFAULT_DEBUG_CHANNEL(quartz);
39 #include "quartz_private.h"
43 static const WCHAR ColorConv_FilterName[] =
44 {'C','o','l','o','r',' ','S','p','a','c','e',' ','C','o','n','v','e','r','t','e','r',0};
48 const GUID* psubtypeIn;
49 const GUID* psubtypeOut;
53 static const struct BltHandler conv_handlers[] =
55 { &MEDIASUBTYPE_RGB24, &MEDIASUBTYPE_RGB32, VIDEOBLT_Blt_888_to_8888 },
56 { &MEDIASUBTYPE_RGB24, &MEDIASUBTYPE_RGB565, VIDEOBLT_Blt_888_to_565 },
57 { &MEDIASUBTYPE_RGB24, &MEDIASUBTYPE_RGB555, VIDEOBLT_Blt_888_to_555 },
58 { &MEDIASUBTYPE_RGB24, &MEDIASUBTYPE_RGB8, VIDEOBLT_Blt_888_to_332 },
62 typedef struct CColorConvImpl
65 AM_MEDIA_TYPE* m_pmtConv;
71 /***************************************************************************
73 * CColorConvImpl methods
77 static void ColorConv_FreeOutTypes(CColorConvImpl* This)
81 if ( This->m_pmtConv == NULL )
84 TRACE("cConv = %lu\n",This->m_cConv);
85 for ( i = 0; i < This->m_cConv; i++ )
87 QUARTZ_MediaType_Free(&This->m_pmtConv[i]);
89 QUARTZ_FreeMem(This->m_pmtConv);
90 This->m_pmtConv = NULL;
94 static HRESULT ColorConv_FillBitmapInfo( BITMAPINFO* pbiOut, LONG biWidth, LONG biHeight, const GUID* psubtype )
100 pbiOut->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
101 pbiOut->bmiHeader.biWidth = biWidth;
102 pbiOut->bmiHeader.biHeight = biHeight;
103 pbiOut->bmiHeader.biPlanes = 1;
105 if ( IsEqualGUID( psubtype, &MEDIASUBTYPE_RGB8 ) )
107 pbiOut->bmiHeader.biBitCount = 8;
108 for ( i = 0; i < 256; i++ )
110 pbiOut->bmiColors[i].rgbRed = ((i>>5)&7)*255/7;
111 pbiOut->bmiColors[i].rgbGreen = ((i>>2)&7)*255/7;
112 pbiOut->bmiColors[i].rgbBlue = (i&3)*255/3;
116 if ( IsEqualGUID( psubtype, &MEDIASUBTYPE_RGB555 ) )
118 pbiOut->bmiHeader.biBitCount = 16;
121 if ( IsEqualGUID( psubtype, &MEDIASUBTYPE_RGB565 ) )
123 pbiOut->bmiHeader.biBitCount = 16;
124 pbiOut->bmiHeader.biCompression = 3;
125 pdwBitf = (DWORD*)(&pbiOut->bmiColors[0]);
131 if ( IsEqualGUID( psubtype, &MEDIASUBTYPE_RGB24 ) )
133 pbiOut->bmiHeader.biBitCount = 24;
136 if ( IsEqualGUID( psubtype, &MEDIASUBTYPE_RGB32 ) )
138 pbiOut->bmiHeader.biBitCount = 32;
142 pbiOut->bmiHeader.biSizeImage = DIBSIZE(pbiOut->bmiHeader);
148 static HRESULT ColorConv_Init( CTransformBaseImpl* pImpl )
150 CColorConvImpl* This = pImpl->m_pUserData;
155 This = (CColorConvImpl*)QUARTZ_AllocMem( sizeof(CColorConvImpl) );
157 return E_OUTOFMEMORY;
158 ZeroMemory( This, sizeof(CColorConvImpl) );
159 pImpl->m_pUserData = This;
162 This->m_pmtConv = NULL;
168 static HRESULT ColorConv_Cleanup( CTransformBaseImpl* pImpl )
170 CColorConvImpl* This = pImpl->m_pUserData;
175 ColorConv_FreeOutTypes(This);
177 QUARTZ_FreeMem( This );
178 pImpl->m_pUserData = NULL;
183 static HRESULT ColorConv_CheckMediaType( CTransformBaseImpl* pImpl, const AM_MEDIA_TYPE* pmtIn, const AM_MEDIA_TYPE* pmtOut )
185 CColorConvImpl* This = pImpl->m_pUserData;
186 BITMAPINFOHEADER* pbiIn = NULL;
187 BITMAPINFOHEADER* pbiOut = NULL;
190 const struct BltHandler* phandler;
192 TRACE("(%p)\n",This);
197 if ( !IsEqualGUID( &pmtIn->majortype, &MEDIATYPE_Video ) )
199 if ( !IsEqualGUID( &pmtIn->formattype, &FORMAT_VideoInfo ) )
201 pbiIn = (&((VIDEOINFOHEADER*)pmtIn->pbFormat)->bmiHeader);
202 if ( pbiIn->biCompression != 0 &&
203 pbiIn->biCompression != 3 )
206 hr = QUARTZ_MediaSubType_FromBitmap( &stIn, pbiIn );
207 if ( hr != S_OK || !IsEqualGUID( &pmtIn->subtype, &stIn ) )
210 if ( pmtOut != NULL )
212 if ( !IsEqualGUID( &pmtOut->majortype, &MEDIATYPE_Video ) )
214 if ( !IsEqualGUID( &pmtOut->formattype, &FORMAT_VideoInfo ) )
216 pbiOut = (&((VIDEOINFOHEADER*)pmtOut->pbFormat)->bmiHeader);
217 if ( pbiOut->biCompression != 0 &&
218 pbiOut->biCompression != 3 )
220 hr = QUARTZ_MediaSubType_FromBitmap( &stOut, pbiOut );
221 if ( hr != S_OK || !IsEqualGUID( &pmtOut->subtype, &stOut ) )
223 if ( pbiIn->biWidth != pbiOut->biWidth ||
224 pbiIn->biHeight != pbiOut->biHeight ||
225 pbiIn->biPlanes != 1 || pbiOut->biPlanes != 1 )
229 phandler = conv_handlers;
230 while ( phandler->psubtypeIn != NULL )
232 if ( IsEqualGUID( &pmtIn->subtype, phandler->psubtypeIn ) )
234 if ( pmtOut == NULL )
236 if ( IsEqualGUID( &pmtOut->subtype, phandler->psubtypeOut ) )
245 static HRESULT ColorConv_GetOutputTypes( CTransformBaseImpl* pImpl, const AM_MEDIA_TYPE* pmtIn, const AM_MEDIA_TYPE** ppmtAcceptTypes, ULONG* pcAcceptTypes )
247 CColorConvImpl* This = pImpl->m_pUserData;
249 const struct BltHandler* phandler;
251 BITMAPINFOHEADER* pbiIn = NULL;
252 BITMAPINFOHEADER* pbiOut = NULL;
254 TRACE("(%p)\n",This);
259 hr = ColorConv_CheckMediaType( pImpl, pmtIn, NULL );
262 pbiIn = (&((VIDEOINFOHEADER*)pmtIn->pbFormat)->bmiHeader);
264 ColorConv_FreeOutTypes(This);
267 phandler = conv_handlers;
268 while ( phandler->psubtypeIn != NULL )
270 if ( IsEqualGUID( &pmtIn->subtype, phandler->psubtypeIn ) )
275 This->m_cConv = cConv;
276 This->m_pmtConv = (AM_MEDIA_TYPE*)QUARTZ_AllocMem(
277 sizeof(AM_MEDIA_TYPE) * cConv );
278 if ( This->m_pmtConv == NULL )
279 return E_OUTOFMEMORY;
280 ZeroMemory( This->m_pmtConv, sizeof(AM_MEDIA_TYPE) * cConv );
283 phandler = conv_handlers;
284 while ( phandler->psubtypeIn != NULL )
286 if ( IsEqualGUID( &pmtIn->subtype, phandler->psubtypeIn ) )
288 memcpy( &This->m_pmtConv[cConv].majortype, &MEDIATYPE_Video, sizeof(GUID) );
289 memcpy( &This->m_pmtConv[cConv].subtype, phandler->psubtypeOut, sizeof(GUID) );
290 This->m_pmtConv[cConv].bFixedSizeSamples = 1;
291 This->m_pmtConv[cConv].bTemporalCompression = 0;
292 This->m_pmtConv[cConv].lSampleSize = DIBSIZE(*pbiIn);
293 memcpy( &This->m_pmtConv[cConv].formattype, &FORMAT_VideoInfo, sizeof(GUID) );
294 This->m_pmtConv[cConv].cbFormat = sizeof(VIDEOINFO);
295 This->m_pmtConv[cConv].pbFormat = (BYTE*)CoTaskMemAlloc( This->m_pmtConv[cConv].cbFormat );
296 if ( This->m_pmtConv[cConv].pbFormat == NULL )
297 return E_OUTOFMEMORY;
298 ZeroMemory( This->m_pmtConv[cConv].pbFormat, This->m_pmtConv[cConv].cbFormat );
299 pbiOut = &(((VIDEOINFOHEADER*)(This->m_pmtConv[cConv].pbFormat))->bmiHeader);
300 hr = ColorConv_FillBitmapInfo( (BITMAPINFO*)pbiOut, pbiIn->biWidth, pbiIn->biHeight, phandler->psubtypeOut );
309 *ppmtAcceptTypes = This->m_pmtConv;
310 *pcAcceptTypes = This->m_cConv;
315 static HRESULT ColorConv_GetAllocProp( CTransformBaseImpl* pImpl, const AM_MEDIA_TYPE* pmtIn, const AM_MEDIA_TYPE* pmtOut, ALLOCATOR_PROPERTIES* pProp, BOOL* pbTransInPlace, BOOL* pbTryToReuseSample )
317 CColorConvImpl* This = pImpl->m_pUserData;
319 BITMAPINFOHEADER* pbiOut = NULL;
321 TRACE("(%p)\n",This);
326 hr = ColorConv_CheckMediaType( pImpl, pmtIn, pmtOut );
330 pbiOut = (&((VIDEOINFOHEADER*)pmtOut->pbFormat)->bmiHeader);
333 pProp->cbBuffer = DIBSIZE(*pbiOut);
334 TRACE("%ldx%ldx%u cbBuffer = %ld\n",pbiOut->biWidth,pbiOut->biHeight,(unsigned)pbiOut->biBitCount,pProp->cbBuffer);
339 static HRESULT ColorConv_BeginTransform( CTransformBaseImpl* pImpl, const AM_MEDIA_TYPE* pmtIn, const AM_MEDIA_TYPE* pmtOut, BOOL bReuseSample )
341 CColorConvImpl* This = pImpl->m_pUserData;
343 BITMAPINFOHEADER* pbiIn = NULL;
344 BITMAPINFOHEADER* pbiOut = NULL;
345 const struct BltHandler* phandler;
347 TRACE("(%p)\n",This);
352 hr = ColorConv_CheckMediaType( pImpl, pmtIn, pmtOut );
356 pbiIn = (&((VIDEOINFOHEADER*)pmtIn->pbFormat)->bmiHeader);
357 pbiOut = (&((VIDEOINFOHEADER*)pmtOut->pbFormat)->bmiHeader);
359 This->pitchIn = DIBWIDTHBYTES(*pbiIn);
360 This->pitchOut = DIBWIDTHBYTES(*pbiOut);
363 phandler = conv_handlers;
364 while ( phandler->psubtypeIn != NULL )
366 if ( IsEqualGUID( &pmtIn->subtype, phandler->psubtypeIn ) )
368 if ( IsEqualGUID( &pmtOut->subtype, phandler->psubtypeOut ) )
370 This->m_pBlt = phandler->pBlt;
380 static HRESULT ColorConv_Transform( CTransformBaseImpl* pImpl, IMediaSample* pSampIn, IMediaSample* pSampOut )
382 CColorConvImpl* This = pImpl->m_pUserData;
383 BYTE* pDataIn = NULL;
384 BYTE* pDataOut = NULL;
392 hr = IMediaSample_GetPointer( pSampIn, &pDataIn );
395 hr = IMediaSample_GetPointer( pSampOut, &pDataOut );
399 if ( This->m_pBlt != NULL )
401 pbiIn = (BITMAPINFO*)&(((VIDEOINFOHEADER*)pImpl->pInPin->pin.pmtConn->pbFormat)->bmiHeader);
402 pbiOut = (BITMAPINFO*)&(((VIDEOINFOHEADER*)pImpl->pOutPin->pin.pmtConn->pbFormat)->bmiHeader);
404 pDataOut, This->pitchOut,
405 pDataIn, This->pitchIn,
406 pbiIn->bmiHeader.biWidth,
407 abs(pbiIn->bmiHeader.biHeight),
408 &pbiIn->bmiColors[0], pbiIn->bmiHeader.biClrUsed );
409 hr = IMediaSample_SetActualDataLength(pSampOut,DIBSIZE(pbiOut->bmiHeader));
417 static HRESULT ColorConv_EndTransform( CTransformBaseImpl* pImpl )
419 CColorConvImpl* This = pImpl->m_pUserData;
430 static const TransformBaseHandlers transhandlers =
434 ColorConv_CheckMediaType,
435 ColorConv_GetOutputTypes,
436 ColorConv_GetAllocProp,
437 ColorConv_BeginTransform,
439 ColorConv_EndTransform,
442 HRESULT QUARTZ_CreateColour(IUnknown* punkOuter,void** ppobj)
444 return QUARTZ_CreateTransformBase(
447 ColorConv_FilterName,