Beispiel #1
0
void putBmpIntoPixels(FIBITMAP * bmp, ofPixels_<PixelType> &pix, bool swapForLittleEndian = true) {
	// convert to correct type depending on type of input bmp and PixelType
	FIBITMAP* bmpConverted = NULL;
	FREE_IMAGE_TYPE imgType = FreeImage_GetImageType(bmp);
	if(sizeof(PixelType)==1 &&
		(FreeImage_GetColorType(bmp) == FIC_PALETTE || FreeImage_GetBPP(bmp) < 8
		||  imgType!=FIT_BITMAP)) {
		if(FreeImage_IsTransparent(bmp)) {
			bmpConverted = FreeImage_ConvertTo32Bits(bmp);
		} else {
			bmpConverted = FreeImage_ConvertTo24Bits(bmp);
		}
		bmp = bmpConverted;
	}else if(sizeof(PixelType)==2 && imgType!=FIT_UINT16 && imgType!=FIT_RGB16 && imgType!=FIT_RGBA16){
		if(FreeImage_IsTransparent(bmp)) {
			bmpConverted = FreeImage_ConvertToType(bmp,FIT_RGBA16);
		} else {
			bmpConverted = FreeImage_ConvertToType(bmp,FIT_RGB16);
		}
		bmp = bmpConverted;
	}else if(sizeof(PixelType)==4 && imgType!=FIT_FLOAT && imgType!=FIT_RGBF && imgType!=FIT_RGBAF){
		if(FreeImage_IsTransparent(bmp)) {
			bmpConverted = FreeImage_ConvertToType(bmp,FIT_RGBAF);
		} else {
			bmpConverted = FreeImage_ConvertToType(bmp,FIT_RGBF);
		}
		bmp = bmpConverted;
	}

	unsigned int width = FreeImage_GetWidth(bmp);
	unsigned int height = FreeImage_GetHeight(bmp);
	unsigned int bpp = FreeImage_GetBPP(bmp);
	unsigned int channels = (bpp / sizeof(PixelType)) / 8;
	unsigned int pitch = FreeImage_GetPitch(bmp);

	// ofPixels are top left, FIBITMAP is bottom left
	FreeImage_FlipVertical(bmp);
	
	unsigned char* bmpBits = FreeImage_GetBits(bmp);
	if(bmpBits != NULL) {
		pix.setFromAlignedPixels((PixelType*) bmpBits, width, height, channels, pitch);
	} else {
		ofLogError("ofImage") << "putBmpIntoPixels(): unable to set ofPixels from FIBITMAP";
	}
	
	if(bmpConverted != NULL) {
		FreeImage_Unload(bmpConverted);
	}

#ifdef TARGET_LITTLE_ENDIAN
	if(swapForLittleEndian && sizeof(PixelType) == 1) {
		pix.swapRgb();
	}
#endif
}
Beispiel #2
0
HBITMAP BmpFilterLoadBitmap(BOOL *bIsTransparent, const wchar_t *ptszFilename)
{
	FIBITMAP *dib = (FIBITMAP*)Image_Load(ptszFilename, IMGL_RETURNDIB);
	if (dib == nullptr)
		return nullptr;

	FIBITMAP *dib32 = nullptr;
	if (FreeImage_GetBPP(dib) != 32) {
		dib32 = FreeImage_ConvertTo32Bits(dib);
		FreeImage_Unload(dib);
	}
	else dib32 = dib;

	if (dib32 == nullptr)
		return nullptr;

	if (FreeImage_IsTransparent(dib32))
		if (bIsTransparent)
			*bIsTransparent = TRUE;

	if (FreeImage_GetWidth(dib32) > 128 || FreeImage_GetHeight(dib32) > 128) {
		FIBITMAP *dib_new = FreeImage_MakeThumbnail(dib32, 128, FALSE);
		FreeImage_Unload(dib32);
		if (dib_new == nullptr)
			return nullptr;
		dib32 = dib_new;
	}

	HBITMAP bitmap = FreeImage_CreateHBITMAPFromDIB(dib32);
	FreeImage_Unload(dib32);
	FreeImage_CorrectBitmap32Alpha(bitmap, FALSE);
	return bitmap;
}
Beispiel #3
0
/*!
 *	\brief Opens the image file using the FreeImage library in the specified orientation
 * 		   and builds the 2D Texture MipMaps.
 *	\param pathImagefile Path to the image file.
 *	\param bVertFlip	1, if the image texture must be vertically flipped
 * 						0, otherwise
 *	\param bHorzFlip	1, if the image texture must be horizontally flipped
 * 						0, otherwise 
 *	\return Texture ID.
 */
GLuint loadTexture(const char* pathImagefile, int bVertFlip, int bHorzFlip)
{
	GLuint textureID;
	
    FREE_IMAGE_FORMAT format = FreeImage_GetFileType(pathImagefile,0);
	FIBITMAP* image = FreeImage_Load(format, pathImagefile,0);
	int bRGBA = FreeImage_IsTransparent(image);
	
	FIBITMAP* temp = image;
	if(bRGBA)
	{
		image = FreeImage_ConvertTo32Bits(temp);
	}
	else
	{
		image = FreeImage_ConvertTo24Bits(temp);
	}
	FreeImage_Unload(temp);	
	
	if(bVertFlip)
	{
		FreeImage_FlipVertical(image);
	}
	
	if(bHorzFlip)
	{
		FreeImage_FlipHorizontal(image);
	}	
	
	int w = FreeImage_GetWidth(image);
	int h = FreeImage_GetHeight(image);
	
	glGenTextures(1, &textureID);
	glBindTexture(GL_TEXTURE_2D, textureID);
	
	//// turn off bilinear filtering
	//gl.glTexParameteri(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_MIN_FILTER, gl.GL_NEAREST)
	//gl.glTexParameteri(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_MAG_FILTER, gl.GL_NEAREST)	
	
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
	
	if(bRGBA)
	{
		gluBuild2DMipmaps(GL_TEXTURE_2D, 4, w, h, GL_BGRA, GL_UNSIGNED_BYTE, FreeImage_GetBits(image));
	}
	else
	{
		gluBuild2DMipmaps(GL_TEXTURE_2D, 3, w, h, GL_BGR, GL_UNSIGNED_BYTE, FreeImage_GetBits(image));	
	}

	FreeImage_Unload(image);
	
	return textureID;
}
void putBmpIntoPixels(FIBITMAP * bmp, ofPixels_<PixelType> &pix, bool swapForLittleEndian = true) {
	// some images use a palette, or <8 bpp, so convert them to raster 8-bit channels
	FIBITMAP* bmpConverted = NULL;
	if(FreeImage_GetColorType(bmp) == FIC_PALETTE || FreeImage_GetBPP(bmp) < 8) {
		if(FreeImage_IsTransparent(bmp)) {
			bmpConverted = FreeImage_ConvertTo32Bits(bmp);
		} else {
			bmpConverted = FreeImage_ConvertTo24Bits(bmp);
		}
		bmp = bmpConverted;
	}

	unsigned int width = FreeImage_GetWidth(bmp);
	unsigned int height = FreeImage_GetHeight(bmp);
	unsigned int bpp = FreeImage_GetBPP(bmp);
	unsigned int channels = (bpp / sizeof(PixelType)) / 8;
	unsigned int pitch = FreeImage_GetPitch(bmp);

	// ofPixels are top left, FIBITMAP is bottom left
	FreeImage_FlipVertical(bmp);
	
	unsigned char* bmpBits = FreeImage_GetBits(bmp);
	if(bmpBits != NULL) {
		pix.setFromAlignedPixels((PixelType*) bmpBits, width, height, channels, pitch);
	} else {
		ofLogError() << "ofImage::putBmpIntoPixels() unable to set ofPixels from FIBITMAP";
	}
	
	if(bmpConverted != NULL) {
		FreeImage_Unload(bmpConverted);
	}

#ifdef TARGET_LITTLE_ENDIAN
	if(swapForLittleEndian && sizeof(PixelType) == 1) {
		pix.swapRgb();
	}
#endif
}
Beispiel #5
0
BOOL fipImage::isTransparent() const {
	return FreeImage_IsTransparent(_dib);
}
	virtual bool load(const std::string& filename, Array &lat) {
		FREE_IMAGE_FORMAT type = FreeImage_GetFIFFromFilename(filename.c_str());
		if(type == FIF_UNKNOWN) {
			AL_WARN("image format not recognized: %s", filename.c_str());
			return false;
		}
		if(!FreeImage_FIFSupportsReading(type)) {
			AL_WARN("image format not supported: %s", filename.c_str());
			return false;
		}
		
		destroy();
		mImage = FreeImage_Load(type, filename.c_str(), 0);
		if (mImage == NULL) {
			AL_WARN("image failed to load: %s", filename.c_str());
			return false;
		}
		
		FREE_IMAGE_COLOR_TYPE colorType = FreeImage_GetColorType(mImage);
		switch(colorType) {
			case FIC_MINISBLACK:
			case FIC_MINISWHITE: {
					FIBITMAP *res = FreeImage_ConvertToGreyscale(mImage);
					FreeImage_Unload(mImage);
					mImage = res;
				}
				break;

			case FIC_PALETTE: {
					if(FreeImage_IsTransparent(mImage)) {
						FIBITMAP *res = FreeImage_ConvertTo32Bits(mImage);
						FreeImage_Unload(mImage);
						mImage = res;
					}
					else {
						FIBITMAP *res = FreeImage_ConvertTo24Bits(mImage);
						FreeImage_Unload(mImage);
						mImage = res;
					}
				}
				break;

			case FIC_CMYK: {
					AL_WARN("CMYK images currently not supported");
					return false;
				}
				break;

			default:
				break;
		}

		// flip vertical for OpenGL:
		//FreeImage_FlipVertical(mImage);
		
		//Freeimage is not tightly packed, so we use
		//a custom method instead of one of the Matrix
		//utility methods
		int planes = getPlanes();
		AlloTy ty = getDataType();
		int w, h;
		getDim(w, h);
		lat.format(planes, ty, w, h);
		
		Image::Format format = Image::getFormat(planes);
		switch(format) {
			case Image::LUMINANCE: {
				char *o_pix = (char *)(lat.data.ptr);
				int rowstride = lat.header.stride[1];
				for(unsigned j = 0; j < lat.header.dim[1]; ++j) {
					char *pix = (char *)FreeImage_GetScanLine(mImage, j);
					memcpy(o_pix, pix, rowstride);
					o_pix += rowstride;
				}
			}
			break;
			
			case Image::RGB: {
				switch(lat.header.type) {
					case AlloUInt8Ty: {
						char *bp = (char *)(lat.data.ptr);
						int rowstride = lat.header.stride[1];

						for(unsigned j = 0; j < lat.header.dim[1]; ++j) {
							RGBTRIPLE * pix = (RGBTRIPLE *)FreeImage_GetScanLine(mImage, j);
							Image::RGBPix<uint8_t> *o_pix = (Image::RGBPix<uint8_t> *)(bp + j*rowstride);
							for(unsigned i=0; i < lat.header.dim[0]; ++i) {
								o_pix->r = pix->rgbtRed;
								o_pix->g = pix->rgbtGreen;
								o_pix->b = pix->rgbtBlue;
								++pix;
								++o_pix;
							}
						}
					}
					break;

					case AlloFloat32Ty: {
						char *o_pix = (char *)(lat.data.ptr);
						int rowstride = lat.header.stride[1];

						for(unsigned j = 0; j < lat.header.dim[1]; ++j) {
							char *pix = (char *)FreeImage_GetScanLine(mImage, j);
							memcpy(o_pix, pix, rowstride);
							o_pix += rowstride;
						}
					}
					break;

					default: 
					break;

				}
			}
			break;
			
			case Image::RGBA: {
				switch(lat.header.type) {
					case AlloUInt8Ty: {
						char *bp = (char *)(lat.data.ptr);
						int rowstride = lat.header.stride[1];
						for(unsigned j = 0; j < lat.header.dim[1]; ++j) {
							RGBQUAD *pix = (RGBQUAD *)FreeImage_GetScanLine(mImage, j);
							Image::RGBAPix<uint8_t> *o_pix = (Image::RGBAPix<uint8_t> *)(bp + j*rowstride);
							for(unsigned i=0; i < lat.header.dim[0]; ++i) {
								o_pix->r = pix->rgbRed;
								o_pix->g = pix->rgbGreen;
								o_pix->b = pix->rgbBlue;
								o_pix->a = pix->rgbReserved;
								++pix;
								++o_pix;
							}
						}
					}
					break;

					case AlloFloat32Ty: {
						char *o_pix = (char *)(lat.data.ptr);
						int rowstride = lat.header.stride[1];
						for(unsigned j = 0; j < lat.header.dim[1]; ++j) {
							char *pix = (char *)FreeImage_GetScanLine(mImage, j);
							memcpy(o_pix, pix, rowstride);
							o_pix += rowstride;
						}
					}
					break;

					default: break;
				}
			}
			break;
			
			default: 
				AL_WARN("image data not understood");
				destroy();
				return false;
		}
		return true;
	}
Beispiel #7
0
void ofxGifDecoder::processFrame(FIBITMAP * bmp, int _frameNum){
        FITAG *tag;
        ofPixels pix;
    
        unsigned int   frameLeft, frameTop;
        float frameDuration;
        GifFrameDisposal disposal_method = GIF_DISPOSAL_BACKGROUND;
        
        if( FreeImage_GetMetadata(FIMD_ANIMATION, bmp, "FrameLeft", &tag)) {
                frameLeft = *(unsigned short *)FreeImage_GetTagValue(tag);
            }
        
        if( FreeImage_GetMetadata(FIMD_ANIMATION, bmp, "FrameTop", &tag)) {
                frameTop = *(unsigned short *)FreeImage_GetTagValue(tag);
            }
        
        if( FreeImage_GetMetadata(FIMD_ANIMATION, bmp, "FrameTime", &tag)) {
                long frameTime = *(long *)FreeImage_GetTagValue(tag);// centiseconds 1/100 sec
                frameDuration =(float)frameTime/1000.f;
            }
        
        if( FreeImage_GetMetadata(FIMD_ANIMATION, bmp, "DisposalMethod", &tag)) {
                disposal_method = (GifFrameDisposal) *(unsigned char *)FreeImage_GetTagValue(tag);
            }
        
        // we do this for drawing. eventually we should be able to draw 8 bits? at least to retain the data
    //    if(FreeImage_GetBPP(bmp) == 8) {
    //        // maybe we should only do this when asked for rendering?
    //        bmp = FreeImage_ConvertTo24Bits(bmp);
    //    }
        
        FIBITMAP* bmpConverted = NULL;
    if(FreeImage_GetColorType(bmp) == FIC_PALETTE || FreeImage_GetBPP(bmp) < 8) {
        if(FreeImage_IsTransparent(bmp)) {
            bmpConverted = FreeImage_ConvertTo32Bits(bmp);
        } else {
            bmpConverted = FreeImage_ConvertTo24Bits(bmp);
        }
        bmp = bmpConverted;
    }
        
    unsigned int width      = FreeImage_GetWidth(bmp);
    unsigned int height     = FreeImage_GetHeight(bmp);
    unsigned int bpp        = FreeImage_GetBPP(bmp);
        // changed this bc we're not using PixelType template anywhere else...
    unsigned int channels   = (bpp / sizeof( unsigned char )) / 8;
    unsigned int pitch      = FreeImage_GetPitch(bmp);
        
    // ofPixels are top left, FIBITMAP is bottom left
    FreeImage_FlipVertical(bmp);
    
    unsigned char * bmpBits = FreeImage_GetBits(bmp);
        
    if(bmpBits != NULL) {
                
        pix.setFromAlignedPixels(bmpBits, width, height, channels, pitch);
                    
                #ifdef TARGET_LITTLE_ENDIAN
                    pix.swapRgb();
                #endif
                
                gifFile.addFrame(pix, frameLeft, frameTop, disposal_method, frameDuration);
    } else {
        ofLogError() << "ofImage::putBmpIntoPixels() unable to set ofPixels from FIBITMAP";
    }
}
    //---------------------------------------------------------------------
    Codec::DecodeResult FreeImageCodec::decode(DataStreamPtr& input) const
    {
		// Set error handler
		FreeImage_SetOutputMessage(FreeImageLoadErrorHandler);

		// Buffer stream into memory (TODO: override IO functions instead?)
		MemoryDataStream memStream(input, true);

		FIMEMORY* fiMem = 
			FreeImage_OpenMemory(memStream.getPtr(), static_cast<DWORD>(memStream.size()));

		FIBITMAP* fiBitmap = FreeImage_LoadFromMemory(
			(FREE_IMAGE_FORMAT)mFreeImageType, fiMem);
		if (!fiBitmap)
		{
			OGRE_EXCEPT(Exception::ERR_INTERNAL_ERROR, 
				"Error decoding image", 
				"FreeImageCodec::decode");
		}


		ImageData* imgData = OGRE_NEW ImageData();
		MemoryDataStreamPtr output;

		imgData->depth = 1; // only 2D formats handled by this codec
		imgData->width = FreeImage_GetWidth(fiBitmap);
		imgData->height = FreeImage_GetHeight(fiBitmap);
        imgData->num_mipmaps = 0; // no mipmaps in non-DDS 
        imgData->flags = 0;

		// Must derive format first, this may perform conversions
		
		FREE_IMAGE_TYPE imageType = FreeImage_GetImageType(fiBitmap);
		FREE_IMAGE_COLOR_TYPE colourType = FreeImage_GetColorType(fiBitmap);
		unsigned bpp = FreeImage_GetBPP(fiBitmap);

		switch(imageType)
		{
		case FIT_UNKNOWN:
		case FIT_COMPLEX:
		case FIT_UINT32:
		case FIT_INT32:
		case FIT_DOUBLE:
        default:
			OGRE_EXCEPT(Exception::ERR_ITEM_NOT_FOUND, 
				"Unknown or unsupported image format", 
				"FreeImageCodec::decode");
				
			break;
		case FIT_BITMAP:
			// Standard image type
			// Perform any colour conversions for greyscale
			if (colourType == FIC_MINISWHITE || colourType == FIC_MINISBLACK)
			{
				FIBITMAP* newBitmap = FreeImage_ConvertToGreyscale(fiBitmap);
				// free old bitmap and replace
				FreeImage_Unload(fiBitmap);
				fiBitmap = newBitmap;
				// get new formats
				bpp = FreeImage_GetBPP(fiBitmap);
				colourType = FreeImage_GetColorType(fiBitmap);
			}
			// Perform any colour conversions for RGB
			else if (bpp < 8 || colourType == FIC_PALETTE || colourType == FIC_CMYK)
			{
				FIBITMAP* newBitmap =  NULL;	
				if (FreeImage_IsTransparent(fiBitmap))
				{
					// convert to 32 bit to preserve the transparency 
					// (the alpha byte will be 0 if pixel is transparent)
					newBitmap = FreeImage_ConvertTo32Bits(fiBitmap);
				}
				else
				{
					// no transparency - only 3 bytes are needed
					newBitmap = FreeImage_ConvertTo24Bits(fiBitmap);
				}

				// free old bitmap and replace
				FreeImage_Unload(fiBitmap);
				fiBitmap = newBitmap;
				// get new formats
				bpp = FreeImage_GetBPP(fiBitmap);
				colourType = FreeImage_GetColorType(fiBitmap);
			}

			// by this stage, 8-bit is greyscale, 16/24/32 bit are RGB[A]
			switch(bpp)
			{
			case 8:
				imgData->format = PF_L8;
				break;
			case 16:
				// Determine 555 or 565 from green mask
				// cannot be 16-bit greyscale since that's FIT_UINT16
				if(FreeImage_GetGreenMask(fiBitmap) == FI16_565_GREEN_MASK)
				{
					imgData->format = PF_R5G6B5;
				}
				else
				{
					// FreeImage doesn't support 4444 format so must be 1555
					imgData->format = PF_A1R5G5B5;
				}
				break;
			case 24:
				// FreeImage differs per platform
				//     PF_BYTE_BGR[A] for little endian (== PF_ARGB native)
				//     PF_BYTE_RGB[A] for big endian (== PF_RGBA native)
#if FREEIMAGE_COLORORDER == FREEIMAGE_COLORORDER_RGB
				imgData->format = PF_BYTE_RGB;
#else
				imgData->format = PF_BYTE_BGR;
#endif
				break;
			case 32:
#if FREEIMAGE_COLORORDER == FREEIMAGE_COLORORDER_RGB
				imgData->format = PF_BYTE_RGBA;
#else
				imgData->format = PF_BYTE_BGRA;
#endif
				break;
				
				
			};
			break;
		case FIT_UINT16:
		case FIT_INT16:
			// 16-bit greyscale
			imgData->format = PF_L16;
			break;
		case FIT_FLOAT:
			// Single-component floating point data
			imgData->format = PF_FLOAT32_R;
			break;
		case FIT_RGB16:
			imgData->format = PF_SHORT_RGB;
			break;
		case FIT_RGBA16:
			imgData->format = PF_SHORT_RGBA;
			break;
		case FIT_RGBF:
			imgData->format = PF_FLOAT32_RGB;
			break;
		case FIT_RGBAF:
			imgData->format = PF_FLOAT32_RGBA;
			break;
			
			
		};

		unsigned char* srcData = FreeImage_GetBits(fiBitmap);
		unsigned srcPitch = FreeImage_GetPitch(fiBitmap);

		// Final data - invert image and trim pitch at the same time
		size_t dstPitch = imgData->width * PixelUtil::getNumElemBytes(imgData->format);
		imgData->size = dstPitch * imgData->height;
        // Bind output buffer
        output.bind(OGRE_NEW MemoryDataStream(imgData->size));

		uchar* pSrc;
		uchar* pDst = output->getPtr();
		for (size_t y = 0; y < imgData->height; ++y)
		{
			pSrc = srcData + (imgData->height - y - 1) * srcPitch;
			memcpy(pDst, pSrc, dstPitch);
			pDst += dstPitch;
		}

		
		FreeImage_Unload(fiBitmap);
		FreeImage_CloseMemory(fiMem);


        DecodeResult ret;
        ret.first = output;
        ret.second = CodecDataPtr(imgData);
		return ret;

    }
Beispiel #9
0
static FIBITMAP * DLL_CALLCONV 
Load(FreeImageIO *io, fi_handle handle, int page, int flags, void *data) {
	if( data == NULL ) {
		return NULL;
	}
	GIFinfo *info = (GIFinfo *)data;

	if( page == -1 ) {
		page = 0;
	}
	if( page < 0 || page >= (int)info->image_descriptor_offsets.size() ) {
		return NULL;
	}

	FIBITMAP *dib = NULL;
	try {
		bool have_transparent = false, no_local_palette = false, interlaced = false;
		int disposal_method = GIF_DISPOSAL_LEAVE, delay_time = 0, transparent_color = 0;
		WORD left, top, width, height;
		BYTE packed, b;
		WORD w;

		//playback pages to generate what the user would see for this frame
		if( (flags & GIF_PLAYBACK) == GIF_PLAYBACK ) {
			//Logical Screen Descriptor
			io->seek_proc(handle, 6, SEEK_SET);
			WORD logicalwidth, logicalheight;
			io->read_proc(&logicalwidth, 2, 1, handle);
			io->read_proc(&logicalheight, 2, 1, handle);
#ifdef FREEIMAGE_BIGENDIAN
			SwapShort(&logicalwidth);
			SwapShort(&logicalheight);
#endif
			//set the background color with 0 alpha
			RGBQUAD background;
			if( info->global_color_table_offset != 0 && info->background_color < info->global_color_table_size ) {
				io->seek_proc(handle, info->global_color_table_offset + (info->background_color * 3), SEEK_SET);
				io->read_proc(&background.rgbRed, 1, 1, handle);
				io->read_proc(&background.rgbGreen, 1, 1, handle);
				io->read_proc(&background.rgbBlue, 1, 1, handle);
			} else {
				background.rgbRed = 0;
				background.rgbGreen = 0;
				background.rgbBlue = 0;
			}
			background.rgbReserved = 0;

			//allocate entire logical area
			dib = FreeImage_Allocate(logicalwidth, logicalheight, 32);
			if( dib == NULL ) {
				throw "DIB allocated failed";
			}

			//fill with background color to start
			int x, y;
			RGBQUAD *scanline;
			for( y = 0; y < logicalheight; y++ ) {
				scanline = (RGBQUAD *)FreeImage_GetScanLine(dib, y);
				for( x = 0; x < logicalwidth; x++ ) {
					*scanline++ = background;
				}
			}

			//cache some info about each of the pages so we can avoid decoding as many of them as possible
			std::vector<PageInfo> pageinfo;
			int start = page, end = page;
			while( start >= 0 ) {
				//Graphic Control Extension
				io->seek_proc(handle, info->graphic_control_extension_offsets[start] + 1, SEEK_SET);
				io->read_proc(&packed, 1, 1, handle);
				have_transparent = (packed & GIF_PACKED_GCE_HAVETRANS) ? true : false;
				disposal_method = (packed & GIF_PACKED_GCE_DISPOSAL) >> 2;
				//Image Descriptor
				io->seek_proc(handle, info->image_descriptor_offsets[page], SEEK_SET);
				io->read_proc(&left, 2, 1, handle);
				io->read_proc(&top, 2, 1, handle);
				io->read_proc(&width, 2, 1, handle);
				io->read_proc(&height, 2, 1, handle);
#ifdef FREEIMAGE_BIGENDIAN
				SwapShort(&left);
				SwapShort(&top);
				SwapShort(&width);
				SwapShort(&height);
#endif

				pageinfo.push_back(PageInfo(disposal_method, left, top, width, height));

				if( start != end ) {
					if( left == 0 && top == 0 && width == logicalwidth && height == logicalheight ) {
						if( disposal_method == GIF_DISPOSAL_BACKGROUND ) {
							pageinfo.pop_back();
							start++;
							break;
						} else if( disposal_method != GIF_DISPOSAL_PREVIOUS ) {
							if( !have_transparent ) {
								break;
							}
						}
					}
				}
				start--;
			}
			if( start < 0 ) {
				start = 0;
			}

			//draw each page into the logical area
			for( page = start; page <= end; page++ ) {
				PageInfo &info = pageinfo[end - page];
				//things we can skip having to decode
				if( page != end ) {
					if( info.disposal_method == GIF_DISPOSAL_PREVIOUS ) {
						continue;
					}
					if( info.disposal_method == GIF_DISPOSAL_BACKGROUND ) {
						for( y = 0; y < info.height; y++ ) {
							scanline = (RGBQUAD *)FreeImage_GetScanLine(dib, logicalheight - (y + info.top) - 1) + info.left;
							for( x = 0; x < info.width; x++ ) {
								*scanline++ = background;
							}
						}
					}
				}

				//decode page
				FIBITMAP *pagedib = Load(io, handle, page, GIF_LOAD256, data);
				if( pagedib != NULL ) {
					RGBQUAD *pal = FreeImage_GetPalette(pagedib);
					have_transparent = false;
					if( FreeImage_IsTransparent(pagedib) ) {
						int count = FreeImage_GetTransparencyCount(pagedib);
						BYTE *table = FreeImage_GetTransparencyTable(pagedib);
						for( int i = 0; i < count; i++ ) {
							if( table[i] == 0 ) {
								have_transparent = true;
								transparent_color = i;
								break;
							}
						}
					}
					//copy page data into logical buffer, with full alpha opaqueness
					for( y = 0; y < info.height; y++ ) {
						scanline = (RGBQUAD *)FreeImage_GetScanLine(dib, logicalheight - (y + info.top) - 1) + info.left;
						BYTE *pageline = FreeImage_GetScanLine(pagedib, info.height - y - 1);
						for( x = 0; x < info.width; x++ ) {
							if( !have_transparent || *pageline != transparent_color ) {
								*scanline = pal[*pageline];
								scanline->rgbReserved = 255;
							}
							scanline++;
							pageline++;
						}
					}
					FreeImage_Unload(pagedib);
				}
			}

			return dib;
		}

		//get the actual frame image data for a single frame

		//Image Descriptor
		io->seek_proc(handle, info->image_descriptor_offsets[page], SEEK_SET);
		io->read_proc(&left, 2, 1, handle);
		io->read_proc(&top, 2, 1, handle);
		io->read_proc(&width, 2, 1, handle);
		io->read_proc(&height, 2, 1, handle);
#ifdef FREEIMAGE_BIGENDIAN
		SwapShort(&left);
		SwapShort(&top);
		SwapShort(&width);
		SwapShort(&height);
#endif
		io->read_proc(&packed, 1, 1, handle);
		interlaced = (packed & GIF_PACKED_ID_INTERLACED) ? true : false;
		no_local_palette = (packed & GIF_PACKED_ID_HAVELCT) ? false : true;

		int bpp = 8;
		if( (flags & GIF_LOAD256) == 0 ) {
			if( !no_local_palette ) {
				int size = 2 << (packed & GIF_PACKED_ID_LCTSIZE);
				if( size <= 2 ) bpp = 1;
				else if( size <= 16 ) bpp = 4;
			} else if( info->global_color_table_offset != 0 ) {
				if( info->global_color_table_size <= 2 ) bpp = 1;
				else if( info->global_color_table_size <= 16 ) bpp = 4;
			}
		}
		dib = FreeImage_Allocate(width, height, bpp);
		if( dib == NULL ) {
			throw "DIB allocated failed";
		}

		FreeImage_SetMetadataEx(FIMD_ANIMATION, dib, "FrameLeft", ANIMTAG_FRAMELEFT, FIDT_SHORT, 1, 2, &left);
		FreeImage_SetMetadataEx(FIMD_ANIMATION, dib, "FrameTop", ANIMTAG_FRAMETOP, FIDT_SHORT, 1, 2, &top);
		b = no_local_palette ? 1 : 0;
		FreeImage_SetMetadataEx(FIMD_ANIMATION, dib, "NoLocalPalette", ANIMTAG_NOLOCALPALETTE, FIDT_BYTE, 1, 1, &b);
		b = interlaced ? 1 : 0;
		FreeImage_SetMetadataEx(FIMD_ANIMATION, dib, "Interlaced", ANIMTAG_INTERLACED, FIDT_BYTE, 1, 1, &b);

		//Palette
		RGBQUAD *pal = FreeImage_GetPalette(dib);
		if( !no_local_palette ) {
			int size = 2 << (packed & GIF_PACKED_ID_LCTSIZE);

			int i = 0;
			while( i < size ) {
				io->read_proc(&pal[i].rgbRed, 1, 1, handle);
				io->read_proc(&pal[i].rgbGreen, 1, 1, handle);
				io->read_proc(&pal[i].rgbBlue, 1, 1, handle);
				i++;
			}
		} else if( info->global_color_table_offset != 0 ) {
			long pos = io->tell_proc(handle);
			io->seek_proc(handle, info->global_color_table_offset, SEEK_SET);

			int i = 0;
			while( i < info->global_color_table_size ) {
				io->read_proc(&pal[i].rgbRed, 1, 1, handle);
				io->read_proc(&pal[i].rgbGreen, 1, 1, handle);
				io->read_proc(&pal[i].rgbBlue, 1, 1, handle);
				i++;
			}

			io->seek_proc(handle, pos, SEEK_SET);
		} else {
			//its legal to have no palette, but we're going to generate *something*
			for( int i = 0; i < 256; i++ ) {
				pal[i].rgbRed = i;
				pal[i].rgbGreen = i;
				pal[i].rgbBlue = i;
			}
		}

		//LZW Minimum Code Size
		io->read_proc(&b, 1, 1, handle);
		StringTable stringtable;
		stringtable.Initialize(b);

		//Image Data Sub-blocks
		int x = 0, xpos = 0, y = 0, shift = 8 - bpp, mask = (1 << bpp) - 1, interlacepass = 0;
		BYTE *scanline = FreeImage_GetScanLine(dib, height - 1);
		BYTE buf[1024];
		io->read_proc(&b, 1, 1, handle);
		while( b ) {
			io->read_proc(stringtable.FillInputBuffer(b), b, 1, handle);
			int size = sizeof(buf);
			while( stringtable.Decompress(buf, &size) ) {
				for( int i = 0; i < size; i++ ) {
					scanline[xpos] |= (buf[i] & mask) << shift;
					if( shift > 0 ) {
						shift -= bpp;
					} else {
						xpos++;
						shift = 8 - bpp;
					}
					if( ++x >= width ) {
						if( interlaced ) {
							y += g_GifInterlaceIncrement[interlacepass];
							if( y >= height && interlacepass < GIF_INTERLACE_PASSES ) {
								y = g_GifInterlaceOffset[++interlacepass];
							}
						} else {
							y++;
						}
						if( y >= height ) {
							stringtable.Done();
							break;
						}
						x = xpos = 0;
						shift = 8 - bpp;
						scanline = FreeImage_GetScanLine(dib, height - y - 1);
					}
				}
				size = sizeof(buf);
			}
			io->read_proc(&b, 1, 1, handle);
		}

		if( page == 0 ) {
			size_t idx;

			//Logical Screen Descriptor
			io->seek_proc(handle, 6, SEEK_SET);
			WORD logicalwidth, logicalheight;
			io->read_proc(&logicalwidth, 2, 1, handle);
			io->read_proc(&logicalheight, 2, 1, handle);
#ifdef FREEIMAGE_BIGENDIAN
			SwapShort(&logicalwidth);
			SwapShort(&logicalheight);
#endif
			FreeImage_SetMetadataEx(FIMD_ANIMATION, dib, "LogicalWidth", ANIMTAG_LOGICALWIDTH, FIDT_SHORT, 1, 2, &logicalwidth);
			FreeImage_SetMetadataEx(FIMD_ANIMATION, dib, "LogicalHeight", ANIMTAG_LOGICALHEIGHT, FIDT_SHORT, 1, 2, &logicalheight);

			//Global Color Table
			if( info->global_color_table_offset != 0 ) {
				RGBQUAD globalpalette[256];
				io->seek_proc(handle, info->global_color_table_offset, SEEK_SET);
				int i = 0;
				while( i < info->global_color_table_size ) {
					io->read_proc(&globalpalette[i].rgbRed, 1, 1, handle);
					io->read_proc(&globalpalette[i].rgbGreen, 1, 1, handle);
					io->read_proc(&globalpalette[i].rgbBlue, 1, 1, handle);
					globalpalette[i].rgbReserved = 0;
					i++;
				}
				FreeImage_SetMetadataEx(FIMD_ANIMATION, dib, "GlobalPalette", ANIMTAG_GLOBALPALETTE, FIDT_PALETTE, info->global_color_table_size, info->global_color_table_size * 4, globalpalette);
				//background color
				if( info->background_color < info->global_color_table_size ) {
					FreeImage_SetBackgroundColor(dib, &globalpalette[info->background_color]);
				}
			}

			//Application Extension
			LONG loop = 1; //If no AE with a loop count is found, the default must be 1
			for( idx = 0; idx < info->application_extension_offsets.size(); idx++ ) {
				io->seek_proc(handle, info->application_extension_offsets[idx], SEEK_SET);
				io->read_proc(&b, 1, 1, handle);
				if( b == 11 ) { //All AEs start with an 11 byte sub-block to determine what type of AE it is
					char buf[11];
					io->read_proc(buf, 11, 1, handle);
					if( !memcmp(buf, "NETSCAPE2.0", 11) || !memcmp(buf, "ANIMEXTS1.0", 11) ) { //Not everybody recognizes ANIMEXTS1.0 but it is valid
						io->read_proc(&b, 1, 1, handle);
						if( b == 3 ) { //we're supposed to have a 3 byte sub-block now
							io->read_proc(&b, 1, 1, handle); //this should be 0x01 but isn't really important
							io->read_proc(&w, 2, 1, handle);
#ifdef FREEIMAGE_BIGENDIAN
							SwapShort(&w);
#endif
							loop = w;
							if( loop > 0 ) loop++;
							break;
						}
					}
				}
			}
			FreeImage_SetMetadataEx(FIMD_ANIMATION, dib, "Loop", ANIMTAG_LOOP, FIDT_LONG, 1, 4, &loop);

			//Comment Extension
			for( idx = 0; idx < info->comment_extension_offsets.size(); idx++ ) {
				io->seek_proc(handle, info->comment_extension_offsets[idx], SEEK_SET);
				std::string comment;
				char buf[255];
				io->read_proc(&b, 1, 1, handle);
				while( b ) {
					io->read_proc(buf, b, 1, handle);
					comment.append(buf, b);
					io->read_proc(&b, 1, 1, handle);
				}
				comment.append(1, '\0');
				sprintf(buf, "Comment%d", idx);
				FreeImage_SetMetadataEx(FIMD_COMMENTS, dib, buf, 1, FIDT_ASCII, comment.size(), comment.size(), comment.c_str());
			}
		}

		//Graphic Control Extension
		if( info->graphic_control_extension_offsets[page] != 0 ) {
			io->seek_proc(handle, info->graphic_control_extension_offsets[page] + 1, SEEK_SET);
			io->read_proc(&packed, 1, 1, handle);
			io->read_proc(&w, 2, 1, handle);
#ifdef FREEIMAGE_BIGENDIAN
			SwapShort(&w);
#endif
			io->read_proc(&b, 1, 1, handle);
			have_transparent = (packed & GIF_PACKED_GCE_HAVETRANS) ? true : false;
			disposal_method = (packed & GIF_PACKED_GCE_DISPOSAL) >> 2;
			delay_time = w * 10; //convert cs to ms
			transparent_color = b;
			if( have_transparent ) {
				int size = 1 << bpp;
				if( transparent_color <= size ) {
					BYTE table[256];
					memset(table, 0xFF, size);
					table[transparent_color] = 0;
					FreeImage_SetTransparencyTable(dib, table, size);
				}
			}
		}
Beispiel #10
0
//!!!be sure to release memory before return null
ResHandler* WIPResourceManager::alloc(const char* filename, WIPResourceType type)
{
    ResHandler* res = new ResHandler;
    switch (type)
    {
    case TEXT:
    {

    }
    break;
    case TEXTURE:
    {
        TextureData *data = new TextureData;
        //初始化FreeImage
        FreeImage_Initialise(TRUE);

        FIBITMAP* bmpConverted = NULL;
        FREE_IMAGE_FORMAT fif = FIF_UNKNOWN;
        fif = FreeImage_GetFileType(filename);
        if (fif == FIF_UNKNOWN)
            fif = FreeImage_GetFIFFromFilename(filename);
        if ((fif != FIF_UNKNOWN) && FreeImage_FIFSupportsReading(fif))
        {

            FIBITMAP *dib = FreeImage_Load(fif, filename);

            if (!dib)
            {
                printf("[fatal error]: \"%s\" load error!\n", filename);
                delete data;
                delete_handler(res);
                return NULL;
            }

            // we are top left, FIBITMAP is bottom left
            FreeImage_FlipVertical(dib);
            //get infomation
            FREE_IMAGE_TYPE imgType = FreeImage_GetImageType(dib);
            FREE_IMAGE_COLOR_TYPE colorType = FreeImage_GetColorType(dib);
            unsigned int bpp = FreeImage_GetBPP(dib);

            data->bpp = bpp;
            data->color_type = colorType;
            data->image_type = imgType;
            data->channel = 4;

            int x, y;
            RGBQUAD m_rgb;

            //获取图片长宽
            int width = (int)FreeImage_GetWidth(dib);
            int height = (int)FreeImage_GetHeight(dib);

            unsigned char* imgBuf = new unsigned char[width*height * 4];



            bool is_tr = FreeImage_IsTransparent(dib);

            bool is_little = FreeImage_IsLittleEndian();
            //获取图片数据
            //按RGBA格式保存到数组中
            for (y = 0; y<height; y++)
            {
                for (x = 0; x<width; x++)
                {
                    //获取像素值
                    FreeImage_GetPixelColor(dib, x, y, &m_rgb);

                    if (is_little)
                    {
                        imgBuf[y*width * 4 + x * 4 + 0] = m_rgb.rgbRed;
                        imgBuf[y*width * 4 + x * 4 + 1] = m_rgb.rgbGreen;
                        imgBuf[y*width * 4 + x * 4 + 2] = m_rgb.rgbBlue;
                        //判断是否透明图片
                        //如果是就取alpha值保存
                        if (is_tr)
                            imgBuf[y*width * 4 + x * 4 + 3] = m_rgb.rgbReserved;
                        else
                            imgBuf[y*width * 4 + x * 4 + 3] = 255;
                    }
                    else
                    {
                        //大端警告!
                        //Big Endian Warnning!
                        printf("Note:This is a Big endian!\n");
                    }
                }
            }


            data->width = width;
            data->height = height;
            data->size = height*width * 4;


            FreeImage_Unload(dib);

            res->file_name = filename;
            res->extra = data;
            res->nref = 1;
            res->ptr = imgBuf;
            res->size = width*height * 4;
            res->type = TEXTURE;

            _map[filename] = res;

            return res;
        }
    }
    break;

    case SOUND:
    {
    }
    default:
        return res;
        break;
    }
    delete_handler(res);
    return NULL;
}
FIBITMAP * DLL_CALLCONV 
FreeImage_Rescale(FIBITMAP *src, int dst_width, int dst_height, FREE_IMAGE_FILTER filter) {
	FIBITMAP *dst = NULL;

	if (!src || (dst_width <= 0) || (dst_height <= 0)) {
		return NULL;
	}

	// select the filter
	CGenericFilter *pFilter = NULL;
	switch(filter) {
		case FILTER_BOX:
			pFilter = new CBoxFilter();
			break;
		case FILTER_BICUBIC:
			pFilter = new CBicubicFilter();
			break;
		case FILTER_BILINEAR:
			pFilter = new CBilinearFilter();
			break;
		case FILTER_BSPLINE:
			pFilter = new CBSplineFilter();
			break;
		case FILTER_CATMULLROM:
			pFilter = new CCatmullRomFilter();
			break;
		case FILTER_LANCZOS3:
			pFilter = new CLanczos3Filter();
			break;
	}

	CResizeEngine Engine(pFilter);

	// perform upsampling or downsampling

	if((FreeImage_GetBPP(src) == 4) || (FreeImage_GetColorType(src) == FIC_PALETTE)) {
		// special case for 4-bit images or color map indexed images ...
		if(FreeImage_IsTransparent(src) == FALSE) {
			FIBITMAP *src24 = NULL;
			FIBITMAP *dst24 = NULL;
			try {
				// transparent conversion to 24-bit (any transparency table will be destroyed)
				src24 = FreeImage_ConvertTo24Bits(src);
				if(!src24) throw(1);
				// perform upsampling or downsampling
				dst24 = Engine.scale(src24, dst_width, dst_height);
				if(!dst24) throw(1);
				// color quantize to 8-bit
				dst = FreeImage_ColorQuantize(dst24, FIQ_WUQUANT);
				// free and return
				FreeImage_Unload(src24);
				FreeImage_Unload(dst24);
			} catch(int) {
				if(src24) FreeImage_Unload(src24);
				if(dst24) FreeImage_Unload(dst24);
			}
		} else {
			FIBITMAP *src32 = NULL;
			try {
				// transparent conversion to 32-bit (keep transparency)
				src32 = FreeImage_ConvertTo32Bits(src);
				if(!src32) throw(1);
				// perform upsampling or downsampling
				dst = Engine.scale(src32, dst_width, dst_height);
				if(!dst) throw(1);
				// free and return
				FreeImage_Unload(src32);
			} catch(int) {
				if(src32) FreeImage_Unload(src32);
				if(dst) FreeImage_Unload(dst);
			}
		}
	}
	else if((FreeImage_GetBPP(src) == 16) && (FreeImage_GetImageType(src) == FIT_BITMAP)) {
		// convert 16-bit RGB to 24-bit
		FIBITMAP *src24 = NULL;
		try {
			// transparent conversion to 24-bit (any transparency table will be destroyed)
			src24 = FreeImage_ConvertTo24Bits(src);
			if(!src24) throw(1);
			// perform upsampling or downsampling
			dst = Engine.scale(src24, dst_width, dst_height);
			if(!dst) throw(1);
			// free and return
			FreeImage_Unload(src24);
		} catch(int) {
			if(src24) FreeImage_Unload(src24);
			if(dst) FreeImage_Unload(dst);
		}
	}
	else {
		// normal case : 
		// 1- or 8-bit greyscale, 24- or 32-bit RGB(A) images
		// 16-bit greyscale, 48- or 64-bit RGB(A) images
		// 32-bit float, 96- or 128-bit RGB(A) float images
		dst = Engine.scale(src, dst_width, dst_height);
	}


	delete pFilter;

	return dst;
}
  Ref<Image> loadFreeImage(const FileName& fileName)
  {
      FIBITMAP* dib = NULL;
      FREE_IMAGE_FORMAT fif = FreeImage_GetFileType(fileName.c_str());

	  //-------------------------------------------------
	  // Sonderfall - unser Schutzformat "vrh" laden
	  // ZLib-compressed HDR-Image!
	  //-------------------------------------------------
      std::string ext = std::strlwr(fileName.ext());
      if( ext == "vrh" ) 
      {
          fif = FIF_HDR;
          dib = loadVRH(fileName);
      }
      else
      {
          if(FreeImage_FIFSupportsReading(fif))
              dib = FreeImage_Load(fif, fileName.c_str());
      }

      if(!dib)
          return NULL;

      FREE_IMAGE_COLOR_TYPE fic = FreeImage_GetColorType(dib);
      
      if(fic != FIC_RGB && fic != FIC_RGBALPHA)
          return NULL;

      BYTE* pixels = FreeImage_GetBits(dib);
      
      unsigned int width  = FreeImage_GetWidth(dib);
      unsigned int height = FreeImage_GetHeight(dib);

      if((pixels == 0) || (width == 0) || (height == 0))
          return NULL;

      FREE_IMAGE_TYPE fit = FreeImage_GetImageType(dib);

      // special image handling for float-images (e.g. *.HDR)
      if(fit == FIT_RGBF)
      {
          Image* out = new Image3f(width, height, fileName);

          for(unsigned int y = 0; y < out->height; y++)
          {
              FIRGBF* bits = (FIRGBF*)FreeImage_GetScanLine(dib, y);

              unsigned int y_pos = y;

              // Mirror HDR-images!
			  if(fif == FIF_HDR)
			      y_pos = (height - 1) - y;

              for(unsigned int x = 0; x < out->width; x++)
              {
                  unsigned int x_pos = x;

				  Color4 c;
                  c.r = bits[x].red;
                  c.g = bits[x].green;
                  c.b = bits[x].blue;

                  out->set(x_pos, y_pos, c);
              }
          }

          return out;
      }
      
	  //---------------------------------
      // normal bitmap images 
	  // --> Texturen
      // --> Backplates
	  //---------------------------------
      if(fit == FIT_BITMAP)
      {
          //Image* out = new Image3c(width, height, fileName);

		  Ref<Image> out   = new Image4c(width, height, fileName);

          unsigned int bpp = FreeImage_GetBPP(dib);
          BOOL bHasAlpha   = FreeImage_IsTransparent(dib);

          float rcpMaxRGB = 1.0f / 255.0f;

		  float rcpGamma = 1.0f; // 1.4f; // TEST - nach HDRI Handbuch ( Texturen um Gamma Wert dunker machen ) 
 
          for(unsigned int y = 0; y < out->height; y++)
          {
              BYTE* bits = (BYTE*)FreeImage_GetScanLine(dib, y);

              for(unsigned int x = 0; x < out->width; x++)
              {
				  Color4 c(0, 0, 0, 1 );

                  if(bpp == 8)
                  {
                      c.r = bits[x];
                      c.g = bits[x];
                      c.b = bits[x];
                  }

                  if(bpp == 24)
                  {
                      RGBTRIPLE& Value = ((RGBTRIPLE*)bits)[x];

                      c.r = ( ((float)Value.rgbtRed  ) * rcpMaxRGB )* rcpGamma ;
                      c.g = ( ((float)Value.rgbtGreen) * rcpMaxRGB )* rcpGamma ;
                      c.b = ( ((float)Value.rgbtBlue ) * rcpMaxRGB )* rcpGamma ;
                  }

                  if(bpp == 32)
                  {
                      RGBQUAD& Value = ((RGBQUAD*)bits)[x];

                      if(bHasAlpha && Value.rgbReserved < 255) // Alpha-channel
                      {
                          // Color = Magenta
                          c.r = (255.0f) * rcpMaxRGB;
                          c.g = (  0.0f) * rcpMaxRGB;
                          c.b = (255.0f) * rcpMaxRGB;
                      }
                      else
                      {
                          c.r = ( ((float)Value.rgbRed  ) * rcpMaxRGB)* rcpGamma ;
                          c.g = ( ((float)Value.rgbGreen) * rcpMaxRGB)* rcpGamma ;
                          c.b = ( ((float)Value.rgbBlue ) * rcpMaxRGB)* rcpGamma ;
                      }
                  }

                  out->set(x, y, c);
              }
          }

          return out;
      }

      return NULL;
  }
Beispiel #13
0
const int GetTextureReference(String filename, GLint clampmode, GLint filtermode, bool optional)
{
	bool cached = false;
	TextureCacheEntry* currentCacheEntry = NULL;

	//check cache to see if it's loaded already
	std::map<String,TextureCacheEntry>::iterator it = theTextureCache.find(filename);

	// See if we already have it in the cache.
	if (it != theTextureCache.end())
	{
		//std::cout << "Found cached texture - " << filename.c_str() << std::endl;
		// If we found it and it's not dirty, bail out with the index.
		if (!it->second.dirty)
		{
			return it->second.textureIndex;
		}

		// We found it, but it's dirty.  We'll reload the texture below.
		cached = true;
		currentCacheEntry = &(it->second);
	}

	const char *texFile = filename.c_str();

	// get the image file type from FreeImage
	FREE_IMAGE_FORMAT fifmt = FreeImage_GetFileType(texFile, 0);

	if (fifmt == FIF_UNKNOWN)
	{
		fifmt = FreeImage_GetFIFFromFilename(texFile);
	}

	//actually load the image file
	FIBITMAP *dib = FreeImage_Load(fifmt, texFile, 0);

	if (dib != NULL)
	{
		GLuint texRef = 0;

		// Only generate an index if it's not cached.
		if (cached)
			texRef = currentCacheEntry->textureIndex;
		else
			glGenTextures(1, &texRef);

		glBindTexture(GL_TEXTURE_2D, texRef);

		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, clampmode);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, clampmode);

		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filtermode);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filtermode);

		GLenum format;
		int numComponents;

		if (FreeImage_IsTransparent(dib))
		{
			numComponents = 4;
			//NOTE: FreeImage loads in BGR[A] on little-endian and RGB[A] on big-endian
			//  doesn't matter since we're only using x86/Windows, but this would need to be
			//  ifdeffed if we wanted to support cross-platform stuffs. -- SJML
			format = GL_BGRA_EXT;
		}
		else
		{
			numComponents = 3;
			//NOTE: see above
			format = GL_BGR_EXT;
			dib = FreeImage_ConvertTo24Bits(dib); //want to ensure we don't have an alpha
		}

		BYTE* pixels = (BYTE*)FreeImage_GetBits(dib);

		gluBuild2DMipmaps(
			GL_TEXTURE_2D,
			numComponents,
			FreeImage_GetWidth(dib),
			FreeImage_GetHeight(dib),
			format,
			GL_UNSIGNED_BYTE,
			pixels
			);

		FreeImage_Unload(dib);

		//std::cout << "Loading - " << texFile << std::endl;

		// If it was cached, clear the dirty flag so we don't try and load it again.
		if (cached)
		{
			currentCacheEntry->dirty = false;
		}
		// If we're not cached, add a new entry.
		else 
		{
			TextureCacheEntry newEntry;
			newEntry.filename = filename;
			newEntry.clampMode = clampmode;
			newEntry.filterMode = filtermode;
			newEntry.textureIndex = texRef;
			newEntry.dirty = false;
			theTextureCache[filename] = newEntry;
		}

		return texRef;
	}
	else
	{
		if (!optional)
		{
			std::cout << "Failed to find - " << texFile << std::endl;
		}
		return -1;
	}
}
Beispiel #14
0
//加载图片
//以RGBA格式存储图片
static bool LoadImg(const char* fname,GLint nID)
{
    
    //初始化FreeImage
    FreeImage_Initialise(TRUE);
    
    //定义图片格式为未知
    FREE_IMAGE_FORMAT fif = FIF_UNKNOWN;
    
    //获取图片格式
    fif = FreeImage_GetFileType(fname,0);
    
    //根据获取格式读取图片数据
    FIBITMAP* bitmap = FreeImage_Load(fif,fname,0);
    
    if(!bitmap)
    {
        printf("load error!\n");
        return false;
    }
    
    int x,y;
    RGBQUAD m_rgb;
    
    //获取图片长宽
    width = (int)FreeImage_GetWidth(bitmap);
    height = (int)FreeImage_GetHeight(bitmap);
    
    imgBuf = new unsigned char[width*height*4];
    
    //获取图片数据
    //按RGBA格式保存到数组中
    for(y=0;y<height;y++)
    {
        for(x=0;x<width;x++)
        {
            //获取像素值
            FreeImage_GetPixelColor(bitmap,x,y,&m_rgb);
            
            //将RGB值存入数组
            imgBuf[y*width*4+x*4+0] = m_rgb.rgbRed;
            imgBuf[y*width*4+x*4+1] = m_rgb.rgbGreen;
            imgBuf[y*width*4+x*4+2] = m_rgb.rgbBlue;
            
            //判断是否透明图片
            //如果是就取alpha值保存
            if(FreeImage_IsTransparent(bitmap))
                imgBuf[y*width*4+x*4+3] = m_rgb.rgbReserved;
            else
                imgBuf[y*width*4+x*4+3] = 255;
        }
    }
    
    //绑定纹理ID
    
    if(nID==0)
    {
        glGenTextures(1, &g_texture1);
        glBindTexture(GL_TEXTURE_2D, g_texture1);
    }
    else
    {
        glGenTextures(1, &g_texture2);
        glBindTexture(GL_TEXTURE_2D, g_texture2);
    }
    
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, imgBuf);
    
    //释放FreeImage
    delete imgBuf;
    FreeImage_Unload(bitmap);
    return true;
}
Beispiel #15
0
static BOOL DLL_CALLCONV
Save(FreeImageIO *io, FIBITMAP *dib, fi_handle handle, int page, int flags, void *data) {
	png_structp png_ptr;
	png_infop info_ptr;
	png_colorp palette = NULL;
	png_uint_32 width, height;
	BOOL has_alpha_channel = FALSE;

	RGBQUAD *pal;					// pointer to dib palette
	int bit_depth, pixel_depth;		// pixel_depth = bit_depth * channels
	int palette_entries;
	int	interlace_type;

	fi_ioStructure fio;
    fio.s_handle = handle;
	fio.s_io = io;

	if ((dib) && (handle)) {
		try {
			// create the chunk manage structure

			png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, (png_voidp)NULL, error_handler, warning_handler);

			if (!png_ptr)  {
				return FALSE;
			}

			// allocate/initialize the image information data.

			info_ptr = png_create_info_struct(png_ptr);

			if (!info_ptr)  {
				png_destroy_write_struct(&png_ptr,  (png_infopp)NULL);
				return FALSE;
			}

			// Set error handling.  REQUIRED if you aren't supplying your own
			// error handling functions in the png_create_write_struct() call.

			if (setjmp(png_jmpbuf(png_ptr)))  {
				// if we get here, we had a problem reading the file

				png_destroy_write_struct(&png_ptr, &info_ptr);

				return FALSE;
			}

			// init the IO
            
			png_set_write_fn(png_ptr, &fio, _WriteProc, _FlushProc);

			// set physical resolution

			png_uint_32 res_x = (png_uint_32)FreeImage_GetDotsPerMeterX(dib);
			png_uint_32 res_y = (png_uint_32)FreeImage_GetDotsPerMeterY(dib);

			if ((res_x > 0) && (res_y > 0))  {
				png_set_pHYs(png_ptr, info_ptr, res_x, res_y, PNG_RESOLUTION_METER);
			}
	
			// Set the image information here.  Width and height are up to 2^31,
			// bit_depth is one of 1, 2, 4, 8, or 16, but valid values also depend on
			// the color_type selected. color_type is one of PNG_COLOR_TYPE_GRAY,
			// PNG_COLOR_TYPE_GRAY_ALPHA, PNG_COLOR_TYPE_PALETTE, PNG_COLOR_TYPE_RGB,
			// or PNG_COLOR_TYPE_RGB_ALPHA.  interlace is either PNG_INTERLACE_NONE or
			// PNG_INTERLACE_ADAM7, and the compression_type and filter_type MUST
			// currently be PNG_COMPRESSION_TYPE_BASE and PNG_FILTER_TYPE_BASE. REQUIRED

			width = FreeImage_GetWidth(dib);
			height = FreeImage_GetHeight(dib);
			pixel_depth = FreeImage_GetBPP(dib);

			BOOL bInterlaced = FALSE;
			if( (flags & PNG_INTERLACED) == PNG_INTERLACED) {
				interlace_type = PNG_INTERLACE_ADAM7;
				bInterlaced = TRUE;
			} else {
				interlace_type = PNG_INTERLACE_NONE;
			}

			// set the ZLIB compression level or default to PNG default compression level (ZLIB level = 6)
			int zlib_level = flags & 0x0F;
			if((zlib_level >= 1) && (zlib_level <= 9)) {
				png_set_compression_level(png_ptr, zlib_level);
			} else if((flags & PNG_Z_NO_COMPRESSION) == PNG_Z_NO_COMPRESSION) {
				png_set_compression_level(png_ptr, Z_NO_COMPRESSION);
			}

			// filtered strategy works better for high color images
			if(pixel_depth >= 16){
				png_set_compression_strategy(png_ptr, Z_FILTERED);
				png_set_filter(png_ptr, 0, PNG_FILTER_NONE|PNG_FILTER_SUB|PNG_FILTER_PAETH);
			} else {
				png_set_compression_strategy(png_ptr, Z_DEFAULT_STRATEGY);
			}

			FREE_IMAGE_TYPE image_type = FreeImage_GetImageType(dib);
			if(image_type == FIT_BITMAP) {
				// standard image type
				bit_depth = (pixel_depth > 8) ? 8 : pixel_depth;
			} else {
				// 16-bit greyscale or 16-bit RGB(A)
				bit_depth = 16;
			}

			switch (FreeImage_GetColorType(dib)) {
				case FIC_MINISWHITE:
					// Invert monochrome files to have 0 as black and 1 as white (no break here)
					png_set_invert_mono(png_ptr);

				case FIC_MINISBLACK:
					png_set_IHDR(png_ptr, info_ptr, width, height, bit_depth, 
						PNG_COLOR_TYPE_GRAY, interlace_type, 
						PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);

					break;

				case FIC_PALETTE:
				{
					png_set_IHDR(png_ptr, info_ptr, width, height, bit_depth, 
						PNG_COLOR_TYPE_PALETTE, interlace_type, 
						PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);

					// set the palette

					palette_entries = 1 << bit_depth;
					palette = (png_colorp)png_malloc(png_ptr, palette_entries * sizeof (png_color));
					pal = FreeImage_GetPalette(dib);

					for (int i = 0; i < palette_entries; i++) {
						palette[i].red   = pal[i].rgbRed;
						palette[i].green = pal[i].rgbGreen;
						palette[i].blue  = pal[i].rgbBlue;
					}
					
					png_set_PLTE(png_ptr, info_ptr, palette, palette_entries);

					// You must not free palette here, because png_set_PLTE only makes a link to
					// the palette that you malloced.  Wait until you are about to destroy
					// the png structure.

					break;
				}

				case FIC_RGBALPHA :
					has_alpha_channel = TRUE;

					png_set_IHDR(png_ptr, info_ptr, width, height, bit_depth, 
						PNG_COLOR_TYPE_RGBA, interlace_type, 
						PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);

#if FREEIMAGE_COLORORDER == FREEIMAGE_COLORORDER_BGR
					// flip BGR pixels to RGB
					if(image_type == FIT_BITMAP) {
						png_set_bgr(png_ptr);
					}
#endif
					break;
	
				case FIC_RGB:
					png_set_IHDR(png_ptr, info_ptr, width, height, bit_depth, 
						PNG_COLOR_TYPE_RGB, interlace_type, 
						PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);

#if FREEIMAGE_COLORORDER == FREEIMAGE_COLORORDER_BGR
					// flip BGR pixels to RGB
					if(image_type == FIT_BITMAP) {
						png_set_bgr(png_ptr);
					}
#endif
					break;
					
				case FIC_CMYK:
					break;
			}

			// write possible ICC profile

			FIICCPROFILE *iccProfile = FreeImage_GetICCProfile(dib);
			if (iccProfile->size && iccProfile->data) {
				png_set_iCCP(png_ptr, info_ptr, "Embedded Profile", 0, (png_const_bytep)iccProfile->data, iccProfile->size);
			}

			// write metadata

			WriteMetadata(png_ptr, info_ptr, dib);

			// Optional gamma chunk is strongly suggested if you have any guess
			// as to the correct gamma of the image.
			// png_set_gAMA(png_ptr, info_ptr, gamma);

			// set the transparency table

			if (FreeImage_IsTransparent(dib) && (FreeImage_GetTransparencyCount(dib) > 0)) {
				png_set_tRNS(png_ptr, info_ptr, FreeImage_GetTransparencyTable(dib), FreeImage_GetTransparencyCount(dib), NULL);
			}

			// set the background color

			if(FreeImage_HasBackgroundColor(dib)) {
				png_color_16 image_background;
				RGBQUAD rgbBkColor;

				FreeImage_GetBackgroundColor(dib, &rgbBkColor);
				memset(&image_background, 0, sizeof(png_color_16));
				image_background.blue  = rgbBkColor.rgbBlue;
				image_background.green = rgbBkColor.rgbGreen;
				image_background.red   = rgbBkColor.rgbRed;
				image_background.index = rgbBkColor.rgbReserved;

				png_set_bKGD(png_ptr, info_ptr, &image_background);
			}
			
			// Write the file header information.

			png_write_info(png_ptr, info_ptr);

			// write out the image data

#ifndef FREEIMAGE_BIGENDIAN
			if (bit_depth == 16) {
				// turn on 16 bit byte swapping
				png_set_swap(png_ptr);
			}
#endif

			int number_passes = 1;
			if (bInterlaced) {
				number_passes = png_set_interlace_handling(png_ptr);
			}

			if ((pixel_depth == 32) && (!has_alpha_channel)) {
				BYTE *buffer = (BYTE *)malloc(width * 3);

				// transparent conversion to 24-bit
				// the number of passes is either 1 for non-interlaced images, or 7 for interlaced images
				for (int pass = 0; pass < number_passes; pass++) {
					for (png_uint_32 k = 0; k < height; k++) {
						FreeImage_ConvertLine32To24(buffer, FreeImage_GetScanLine(dib, height - k - 1), width);			
						png_write_row(png_ptr, buffer);
					}
				}
				free(buffer);
			} else {
				// the number of passes is either 1 for non-interlaced images, or 7 for interlaced images
				for (int pass = 0; pass < number_passes; pass++) {
					for (png_uint_32 k = 0; k < height; k++) {			
						png_write_row(png_ptr, FreeImage_GetScanLine(dib, height - k - 1));					
					}
				}
			}

			// It is REQUIRED to call this to finish writing the rest of the file
			// Bug with png_flush

			png_write_end(png_ptr, info_ptr);

			// clean up after the write, and free any memory allocated
			if (palette) {
				png_free(png_ptr, palette);
			}

			png_destroy_write_struct(&png_ptr, &info_ptr);

			return TRUE;
		} catch (const char *text) {
			FreeImage_OutputMessageProc(s_format_id, text);
		}
	}

	return FALSE;
}
Beispiel #16
0
void fipWinImage::drawEx(HDC hDC, RECT& rcDest, BOOL useFileBkg, RGBQUAD *appBkColor, FIBITMAP *bg) const {
	// Convert to a standard bitmap if needed
	if(_bHasChanged) {
		if(_bDeleteMe) {
			FreeImage_Unload(_display_dib);
			_display_dib = NULL;
			_bDeleteMe = FALSE;
		}

		FREE_IMAGE_TYPE image_type = getImageType();
		if(image_type == FIT_BITMAP) {
			BOOL bHasBackground = FreeImage_HasBackgroundColor(_dib);
			BOOL bIsTransparent = FreeImage_IsTransparent(_dib);

			if(!bIsTransparent && (!bHasBackground || !useFileBkg)) {
				// Copy pointer
				_display_dib = _dib;
			}
			else {
				// Create the transparent / alpha blended image
				_display_dib = FreeImage_Composite(_dib, useFileBkg, appBkColor, bg);
				if(_display_dib) {
					// Remember to delete _display_dib
					_bDeleteMe = TRUE;
				} else {
					// Something failed: copy pointers
					_display_dib = _dib;
				}
			}
		} else {
			// Convert to a standard dib for display

			if(image_type == FIT_COMPLEX) {
				// Convert to type FIT_DOUBLE
				FIBITMAP *dib_double = FreeImage_GetComplexChannel(_dib, FICC_MAG);
				// Convert to a standard bitmap (linear scaling)
				_display_dib = FreeImage_ConvertToStandardType(dib_double, TRUE);
				// Free image of type FIT_DOUBLE
				FreeImage_Unload(dib_double);
			} else if((image_type == FIT_RGBF) || (image_type == FIT_RGB16)) {
				// Apply a tone mapping algorithm and convert to 24-bit 
				_display_dib = FreeImage_ToneMapping(_dib, _tmo, _tmo_param_1, _tmo_param_2);
			} else if(image_type == FIT_RGBA16) {
				// Convert to 32-bit
				FIBITMAP *dib32 = FreeImage_ConvertTo32Bits(_dib);
				if(dib32) {
					// Create the transparent / alpha blended image
					_display_dib = FreeImage_Composite(dib32, useFileBkg, appBkColor, bg);
					FreeImage_Unload(dib32);
				}
			} else {
				// Other cases: convert to a standard bitmap (linear scaling)
				_display_dib = FreeImage_ConvertToStandardType(_dib, TRUE);
			}
			// Remember to delete _display_dib
			_bDeleteMe = TRUE;
		}

		_bHasChanged = FALSE;
	}

	// Draw the dib
	SetStretchBltMode(hDC, COLORONCOLOR);	
	StretchDIBits(hDC, rcDest.left, rcDest.top, 
		rcDest.right-rcDest.left, rcDest.bottom-rcDest.top, 
		0, 0, FreeImage_GetWidth(_display_dib), FreeImage_GetHeight(_display_dib),
		FreeImage_GetBits(_display_dib), FreeImage_GetInfo(_display_dib), DIB_RGB_COLORS, SRCCOPY);

}
Beispiel #17
0
/**
@brief Composite a foreground image against a background color or a background image.

The equation for computing a composited sample value is:<br>
output = alpha * foreground + (1-alpha) * background<br>
where alpha and the input and output sample values are expressed as fractions in the range 0 to 1. 
For colour images, the computation is done separately for R, G, and B samples.

@param fg Foreground image
@param useFileBkg If TRUE and a file background is present, use it as the background color
@param appBkColor If not equal to NULL, and useFileBkg is FALSE, use this color as the background color
@param bg If not equal to NULL and useFileBkg is FALSE and appBkColor is NULL, use this as the background image
@return Returns the composite image if successful, returns NULL otherwise
@see FreeImage_IsTransparent, FreeImage_HasBackgroundColor
*/
FIBITMAP * DLL_CALLCONV
FreeImage_Composite(FIBITMAP *fg, BOOL useFileBkg, RGBQUAD *appBkColor, FIBITMAP *bg) {
	if(!FreeImage_HasPixels(fg)) return NULL;

	int width  = FreeImage_GetWidth(fg);
	int height = FreeImage_GetHeight(fg);
	int bpp    = FreeImage_GetBPP(fg);

	if((bpp != 8) && (bpp != 32))
		return NULL;

	if(bg) {
		int bg_width  = FreeImage_GetWidth(bg);
		int bg_height = FreeImage_GetHeight(bg);
		int bg_bpp    = FreeImage_GetBPP(bg);
		if((bg_width != width) || (bg_height != height) || (bg_bpp != 24))
			return NULL;
	}

	int bytespp = (bpp == 8) ? 1 : 4;

	
	int x, y, c;
	BYTE alpha = 0, not_alpha;
	BYTE index;
	RGBQUAD fgc;	// foreground color
	RGBQUAD bkc;	// background color

	memset(&fgc, 0, sizeof(RGBQUAD));
	memset(&bkc, 0, sizeof(RGBQUAD));

	// allocate the composite image
	FIBITMAP *composite = FreeImage_Allocate(width, height, 24, FI_RGBA_RED_MASK, FI_RGBA_GREEN_MASK, FI_RGBA_BLUE_MASK);
	if(!composite) return NULL;

	// get the palette
	RGBQUAD *pal = FreeImage_GetPalette(fg);

	// retrieve the alpha table from the foreground image
	BOOL bIsTransparent = FreeImage_IsTransparent(fg);
	BYTE *trns = FreeImage_GetTransparencyTable(fg);

	// retrieve the background color from the foreground image
	BOOL bHasBkColor = FALSE;

	if(useFileBkg && FreeImage_HasBackgroundColor(fg)) {
		FreeImage_GetBackgroundColor(fg, &bkc);
		bHasBkColor = TRUE;
	} else {
		// no file background color
		// use application background color ?
		if(appBkColor) {
			memcpy(&bkc, appBkColor, sizeof(RGBQUAD));
			bHasBkColor = TRUE;
		}
		// use background image ?
		else if(bg) {
			bHasBkColor = FALSE;
		}
	}

	for(y = 0; y < height; y++) {
		// foreground
		BYTE *fg_bits = FreeImage_GetScanLine(fg, y);
		// background
		BYTE *bg_bits = FreeImage_GetScanLine(bg, y);
		// composite image
		BYTE *cp_bits = FreeImage_GetScanLine(composite, y);

		for(x = 0; x < width; x++) {

			// foreground color + alpha

			if(bpp == 8) {
				// get the foreground color
				index = fg_bits[0];
				memcpy(&fgc, &pal[index], sizeof(RGBQUAD));
				// get the alpha
				if(bIsTransparent) {
					alpha = trns[index];
				} else {
					alpha = 255;
				}
			}
			else if(bpp == 32) {
				// get the foreground color
				fgc.rgbBlue  = fg_bits[FI_RGBA_BLUE];
				fgc.rgbGreen = fg_bits[FI_RGBA_GREEN];
				fgc.rgbRed   = fg_bits[FI_RGBA_RED];
				// get the alpha
				alpha = fg_bits[FI_RGBA_ALPHA];
			}

			// background color

			if(!bHasBkColor) {
				if(bg) {
					// get the background color from the background image
					bkc.rgbBlue  = bg_bits[FI_RGBA_BLUE];
					bkc.rgbGreen = bg_bits[FI_RGBA_GREEN];
					bkc.rgbRed   = bg_bits[FI_RGBA_RED];
				}
				else {
					// use a checkerboard pattern
					c = (((y & 0x8) == 0) ^ ((x & 0x8) == 0)) * 192;
					c = c ? c : 255;
					bkc.rgbBlue  = (BYTE)c;
					bkc.rgbGreen = (BYTE)c;
					bkc.rgbRed   = (BYTE)c;
				}
			}

			// composition

			if(alpha == 0) {
				// output = background
				cp_bits[FI_RGBA_BLUE] = bkc.rgbBlue;
				cp_bits[FI_RGBA_GREEN] = bkc.rgbGreen;
				cp_bits[FI_RGBA_RED] = bkc.rgbRed;
			}
			else if(alpha == 255) {
				// output = foreground
				cp_bits[FI_RGBA_BLUE] = fgc.rgbBlue;
				cp_bits[FI_RGBA_GREEN] = fgc.rgbGreen;
				cp_bits[FI_RGBA_RED] = fgc.rgbRed;
			}
			else {
				// output = alpha * foreground + (1-alpha) * background
				not_alpha = (BYTE)~alpha;
				cp_bits[FI_RGBA_BLUE] = (BYTE)((alpha * (WORD)fgc.rgbBlue  + not_alpha * (WORD)bkc.rgbBlue) >> 8);
				cp_bits[FI_RGBA_GREEN] = (BYTE)((alpha * (WORD)fgc.rgbGreen + not_alpha * (WORD)bkc.rgbGreen) >> 8);
				cp_bits[FI_RGBA_RED] = (BYTE)((alpha * (WORD)fgc.rgbRed   + not_alpha * (WORD)bkc.rgbRed) >> 8);
			}

			fg_bits += bytespp;
			bg_bits += 3;
			cp_bits += 3;
		}
	}

	// copy metadata from src to dst
	FreeImage_CloneMetadata(composite, fg);
	
	return composite;	
}
Beispiel #18
0
/**
 * @return true if transparency is enabled, else false
 */
bool fipImage::isTransparent(){

	return FreeImage_IsTransparent( pImageData );
}