00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include "StdAfx.h"
00023 #include "Shareaza.h"
00024 #include "Plugins.h"
00025 #include "ImageServices.h"
00026 #include "ImageFile.h"
00027 #include "ImageServiceBitmap.h"
00028
00029 #ifdef _DEBUG
00030 #define new DEBUG_NEW
00031 #undef THIS_FILE
00032 static char THIS_FILE[] = __FILE__;
00033 #endif
00034
00035 IMPLEMENT_DYNAMIC(CImageServices, CComObject)
00036
00037 LPCTSTR RT_JPEG = _T("JPEG");
00038 LPCTSTR RT_PNG = _T("PNG");
00039
00040
00042
00043
00044 CImageServices::CImageServices()
00045 {
00046 m_bCOM = GetCurrentThreadId() == AfxGetApp()->m_nThreadID;
00047 }
00048
00049 CImageServices::~CImageServices()
00050 {
00051 Cleanup();
00052 }
00053
00055
00056
00057 BOOL CImageServices::LoadFromMemory(CImageFile* pFile, LPCTSTR pszType, LPCVOID pData, DWORD nLength, BOOL bScanOnly, BOOL bPartialOk)
00058 {
00059 IImageServicePlugin* pService = GetService( pszType );
00060 if ( pService == NULL ) return FALSE;
00061
00062 IMAGESERVICEDATA pParams;
00063 ZeroMemory( &pParams, sizeof(pParams) );
00064
00065 pParams.cbSize = sizeof(pParams);
00066 pParams.nComponents = 3;
00067
00068 if ( bScanOnly ) pParams.nFlags |= IMAGESERVICE_SCANONLY;
00069 if ( bPartialOk ) pParams.nFlags |= IMAGESERVICE_PARTIAL_IN;
00070
00071 SAFEARRAY* pInput;
00072 LPBYTE pTarget;
00073
00074 if ( FAILED( SafeArrayAllocDescriptor( 1, &pInput ) ) || pInput == NULL ) return FALSE;
00075
00076 pInput->cbElements = 1;
00077 pInput->rgsabound[ 0 ].lLbound = 0;
00078 pInput->rgsabound[ 0 ].cElements = nLength;
00079 SafeArrayAllocData( pInput );
00080
00081 if ( FAILED( SafeArrayAccessData( pInput, (void HUGEP* FAR*)&pTarget ) ) ) return FALSE;
00082
00083 CopyMemory( pTarget, pData, nLength );
00084 SafeArrayUnaccessData( pInput );
00085
00086 SAFEARRAY* pArray = NULL;
00087 HINSTANCE hRes = AfxGetResourceHandle();
00088 BOOL bSuccess = SUCCEEDED( pService->LoadFromMemory( pInput, &pParams, &pArray ) );
00089 AfxSetResourceHandle( hRes );
00090
00091 SafeArrayDestroy( pInput );
00092
00093 return PostLoad( pFile, &pParams, pArray, bSuccess );
00094 }
00095
00096 const CLSID CLSID_AVIThumb = { 0x4956C5F5, 0xD9A8, 0x4CBB, { 0x89, 0x94, 0xF5, 0x3C, 0xF5, 0x5C, 0xFD, 0xF5 } };
00097
00098 BOOL CImageServices::LoadFromFile(CImageFile* pFile, LPCTSTR pszType, HANDLE hFile, DWORD nLength, BOOL bScanOnly, BOOL bPartialOk)
00099 {
00100 CLSID* pCLSID = NULL;
00101 IImageServicePlugin* pService = GetService( pszType, &pCLSID );
00102 if ( pService == NULL ) return FALSE;
00103
00104 IMAGESERVICEDATA pParams;
00105 ZeroMemory( &pParams, sizeof(pParams) );
00106
00107 pParams.cbSize = sizeof(pParams);
00108 pParams.nComponents = 3;
00109
00110 if ( bScanOnly ) pParams.nFlags |= IMAGESERVICE_SCANONLY;
00111 if ( bPartialOk ) pParams.nFlags |= IMAGESERVICE_PARTIAL_IN;
00112
00113 SAFEARRAY* pArray = NULL;
00114 HINSTANCE hRes = AfxGetResourceHandle();
00115 HRESULT hr = E_FAIL;
00116
00117 if ( pCLSID != NULL && *pCLSID == CLSID_AVIThumb && *pszType != '.' )
00118 {
00119 USES_CONVERSION;
00120 LPCSTR pszASCII = T2CA(pszType);
00121 hr = pService->LoadFromFile( (HANDLE)pszASCII, 0xFEFEFEFE, &pParams, &pArray );
00122 }
00123 else
00124 {
00125 hr = pService->LoadFromFile( hFile, nLength, &pParams, &pArray );
00126 }
00127
00128 AfxSetResourceHandle( hRes );
00129
00130 if ( hr != E_NOTIMPL ) return PostLoad( pFile, &pParams, pArray, SUCCEEDED( hr ) );
00131
00132 pFile->Clear();
00133 if ( pArray != NULL ) SafeArrayDestroy( pArray );
00134
00135 HANDLE hMap = CreateFileMapping( hFile, NULL, PAGE_READONLY, 0, 0, NULL );
00136 if ( hMap == INVALID_HANDLE_VALUE ) return FALSE;
00137
00138 DWORD nPosition = SetFilePointer( hFile, 0, NULL, FILE_CURRENT );
00139 BOOL bMapped = FALSE;
00140
00141 if ( LPCVOID pBuffer = MapViewOfFile( hMap, FILE_MAP_READ, 0, nPosition, nLength ) )
00142 {
00143 bMapped = LoadFromMemory( pFile, pszType, pBuffer, nLength, bScanOnly, bPartialOk );
00144 UnmapViewOfFile( pBuffer );
00145 }
00146
00147 CloseHandle( hMap );
00148
00149 return bMapped;
00150 }
00151
00153
00154
00155 BOOL CImageServices::PostLoad(CImageFile* pFile, IMAGESERVICEDATA* pParams, SAFEARRAY* pArray, BOOL bSuccess)
00156 {
00157 pFile->Clear();
00158
00159 if ( ! bSuccess )
00160 {
00161 if ( pArray != NULL ) SafeArrayDestroy( pArray );
00162 return FALSE;
00163 }
00164
00165 pFile->m_bScanned = TRUE;
00166 pFile->m_nWidth = pParams->nWidth;
00167 pFile->m_nHeight = pParams->nHeight;
00168 pFile->m_nComponents = pParams->nComponents;
00169
00170 if ( pArray == NULL ) return TRUE;
00171
00172 pFile->m_bLoaded = TRUE;
00173
00174 LONG nArray = 0;
00175 SafeArrayGetUBound( pArray, 1, &nArray );
00176 nArray++;
00177
00178 LONG nFullSize = pParams->nWidth * pParams->nComponents;
00179 while ( nFullSize & 3 ) nFullSize++;
00180 nFullSize *= pParams->nHeight;
00181
00182 if ( nArray != nFullSize )
00183 {
00184 SafeArrayDestroy( pArray );
00185 return FALSE;
00186 }
00187
00188 pFile->m_pImage = new BYTE[ nArray ];
00189
00190 LPBYTE pData;
00191 SafeArrayAccessData( pArray, (VOID**)&pData );
00192 CopyMemory( pFile->m_pImage, pData, nArray );
00193 SafeArrayUnaccessData( pArray );
00194 SafeArrayDestroy( pArray );
00195
00196 return TRUE;
00197 }
00198
00200
00201
00202 BOOL CImageServices::SaveToMemory(CImageFile* pFile, LPCTSTR pszType, int nQuality, LPBYTE* ppBuffer, DWORD* pnLength)
00203 {
00204 *ppBuffer = NULL;
00205 *pnLength = 0;
00206
00207 IImageServicePlugin* pService = GetService( pszType );
00208 if ( pService == NULL ) return FALSE;
00209
00210 SAFEARRAY* pSource = ImageToArray( pFile );
00211 if ( pSource == NULL ) return FALSE;
00212
00213 IMAGESERVICEDATA pParams;
00214 ZeroMemory( &pParams, sizeof(pParams) );
00215
00216 pParams.cbSize = sizeof(pParams);
00217 pParams.nWidth = pFile->m_nWidth;
00218 pParams.nHeight = pFile->m_nHeight;
00219 pParams.nComponents = pFile->m_nComponents;
00220 pParams.nQuality = nQuality;
00221
00222 SAFEARRAY* pOutput = NULL;
00223 HINSTANCE hRes = AfxGetResourceHandle();
00224 BOOL bSuccess = SUCCEEDED( pService->SaveToMemory( &pOutput, &pParams, pSource ) );
00225 AfxSetResourceHandle( hRes );
00226
00227 SafeArrayDestroy( pSource );
00228
00229 if ( pOutput == NULL ) return FALSE;
00230
00231 SafeArrayGetUBound( pOutput, 1, (PLONG)pnLength );
00232 (*pnLength)++;
00233
00234 LPBYTE pEncoded;
00235 SafeArrayAccessData( pOutput, (VOID**)&pEncoded );
00236
00237 *ppBuffer = new BYTE[ *pnLength ];
00238 CopyMemory( *ppBuffer, pEncoded, *pnLength );
00239
00240 SafeArrayUnaccessData( pOutput );
00241 SafeArrayDestroy( pOutput );
00242
00243 return TRUE;
00244 }
00245
00246 BOOL CImageServices::SaveToFile(CImageFile* pFile, LPCTSTR pszType, int nQuality, HANDLE hFile, DWORD* pnLength)
00247 {
00248 if ( pnLength ) *pnLength = 0;
00249
00250 IImageServicePlugin* pService = GetService( pszType );
00251 if ( pService == NULL ) return FALSE;
00252
00253 SAFEARRAY* pSource = ImageToArray( pFile );
00254 if ( pSource == NULL ) return FALSE;
00255
00256 IMAGESERVICEDATA pParams;
00257 ZeroMemory( &pParams, sizeof(pParams) );
00258
00259 pParams.cbSize = sizeof(pParams);
00260 pParams.nWidth = pFile->m_nWidth;
00261 pParams.nHeight = pFile->m_nHeight;
00262 pParams.nComponents = pFile->m_nComponents;
00263 pParams.nQuality = nQuality;
00264
00265 DWORD nBefore = SetFilePointer( hFile, 0, NULL, FILE_CURRENT );
00266
00267 HINSTANCE hRes = AfxGetResourceHandle();
00268 BOOL bSuccess = SUCCEEDED( pService->SaveToFile( hFile, &pParams, pSource ) );
00269 AfxSetResourceHandle( hRes );
00270
00271 SafeArrayDestroy( pSource );
00272
00273 if ( pnLength )
00274 {
00275 DWORD nAfter = SetFilePointer( hFile, 0, NULL, FILE_CURRENT );
00276 *pnLength = nAfter - nBefore;
00277 }
00278
00279 return bSuccess;
00280 }
00281
00283
00284
00285 SAFEARRAY* CImageServices::ImageToArray(CImageFile* pFile)
00286 {
00287 SAFEARRAY* pOutput;
00288
00289 if ( FAILED( SafeArrayAllocDescriptor( 1, &pOutput ) ) || pOutput == NULL ) return NULL;
00290
00291 DWORD nLength = pFile->m_nWidth * pFile->m_nComponents;
00292 while ( nLength & 3 ) nLength ++;
00293 nLength *= pFile->m_nHeight;
00294
00295 pOutput->cbElements = 1;
00296 pOutput->rgsabound[ 0 ].lLbound = 0;
00297 pOutput->rgsabound[ 0 ].cElements = nLength;
00298
00299 if ( FAILED( SafeArrayAllocData( pOutput ) ) ) return NULL;
00300
00301 LPBYTE pTarget;
00302 if ( FAILED( SafeArrayAccessData( pOutput, (void HUGEP* FAR*)&pTarget ) ) ) return NULL;
00303
00304 CopyMemory( pTarget, pFile->m_pImage, nLength );
00305
00306 SafeArrayUnaccessData( pOutput );
00307
00308 return pOutput;
00309 }
00310
00312
00313
00314 IImageServicePlugin* CImageServices::GetService(LPCTSTR pszFile, CLSID** ppCLSID)
00315 {
00316 LPCTSTR pszType = _tcsrchr( pszFile, '.' );
00317 if ( pszType == NULL ) return NULL;
00318
00319 IImageServicePlugin* pService = NULL;
00320 CString strType( pszType );
00321 CharLower( strType.GetBuffer() );
00322 strType.ReleaseBuffer();
00323
00324 if ( m_pService.Lookup( strType, (void*&)pService ) )
00325 {
00326 if ( pService != NULL && ppCLSID != NULL )
00327 {
00328 m_pCLSID.Lookup( strType, (void*&)*ppCLSID );
00329 }
00330
00331 return pService;
00332 }
00333 else
00334 {
00335 CLSID pCLSID = { 0 };
00336
00337 pService = LoadService( strType, &pCLSID );
00338 m_pService.SetAt( strType, pService );
00339
00340 if ( pService != NULL )
00341 {
00342 CLSID* pCopy = new CLSID;
00343 *pCopy = pCLSID;
00344 delete m_pCLSID[ strType ];
00345 m_pCLSID[ strType ] = pCopy;
00346 if ( ppCLSID != NULL ) *ppCLSID = pCopy;
00347 }
00348
00349 return pService;
00350 }
00351 }
00352
00353 IImageServicePlugin* CImageServices::LoadService(LPCTSTR pszType, CLSID* ppCLSID)
00354 {
00355 IImageServicePlugin* pService = NULL;
00356
00357 DWORD dwContext = 0;
00358 if ( _tcscmp( pszType, _T(".bmp") ) == 0 )
00359 {
00360 return CBitmapImageService::Create();
00361 }
00362 else if ( _tcscmp( pszType, _T(".avi") ) == 0 )
00363 {
00364 dwContext = CLSCTX_NO_CUSTOM_MARSHAL;
00365 }
00366
00367 CLSID pCLSID;
00368
00369 if ( ! Plugins.LookupCLSID( _T("ImageService"), pszType, pCLSID ) ) return NULL;
00370
00371 if ( ppCLSID != NULL ) *ppCLSID = pCLSID;
00372
00373 if ( ! m_bCOM )
00374 {
00375 if ( FAILED( CoInitializeEx( NULL, COINIT_MULTITHREADED ) ) ) return NULL;
00376 m_bCOM = TRUE;
00377 }
00378
00379 HINSTANCE hRes = AfxGetResourceHandle();
00380 HRESULT hResult = CoCreateInstance( pCLSID, NULL, CLSCTX_INPROC_SERVER|dwContext,
00381 IID_IImageServicePlugin, (void**)&pService );
00382 AfxSetResourceHandle( hRes );
00383
00384 if ( FAILED( hResult ) )
00385 {
00386
00387 return NULL;
00388 }
00389
00390 return pService;
00391 }
00392
00394
00395
00396 void CImageServices::Cleanup()
00397 {
00398 CString strType;
00399 POSITION pos;
00400
00401 for ( pos = m_pService.GetStartPosition() ; pos ; )
00402 {
00403 IImageServicePlugin* pService = NULL;
00404 m_pService.GetNextAssoc( pos, strType, (void*&)pService );
00405 if ( pService != NULL ) pService->Release();
00406 }
00407
00408 m_pService.RemoveAll();
00409
00410 for ( pos = m_pCLSID.GetStartPosition() ; pos ; )
00411 {
00412 CLSID* pCLSID = NULL;
00413 m_pCLSID.GetNextAssoc( pos, strType, (void*&)pCLSID );
00414 if ( pCLSID != NULL ) delete pCLSID;
00415 }
00416
00417 m_pCLSID.RemoveAll();
00418
00419 if ( m_bCOM && ( GetCurrentThreadId() != AfxGetApp()->m_nThreadID ) )
00420 {
00421 m_bCOM = FALSE;
00422 CoUninitialize();
00423 }
00424 }
00425
00427
00428
00429 BOOL CImageServices::LoadBitmap(CBitmap* pBitmap, UINT nResourceID, LPCTSTR pszType)
00430 {
00431 if ( pBitmap->m_hObject == NULL ) pBitmap->DeleteObject();
00432
00433 CImageServices pService;
00434 CImageFile pFile( &pService );
00435 if ( ! pFile.LoadFromResource( AfxGetResourceHandle(), nResourceID, pszType ) ) return FALSE;
00436 if ( ! pFile.EnsureRGB() ) return FALSE;
00437 pBitmap->Attach( pFile.CreateBitmap() );
00438
00439 return TRUE;
00440 }