Пример #1
0
Image *Image::New(FIBITMAP* dib) {
  NanScope();

  Local<Value> arg = NanNew<Integer>(0);
  Local<Object> obj = NanNew<FunctionTemplate>(constructor_template)->GetFunction()->NewInstance(1, &arg);

  Image *image = ObjectWrap::Unwrap<Image>(obj);

  int w,h,pitch;
  FREE_IMAGE_TYPE type = FreeImage_GetImageType(dib);

  obj->SetInternalField(0, NanNew<External>(dib));
  obj->Set(NanNew<String>("width"), NanNew<Integer>(w=FreeImage_GetWidth(dib)));
  obj->Set(NanNew<String>("height"), NanNew<Integer>(h=FreeImage_GetHeight(dib)));
  obj->Set(NanNew<String>("bpp"), NanNew<Integer>((int)FreeImage_GetBPP(dib)));
  obj->Set(NanNew<String>("pitch"), NanNew<Integer>(pitch=FreeImage_GetPitch(dib)));
  obj->Set(NanNew<String>("type"), NanNew<Integer>(type));
  obj->Set(NanNew<String>("redMask"), NanNew<Integer>((int)FreeImage_GetRedMask(dib)));
  obj->Set(NanNew<String>("greenMask"), NanNew<Integer>((int)FreeImage_GetGreenMask(dib)));
  obj->Set(NanNew<String>("blueMask"), NanNew<Integer>((int)FreeImage_GetBlueMask(dib)));

  BYTE *bits = FreeImage_GetBits(dib);
  obj->Set(NanNew<String>("buffer"), NanNewBufferHandle((char*) bits, h * pitch));

  return image;
}
Пример #2
0
template<class Tdst, class Tsrc> FIBITMAP* 
CONVERT_TYPE<Tdst, Tsrc>::convert(FIBITMAP *src, FREE_IMAGE_TYPE dst_type) {

	FIBITMAP *dst = NULL;

	unsigned width	= FreeImage_GetWidth(src);
	unsigned height = FreeImage_GetHeight(src);
	unsigned bpp	= FreeImage_GetBPP(src);

	// allocate dst image

	dst = FreeImage_AllocateT(dst_type, width, height, bpp, 
			FreeImage_GetRedMask(src), FreeImage_GetGreenMask(src), FreeImage_GetBlueMask(src));
	if(!dst) return NULL;

	// convert from src_type to dst_type
	
	for(unsigned y = 0; y < height; y++) {
		const Tsrc *src_bits = reinterpret_cast<Tsrc*>(FreeImage_GetScanLine(src, y));
		Tdst *dst_bits = reinterpret_cast<Tdst*>(FreeImage_GetScanLine(dst, y));

		for(unsigned x = 0; x < width; x++) {
			*dst_bits++ = static_cast<Tdst>(*src_bits++);
		}
	}

	return dst;
}
Пример #3
0
Image *Image::New(FIBITMAP* dib) {

  HandleScope scope;

  Local<Value> arg = Integer::NewFromUnsigned(0);
  Local<Object> obj = constructor_template->GetFunction()->NewInstance(1, &arg);

  Image *image = ObjectWrap::Unwrap<Image>(obj);
  image->dib = dib;

  int w,h,pitch;
  FREE_IMAGE_TYPE type = FreeImage_GetImageType(dib);

  obj->SetInternalField(0, External::New(dib));
  obj->Set(JS_STR("width"), JS_INT(w=FreeImage_GetWidth(dib)));
  obj->Set(JS_STR("height"), JS_INT(h=FreeImage_GetHeight(dib)));
  obj->Set(JS_STR("bpp"), JS_INT((int)FreeImage_GetBPP(dib)));
  obj->Set(JS_STR("pitch"), JS_INT(pitch=FreeImage_GetPitch(dib)));
  obj->Set(JS_STR("type"), JS_INT(type));
  obj->Set(JS_STR("redMask"), JS_INT((int)FreeImage_GetRedMask(dib)));
  obj->Set(JS_STR("greenMask"), JS_INT((int)FreeImage_GetGreenMask(dib)));
  obj->Set(JS_STR("blueMask"), JS_INT((int)FreeImage_GetBlueMask(dib)));

  BYTE *bits=FreeImage_GetBits(dib);
  node::Buffer *buf = node::Buffer::New((char*)bits,h*pitch);
  obj->Set(JS_STR("buffer"), buf->handle_);

  return image;
}
/*
==================
Receiving a IND_Image returns a D3D format for the source and destination. No conversion allowed in-between
==================
*/
void DirectXTextureBuilder::getSourceAndDestinationFormat(IND_Image *pImage, D3DFORMAT* pSrcFormat, D3DFORMAT* pDstFormat) {
	int bpp (pImage->getBpp());
	switch (pImage->getFormatInt()) {
	case IND_RGB: {
		if (16 == bpp) {
			FIBITMAP* fib = pImage->getFreeImageHandle();
			//Check if 565 RGB
			if ((FreeImage_GetRedMask(fib) == FI16_565_RED_MASK) 
				&& (FreeImage_GetGreenMask(fib) == FI16_565_GREEN_MASK) 
				&& (FreeImage_GetBlueMask(fib) == FI16_565_BLUE_MASK)) {
					*pSrcFormat = D3DFMT_R5G6B5;
			} else {
				*pSrcFormat = D3DFMT_UNKNOWN;
				g_debug->header("Not supported format of image! texture not loaded" , 4);
	}
		} else if (32 == bpp) {
			*pSrcFormat = D3DFMT_A8B8G8R8;
		} else {
			*pSrcFormat = D3DFMT_UNKNOWN;
			g_debug->header("The pixel format for the image could not be resolved correctly!" , 4);
		}
	}
	break;
	case IND_RGBA: {
		if (16 == bpp) {
			*pSrcFormat =D3DFMT_A4R4G4B4;
		} else if (32 == bpp){
			*pSrcFormat = D3DFMT_A8R8G8B8;
		} else {
			*pSrcFormat = D3DFMT_UNKNOWN;
			g_debug->header("The pixel format for the image could not be resolved correctly!" , 4);
	}
		
	}
	break;
    //FIXME: IND_LUMINANCE ignored?
	default: {
		*pSrcFormat = D3DFMT_UNKNOWN;
		g_debug->header("The pixel format for the image could not be resolved correctly!" , 4);
	}
	}

	//No conversions by DirectX
	*pDstFormat = *pSrcFormat;
}
Пример #5
0
	byte* LoadImage(const char* filename, uint* width, uint* height, uint* bits, bool flipY)
	{
		FREE_IMAGE_FORMAT fif = FIF_UNKNOWN;
		FIBITMAP* dib = nullptr;
		fif = FreeImage_GetFileType(filename, 0);
		if (fif == FIF_UNKNOWN)
			fif = FreeImage_GetFIFFromFilename(filename);
		if (fif == FIF_UNKNOWN)
			return nullptr;

		if (FreeImage_FIFSupportsReading(fif))
			dib = FreeImage_Load(fif, filename);

		SP_ASSERT(dib, "Could not load image '", filename, "'!");

		FIBITMAP* bitmap = FreeImage_ConvertTo32Bits(dib);
		FreeImage_Unload(dib);

		byte* pixels = FreeImage_GetBits(bitmap);
		uint w = FreeImage_GetWidth(bitmap);
		uint h = FreeImage_GetHeight(bitmap);
		uint b = FreeImage_GetBPP(bitmap);

		if (flipY)
			FreeImage_FlipVertical(bitmap);

		if (FreeImage_GetRedMask(bitmap) == 0xff0000)
			SwapRedBlue32(bitmap);

		if (width)
			*width = w;
		if (height)
			*height = h;
		if (bits)
			*bits = b;

		int32 size = w * h * (b / 8);
		byte* result = spnew byte[size];
		memcpy(result, pixels, size);
		FreeImage_Unload(bitmap);
		return result;
	}
Пример #6
0
    void GLTexture2D::Load()
    {
        auto fileOptions = GetParameters();
        auto filename = application->GetConfig().resourceBase + "/" + fileOptions[0];
        if (!boost::filesystem::exists(filename)) {
            LOG(ERROR) << "File \"" << filename.c_str() << L"\" cannot be opened.";
            throw resource_loading_error() << ::boost::errinfo_file_name(filename) << resid_info(id)
                << errdesc_info("Cannot open include file.");
        }

        auto format = FreeImage_GetFileType(filename.c_str());
        auto flags = 0;

        if (format == FIF_JPEG) {
            flags = JPEG_ACCURATE;
        } else if (format == FIF_TARGA) {
            flags = TARGA_LOAD_RGB888;
        }

        auto bitmap = FreeImage_Load(format, filename.c_str(), flags);
        auto bitmap32 = FreeImage_ConvertTo32Bits(bitmap);
        auto width = FreeImage_GetWidth(bitmap32);
        auto height = FreeImage_GetHeight(bitmap32);
        auto redMask = FreeImage_GetRedMask(bitmap32);
        auto greenMask = FreeImage_GetGreenMask(bitmap32);
        auto blueMask = FreeImage_GetBlueMask(bitmap32);
        void* data = FreeImage_GetBits(bitmap32);
        GLenum fmt = GL_RGBA;
        if (redMask > greenMask && greenMask > blueMask) fmt = GL_BGRA;
        auto internalFmt = GL_RGBA8;
        for (unsigned int i = 1; i < fileOptions.size(); ++i) {
            boost::trim(fileOptions[i]);
            if (fileOptions[i] == "sRGB" && application->GetConfig().useSRGB) internalFmt = GL_SRGB8_ALPHA8;
        }
        TextureDescriptor texDesc(4, internalFmt, fmt, GL_UNSIGNED_BYTE);
        texture = std::make_unique<GLTexture>(width, height, texDesc, data);
        FreeImage_Unload(bitmap32);
        FreeImage_Unload(bitmap);
        Resource::Load();
    }
static void splitRGBAtoBitBlt(FIBITMAP * &image, FIBITMAP *&mask)
{
    unsigned int img_w   = FreeImage_GetWidth(image);
    unsigned int img_h   = FreeImage_GetHeight(image);

    mask = FreeImage_AllocateT(FIT_BITMAP,
                               img_w, img_h,
                               FreeImage_GetBPP(image),
                               FreeImage_GetRedMask(image),
                               FreeImage_GetGreenMask(image),
                               FreeImage_GetBlueMask(image));

    RGBQUAD Fpix;
    RGBQUAD Npix = {0x0, 0x0, 0x0, 0xFF};

    for(unsigned int y = 0; (y < img_h); y++)
    {
        for(unsigned int x = 0; (x < img_w); x++)
        {
            FreeImage_GetPixelColor(image, x, y, &Fpix);

            uint8_t grey = (255 - Fpix.rgbReserved);
            Npix.rgbRed  = grey;
            Npix.rgbGreen= grey;
            Npix.rgbBlue = grey;
            Npix.rgbReserved = 255;

            Fpix.rgbRed  = subtractAlpha(Fpix.rgbRed, grey);
            Fpix.rgbGreen= subtractAlpha(Fpix.rgbGreen, grey);
            Fpix.rgbBlue = subtractAlpha(Fpix.rgbBlue, grey);
            Fpix.rgbReserved = 255;

            FreeImage_SetPixelColor(image, x, y, &Fpix);
            FreeImage_SetPixelColor(mask,  x, y, &Npix);
        }
    }
}
Пример #8
0
static BOOL DLL_CALLCONV
Save(FreeImageIO *io, FIBITMAP *dib, fi_handle handle, int page, int flags, void *data) {
	if ((dib != NULL) && (handle != NULL)) {
		// write the file header

		BITMAPFILEHEADER bitmapfileheader;
		bitmapfileheader.bfType = 0x4D42;
		bitmapfileheader.bfSize = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + FreeImage_GetHeight(dib) * FreeImage_GetPitch(dib);
		bitmapfileheader.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + FreeImage_GetColorsUsed(dib) * sizeof(RGBQUAD);
		bitmapfileheader.bfReserved1 = 0;
		bitmapfileheader.bfReserved2 = 0;

		// take care of the bit fields data of any

		bool bit_fields = (FreeImage_GetBPP(dib) == 16);

		if (bit_fields) {
			bitmapfileheader.bfSize += 3 * sizeof(DWORD);
			bitmapfileheader.bfOffBits += 3 * sizeof(DWORD);
		}

#ifdef FREEIMAGE_BIGENDIAN
		SwapFileHeader(&bitmapfileheader);
#endif
		if (io->write_proc(&bitmapfileheader, sizeof(BITMAPFILEHEADER), 1, handle) != 1)
			return FALSE;		

		// update the bitmap info header

		BITMAPINFOHEADER bih = *FreeImage_GetInfoHeader(dib);

		if (bit_fields)
			bih.biCompression = BI_BITFIELDS;
		else if ((bih.biBitCount == 8) && (flags & BMP_SAVE_RLE))
			bih.biCompression = BI_RLE8;
		else
			bih.biCompression = BI_RGB;

		// write the bitmap info header

#ifdef FREEIMAGE_BIGENDIAN
		SwapInfoHeader(&bih);
#endif
		if (io->write_proc(&bih, sizeof(BITMAPINFOHEADER), 1, handle) != 1)
			return FALSE;

		// write the bit fields when we are dealing with a 16 bit BMP

		if (bit_fields) {
			DWORD d;

			d = FreeImage_GetRedMask(dib);

			if (io->write_proc(&d, sizeof(DWORD), 1, handle) != 1)
				return FALSE;

			d = FreeImage_GetGreenMask(dib);

			if (io->write_proc(&d, sizeof(DWORD), 1, handle) != 1)
				return FALSE;

			d = FreeImage_GetBlueMask(dib);

			if (io->write_proc(&d, sizeof(DWORD), 1, handle) != 1)
				return FALSE;
		}

		// write the palette

		if (FreeImage_GetPalette(dib) != NULL) {
			RGBQUAD *pal = FreeImage_GetPalette(dib);
			FILE_BGRA bgra;
			for(unsigned i = 0; i < FreeImage_GetColorsUsed(dib); i++ ) {
				bgra.b = pal[i].rgbBlue;
				bgra.g = pal[i].rgbGreen;
				bgra.r = pal[i].rgbRed;
				bgra.a = pal[i].rgbReserved;
				if (io->write_proc(&bgra, sizeof(FILE_BGRA), 1, handle) != 1)
					return FALSE;
			}
		}

		// write the bitmap data... if RLE compression is enable, use it

		unsigned bpp = FreeImage_GetBPP(dib);
		if ((bpp == 8) && (flags & BMP_SAVE_RLE)) {
			BYTE *buffer = new BYTE[FreeImage_GetPitch(dib) * 2];

			for (DWORD i = 0; i < FreeImage_GetHeight(dib); ++i) {
				int size = RLEEncodeLine(buffer, FreeImage_GetScanLine(dib, i), FreeImage_GetLine(dib));

				if (io->write_proc(buffer, size, 1, handle) != 1) {
					delete [] buffer;
					return FALSE;
				}
			}

			buffer[0] = RLE_COMMAND;
			buffer[1] = RLE_ENDOFBITMAP;

			if (io->write_proc(buffer, 2, 1, handle) != 1) {
				delete [] buffer;
				return FALSE;
			}

			delete [] buffer;
#ifdef FREEIMAGE_BIGENDIAN
		} else if (bpp == 16) {
			WORD pixel;
			for(int y = 0; y < FreeImage_GetHeight(dib); y++) {
				BYTE *line = FreeImage_GetScanLine(dib, y);
				for(int x = 0; x < FreeImage_GetWidth(dib); x++) {
					pixel = ((WORD *)line)[x];
					SwapShort(&pixel);
					if (io->write_proc(&pixel, sizeof(WORD), 1, handle) != 1)
						return FALSE;
				}
			}
		} else if (bpp == 24) {
			FILE_BGR bgr;
			for(int y = 0; y < FreeImage_GetHeight(dib); y++) {
				BYTE *line = FreeImage_GetScanLine(dib, y);
				for(int x = 0; x < FreeImage_GetWidth(dib); x++) {
					RGBTRIPLE *triple = ((RGBTRIPLE *)line)+x;
					bgr.b = triple->rgbtBlue;
					bgr.g = triple->rgbtGreen;
					bgr.r = triple->rgbtRed;
					if (io->write_proc(&bgr, sizeof(FILE_BGR), 1, handle) != 1)
						return FALSE;
				}
			}
		} else if (bpp == 32) {
			FILE_BGRA bgra;
			for(int y = 0; y < FreeImage_GetHeight(dib); y++) {
				BYTE *line = FreeImage_GetScanLine(dib, y);
				for(int x = 0; x < FreeImage_GetWidth(dib); x++) {
					RGBQUAD *quad = ((RGBQUAD *)line)+x;
					bgra.b = quad->rgbBlue;
					bgra.g = quad->rgbGreen;
					bgra.r = quad->rgbRed;
					bgra.a = quad->rgbReserved;
					if (io->write_proc(&bgra, sizeof(FILE_BGRA), 1, handle) != 1)
						return FALSE;
				}
			}
#endif
		} else if (io->write_proc(FreeImage_GetBits(dib), FreeImage_GetHeight(dib) * FreeImage_GetPitch(dib), 1, handle) != 1) {
			return FALSE;
		}

		return TRUE;
	} else {
		return FALSE;
	}
}
Пример #9
0
FIBITMAP * DLL_CALLCONV
FreeImage_Clone(FIBITMAP *dib) {
	if(!dib) return NULL;

	unsigned width  = FreeImage_GetWidth(dib);
	unsigned height = FreeImage_GetHeight(dib);
	unsigned bpp    = FreeImage_GetBPP(dib);
	
	// allocate a new dib
	FIBITMAP *new_dib = FreeImage_AllocateT(FreeImage_GetImageType(dib), width, height, bpp, 
			FreeImage_GetRedMask(dib), FreeImage_GetGreenMask(dib), FreeImage_GetBlueMask(dib));

	if (new_dib) {
		// save ICC profile links
		FIICCPROFILE *src_iccProfile = FreeImage_GetICCProfile(dib);
		FIICCPROFILE *dst_iccProfile = FreeImage_GetICCProfile(new_dib);

		// save metadata links
		METADATAMAP *src_metadata = ((FREEIMAGEHEADER *)dib->data)->metadata;
		METADATAMAP *dst_metadata = ((FREEIMAGEHEADER *)new_dib->data)->metadata;

		// calculate the size of a FreeImage image
		// align the palette and the pixels on a FIBITMAP_ALIGNMENT bytes alignment boundary
		// palette is aligned on a 16 bytes boundary
		// pixels are aligned on a 16 bytes boundary

		unsigned dib_size = FreeImage_GetImageSize(width, height, bpp); 

		// copy the bitmap + internal pointers (remember to restore new_dib internal pointers later)
		memcpy(new_dib->data, dib->data, dib_size);

		// reset ICC profile link for new_dib
		memset(dst_iccProfile, 0, sizeof(FIICCPROFILE));

		// restore metadata link for new_dib
		((FREEIMAGEHEADER *)new_dib->data)->metadata = dst_metadata;

		// copy possible ICC profile
		FreeImage_CreateICCProfile(new_dib, src_iccProfile->data, src_iccProfile->size);
		dst_iccProfile->flags = src_iccProfile->flags;

		// copy metadata models
		for(METADATAMAP::iterator i = (*src_metadata).begin(); i != (*src_metadata).end(); i++) {
			int model = (*i).first;
			TAGMAP *src_tagmap = (*i).second;

			if(src_tagmap) {
				// create a metadata model
				TAGMAP *dst_tagmap = new TAGMAP();

				// fill the model
				for(TAGMAP::iterator j = src_tagmap->begin(); j != src_tagmap->end(); j++) {
					std::string dst_key = (*j).first;
					FITAG *dst_tag = FreeImage_CloneTag( (*j).second );

					// assign key and tag value
					(*dst_tagmap)[dst_key] = dst_tag;
				}

				// assign model and tagmap
				(*dst_metadata)[model] = dst_tagmap;
			}
		}

		return new_dib;
	}

	return NULL;
}
/*
==================
Return OpenGL format and type depending on IndieLib defined quality and type
This methot converts source image as needed
==================
*/
void OpenGLTextureBuilder::getGLFormat(IND_Surface *pNewSurface, IND_Image* pImage,GLint *pGLInternalFormat, GLint *pGLFormat, GLint *pGLType) {
    
    assert(pNewSurface);
    assert(pImage);
    assert(pGLFormat);
    assert(pGLType);

    if (!pGLFormat || !pGLType || !pNewSurface || !pImage)
        return;

    //TODO: Review image loading to support luminance+alpha. Now only supports Luminance without alpha
	int colorFormat = pImage->getFormatInt();
	int bpp = pImage->getBpp();
	//Check image color format
	switch (colorFormat) {
		case IND_LUMINANCE:
			//TODO: Other bpp
			*pGLInternalFormat = GL_LUMINANCE;
			*pGLFormat = GL_LUMINANCE;
			if (8 == bpp) {
				//No alpha channel by default
            pNewSurface->_surface->_attributes._type = IND_OPAQUE;
				//GL type
				*pGLType = GL_UNSIGNED_BYTE;
			} else if (16 == bpp) {
				//No alpha channel by default
				pNewSurface->_surface->_attributes._type = IND_OPAQUE;
            //GL types
				*pGLType = GL_UNSIGNED_SHORT_5_6_5;
			} else {
				*pGLInternalFormat = GL_NONE;
				*pGLFormat = GL_NONE;
				*pGLType = GL_NONE;
				g_debug->header("Not supported format of image! texture not loaded" , DebugApi::LogHeaderWarning);
                }

			break;
		case (IND_RGB):
				*pGLInternalFormat = GL_RGB;

			if (16 == bpp) {
				FIBITMAP* fib = pImage->getFreeImageHandle();
                *pGLFormat = GL_RGB;
				//Check if 565 RGB
				if ((FreeImage_GetRedMask(fib) == FI16_565_RED_MASK) 
					&& (FreeImage_GetGreenMask(fib) == FI16_565_GREEN_MASK) 
					&& (FreeImage_GetBlueMask(fib) == FI16_565_BLUE_MASK)) {
                *pGLType = GL_UNSIGNED_SHORT_5_6_5;
				} else {
					*pGLInternalFormat = GL_NONE;
					*pGLFormat = GL_NONE;
					*pGLType = GL_NONE;
					g_debug->header("Not supported format of image! texture not loaded" , DebugApi::LogHeaderWarning);
            }
			} else if (32 == bpp) {
				//FreeImage loads channel order differently depending on processor endianess (24 and 32 bits).
#if FI_RGBA_BLUE > FI_RGBA_RED
                *pGLFormat = GL_RGB;  //Generally for MacOSX and Big Endian Linux / Unix
#else
				*pGLFormat = GL_BGR;  //Generally for Windows and Linux (little Endian)
#endif
                *pGLType = GL_UNSIGNED_BYTE;
			} else {
				*pGLInternalFormat = GL_NONE;
				*pGLFormat = GL_NONE;
				*pGLType = GL_NONE;
				g_debug->header("Not supported format of image! texture not loaded" , DebugApi::LogHeaderWarning);
                }
			break;
		case (IND_RGBA): 
			if (16 == bpp) {
				*pGLInternalFormat = GL_RGBA;
                *pGLFormat = GL_RGBA; 
                *pGLType = GL_UNSIGNED_SHORT_4_4_4_4;
			} else if (32 == bpp) {
				*pGLInternalFormat = GL_RGBA;
				//FreeImage loads channel order differently depending on processor endianess (24 and 32 bits).
#if FI_RGBA_BLUE > FI_RGBA_RED
                *pGLFormat = GL_RGBA;  //Generally for MacOSX and Big Endian Linux / Unix
#else
				*pGLFormat = GL_BGRA;  //Generally for Windows and Linux (little Endian)
#endif
                *pGLType = GL_UNSIGNED_BYTE;
			} else {
				*pGLInternalFormat = GL_NONE;
				*pGLFormat = GL_NONE;
				*pGLType = GL_NONE;
				g_debug->header("Not supported format of image! texture not loaded" , DebugApi::LogHeaderWarning);
            }

            break;
		case (IND_COLOUR_INDEX):
		default:
			*pGLInternalFormat = GL_NONE;
            *pGLFormat = GL_NONE;
			*pGLType = GL_NONE;
            g_debug->header("Not supported format of image! texture not loaded" , DebugApi::LogHeaderWarning);
            break;
    }        
}
Пример #11
0
FIBITMAP * DLL_CALLCONV
FreeImage_Clone(FIBITMAP *dib) {
	if(!dib) {
		return NULL;
	}

	FREE_IMAGE_TYPE type = FreeImage_GetImageType(dib);
	unsigned width	= FreeImage_GetWidth(dib);
	unsigned height	= FreeImage_GetHeight(dib);
	unsigned bpp	= FreeImage_GetBPP(dib);

	const BYTE *ext_bits = ((FREEIMAGEHEADER *)dib->data)->external_bits;
	
	// check for pixel availability ...
	BOOL header_only = FreeImage_HasPixels(dib) ? FALSE : TRUE;

	// check whether this image has masks defined ...
	BOOL need_masks = (bpp == 16 && type == FIT_BITMAP) ? TRUE : FALSE;

	// allocate a new dib
	FIBITMAP *new_dib = FreeImage_AllocateHeaderT(header_only, type, width, height, bpp,
			FreeImage_GetRedMask(dib), FreeImage_GetGreenMask(dib), FreeImage_GetBlueMask(dib));

	if (new_dib) {
		// save ICC profile links
		FIICCPROFILE *src_iccProfile = FreeImage_GetICCProfile(dib);
		FIICCPROFILE *dst_iccProfile = FreeImage_GetICCProfile(new_dib);

		// save metadata links
		METADATAMAP *src_metadata = ((FREEIMAGEHEADER *)dib->data)->metadata;
		METADATAMAP *dst_metadata = ((FREEIMAGEHEADER *)new_dib->data)->metadata;

		// calculate the size of the src image
		// align the palette and the pixels on a FIBITMAP_ALIGNMENT bytes alignment boundary
		// palette is aligned on a 16 bytes boundary
		// pixels are aligned on a 16 bytes boundary
		
		// when using a user provided pixel buffer, force a 'header only' calculation		

		size_t dib_size = FreeImage_GetInternalImageSize(header_only || ext_bits, width, height, bpp, need_masks);

		// copy the bitmap + internal pointers (remember to restore new_dib internal pointers later)
		memcpy(new_dib->data, dib->data, dib_size);

		// reset ICC profile link for new_dib
		memset(dst_iccProfile, 0, sizeof(FIICCPROFILE));

		// restore metadata link for new_dib
		((FREEIMAGEHEADER *)new_dib->data)->metadata = dst_metadata;

		// reset thumbnail link for new_dib
		((FREEIMAGEHEADER *)new_dib->data)->thumbnail = NULL;

		// copy possible ICC profile
		FreeImage_CreateICCProfile(new_dib, src_iccProfile->data, src_iccProfile->size);
		dst_iccProfile->flags = src_iccProfile->flags;

		// copy metadata models
		for(METADATAMAP::iterator i = (*src_metadata).begin(); i != (*src_metadata).end(); i++) {
			int model = (*i).first;
			TAGMAP *src_tagmap = (*i).second;

			if(src_tagmap) {
				// create a metadata model
				TAGMAP *dst_tagmap = new(std::nothrow) TAGMAP();

				if(dst_tagmap) {
					// fill the model
					for(TAGMAP::iterator j = src_tagmap->begin(); j != src_tagmap->end(); j++) {
						std::string dst_key = (*j).first;
						FITAG *dst_tag = FreeImage_CloneTag( (*j).second );

						// assign key and tag value
						(*dst_tagmap)[dst_key] = dst_tag;
					}

					// assign model and tagmap
					(*dst_metadata)[model] = dst_tagmap;
				}
			}
		}

		// copy the thumbnail
		FreeImage_SetThumbnail(new_dib, FreeImage_GetThumbnail(dib));

		// copy user provided pixel buffer (if any)
		if(ext_bits) {
			const unsigned pitch = FreeImage_GetPitch(dib);
			const unsigned linesize = FreeImage_GetLine(dib);
			for(unsigned y = 0; y < height; y++) {
				memcpy(FreeImage_GetScanLine(new_dib, y), ext_bits, linesize);
				ext_bits += pitch;
			}
		}

		return new_dib;
	}

	return NULL;
}
Пример #12
0
FIBITMAP* CResizeEngine::scale(FIBITMAP *src, unsigned dst_width, unsigned dst_height) { 
	DWORD src_width  = FreeImage_GetWidth(src); 
	DWORD src_height = FreeImage_GetHeight(src);

	unsigned redMask	= FreeImage_GetRedMask(src);
	unsigned greenMask	= FreeImage_GetGreenMask(src);
	unsigned blueMask	= FreeImage_GetBlueMask(src);

	unsigned bpp = FreeImage_GetBPP(src);

	FREE_IMAGE_TYPE image_type = FreeImage_GetImageType(src);

	// allocate the dst image
	FIBITMAP *dst = FreeImage_AllocateT(image_type, dst_width, dst_height, bpp, redMask, greenMask, blueMask);
	if(!dst) return NULL;
	
	if(bpp == 8) {
		if(FreeImage_GetColorType(src) == FIC_MINISWHITE) {
			// build an inverted greyscale palette
			RGBQUAD *dst_pal = FreeImage_GetPalette(dst);
			for(int i = 0; i < 256; i++) {
				dst_pal[i].rgbRed = dst_pal[i].rgbGreen =
					dst_pal[i].rgbBlue = (BYTE)(255 - i);
			}
		} else {
			// build a greyscale palette
			RGBQUAD *dst_pal = FreeImage_GetPalette(dst);
			for(int i = 0; i < 256; i++) {
				dst_pal[i].rgbRed = dst_pal[i].rgbGreen =
					dst_pal[i].rgbBlue = (BYTE)i;
			}
		}
	}

	// decide which filtering order (xy or yx) is faster for this mapping by
	// counting convolution multiplies

	if(dst_width*src_height <= dst_height*src_width) {
		// xy filtering
		// -------------

		// allocate a temporary image
		FIBITMAP *tmp = FreeImage_AllocateT(image_type, dst_width, src_height, bpp, redMask, greenMask, blueMask);
		if(!tmp) {
			FreeImage_Unload(dst);
			return NULL;
		}

		// scale source image horizontally into temporary image
		horizontalFilter(src, src_width, src_height, tmp, dst_width, src_height);

		// scale temporary image vertically into result image    
		verticalFilter(tmp, dst_width, src_height, dst, dst_width, dst_height);

		// free temporary image
		FreeImage_Unload(tmp);

	} else {
		// yx filtering
		// -------------

		// allocate a temporary image
		FIBITMAP *tmp = FreeImage_AllocateT(image_type, src_width, dst_height, bpp, redMask, greenMask, blueMask);
		if(!tmp) {
			FreeImage_Unload(dst);
			return NULL;
		}

		// scale source image vertically into temporary image
		verticalFilter(src, src_width, src_height, tmp, src_width, dst_height);

		// scale temporary image horizontally into result image    
		horizontalFilter(tmp, src_width, dst_height, dst, dst_width, dst_height);

		// free temporary image
		FreeImage_Unload(tmp);
	}

	return dst;
} 
Пример #13
0
/**
Scan input dib format and return the equivalent PKPixelFormatGUID format for saving
@param dib Image to be saved
@param guid_format (returned value) GUID format
@param bHasAlpha (returned value) TRUE if an alpha layer is present
@return Returns TRUE if successful, returns FALSE otherwise
*/
static ERR
GetOutputPixelFormat(FIBITMAP *dib, PKPixelFormatGUID *guid_format, BOOL *bHasAlpha) {
	const FREE_IMAGE_TYPE image_type = FreeImage_GetImageType(dib);
	const unsigned bpp = FreeImage_GetBPP(dib);
	const FREE_IMAGE_COLOR_TYPE color_type = FreeImage_GetColorType(dib);

	*guid_format = GUID_PKPixelFormatDontCare;
	*bHasAlpha = FALSE;

	switch(image_type) {
		case FIT_BITMAP:	// standard image	: 1-, 4-, 8-, 16-, 24-, 32-bit
			switch(bpp) {
				case 1:
					// assume FIC_MINISBLACK
					if(color_type == FIC_MINISBLACK) {
						*guid_format = GUID_PKPixelFormatBlackWhite;
					}
					break;
				case 8:
					// assume FIC_MINISBLACK
					if(color_type == FIC_MINISBLACK) {
						*guid_format = GUID_PKPixelFormat8bppGray;
					}
					break;
				case 16:
					if ((FreeImage_GetRedMask(dib) == FI16_565_RED_MASK) && (FreeImage_GetGreenMask(dib) == FI16_565_GREEN_MASK) && (FreeImage_GetBlueMask(dib) == FI16_565_BLUE_MASK)) {
						*guid_format = GUID_PKPixelFormat16bppRGB565;
					} else {
						// includes case where all the masks are 0
						*guid_format = GUID_PKPixelFormat16bppRGB555;
					}
					break;
#if FREEIMAGE_COLORORDER == FREEIMAGE_COLORORDER_BGR
				case 24:
					*guid_format = GUID_PKPixelFormat24bppBGR;
					break;
				case 32:
					*guid_format = GUID_PKPixelFormat32bppBGRA;
					*bHasAlpha = TRUE;
					break;
#elif FREEIMAGE_COLORORDER == FREEIMAGE_COLORORDER_RGB
				case 24:
					*guid_format = GUID_PKPixelFormat24bppRGB;
					break;
				case 32:
					*guid_format = GUID_PKPixelFormat32bppRGBA;
					*bHasAlpha = TRUE;
					break;
#endif
				case 4:
				default:
					// not supported
					break;
			}
			break;
		case FIT_UINT16:	// array of unsigned short	: unsigned 16-bit
			*guid_format = GUID_PKPixelFormat16bppGray;
			break;
		case FIT_FLOAT:		// array of float			: 32-bit IEEE floating point
			*guid_format = GUID_PKPixelFormat32bppGrayFloat;
			break;
		case FIT_RGB16:		// 48-bit RGB image			: 3 x 16-bit
			*guid_format = GUID_PKPixelFormat48bppRGB;
			break;
		case FIT_RGBA16:	// 64-bit RGBA image		: 4 x 16-bit
			*guid_format = GUID_PKPixelFormat64bppRGBA;
			*bHasAlpha = TRUE;
			break;
		case FIT_RGBF:		// 96-bit RGB float image	: 3 x 32-bit IEEE floating point
			*guid_format = GUID_PKPixelFormat96bppRGBFloat;
			break;
		case FIT_RGBAF:		// 128-bit RGBA float image	: 4 x 32-bit IEEE floating point
			*guid_format = GUID_PKPixelFormat128bppRGBAFloat;
			*bHasAlpha = TRUE;
			break;

		case FIT_INT16:		// array of short			: signed 16-bit
		case FIT_UINT32:	// array of unsigned long	: unsigned 32-bit
		case FIT_INT32:		// array of long			: signed 32-bit
		case FIT_DOUBLE:	// array of double			: 64-bit IEEE floating point
		case FIT_COMPLEX:	// array of FICOMPLEX		: 2 x 64-bit IEEE floating point

		default:
			// unsupported format
			break;
	}

	return (*guid_format != GUID_PKPixelFormatDontCare) ? WMP_errSuccess : WMP_errUnsupportedFormat;
}