Alien-FreeImage

 view release on metacpan or  search on metacpan

src/Source/FreeImage/PluginDDS.cpp  view on Meta::CPAN

// ==========================================================
// Plugin Interface
// ==========================================================

static int s_format_id;

// ==========================================================
// Internal functions
// ==========================================================

static FIBITMAP *
LoadRGB (DDSURFACEDESC2 &desc, FreeImageIO *io, fi_handle handle, int page, int flags, void *data) {
	int width = (int)desc.dwWidth & ~3;
	int height = (int)desc.dwHeight & ~3;
	int bpp = (int)desc.ddpfPixelFormat.dwRGBBitCount;
	
	// allocate a new dib
	FIBITMAP *dib = FreeImage_Allocate (width, height, bpp, desc.ddpfPixelFormat.dwRBitMask,
		desc.ddpfPixelFormat.dwGBitMask, desc.ddpfPixelFormat.dwBBitMask);
	if (dib == NULL)
		return NULL;

#if FREEIMAGE_COLORORDER == FREEIMAGE_COLORORDER_RGB
		// Calculate the number of bytes per pixel (3 for 24-bit or 4 for 32-bit)
		int bytespp = FreeImage_GetLine(dib) / FreeImage_GetWidth(dib);
#endif
	
	// read the file
	int line   = CalculateLine(width, bpp);
	int filePitch = (desc.dwFlags & DDSD_PITCH) ? (int)desc.dwPitchOrLinearSize : line;
	long delta = (long)filePitch - (long)line;
	for (int i = 0; i < height; i++) {
		BYTE *pixels = FreeImage_GetScanLine(dib, height - i - 1);
		io->read_proc (pixels, 1, line, handle);
		io->seek_proc (handle, delta, SEEK_CUR);
#if FREEIMAGE_COLORORDER == FREEIMAGE_COLORORDER_RGB
 		for(int x = 0; x < width; x++) {
			INPLACESWAP(pixels[FI_RGBA_RED],pixels[FI_RGBA_BLUE]);
			pixels += bytespp;
		}
#endif
	}
	
	// enable transparency
	FreeImage_SetTransparent (dib, (desc.ddpfPixelFormat.dwFlags & DDPF_ALPHAPIXELS) ? TRUE : FALSE);

	if (!(desc.ddpfPixelFormat.dwFlags & DDPF_ALPHAPIXELS) && bpp == 32) {
		// no transparency: convert to 24-bit
		FIBITMAP *old = dib;
		dib = FreeImage_ConvertTo24Bits (old);
		FreeImage_Unload (old);
	}
	return dib;
}

template <class DECODER> static void 
LoadDXT_Helper (FreeImageIO *io, fi_handle handle, int page, int flags, void *data, FIBITMAP *dib, int width, int height, int line) {
	typedef typename DECODER::INFO INFO;
	typedef typename INFO::Block Block;

	Block *input_buffer = new(std::nothrow) Block[(width + 3) / 4];
	if(!input_buffer) return;

	int widthRest = (int) width & 3;
	int heightRest = (int) height & 3;
	int inputLine = (width + 3) / 4;
	int y = 0;

	if (height >= 4) {
		for (; y < height; y += 4) {
			io->read_proc (input_buffer, sizeof (typename INFO::Block), inputLine, handle);
			// TODO: probably need some endian work here
			BYTE *pbSrc = (BYTE *)input_buffer;
			BYTE *pbDst = FreeImage_GetScanLine (dib, height - y - 1);

			if (width >= 4) {
				for (int x = 0; x < width; x += 4) {
					DecodeDXTBlock <DECODER> (pbDst, pbSrc,	line, 4, 4);
					pbSrc += INFO::bytesPerBlock;
					pbDst += 4 * 4;
				}
			}
			if (widthRest) {
				DecodeDXTBlock <DECODER> (pbDst, pbSrc, line, widthRest, 4);
			}
		}
	}
	if (heightRest)	{
		io->read_proc (input_buffer, sizeof (typename INFO::Block), inputLine, handle);
		// TODO: probably need some endian work here
		BYTE *pbSrc = (BYTE *)input_buffer;
		BYTE *pbDst = FreeImage_GetScanLine (dib, height - y - 1);

		if (width >= 4) {
			for (int x = 0; x < width; x += 4) {
				DecodeDXTBlock <DECODER> (pbDst, pbSrc,	line, 4, heightRest);
				pbSrc += INFO::bytesPerBlock;
				pbDst += 4 * 4;
			}
		}
		if (widthRest) {
			DecodeDXTBlock <DECODER> (pbDst, pbSrc,	line, widthRest, heightRest);
		}

	}

	delete [] input_buffer;
}

static FIBITMAP *
LoadDXT (int type, DDSURFACEDESC2 &desc, FreeImageIO *io, fi_handle handle, int page, int flags, void *data) {
	int width = (int)desc.dwWidth & ~3;
	int height = (int)desc.dwHeight & ~3;

	// allocate a 32-bit dib
	FIBITMAP *dib = FreeImage_Allocate (width, height, 32, FI_RGBA_RED_MASK, FI_RGBA_GREEN_MASK, FI_RGBA_BLUE_MASK);
	if (dib == NULL)
		return NULL;

	int bpp = FreeImage_GetBPP (dib);
	int line = CalculateLine (width, bpp);



( run in 0.575 second using v1.01-cache-2.11-cpan-cdf2f3d4e48 )