win32image.cpp

来自「这是VCF框架的代码」· C++ 代码 · 共 748 行 · 第 1/2 页

CPP
748
字号
//Win32Image.cpp

/*
Copyright 2000-2004 The VCF Project.
Please see License.txt in the top level directory
where you installed the VCF.
*/


#include "vcf/GraphicsKit/GraphicsKit.h"
#include "vcf/GraphicsKit/GraphicsKitPrivate.h"


using namespace VCF;

Win32Image::Win32Image()
{
	flipBits_ = false;
	ownDC_ = true;
	init();
}

Win32Image::Win32Image( const unsigned long& width, const unsigned long& height ):
	AbstractImage(false)
{
	flipBits_ = false;
	ownDC_ = true;
	init();

	setSize( width, height );
}

Win32Image::Win32Image( const String& fileName ):
	AbstractImage(false)
{
	flipBits_ = true;
	ownDC_ = true;
	init();
	loadFromFile( fileName );
}

Win32Image::Win32Image( GraphicsContext* context, Rect* rect  ):
	AbstractImage(false)
{
	flipBits_ = false;
	ownDC_ = false; //leave it this way to begin with and then
	//switch to false for the duration after the intial
	//bitmap has been created
	if ( (NULL != context) && (NULL != rect) ){
		Win32Context* ctx = reinterpret_cast<Win32Context*>(context->getPeer() );
		if ( NULL != ctx ){
			//set up the bitmap data
			IMTRAITS::setChannelType( flags_, IMTRAITS::getTraitsChannelType() );
			IMTRAITS::setChannelSize( flags_, IMTRAITS::getTraitsChannelSize() );
			IMTRAITS::setImageType( flags_, IMTRAITS::getTraitsImageType() );
			IMTRAITS::setPixelLayoutOrder( flags_, Image::ploBGRA );

			//hBitmap_ = NULL;

			palette_ = NULL;

			HDC contextDC = (HDC)ctx->getContextID();

			//the deletion of the context_ should delete the
			//dc_ handle
			context_ = context;

			HDC tmpDC = CreateCompatibleDC( contextDC );
			HDC origDC = contextDC;
			contextDC = tmpDC;

			setSize( rect->getWidth(), rect->getHeight() );

			contextDC = origDC;

			int r = BitBlt( tmpDC, 0, 0, getWidth(), getHeight(), contextDC, (int)rect->left_, (int)rect->top_, SRCCOPY );

			::SelectObject( tmpDC, hbmp_.oldBMP() );
			DeleteDC( tmpDC );

			hbmp_.attach( contextDC );

			//hOldBitmap_ = (HBITMAP)::SelectObject( dc_, (HBITMAP)hbmp );
			//ownDC_ = false;
		}
		else {
			//throw exception !!!
			throw InvalidPointerException( MAKE_ERROR_MSG_2("Incorrect peer class (isn't a Win32Context) for passed GraphicsContext instance" ) );
		}
	}
	else {
		//throw exception !!!
		throw InvalidPointerException( MAKE_ERROR_MSG_2("Graphics Context passed in to Win32Image is NULL" ) );
	}
}


Win32Image::Win32Image( HBITMAP bitmap )
	:AbstractImage(false)
{
	flipBits_ = true;
	ownDC_ = true;
	init();

	if ( NULL == bitmap ) {
		throw InvalidPointerException(MAKE_ERROR_MSG_2("NULL HBITMAP passed into Win32Image constructor"));
	}
	loadFromBMPHandle( bitmap );
}

Win32Image::Win32Image( HICON icon )
	:AbstractImage(false)
{
	flipBits_ = true;
	ownDC_ = true;
	init();

	ICONINFO info = {0};
	if ( GetIconInfo( icon, &info ) ) {
		BITMAP bmp;
		if ( GetObject( info.hbmColor, sizeof(BITMAP), &bmp ) ) {
		
			setSize( bmp.bmWidth, bmp.bmHeight );

			if ( !DrawIcon( hbmp_.dc(), 0, 0, icon ) ) {
				StringUtils::traceWithArgs( Format("DrawIcon failed, err: %d\n") % GetLastError()  );
			}
		}
	}
}

Win32Image::~Win32Image()
{
	//if ( NULL != hBitmap_ ){
	//	SelectObject( dc_, hOldBitmap_ );
	//	int err = DeleteObject( hBitmap_ );
	//}

	//the base class AbstractImage will take care of
	//deleting hte GraphicsContext. If we don't
	//own the DC then set the context_ to null
	//to prevent from deleting it
	if ( ownDC_ ) {
		//DeleteDC( dc_ );
	}
	else {
		hbmp_.detach();
		context_ = NULL;
	}
	imageBits_->pixels_ = NULL;
}

void Win32Image::init()
{
	//NOTE: init() is not called if ownDC_ is true - the constructor takes care of this
	IMTRAITS::setChannelType( flags_, IMTRAITS::getTraitsChannelType() );
	IMTRAITS::setChannelSize( flags_, IMTRAITS::getTraitsChannelSize() );
	IMTRAITS::setImageType( flags_, IMTRAITS::getTraitsImageType() );
	IMTRAITS::setPixelLayoutOrder( flags_, Image::ploBGRA );

	//hBitmap_ = NULL;

	palette_ = NULL;

	//dc_ = ::CreateCompatibleDC( NULL );

	//the deletion of the context_ should delete the
	//dc_ handle
	context_ = new GraphicsContext( (OSHandleID)hbmp_.dc() );
}

void Win32Image::setSize( const unsigned long & width, const unsigned long & height )
{
	if ( (!ownDC_) && (hbmp_ != NULL) ) {
		throw RuntimeException( MAKE_ERROR_MSG_2("Cannot set size for non modifiable image") );
	}
	AbstractImage::setSize( width, height );
	createBMP();
}


void Win32Image::createBMP()
{
	if ( (!ownDC_) && (hbmp_ != NULL) ) {
		throw RuntimeException( MAKE_ERROR_MSG_2("Cannot set size for non modifiable image") );
	}

	

	dataBuffer_ = NULL;

	
	//hBitmap_ = NULL;
	memset( &bmpInfo_, 0, sizeof (BITMAPINFOHEADER) );
	bmpInfo_.bmiHeader.biSize = sizeof (BITMAPINFOHEADER);
	bmpInfo_.bmiHeader.biWidth = getWidth();
	if ( true == flipBits_ ) {
		bmpInfo_.bmiHeader.biHeight = -getHeight(); // Win32 DIB are upside down - do this to filp it over
	}
	else {
		//this needs to be fixed
		//I put this back for now JEC-12-10-2001
		bmpInfo_.bmiHeader.biHeight = -getHeight(); // this is WRONG, cause there are times when we don't
													 // want it this way, but it will have to do for now :(
	}
	bmpInfo_.bmiHeader.biPlanes = 1;
	bmpInfo_.bmiHeader.biBitCount = 32;
	bmpInfo_.bmiHeader.biCompression = BI_RGB;
	bmpInfo_.bmiHeader.biSizeImage = abs(bmpInfo_.bmiHeader.biHeight) * bmpInfo_.bmiHeader.biWidth * 4;
	imageBits_->pixels_ = NULL;

	hbmp_.setSize( getWidth(), getHeight() );


	//hBitmap_ = CreateDIBSection ( dc_, &bmpInfo_, DIB_RGB_COLORS, (void **)&imageBits_->pixels_, NULL, NULL );

	if ( (hbmp_ != NULL) ) {
		
		dataBuffer_ = (unsigned char*)hbmp_.data();
		imageBits_->pixels_ = (SysPixelType*)hbmp_.data();

		SysPixelType* pix = imageBits_->pixels_;
		int sz = bmpInfo_.bmiHeader.biWidth * abs(bmpInfo_.bmiHeader.biHeight);
		do {
			sz --;
			pix[sz].a = 255;
		} while( sz > 0 );


		//hOldBitmap_ = (HBITMAP)::SelectObject( dc_, hBitmap_ );
		//::DeleteObject( oldObj );//clear out the old object
	}
}

HBITMAP Win32Image::getBitmap()
{
	return hbmp_;
}

HDC Win32Image::getDC()
{
	return hbmp_.dc();
}

void Win32Image::loadFromFile( const String& fileName )
{
	flipBits_ = true;

	HBITMAP hBMP = NULL;
	if ( System::isUnicodeEnabled() ) {
		hBMP = (HBITMAP)LoadImageW( NULL, fileName.c_str(), IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE );
	}
	else {
		hBMP = (HBITMAP)LoadImageA( NULL, fileName.ansi_c_str(), IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE );
	}

	if ( NULL == hBMP ) {
		throw ImageLoaderException(MAKE_ERROR_MSG_2("Image file unreadable - this may be due to an incorrect file name"));
	}
	loadFromBMPHandle( hBMP );
}

void Win32Image::loadFromBMPHandle( HBITMAP bitmap )
{
	flipBits_ = true;

	//hBitmap_ = bitmap;
	BITMAP bmp = {0};
	GetObject( bitmap, sizeof(bmp), &bmp );

	setSize( bmp.bmWidth, bmp.bmHeight );

	HDC tmpBMPDC = CreateCompatibleDC( NULL );
	HBITMAP oldBitmap = (HBITMAP)::SelectObject(  tmpBMPDC, bitmap );

	BitBlt( hbmp_.dc(), 0, 0, bmp.bmWidth, bmp.bmHeight, tmpBMPDC, 0, 0, SRCCOPY );

	::SelectObject(  tmpBMPDC, oldBitmap );
	DeleteDC( tmpBMPDC );
	DeleteObject( bitmap );

	SysPixelType* pix = imageBits_->pixels_;
	int sz = bmpInfo_.bmiHeader.biWidth * abs(bmpInfo_.bmiHeader.biHeight);
	do {
		sz --;
		pix[sz].a = 255;
	} while( sz > 0 );
}

void Win32Image::internal_saveToFile( const String& fileName )
{

	/**
	NOTE!!!!
	It's important that this get's written out with "wb", not 
	just "w" here.
	*/
#ifdef VCF_CW
	FILE* f = fopen( fileName.ansi_c_str(), "wb" );
#else
	FILE* f = _wfopen( fileName.c_str(), L"wb" );
#endif

	// write the file header

	const int bitsPerPix = 24;
	//store width for 24bit image NOT 32
	DWORD width = ((((bitsPerPix * getWidth()) + 31) / 32) * 4);

	DWORD size = getHeight() * width;

	BITMAPINFOHEADER bih = {0};
	
	bih.biHeight = getHeight();
	bih.biWidth = getWidth();
	
	bih.biClrImportant = 0;
	bih.biClrUsed = 0;

	bih.biPlanes = 1;
	bih.biSizeImage = size;
	bih.biBitCount = bitsPerPix;
	bih.biSize = sizeof(BITMAPINFOHEADER);

	bih.biCompression = BI_RGB;

	bih.biXPelsPerMeter = 0;
	bih.biYPelsPerMeter = 0;


	BITMAPFILEHEADER bitmapfileheader;
	bitmapfileheader.bfType = 0x4D42;
	bitmapfileheader.bfSize = sizeof(BITMAPFILEHEADER) + size;

	bitmapfileheader.bfOffBits = (DWORD) sizeof(BITMAPFILEHEADER) + bih.biSize;
		//sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) +
		//0 * sizeof(RGBQUAD);

	bitmapfileheader.bfReserved1 = 0;
	bitmapfileheader.bfReserved2 = 0;

	fwrite( &bitmapfileheader, sizeof(BITMAPFILEHEADER), 1, f );
	


	// write the info header
	fwrite( &bih, bih.biSize, 1, f );



	

	// write the palette here, but we'll do nothing since we don't support palettes


	DWORD height = getHeight();
	SysPixelType* bits = getImageBits()->pixels_;
	unsigned char* row = new unsigned char[width];
	unsigned long imgWidth = getWidth();

	// write the bitmap data

	unsigned char* tmpRow = row;
	for ( int y=height-1;y>=0;y-- ) {		
		tmpRow = row;
		for (unsigned long x=0;x<imgWidth;x++ ) {		
			SysPixelType& pix = bits[y*imgWidth + x];
			
			*tmpRow = pix.b;
			tmpRow++;
			*tmpRow = pix.g;
			tmpRow++;
			*tmpRow = pix.r;
			tmpRow++;

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?