Beispiel #1
0
// cf. http://stackoverflow.com/questions/4598872/creating-hbitmap-from-memory-buffer/4616394#4616394
Bitmap *BitmapFromData(const char *data, size_t len)
{
    ImgFormat format = GfxFormatFromData(data, len);
    if (Img_TGA == format)
        return tga::ImageFromData(data, len);
    if (Img_WebP == format)
        return webp::ImageFromData(data, len);
    if (Img_JP2 == format)
        return fitz::ImageFromData(data, len);
    if (Img_JPEG == format && JpegUsesArithmeticCoding(data, len))
        return fitz::ImageFromData(data, len);

    ScopedComPtr<IStream> stream(CreateStreamFromData(data, len));
    if (!stream)
        return NULL;
    if (Img_JXR == format)
        return WICDecodeImageFromStream(stream);

    Bitmap *bmp = Bitmap::FromStream(stream);
    if (bmp && bmp->GetLastStatus() != Ok) {
        delete bmp;
        bmp = NULL;
    }
    // GDI+ under Windows XP sometimes fails to extract JPEG image dimensions
    if (bmp && Img_JPEG == format && (0 == bmp->GetWidth() || 0 == bmp->GetHeight())) {
        delete bmp;
        bmp = fitz::ImageFromData(data, len);
    }
    return bmp;
}
Beispiel #2
0
// cf. http://stackoverflow.com/questions/4598872/creating-hbitmap-from-memory-buffer/4616394#4616394
Bitmap *BitmapFromData(const char *data, size_t len)
{
    ImgFormat format = GfxFormatFromData(data, len);
    if (Img_TGA == format)
        return tga::ImageFromData(data, len);

    ScopedComPtr<IStream> stream(CreateStreamFromData(data, len));
    if (!stream)
        return NULL;
    if (Img_JXR == format)
        return WICDecodeImageFromStream(stream);

    Bitmap *bmp = Bitmap::FromStream(stream);
    if (bmp && bmp->GetLastStatus() != Ok) {
        delete bmp;
        bmp = NULL;
    }
    // GDI+ under Windows XP sometimes fails to extract JPEG image dimensions
    if (bmp && Img_JPEG == format && 0 == bmp->GetWidth() && 0 == bmp->GetHeight()) {
        delete bmp;
        LARGE_INTEGER zero = { 0 };
        stream->Seek(zero, STREAM_SEEK_SET, NULL);
        bmp = WICDecodeImageFromStream(stream);
    }
    return bmp;
}
Beispiel #3
0
/********************************************************************
 GdipBitmapFromFile - read a GDI+ image from a file.

********************************************************************/
extern "C" HRESULT DAPI GdipBitmapFromFile(
    __in_z LPCWSTR wzFileName,
    __out Bitmap **ppBitmap
    )
{
    HRESULT hr = S_OK;
    Bitmap *pBitmap = NULL;
    Status gs = Ok;

    ExitOnNull(ppBitmap, hr, E_INVALIDARG, "Invalid null wzFileName");

    pBitmap = Bitmap::FromFile(wzFileName);
    ExitOnNull(pBitmap, hr, E_OUTOFMEMORY, "Failed to allocate bitmap from file.");

    gs = pBitmap->GetLastStatus();
    ExitOnGdipFailure(gs, hr, "Failed to load bitmap from file: %ls", wzFileName);

    *ppBitmap = pBitmap;
    pBitmap = NULL;

LExit:
    if (pBitmap)
    {
        delete pBitmap;
    }

    return hr;
}
// 读取图片(从文件读)
BOOL LoadBitmapFromFile(const CString strPathFile, CBitmap &bitmap, CSize &size)
{	
	HBITMAP hBitmap = NULL;
#ifdef _UNICODE
	Bitmap* pBitmap = Bitmap::FromFile(strPathFile);
#else
	Bitmap* pBitmap = Bitmap::FromFile(CEncodingUtil::AnsiToUnicode(strPathFile));
#endif
	Status status = pBitmap->GetLastStatus();
	if(Ok == status)
	{		
		status = pBitmap->GetHBITMAP(Color(0,0,0), &hBitmap);
		if(Ok == status)
		{
			if(bitmap.m_hObject != NULL)
			{
				bitmap.Detach();
			}
			bitmap.Attach(hBitmap);
			
			BITMAP bmInfo;
			::GetObject( bitmap.m_hObject, sizeof(BITMAP), &bmInfo );
			size.cx = bmInfo.bmWidth;
			size.cy = bmInfo.bmHeight;

			delete pBitmap;

			return TRUE;
		}
	}

	return FALSE;
}
Beispiel #5
0
HBITMAP loadImageFromBuffer(const void* buf, unsigned int size, HWND hWnd, const BOOL& keepAspect, const BOOL& resize)
{
	if (!buf) {
		return NULL;
	}

	if (!bUseGdip) {
		return loadPNGFromBuffer(buf, size, hWnd, keepAspect, resize);
	}

	HGLOBAL hBuffer = ::GlobalAlloc(GMEM_MOVEABLE, size);
	if (!hBuffer) {
		return NULL;
	}

	Bitmap* pBitmap = NULL;
	Status stat;

	void* pBuffer = ::GlobalLock(hBuffer);
	if (pBuffer)
	{
		memcpy(pBuffer, buf, size);

		IStream* pStream = NULL;
		if (::CreateStreamOnHGlobal(hBuffer, FALSE, &pStream) == S_OK) {
			// create a new Image object based on pStream
			pBitmap = Bitmap::FromStream(pStream);
			stat = pBitmap->GetLastStatus();
			pStream->Release();
		}
		::GlobalUnlock(hBuffer);
	}
	::GlobalFree(hBuffer);

	if (stat != Ok) {
		if (pBitmap) {
			delete pBitmap;
		}
		return NULL;
	}

	HBITMAP hBitmap = NULL;
	pBitmap->GetHBITMAP(color, &hBitmap);

	if (resize) {
		hBitmap = resizeBitmap(hWnd, hBitmap, pBitmap->GetWidth(), pBitmap->GetHeight(), keepAspect);
	}

	if (pBitmap) {
		delete pBitmap;
	}

	return hBitmap;
}
// 读取图片(从资源读)
BOOL LoadBitmapFromIDResource(UINT nID, CBitmap &bitmap, CSize &size, CString strType)
{
	HINSTANCE hInst = AfxGetResourceHandle();  
	HRSRC hRsrc = ::FindResource (hInst,MAKEINTRESOURCE(nID), strType);
	if (!hRsrc)  
	{
		return FALSE; 
	}

	DWORD len = SizeofResource(hInst, hRsrc);  
	BYTE* lpRsrc = (BYTE*)LoadResource(hInst, hRsrc);  
	if (!lpRsrc)  
	{
		return FALSE;
	}
	HGLOBAL m_hMem = GlobalAlloc(GMEM_FIXED, len);  
	BYTE* pmem = (BYTE*)GlobalLock(m_hMem);  
	memcpy(pmem,lpRsrc,len);  
	IStream* pstm;  
	CreateStreamOnHGlobal(m_hMem,FALSE,&pstm);  
	Bitmap* pBitmap = Gdiplus::Bitmap::FromStream(pstm);  
	GlobalUnlock(m_hMem);  
	GlobalFree(m_hMem);
	pstm->Release();  
	FreeResource(lpRsrc); 

	HBITMAP hBitmap = NULL;
	Status status = pBitmap->GetLastStatus();
	if(Ok == status)
	{		
		status = pBitmap->GetHBITMAP(Color(0,0,0), &hBitmap);
		delete pBitmap;

		if(Ok == status)
		{
			if(bitmap.m_hObject != NULL)
			{
				bitmap.Detach();
			}
			bitmap.Attach(hBitmap);

			BITMAP bmInfo;
			::GetObject( bitmap.m_hObject, sizeof(BITMAP), &bmInfo );
			size.cx = bmInfo.bmWidth;
			size.cy = bmInfo.bmHeight;				

			return TRUE;
		}
	}

	return FALSE;
}
// 读取图标(从内存中加载)
BOOL LoadIconFromMem(BYTE* pByte, DWORD dwSize, HICON &hIcon)
{
	// 根据文件大小分配HGLOBAL内存
	HGLOBAL hGlobal = GlobalAlloc( GMEM_MOVEABLE | GMEM_NODISCARD, dwSize );
	if ( !hGlobal )
	{
		TRACE( _T( "Load (file): Error allocating memory\n" ) );
		return FALSE;
	};

	char *pData = reinterpret_cast<char*>(GlobalLock(hGlobal));
	if ( !pData )
	{
		TRACE( _T( "Load (file): Error locking memory\n" ) );
		GlobalFree( hGlobal );
		return FALSE;
	};

	// 将文件内容读到HGLOBAL内存中
	memcpy(pData, pByte, dwSize);
	GlobalUnlock( hGlobal );

	// 利用hGlobal内存中的数据创建stream
	IStream *pStream = NULL;
	if ( CreateStreamOnHGlobal( hGlobal, TRUE, &pStream ) != S_OK )
	{
		return FALSE;
	}

	Bitmap* pBitmap = Gdiplus::Bitmap::FromStream(pStream);

	// 要加上这一句,否则由GlobalAlloc得来的hGlobal内存没有被释放,导致内存泄露,由于
	// CreateStreamOnHGlobal第二个参数被设置为TRUE,所以调用pStream->Release()会自动
	// 将hGlobal内存(参见msdn对CreateStreamOnHGlobal的说明)
	pStream->Release();

	HBITMAP hBitmap = NULL;
	Status status = pBitmap->GetLastStatus();
	if(Ok == status)
	{
		status = pBitmap->GetHICON(&hIcon);
		delete pBitmap;

		if(Ok == status)
		{
			return TRUE;
		}
	}

	return FALSE;
}
Beispiel #8
0
int SSkinGif::LoadFromFile( LPCTSTR pszFileName )
{
    Bitmap *pImg = Bitmap::FromFile(S_CT2W(pszFileName));
    if(!pImg) return 0;
    if(pImg->GetLastStatus() != Gdiplus::Ok)
    {
        delete pImg;
        return 0;
    }

    LoadFromGdipImage(pImg);
    delete pImg;
    return m_nFrames;
}
Beispiel #9
0
LIBELCBASEUI_API BOOL LoadImageFromBuffer(LPBYTE lpBuffer, int cbBuffer, CBitmap* pBitmap, CSize& size)
{
	AFX_MANAGE_STATE(AfxGetStaticModuleState());

	if (!lpBuffer || cbBuffer <= 0 || !pBitmap)
		return FALSE;

	IStream* pstm = NULL;
	Bitmap *pImage = NULL;
	BOOL bSuccessful = FALSE;
	PBYTE pMem = NULL;
	HGLOBAL hMem = NULL;
	
	do 
	{
		hMem = GlobalAlloc(GMEM_FIXED, cbBuffer);
		pMem = (BYTE*)GlobalLock(hMem);
		memcpy(pMem, lpBuffer, cbBuffer);
		CreateStreamOnHGlobal(hMem, FALSE, &pstm);

		pImage = Bitmap::FromStream(pstm);
		if (!pImage || pImage->GetLastStatus() != Ok)
			break;

		HBITMAP hBitmap = NULL;
		pImage->GetHBITMAP(Color::White, &hBitmap);
		pBitmap->DeleteObject();
		if (!pBitmap->Attach(hBitmap))
			break;

		BITMAP bm;
		GetObject(pBitmap->m_hObject, sizeof(bm), &bm);

		size.cx = pImage->GetWidth();
		size.cy = pImage->GetHeight();

		bSuccessful = TRUE;
	} while (0);

	if (hMem)
		GlobalUnlock(hMem);
	if (pstm)
		pstm->Release();
	if (pImage)
		delete pImage;

	return bSuccessful;
}
Beispiel #10
0
Bitmap* CExampleDemoDlg::ReadBitmap(string path)
{
	
	const char* szName = path.c_str();


	WCHAR wstr[1000];
	MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, szName, -1, wstr, 1000);

	Bitmap* pInImage = Bitmap::FromFile(wstr);
	if (pInImage->GetLastStatus() == -1)
	{
		SAFE_DELETE(pInImage);
		return NULL;
	}
	return pInImage;

}
Beispiel #11
0
vector<Bitmap*> CExampleDemoDlg::LoadTemplateImg(string filesrc)
{
	vector<Bitmap*> tempplate;
	vector<string>filepathname;
	ScanDirectory(filesrc, ".jpg", filepathname);//filesrc是文件夹名字
	//std::sort(filepathname.begin(),filepathname.end());
	for (int i = 0; i < filepathname.size(); i++)
	{
		string image = filesrc+"\\"+ filepathname[i];
		std::wstring widestr = std::wstring(image.begin(), image.end());
		Bitmap* pInImage = Bitmap::FromFile(widestr.c_str());
		if (pInImage->GetLastStatus() == -1)
		{
			SAFE_DELETE(pInImage);
			continue;
		}

		Bitmap*  img = pInImage->Clone(0, 0, pInImage->GetWidth(), pInImage->GetHeight(), PixelFormat32bppARGB);
		tempplate.push_back(img);
	}
	return tempplate;
}
Beispiel #12
0
BOOL GDImage::_LoadImage( const WCHAR *pImageFilename )
{
	if ( m_filename == std::wstring(pImageFilename ? pImageFilename : L"") )
	{
		return true;
	}

	if ( m_pImage != NULL )
	{
		m_filename.clear();
		delete m_pImage;
		m_pImage = NULL;
	}

	if ( pImageFilename == NULL )
	{
		return TRUE;
	}

	// Try to laod the file if it exists
	//Bitmap *pNewImage = Bitmap::FromFile( pImageFilename );
	Bitmap *pNewImage = new Bitmap( pImageFilename );
	Status loadStatus = pNewImage->GetLastStatus();

	if ( loadStatus != Ok )
	{
		// Failed to laod image
		delete pNewImage;
		return FALSE;
	}

	m_filename = pImageFilename;
	m_pImage = pNewImage;

	return TRUE;
}
Beispiel #13
0
/********************************************************************
 GdipBitmapFromResource - read a GDI+ image out of a resource stream

********************************************************************/
extern "C" HRESULT DAPI GdipBitmapFromResource(
    __in_opt HINSTANCE hinst,
    __in_z LPCSTR szId,
    __out Bitmap **ppBitmap
    )
{
    HRESULT hr = S_OK;
    LPVOID pvData = NULL;
    DWORD cbData = 0;
    HGLOBAL hGlobal = NULL;;
    LPVOID pv = NULL;
    IStream *pStream = NULL;
    Bitmap *pBitmap = NULL;
    Status gs = Ok;

    hr = ResReadData(hinst, szId, &pvData, &cbData);
    ExitOnFailure(hr, "Failed to load GDI+ bitmap from resource.");

    // Have to copy the fixed resource data into moveable (heap) memory
    // since that's what GDI+ expects.
    hGlobal = ::GlobalAlloc(GMEM_MOVEABLE, cbData);
    ExitOnNullWithLastError(hGlobal, hr, "Failed to allocate global memory.");

    pv = ::GlobalLock(hGlobal);
    ExitOnNullWithLastError(pv, hr, "Failed to lock global memory.");

    memcpy(pv, pvData, cbData);

    ::GlobalUnlock(pv); // no point taking any more memory than we have already
    pv = NULL;

    hr = ::CreateStreamOnHGlobal(hGlobal, TRUE, &pStream);
    ExitOnFailure(hr, "Failed to allocate stream from global memory.");

    hGlobal = NULL; // we gave the global memory to the stream object so it will close it

    pBitmap = Bitmap::FromStream(pStream);
    ExitOnNull(pBitmap, hr, E_OUTOFMEMORY, "Failed to allocate bitmap from stream.");

    gs = pBitmap->GetLastStatus();
    ExitOnGdipFailure(gs, hr, "Failed to load bitmap from stream.");

    *ppBitmap = pBitmap;
    pBitmap = NULL;

LExit:
    if (pBitmap)
    {
        delete pBitmap;
    }

    ReleaseObject(pStream);

    if (pv)
    {
        ::GlobalUnlock(pv);
    }

    if (hGlobal)
    {
        ::GlobalFree(hGlobal);
    }

    return hr;
}
Beispiel #14
0
//----------------------------------------------------------------------------------------------------------------------
//  DO IMAGE LIST
//----------------------------------------------------------------------------------------------------------------------
void cListView :: do_image_list ( const cFigViewItemList * pList )
{
	mojo::cPtI IconSize = get_icon_size ();
	int iDimX = IconSize.x;
	int iDimY = IconSize.y;

	HIMAGELIST hIL = ImageList_Create ( iDimX, iDimY, LR_CREATEDIBSECTION | ILC_COLOR32, pList->qty(), 1 );

	//------------------------------------------
	//  LOAD DEFAULT IMAGES
	//------------------------------------------

	const int * aiBitmap = default_bitmap_ids ();

	for ( int i = 0; aiBitmap[i]; i++ )
	{
		HANDLE hBitmap = LoadImage ( g_hInstance, MAKEINTRESOURCE ( aiBitmap[i] ), IMAGE_BITMAP, 0, 0, LR_CREATEDIBSECTION );
		ImageList_Add ( hIL, (HBITMAP) hBitmap, NULL );
	}

	int iItemIndex = 0;
	for ( cFigViewItem * p = pList->pHead; p; p = p->pNext, iItemIndex++ )
	{
		bool bLoadedFromFile = false;
		int iImageIndex = 0;

		//-------------------------------
		// TRY TO LOAD IMAGE FROM FILE
		//-------------------------------

		if ( p->sIconPath.len() )
		{
			if ( ! file_exists ( p->sIconPath.cstr() ) )
			{
				mojo::put_ad_lib_memo ( mojo::cMemo::error, L"Image file not found", L"%s", p->sIconPath.cstr() );
				cStrW s;
				s.f ( L"Image file not found: %s", p->sIconPath.cstr() );
				LOG ( s.cstr() );
			}

			else
			{
				HICON hIcon;
				Bitmap bm ( p->sIconPath.cstr() );
				if ( ! ( Ok == bm.GetLastStatus() ) )
					LOG_V ( L"Bitmap constructor failed with %s.", p->sIconPath.cstr() );

				else
				{
					bm.GetHICON(&hIcon);
					if ( Ok !=  bm.GetLastStatus() )
						LOG_V ( L"Bitmap::GetHICON() failed with %s", p->sIconPath.cstr() );

					else
					{
						iImageIndex = ImageList_AddIcon( hIL, hIcon );
						bLoadedFromFile = true;
					}
				}

				if ( ! bLoadedFromFile)
					mojo::put_ad_lib_memo ( mojo::cMemo::error, L"Unable to display image file", L"%s", p->sIconPath.cstr() );
			}
		}

		if ( ! bLoadedFromFile )
		{
			iImageIndex = 0;;
		}
#if 0

		LVITEM lvi;
		ZeroMemory ( &lvi, sizeof(lvi) );
		lvi.mask = LVIF_IMAGE;
		lvi.iItem = iItemIndex;
		lvi.iImage = iImageIndex;
		ListView_SetItem ( hwnd, &lvi );
#endif
	}

	HIMAGELIST hResult = ListView_SetImageList ( hwnd, hIL, LVSIL_NORMAL ); 
	hResult;
}
Beispiel #15
0
/*
** Sets the system wallpapar.
**
*/
void System::SetWallpaper(const std::wstring& wallpaper, const std::wstring& style)
{
	if (!wallpaper.empty())
	{
		if (_waccess(wallpaper.c_str(), 0) == -1)
		{
			LogErrorF(L"!SetWallpaper: Unable to read file: %s", wallpaper.c_str());
			return;
		}

		Bitmap* bitmap = Bitmap::FromFile(wallpaper.c_str());
		if (bitmap && bitmap->GetLastStatus() == Ok)
		{
			std::wstring file = GetRainmeter().GetSettingsPath() + L"Wallpaper.bmp";

			const CLSID bmpClsid = { 0x557cf400, 0x1a04, 0x11d3, { 0x9a, 0x73, 0x0, 0x0, 0xf8, 0x1e, 0xf3, 0x2e } };
			if (bitmap->Save(file.c_str(), &bmpClsid) == Ok)
			{
				if (!style.empty())
				{
					HKEY hKey;
					if (RegOpenKeyEx(HKEY_CURRENT_USER, L"Control Panel\\Desktop", 0, KEY_SET_VALUE, &hKey) == ERROR_SUCCESS)
					{
						const WCHAR* wallStyle = nullptr;
						const WCHAR* wallTile = L"0";

						const WCHAR* option = style.c_str();
						if (_wcsicmp(option, L"CENTER") == 0)
						{
							wallStyle = L"0";
						}
						else if (_wcsicmp(option, L"TILE") == 0)
						{
							wallStyle = L"0";
							wallTile = L"1";
						}
						else if (_wcsicmp(option, L"STRETCH") == 0)
						{
							wallStyle = L"2";
						}
						else if (Platform::IsAtLeastWin7())
						{
							if (_wcsicmp(option, L"FIT") == 0)
							{
								wallStyle = L"6";
							}
							else if (_wcsicmp(option, L"FILL") == 0)
							{
								wallStyle = L"10";
							}
						}

						if (wallStyle)
						{
							RegSetValueEx(hKey, L"WallpaperStyle", 0, REG_SZ, (const BYTE*)wallStyle, sizeof(WCHAR) * 2);
							RegSetValueEx(hKey, L"TileWallpaper", 0, REG_SZ, (const BYTE*)wallTile, sizeof(WCHAR) * 2);
						}
						else
						{
							LogError(L"!SetWallpaper: Invalid style");
						}

						RegCloseKey(hKey);
					}
				}

				SystemParametersInfo(SPI_SETDESKWALLPAPER, 0, (void*)file.c_str(), SPIF_UPDATEINIFILE);
			}
		}

		delete bitmap;
	}
}
// 读取图片(从内存中加载)
BOOL LoadBitmapFromMem(BYTE* pByte, DWORD dwSize, CBitmap &bitmap, CSize &size)
{
	// 根据文件大小分配HGLOBAL内存
	HGLOBAL hGlobal = GlobalAlloc( GMEM_MOVEABLE | GMEM_NODISCARD, dwSize );
	if ( !hGlobal )
	{
		TRACE( _T( "Load (file): Error allocating memory\n" ) );
		return FALSE;
	};

	char *pData = reinterpret_cast<char*>(GlobalLock(hGlobal));
	if ( !pData )
	{
		TRACE( _T( "Load (file): Error locking memory\n" ) );
		GlobalFree( hGlobal );
		return FALSE;
	};

	// 将文件内容读到HGLOBAL内存中
	memcpy(pData, pByte, dwSize);
	GlobalUnlock( hGlobal );

	// 利用hGlobal内存中的数据创建stream
	IStream *pStream = NULL;
	if ( CreateStreamOnHGlobal( hGlobal, TRUE, &pStream ) != S_OK )
	{
		return FALSE;
	}

	Bitmap* pBitmap = Gdiplus::Bitmap::FromStream(pStream);

	// 要加上这一句,否则由GlobalAlloc得来的hGlobal内存没有被释放,导致内存泄露,由于
	// CreateStreamOnHGlobal第二个参数被设置为TRUE,所以调用pStream->Release()会自动
	// 将hGlobal内存(参见msdn对CreateStreamOnHGlobal的说明)
	pStream->Release();

	HBITMAP hBitmap = NULL;
	Status status = pBitmap->GetLastStatus();
	if(Ok == status)
	{		
		status = pBitmap->GetHBITMAP(Color(0,0,0), &hBitmap);
		delete pBitmap;

		if(Ok == status)
		{
			if(bitmap.m_hObject != NULL)
			{
				bitmap.Detach();
			}
			bitmap.Attach(hBitmap);

			BITMAP bmInfo;
			::GetObject( bitmap.m_hObject, sizeof(BITMAP), &bmInfo );
			size.cx = bmInfo.bmWidth;
			size.cy = bmInfo.bmHeight;				

			return TRUE;
		}
	}

	return FALSE;
}
Beispiel #17
0
/*
** Loads the image from file handle
**
*/
Bitmap* TintedImage::LoadImageFromFileHandle(HANDLE fileHandle, DWORD fileSize, HGLOBAL* phBuffer)
{
	HGLOBAL hBuffer = ::GlobalAlloc(GMEM_MOVEABLE, fileSize);
	if (hBuffer)
	{
		void* pBuffer = ::GlobalLock(hBuffer);
		if (pBuffer)
		{
			DWORD readBytes;
			ReadFile(fileHandle, pBuffer, fileSize, &readBytes, nullptr);
			::GlobalUnlock(hBuffer);

			IStream* pStream = nullptr;
			if (::CreateStreamOnHGlobal(hBuffer, FALSE, &pStream) == S_OK)
			{
				Bitmap* bitmap = Bitmap::FromStream(pStream);
				pStream->Release();

				if (Ok == bitmap->GetLastStatus())
				{
					GUID guid;
					if (Ok == bitmap->GetRawFormat(&guid) && guid != ImageFormatIcon)
					{
						// Gather EXIF orientation information
						if (m_UseExifOrientation)
						{
							UINT size = bitmap->GetPropertyItemSize(PropertyTagOrientation);
							if (size)
							{
								RotateFlipType flip = RotateNoneFlipNone;
								PropertyItem* orientation = (PropertyItem*)new BYTE[size];
								bitmap->GetPropertyItem(PropertyTagOrientation, size, orientation);
								if (orientation)
								{
									switch(*(short*)orientation->value)
									{
									case 8:
										flip = Rotate270FlipNone;
										break;

									case 7:
										flip = Rotate270FlipX;
										break;

									case 6:
										flip = Rotate90FlipNone;
										break;

									case 5:
										flip = Rotate90FlipX;
										break;

									case 4:
										flip = Rotate180FlipX;
										break;

									case 3:
										flip = Rotate180FlipNone;
										break;

									case 2:
										flip = RotateNoneFlipX;
										break;

									default:
										flip = RotateNoneFlipNone;
									}

									bitmap->RotateFlip(flip);
								}
								delete [] orientation;
							}
						}

						////////////////////////////////////////////
						// Convert loaded image to faster blittable bitmap (may increase memory usage slightly)
						Rect r(0, 0, bitmap->GetWidth(), bitmap->GetHeight());
						Bitmap* clone = new Bitmap(r.Width, r.Height, PixelFormat32bppPARGB);
						{
							Graphics graphics(clone);
							graphics.DrawImage(bitmap, r, 0, 0, r.Width, r.Height, UnitPixel);
						}
						delete bitmap;
						bitmap = clone;

						::GlobalFree(hBuffer);
						hBuffer = nullptr;
						////////////////////////////////////////////
					}
					*phBuffer = hBuffer;
					return bitmap;
				}

				delete bitmap;
			}
		}

		::GlobalFree(hBuffer);
	}

	*phBuffer = nullptr;
	return nullptr;
}
int loadImage(struct textureTableIndexStruct *tti, char *fname)
{
	/* http://msdn.microsoft.com/en-us/library/ms536298(VS.85).aspx   GDI+ Lockbits example - what this function is based on*/
	/* http://www.microsoft.com/downloads/details.aspx?FamilyID=6a63ab9c-df12-4d41-933c-be590feaa05a&DisplayLang=en  GDI+ redistributable download - gdiplus.dll 2MB */
	if(!loaded)
	{
		initImageLoader();
		loaded = 1;
	}
	// convert to wide char http://msdn.microsoft.com/en-us/library/ms235631(VS.80).aspx   
	//fname = "C:/source2/freewrl/freex3d/tests/helpers/brick.png";  
    //fname = "junk.jpg"; //test failure condition
	size_t origsize = strlen(fname) + 1;
	char* fname2 = (char*) malloc(origsize);
	strcpy(fname2,fname);
	for(int jj=0;jj<strlen(fname2);jj++)
		if(fname2[jj] == '/' ) fname2[jj] = '\\';

    const size_t newsize = 225;
    size_t convertedChars = 0;
    wchar_t wcstring[newsize];
    //mbstowcs_s(&convertedChars, wcstring, origsize, fname, _TRUNCATE);
#if _MSC_VER >= 1500
    mbstowcs_s(&convertedChars, wcstring, origsize, fname2, _TRUNCATE);
#else
    mbstowcs(wcstring, fname2, MB_CUR_MAX);
#endif

	free(fname2);
	Bitmap *bitmap = NULL;
	Status stat;
	bitmap = Bitmap::FromFile(wcstring,false); //new Bitmap(wcstring); //or Bitmap::FromFile(wcstring,false); L"LockBitsTest1.bmp");
	// verifying the success of constructors http://msdn.microsoft.com/en-us/library/ms533801(VS.85).aspx

	stat = bitmap->GetLastStatus(); // http://msdn.microsoft.com/en-us/library/ms535410(VS.85).aspx
	if(stat != Ok)
		return 0; //should come here if it can't find the image file
   BitmapData* bitmapData = new BitmapData;

//#define verbose 1
#ifdef verbose
   printf("bitmap W=%d H=%d\n",bitmap->GetWidth(),bitmap->GetHeight());
   /* http://msdn.microsoft.com/en-us/library/ms535387(VS.85).aspx GetPixelFormat
	  http://msdn.microsoft.com/en-us/library/ms534412(v=VS.85).aspx  pixelFormat constants
	  http://msdn.microsoft.com/en-us/library/ms534136(v=VS.85).aspx   Image::GetFlags ImageFlagsColorSpaceGRAY      = 0x0040,

   */
   UINT flags = bitmap->GetFlags();
   printf("The value of flags, in hexadecimal form, is %x.\n", flags);

   // Is the ColorSpaceRGB flag set?
   if(flags & ImageFlagsColorSpaceRGB)
      printf("The ColorSpaceRGB flag is set.\n");
   else if(flags & ImageFlagsColorSpaceGRAY)
     printf("The ColorSpaceGRAY flag is set.\n");
   printf("bitmap format index =%d %d\n",bitmap->GetPixelFormat()%256,bitmap->GetPixelFormat());
   if(Gdiplus::IsAlphaPixelFormat(bitmap->GetPixelFormat()) ) 
	   printf("has alpha channel\n");
   else
	   printf("no alpha channel\n");
   if(Gdiplus::IsCanonicalPixelFormat(bitmap->GetPixelFormat()) )
	   printf("is canonical\n");
   else
	   printf("not canonical\n");
   printf("Number of bits per pixel %d\n",Gdiplus::GetPixelFormatSize(bitmap->GetPixelFormat()));
#endif
#undef verbose
   bool flipVertically = true;
   Rect rect(0,0,bitmap->GetWidth(),bitmap->GetHeight());
   if(flipVertically)
		bitmapData->Stride = -bitmap->GetWidth()*4;
   else
	   bitmapData->Stride = bitmap->GetWidth()*4;
   bitmapData->Width = bitmap->GetWidth();
   bitmapData->Height = bitmap->GetHeight();
   bitmapData->PixelFormat = PixelFormat32bppARGB;
   int totalbytes = bitmap->GetWidth() * bitmap->GetHeight() * 4; //tti->depth;
   unsigned char * blob = (unsigned char*)malloc(totalbytes);
   if(flipVertically)
		bitmapData->Scan0 = &blob[bitmap->GetWidth()*bitmap->GetHeight()*4 + bitmapData->Stride]; 
   else
	   bitmapData->Scan0 = blob;

   // Lock a rectangular portion of the bitmap for reading.
   bitmap->LockBits(
      &rect,
      ImageLockModeRead|ImageLockModeUserInputBuf,
	  PixelFormat32bppARGB, //PixelFormat24bppRGB, 
      bitmapData);

#ifdef verbose
   printf("The stride is %d.\n\n", bitmapData->Stride);
   printf("bitmapData W=%d H=%d\n",bitmapData->Width,bitmapData->Height);
#endif
#ifdef verbose

   // Display the hexadecimal value of each pixel in the 5x3 rectangle.
   UINT* pixels = (UINT*)bitmapData->Scan0;

   for(UINT row = 0; row < 23; ++row)
   {
      for(UINT col = 0; col < 5; ++col)
      {
         printf("%x\n", pixels[row * bitmapData->Stride / 4 + col]);
      }
      printf("- - - - - - - - - - \n");
   }
#endif

   //deep copy data so browser owns it (and does its FREE_IF_NZ) and we can delete our copy here and forget about it
   tti->x = bitmapData->Width;
   tti->y = bitmapData->Height;
   tti->frames = 1;
   tti->texdata = blob; 
   if(!blob)
	   printf("ouch in gdiplus image loader L140 - no image data\n");
   //tti->hasAlpha = Gdiplus::IsAlphaPixelFormat(bitmapData->PixelFormat)?1:0; 
   tti->hasAlpha = Gdiplus::IsAlphaPixelFormat(bitmap->GetPixelFormat())?1:0; 
   //printf("fname=%s alpha=%ld\n",fname,tti->hasAlpha);

#ifdef verbose
   for(UINT row = 0; row < 23; ++row)
   {
      for(UINT col = 0; col < 5; ++col)
      {
         //printf("%x\n", *(UINT*)&(tti->texdata[(row * bitmapData->Stride / 4 + col)*tti->depth]));
         printf("%x\n", *(UINT*)&(tti->texdata[(row * tti->x + col)*4])); //tti->depth]));
      }
      printf("- - - - - - - - - - \n");
   }
#endif

   tti->filename = fname;
  // wrong: tti->status = TEX_NEEDSBINDING; //make this the last thing you set, because another thread is watching ready to bind
   // wrong - let the calling function set the status otherwise textures disappear sometimes


   bitmap->UnlockBits(bitmapData);
   delete bitmapData;
   delete bitmap;
   //shutdownImageLoader();  //we'll keep it loaded
   if(0)
   {
	   shutdownImageLoader();
	   loaded = 0;
   }

   return 1;

}