FIBITMAP *GraphicsHelps::loadImage(std::string file, bool convertTo32bit)
{
#ifdef DEBUG_BUILD
    ElapsedTimer loadingTime;
    ElapsedTimer fReadTime;
    ElapsedTimer imgConvTime;
    loadingTime.start();
    fReadTime.start();
#endif
#if  defined(__unix__) || defined(__APPLE__) || defined(_WIN32)
    FileMapper fileMap;

    if(!fileMap.open_file(file.c_str()))
        return NULL;

    FIMEMORY *imgMEM = FreeImage_OpenMemory(reinterpret_cast<unsigned char *>(fileMap.data()),
                                            static_cast<unsigned int>(fileMap.size()));
    FREE_IMAGE_FORMAT formato = FreeImage_GetFileTypeFromMemory(imgMEM);

    if(formato  == FIF_UNKNOWN)
        return NULL;

    FIBITMAP *img = FreeImage_LoadFromMemory(formato, imgMEM, 0);
    FreeImage_CloseMemory(imgMEM);
    fileMap.close_file();

    if(!img)
        return NULL;

#else
    FREE_IMAGE_FORMAT formato = FreeImage_GetFileType(file.toUtf8().data(), 0);

    if(formato  == FIF_UNKNOWN)
        return NULL;

    FIBITMAP *img = FreeImage_Load(formato, file.toUtf8().data());

    if(!img)
        return NULL;

#endif
#ifdef DEBUG_BUILD
    long long fReadTimeElapsed = static_cast<long long>(fReadTime.elapsed());
    long long imgConvertElapsed = 0;
#endif

    if(convertTo32bit)
    {
#ifdef DEBUG_BUILD
        imgConvTime.start();
#endif
        FIBITMAP *temp;
        temp = FreeImage_ConvertTo32Bits(img);

        if(!temp)
            return NULL;

        FreeImage_Unload(img);
        img = temp;
#ifdef DEBUG_BUILD
        imgConvertElapsed = static_cast<long long>(imgConvTime.elapsed());
#endif
    }

#ifdef DEBUG_BUILD
    D_pLogDebug("File read of texture %s passed in %d milliseconds", file.c_str(), static_cast<int>(fReadTimeElapsed));
    D_pLogDebug("Conv to 32-bit of %s passed in %d milliseconds", file.c_str(), static_cast<int>(imgConvertElapsed));
    D_pLogDebug("Total Loading of image %s passed in %d milliseconds", file.c_str(), static_cast<int>(loadingTime.elapsed()));
#endif
    return img;
}
Exemple #2
0
int liimg_png_load (
	const char* file,
	int*        result_width,
	int*        result_height,
	void**      result_pixels)
{
#ifdef HAVE_FREEIMAGE
	size_t i;
	size_t x;
	size_t y;
	size_t w;
	size_t h;
	uint8_t* pixels;
	FIBITMAP* image;
	RGBQUAD color;

	/* Load the image. */
	image = FreeImage_Load (FIF_PNG, file, PNG_DEFAULT);
	if (image == NULL)
		return 0;

	/* Allocate pixel data. */
	w = FreeImage_GetWidth (image);
	h = FreeImage_GetHeight (image);
	if (w > 0 && h > 0)
	{
		pixels = lisys_calloc (w * h * 4, 1);
		if (pixels == NULL)
		{
			FreeImage_Unload (image);
			return 0;
		}
	}
	else
		pixels = NULL;

	/* Copy the pixel data. */
	for (y = 0, i = 0 ; y < h ; y++)
	{
		for (x = 0 ; x < w ; x++, i++)
		{
			FreeImage_GetPixelColor (image, x, h - y - 1, &color);
			pixels[4 * i + 0] = color.rgbRed;
			pixels[4 * i + 1] = color.rgbGreen;
			pixels[4 * i + 2] = color.rgbBlue;
			if (FreeImage_GetBPP (image) == 32)
				pixels[4 * i + 3] = color.rgbReserved;
			else
				pixels[4 * i + 3] = 0xFF;
		}
	}

	/* Set the results. */
	*result_width = w;
	*result_height = h;
	*result_pixels = pixels;
	FreeImage_Unload (image);

	return 1;
#else
	int x;
	int y;
	int depth;
	int width;
	int height;
	char* dst;
	void* pixels;
	FILE* fp;
	png_bytepp rows;
	png_infop info;
	png_structp png;

	/* Initialize structures. */
	png = png_create_read_struct (PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
	if (png == NULL)
	{
		lisys_error_set (ENOMEM, NULL);
		return 0;
	}
	info = png_create_info_struct (png);
	if (info == NULL)
	{
		png_destroy_read_struct (&png, NULL, NULL);
		lisys_error_set (ENOMEM, NULL);
		return 0;
	}

	/* Open file. */
	fp = fopen (file, "rb");
	if (fp == NULL)
	{
		lisys_error_set (EIO, "cannot open file `%s'", file);
		png_destroy_read_struct (&png, &info, NULL);
		return 0;
	}

	/* Read data. */
	if (setjmp (png_jmpbuf (png)))
	{
		lisys_error_set (EIO, "error while reading `%s'", file);
		png_destroy_read_struct (&png, &info, NULL);
		fclose (fp);
		return 0;
	}
	png_init_io (png, fp);
	png_read_png (png, info, PNG_TRANSFORM_EXPAND | PNG_TRANSFORM_STRIP_16 | PNG_TRANSFORM_PACKING, NULL);
	width = png_get_image_width (png, info);
	height = png_get_image_height (png, info);
	rows = png_get_rows (png, info);
	depth = png_get_rowbytes (png, info);
	depth /= width;
	fclose (fp);

	/* Allocate pixel data. */
	pixels = lisys_malloc (width * height * 4);
	if (pixels == NULL)
	{
		png_destroy_read_struct (&png, &info, NULL);
		return 0;
	}

	/* Copy pixel data. */
	if (depth == 3)
	{
		for (y = 0 ; y < height ; y++)
		{
			dst = pixels + 4 * width * y;
			for (x = 0 ; x < width ; x++)
			{
				dst[4 * x + 0] = ((char*) rows[y])[3 * x + 0];
				dst[4 * x + 1] = ((char*) rows[y])[3 * x + 1];
				dst[4 * x + 2] = ((char*) rows[y])[3 * x + 2];
				dst[4 * x + 3] = 0xFF;
			}
		}
	}
	else
	{
		for (y = 0 ; y < height ; y++)
		{
			dst = pixels + 4 * width * y;
			memcpy (dst, rows[y], 4 * width);
		}
	}
	*result_pixels = pixels;
	*result_width = width;
	*result_height = height;
	png_destroy_read_struct (&png, &info, NULL);

	return 1;
#endif
}
Exemple #3
0
  bool Texture::saveImToFile(const std::string& filename, const uint8_t* im, 
    const uint32_t width, const uint32_t height, const bool save_flipped, 
    const uint32_t num_channels) {
    freeimage_init_lock_.lock();
    if (!freeimage_init_) {
      freeimage_init_lock_.unlock();
      throw std::wruntime_error("Texture::Texture() - ERROR: Please call "
        "initTextureSystem() before loading textures from file!");
    }
    freeimage_init_lock_.unlock();

    // NEW CODE USING THE FREEIMAGE LIBRARY
    FREE_IMAGE_FORMAT fif = FIF_UNKNOWN;  //image format

	  // if still unknown, try to guess the file format from the file extension
	  if (fif == FIF_UNKNOWN) {
      fif = FreeImage_GetFIFFromFilename(filename.c_str());
    }
	  // if still unkown, return failure
	  if (fif == FIF_UNKNOWN) {
      throw wruntime_error(wstring(L"saveRGBToFile() - ERROR: Cannot deduce "
        L"format of the filename: ") + string_util::ToWideString(filename));
    }

    if (!FreeImage_FIFSupportsWriting(fif)) {
      throw std::wruntime_error("saveRGBToFile() - ERROR: Freeimage does not "
        "support writing to this image format!");
      return false;
    }

    BYTE* fi_bits = NULL;
    uint8_t* im_rev = NULL;

    // Unfortunately, Freeimage has a bug:
    // http://sourceforge.net/p/freeimage/bugs/172/
    // It ignores the mask properties and so the red and blue channels (24bpp)
    // get flipped.  Unfortunately, we have to swap them around.
    // As of 4/26/2013 this issue still isn't fixed.
    switch (num_channels) {
    case 0:
      throw std::wruntime_error("saveImToFile() - ERROR: num_channels == 0");
    case 1:
      fi_bits = (BYTE*)im;
      break;
    case 2:
    case 3:
      im_rev = new uint8_t[width * height * num_channels];
      for (uint32_t i = 0; i < width * height * num_channels; i+=num_channels) {
        for (uint32_t j = 0; j < num_channels; j++) {
          im_rev[i + j] = im[i + (num_channels - 1 - j)];
        }
      }
      fi_bits = (BYTE*)im_rev;
      break;
    default:
      throw std::wruntime_error("saveImToFile() - ERROR: num_channels > 0."
        " Saving images with alpha not yet supported.");
    }
    uint32_t pitch = num_channels * width;
    uint32_t bpp = 8 * num_channels;
    uint32_t red_mask = 0x0000FF;  // Free image likes the mask backwards?
    uint32_t green_mask = 0x00FF00;
    uint32_t blue_mask = 0xFF0000;
    FIBITMAP* fi_bit_map = FreeImage_ConvertFromRawBits(fi_bits, width, height,
      pitch, bpp, red_mask, blue_mask, green_mask, save_flipped);
    bool ret = false;
    if (fi_bit_map) {
      ret = (bool)FreeImage_Save(fif, fi_bit_map, filename.c_str(), 
        JPEG_QUALITYSUPERB);
    }
    if (fi_bit_map) {
      FreeImage_Unload(fi_bit_map);
    }

    SAFE_DELETE_ARR(im_rev);
    return ret;
  }
Exemple #4
0
/**
Compute gradients in x and y directions, attenuate them with the attenuation matrix, 
then compute the divergence div G from the attenuated gradient. 
@param H Normalized luminance
@param PHI Attenuation matrix
@return Returns the divergence matrix if successful, returns NULL otherwise
*/
static FIBITMAP* Divergence(FIBITMAP *H, FIBITMAP *PHI) {
	FIBITMAP *Gx = NULL, *Gy = NULL, *divG = NULL;
	float *phi, *h, *gx, *gy, *divg;

	try {
		const FREE_IMAGE_TYPE image_type = FreeImage_GetImageType(H);
		if(image_type != FIT_FLOAT) throw(1);

		const unsigned width = FreeImage_GetWidth(H);
		const unsigned height = FreeImage_GetHeight(H);

		Gx = FreeImage_AllocateT(image_type, width, height);
		if(!Gx) throw(1);
		Gy = FreeImage_AllocateT(image_type, width, height);
		if(!Gy) throw(1);
		
		const unsigned pitch = FreeImage_GetPitch(H) / sizeof(float);
		
		// perform gradient attenuation

		phi = (float*)FreeImage_GetBits(PHI);
		h   = (float*)FreeImage_GetBits(H);
		gx  = (float*)FreeImage_GetBits(Gx);
		gy  = (float*)FreeImage_GetBits(Gy);

		for(unsigned y = 0; y < height; y++) {
			const unsigned s = (y+1 == height ? y : y+1);
			for(unsigned x = 0; x < width; x++) {				
				const unsigned e = (x+1 == width ? x : x+1);
				// forward difference
				const unsigned index = y*pitch + x;
				const float phi_xy = phi[index];
				const float h_xy   = h[index];
				gx[x] = (h[y*pitch+e] - h_xy) * phi_xy; // [H(x+1, y) - H(x, y)] * PHI(x, y)
				gy[x] = (h[s*pitch+x] - h_xy) * phi_xy; // [H(x, y+1) - H(x, y)] * PHI(x, y)
			}
			// next line
			gx += pitch;
			gy += pitch;
		}

		// calculate the divergence

		divG = FreeImage_AllocateT(image_type, width, height);
		if(!divG) throw(1);
		
		gx  = (float*)FreeImage_GetBits(Gx);
		gy  = (float*)FreeImage_GetBits(Gy);
		divg = (float*)FreeImage_GetBits(divG);

		for(unsigned y0 = 0; y0 < height; y0++) {
			for(unsigned x = 0; x < width; x++) {				
				// backward difference approximation
				// divG = Gx(x, y) - Gx(x-1, y) + Gy(x, y) - Gy(x, y-1)
				const unsigned index = y0*pitch + x;
				divg[index] = gx[index] + gy[index];
				if(x > 0) divg[index] -= gx[index-1];
				if(y0 > 0) divg[index] -= gy[index-pitch];
			}
		}

		// no longer needed ... 
		FreeImage_Unload(Gx);
		FreeImage_Unload(Gy);

		// return the divergence
		return divG;

	} catch(int) {
		if(Gx) FreeImage_Unload(Gx);
		if(Gy) FreeImage_Unload(Gy);
		if(divG) FreeImage_Unload(divG);
		return NULL;
	}
}
Exemple #5
0
/**
Gradient Domain HDR tone mapping operator
@param Y Image luminance values
@param alpha Parameter alpha of the paper (suggested value is 0.1)
@param beta Parameter beta of the paper (suggested value is between 0.8 and 0.9)
@return returns the tone mapped luminance
*/
static FIBITMAP* tmoFattal02(FIBITMAP *Y, float alpha, float beta) {
	const unsigned MIN_PYRAMID_SIZE = 32;	// minimun size (width or height) of the coarsest level of the pyramid

	FIBITMAP *H = NULL;
	FIBITMAP **pyramid = NULL;
	FIBITMAP **gradients = NULL;
	FIBITMAP *phy = NULL;
	FIBITMAP *divG = NULL;
	FIBITMAP *U = NULL;
	float *avgGrad = NULL;

	int k;
	int nlevels = 0;

	try {
		// get the normalized luminance
		FIBITMAP *H = LogLuminance(Y);
		if(!H) throw(1);
		
		// get the number of levels for the pyramid
		const unsigned width = FreeImage_GetWidth(H);
		const unsigned height = FreeImage_GetHeight(H);
		unsigned minsize = MIN(width, height);
		while(minsize >= MIN_PYRAMID_SIZE) {
			nlevels++;
			minsize /= 2;
		}

		// create the Gaussian pyramid
		pyramid = (FIBITMAP**)malloc(nlevels * sizeof(FIBITMAP*));
		if(!pyramid) throw(1);
		memset(pyramid, 0, nlevels * sizeof(FIBITMAP*));

		if(!GaussianPyramid(H, pyramid, nlevels)) throw(1);

		// calculate gradient magnitude and its average value on each pyramid level
		gradients = (FIBITMAP**)malloc(nlevels * sizeof(FIBITMAP*));
		if(!gradients) throw(1);
		memset(gradients, 0, nlevels * sizeof(FIBITMAP*));
		avgGrad = (float*)malloc(nlevels * sizeof(float));
		if(!avgGrad) throw(1);

		if(!GradientPyramid(pyramid, nlevels, gradients, avgGrad)) throw(1);

		// free the Gaussian pyramid
		for(k = 0; k < nlevels; k++) {
			if(pyramid[k]) FreeImage_Unload(pyramid[k]);
		}
		free(pyramid); pyramid = NULL;

		// compute the gradient attenuation function PHI(x, y)
		phy = PhiMatrix(gradients, avgGrad, nlevels, alpha, beta);
		if(!phy) throw(1);

		// free the gradient pyramid
		for(k = 0; k < nlevels; k++) {
			if(gradients[k]) FreeImage_Unload(gradients[k]);
		}
		free(gradients); gradients = NULL;
		free(avgGrad); avgGrad = NULL;

		// compute gradients in x and y directions, attenuate them with the attenuation matrix, 
		// then compute the divergence div G from the attenuated gradient. 
		divG = Divergence(H, phy);
		if(!divG) throw(1);

		// H & phy no longer needed
		FreeImage_Unload(H); H = NULL;
		FreeImage_Unload(phy); phy = NULL;

		// solve the PDE (Poisson equation) using a multigrid solver and 3 cycles
		FIBITMAP *U = FreeImage_MultigridPoissonSolver(divG, 3);
		if(!U) throw(1);

		FreeImage_Unload(divG);

		// perform exponentiation and recover the log compressed image
		ExpLuminance(U);

		return U;

	} catch(int) {
		if(H) FreeImage_Unload(H);
		if(pyramid) {
			for(int i = 0; i < nlevels; i++) {
				if(pyramid[i]) FreeImage_Unload(pyramid[i]);
			}
			free(pyramid);
		}
		if(gradients) {
			for(int i = 0; i < nlevels; i++) {
				if(gradients[i]) FreeImage_Unload(gradients[i]);
			}
			free(gradients);
		}
		if(avgGrad) free(avgGrad);
		if(phy) FreeImage_Unload(phy);
		if(divG) FreeImage_Unload(divG);
		if(U) FreeImage_Unload(U);

		return NULL;
	}
}
Exemple #6
0
psdThumbnail::~psdThumbnail() { 
	FreeImage_Unload(_dib);
}
Exemple #7
0
FIBITMAP* psdParser::ReadImageData(FreeImageIO *io, fi_handle handle) {
	if(handle == NULL) 
		return NULL;
	
	bool header_only = (_fi_flags & FIF_LOAD_NOPIXELS) == FIF_LOAD_NOPIXELS;
	
	WORD nCompression = 0;
	io->read_proc(&nCompression, sizeof(nCompression), 1, handle);
	
#ifndef FREEIMAGE_BIGENDIAN
	SwapShort(&nCompression);
#endif
	
	if((nCompression != PSDP_COMPRESSION_NONE && nCompression != PSDP_COMPRESSION_RLE))	{
		FreeImage_OutputMessageProc(_fi_format_id, "Unsupported compression %d", nCompression);
		return NULL;
	}
	
	const unsigned nWidth = _headerInfo._Width;
	const unsigned nHeight = _headerInfo._Height;
	const unsigned nChannels = _headerInfo._Channels;
	const unsigned depth = _headerInfo._BitsPerChannel;
	const unsigned bytes = (depth == 1) ? 1 : depth / 8;
		
	// channel(plane) line (BYTE aligned)
	const unsigned lineSize = (_headerInfo._BitsPerChannel == 1) ? (nWidth + 7) / 8 : nWidth * bytes;
	
	if(nCompression == PSDP_COMPRESSION_RLE && depth > 16) {
		FreeImage_OutputMessageProc(_fi_format_id, "Unsupported RLE with depth %d", depth);
		return NULL;
	}
	
	// build output buffer
	
	FIBITMAP* bitmap = NULL;
	unsigned dstCh = 0;
	
	short mode = _headerInfo._ColourMode;
	
	if(mode == PSDP_MULTICHANNEL && nChannels < 3) {
		// CM 
		mode = PSDP_GRAYSCALE; // C as gray, M as extra channel
	}
		
	bool needPalette = false;
	switch (mode) {
		case PSDP_BITMAP:
		case PSDP_DUOTONE:	
		case PSDP_INDEXED:
		case PSDP_GRAYSCALE:
			dstCh = 1;
			switch(depth) {
				case 16:
				bitmap = FreeImage_AllocateHeaderT(header_only, FIT_UINT16, nWidth, nHeight, depth*dstCh);
				break;
				case 32:
				bitmap = FreeImage_AllocateHeaderT(header_only, FIT_FLOAT, nWidth, nHeight, depth*dstCh);
				break;
				default: // 1-, 8-
				needPalette = true;
				bitmap = FreeImage_AllocateHeader(header_only, nWidth, nHeight, depth*dstCh);
				break;
			}
			break;
		case PSDP_RGB:	
		case PSDP_LAB:		
		case PSDP_CMYK	:
		case PSDP_MULTICHANNEL	:
			// force PSDP_MULTICHANNEL CMY as CMYK
			dstCh = (mode == PSDP_MULTICHANNEL && !header_only) ? 4 : MIN<unsigned>(nChannels, 4);
			if(dstCh < 3) {
				throw "Invalid number of channels";
			}

			switch(depth) {
				case 16:
				bitmap = FreeImage_AllocateHeaderT(header_only, dstCh < 4 ? FIT_RGB16 : FIT_RGBA16, nWidth, nHeight, depth*dstCh);
				break;
				case 32:
				bitmap = FreeImage_AllocateHeaderT(header_only, dstCh < 4 ? FIT_RGBF : FIT_RGBAF, nWidth, nHeight, depth*dstCh);
				break;
				default:
				bitmap = FreeImage_AllocateHeader(header_only, nWidth, nHeight, depth*dstCh);
				break;
			}
			break;
		default:
			throw "Unsupported color mode";
			break;
	}
	if(!bitmap) {
		throw FI_MSG_ERROR_DIB_MEMORY;
	}

	// write thumbnail
	FreeImage_SetThumbnail(bitmap, _thumbnail.getDib());
		
	// @todo Add some metadata model
		
	if(header_only) {
		return bitmap;
	}
	
	// Load pixels data

	const unsigned dstChannels = dstCh;
	
	const unsigned dstBpp =  (depth == 1) ? 1 : FreeImage_GetBPP(bitmap)/8;
	const unsigned dstLineSize = FreeImage_GetPitch(bitmap);	
	BYTE* const dst_first_line = FreeImage_GetScanLine(bitmap, nHeight - 1);//<*** flipped
	
	BYTE* line_start = new BYTE[lineSize]; //< fileline cache

	switch ( nCompression ) {
		case PSDP_COMPRESSION_NONE: // raw data	
		{			
			for(unsigned c = 0; c < nChannels; c++) {
				if(c >= dstChannels) {
					// @todo write extra channels
					break; 
				}
					
				const unsigned channelOffset = c * bytes;
				
				BYTE* dst_line_start = dst_first_line;
				for(unsigned h = 0; h < nHeight; ++h, dst_line_start -= dstLineSize) {//<*** flipped

					io->read_proc(line_start, lineSize, 1, handle);
					
					for (BYTE *line = line_start, *dst_line = dst_line_start; line < line_start + lineSize; 
						line += bytes, dst_line += dstBpp) {
#ifdef FREEIMAGE_BIGENDIAN
							memcpy(dst_line + channelOffset, line, bytes);
#else
						// reverse copy bytes
						for (unsigned b = 0; b < bytes; ++b) {
							dst_line[channelOffset + b] = line[(bytes-1) - b];
						}
#endif // FREEIMAGE_BIGENDIAN
					}
				} //< h
			}//< ch
			
			SAFE_DELETE_ARRAY(line_start);
					
		}
		break;
		
		case PSDP_COMPRESSION_RLE: // RLE compression	
		{			
									
			// The RLE-compressed data is preceeded by a 2-byte line size for each row in the data,
			// store an array of these

			// later use this array as WORD rleLineSizeList[nChannels][nHeight];
			WORD *rleLineSizeList = new (std::nothrow) WORD[nChannels*nHeight];

			if(!rleLineSizeList) {
				FreeImage_Unload(bitmap);
				SAFE_DELETE_ARRAY(line_start);
				throw std::bad_alloc();
			}	
			
			io->read_proc(rleLineSizeList, 2, nChannels * nHeight, handle);
			
			WORD largestRLELine = 0;
			for(unsigned ch = 0; ch < nChannels; ++ch) {
				for(unsigned h = 0; h < nHeight; ++h) {
					const unsigned index = ch * nHeight + h;

#ifndef FREEIMAGE_BIGENDIAN 
					SwapShort(&rleLineSizeList[index]);
#endif
					if(largestRLELine < rleLineSizeList[index]) {
						largestRLELine = rleLineSizeList[index];
					}
				}
			}

			BYTE* rle_line_start = new (std::nothrow) BYTE[largestRLELine];
			if(!rle_line_start) {
				FreeImage_Unload(bitmap);
				SAFE_DELETE_ARRAY(line_start);
				SAFE_DELETE_ARRAY(rleLineSizeList);
				throw std::bad_alloc();
			}
			
			// Read the RLE data (assume 8-bit)
			
			const BYTE* const line_end = line_start + lineSize;

			for (unsigned ch = 0; ch < nChannels; ch++) {
				const unsigned channelOffset = ch * bytes;
				
				BYTE* dst_line_start = dst_first_line;
				for(unsigned h = 0; h < nHeight; ++h, dst_line_start -= dstLineSize) {//<*** flipped
					const unsigned index = ch * nHeight + h;
					
					// - read and uncompress line -
					
					const WORD rleLineSize = rleLineSizeList[index];
					
					io->read_proc(rle_line_start, rleLineSize, 1, handle);
					
					for (BYTE* rle_line = rle_line_start, *line = line_start; 
						rle_line < rle_line_start + rleLineSize, line < line_end;) {

						int len = *rle_line++;
						
						// NOTE len is signed byte in PackBits RLE
						
						if ( len < 128 ) { //<- MSB is not set
							// uncompressed packet
							
							// (len + 1) bytes of data are copied
							
							++len;
							
							// assert we don't write beyound eol
							memcpy(line, rle_line, line + len > line_end ? line_end - line : len);
							line += len;
							rle_line += len;
						}
						else if ( len > 128 ) { //< MSB is set
						
							// RLE compressed packet
							
							// One byte of data is repeated (–len + 1) times
							
							len ^= 0xFF; // same as (-len + 1) & 0xFF 
							len += 2;    //

							// assert we don't write beyound eol
							memset(line, *rle_line++, line + len > line_end ? line_end - line : len);							
							line += len;

						}
						else if ( 128 == len ) {
							// Do nothing
						}
					}//< rle_line
					
					// - write line to destination -
					
					if(ch >= dstChannels) {
						// @todo write to extra channels
						break; 
					}
						
					// byte by byte copy a single channel to pixel
					for (BYTE *line = line_start, *dst_line = dst_line_start; line < line_start + lineSize; 
						line += bytes, dst_line += dstBpp) {

#ifdef FREEIMAGE_BIGENDIAN
							memcpy(dst_line + channelOffset, line, bytes);
#else
							// reverse copy bytes
							for (unsigned b = 0; b < bytes; ++b) {
								dst_line[channelOffset + b] = line[(bytes-1) - b];							
							}
#endif // FREEIMAGE_BIGENDIAN
					}	
				}//< h
			}//< ch
			
			SAFE_DELETE_ARRAY(line_start);
			SAFE_DELETE_ARRAY(rleLineSizeList);
			SAFE_DELETE_ARRAY(rle_line_start);
		}
		break;
		
		case 2: // ZIP without prediction, no specification
			break;
			
		case 3: // ZIP with prediction, no specification
			break;
			
		default: // Unknown format
			break;
		
	}
	
	// --- Further process the bitmap ---
	
	if((mode == PSDP_CMYK || mode == PSDP_MULTICHANNEL)) {	
		// CMYK values are "inverted", invert them back		

		if(mode == PSDP_MULTICHANNEL) {
			invertColor(bitmap);
		} else {
			FreeImage_Invert(bitmap);
		}

		if((_fi_flags & PSD_CMYK) == PSD_CMYK) {
			// keep as CMYK

			if(mode == PSDP_MULTICHANNEL) {
				//### we force CMY to be CMYK, but CMY has no ICC. 
				// Create empty profile and add the flag.
				FreeImage_CreateICCProfile(bitmap, NULL, 0);
				FreeImage_GetICCProfile(bitmap)->flags |= FIICC_COLOR_IS_CMYK;
			}
		}
		else { 
			// convert to RGB
			
			ConvertCMYKtoRGBA(bitmap);
			
			// The ICC Profile is no longer valid
			_iccProfile.clear();
			
			// remove the pending A if not present in source 
			if(nChannels == 4 || nChannels == 3 ) {
				FIBITMAP* t = RemoveAlphaChannel(bitmap);
				if(t) {
					FreeImage_Unload(bitmap);
					bitmap = t;
				} // else: silently fail
			}
		}
	}
	else if ( mode == PSDP_LAB && !((_fi_flags & PSD_LAB) == PSD_LAB)) {
		ConvertLABtoRGB(bitmap);
	}
	else {
		if (needPalette && FreeImage_GetPalette(bitmap)) {
			
			if(mode == PSDP_BITMAP) {
				CREATE_GREYSCALE_PALETTE_REVERSE(FreeImage_GetPalette(bitmap), 2);
			}
			else if(mode == PSDP_INDEXED) {
				if(!_colourModeData._plColourData || _colourModeData._Length != 768 || _ColourCount < 0) {
					FreeImage_OutputMessageProc(_fi_format_id, "Indexed image has no palette. Using the default grayscale one.");
				} else {
					_colourModeData.FillPalette(bitmap);
				}
			}
			// GRAYSCALE, DUOTONE - use default grayscale palette
		}
		
#if FREEIMAGE_COLORORDER == FREEIMAGE_COLORORDER_BGR
		if(FreeImage_GetImageType(bitmap) == FIT_BITMAP) {
			SwapRedBlue32(bitmap);
		}
#endif
	}
	
	return bitmap;
} 
FIBITMAP * DLL_CALLCONV
FreeImage_ConvertToRGBF(FIBITMAP *dib) {
    FIBITMAP *src = NULL;
    FIBITMAP *dst = NULL;

    if(!FreeImage_HasPixels(dib)) return NULL;

    const FREE_IMAGE_TYPE src_type = FreeImage_GetImageType(dib);

    // check for allowed conversions
    switch(src_type) {
        case FIT_BITMAP:
            {
                // allow conversion from 24- and 32-bit
                const FREE_IMAGE_COLOR_TYPE color_type = FreeImage_GetColorType(dib);
                if((color_type != FIC_RGB) && (color_type != FIC_RGBALPHA)) {
                    src = FreeImage_ConvertTo24Bits(dib);
                    if(!src) return NULL;
                } else {
                    src = dib;
                }
                break;
            }
        case FIT_UINT16:
            // allow conversion from 16-bit
            src = dib;
            break;
        case FIT_RGB16:
            // allow conversion from 48-bit RGB
            src = dib;
            break;
        case FIT_RGBA16:
            // allow conversion from 64-bit RGBA (ignore the alpha channel)
            src = dib;
            break;
        case FIT_FLOAT:
            // allow conversion from 32-bit float
            src = dib;
            break;
        case FIT_RGBAF:
            // allow conversion from 128-bit RGBAF
            src = dib;
            break;
        case FIT_RGBF:
            // RGBF type : clone the src
            return FreeImage_Clone(dib);
            break;
        default:
            return NULL;
    }

    // allocate dst image

    const unsigned width = FreeImage_GetWidth(src);
    const unsigned height = FreeImage_GetHeight(src);

    dst = FreeImage_AllocateT(FIT_RGBF, width, height);
    if(!dst) {
        if(src != dib) {
            FreeImage_Unload(src);
        }
        return NULL;
    }

    // copy metadata from src to dst
    FreeImage_CloneMetadata(dst, src);

    // convert from src type to RGBF

    const unsigned src_pitch = FreeImage_GetPitch(src);
    const unsigned dst_pitch = FreeImage_GetPitch(dst);

    switch(src_type) {
        case FIT_BITMAP:
            {
                // calculate the number of bytes per pixel (3 for 24-bit or 4 for 32-bit)
                const unsigned bytespp = FreeImage_GetLine(src) / FreeImage_GetWidth(src);

                const BYTE *src_bits = (BYTE*)FreeImage_GetBits(src);
                BYTE *dst_bits = (BYTE*)FreeImage_GetBits(dst);

                for(unsigned y = 0; y < height; y++) {
                    const BYTE   *src_pixel = (BYTE*)src_bits;
                    FIRGBF *dst_pixel = (FIRGBF*)dst_bits;
                    for(unsigned x = 0; x < width; x++) {
                        // convert and scale to the range [0..1]
                        dst_pixel->red   = (float)(src_pixel[FI_RGBA_RED])   / 255.0F;
                        dst_pixel->green = (float)(src_pixel[FI_RGBA_GREEN]) / 255.0F;
                        dst_pixel->blue  = (float)(src_pixel[FI_RGBA_BLUE])  / 255.0F;

                        src_pixel += bytespp;
                        dst_pixel ++;
                    }
                    src_bits += src_pitch;
                    dst_bits += dst_pitch;
                }
            }
            break;

        case FIT_UINT16:
            {
                const BYTE *src_bits = (BYTE*)FreeImage_GetBits(src);
                BYTE *dst_bits = (BYTE*)FreeImage_GetBits(dst);

                for(unsigned y = 0; y < height; y++) {
                    const WORD *src_pixel = (WORD*)src_bits;
                    FIRGBF *dst_pixel = (FIRGBF*)dst_bits;

                    for(unsigned x = 0; x < width; x++) {
                        // convert and scale to the range [0..1]
                        const float dst_value = (float)src_pixel[x] / 65535.0F;
                        dst_pixel[x].red   = dst_value;
                        dst_pixel[x].green = dst_value;
                        dst_pixel[x].blue  = dst_value;
                    }
                    src_bits += src_pitch;
                    dst_bits += dst_pitch;
                }
            }
            break;

        case FIT_RGB16:
            {
                const BYTE *src_bits = (BYTE*)FreeImage_GetBits(src);
                BYTE *dst_bits = (BYTE*)FreeImage_GetBits(dst);

                for(unsigned y = 0; y < height; y++) {
                    const FIRGB16 *src_pixel = (FIRGB16*) src_bits;
                    FIRGBF  *dst_pixel = (FIRGBF*)  dst_bits;

                    for(unsigned x = 0; x < width; x++) {
                        // convert and scale to the range [0..1]
                        dst_pixel[x].red   = (float)(src_pixel[x].red)   / 65535.0F;
                        dst_pixel[x].green = (float)(src_pixel[x].green) / 65535.0F;
                        dst_pixel[x].blue  = (float)(src_pixel[x].blue)  / 65535.0F;
                    }
                    src_bits += src_pitch;
                    dst_bits += dst_pitch;
                }
            }
            break;

        case FIT_RGBA16:
            {
                const BYTE *src_bits = (BYTE*)FreeImage_GetBits(src);
                BYTE *dst_bits = (BYTE*)FreeImage_GetBits(dst);

                for(unsigned y = 0; y < height; y++) {
                    const FIRGBA16 *src_pixel = (FIRGBA16*) src_bits;
                    FIRGBF  *dst_pixel = (FIRGBF*)  dst_bits;

                    for(unsigned x = 0; x < width; x++) {
                        // convert and scale to the range [0..1]
                        dst_pixel[x].red   = (float)(src_pixel[x].red)   / 65535.0F;
                        dst_pixel[x].green = (float)(src_pixel[x].green) / 65535.0F;
                        dst_pixel[x].blue  = (float)(src_pixel[x].blue)  / 65535.0F;
                    }
                    src_bits += src_pitch;
                    dst_bits += dst_pitch;
                }
            }
            break;

        case FIT_FLOAT:
            {
                const BYTE *src_bits = (BYTE*)FreeImage_GetBits(src);
                BYTE *dst_bits = (BYTE*)FreeImage_GetBits(dst);

                for(unsigned y = 0; y < height; y++) {
                    const float *src_pixel = (float*) src_bits;
                    FIRGBF  *dst_pixel = (FIRGBF*)  dst_bits;

                    for(unsigned x = 0; x < width; x++) {
                        // convert by copying greyscale channel to each R, G, B channels
                        // assume float values are in [0..1]
                        const float value = CLAMP(src_pixel[x], 0.0F, 1.0F);
                        dst_pixel[x].red   = value;
                        dst_pixel[x].green = value;
                        dst_pixel[x].blue  = value;
                    }
                    src_bits += src_pitch;
                    dst_bits += dst_pitch;
                }
            }
            break;

        case FIT_RGBAF:
            {
                const BYTE *src_bits = (BYTE*)FreeImage_GetBits(src);
                BYTE *dst_bits = (BYTE*)FreeImage_GetBits(dst);

                for(unsigned y = 0; y < height; y++) {
                    const FIRGBAF *src_pixel = (FIRGBAF*) src_bits;
                    FIRGBF  *dst_pixel = (FIRGBF*)  dst_bits;

                    for(unsigned x = 0; x < width; x++) {
                        // convert and skip alpha channel
                        dst_pixel[x].red   = CLAMP(src_pixel[x].red, 0.0F, 1.0F);
                        dst_pixel[x].green = CLAMP(src_pixel[x].green, 0.0F, 1.0F);
                        dst_pixel[x].blue  = CLAMP(src_pixel[x].blue, 0.0F, 1.0F);
                    }
                    src_bits += src_pitch;
                    dst_bits += dst_pitch;
                }
            }
            break;
    }

    if(src != dib) {
        FreeImage_Unload(src);
    }

    return dst;
}
Exemple #9
0
static FIBITMAP * DLL_CALLCONV
Load(FreeImageIO *io, fi_handle handle, int page, int flags, void *data) {
	FIBITMAP *dib = NULL;
	LibRaw RawProcessor;

	BOOL header_only = (flags & FIF_LOAD_NOPIXELS) == FIF_LOAD_NOPIXELS;

	try {
		// wrap the input datastream
		LibRaw_freeimage_datastream datastream(io, handle);

		// open the datastream
		if(RawProcessor.open_datastream(&datastream) != LIBRAW_SUCCESS) {
			throw "LibRaw : failed to open input stream (unknown format)";
		}

		if(header_only) {
			// header only mode
			dib = FreeImage_AllocateHeaderT(header_only, FIT_RGB16, RawProcessor.imgdata.sizes.width, RawProcessor.imgdata.sizes.height);
			// try to get JPEG embedded Exif metadata
			if(dib) {
				FIBITMAP *metadata_dib = libraw_LoadEmbeddedPreview(RawProcessor, FIF_LOAD_NOPIXELS);
				if(metadata_dib) {
					FreeImage_CloneMetadata(dib, metadata_dib);
					FreeImage_Unload(metadata_dib);
				}
			}
		}
		else if((flags & RAW_PREVIEW) == RAW_PREVIEW) {
			// try to get the embedded JPEG
			dib = libraw_LoadEmbeddedPreview(RawProcessor, 0);
			if(!dib) {
				// no JPEG preview: try to load as 8-bit/sample (i.e. RGB 24-bit)
				dib = libraw_LoadRawData(RawProcessor, 8);
			}
		} 
		else if((flags & RAW_DISPLAY) == RAW_DISPLAY) {
			// load raw data as 8-bit/sample (i.e. RGB 24-bit)
			dib = libraw_LoadRawData(RawProcessor, 8);
		} 
		else {
			// default: load raw data as linear 16-bit/sample (i.e. RGB 48-bit)
			dib = libraw_LoadRawData(RawProcessor, 16);
		}

		// save ICC profile if present
		if(NULL != RawProcessor.imgdata.color.profile) {
			FreeImage_CreateICCProfile(dib, RawProcessor.imgdata.color.profile, RawProcessor.imgdata.color.profile_length);
		}

		// try to get JPEG embedded Exif metadata
		if(dib && !((flags & RAW_PREVIEW) == RAW_PREVIEW) ) {
			FIBITMAP *metadata_dib = libraw_LoadEmbeddedPreview(RawProcessor, FIF_LOAD_NOPIXELS);
			if(metadata_dib) {
				FreeImage_CloneMetadata(dib, metadata_dib);
				FreeImage_Unload(metadata_dib);
			}
		}

		// clean-up internal memory allocations
		RawProcessor.recycle();

		return dib;

	} catch(const char *text) {
		if(dib) {
			FreeImage_Unload(dib);
		}
		RawProcessor.recycle();
		FreeImage_OutputMessageProc(s_format_id, text);
	}

	return NULL;
}
static void saveImage(ofPixels_<PixelType> & pix, string fileName, ofImageQualityType qualityLevel) {
	ofInitFreeImage();
	if (pix.isAllocated() == false){
		ofLog(OF_LOG_ERROR,"error saving image - pixels aren't allocated");
		return;
	}

	#ifdef TARGET_LITTLE_ENDIAN
	if(sizeof(PixelType) == 1) {
		pix.swapRgb();
	}
	#endif

	FIBITMAP * bmp	= getBmpFromPixels(pix);

	#ifdef TARGET_LITTLE_ENDIAN
	if(sizeof(PixelType) == 1) {
		pix.swapRgb();
	}
	#endif
	
	fileName = ofToDataPath(fileName);
	FREE_IMAGE_FORMAT fif = FIF_UNKNOWN;
	fif = FreeImage_GetFileType(fileName.c_str(), 0);
	if(fif == FIF_UNKNOWN) {
		// or guess via filename
		fif = FreeImage_GetFIFFromFilename(fileName.c_str());
	}
	if((fif != FIF_UNKNOWN) && FreeImage_FIFSupportsReading(fif)) {
		if(fif == FIF_JPEG) {
			int quality = JPEG_QUALITYSUPERB;
			switch(qualityLevel) {
				case OF_IMAGE_QUALITY_WORST: quality = JPEG_QUALITYBAD; break;
				case OF_IMAGE_QUALITY_LOW: quality = JPEG_QUALITYAVERAGE; break;
				case OF_IMAGE_QUALITY_MEDIUM: quality = JPEG_QUALITYNORMAL; break;
				case OF_IMAGE_QUALITY_HIGH: quality = JPEG_QUALITYGOOD; break;
				case OF_IMAGE_QUALITY_BEST: quality = JPEG_QUALITYSUPERB; break;
			}
			FreeImage_Save(fif, bmp, fileName.c_str(), quality);
		} else {
			if(qualityLevel != OF_IMAGE_QUALITY_BEST) {
				ofLogWarning() << "ofImageCompressionType only applies to JPEG images, ignoring value";
			}
			
			if (fif == FIF_GIF) {
				FIBITMAP* convertedBmp;
				if(pix.getImageType() == OF_IMAGE_COLOR_ALPHA) {
					// this just converts the image to grayscale so it can save something
					convertedBmp = FreeImage_ConvertTo8Bits(bmp);
				} else {
					// this will create a 256-color palette from the image
					convertedBmp = FreeImage_ColorQuantize(bmp, FIQ_NNQUANT);
				}
				FreeImage_Save(fif, convertedBmp, fileName.c_str());
				if (convertedBmp != NULL){
					FreeImage_Unload(convertedBmp);
				}
			} else {
				FreeImage_Save(fif, bmp, fileName.c_str());
			}
		}
	}

	if (bmp != NULL){
		FreeImage_Unload(bmp);
	}
}
static void saveImage(ofPixels_<PixelType> & pix, ofBuffer & buffer, ofImageFormat format, ofImageQualityType qualityLevel) {
	//thanks to alvaro casinelli for the implementation

	ofInitFreeImage();

	if (pix.isAllocated() == false){
		ofLog(OF_LOG_ERROR,"error saving image - pixels aren't allocated");
		return;
	}

	#ifdef TARGET_LITTLE_ENDIAN
	if(sizeof(PixelType) == 1) {
		pix.swapRgb();
	}
	#endif

	FIBITMAP * bmp	= getBmpFromPixels(pix);

	#ifdef TARGET_LITTLE_ENDIAN
	if(sizeof(PixelType) == 1) {
		pix.swapRgb();
	}
	#endif

	if (bmp)  // bitmap successfully created
	{
		   // (b) open a memory stream to compress the image onto mem_buffer:
		   //
		   FIMEMORY *hmem = FreeImage_OpenMemory();
		   // (c) encode and save the image to the memory (on dib FIBITMAP image):
		   //
		   if(FREE_IMAGE_FORMAT(format) == FIF_JPEG) {
				int quality = JPEG_QUALITYSUPERB;
				switch(qualityLevel) {
					case OF_IMAGE_QUALITY_WORST: quality = JPEG_QUALITYBAD; break;
					case OF_IMAGE_QUALITY_LOW: quality = JPEG_QUALITYAVERAGE; break;
					case OF_IMAGE_QUALITY_MEDIUM: quality = JPEG_QUALITYNORMAL; break;
					case OF_IMAGE_QUALITY_HIGH: quality = JPEG_QUALITYGOOD; break;
					case OF_IMAGE_QUALITY_BEST: quality = JPEG_QUALITYSUPERB; break;
				}
				FreeImage_SaveToMemory(FIF_JPEG, bmp, hmem, quality);
		   }else{
				FreeImage_SaveToMemory((FREE_IMAGE_FORMAT)format, bmp, hmem);
		   }
		   /*

		  NOTE: at this point, hmem contains the entire data in memory stored in fif format. the
		  amount of space used by the memory is equal to file_size:
		  long file_size = FreeImage_TellMemory(hmem);
		  but can also be retrieved by FreeImage_AcquireMemory that retrieves both the
		  length of the buffer, and the buffer memory address.
		  */
			#ifdef TARGET_WIN32
		   	   DWORD size_in_bytes = 0;
			#else
		   	   uint32_t size_in_bytes = 0;
			#endif
		   // Save compressed data on mem_buffer
		   // note: FreeImage_AquireMemory allocates space for aux_mem_buffer):
		   //
		   unsigned char *mem_buffer = NULL;
		   if (!FreeImage_AcquireMemory(hmem, &mem_buffer, &size_in_bytes))
				   cout << "Error aquiring compressed image from memory" << endl;

		   /*
			  Now, before closing the memory stream, copy the content of mem_buffer
			  to an auxiliary buffer
		    */

		   buffer.set((char*)mem_buffer,size_in_bytes);

		   // Finally, close the FIBITMAP object, or we will get a memory leak:
		   FreeImage_Unload(bmp);

		   // Close the memory stream (otherwise we may get a memory leak).
		   FreeImage_CloseMemory(hmem);
	}
}
unsigned int LoadTexture(const char* a_szTexture) 
{ 
	FIBITMAP* pBitmap = nullptr;
 
	// Determime File Type from File Signature
	FREE_IMAGE_FORMAT fif = FreeImage_GetFileType(a_szTexture, 0); 
 
	// Success
	if (fif != FIF_UNKNOWN && FreeImage_FIFSupportsReading(fif)) 
	{ 
		pBitmap = FreeImage_Load(fif, a_szTexture); 
	} 
 
	// Failure
	if (pBitmap == nullptr) 
	{ 
		printf("Error: Failed to load image '%s'!\n", a_szTexture); 
		return 0; 
	} 
 
	// Force the image to RGBA
 
	// Get size of pixel in bits
	unsigned int bpp = FreeImage_GetBPP(pBitmap);
	
	/*
 
	// How does this conversion to RGBA work?
	if( a_uiBPP != nullptr )
	{
		*a_uiBPP = bpp/8;
 
		//RGBA has 8 bits per color channel...
	}
 
	*/
 
	// Get Color Type
	FREE_IMAGE_COLOR_TYPE fi_colourType = FreeImage_GetColorType(pBitmap); 
 
	if (fi_colourType != FIC_RGBALPHA ) 
	{ 
		FIBITMAP* ndib = FreeImage_ConvertTo32Bits(pBitmap); 
		FreeImage_Unload(pBitmap); 
		pBitmap = ndib; 
		bpp = FreeImage_GetBPP(pBitmap); 
		fi_colourType = FreeImage_GetColorType(pBitmap); 
	} 
 
	// get the pixel data 
	BYTE* pData = FreeImage_GetBits(pBitmap); 
 
	// try to determine data type of file (bytes/floats) 
	FREE_IMAGE_TYPE fit = FreeImage_GetImageType(pBitmap);
 
	// VARIABLE	 =   (		CONDITION TO EVALUATE      ) ? IF_TRUE :	IF_FALSE	;
	GLenum eType = (fit == FIT_RGBF || fit == FIT_FLOAT) ? GL_FLOAT:GL_UNSIGNED_BYTE;
 
	// Create variable to store OGL Tex ID
	GLuint textureID;
	
	// Generate OGL Tex ID
	glGenTextures( 1, &textureID ); 
	
	// Bind Texture for Use by using the OGL Tex DI
	glBindTexture( GL_TEXTURE_2D, textureID ); 
	
	// Texturing allows elements of an image array to be read by shaders.
 
	glTexImage2D( GL_TEXTURE_2D,				// TARGET
				  0,							// level of detail
				  GL_RGBA,						// color format
				  FreeImage_GetWidth(pBitmap),	// width
				  FreeImage_GetHeight(pBitmap),	// height
				  0,							// border (must be 0)
				  fi_colourType,					// pixel data format - i.e. RGBA
				  eType,						// pixel data type
				  pData);						// data
 
	// specify default filtering and wrapping 
	glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 
	glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 
	glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE ); 
	glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE ); 
 
	// unbind texture 
	glBindTexture( GL_TEXTURE_2D, 0 ); 
 
	// delete data 
	FreeImage_Unload(pBitmap);
 
	return textureID; 
}
/** 
 Image rotation using a 3rd order (cubic) B-Splines.

 @param dib Input dib (8, 24 or 32-bit)
 @param angle Output image rotation
 @param x_shift Output image horizontal shift
 @param y_shift Output image vertical shift
 @param x_origin Output origin of the x-axis
 @param y_origin Output origin of the y-axis
 @param use_mask Whether or not to mask the image
 @return Returns the translated & rotated dib if successful, returns NULL otherwise
*/
FIBITMAP * DLL_CALLCONV 
FreeImage_RotateEx(FIBITMAP *dib, double angle, double x_shift, double y_shift, double x_origin, double y_origin, BOOL use_mask) {

	int x, y, bpp;
	int channel, nb_channels;
	BYTE *src_bits, *dst_bits;
	FIBITMAP *src8 = NULL, *dst8 = NULL, *dst = NULL;

	try {

		bpp = FreeImage_GetBPP(dib);

		if(bpp == 8) {
			return Rotate8Bit(dib, angle, x_shift, y_shift, x_origin, y_origin, ROTATE_CUBIC, use_mask);
		}
		if((bpp == 24) || (bpp == 32)) {
			// allocate dst image
			int width  = FreeImage_GetWidth(dib);
			int height = FreeImage_GetHeight(dib);
			if( bpp == 24 ) {
				dst = FreeImage_Allocate(width, height, bpp, FI_RGBA_RED_MASK, FI_RGBA_GREEN_MASK, FI_RGBA_BLUE_MASK);
			} else {
				dst = FreeImage_Allocate(width, height, bpp, FI_RGBA_RED_MASK, FI_RGBA_GREEN_MASK, FI_RGBA_BLUE_MASK);
			}
			if(!dst) throw(1);

			// allocate a temporary 8-bit dib (no need to build a palette)
			src8 = FreeImage_Allocate(width, height, 8);
			if(!src8) throw(1);

			// process each channel separately
			// -------------------------------
			nb_channels = (bpp / 8);

			for(channel = 0; channel < nb_channels; channel++) {
				// extract channel from source dib
				for(y = 0; y < height; y++) {
					src_bits = FreeImage_GetScanLine(dib, y);
					dst_bits = FreeImage_GetScanLine(src8, y);
					for(x = 0; x < width; x++) {
						dst_bits[x] = src_bits[channel];
						src_bits += nb_channels;
					}
				}

				// process channel
				dst8 = Rotate8Bit(src8, angle, x_shift, y_shift, x_origin, y_origin, ROTATE_CUBIC, use_mask);
				if(!dst8) throw(1);

				// insert channel to destination dib
				for(y = 0; y < height; y++) {
					src_bits = FreeImage_GetScanLine(dst8, y);
					dst_bits = FreeImage_GetScanLine(dst, y);
					for(x = 0; x < width; x++) {
						dst_bits[channel] = src_bits[x];
						dst_bits += nb_channels;
					}
				}

				FreeImage_Unload(dst8);
			}

			FreeImage_Unload(src8);

			return dst;
		}
	} catch(int) {
		if(src8) FreeImage_Unload(src8);
		if(dst8) FreeImage_Unload(dst8);
		if(dst)  FreeImage_Unload(dst);
	}

	return NULL;
}
/** 
 Image translation and rotation using B-Splines.

 @param dib Input 8-bit greyscale image
 @param angle Output image rotation in degree
 @param x_shift Output image horizontal shift
 @param y_shift Output image vertical shift
 @param x_origin Output origin of the x-axis
 @param y_origin Output origin of the y-axis
 @param spline_degree Output degree of the B-spline model
 @param use_mask Whether or not to mask the image
 @return Returns the translated & rotated dib if successful, returns NULL otherwise
*/
static FIBITMAP * 
Rotate8Bit(FIBITMAP *dib, double angle, double x_shift, double y_shift, double x_origin, double y_origin, long spline_degree, BOOL use_mask) {
	double	*ImageRasterArray;
	double	p;
	double	a11, a12, a21, a22;
	double	x0, y0, x1, y1;
	long	x, y;
	long	spline;
	bool	bResult;

	int bpp = FreeImage_GetBPP(dib);
	if(bpp != 8) {
		return NULL;
	}
	
	int width = FreeImage_GetWidth(dib);
	int height = FreeImage_GetHeight(dib);
	switch(spline_degree) {
		case ROTATE_QUADRATIC:
			spline = 2L;	// Use splines of degree 2 (quadratic interpolation)
			break;
		case ROTATE_CUBIC:
			spline = 3L;	// Use splines of degree 3 (cubic interpolation)
			break;
		case ROTATE_QUARTIC:
			spline = 4L;	// Use splines of degree 4 (quartic interpolation)
			break;
		case ROTATE_QUINTIC:
			spline = 5L;	// Use splines of degree 5 (quintic interpolation)
			break;
		default:
			spline = 3L;
	}

	// allocate output image
	FIBITMAP *dst = FreeImage_Allocate(width, height, bpp);
	if(!dst)
		return NULL;
	// buid a grey scale palette
	RGBQUAD *pal = FreeImage_GetPalette(dst);
	for(int i = 0; i < 256; i++) {
		pal[i].rgbRed = pal[i].rgbGreen = pal[i].rgbBlue = (BYTE)i;
	}

	// allocate a temporary array
	ImageRasterArray = (double*)malloc(width * height * sizeof(double));
	if(!ImageRasterArray) {
		FreeImage_Unload(dst);
		return NULL;
	}
	// copy data samples
	for(y = 0; y < height; y++) {
		double *pImage = &ImageRasterArray[y*width];
		BYTE *src_bits = FreeImage_GetScanLine(dib, height-1-y);

		for(x = 0; x < width; x++) {
			pImage[x] = (double)src_bits[x];
		}
	}

	// convert between a representation based on image samples
	// and a representation based on image B-spline coefficients
	bResult = SamplesToCoefficients(ImageRasterArray, width, height, spline);
	if(!bResult) {
		FreeImage_Unload(dst);
		free(ImageRasterArray);
		return NULL;
	}

	// prepare the geometry
	angle *= PI / 180.0;
	a11 = cos(angle);
	a12 = -sin(angle);
	a21 = sin(angle);
	a22 = cos(angle);
	x0 = a11 * (x_shift + x_origin) + a12 * (y_shift + y_origin);
	y0 = a21 * (x_shift + x_origin) + a22 * (y_shift + y_origin);
	x_shift = x_origin - x0;
	y_shift = y_origin - y0;

	// visit all pixels of the output image and assign their value
	for(y = 0; y < height; y++) {
		BYTE *dst_bits = FreeImage_GetScanLine(dst, height-1-y);
		
		x0 = a12 * (double)y + x_shift;
		y0 = a22 * (double)y + y_shift;

		for(x = 0; x < width; x++) {
			x1 = x0 + a11 * (double)x;
			y1 = y0 + a21 * (double)x;
			if(use_mask) {
				if((x1 <= -0.5) || (((double)width - 0.5) <= x1) || (y1 <= -0.5) || (((double)height - 0.5) <= y1)) {
					p = 0;
				}
				else {
					p = (double)InterpolatedValue(ImageRasterArray, width, height, x1, y1, spline);
				}
			}
			else {
				p = (double)InterpolatedValue(ImageRasterArray, width, height, x1, y1, spline);
			}
			// clamp and convert to BYTE
			dst_bits[x] = (BYTE)MIN(MAX((int)0, (int)(p + 0.5)), (int)255);
		}
	}

	// free working array and return
	free(ImageRasterArray);

	return dst;
}
BOOL DLL_CALLCONV
FreeImage_CloseMultiBitmap(FIMULTIBITMAP *bitmap, int flags) {
	if (bitmap) {
		BOOL success = TRUE;

		if (bitmap->data) {
			MULTIBITMAPHEADER *header = FreeImage_GetMultiBitmapHeader(bitmap);			

			if (header->changed) {
				// open a temp file

				char spool_name[256];

				ReplaceExtension(spool_name, header->m_filename, "fispool");

				// open the spool file and the source file

				FILE *f = fopen(spool_name, "w+b");

				void *data = FreeImage_Open(header->node, header->io, (fi_handle)f, FALSE);
				void *data_read = NULL;

				if (header->handle) {
					header->io->seek_proc(header->handle, 0, SEEK_SET);

			   		data_read = FreeImage_Open(header->node, header->io, header->handle, TRUE);
				}

				// write all the pages to the temp file

				int count = 0;				

				for (BlockListIterator i = header->m_blocks.begin(); i != header->m_blocks.end(); i++) {
					if (success) {
						switch((*i)->m_type) {
							case BLOCK_CONTINUEUS :
							{
								BlockContinueus *block = (BlockContinueus *)(*i);

								for (int j = block->m_start; j <= block->m_end; j++) {
									FIBITMAP *dib = header->node->m_plugin->load_proc(header->io, header->handle, j, header->load_flags, data_read);

									success = header->node->m_plugin->save_proc(header->io, dib, (fi_handle)f, count, flags, data);
									count++;

									FreeImage_Unload(dib);
								}

								break;
							}

							case BLOCK_REFERENCE :
							{
								BlockReference *ref = (BlockReference *)(*i);

								// read the compressed data

								BYTE *compressed_data = (BYTE*)malloc(ref->m_size * sizeof(BYTE));

								header->m_cachefile->readFile((BYTE *)compressed_data, ref->m_reference, ref->m_size);

								// uncompress the data

								FIMEMORY *hmem = FreeImage_OpenMemory(compressed_data, ref->m_size);
								FIBITMAP *dib = FreeImage_LoadFromMemory(header->cache_fif, hmem, 0);
								FreeImage_CloseMemory(hmem);

								// get rid of the buffer
								free(compressed_data);

								// save the data

								success = header->node->m_plugin->save_proc(header->io, dib, (fi_handle)f, count, flags, data);
								count++;

								// unload the dib

								FreeImage_Unload(dib);

								break;
							}
						}
					} else {
						break;
					}
				}

				// close the files

				FreeImage_Close(header->node, header->io, (fi_handle)f, data); 

				fclose(f);

				if (header->handle) {
					FreeImage_Close(header->node, header->io, header->handle, data_read);

					fclose((FILE *)header->handle);
				}	

				if (success) {
					remove(header->m_filename);

					rename(spool_name, header->m_filename);
				} else {
					remove(spool_name);
				}
			} else {
				if (header->handle && header->m_filename) {
					fclose((FILE *)header->handle);
				}
			}

			// clear the blocks list

			for (BlockListIterator i = header->m_blocks.begin(); i != header->m_blocks.end(); ++i)
				delete *i;

			// flush and dispose the cache

			if (header->m_cachefile) {
				header->m_cachefile->close();

				delete header->m_cachefile;
			}

			// delete the last open bitmaps

			while (!header->locked_pages.empty()) {
				FreeImage_Unload(header->locked_pages.begin()->first);

				header->locked_pages.erase(header->locked_pages.begin()->first);
			}

			// get rid of the IO structure

			delete header->io;

			// delete the filename

			if(header->m_filename)
				delete[] header->m_filename;

			// delete the FIMULTIBITMAPHEADER

			delete header;
		}

		delete bitmap;

		return success;
	}

	return FALSE;
}
Exemple #16
0
BOOL DLL_CALLCONV
FreeImage_SaveMultiBitmapToHandle(FREE_IMAGE_FORMAT fif, FIMULTIBITMAP *bitmap, FreeImageIO *io, fi_handle handle, int flags) {
	if(!bitmap || !bitmap->data || !io || !handle) {
		return FALSE;
	}

	BOOL success = TRUE;

	// retrieve the plugin list to find the node belonging to this plugin
	PluginList *list = FreeImage_GetPluginList();
	
	if (list) {
		PluginNode *node = list->FindNodeFromFIF(fif);

		if(node) {
			MULTIBITMAPHEADER *header = FreeImage_GetMultiBitmapHeader(bitmap);
			
			// dst data
			void *data = FreeImage_Open(node, io, handle, FALSE);
			// src data
			void *data_read = NULL;
			
			if(header->handle) {
				// open src
				header->io->seek_proc(header->handle, 0, SEEK_SET);
				data_read = FreeImage_Open(header->node, header->io, header->handle, TRUE);
			}
			
			// write all the pages to the file using handle and io
			
			int count = 0;
			
			for (BlockListIterator i = header->m_blocks.begin(); i != header->m_blocks.end(); i++) {
				if (success) {
					switch((*i)->m_type) {
						case BLOCK_CONTINUEUS:
						{
							BlockContinueus *block = (BlockContinueus *)(*i);
							
							for (int j = block->m_start; j <= block->m_end; j++) {

								// load the original source data
								FIBITMAP *dib = header->node->m_plugin->load_proc(header->io, header->handle, j, header->load_flags, data_read);
								
								// save the data
								success = node->m_plugin->save_proc(io, dib, handle, count, flags, data);
								count++;
								
								FreeImage_Unload(dib);
							}
							
							break;
						}
						
						case BLOCK_REFERENCE:
						{
							BlockReference *ref = (BlockReference *)(*i);
							
							// read the compressed data
							
							BYTE *compressed_data = (BYTE*)malloc(ref->m_size * sizeof(BYTE));
							
							header->m_cachefile->readFile((BYTE *)compressed_data, ref->m_reference, ref->m_size);
							
							// uncompress the data
							
							FIMEMORY *hmem = FreeImage_OpenMemory(compressed_data, ref->m_size);
							FIBITMAP *dib = FreeImage_LoadFromMemory(header->cache_fif, hmem, 0);
							FreeImage_CloseMemory(hmem);
							
							// get rid of the buffer
							free(compressed_data);
							
							// save the data
							
							success = node->m_plugin->save_proc(io, dib, handle, count, flags, data);
							count++;
							
							// unload the dib

							FreeImage_Unload(dib);

							break;
						}
					}
				} else {
					break;
				}
			}
			
			// close the files
			
			FreeImage_Close(header->node, header->io, header->handle, data_read);

			FreeImage_Close(node, io, handle, data); 
			
			return success;
		}
	}

	return FALSE;
}
void DLL_CALLCONV
FreeImage_UnlockPage(FIMULTIBITMAP *bitmap, FIBITMAP *page, BOOL changed) {
	if ((bitmap) && (page)) {
		MULTIBITMAPHEADER *header = FreeImage_GetMultiBitmapHeader(bitmap);

		// find out if the page we try to unlock is actually locked...

		if (header->locked_pages.find(page) != header->locked_pages.end()) {
			// store the bitmap compressed in the cache for later writing

			if (changed && !header->read_only) {
				header->changed = TRUE;

				// cut loose the block from the rest

				BlockListIterator i = FreeImage_FindBlock(bitmap, header->locked_pages[page]);

				// compress the data

				DWORD compressed_size = 0;
				BYTE *compressed_data = NULL;

				// open a memory handle
				FIMEMORY *hmem = FreeImage_OpenMemory();
				// save the page to memory
				FreeImage_SaveToMemory(header->cache_fif, page, hmem, 0);
				// get the buffer from the memory stream
				FreeImage_AcquireMemory(hmem, &compressed_data, &compressed_size);

				// write the data to the cache

				switch ((*i)->m_type) {
					case BLOCK_CONTINUEUS :
					{
						int iPage = header->m_cachefile->writeFile(compressed_data, compressed_size);

						delete (*i);

						*i = (BlockTypeS *)new BlockReference(iPage, compressed_size);

						break;
					}

					case BLOCK_REFERENCE :
					{
						BlockReference *reference = (BlockReference *)(*i);

						header->m_cachefile->deleteFile(reference->m_reference);

						delete (*i);

						int iPage = header->m_cachefile->writeFile(compressed_data, compressed_size);

						*i = (BlockTypeS *)new BlockReference(iPage, compressed_size);

						break;
					}
				}

				// get rid of the compressed data

				FreeImage_CloseMemory(hmem);
			}

			// reset the locked page so that another page can be locked

			FreeImage_Unload(page);

			header->locked_pages.erase(page);
		}
	}
}
Exemple #18
0
BOOL DLL_CALLCONV
FreeImage_CloseMultiBitmap(FIMULTIBITMAP *bitmap, int flags) {
	if (bitmap) {
		BOOL success = TRUE;
		
		if (bitmap->data) {
			MULTIBITMAPHEADER *header = FreeImage_GetMultiBitmapHeader(bitmap);			
			
			// saves changes only of images loaded directly from a file
			if (header->changed && header->m_filename) {
				try {
					// open a temp file

					std::string spool_name;

					ReplaceExtension(spool_name, header->m_filename, "fispool");

					// open the spool file and the source file
        
					FILE *f = fopen(spool_name.c_str(), "w+b");
				
					// saves changes
					if (f == NULL) {
						FreeImage_OutputMessageProc(header->fif, "Failed to open %s, %s", spool_name.c_str(), strerror(errno));
						success = FALSE;
					} else {
						success = FreeImage_SaveMultiBitmapToHandle(header->fif, bitmap, header->io, (fi_handle)f, flags);

						// close the files

						if (fclose(f) != 0) {
							success = FALSE;
							FreeImage_OutputMessageProc(header->fif, "Failed to close %s, %s", spool_name.c_str(), strerror(errno));
						}
					}
					if (header->handle) {
						fclose((FILE *)header->handle);
					}
				
					// applies changes to the destination file

					if (success) {
						remove(header->m_filename);
						success = (rename(spool_name.c_str(), header->m_filename) == 0) ? TRUE:FALSE;
						if(!success) {
							FreeImage_OutputMessageProc(header->fif, "Failed to rename %s to %s", spool_name.c_str(), header->m_filename);
						}
					} else {
						remove(spool_name.c_str());
					}
				} catch (std::bad_alloc &) {
					success = FALSE;
				}

			} else {
				if (header->handle && header->m_filename) {
					fclose((FILE *)header->handle);
				}
			}

			// clear the blocks list

			for (BlockListIterator i = header->m_blocks.begin(); i != header->m_blocks.end(); ++i) {
				delete *i;
			}

			// flush and dispose the cache

			if (header->m_cachefile) {
				header->m_cachefile->close();
				delete header->m_cachefile;
			}

			// delete the last open bitmaps

			while (!header->locked_pages.empty()) {
				FreeImage_Unload(header->locked_pages.begin()->first);

				header->locked_pages.erase(header->locked_pages.begin()->first);
			}

			// get rid of the IO structure

			delete header->io;

			// delete the filename

			if(header->m_filename) {
				delete[] header->m_filename;
			}

			// delete the FIMULTIBITMAPHEADER

			delete header;
		}

		delete bitmap;

		return success;
	}

	return FALSE;
}
Exemple #19
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;
}
Exemple #20
0
int 
main(int argc, char *argv[]) {

	const char *input_dir = "d:\\images\\";
	FIBITMAP *dib = NULL;
	int id = 1;

	// 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");

	// open the log file

	FILE *log_file = fopen("log_file.txt", "w");

	// batch convert all supported bitmaps

	_finddata_t finddata;
	long handle;
	char image_path[MAX_PATH];

	// scan all files
	strcpy(image_path, input_dir);
	strcat(image_path, "*.*");

	if ((handle = _findfirst(image_path, &finddata)) != -1) {
		do {
			// make a path to a directory

			char *directory = new char[MAX_PATH];
			strcpy(directory, input_dir);
			strcat(directory, finddata.name);

			// make a unique filename

			char *unique = new char[128];
			itoa(id, unique, 10);
			strcat(unique, ".png");

			// open and load the file using the default load option
			dib = GenericLoader(directory, 0);

			if (dib != NULL) {
				// save the file as PNG
				bool bSuccess = GenericWriter(dib, unique, PNG_DEFAULT);

				// free the dib
				FreeImage_Unload(dib);

				if(bSuccess) {
					fwrite(unique, strlen(unique), 1, log_file);
				} else {
					strcpy(unique, "FAILED");
					fwrite(unique, strlen(unique), 1, log_file);
				}
				fwrite(" >> ", 4, 1, log_file);
				fwrite(directory, strlen(directory), 1, log_file);
				fwrite("\n", 1, 1, log_file);

				id++;
			}

			delete [] unique;
			delete [] directory;

		} while (_findnext(handle, &finddata) == 0);

		_findclose(handle);
	}

	fclose(log_file);

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

	return 0;
}
Exemple #21
0
/**
Compute the gradient attenuation function PHI(x, y)
@param gradients Gradient pyramid (nlevels levels)
@param avgGrad Average gradient on each level (array of size nlevels)
@param nlevels Number of levels
@param alpha Parameter alpha in the paper
@param beta Parameter beta in the paper
@return Returns the attenuation matrix Phi if successful, returns NULL otherwise
*/
static FIBITMAP* PhiMatrix(FIBITMAP **gradients, float *avgGrad, int nlevels, float alpha, float beta) {
	float *src_pixel, *dst_pixel;
	FIBITMAP **phi = NULL;

	try {
		phi = (FIBITMAP**)malloc(nlevels * sizeof(FIBITMAP*));
		if(!phi) throw(1);
		memset(phi, 0, nlevels * sizeof(FIBITMAP*));

		for(int k = nlevels-1; k >= 0; k--) {
			// compute phi(k)

			FIBITMAP *Gk = gradients[k];

			const unsigned width = FreeImage_GetWidth(Gk);
			const unsigned height = FreeImage_GetHeight(Gk);
			const unsigned pitch = FreeImage_GetPitch(Gk) / sizeof(float);

			// parameter alpha is 0.1 times the average gradient magnitude
			// also, note the factor of 2**k in the denominator; 
			// that is there to correct for the fact that an average gradient avgGrad(H) over 2**k pixels 
			// in the original image will appear as a gradient grad(Hk) = 2**k*avgGrad(H) over a single pixel in Hk. 
			float ALPHA =  alpha * avgGrad[k] * (float)((int)1 << k);
			if(ALPHA == 0) ALPHA = EPSILON;

			phi[k] = FreeImage_AllocateT(FIT_FLOAT, width, height);
			if(!phi[k]) throw(1);
			
			src_pixel = (float*)FreeImage_GetBits(Gk);
			dst_pixel = (float*)FreeImage_GetBits(phi[k]);
			for(unsigned y = 0; y < height; y++) {
				for(unsigned x = 0; x < width; x++) {
					// compute (alpha / grad) * (grad / alpha) ** beta
					const float v = src_pixel[x] / ALPHA;
					const float value = (float)pow((float)v, (float)(beta-1));
					dst_pixel[x] = (value > 1) ? 1 : value;
				}
				// next line
				src_pixel += pitch;
				dst_pixel += pitch;
			}

			if(k < nlevels-1) {
				// compute PHI(k) = L( PHI(k+1) ) * phi(k)
				FIBITMAP *L = FreeImage_Rescale(phi[k+1], width, height, FILTER_BILINEAR);
				if(!L) throw(1);

				src_pixel = (float*)FreeImage_GetBits(L);
				dst_pixel = (float*)FreeImage_GetBits(phi[k]);
				for(unsigned y = 0; y < height; y++) {
					for(unsigned x = 0; x < width; x++) {
						dst_pixel[x] *= src_pixel[x];
					}
					// next line
					src_pixel += pitch;
					dst_pixel += pitch;
				}

				FreeImage_Unload(L);

				// PHI(k+1) is no longer needed
				FreeImage_Unload(phi[k+1]);
				phi[k+1] = NULL;
			}

			// next level
		}

		// get the final result and return
		FIBITMAP *dst = phi[0];

		free(phi);

		return dst;

	} catch(int) {
		if(phi) {
			for(int k = nlevels-1; k >= 0; k--) {
				if(phi[k]) FreeImage_Unload(phi[k]);
			}
			free(phi);
		}
		return NULL;
	}
}
Exemple #22
0
static FIBITMAP * DLL_CALLCONV
Load(FreeImageIO *io, fi_handle handle, int page, int flags, void *data) {
	mng_handle hmng = NULL;

	if (handle != NULL) {
		try {
			// allocate our stream data structure
			mngstuff *mymng = (mngstuff *)data;

			// set up the mng decoder for our stream
			hmng = mng_initialize(mymng, mymngalloc, mymngfree, MNG_NULL);

			if (hmng == MNG_NULL) {
				throw "could not initialize libmng";			
			}
			
			// set the colorprofile, lcms uses this
			mng_set_srgb(hmng, MNG_TRUE );
			// set white as background color
			WORD wRed, wGreen, wBlue;
			wRed = wGreen = wBlue = (255 << 8) + 255;
			mng_set_bgcolor(hmng, wRed, wGreen, wBlue);
			// if PNG Background is available, use it
			mng_set_usebkgd(hmng, MNG_TRUE );
			// no need to store chunks
			mng_set_storechunks(hmng, MNG_FALSE);
			// no need to wait: straight reading
			mng_set_suspensionmode(hmng, MNG_FALSE);

			// set the callbacks
			mng_setcb_errorproc(hmng, mymngerror);
			mng_setcb_openstream(hmng, mymngopenstream);
			mng_setcb_closestream(hmng, mymngclosestream);
			mng_setcb_readdata(hmng, mymngreadstream);
			mng_setcb_processheader(hmng, mymngprocessheader);
			mng_setcb_getcanvasline(hmng, mymnggetcanvasline);
			mng_setcb_refresh(hmng, mymngrefresh);
			mng_setcb_gettickcount(hmng, mymnggetticks);
			mng_setcb_settimer(hmng, mymngsettimer);
	
			// read in the bitmap
			mng_readdisplay(hmng);

			// read all bitmaps
			int retval = MNG_NOERROR;
			mng_datap pData = (mng_datap)hmng;
			while(pData->bReading) {
				retval = mng_display_resume(hmng);
				if((retval == MNG_NEEDTIMERWAIT) || (retval == MNG_FUNCTIONINVALID))
					break;
			}

			// temp store the newly created bitmap
			FIBITMAP *bitmap = mymng->bitmap;

			// cleanup and return the temp stored bitmap
			mng_cleanup(&hmng);

			return bitmap;

		} catch (const char *message) {
			FIBITMAP *bitmap = ((mngstuff *)mng_get_userdata(hmng))->bitmap;
			if(bitmap) {
				FreeImage_Unload(bitmap);
			}
			mng_cleanup(&hmng);
			FreeImage_OutputMessageProc(s_format_id, message);
		}
	}

	return NULL;
}	
Exemple #23
0
/**
Performs a 5 by 5 gaussian filtering using two 1D convolutions, 
followed by a subsampling by 2. 
@param dib Input image
@return Returns a blurred image of size SIZE(dib)/2
@see GaussianPyramid
*/
static FIBITMAP* GaussianLevel5x5(FIBITMAP *dib) {
	FIBITMAP *h_dib = NULL, *v_dib = NULL, *dst = NULL;
	float *src_pixel, *dst_pixel;

	try {
		const FREE_IMAGE_TYPE image_type = FreeImage_GetImageType(dib);
		if(image_type != FIT_FLOAT) throw(1);

		const unsigned width = FreeImage_GetWidth(dib);
		const unsigned height = FreeImage_GetHeight(dib);

		h_dib = FreeImage_AllocateT(image_type, width, height);
		v_dib = FreeImage_AllocateT(image_type, width, height);
		if(!h_dib || !v_dib) throw(1);

		const unsigned pitch = FreeImage_GetPitch(dib) / sizeof(float);

		// horizontal convolution dib -> h_dib

		src_pixel = (float*)FreeImage_GetBits(dib);
		dst_pixel = (float*)FreeImage_GetBits(h_dib);

		for(unsigned y = 0; y < height; y++) {
			// work on line y
			for(unsigned x = 2; x < width - 2; x++) {
				dst_pixel[x] = src_pixel[x-2] + src_pixel[x+2] + 4 * (src_pixel[x-1] + src_pixel[x+1]) + 6 * src_pixel[x];
				dst_pixel[x] /= 16;
			}
			// boundary mirroring
			dst_pixel[0] = (2 * src_pixel[2] + 8 * src_pixel[1] + 6 * src_pixel[0]) / 16;
			dst_pixel[1] = (src_pixel[3] + 4 * (src_pixel[0] + src_pixel[2]) + 7 * src_pixel[1]) / 16;
			dst_pixel[width-2] = (src_pixel[width-4] + 5 * src_pixel[width-1] + 4 * src_pixel[width-3] + 6 * src_pixel[width-2]) / 16;
			dst_pixel[width-1] = (src_pixel[width-3] + 5 * src_pixel[width-2] + 10 * src_pixel[width-1]) / 16;

			// next line
			src_pixel += pitch;
			dst_pixel += pitch;
		}

		// vertical convolution h_dib -> v_dib

		src_pixel = (float*)FreeImage_GetBits(h_dib);
		dst_pixel = (float*)FreeImage_GetBits(v_dib);

		for(unsigned x = 0; x < width; x++) {		
			// work on column x
			for(unsigned y = 2; y < height - 2; y++) {
				const unsigned index = y*pitch + x;
				dst_pixel[index] = src_pixel[index-2*pitch] + src_pixel[index+2*pitch] + 4 * (src_pixel[index-pitch] + src_pixel[index+pitch]) + 6 * src_pixel[index];
				dst_pixel[index] /= 16;
			}
			// boundary mirroring
			dst_pixel[x] = (2 * src_pixel[x+2*pitch] + 8 * src_pixel[x+pitch] + 6 * src_pixel[x]) / 16;
			dst_pixel[x+pitch] = (src_pixel[x+3*pitch] + 4 * (src_pixel[x] + src_pixel[x+2*pitch]) + 7 * src_pixel[x+pitch]) / 16;
			dst_pixel[(height-2)*pitch+x] = (src_pixel[(height-4)*pitch+x] + 5 * src_pixel[(height-1)*pitch+x] + 4 * src_pixel[(height-3)*pitch+x] + 6 * src_pixel[(height-2)*pitch+x]) / 16;
			dst_pixel[(height-1)*pitch+x] = (src_pixel[(height-3)*pitch+x] + 5 * src_pixel[(height-2)*pitch+x] + 10 * src_pixel[(height-1)*pitch+x]) / 16;
		}

		FreeImage_Unload(h_dib); h_dib = NULL;

		// perform downsampling

		dst = FreeImage_Rescale(v_dib, width/2, height/2, FILTER_BILINEAR);

		FreeImage_Unload(v_dib);

		return dst;

	} catch(int) {
		if(h_dib) FreeImage_Unload(h_dib);
		if(v_dib) FreeImage_Unload(v_dib);
		if(dst) FreeImage_Unload(dst);
		return NULL;
	}
}
Exemple #24
0
static FIBITMAP * DLL_CALLCONV
Load(FreeImageIO *io, fi_handle handle, int page, int flags, void *data) {
	png_structp png_ptr = NULL;
	png_infop info_ptr;
	png_uint_32 width, height;
	png_colorp png_palette = NULL;
	int color_type, palette_entries = 0;
	int bit_depth, pixel_depth;		// pixel_depth = bit_depth * channels

	FIBITMAP *dib = NULL;
	RGBQUAD *palette = NULL;		// pointer to dib palette
	png_bytepp  row_pointers = NULL;
	int i;

    fi_ioStructure fio;
    fio.s_handle = handle;
	fio.s_io = io;
    
	if (handle) {
		BOOL header_only = (flags & FIF_LOAD_NOPIXELS) == FIF_LOAD_NOPIXELS;

		try {		
			// check to see if the file is in fact a PNG file

			BYTE png_check[PNG_BYTES_TO_CHECK];

			io->read_proc(png_check, PNG_BYTES_TO_CHECK, 1, handle);

			if (png_sig_cmp(png_check, (png_size_t)0, PNG_BYTES_TO_CHECK) != 0) {
				return NULL;	// Bad signature
			}
			
			// create the chunk manage structure

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

			if (!png_ptr) {
				return NULL;			
			}

			// create the info structure

		    info_ptr = png_create_info_struct(png_ptr);

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

			// init the IO

			png_set_read_fn(png_ptr, &fio, _ReadProc);

            if (setjmp(png_jmpbuf(png_ptr))) {
				png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
				return NULL;
			}

			// because we have already read the signature...

			png_set_sig_bytes(png_ptr, PNG_BYTES_TO_CHECK);

			// read the IHDR chunk

			png_read_info(png_ptr, info_ptr);
			png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, NULL, NULL, NULL);

			pixel_depth = png_get_bit_depth(png_ptr, info_ptr) * png_get_channels(png_ptr, info_ptr);

			// get image data type (assume standard image type)

			FREE_IMAGE_TYPE image_type = FIT_BITMAP;
			if (bit_depth == 16) {
				if ((pixel_depth == 16) && (color_type == PNG_COLOR_TYPE_GRAY)) {
					image_type = FIT_UINT16;
				} 
				else if ((pixel_depth == 48) && (color_type == PNG_COLOR_TYPE_RGB)) {
					image_type = FIT_RGB16;
				} 
				else if ((pixel_depth == 64) && (color_type == PNG_COLOR_TYPE_RGB_ALPHA)) {
					image_type = FIT_RGBA16;
				} else {
					// tell libpng to strip 16 bit/color files down to 8 bits/color
					png_set_strip_16(png_ptr);
					bit_depth = 8;
				}
			}

#ifndef FREEIMAGE_BIGENDIAN
			if((image_type == FIT_UINT16) || (image_type == FIT_RGB16) || (image_type == FIT_RGBA16)) {
				// turn on 16 bit byte swapping
				png_set_swap(png_ptr);
			}
#endif						

			// set some additional flags

			switch(color_type) {
				case PNG_COLOR_TYPE_RGB:
				case PNG_COLOR_TYPE_RGB_ALPHA:
#if FREEIMAGE_COLORORDER == FREEIMAGE_COLORORDER_BGR
					// flip the RGB pixels to BGR (or RGBA to BGRA)

					if(image_type == FIT_BITMAP) {
						png_set_bgr(png_ptr);
					}
#endif
					break;

				case PNG_COLOR_TYPE_PALETTE:
					// expand palette images to the full 8 bits from 2 bits/pixel

					if (pixel_depth == 2) {
						png_set_packing(png_ptr);
						pixel_depth = 8;
					}					

					break;

				case PNG_COLOR_TYPE_GRAY:
					// expand grayscale images to the full 8 bits from 2 bits/pixel
					// but *do not* expand fully transparent palette entries to a full alpha channel

					if (pixel_depth == 2) {
						png_set_expand_gray_1_2_4_to_8(png_ptr);
						pixel_depth = 8;
					}

					break;

				case PNG_COLOR_TYPE_GRAY_ALPHA:
					// expand 8-bit greyscale + 8-bit alpha to 32-bit

					png_set_gray_to_rgb(png_ptr);
#if FREEIMAGE_COLORORDER == FREEIMAGE_COLORORDER_BGR
					// flip the RGBA pixels to BGRA

					png_set_bgr(png_ptr);
#endif
					pixel_depth = 32;

					break;

				default:
					throw FI_MSG_ERROR_UNSUPPORTED_FORMAT;
			}

			// unlike the example in the libpng documentation, we have *no* idea where
			// this file may have come from--so if it doesn't have a file gamma, don't
			// do any correction ("do no harm")

			if (png_get_valid(png_ptr, info_ptr, PNG_INFO_gAMA)) {
				double gamma = 0;
				double screen_gamma = 2.2;

				if (png_get_gAMA(png_ptr, info_ptr, &gamma) && ( flags & PNG_IGNOREGAMMA ) != PNG_IGNOREGAMMA) {
					png_set_gamma(png_ptr, screen_gamma, gamma);
				}
			}

			// all transformations have been registered; now update info_ptr data

			png_read_update_info(png_ptr, info_ptr);

			// color type may have changed, due to our transformations

			color_type = png_get_color_type(png_ptr,info_ptr);

			// create a DIB and write the bitmap header
			// set up the DIB palette, if needed

			switch (color_type) {
				case PNG_COLOR_TYPE_RGB:
					png_set_invert_alpha(png_ptr);

					if(image_type == FIT_BITMAP) {
						dib = FreeImage_AllocateHeader(header_only, width, height, 24, FI_RGBA_RED_MASK, FI_RGBA_GREEN_MASK, FI_RGBA_BLUE_MASK);
					} else {
						dib = FreeImage_AllocateHeaderT(header_only, image_type, width, height, pixel_depth);
					}
					break;

				case PNG_COLOR_TYPE_RGB_ALPHA:
					if(image_type == FIT_BITMAP) {
						dib = FreeImage_AllocateHeader(header_only, width, height, 32, FI_RGBA_RED_MASK, FI_RGBA_GREEN_MASK, FI_RGBA_BLUE_MASK);
					} else {
						dib = FreeImage_AllocateHeaderT(header_only, image_type, width, height, pixel_depth);
					}
					break;

				case PNG_COLOR_TYPE_PALETTE:
					dib = FreeImage_AllocateHeader(header_only, width, height, pixel_depth);

					png_get_PLTE(png_ptr,info_ptr, &png_palette, &palette_entries);

					palette_entries = MIN((unsigned)palette_entries, FreeImage_GetColorsUsed(dib));
					palette = FreeImage_GetPalette(dib);

					// store the palette

					for (i = 0; i < palette_entries; i++) {
						palette[i].rgbRed   = png_palette[i].red;
						palette[i].rgbGreen = png_palette[i].green;
						palette[i].rgbBlue  = png_palette[i].blue;
					}
					break;

				case PNG_COLOR_TYPE_GRAY:
					dib = FreeImage_AllocateHeaderT(header_only, image_type, width, height, pixel_depth);

					if(pixel_depth <= 8) {
						palette = FreeImage_GetPalette(dib);
						palette_entries = 1 << pixel_depth;

						for (i = 0; i < palette_entries; i++) {
							palette[i].rgbRed   =
							palette[i].rgbGreen =
							palette[i].rgbBlue  = (BYTE)((i * 255) / (palette_entries - 1));
						}
					}
					break;

				default:
					throw FI_MSG_ERROR_UNSUPPORTED_FORMAT;
			}

			// store the transparency table

			if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) {
				// array of alpha (transparency) entries for palette
				png_bytep trans_alpha = NULL;
				// number of transparent entries
				int num_trans = 0;						
				// graylevel or color sample values of the single transparent color for non-paletted images
				png_color_16p trans_color = NULL;

				png_get_tRNS(png_ptr, info_ptr, &trans_alpha, &num_trans, &trans_color);

				if((color_type == PNG_COLOR_TYPE_GRAY) && trans_color) {
					// single transparent color
					if (trans_color->gray < palette_entries) { 
						BYTE table[256]; 
						memset(table, 0xFF, palette_entries); 
						table[trans_color->gray] = 0; 
						FreeImage_SetTransparencyTable(dib, table, palette_entries); 
					}
				} else if((color_type == PNG_COLOR_TYPE_PALETTE) && trans_alpha) {
					// transparency table
					FreeImage_SetTransparencyTable(dib, (BYTE *)trans_alpha, num_trans);
				}
			}

			// store the background color 

			if (png_get_valid(png_ptr, info_ptr, PNG_INFO_bKGD)) {
				// Get the background color to draw transparent and alpha images over.
				// Note that even if the PNG file supplies a background, you are not required to
				// use it - you should use the (solid) application background if it has one.

				png_color_16p image_background = NULL;
				RGBQUAD rgbBkColor;

				if (png_get_bKGD(png_ptr, info_ptr, &image_background)) {
					rgbBkColor.rgbRed      = (BYTE)image_background->red;
					rgbBkColor.rgbGreen    = (BYTE)image_background->green;
					rgbBkColor.rgbBlue     = (BYTE)image_background->blue;
					rgbBkColor.rgbReserved = 0;

					FreeImage_SetBackgroundColor(dib, &rgbBkColor);
				}
			}

			// get physical resolution

			if (png_get_valid(png_ptr, info_ptr, PNG_INFO_pHYs)) {
				png_uint_32 res_x, res_y;
				
				// we'll overload this var and use 0 to mean no phys data,
				// since if it's not in meters we can't use it anyway

				int res_unit_type = PNG_RESOLUTION_UNKNOWN;

				png_get_pHYs(png_ptr,info_ptr, &res_x, &res_y, &res_unit_type);

				if (res_unit_type == PNG_RESOLUTION_METER) {
					FreeImage_SetDotsPerMeterX(dib, res_x);
					FreeImage_SetDotsPerMeterY(dib, res_y);
				}
			}

			// get possible ICC profile

			if (png_get_valid(png_ptr, info_ptr, PNG_INFO_iCCP)) {
				png_charp profile_name = NULL;
				png_bytep profile_data = NULL;
				png_uint_32 profile_length = 0;
				int  compression_type;

				png_get_iCCP(png_ptr, info_ptr, &profile_name, &compression_type, &profile_data, &profile_length);

				// copy ICC profile data (must be done after FreeImage_AllocateHeader)

				FreeImage_CreateICCProfile(dib, profile_data, profile_length);
			}

			// --- header only mode => clean-up and return

			if (header_only) {
				// get possible metadata (it can be located both before and after the image data)
				ReadMetadata(png_ptr, info_ptr, dib);
				if (png_ptr) {
					// clean up after the read, and free any memory allocated - REQUIRED
					png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL);
				}
				return dib;
			}

			// set the individual row_pointers to point at the correct offsets

			row_pointers = (png_bytepp)malloc(height * sizeof(png_bytep));

			if (!row_pointers) {
				png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
				FreeImage_Unload(dib);
				return NULL;
			}

			// read in the bitmap bits via the pointer table
			// allow loading of PNG with minor errors (such as images with several IDAT chunks)

			for (png_uint_32 k = 0; k < height; k++) {
				row_pointers[height - 1 - k] = FreeImage_GetScanLine(dib, k);			
			}

			png_set_benign_errors(png_ptr, 1);
			png_read_image(png_ptr, row_pointers);

			// check if the bitmap contains transparency, if so enable it in the header

			if (FreeImage_GetBPP(dib) == 32) {
				if (FreeImage_GetColorType(dib) == FIC_RGBALPHA) {
					FreeImage_SetTransparent(dib, TRUE);
				} else {
					FreeImage_SetTransparent(dib, FALSE);
				}
			}
				
			// cleanup

			if (row_pointers) {
				free(row_pointers);
				row_pointers = NULL;
			}

			// read the rest of the file, getting any additional chunks in info_ptr

			png_read_end(png_ptr, info_ptr);

			// get possible metadata (it can be located both before and after the image data)

			ReadMetadata(png_ptr, info_ptr, dib);

			if (png_ptr) {
				// clean up after the read, and free any memory allocated - REQUIRED
				png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL);
			}

			return dib;

		} catch (const char *text) {
			if (png_ptr) {
				png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL);
			}
			if (row_pointers) {
				free(row_pointers);
			}
			if (dib) {
				FreeImage_Unload(dib);			
			}
			FreeImage_OutputMessageProc(s_format_id, text);
			
			return NULL;
		}
	}			

	return NULL;
}
Exemple #25
0
/**
Apply the Gradient Domain High Dynamic Range Compression to a RGBF image and convert to 24-bit RGB
@param dib Input RGBF / RGB16 image
@param color_saturation Color saturation (s parameter in the paper) in [0.4..0.6]
@param attenuation Atenuation factor (beta parameter in the paper) in [0.8..0.9]
@return Returns a 24-bit RGB image if successful, returns NULL otherwise
*/
FIBITMAP* DLL_CALLCONV 
FreeImage_TmoFattal02(FIBITMAP *dib, double color_saturation, double attenuation) {	
	const float alpha = 0.1F;									// parameter alpha = 0.1
	const float beta = (float)MAX(0.8, MIN(0.9, attenuation));	// parameter beta = [0.8..0.9]
	const float s = (float)MAX(0.4, MIN(0.6, color_saturation));// exponent s controls color saturation = [0.4..0.6]

	FIBITMAP *src = NULL;
	FIBITMAP *Yin = NULL;
	FIBITMAP *Yout = NULL;
	FIBITMAP *dst = NULL;

	if(!FreeImage_HasPixels(dib)) return NULL;

	try {

		// convert to RGBF
		src = FreeImage_ConvertToRGBF(dib);
		if(!src) throw(1);

		// get the luminance channel
		Yin = ConvertRGBFToY(src);
		if(!Yin) throw(1);

		// perform the tone mapping
		Yout = tmoFattal02(Yin, alpha, beta);
		if(!Yout) throw(1);

		// clip low and high values and normalize to [0..1]
		//NormalizeY(Yout, 0.001F, 0.995F);
		NormalizeY(Yout, 0, 1);

		// compress the dynamic range

		const unsigned width = FreeImage_GetWidth(src);
		const unsigned height = FreeImage_GetHeight(src);

		const unsigned rgb_pitch = FreeImage_GetPitch(src);
		const unsigned y_pitch = FreeImage_GetPitch(Yin);

		BYTE *bits      = (BYTE*)FreeImage_GetBits(src);
		BYTE *bits_yin  = (BYTE*)FreeImage_GetBits(Yin);
		BYTE *bits_yout = (BYTE*)FreeImage_GetBits(Yout);

		for(unsigned y = 0; y < height; y++) {
			float *Lin = (float*)bits_yin;
			float *Lout = (float*)bits_yout;
			float *color = (float*)bits;
			for(unsigned x = 0; x < width; x++) {
				for(unsigned c = 0; c < 3; c++) {
					*color = (Lin[x] > 0) ? pow(*color/Lin[x], s) * Lout[x] : 0;
					color++;
				}
			}
			bits += rgb_pitch;
			bits_yin += y_pitch;
			bits_yout += y_pitch;
		}

		// not needed anymore
		FreeImage_Unload(Yin);  Yin  = NULL;
		FreeImage_Unload(Yout); Yout = NULL;

		// clamp image highest values to display white, then convert to 24-bit RGB
		dst = ClampConvertRGBFTo24(src);

		// clean-up and return
		FreeImage_Unload(src); src = NULL;

		// copy metadata from src to dst
		FreeImage_CloneMetadata(dst, dib);
		
		return dst;

	} catch(int) {
		if(src) FreeImage_Unload(src);
		if(Yin) FreeImage_Unload(Yin);
		if(Yout) FreeImage_Unload(Yout);
		return NULL;
	}
}
Exemple #26
0
	GLuint OGLRenderSystem::GetTextureCache( TextureBase* tex )
	{
		GLuint& cache = (GLuint&)tex->mCache;
		if( tex->IsDirty( ) )
		{
			if( cache ) {
				glDeleteTextures( 1, &cache );
				cache = 0;
			}

			int texformat = tex->GetFormat( );
			if( texformat == 0 ) {
				glGenTextures( 1, &cache );
				if( !cache )
				{
					printf( "Failed to generate texture :: cache = 0\n" );
					return 0;
				}

				glBindTexture( GL_TEXTURE_2D, cache );
				glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
				glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );

				DWORD dwFlags = *(DWORD*)(tex->mData + 0x50);
				if( dwFlags & 0x40 )
				{
					DWORD bpp = *(DWORD*)(tex->mData + 0x58);
					int hasAlpha = dwFlags & 0x1;
					DWORD aMask = *(DWORD*)(tex->mData + 0x68);

					int type;
					int format;
					int data;

					if( bpp == 16 ) {
						if( aMask == 0x80 ) {
							//a1r5g5b5
							format = GL_RGB5_A1;
							type = GL_BGRA;
							data = GL_UNSIGNED_SHORT_1_5_5_5_REV;
						} else {
							//a4r4g4b4
							if( hasAlpha ) {
								format = GL_RGBA4;
								type = GL_BGRA;
								data = GL_UNSIGNED_SHORT_4_4_4_4_REV;
							} else {
								format = GL_RGB4;
								type = GL_BGR;
								data = GL_UNSIGNED_SHORT_4_4_4_4_REV;
							}
						}
					} else if( bpp == 32 ) {
						if( hasAlpha ) {
							format = GL_RGBA;
							type = GL_BGRA;
							data = GL_UNSIGNED_INT_8_8_8_8_REV;
						} else {
							format = GL_RGB;
							type = GL_BGR;
							data = GL_UNSIGNED_INT_8_8_8_8_REV;
						}
					}

					DWORD width = tex->GetWidth( );
					DWORD height = tex->GetHeight( );

					glTexImage2D( GL_TEXTURE_2D, 0, format, width, height, 0, type, data, (GLvoid*)(tex->mData + 0x80) );
				} else {
					FIMEMORY* imgmem = FreeImage_OpenMemory( tex->mData, tex->mDataLen );
					FREE_IMAGE_FORMAT fif = FreeImage_GetFileTypeFromMemory( imgmem );
					FIBITMAP* img = FreeImage_LoadFromMemory( fif, imgmem, 0 );

					FIBITMAP* temp = img;
					img = FreeImage_ConvertTo32Bits( img );
					FreeImage_FlipVertical( img );

					glTexImage2D( GL_TEXTURE_2D, 0, 4, FreeImage_GetWidth( img ), FreeImage_GetHeight( img ), 0, GL_BGRA, GL_UNSIGNED_BYTE, (GLvoid*)FreeImage_GetBits( img ) );

					FreeImage_Unload( temp );
					FreeImage_Unload( img );
					FreeImage_CloseMemory( imgmem );
				}
			} else if( texformat == TextureFormat::A8 ) {
				glGenTextures( 1, &cache );
				glBindTexture( GL_TEXTURE_2D, cache );
				glTexImage2D( GL_TEXTURE_2D, 0, GL_ALPHA8, tex->GetWidth( ), tex->GetHeight( ), 0, GL_ALPHA, GL_UNSIGNED_BYTE, (GLvoid*)tex->mData );
			} else {
				printf( "Failed to create Texture Cache :: Invalid format: %d\n", texformat );
				return 0;
			}

			tex->SetDirty( false );
		}
		return cache;
	};
Exemple #27
0
static FIBITMAP * DLL_CALLCONV
Load(FreeImageIO *io, fi_handle handle, int page, int flags, void *data) {
	if (handle) {
		opj_dparameters_t parameters;	// decompression parameters 
		opj_event_mgr_t event_mgr;		// event manager 
		opj_image_t *image = NULL;		// decoded image 

		BYTE *src = NULL; 
		long file_length;

		opj_dinfo_t* dinfo = NULL;	// handle to a decompressor 
		opj_cio_t *cio = NULL;

		FIBITMAP *dib = NULL;

		// check the file format
		if(!Validate(io, handle)) {
			return NULL;
		}

		// configure the event callbacks
		memset(&event_mgr, 0, sizeof(opj_event_mgr_t));
		event_mgr.error_handler = jp2_error_callback;
		event_mgr.warning_handler = jp2_warning_callback;
		event_mgr.info_handler = NULL;

		// set decoding parameters to default values 
		opj_set_default_decoder_parameters(&parameters);

		try {
			// read the input file and put it in memory

			long start_pos = io->tell_proc(handle);
			io->seek_proc(handle, 0, SEEK_END);
			file_length = io->tell_proc(handle) - start_pos;
			io->seek_proc(handle, start_pos, SEEK_SET);
			src = (BYTE*)malloc(file_length * sizeof(BYTE));
			if(!src) {
				throw FI_MSG_ERROR_MEMORY;
			}
			if(io->read_proc(src, 1, file_length, handle) < 1) {
				throw "Error while reading input stream";
			}

			// decode the JPEG-2000 file

			// get a decoder handle 
			dinfo = opj_create_decompress(CODEC_JP2);
			
			// catch events using our callbacks
			opj_set_event_mgr((opj_common_ptr)dinfo, &event_mgr, NULL);			

			// setup the decoder decoding parameters using user parameters 
			opj_setup_decoder(dinfo, &parameters);

			// open a byte stream 
			cio = opj_cio_open((opj_common_ptr)dinfo, src, file_length);

			// decode the stream and fill the image structure 
			image = opj_decode(dinfo, cio);
			if(!image) {
				throw "Failed to decode image!\n";
			}
			
			// close the byte stream 
			opj_cio_close(cio);
			cio = NULL;

			// free the memory containing the code-stream 
			free(src);
			src = NULL;

			// free the codec context
			opj_destroy_decompress(dinfo);

			// create output image 
			dib = J2KImageToFIBITMAP(s_format_id, image);
			if(!dib) throw "Failed to import JPEG2000 image";

			// free image data structure
			opj_image_destroy(image);

			return dib;

		} catch (const char *text) {
			if(src) free(src);
			if(dib) FreeImage_Unload(dib);
			// free remaining structures
			opj_destroy_decompress(dinfo);
			opj_image_destroy(image);
			// close the byte stream
			if(cio) opj_cio_close(cio);

			FreeImage_OutputMessageProc(s_format_id, text);

			return NULL;
		}
	}

	return NULL;
}
    GXBOOL RenderTargetImpl::SaveToMemory(clstd::MemBuffer* pBuffer, GXLPCSTR pImageFormat)
    {
      GXSIZE sDimension;
      GXBOOL bval = TRUE;
      GXFormat format = m_pColorTexture->GetFormat();
      m_pColorTexture->GetDimension(&sDimension);
      Texture* pReadBackTexture = NULL;

      GetColorTexture(&pReadBackTexture, GXResUsage::Read);

      Texture::MAPPED mapped;
      if(pReadBackTexture->Map(&mapped, GXResMap::Read))
      {
        GXUINT bpp = GetBytesOfGraphicsFormat(format);

        GXLPVOID pSourceBits = mapped.pBits;
        GXINT nSourcePitch = mapped.Pitch;
        clstd::Image temp_image;
        FREE_IMAGE_TYPE fit = FIT_BITMAP;
        switch(format)
        {
        case Format_R8G8B8A8:
          temp_image.Set(sDimension.cx, sDimension.cy, "RGBA", 8, pSourceBits, nSourcePitch);
          break;
        case Format_B8G8R8X8:
          temp_image.Set(sDimension.cx, sDimension.cy, "BGRX", 8, pSourceBits, nSourcePitch);
          break;
        case Format_B8G8R8:
          temp_image.Set(sDimension.cx, sDimension.cy, "BGRX", 8, pSourceBits, nSourcePitch);
          break;
        case Format_R8:
          temp_image.Set(sDimension.cx, sDimension.cy, "R", 8, pSourceBits, nSourcePitch);
          break;
        case Format_R8G8:
          temp_image.Set(sDimension.cx, sDimension.cy, "RG", 8, pSourceBits, nSourcePitch);
          break;
        case Format_R32G32B32A32_Float:
          fit = FIT_RGBAF;
          break;
        case Format_R32:
          fit = FIT_FLOAT;
          break;
        }

        if(temp_image.GetDataSize() > 0)
        {
          temp_image.SetFormat("BGRA");
          pSourceBits = temp_image.GetLine(0);
          nSourcePitch = temp_image.GetPitch();
          bpp = temp_image.GetChannels();
        }

        FIBITMAP* fibmp = (fit == FIT_BITMAP)
          ? FreeImage_Allocate(sDimension.cx, sDimension.cy, bpp * 8)
          : FreeImage_AllocateT(fit, sDimension.cx, sDimension.cy, bpp * 8);
        BYTE* pDest = FreeImage_GetBits(fibmp);
        GXINT nDestPitch = FreeImage_GetPitch(fibmp);

        pDest += nDestPitch * (sDimension.cy - 1);
        for(int y = 0; y < sDimension.cy; y++)
        {
          memcpy(pDest, pSourceBits, clMin(nDestPitch, nSourcePitch));

          pDest -= nDestPitch;
          pSourceBits = reinterpret_cast<GXLPVOID>(reinterpret_cast<size_t>(pSourceBits) + nSourcePitch);
        }

        pReadBackTexture->Unmap();

        FREE_IMAGE_FORMAT fi_format = FIF_UNKNOWN;
        clStringA strFormat = pImageFormat;
        strFormat.MakeUpper();

        if(strFormat == "PNG") {
          fi_format = FIF_PNG;
        }
        else if(strFormat == "JPEG" || strFormat == "JPG") {
          fi_format = FIF_JPEG;
        }
        else if(strFormat == "TIF" || strFormat == "TIFF") {
          fi_format = FIF_TIFF;
        }
        else if(strFormat == "TGA") {
          fi_format = FIF_TARGA;
        }
        else if(strFormat == "BMP") {
          fi_format = FIF_BMP;
        }
        else if(strFormat == "EXR") {
          fi_format = FIF_EXR;
        }

        if(fi_format != FIF_UNKNOWN)
        {
          FIMEMORY* fimemory = FreeImage_OpenMemory();
          if(FreeImage_SaveToMemory(fi_format, fibmp, fimemory))
          {
            BYTE *pData;
            DWORD size_in_bytes;
            if(FreeImage_AcquireMemory(fimemory, &pData, &size_in_bytes))
            {
              pBuffer->Resize(0, FALSE);
              pBuffer->Append(pData, size_in_bytes);
            }
            else
            {
              bval = FALSE;
            }
          }
          else
          {
            bval = FALSE;
          }
          FreeImage_CloseMemory(fimemory);
        }
        else
        {
          bval = FALSE;
        }

        FreeImage_Unload(fibmp);
      }

      SAFE_RELEASE(pReadBackTexture);
      return bval;
    }
Exemple #29
0
  // Load a texture from disk
  Texture::Texture(const std::string& filename,
    const TextureWrapMode wrap, const TextureFilterMode filter,
    const bool mip_map) {
    freeimage_init_lock_.lock();
    if (!freeimage_init_) {
      freeimage_init_lock_.unlock();
      throw std::wruntime_error("Texture::Texture() - ERROR: Please call "
        "initTextureSystem() before loading textures from file!");
    }
    freeimage_init_lock_.unlock();

    mip_map_ = mip_map;
    wrap_ = wrap;
    filter_ = filter;
    filename_ = filename;
    // Check if the file has any backslashes (these dont load on Mac OS X)
    size_t ind = filename_.find_first_of('\\');
    while (ind != std::string::npos) {
      filename_[ind] = '/';
      ind = filename_.find_first_of('\\');
    }
    managed_ = false;
    from_file_ = true;

    generateTextureID();

    // NEW CODE USING THE FREEIMAGE LIBRARY
    FREE_IMAGE_FORMAT fif = FIF_UNKNOWN;  //image format
	  FIBITMAP* dib = NULL;  //pointer to the image, once loaded
	  BYTE* fi_bits = NULL;  //pointer to the image data

    // check the file signature and deduce its format
    fif = FreeImage_GetFileType(filename_.c_str(), 0);
	  // if still unknown, try to guess the file format from the file extension
	  if (fif == FIF_UNKNOWN) {
      fif = FreeImage_GetFIFFromFilename(filename_.c_str());
    }
	  // if still unkown, return failure
	  if (fif == FIF_UNKNOWN) {
      throw wruntime_error(wstring(L"Texture() - ERROR: Cannot deduce format"
        L" of the file: ") + string_util::ToWideString(filename_));
    }

    // check that FreeImage has reading capabilities and if so load the file
    if (FreeImage_FIFSupportsReading(fif)) {
      dib = FreeImage_Load(fif, filename_.c_str());
    }
    //if the image failed to load, return failure
    if (!dib) {
      throw wruntime_error(wstring(L"Texture() - ERROR: FreeImage couldn't "
        L"load the file: ") + string_util::ToWideString(filename_));
    }

    // Convert everything to RGBA:
    unsigned int nbits = FreeImage_GetBPP(dib);
    if (nbits != 32) {
      FIBITMAP* old_dib = dib;
      dib = FreeImage_ConvertTo32Bits(old_dib);
      FreeImage_Unload(old_dib);
    }

    FreeImage_FlipVertical(dib);

    //retrieve the image data
	  fi_bits = FreeImage_GetBits(dib);
	  //get the image width and height
	  w_ = FreeImage_GetWidth(dib);
	  h_ = FreeImage_GetHeight(dib);
	  // if this somehow one of these failed (they shouldn't), return failure
	  if ((fi_bits == 0) || (w_ == 0) || (h_ == 0)) {
      throw wruntime_error(wstring(L"Texture() - ERROR: FreeImage couldn't "
        L"load the file: ") + string_util::ToWideString(filename));
    }

    // Copy it into memory and leave it there in case we need it later.
    bits_ = new unsigned char[w_ * h_ * 4];
    memcpy(bits_, fi_bits, sizeof(bits_[0]) * w_ * h_ * 4);

    format_internal_ = GL_RGBA;
    format_ = GL_BGRA;  // FreeImage has bits flipped!
    type_ = GL_UNSIGNED_BYTE;

    dirty_data_ = true;
    sync();  // Sync anyway on startup (fixes some shutdown bugs)

    // Free FreeImage's copy of the data
	  FreeImage_Unload(dib);

    // Unbind the texture so no one accidently makes changes to it
    GLState::glsBindTexture(GL_TEXTURE_2D, 0);
  }
void GraphicsHelps::closeImage(FIBITMAP *img)
{
    FreeImage_Unload(img);
}