📄 imagefile.cpp
字号:
//
// ImageFile.cpp
//
// Copyright (c) Shareaza Development Team, 2002-2004.
// This file is part of SHAREAZA (www.shareaza.com)
//
// Shareaza is free software; you can redistribute it
// and/or modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2 of
// the License, or (at your option) any later version.
//
// Shareaza is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Shareaza; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
#include "StdAfx.h"
#include "Shareaza.h"
#include "ImageServices.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
IMPLEMENT_DYNAMIC(CImageFile, CComObject)
/////////////////////////////////////////////////////////////////////////////
// CImageFile construction
CImageFile::CImageFile(CImageServices* pService)
{
m_pService = pService;
m_bScanned = FALSE;
m_nWidth = 0;
m_nHeight = 0;
m_nComponents = 0;
m_bLoaded = FALSE;
m_pImage = NULL;
}
CImageFile::~CImageFile()
{
Clear();
}
/////////////////////////////////////////////////////////////////////////////
// CImageFile clear operation
void CImageFile::Clear()
{
if ( m_bLoaded ) delete [] m_pImage;
m_bScanned = FALSE;
m_nWidth = 0;
m_nHeight = 0;
m_nComponents = 0;
m_bLoaded = FALSE;
m_pImage = NULL;
}
/////////////////////////////////////////////////////////////////////////////
// CImageFile load operations
BOOL CImageFile::LoadFromMemory(LPCTSTR pszType, LPCVOID pData, DWORD nLength, BOOL bScanOnly, BOOL bPartialOk)
{
return m_pService->LoadFromMemory( this, pszType, pData, nLength, bScanOnly, bPartialOk );
}
BOOL CImageFile::LoadFromFile(LPCTSTR pszType, HANDLE hFile, DWORD nLength, BOOL bScanOnly, BOOL bPartialOk)
{
return m_pService->LoadFromFile( this, pszType, hFile, nLength, bScanOnly, bPartialOk );
}
BOOL CImageFile::LoadFromFile(LPCTSTR pszFile, BOOL bScanOnly, BOOL bPartialOk)
{
HANDLE hFile = CreateFile( pszFile, GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE,
NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL );
if ( hFile == INVALID_HANDLE_VALUE ) return FALSE;
BOOL bResult = m_pService->LoadFromFile( this, pszFile, hFile, GetFileSize( hFile, NULL ), bScanOnly, bPartialOk );
CloseHandle( hFile );
return bResult;
}
BOOL CImageFile::LoadFromResource(HINSTANCE hInstance, UINT nResourceID, LPCTSTR pszType, BOOL bScanOnly, BOOL bPartialOk)
{
HMODULE hModule = (HMODULE)hInstance;
HRSRC hRes = FindResource( hModule, MAKEINTRESOURCE( nResourceID ), pszType );
if ( hRes == NULL ) return FALSE;
DWORD nSize = SizeofResource( hModule, hRes );
HGLOBAL hMemory = ::LoadResource( hModule, hRes );
LPCVOID pMemory = (LPCVOID)LockResource( hMemory );
CString strType;
if ( pszType == RT_BITMAP || _tcscmp( pszType, _T("BMP") ) == 0 )
{
pszType = _T(".bmp");
}
else if ( _tcscmp( pszType, RT_JPEG ) == 0 )
{
pszType = _T(".jpg");
}
else if ( _tcscmp( pszType, RT_PNG ) == 0 )
{
pszType = _T(".png");
}
else
{
strType.Format( _T(".%s"), pszType );
pszType = strType;
}
return m_pService->LoadFromMemory( this, pszType, pMemory, nSize, bScanOnly, bPartialOk );
}
/////////////////////////////////////////////////////////////////////////////
// CImageFile save operations
BOOL CImageFile::SaveToMemory(LPCTSTR pszType, int nQuality, LPBYTE* ppBuffer, DWORD* pnLength)
{
return m_pService->SaveToMemory( this, pszType, nQuality, ppBuffer, pnLength );
}
BOOL CImageFile::SaveToFile(LPCTSTR pszType, int nQuality, HANDLE hFile, DWORD* pnLength)
{
return m_pService->SaveToFile( this, pszType, nQuality, hFile, pnLength );
}
BOOL CImageFile::SaveToFile(LPCTSTR pszFile, int nQuality)
{
HANDLE hFile = CreateFile( pszFile, GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE,
NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL );
if ( hFile == INVALID_HANDLE_VALUE ) return FALSE;
BOOL bResult = m_pService->SaveToFile( this, pszFile, nQuality, hFile );
CloseHandle( hFile );
if ( ! bResult ) DeleteFile( pszFile );
return bResult;
}
/////////////////////////////////////////////////////////////////////////////
// CImageFile serialization
DWORD CImageFile::GetSerialSize() const
{
if ( ! m_bLoaded ) return 4;
int nPitch = m_nWidth * m_nComponents;
while ( nPitch & 3 ) nPitch++;
return 12 + nPitch * m_nHeight;
}
void CImageFile::Serialize(CArchive& ar)
{
if ( ar.IsStoring() )
{
if ( ! m_bLoaded )
{
ar << m_bLoaded;
return;
}
ar << m_nWidth;
ar << m_nHeight;
ar << m_nComponents;
int nPitch = m_nWidth * m_nComponents;
while ( nPitch & 3 ) nPitch++;
ar.Write( m_pImage, nPitch * m_nHeight );
}
else
{
Clear();
ar >> m_nWidth;
if ( m_nWidth == 0 ) return;
ar >> m_nHeight;
ar >> m_nComponents;
int nPitch = m_nWidth * m_nComponents;
while ( nPitch & 3 ) nPitch++;
m_pImage = new BYTE[ nPitch * m_nHeight ];
ar.Read( m_pImage, nPitch * m_nHeight );
m_bLoaded = TRUE;
}
}
/////////////////////////////////////////////////////////////////////////////
// CImageFile image access operations
HBITMAP CImageFile::CreateBitmap(HDC hUseDC)
{
if ( ! m_bLoaded ) return NULL;
if ( m_nComponents != 3 ) return NULL;
BITMAPINFO pInfo;
ZeroMemory( &pInfo, sizeof(pInfo) );
pInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
pInfo.bmiHeader.biWidth = (LONG)m_nWidth;
pInfo.bmiHeader.biHeight = (LONG)m_nHeight;
pInfo.bmiHeader.biPlanes = 1;
pInfo.bmiHeader.biBitCount = 24;
pInfo.bmiHeader.biCompression = BI_RGB;
pInfo.bmiHeader.biSizeImage = m_nWidth * m_nHeight * 3;
HDC hDC = hUseDC ? hUseDC : GetDC( 0 );
HBITMAP hBitmap = CreateDIBitmap( hDC, &pInfo.bmiHeader, 0, NULL, &pInfo, DIB_RGB_COLORS );
if ( hBitmap )
{
DWORD nPitch = m_nWidth * 3;
BYTE* pLine = m_pImage;
while ( nPitch & 3 ) nPitch++;
for ( int nY = m_nHeight ; nY ; nY-- )
{
BYTE bSwap, *pSwap = pLine;
for ( int nX = m_nWidth ; nX ; nX--, pSwap += 3 )
{
bSwap = *pSwap;
*pSwap = pSwap[2];
pSwap[2] = bSwap;
}
SetDIBits( hDC, hBitmap, nY - 1, 1, pLine, &pInfo, DIB_RGB_COLORS );
pSwap = pLine;
for ( nX = m_nWidth ; nX ; nX--, pSwap += 3 )
{
bSwap = *pSwap;
*pSwap = pSwap[2];
pSwap[2] = bSwap;
}
pLine += nPitch;
}
}
if ( hDC != hUseDC ) ReleaseDC( 0, hDC );
return hBitmap;
}
/////////////////////////////////////////////////////////////////////////////
// CImageFile image modification operations
BOOL CImageFile::Resample(int nNewWidth, int nNewHeight)
{
if ( ! m_bLoaded ) return FALSE;
if ( m_nComponents != 3 ) return FALSE;
if ( nNewWidth == m_nWidth && nNewHeight == m_nHeight ) return TRUE;
DWORD nInPitch = m_nWidth * 3;
DWORD nOutPitch = nNewWidth * 3;
while ( nOutPitch & 3 ) nOutPitch++;
while ( nInPitch & 3 ) nInPitch++;
BYTE* pNew = new BYTE[ nOutPitch * nNewHeight ];
BYTE* pOut = pNew;
int* pColInfo = new int[ nNewWidth * 2 ];
int* pColPtr = pColInfo;
for ( int nX = 0 ; nX < nNewWidth ; nX++ )
{
int nFirst = ( nX * m_nWidth / nNewWidth );
int nCount = ( (nX+1) * m_nWidth / nNewWidth ) - nFirst + 1;
if ( nFirst + nCount >= m_nWidth ) nCount = 1;
*pColPtr++ = nFirst * 3;
*pColPtr++ = nCount;
}
for ( int nY = 0 ; nY < nNewHeight ; nY++ )
{
int nFirst = ( nY * m_nHeight / nNewHeight );
int nCount = ( (nY+1) * m_nHeight / nNewHeight ) - nFirst + 1;
if ( nFirst + nCount >= m_nHeight ) nCount = 1;
BYTE* pRow = m_pImage + nInPitch * nFirst;
pColPtr = pColInfo;
for ( nX = 0 ; nX < nNewWidth ; nX++, pColPtr++ )
{
BYTE* pIn = pRow + *pColPtr++;
DWORD nRed = 0, nGreen = 0, nBlue = 0, nPixels = 0;
for ( int nYY = nCount ; nYY ; nYY-- )
{
for ( int nXX = *pColPtr ; nXX ; nXX-- )
{
nRed += *pIn++;
nGreen += *pIn++;
nBlue += *pIn++;
nPixels++;
}
pIn += nInPitch - *pColPtr - *pColPtr - *pColPtr;
}
*pOut++ = (BYTE)( nRed / nPixels );
*pOut++ = (BYTE)( nGreen / nPixels );
*pOut++ = (BYTE)( nBlue / nPixels );
}
pOut += ( nOutPitch - nNewWidth * 3 );
}
delete [] pColInfo;
delete [] m_pImage;
m_pImage = pNew;
m_nWidth = nNewWidth;
m_nHeight = nNewHeight;
return TRUE;
}
BOOL CImageFile::FastResample(int nNewWidth, int nNewHeight)
{
if ( ! m_bLoaded ) return FALSE;
if ( m_nComponents != 3 ) return FALSE;
if ( nNewWidth == m_nWidth && nNewHeight == m_nHeight ) return TRUE;
DWORD nInPitch = m_nWidth * 3;
DWORD nOutPitch = nNewWidth * 3;
while ( nOutPitch & 3 ) nOutPitch++;
while ( nInPitch & 3 ) nInPitch++;
BYTE *pNew, *pRow, *pIn, *pOut;
pOut = pNew = new BYTE[ nOutPitch * nNewHeight ];
for ( int nY = 0 ; nY < nNewHeight ; nY++ )
{
pRow = m_pImage + nInPitch * ( nY * m_nHeight / nNewHeight );
for ( int nX = 0 ; nX < nNewWidth ; nX++ )
{
pIn = pRow + 3 * ( nX * m_nWidth / nNewWidth );
*pOut++ = *pIn++;
*pOut++ = *pIn++;
*pOut++ = *pIn++;
}
pOut += ( nOutPitch - nNewWidth * 3 );
}
delete [] m_pImage;
m_pImage = pNew;
m_nWidth = nNewWidth;
m_nHeight = nNewHeight;
return TRUE;
}
/////////////////////////////////////////////////////////////////////////////
// CImageFile image component modification
BOOL CImageFile::EnsureRGB(COLORREF crBack)
{
if ( ! m_bLoaded || ! m_nWidth || ! m_nHeight )
{
return FALSE;
}
else if ( m_nComponents == 3 )
{
return TRUE;
}
else if ( m_nComponents == 1 )
{
return MonoToRGB();
}
else if ( m_nComponents == 4 )
{
return AlphaToRGB( crBack );
}
else
{
return FALSE;
}
}
BOOL CImageFile::MonoToRGB()
{
if ( ! m_bLoaded ) return FALSE;
if ( m_nComponents == 3 ) return TRUE;
if ( m_nComponents != 1 ) return FALSE;
DWORD nInPitch = m_nWidth * 1;
DWORD nOutPitch = m_nWidth * 3;
while ( nInPitch & 3 ) nInPitch++;
while ( nOutPitch & 3 ) nOutPitch++;
BYTE* pNew = new BYTE[ nOutPitch * m_nHeight ];
BYTE* pInRow = m_pImage;
BYTE* pOutRow = pNew;
for ( int nY = m_nHeight ; nY ; nY-- )
{
BYTE* pInCol = pInRow;
BYTE* pOutCol = pOutRow;
for ( int nX = m_nWidth ; nX ; nX-- )
{
*pOutCol++ = *pInCol;
*pOutCol++ = *pInCol;
*pOutCol++ = *pInCol++;
}
pInRow += nInPitch;
pOutRow += nOutPitch;
}
delete [] m_pImage;
m_pImage = pNew;
m_nComponents = 3;
return TRUE;
}
BOOL CImageFile::AlphaToRGB(COLORREF crBack)
{
if ( ! m_bLoaded ) return FALSE;
if ( m_nComponents == 3 ) return TRUE;
if ( m_nComponents != 4 ) return FALSE;
DWORD nInPitch = m_nWidth * 4;
DWORD nOutPitch = m_nWidth * 3;
while ( nInPitch & 3 ) nInPitch++;
while ( nOutPitch & 3 ) nOutPitch++;
BYTE* pNew = new BYTE[ nOutPitch * m_nHeight ];
BYTE* pInRow = m_pImage;
BYTE* pOutRow = pNew;
for ( int nY = m_nHeight ; nY ; nY-- )
{
BYTE* pInCol = pInRow;
BYTE* pOutCol = pOutRow;
for ( int nX = m_nWidth ; nX ; nX-- )
{
DWORD nAlpha = (DWORD)pInCol[3];
if ( nAlpha == 255 )
{
*pOutCol++ = *pInCol++;
*pOutCol++ = *pInCol++;
*pOutCol++ = *pInCol++;
pInCol++;
}
else if ( nAlpha == 0 )
{
*pOutCol++ = GetRValue( crBack );
*pOutCol++ = GetGValue( crBack );
*pOutCol++ = GetBValue( crBack );
pInCol += 4;
}
else
{
*pOutCol++ = (BYTE)( ( (DWORD)(*pInCol++) * nAlpha + (DWORD)GetRValue( crBack ) * ( 255 - nAlpha ) ) / 255 );
*pOutCol++ = (BYTE)( ( (DWORD)(*pInCol++) * nAlpha + (DWORD)GetGValue( crBack ) * ( 255 - nAlpha ) ) / 255 );
*pOutCol++ = (BYTE)( ( (DWORD)(*pInCol++) * nAlpha + (DWORD)GetBValue( crBack ) * ( 255 - nAlpha ) ) / 255 );
pInCol++;
}
}
pInRow += nInPitch;
pOutRow += nOutPitch;
}
delete [] m_pImage;
m_pImage = pNew;
m_nComponents = 3;
return TRUE;
}
BOOL CImageFile::SwapRGB()
{
if ( ! m_bLoaded ) return FALSE;
if ( m_nComponents != 3 ) return FALSE;
DWORD nPitch = m_nWidth * 3;
while ( nPitch & 3 ) nPitch++;
BYTE* pImage = m_pImage;
BYTE nTemp;
for ( int nY = m_nHeight ; nY ; nY-- )
{
BYTE* pRow = pImage;
pImage += nPitch;
for ( int nX = m_nWidth ; nX ; nX-- )
{
nTemp = pRow[0];
pRow[0] = pRow[2];
pRow[2] = nTemp;
pRow += 3;
}
}
return TRUE;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -