//by patrox ou comment charger une JPEG sans lib, sous windoze 95->XP

//modifs du jour :
//Ajout de CreateDibSection qui permet de recuperer l'image dans un buffer.
//a vous de placer votre code au niveau du blit pour recuperer l'image.


//important, il faut linker : UUID.LIB, OLE32.LIB et OLEPRO32.LIB
#include	 <windows.h>

#include	<olectl.h>
#include	<commdlg.h>
#include 	<ocidl.h>
#include 	<crtdbg.h>


#define	HIMETRIC_INCH	2540
#define	RES_OK				true 
#define	RES_FAIL				false


bool		LoadPictureFromFile( LPCTSTR szFile) ;
bool		RenderPicture( LPPICTURE 		picture  ) ;

extern		HWND hWnd;

// This function loads a file into an IStream.
bool		LoadPictureFromFile( LPCTSTR szFile)
{
HRESULT 			hr;
unsigned long 	ulFileSize = 0  , ulBytesRead = 0 ;
HANDLE			hFile;
char					*dataPtr ;
HGLOBAL 			hGlobal = NULL ;
LPSTREAM 		pictureStreamPtr  ;
LPPICTURE 		picture;


	try 
	{
		// open file
		 hFile = CreateFile(szFile, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL);
		 if ( hFile == INVALID_HANDLE_VALUE )				throw( "Fichier manquant" ) ;
		
		// get file size
		ulFileSize = GetFileSize(hFile, NULL);
		if ( ulFileSize == 0xFFFFFFFF || ulFileSize == 0) 		throw("Fichier corrompu") ;

		dataPtr  = NULL;
		
		// alloc memory based on file size
		hGlobal = GlobalAlloc(GMEM_MOVEABLE, ulFileSize);
		if ( hGlobal == NULL )		throw("Out of memory") ;

		dataPtr = (char*) GlobalLock(hGlobal);	//our data points to the buffer prepared to receive the file
		if ( dataPtr == NULL )		throw("Impossible de locker le bloc memoire") ;

		// read file and store in global memory
		ReadFile(hFile, dataPtr, ulFileSize, &ulBytesRead, NULL);
		if ( ulBytesRead != ulFileSize)	throw("Impossible de lire le fichier") ;

		// create IStream* from global memory and FREE the memory of the HGLOBAL ( TRUE flag )
		hr = CreateStreamOnHGlobal(hGlobal, TRUE, &pictureStreamPtr);
		if ( hr != S_OK )		throw("Impossible de recuperer le picture stream") ;
	
		hr = OleLoadPicture(pictureStreamPtr, ulFileSize, FALSE, IID_IPicture , (LPVOID *)&picture);
		if (hr != S_OK )			throw("Impossible d'obtenir l'interface IPICTURE") ;

		RenderPicture( picture  ) ;
		picture->Release( ) ;
	}
	catch( char	*message )
	{
		MessageBox( 0, message ,0,0 ) ;
		
		if ( pictureStreamPtr )		pictureStreamPtr->Release() ;
		if( hGlobal )					
		{	
			GlobalUnlock( hGlobal );
			GlobalFree( hGlobal ) ;
		}

		CloseHandle(hFile);
		return	RES_FAIL ;
	}

		//cool we could decompress our picture !	
		if ( pictureStreamPtr )		pictureStreamPtr->Release() ;
		if( hGlobal )					
		{	
			GlobalUnlock( hGlobal );
			GlobalFree( hGlobal ) ;
		}

		CloseHandle(hFile);
		return	RES_OK ;
}

bool		RenderPicture( LPPICTURE 		picture ) 
{
long 		pictureWidth ,  pictureHeight ;
RECT	r = {0,0,320,240 } ;
HBITMAP		memBitmap , oldBitmap ;			//bitmap memoire qui va nous servir de buffer
HDC				memDC	;				//	HDC memoire
char				*pixelPtr ;				//adresse de base de l'image
BITMAPINFO	bmi ;



	picture->get_Width(&pictureWidth);
	picture->get_Height(&pictureHeight);

	memDC	=	CreateCompatibleDC( NULL ) ;		//on cree un DC compatible bidon

	// convert himetric to pixels
	int nWidth	= MulDiv(	pictureWidth		, GetDeviceCaps(memDC, LOGPIXELSX), HIMETRIC_INCH) ;
	int nHeight	= MulDiv(	pictureHeight		, GetDeviceCaps(memDC, LOGPIXELSY), HIMETRIC_INCH) ;
	


	memset( &bmi , 0  , sizeof(BITMAPINFO) ) ;
	bmi.bmiHeader.biSize		=	sizeof (BITMAPINFOHEADER ) ;
	bmi.bmiHeader.biWidth	=	nWidth ;
	bmi.bmiHeader.biHeight	=	nHeight ;
	bmi.bmiHeader.biPlanes	=	1 ;
	bmi.bmiHeader.biBitCount	=	16 ;  //16 = 16 bits  24 = 24 bits et 32 = 32 bits
	bmi.bmiHeader.biCompression	=	BI_RGB ;
	bmi.bmiHeader.biSizeImage	=	0	;
	bmi.bmiHeader.biXPelsPerMeter	=	0 ;
	bmi.bmiHeader.biYPelsPerMeter	=	0 ;
	bmi.bmiHeader.biClrUsed			=	0 ;
	bmi.bmiHeader.biClrImportant		=	0 ;
		
	memBitmap	=	 CreateDIBSection( 	memDC , 
															&bmi ,
															DIB_RGB_COLORS , 
															&pixelPtr ,			//recois l'adresse des  pixels
															NULL ,
															0
															 ) ;
															 															
	oldBitmap	=	( HBITMAP)SelectObject( memDC , memBitmap ) ;	// selectionne la bitmap sur le hdc ( important !!)

	picture->Render(	memDC,
								0,0,nWidth	,nHeight,						//destination
								0,pictureHeight,pictureWidth	,-pictureHeight,		//source  ( stored baCKWARDS )
								NULL  )	;
	
	//a ce point precis la carte des pixels se situe dans :	pixelPtr
	BitBlt(GetDC( hWnd ) ,0,0,640,480,memDC,0,0, SRCCOPY ) ;
	
	//on vire ce qui est inutile
	SelectObject( memDC , oldBitmap ) ;	// restaure l'ancienne bitmap sur le hdc
	DeleteObject( memBitmap ) ;					//on peu detruire
	DeleteObject( memDC ) ;				
		
	return	RES_OK ;
}


