Example #1
0
bool FreeimagelibPlugin::LoadDoc(cpcl::IOStream *input, plcl::Doc **r) {
	FREE_IMAGE_FORMAT fif = (FREE_IMAGE_FORMAT)freeimagelib_format;
	FreeimagelibStuff stuff(input);
	boost::shared_ptr<FIBITMAP> fibitmap(FreeImage_LoadFromHandle(fif, &stuff.io, stuff.io_handle), FreeImage_Unload);
	if (!fibitmap) {
		cpcl::Error(cpcl::StringPieceFromLiteral("FreeimagelibPlugin::LoadDoc(): unable to load image"));
		return false;
	}
	
	if (FreeImage_GetImageType(fibitmap.get()) != FIT_BITMAP) {
		boost::shared_ptr<FIBITMAP> tmp(FreeImage_ConvertToType(fibitmap.get(), FIT_BITMAP), FreeImage_Unload);
		if (!tmp || (FreeImage_GetImageType(tmp.get()) != FIT_BITMAP)) {
			cpcl::Error(cpcl::StringPieceFromLiteral("FreeimagelibPlugin::LoadDoc(): unable to convert the image to FIT_BITMAP"));
			return false;
		}
		fibitmap = tmp;
	}

	unsigned int const bpp = FreeImage_GetBPP(fibitmap.get());
	if (!(bpp == 24 || bpp == 32)) {
		boost::shared_ptr<FIBITMAP> tmp((bpp > 32) ? FreeImage_ConvertTo32Bits(fibitmap.get()) : FreeImage_ConvertTo24Bits(fibitmap.get()), FreeImage_Unload);
		if (!tmp) {
			cpcl::Trace(CPCL_TRACE_LEVEL_ERROR,
				"FreeimagelibPlugin::LoadDoc(): unable to convert image with bpp %u",
				bpp);
		}
		fibitmap = tmp;
	}

	if (r)
		*r = new FreeimagelibDoc(fibitmap);
	return true;
}
Example #2
0
bool ImageImporter::load(QIODevice *device)
{
	d->deleteBitmap();
	
	FreeImage_SetOutputMessage(outputMessage);
	
	FreeImageIO io;
	io.read_proc = readFromQIODevice;
	io.write_proc = 0;
	io.seek_proc = seekQIODevice;
	io.tell_proc = tellQIODevice;
	
	auto format = FreeImage_GetFileTypeFromHandle(&io, device);
	
	if (format != FIF_UNKNOWN)
	{
		int flags = 0;
		
		if (format == FIF_JPEG)
			flags = JPEG_ACCURATE;
		
		d->bitmap = FreeImage_LoadFromHandle(format, &io, device, flags);
	}
	
	if (d->bitmap)
	{
		int w = FreeImage_GetWidth(d->bitmap);
		int h = FreeImage_GetHeight(d->bitmap);
		
		d->size = QSize(w, h);
	}
	
	return d->bitmap;
}
Example #3
0
void CContent::init()
{
	//just load one image for now, testing only
	FILE * file = fopen("Resources\\Sprites\\zfgc.png", "rb");
	FreeImageIO io;
	

	//load the image data
	io.read_proc  = _readProc;
	io.write_proc = _writeProc;
	io.seek_proc  = _seekProc;
	io.tell_proc  = _tellProc;

	FREE_IMAGE_FORMAT format = FreeImage_GetFileTypeFromHandle(&io, (fi_handle)file, 0);

	if (format != FIF_PNG)
		return;



	FIBITMAP * dib = FreeImage_LoadFromHandle(format, &io, (fi_handle)file, 0);
	fclose(file);
	_sprites.insert(std::pair<std::string, FIBITMAP *>("test", dib));

}
Example #4
0
FIBITMAP * DLL_CALLCONV
FreeImage_LoadFromMemory(FREE_IMAGE_FORMAT fif, FIMEMORY *stream, int flags) {
	if (stream && stream->data) {
		FreeImageIO io;
		SetMemoryIO(&io);

		return FreeImage_LoadFromHandle(fif, &io, (fi_handle)stream, flags);
	}

	return NULL;
}
Example #5
0
BOOL fipImage::loadFromHandle(FreeImageIO *io, fi_handle handle, int flag) {
	FREE_IMAGE_FORMAT fif = FIF_UNKNOWN;

	// check the file signature and get its format
	fif = FreeImage_GetFileTypeFromHandle(io, handle, 16);
	if((fif != FIF_UNKNOWN) && FreeImage_FIFSupportsReading(fif)) {
		// Free the previous dib
		if(_dib) {
			FreeImage_Unload(_dib);			
		}
		// Load the file
		_dib = FreeImage_LoadFromHandle(fif, io, handle, flag);
		_bHasChanged = TRUE;
		if(_dib == NULL)
			return FALSE;
		return TRUE;
	}
	return FALSE;
}
Example #6
0
int psdThumbnail::Read(FreeImageIO *io, fi_handle handle, int iResourceSize, bool isBGR) {
	BYTE ShortValue[2], IntValue[4];
	int nBytes=0, n;

	// remove the header size (28 bytes) from the total data size
	int iTotalData = iResourceSize - 28;

	const long block_end = io->tell_proc(handle) + iTotalData;	
	
	n = (int)io->read_proc(&IntValue, sizeof(IntValue), 1, handle);
	nBytes += n * sizeof(IntValue);
	_Format = psdGetValue(IntValue, sizeof(_Format) );
	
	n = (int)io->read_proc(&IntValue, sizeof(IntValue), 1, handle);
	nBytes += n * sizeof(IntValue);
	_Width = psdGetValue(IntValue, sizeof(_Width) );
	
	n = (int)io->read_proc(&IntValue, sizeof(IntValue), 1, handle);
	nBytes += n * sizeof(IntValue);
	_Height = psdGetValue(IntValue, sizeof(_Height) );
	
	n = (int)io->read_proc(&IntValue, sizeof(IntValue), 1, handle);
	nBytes += n * sizeof(IntValue);
	_WidthBytes = psdGetValue(IntValue, sizeof(_WidthBytes) );

	n = (int)io->read_proc(&IntValue, sizeof(IntValue), 1, handle);
	nBytes += n * sizeof(IntValue);
	_Size = psdGetValue(IntValue, sizeof(_Size) );

	n = (int)io->read_proc(&IntValue, sizeof(IntValue), 1, handle);
	nBytes += n * sizeof(IntValue);
	_CompressedSize = psdGetValue(IntValue, sizeof(_CompressedSize) );

	n = (int)io->read_proc(&ShortValue, sizeof(ShortValue), 1, handle);
	nBytes += n * sizeof(ShortValue);
	_BitPerPixel = (short)psdGetValue(ShortValue, sizeof(_BitPerPixel) );

	n = (int)io->read_proc(&ShortValue, sizeof(ShortValue), 1, handle);
	nBytes += n * sizeof(ShortValue);
	_Planes = (short)psdGetValue(ShortValue, sizeof(_Planes) );

	const long JFIF_startpos = io->tell_proc(handle);

	if(_dib) {
		FreeImage_Unload(_dib);
	}

	if(_Format == 1) {
		// kJpegRGB thumbnail image
		_dib = FreeImage_LoadFromHandle(FIF_JPEG, io, handle);
		if(isBGR) {
			SwapRedBlue32(_dib);
		}			
		// HACK: manually go to end of thumbnail, because (for some reason) LoadFromHandle consumes more bytes then available! 
		io->seek_proc(handle, block_end, SEEK_SET);
	}
	else {
		// kRawRGB thumbnail image		
		// ### Unimplemented (should be trivial)

		// skip the thumbnail part
		io->seek_proc(handle, iTotalData, SEEK_CUR);
		return iResourceSize;
	}
	
	nBytes += (block_end - JFIF_startpos); 

	return nBytes;
}
Example #7
0
Auto<Resource> Texture2DLoader::LoadResource(ResourceManager& resourceManager, istream& inputStream, const std::string& internalName)
{
	FreeImageIO io;
	fi_handle handle = (fi_handle)(&inputStream);

	io.read_proc = [] (void *buffer, unsigned size, unsigned count, fi_handle handle) {
		istream* input = (istream*)handle;
		unsigned bytes = size * count;

		unsigned totalRead = 0;
		unsigned loopRead = 0;

		do
		{
			input->read((char*)buffer + totalRead, bytes - totalRead);
			loopRead = (unsigned)input->gcount();
			totalRead += loopRead;
		} while (loopRead > 0 && totalRead < bytes);

		unsigned result = totalRead / size;
		unsigned overRead = totalRead % size;

		if (overRead > 0)
		{
			input->seekg(-(int)overRead, ios_base::cur);
		}

		return result;
	};

	io.write_proc = NULL;
	io.seek_proc = [] (fi_handle handle, long offset, int origin) {
		istream* input = (istream*)handle;

		ios_base::seekdir seekDir = 
			(origin == SEEK_END) ? ios_base::end : (
			(origin == SEEK_CUR) ? ios_base::cur : ios_base::beg);

		try
		{
			input->seekg(offset, seekDir);
			return (int)(input->fail() ? 1 : 0);
		}
		catch (ios_base::failure&)
		{
			return (int)1;
		}
	};

	io.tell_proc = [](fi_handle handle) {
		istream* input = (istream*)handle;
		return (long)input->tellg();
	};

	FREE_IMAGE_FORMAT imageFormat = FreeImage_GetFileTypeFromHandle(&io, handle, 0);
	
	if (imageFormat == FIF_UNKNOWN)
	{
		throw FormatException("Unrecogized image format");
	}

	FIBITMAP* bitmap = FreeImage_LoadFromHandle(imageFormat, &io, handle, 0);

	FREE_IMAGE_TYPE dataType = FreeImage_GetImageType(bitmap);

	DataFormat::Type formatType;
	size_t channelCount = 0;

	vector<unsigned char> textureData;

	Vector2i size(FreeImage_GetWidth(bitmap), FreeImage_GetHeight(bitmap));

	if (dataType == FIT_BITMAP)
	{
		formatType = DataFormat::Int8UNorm;
		channelCount = 4;

		FIBITMAP* bitmap32Bit = FreeImage_ConvertTo32Bits(bitmap);

		FreeImage_Unload(bitmap);

		bitmap = bitmap32Bit;

		textureData.resize(FreeImage_GetPitch(bitmap) * size.y);

		SwapChannels<unsigned char>(FreeImage_GetBits(bitmap), &textureData.front(), 0, 2, size.x * size.y, 4);
	}
	else
	{
		throw FormatException("Unsupported depth format");
	}

	Auto<Texture2D> result = resourceManager.GetGraphics()->CreateTexture2D(size, DataFormat(formatType, channelCount));

	result->LoadMemory(&textureData.front());
	result->GenerateMipmaps();

	if (bitmap != NULL)
	{
		FreeImage_Unload(bitmap);
		bitmap = NULL;
	}

	return result;
}
Example #8
0
bool Image::load (const char* fname)
{
	release () ;

//	createTestData () ;
//	return true ;

	char buf[256] ;
	sprintf_s (buf, sizeof (buf), "image\\%s", fname) ;
//	fname = "image\\avatar000.png" ;

	FILE* pFile = NULL ;
	fopen_s (&pFile, buf, "rb") ;
	if (pFile == NULL)
		return false ;

	FreeImageIO io;

	io.read_proc  = myReadProc;
	io.write_proc = myWriteProc;
	io.seek_proc  = mySeekProc;
	io.tell_proc  = myTellProc;

	// find the buffer format
	FREE_IMAGE_FORMAT fif = FreeImage_GetFileTypeFromHandle(&io, (fi_handle)pFile, 0);

	if(fif == FIF_UNKNOWN) 
	{
	   /* Close the file */
		fclose(pFile);
		return false ;
	}

	// load from the file handle
	FIBITMAP *dib = FreeImage_LoadFromHandle(fif, &io, (fi_handle)pFile, 0);
		
	BYTE* pPixelData = FreeImage_GetBits(dib) ;

	int width, height,pitch  ;
	width =  FreeImage_GetWidth(dib);
	height = FreeImage_GetHeight(dib);
	pitch = FreeImage_GetPitch(dib);
	int bpp = FreeImage_GetBPP(dib) ;
	assert (bpp == 32) ;

	FREE_IMAGE_TYPE image_type = FreeImage_GetImageType(dib) ;
	assert (image_type == FIT_BITMAP) ;

//	/*
	//轉換rgba(因為rgba,的順序不同)
	RGBQUAD rgba ;
	BYTE* pBit = pPixelData ;
	for (int i = 0 ; i<height; i++)
	{
		BYTE* pPixel = pBit ;
		for (int m = 0; m<width; m++)
		{
			if (FreeImage_GetPixelColor(dib, m, i, &rgba))
			{
				BYTE tmp = rgba.rgbBlue ;
				rgba.rgbBlue = rgba.rgbRed ;
				rgba.rgbRed = tmp ;
				FreeImage_SetPixelColor (dib, m, i, &rgba) ;
			}
		}
		pBit += pitch ;
	}
//			*/

//---------------------------------------------------
   //把pixel copy給
   //最大記憶體
	if (pPixelData != NULL)
	{
		assert (textureID == NO_TEXTURE_ID) ;
		if (textureID == NO_TEXTURE_ID)
		{
			//空的要先建立
			// Allocates one texture handle
			glGenTextures(1, &textureID);
		}

		assert (textureID != NO_TEXTURE_ID) ;


		// Binds this texture handle so we can load the data into it
		glBindTexture(GL_TEXTURE_2D, textureID);

		glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pPixelData);

		glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
		glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );

		// free the loaded FIBITMAP
		FreeImage_Unload(dib);
	}


	return true ;
}
Example #9
0
CImageDataLoader::CImageData::CImageData(IDataStream* pData)
{
	if(pData->IsValid())
	{
		static bool init = false;
		if(!init)
		{
			init = true;
			
			TLS_data backup = *TLS::getData();
			TLS::getData()->domain_ptr = nullptr;
			TLS::getData()->domain_guid = guidNull;
			FreeImage_Initialise();
			*TLS::getData() = backup;
		}

		TLS_data backup = *TLS::getData();
		TLS::getData()->domain_ptr = nullptr;
		TLS::getData()->domain_guid = guidNull;
		FIBITMAP* fibitmap = FreeImage_LoadFromHandle(FIF_PNG,&ImageLoaderIO,(fi_handle)pData);
		*TLS::getData() = backup;

		if(fibitmap)
		{
			_Width = FreeImage_GetWidth(fibitmap);
			_Height = FreeImage_GetHeight(fibitmap);
			_Format = R8G8B8A8;
			_Data = new u8[_Width*_Height*sizeof(u32)];
			for(int iy =0; iy < _Height; ++iy)
				for(int ix =0; ix < _Width; ++ix)
				{
					RGBQUAD color;
					FreeImage_GetPixelColor(fibitmap,ix,iy,&color);
					((u32*)_Data)[iy*_Width+ix] = ((u32)color.rgbRed << 0) | ((u32)color.rgbGreen << 8) | ((u32)color.rgbBlue << 16) | ((u32)0xff << 24);
				}
			
			TLS_data backup = *TLS::getData();
			TLS::getData()->domain_ptr = nullptr;
			TLS::getData()->domain_guid = guidNull;
	
			FreeImage_Unload(fibitmap);

			*TLS::getData() = backup;

			_Levels = 1;
			return;
		}
		pData->Seek(0,IDataStream::ORIGIN_BEGINNING);
		if(TryLoadBLP(pData))
			return;
		
		pData->Seek(0,IDataStream::ORIGIN_BEGINNING);
		/*
		SparseVirtualTextureFile hsvt;
		if(hsvt.Open(pData))
		{
			_Width = 5120;
			_Height = 5120;
			_Format = R8G8B8A8;
			_Levels = 1;
			_Data = new u8[_Width*_Height*sizeof(u32)];


			hsvt.ReadImageFromVirtualTexture(0,0,_Width,_Height,_Data,6);


			return;
		}
		
		pData->Seek(0,IDataStream::ORIGIN_BEGINNING);*/


	}

	// loading failed
	_Width = 256;
	_Height = 256;
	_Format = R8G8B8A8;
	_Levels = 1;
	_Data = new u8[_Width*_Height*sizeof(u32)];
	for(int iy =0; iy < _Height; ++iy)
		for(int ix =0; ix < _Width; ++ix)
			((u32*)_Data)[iy*_Width+ix] = ((1-((iy/64)+(ix/64))%2) * 0x00ffffff) | 0xff000000;
}
Example #10
0
int 
main(int argc, char *argv[]) {
	
	// call this ONLY when linking with FreeImage as a static library
#ifdef FREEIMAGE_LIB
	FreeImage_Initialise();
#endif // FREEIMAGE_LIB

	// initialize your own FreeImage error handler

	FreeImage_SetOutputMessage(FreeImageErrorHandler);

	// print version & copyright infos

	printf(FreeImage_GetVersion());
	printf("\n");
	printf(FreeImage_GetCopyrightMessage());
	printf("\n");


	if(argc != 2) {
		printf("Usage : LoadFromHandle <input file name>\n");
		return 0;
	}

	// initialize your own IO functions

	FreeImageIO io;

	io.read_proc  = myReadProc;
	io.write_proc = myWriteProc;
	io.seek_proc  = mySeekProc;
	io.tell_proc  = myTellProc;

	FILE *file = fopen(argv[1], "rb");

	if (file != NULL) {
		// find the buffer format
		FREE_IMAGE_FORMAT fif = FreeImage_GetFileTypeFromHandle(&io, (fi_handle)file, 0);

		if(fif != FIF_UNKNOWN) {
			// load from the file handle
			FIBITMAP *dib = FreeImage_LoadFromHandle(fif, &io, (fi_handle)file, 0);

			// save the bitmap as a PNG ...
			const char *output_filename = "test.png";

			// first, check the output format from the file name or file extension
			FREE_IMAGE_FORMAT out_fif = FreeImage_GetFIFFromFilename(output_filename);

			if(out_fif != FIF_UNKNOWN) {
				// then save the file
				FreeImage_Save(out_fif, dib, output_filename, 0);
			}

			// free the loaded FIBITMAP
			FreeImage_Unload(dib);
		}
		fclose(file);
	}

	// call this ONLY when linking with FreeImage as a static library
#ifdef FREEIMAGE_LIB
	FreeImage_DeInitialise();
#endif // FREEIMAGE_LIB

	return 0;
}
Example #11
0
bool M_loadImage(const char * filename, void * data, void * arg)
{
	if(! filename)
		return false;
		
	if(! data)
		return false;

	// freeimage io
	FreeImageIO io;
	io.read_proc  = (FI_ReadProc)readProc;
	io.write_proc = (FI_WriteProc)writeProc;
	io.tell_proc  = (FI_TellProc)tellProc;
	io.seek_proc  = (FI_SeekProc)seekProc;
	
	
	// read file buffer
	MFile * fp = M_fopen(filename, "rb");
	if(! fp)
	{
		printf("Error : can't read file %s\n", filename);
		return false;
	}
	
	
	// read freeimage
	FREE_IMAGE_FORMAT format = FreeImage_GetFileTypeFromHandle(&io, (fi_handle)fp, 0);
	if(format == FIF_UNKNOWN)
	{
		printf("Error : unknow format %s\n", filename);
		M_fclose(fp);
		return false;
	}
	
	FIBITMAP * dib = FreeImage_LoadFromHandle(format, &io, (fi_handle)fp);
	if(! dib)
	{
		printf("Error : unknow dib %s\n", filename);
		M_fclose(fp);
		return false;
	}
	
	BYTE * bits = FreeImage_GetBits(dib);
	unsigned int width = FreeImage_GetWidth(dib);
	unsigned int height = FreeImage_GetHeight(dib);
	unsigned int bpp = FreeImage_GetBPP(dib);
	FREE_IMAGE_TYPE image_type = FreeImage_GetImageType(dib);
	
	if((bits == 0) || (width == 0) || (height == 0))
	{
		FreeImage_Unload(dib);
		M_fclose(fp);
		return false;
	}
	
	// flip
	FreeImage_FlipVertical(dib);
	
	// create image
	MImage * image = (MImage *)data;
	
	switch(image_type)
	{
	case FIT_BITMAP:
		switch(bpp)
		{
		case 8:
			image->create(M_UBYTE, width, height, 1);
			for(unsigned int y=0; y<height; y++)
			{
				unsigned char * dest = (unsigned char *)image->getData() + width*y;
				bits = FreeImage_GetScanLine(dib, y);
				memcpy(dest, bits, width*sizeof(char));
			}
			break;

		case 24:
			SwapRedBlue32(dib);
			image->create(M_UBYTE, width, height, 3);
			for(unsigned int y=0; y<height; y++)
			{
				unsigned char * dest = (unsigned char *)image->getData() + width*y*3;
				bits = FreeImage_GetScanLine(dib, y);
				memcpy(dest, bits, width*3*sizeof(char));
			}
			break;
	
		case 32:
			SwapRedBlue32(dib);
			image->create(M_UBYTE, width, height, 4);
			for(unsigned int y=0; y<height; y++)
			{
				unsigned char * dest = (unsigned char *)image->getData() + width*y*4;
				bits = FreeImage_GetScanLine(dib, y);
				memcpy(dest, bits, width*4*sizeof(char));
			}
			break;
			
		default:
			break;
		}
		break;
		
	case FIT_RGB16:
		image->create(M_USHORT, width, height, 3);
		for(unsigned int y=0; y<height; y++)
		{
			unsigned short * dest = (unsigned short *)image->getData() + width*y*3;
			bits = FreeImage_GetScanLine(dib, y);
			memcpy(dest, bits, width*3*sizeof(short));
		}
		break;
	
	case FIT_RGBA16:
		image->create(M_USHORT, width, height, 4);
		for(unsigned int y=0; y<height; y++)
		{
			unsigned short * dest = (unsigned short *)image->getData() + width*y*4;
			bits = FreeImage_GetScanLine(dib, y);
			memcpy(dest, bits, width*4*sizeof(short));
		}
		break;

	case FIT_FLOAT:
		image->create(M_FLOAT, width, height, 1);
		for(unsigned int y=0; y<height; y++)
		{
			float * dest = (float *)image->getData() + width*y;
			bits = FreeImage_GetScanLine(dib, y);
			memcpy(dest, bits, width*sizeof(float));
		}
		break;
		
	case FIT_RGBF:
		image->create(M_FLOAT, width, height, 3);
		for(unsigned int y=0; y<height; y++)
		{
			float * dest = (float *)image->getData() + width*y*3;
			bits = FreeImage_GetScanLine(dib, y);
			memcpy(dest, bits, width*3*sizeof(float));
		}
		break;
		
	case FIT_RGBAF:
		image->create(M_FLOAT, width, height, 4);
		for(unsigned int y=0; y<height; y++)
		{
			float * dest = (float *)image->getData() + width*y*4;
			bits = FreeImage_GetScanLine(dib, y);
			memcpy(dest, bits, width*4*sizeof(float));
		}
		break;
		
	default:
		break;
	}
	
	
	// clean
	FreeImage_Unload(dib);
	M_fclose(fp);
	return true;
}
Example #12
0
// This is what does the work in the background thread
UINT CHexEditDoc::RunPreviewThread()
{
	// Keep looping until we are told to die
	for (;;)
	{
		// Signal that we are waiting then wait for start_preview_event_ to be pulsed
		{
			CSingleLock sl(&docdata_, TRUE);
			preview_state_ = WAITING;
		}
		TRACE1("+++ BGPreview: waiting for %p\n", this);
		DWORD wait_status = ::WaitForSingleObject(HANDLE(start_preview_event_), INFINITE);
		docdata_.Lock();
		preview_state_ = SCANNING;
		docdata_.Unlock();
		start_preview_event_.ResetEvent();
		ASSERT(wait_status == WAIT_OBJECT_0);
		TRACE1("+++ BGPreview: got event for %p\n", this);

		if (PreviewProcessStop())
			continue;

		// Reset for new scan
		docdata_.Lock();
		preview_fin_ = false;
		preview_address_ = 0;
		if (preview_dib_ != NULL)
		{
			FreeImage_Unload(preview_dib_);
			preview_dib_ = NULL;
		}
		docdata_.Unlock();

		FREE_IMAGE_FORMAT fif = FreeImage_GetFileTypeFromHandle(&fi_funcs, this);
		FIBITMAP * dib;
		// Catch FreeImage_Load exceptions since it has been known to have memory access violations on bad data
		try
		{
			dib = FreeImage_LoadFromHandle(fif, &fi_funcs, this);
		}
		catch (...)
		{
			dib = NULL;
		}
		int bpp = FreeImage_GetBPP(dib);
		unsigned width = FreeImage_GetWidth(dib);
		unsigned height = FreeImage_GetHeight(dib);

		TRACE1("+++ BGPreview: finished load for %p\n", this);
		docdata_.Lock();
		preview_fin_ = true;
		preview_address_ = 0;
		preview_dib_ = dib;

		// Save info about the bitmap just loaded
		preview_fif_ = fif;
		preview_bpp_ = bpp;
		preview_width_ = width;
		preview_height_ = height;
		docdata_.Unlock();
	}
	return 0;   // never reached
}