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 "ImageServices.h"
00025
00026 #ifdef _DEBUG
00027 #define new DEBUG_NEW
00028 #undef THIS_FILE
00029 static char THIS_FILE[] = __FILE__;
00030 #endif
00031
00032
00033 #if __INTEL_COMPILER > 0
00034 #define asm_m_nWidth CImageFile.m_nWidth
00035 #else
00036 #define asm_m_nWidth CImageFile::m_nWidth
00037 #endif
00038
00039 IMPLEMENT_DYNAMIC(CImageFile, CComObject)
00040
00041
00042
00043
00044
00045 CImageFile::CImageFile(CImageServices* pService)
00046 {
00047 m_pService = pService;
00048 m_bScanned = FALSE;
00049 m_nWidth = 0;
00050 m_nHeight = 0;
00051 m_nComponents = 0;
00052 m_bLoaded = FALSE;
00053 m_pImage = NULL;
00054 }
00055
00056 CImageFile::~CImageFile()
00057 {
00058 Clear();
00059 }
00060
00062
00063
00064 void CImageFile::Clear()
00065 {
00066 if ( m_bLoaded ) delete [] m_pImage;
00067
00068 m_bScanned = FALSE;
00069 m_nWidth = 0;
00070 m_nHeight = 0;
00071 m_nComponents = 0;
00072 m_bLoaded = FALSE;
00073 m_pImage = NULL;
00074 }
00075
00077
00078
00079 BOOL CImageFile::LoadFromMemory(LPCTSTR pszType, LPCVOID pData, DWORD nLength, BOOL bScanOnly, BOOL bPartialOk)
00080 {
00081 return m_pService->LoadFromMemory( this, pszType, pData, nLength, bScanOnly, bPartialOk );
00082 }
00083
00084 BOOL CImageFile::LoadFromFile(LPCTSTR pszType, HANDLE hFile, DWORD nLength, BOOL bScanOnly, BOOL bPartialOk)
00085 {
00086 return m_pService->LoadFromFile( this, pszType, hFile, nLength, bScanOnly, bPartialOk );
00087 }
00088
00089 BOOL CImageFile::LoadFromFile(LPCTSTR pszFile, BOOL bScanOnly, BOOL bPartialOk)
00090 {
00091 HANDLE hFile = CreateFile( pszFile, GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE,
00092 NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL );
00093
00094 if ( hFile == INVALID_HANDLE_VALUE ) return FALSE;
00095
00096 BOOL bResult = m_pService->LoadFromFile( this, pszFile, hFile, GetFileSize( hFile, NULL ), bScanOnly, bPartialOk );
00097
00098 CloseHandle( hFile );
00099
00100 return bResult;
00101 }
00102
00103 BOOL CImageFile::LoadFromResource(HINSTANCE hInstance, UINT nResourceID, LPCTSTR pszType, BOOL bScanOnly, BOOL bPartialOk)
00104 {
00105 HMODULE hModule = (HMODULE)hInstance;
00106 HRSRC hRes = FindResource( hModule, MAKEINTRESOURCE( nResourceID ), pszType );
00107
00108 if ( hRes == NULL ) return FALSE;
00109
00110 DWORD nSize = SizeofResource( hModule, hRes );
00111 HGLOBAL hMemory = ::LoadResource( hModule, hRes );
00112 LPCVOID pMemory = (LPCVOID)LockResource( hMemory );
00113 CString strType;
00114
00115 if ( pszType == RT_BITMAP || _tcscmp( pszType, _T("BMP") ) == 0 )
00116 {
00117 pszType = _T(".bmp");
00118 }
00119 else if ( _tcscmp( pszType, RT_JPEG ) == 0 )
00120 {
00121 pszType = _T(".jpg");
00122 }
00123 else if ( _tcscmp( pszType, RT_PNG ) == 0 )
00124 {
00125 pszType = _T(".png");
00126 }
00127 else
00128 {
00129 strType.Format( _T(".%s"), pszType );
00130 pszType = strType;
00131 }
00132
00133 return m_pService->LoadFromMemory( this, pszType, pMemory, nSize, bScanOnly, bPartialOk );
00134 }
00135
00137
00138
00139 BOOL CImageFile::SaveToMemory(LPCTSTR pszType, int nQuality, LPBYTE* ppBuffer, DWORD* pnLength)
00140 {
00141 return m_pService->SaveToMemory( this, pszType, nQuality, ppBuffer, pnLength );
00142 }
00143
00144 BOOL CImageFile::SaveToFile(LPCTSTR pszType, int nQuality, HANDLE hFile, DWORD* pnLength)
00145 {
00146 return m_pService->SaveToFile( this, pszType, nQuality, hFile, pnLength );
00147 }
00148
00149 BOOL CImageFile::SaveToFile(LPCTSTR pszFile, int nQuality)
00150 {
00151 HANDLE hFile = CreateFile( pszFile, GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE,
00152 NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL );
00153
00154 if ( hFile == INVALID_HANDLE_VALUE ) return FALSE;
00155
00156 BOOL bResult = m_pService->SaveToFile( this, pszFile, nQuality, hFile );
00157
00158 CloseHandle( hFile );
00159
00160 if ( ! bResult ) DeleteFile( pszFile );
00161
00162 return bResult;
00163 }
00164
00166
00167
00168 DWORD CImageFile::GetSerialSize() const
00169 {
00170
00171
00172
00173
00174
00175 if ( ! m_bLoaded ) return 4;
00176 return 12 + ( ( ( ( m_nWidth * m_nComponents ) + 3 ) & (-4) ) * m_nHeight );
00177 }
00178
00179 void CImageFile::Serialize(CArchive& ar)
00180 {
00181 if ( ar.IsStoring() )
00182 {
00183 if ( ! m_bLoaded )
00184 {
00185 ar << m_bLoaded;
00186 return;
00187 }
00188
00189 ar << m_nWidth;
00190 ar << m_nHeight;
00191 ar << m_nComponents;
00192
00193
00194
00195
00196
00197
00198 ar.Write( m_pImage, ( ( ( m_nWidth * m_nComponents ) + 3) & (-4) ) * m_nHeight );
00199 }
00200 else
00201 {
00202 Clear();
00203
00204 ar >> m_nWidth;
00205 if ( m_nWidth == 0 ) return;
00206 ar >> m_nHeight;
00207 ar >> m_nComponents;
00208
00209
00210
00211
00212
00213
00214
00215 int nPitch = ( ( ( m_nWidth * m_nComponents )+ 3 ) & (-4) ) * m_nHeight;
00216
00217 m_pImage = new BYTE[ nPitch ];
00218 ar.Read( m_pImage, nPitch );
00219
00220 m_bLoaded = TRUE;
00221 }
00222 }
00223
00225
00226
00227 HBITMAP CImageFile::CreateBitmap(HDC hUseDC)
00228 {
00229 if ( ! m_bLoaded ) return NULL;
00230 if ( m_nComponents != 3 ) return NULL;
00231
00232 BITMAPINFO pInfo;
00233 ZeroMemory( &pInfo, sizeof(pInfo) );
00234
00235 pInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
00236 pInfo.bmiHeader.biWidth = (LONG)m_nWidth;
00237 pInfo.bmiHeader.biHeight = (LONG)m_nHeight;
00238 pInfo.bmiHeader.biPlanes = 1;
00239 pInfo.bmiHeader.biBitCount = 24;
00240 pInfo.bmiHeader.biCompression = BI_RGB;
00241 pInfo.bmiHeader.biSizeImage = m_nWidth * m_nHeight * 3;
00242
00243 HDC hDC = hUseDC ? hUseDC : GetDC( 0 );
00244
00245 HBITMAP hBitmap = CreateDIBitmap( hDC, &pInfo.bmiHeader, 0, NULL, &pInfo, DIB_RGB_COLORS );
00246
00247 if ( hBitmap )
00248 {
00249 DWORD nPitch = m_nWidth * 3;
00250 BYTE* pLine = m_pImage;
00251
00252
00253 nPitch = ( nPitch + 3) & (-4);
00254
00255 for ( int nY = m_nHeight ; nY ; nY-- )
00256 {
00257
00258
00259
00260
00261
00262
00263
00264
00265
00266
00267 __asm
00268 {
00269 mov edi, this
00270 mov esi, pLine
00271 mov ecx, [edi+asm_m_nWidth]
00272 loop1: mov eax, [esi]
00273 bswap eax
00274 ror eax, 8
00275 mov [esi], eax
00276 add esi, 3
00277 dec ecx
00278 jnz loop1
00279 }
00280
00281 SetDIBits( hDC, hBitmap, nY - 1, 1, pLine, &pInfo, DIB_RGB_COLORS );
00282
00283
00284
00285
00286
00287
00288
00289
00290
00291
00292
00293 __asm
00294 {
00295 mov edi, this
00296 mov esi, pLine
00297 mov ecx, [edi+asm_m_nWidth]
00298 loop2: mov eax, [esi]
00299 bswap eax
00300 ror eax, 8
00301 mov [esi], eax
00302 add esi, 3
00303 dec ecx
00304 jnz loop2
00305 }
00306
00307 pLine += nPitch;
00308 }
00309 }
00310
00311 if ( hDC != hUseDC ) ReleaseDC( 0, hDC );
00312
00313 return hBitmap;
00314 }
00315
00317
00318
00319 BOOL CImageFile::Resample(int nNewWidth, int nNewHeight)
00320 {
00321 if ( ! m_bLoaded ) return FALSE;
00322 if ( m_nComponents != 3 ) return FALSE;
00323 if ( nNewWidth == m_nWidth && nNewHeight == m_nHeight ) return TRUE;
00324
00325 DWORD nInPitch = m_nWidth * 3;
00326 DWORD nOutPitch = nNewWidth * 3;
00327
00328
00329
00330 nOutPitch = ( nOutPitch + 3) & (-4);
00331 nInPitch = ( nInPitch + 3) & (-4);
00332
00333 BYTE* pNew = new BYTE[ nOutPitch * nNewHeight ];
00334 BYTE* pOut = pNew;
00335
00336 int* pColInfo = new int[ nNewWidth * 2 ];
00337 int* pColPtr = pColInfo;
00338
00339 for ( int nX = 0 ; nX < nNewWidth ; nX++ )
00340 {
00341 int nFirst = ( nX * m_nWidth / nNewWidth );
00342 int nCount = ( (nX+1) * m_nWidth / nNewWidth ) - nFirst + 1;
00343 if ( nFirst + nCount >= m_nWidth ) nCount = 1;
00344 *pColPtr++ = nFirst * 3;
00345 *pColPtr++ = nCount;
00346 }
00347
00348 for ( int nY = 0 ; nY < nNewHeight ; nY++ )
00349 {
00350 int nFirst = ( nY * m_nHeight / nNewHeight );
00351 int nCount = ( (nY+1) * m_nHeight / nNewHeight ) - nFirst + 1;
00352
00353 if ( nFirst + nCount >= m_nHeight ) nCount = 1;
00354
00355 BYTE* pRow = m_pImage + nInPitch * nFirst;
00356 pColPtr = pColInfo;
00357
00358 for ( int nX = 0 ; nX < nNewWidth ; nX++, pColPtr++ )
00359 {
00360 BYTE* pIn = pRow + *pColPtr++;
00361
00362
00363
00364
00365
00366
00367
00368
00369
00370
00371
00372
00373
00374
00375
00376
00377
00378
00379
00380
00381 DWORD nPixels = *pColPtr * nCount;
00382 int nYY = nCount;
00383 __asm
00384 {
00385 mov esi, pIn
00386 xor eax, eax ;red
00387 xor ebx, ebx ;Green
00388 xor ecx, ecx
00389 xor edi, edi ;Blue
00390 loopYY: mov edx, pColPtr
00391 mov edx, [edx]
00392 loopXX: mov cl, [esi]
00393 add eax, ecx
00394 mov cl, [esi+1]
00395 add ebx, ecx
00396 mov cl, [esi+2]
00397 add edi, ecx
00398 add esi, 3
00399 dec edx
00400 jnz loopXX
00401 mov edx, pColPtr
00402 mov edx, [edx]
00403 lea edx, [edx+edx*2]
00404 add esi, nInPitch
00405 sub esi, edx
00406 dec nYY
00407 jnz loopYY
00408 xor edx, edx
00409 mov ecx, nPixels
00410 mov esi, pOut
00411 div ecx
00412 mov [esi], al
00413 xor edx, edx
00414 mov eax, ebx
00415 div ecx
00416 mov [esi+1], al
00417 xor edx, edx
00418 mov eax, edi
00419 div ecx
00420 mov [esi+2], al
00421 add esi, 3
00422 mov pOut, esi
00423 }
00424 }
00425 pOut += ( nOutPitch - nNewWidth * 3 );
00426 }
00427
00428 delete [] pColInfo;
00429 delete [] m_pImage;
00430
00431 m_pImage = pNew;
00432 m_nWidth = nNewWidth;
00433 m_nHeight = nNewHeight;
00434
00435 return TRUE;
00436 }
00437
00438 BOOL CImageFile::FastResample(int nNewWidth, int nNewHeight)
00439 {
00440 if ( ! m_bLoaded ) return FALSE;
00441 if ( m_nComponents != 3 ) return FALSE;
00442 if ( nNewWidth == m_nWidth && nNewHeight == m_nHeight ) return TRUE;
00443
00444 DWORD nInPitch = m_nWidth * 3;
00445 DWORD nOutPitch = nNewWidth * 3;
00446
00447
00448
00449 nOutPitch = ( nOutPitch + 3) & (-4);
00450 nInPitch = ( nInPitch + 3) & (-4);
00451
00452 BYTE *pNew, *pRow, *pIn, *pOut;
00453
00454 pOut = pNew = new BYTE[ nOutPitch * nNewHeight ];
00455
00456 for ( int nY = 0 ; nY < nNewHeight ; nY++ )
00457 {
00458 pRow = m_pImage + nInPitch * ( nY * m_nHeight / nNewHeight );
00459
00460 for ( int nX = 0 ; nX < nNewWidth ; nX++ )
00461 {
00462 pIn = pRow + 3 * ( nX * m_nWidth / nNewWidth );
00463 *pOut++ = *pIn++;
00464 *pOut++ = *pIn++;
00465 *pOut++ = *pIn++;
00466 }
00467
00468 pOut += ( nOutPitch - nNewWidth * 3 );
00469 }
00470
00471 delete [] m_pImage;
00472
00473 m_pImage = pNew;
00474 m_nWidth = nNewWidth;
00475 m_nHeight = nNewHeight;
00476
00477 return TRUE;
00478 }
00479
00481
00482
00483 BOOL CImageFile::EnsureRGB(COLORREF crBack)
00484 {
00485 if ( ! m_bLoaded || ! m_nWidth || ! m_nHeight )
00486 {
00487 return FALSE;
00488 }
00489 else if ( m_nComponents == 3 )
00490 {
00491 return TRUE;
00492 }
00493 else if ( m_nComponents == 1 )
00494 {
00495 return MonoToRGB();
00496 }
00497 else if ( m_nComponents == 4 )
00498 {
00499 return AlphaToRGB( crBack );
00500 }
00501 else
00502 {
00503 return FALSE;
00504 }
00505 }
00506
00507 BOOL CImageFile::MonoToRGB()
00508 {
00509 if ( ! m_bLoaded ) return FALSE;
00510 if ( m_nComponents == 3 ) return TRUE;
00511 if ( m_nComponents != 1 ) return FALSE;
00512
00513 DWORD nInPitch = m_nWidth * 1;
00514 DWORD nOutPitch = m_nWidth * 3;
00515
00516
00517
00518 nInPitch = ( nInPitch + 3) & (-4);
00519 nOutPitch = ( nOutPitch + 3) & (-4);
00520
00521 BYTE* pNew = new BYTE[ nOutPitch * m_nHeight ];
00522 BYTE* pInRow = m_pImage;
00523 BYTE* pOutRow = pNew;
00524
00525 for ( int nY = m_nHeight ; nY ; nY-- )
00526 {
00527 BYTE* pInCol = pInRow;
00528 BYTE* pOutCol = pOutRow;
00529
00530 for ( int nX = m_nWidth ; nX ; nX-- )
00531 {
00532 *pOutCol++ = *pInCol;
00533 *pOutCol++ = *pInCol;
00534 *pOutCol++ = *pInCol++;
00535 }
00536
00537 pInRow += nInPitch;
00538 pOutRow += nOutPitch;
00539 }
00540
00541 delete [] m_pImage;
00542
00543 m_pImage = pNew;
00544 m_nComponents = 3;
00545
00546 return TRUE;
00547 }
00548
00549 BOOL CImageFile::AlphaToRGB(COLORREF crBack)
00550 {
00551 if ( ! m_bLoaded ) return FALSE;
00552 if ( m_nComponents == 3 ) return TRUE;
00553 if ( m_nComponents != 4 ) return FALSE;
00554
00555 DWORD nInPitch = m_nWidth * 4;
00556 DWORD nOutPitch = m_nWidth * 3;
00557
00558
00559
00560 nInPitch = ( nInPitch + 3) & (-4);
00561 nOutPitch = ( nOutPitch + 3) & (-4);
00562
00563 BYTE* pNew = new BYTE[ nOutPitch * m_nHeight ];
00564 BYTE* pInRow = m_pImage;
00565 BYTE* pOutRow = pNew;
00566
00567 for ( int nY = m_nHeight ; nY ; nY-- )
00568 {
00569 BYTE* pInCol = pInRow;
00570 BYTE* pOutCol = pOutRow;
00571
00572 for ( int nX = m_nWidth ; nX ; nX-- )
00573 {
00574 DWORD nAlpha = (DWORD)pInCol[3];
00575
00576 if ( nAlpha == 255 )
00577 {
00578 *pOutCol++ = *pInCol++;
00579 *pOutCol++ = *pInCol++;
00580 *pOutCol++ = *pInCol++;
00581 pInCol++;
00582 }
00583 else if ( nAlpha == 0 )
00584 {
00585 *pOutCol++ = GetRValue( crBack );
00586 *pOutCol++ = GetGValue( crBack );
00587 *pOutCol++ = GetBValue( crBack );
00588 pInCol += 4;
00589 }
00590 else
00591 {
00592 *pOutCol++ = (BYTE)( ( (DWORD)(*pInCol++) * nAlpha + (DWORD)GetRValue( crBack ) * ( 255 - nAlpha ) ) / 255 );
00593 *pOutCol++ = (BYTE)( ( (DWORD)(*pInCol++) * nAlpha + (DWORD)GetGValue( crBack ) * ( 255 - nAlpha ) ) / 255 );
00594 *pOutCol++ = (BYTE)( ( (DWORD)(*pInCol++) * nAlpha + (DWORD)GetBValue( crBack ) * ( 255 - nAlpha ) ) / 255 );
00595 pInCol++;
00596 }
00597 }
00598
00599 pInRow += nInPitch;
00600 pOutRow += nOutPitch;
00601 }
00602
00603 delete [] m_pImage;
00604
00605 m_pImage = pNew;
00606 m_nComponents = 3;
00607
00608 return TRUE;
00609 }
00610
00611 BOOL CImageFile::SwapRGB()
00612 {
00613 if ( ! m_bLoaded ) return FALSE;
00614 if ( m_nComponents != 3 ) return FALSE;
00615
00616
00617
00618 DWORD nPitch = ( ( m_nWidth * 3 ) + 3) & (-4);
00619
00620 BYTE* pImage = m_pImage;
00621 BYTE nTemp;
00622
00623 for ( int nY = m_nHeight ; nY ; nY-- )
00624 {
00625 BYTE* pRow = pImage;
00626 pImage += nPitch;
00627
00628 for ( int nX = m_nWidth ; nX ; nX-- )
00629 {
00630 nTemp = pRow[0];
00631 pRow[0] = pRow[2];
00632 pRow[2] = nTemp;
00633 pRow += 3;
00634 }
00635 }
00636
00637 return TRUE;
00638 }