Example #1
0
/*
	Halflite Texture WAD
*/
IImage* CImageLoaderWAL2::loadImage(irr::io::IReadFile* file) const
{
	miptex_halflife header;

	file->seek(0);
	file->read(&header, sizeof(header));

#ifdef __BIG_ENDIAN__
	header.width = os::Byteswap::byteswap(header.width);
	header.height = os::Byteswap::byteswap(header.height);
#endif

	// palette
	//u32 paletteofs = header.mipmap[0] + ((rawtexsize * 85) >> 6) + 2;
	u32 *pal = new u32 [ 192 + 256 ];
	u8 *s = (u8*) pal;

	file->seek ( file->getSize() - 768 - 2 );
	file->read ( s, 768 );
	u32 i;

	for ( i = 0; i < 256; ++i, s+= 3 )
	{
		pal [ 192 + i ] = 0xFF000000 | s[0] << 16 | s[1] << 8 | s[2];
	}

	ECOLOR_FORMAT format = ECF_R8G8B8;

	// transparency in filename;-) funny. rgb:0x0000FF is colorkey
	if ( file->getFileName().findFirst ( '{' ) >= 0 )
	{
		format = ECF_A8R8G8B8;
		pal [ 192 + 255 ] &= 0x00FFFFFF;
	}

	u32 rawtexsize = header.width * header.height;


	u8 *rawtex = new u8 [ rawtexsize ];

	file->seek ( header.mipmap[0] );
	file->read(rawtex, rawtexsize);

	IImage* image = new CImage(format, core::dimension2d<u32>(header.width, header.height));

	switch ( format )
	{
	case ECF_R8G8B8:
		CColorConverter::convert8BitTo24Bit(rawtex, (u8*)image->getData(), header.width, header.height, (u8*) pal + 768, 0, false);
		break;
	case ECF_A8R8G8B8:
		CColorConverter::convert8BitTo32Bit(rawtex, (u8*)image->getData(), header.width, header.height, (u8*) pal + 768, 0, false);
		break;
	}

	delete [] rawtex;
	delete [] pal;

	return image;
}
Example #2
0
/*!
	quake2
*/
IImage* CImageLoaderWAL::loadImage(irr::io::IReadFile* file) const
{
	miptex_quake2 header;

	file->seek(0);
	file->read(&header, sizeof(header));

#ifdef __BIG_ENDIAN__
	header.width = os::Byteswap::byteswap(header.width);
	header.height = os::Byteswap::byteswap(header.height);
#endif

	u32 rawtexsize = header.width * header.height;

	u8 *rawtex = new u8 [ rawtexsize ];

	file->seek ( header.mipmap[0] );
	file->read(rawtex, rawtexsize);

	IImage* image = new CImage(ECF_A8R8G8B8, core::dimension2d<u32>(header.width, header.height));

	CColorConverter::convert8BitTo32Bit(rawtex, (u8*)image->getData(), header.width, header.height, (u8*) colormap_pcx, 0, false);

	delete [] rawtex;

	return image;
}
Example #3
0
/*!
	Quake1, Quake2, Hallife lmp texture
*/
IImage* CImageLoaderLMP::loadImage(irr::io::IReadFile* file) const
{
	SLMPHeader header;

	file->seek(0);
	file->read(&header, sizeof(header));

	// maybe palette file
	u32 rawtexsize = header.width * header.height;
	if ( rawtexsize + sizeof ( header ) != (u32)file->getSize() )
		return 0;

	u8 *rawtex = new u8 [ rawtexsize ];

	file->read(rawtex, rawtexsize);

	IImage* image = new CImage(ECF_A8R8G8B8, core::dimension2d<u32>(header.width, header.height));

	CColorConverter::convert8BitTo32Bit(rawtex, (u8*)image->getData(), header.width, header.height, (u8*) colormap_h, 0, false);

	delete [] rawtex;

	return image;
}
//! creates a surface from the file
IImage* CImageLoaderTGA::loadImage(io::IReadFile* file) const
{
	STGAHeader header;
	u32 *palette = 0;

	file->read(&header, sizeof(STGAHeader));

#ifdef __BIG_ENDIAN__
	header.ColorMapLength = os::Byteswap::byteswap(header.ColorMapLength);
	header.ImageWidth = os::Byteswap::byteswap(header.ImageWidth);
	header.ImageHeight = os::Byteswap::byteswap(header.ImageHeight);
#endif

	// skip image identification field
	if (header.IdLength)
		file->seek(header.IdLength, true);

	if (header.ColorMapType)
	{
		// create 32 bit palette
		palette = new u32[ header.ColorMapLength];

		// read color map
		u8 * colorMap = new u8[header.ColorMapEntrySize/8 * header.ColorMapLength];
		file->read(colorMap,header.ColorMapEntrySize/8 * header.ColorMapLength);

		// convert to 32-bit palette
		switch ( header.ColorMapEntrySize )
		{
			case 16:
				CColorConverter::convert_A1R5G5B5toA8R8G8B8(colorMap, header.ColorMapLength, palette);
				break;
			case 24:
				CColorConverter::convert_B8G8R8toA8R8G8B8(colorMap, header.ColorMapLength, palette);
				break;
			case 32:
				CColorConverter::convert_B8G8R8A8toA8R8G8B8(colorMap, header.ColorMapLength, palette);
				break;
		}
		delete [] colorMap;
	}

	// read image

	u8* data = 0;

	if (	header.ImageType == 1 || // Uncompressed, color-mapped images.
			header.ImageType == 2 || // Uncompressed, RGB images
			header.ImageType == 3 // Uncompressed, black and white images
		)
	{
		const s32 imageSize = header.ImageHeight * header.ImageWidth * header.PixelDepth/8;
		data = new u8[imageSize];
	  	file->read(data, imageSize);
	}
	else
	if(header.ImageType == 10)
	{
		// Runlength encoded RGB images
		data = loadCompressedImage(file, header);
	}
	else
	{
		os::Printer::log("Unsupported TGA file type", file->getFileName(), ELL_ERROR);
		delete [] palette;
		return 0;
	}

	IImage* image = 0;

	switch(header.PixelDepth)
	{
	case 8:
		{
			if (header.ImageType==3) // grey image
			{
				image = new CImage(ECF_R8G8B8,
					core::dimension2d<u32>(header.ImageWidth, header.ImageHeight));
				if (image)
					CColorConverter::convert8BitTo24Bit((u8*)data,
						(u8*)image->getData(),
						header.ImageWidth,header.ImageHeight,
						0, 0, (header.ImageDescriptor&0x20)==0);
			}
			else
			{
				image = new CImage(ECF_A1R5G5B5,
					core::dimension2d<u32>(header.ImageWidth, header.ImageHeight));
				if (image)
					CColorConverter::convert8BitTo16Bit((u8*)data,
						(s16*)image->getData(),
						header.ImageWidth,header.ImageHeight,
						(s32*) palette, 0,
						(header.ImageDescriptor&0x20)==0);
			}
		}
		break;
	case 16:
		image = new CImage(ECF_A1R5G5B5,
			core::dimension2d<u32>(header.ImageWidth, header.ImageHeight));
		if (image)
			CColorConverter::convert16BitTo16Bit((s16*)data,
				(s16*)image->getData(), header.ImageWidth,	header.ImageHeight, 0, (header.ImageDescriptor&0x20)==0);
		break;
	case 24:
			image = new CImage(ECF_R8G8B8,
				core::dimension2d<u32>(header.ImageWidth, header.ImageHeight));
			if (image)
				CColorConverter::convert24BitTo24Bit(
					(u8*)data, (u8*)image->getData(), header.ImageWidth, header.ImageHeight, 0, (header.ImageDescriptor&0x20)==0, true);
		break;
	case 32:
			image = new CImage(ECF_A8R8G8B8,
				core::dimension2d<u32>(header.ImageWidth, header.ImageHeight));
			if (image)
				CColorConverter::convert32BitTo32Bit((s32*)data,
					(s32*)image->getData(), header.ImageWidth, header.ImageHeight, 0, (header.ImageDescriptor&0x20)==0);
		break;
	default:
		os::Printer::log("Unsupported TGA format", file->getFileName(), ELL_ERROR);
		break;
	}

	delete [] data;
	delete [] palette;

	return image;
}
Example #5
0
//! creates a surface from the file
IImage* CImageLoaderPPM::loadImage(io::IReadFile* file) const
{
	IImage* image;

	if (file->getSize() < 12)
		return 0;

	c8 id[2];
	file->read(&id, 2);

	if (id[0]!='P' || id[1]<'1' || id[1]>'6')
		return 0;

	const u8 format = id[1] - '0';
	const bool binary = format>3;

	core::stringc token;
	getNextToken(file, token);
	const u32 width = core::strtoul10(token.c_str());

	getNextToken(file, token);
	const u32 height = core::strtoul10(token.c_str());

	u8* data = 0;
	const u32 size = width*height;
	if (format==1 || format==4)
	{
		skipToNextToken(file); // go to start of data

		const u32 bytesize = size/8+(size & 3)?1:0;
		if (binary)
		{
			if (file->getSize()-file->getPos() < (long)bytesize)
				return 0;
			data = new u8[bytesize];
			file->read(data, bytesize);
		}
		else
		{
			if (file->getSize()-file->getPos() < (long)(2*size)) // optimistic test
				return 0;
			data = new u8[bytesize];
			memset(data, 0, bytesize);
			u32 shift=0;
			for (u32 i=0; i<size; ++i)
			{
				getNextToken(file, token);
				if (token == "1")
					data[i/8] |= (0x01 << shift);
				if (++shift == 8)
					shift=0;
			}
		}
		image = new CImage(ECF_A1R5G5B5, core::dimension2d<u32>(width, height));
		if (image)
			CColorConverter::convert1BitTo16Bit(data, (s16*)image->getData(), width, height);
	}
	else
	{
		getNextToken(file, token);
		const u32 maxDepth = core::strtoul10(token.c_str());
		if (maxDepth > 255) // no double bytes yet
			return 0;

		skipToNextToken(file); // go to start of data

		if (format==2 || format==5)
		{
			if (binary)
			{
				if (file->getSize()-file->getPos() < (long)size)
					return 0;
				data = new u8[size];
				file->read(data, size);
				image = new CImage(ECF_A8R8G8B8, core::dimension2d<u32>(width, height));
				if (image)
				{
					u8* ptr = (u8*)image->getData();
					for (u32 i=0; i<size; ++i)
					{
						*ptr++ = data[i];
						*ptr++ = data[i];
						*ptr++ = data[i];
						*ptr++ = 255;
					}
				}
			}
			else
			{
				if (file->getSize()-file->getPos() < (long)(2*size)) // optimistic test
					return 0;
				image = new CImage(ECF_A8R8G8B8, core::dimension2d<u32>(width, height));
				if (image)
				{
					u8* ptr = (u8*)image->getData();
					for (u32 i=0; i<size; ++i)
					{
						getNextToken(file, token);
						const u8 num = (u8)core::strtoul10(token.c_str());
						*ptr++ = num;
						*ptr++ = num;
						*ptr++ = num;
						*ptr++ = 255;
					}
				}
			}
		}
		else
		{
			const u32 bytesize = 3*size;
			if (binary)
			{
				if (file->getSize()-file->getPos() < (long)bytesize)
					return 0;
				data = new u8[bytesize];
				file->read(data, bytesize);
				image = new CImage(ECF_A8R8G8B8, core::dimension2d<u32>(width, height));
				if (image)
				{
					u8* ptr = (u8*)image->getData();
					for (u32 i=0; i<size; ++i)
					{
						*ptr++ = data[3*i];
						*ptr++ = data[3*i+1];
						*ptr++ = data[3*i+2];
						*ptr++ = 255;
					}
				}
			}
			else
			{
				if (file->getSize()-file->getPos() < (long)(2*bytesize)) // optimistic test
					return 0;
				image = new CImage(ECF_A8R8G8B8, core::dimension2d<u32>(width, height));
				if (image)
				{
					u8* ptr = (u8*)image->getData();
					for (u32 i=0; i<size; ++i)
					{
						getNextToken(file, token);
						*ptr++ = (u8)core::strtoul10(token.c_str());
						getNextToken(file, token);
						*ptr++ = (u8)core::strtoul10(token.c_str());
						getNextToken(file, token);
						*ptr++ = (u8)core::strtoul10(token.c_str());
						*ptr++ = 255;
					}
				}
			}
		}
	}

	delete [] data;

	return image;
}
Example #6
0
//! creates a surface from the file
IImage* CImageLoaderJPG::loadImage(io::IReadFile* file) const
{
	#ifndef _IRR_COMPILE_WITH_LIBJPEG_
	os::Printer::log("Can't load as not compiled with _IRR_COMPILE_WITH_LIBJPEG_:", file->getFileName(), ELL_DEBUG);
	return 0;
	#else

	if (!file)
		return 0;

	Filename = file->getFileName();

	u8 **rowPtr=0;
	u8* input = new u8[file->getSize()];
	file->read(input, file->getSize());

	// allocate and initialize JPEG decompression object
	struct jpeg_decompress_struct cinfo;
	struct irr_jpeg_error_mgr jerr;

	//We have to set up the error handler first, in case the initialization
	//step fails.  (Unlikely, but it could happen if you are out of memory.)
	//This routine fills in the contents of struct jerr, and returns jerr's
	//address which we place into the link field in cinfo.

	cinfo.err = jpeg_std_error(&jerr.pub);
	cinfo.err->error_exit = error_exit;
	cinfo.err->output_message = output_message;

	// compatibility fudge:
	// we need to use setjmp/longjmp for error handling as gcc-linux
	// crashes when throwing within external c code
	if (setjmp(jerr.setjmp_buffer))
	{
		// If we get here, the JPEG code has signaled an error.
		// We need to clean up the JPEG object and return.

		jpeg_destroy_decompress(&cinfo);

		delete [] input;
		delete [] rowPtr;

		// return null pointer
		return 0;
	}

	// Now we can initialize the JPEG decompression object.
	jpeg_create_decompress(&cinfo);

	// specify data source
	jpeg_source_mgr jsrc;

	// Set up data pointer
	jsrc.bytes_in_buffer = file->getSize();
	jsrc.next_input_byte = (JOCTET*)input;
	cinfo.src = &jsrc;

	jsrc.init_source = init_source;
	jsrc.fill_input_buffer = fill_input_buffer;
	jsrc.skip_input_data = skip_input_data;
	jsrc.resync_to_restart = jpeg_resync_to_restart;
	jsrc.term_source = term_source;

	// Decodes JPG input from whatever source
	// Does everything AFTER jpeg_create_decompress
	// and BEFORE jpeg_destroy_decompress
	// Caller is responsible for arranging these + setting up cinfo

	// read file parameters with jpeg_read_header()
	jpeg_read_header(&cinfo, TRUE);

	bool useCMYK=false;
	if (cinfo.jpeg_color_space==JCS_CMYK)
	{
		cinfo.out_color_space=JCS_CMYK;
		cinfo.out_color_components=4;
		useCMYK=true;
	}
	else
	{
		cinfo.out_color_space=JCS_RGB;
		cinfo.out_color_components=3;
	}
	cinfo.output_gamma=2.2;
	cinfo.do_fancy_upsampling=FALSE;

	// Start decompressor
	jpeg_start_decompress(&cinfo);

	// Get image data
	u16 rowspan = cinfo.image_width * cinfo.out_color_components;
	u32 width = cinfo.image_width;
	u32 height = cinfo.image_height;

	// Allocate memory for buffer
	u8* output = new u8[rowspan * height];

	// Here we use the library's state variable cinfo.output_scanline as the
	// loop counter, so that we don't have to keep track ourselves.
	// Create array of row pointers for lib
	rowPtr = new u8* [height];

	for( u32 i = 0; i < height; i++ )
		rowPtr[i] = &output[ i * rowspan ];

	u32 rowsRead = 0;

	while( cinfo.output_scanline < cinfo.output_height )
		rowsRead += jpeg_read_scanlines( &cinfo, &rowPtr[rowsRead], cinfo.output_height - rowsRead );

	delete [] rowPtr;
	// Finish decompression

	jpeg_finish_decompress(&cinfo);

	// Release JPEG decompression object
	// This is an important step since it will release a good deal of memory.
	jpeg_destroy_decompress(&cinfo);

	// convert image
	IImage* image = 0;
	if (useCMYK)
	{
		image = new CImage(ECF_R8G8B8,
				core::dimension2d<u32>(width, height));
		const u32 size = 3*width*height;
		u8* data = (u8*)image->getData();
		if (data)
		{
			for (u32 i=0,j=0; i<size; i+=3, j+=4)
			{
				// Also works without K, but has more contrast with K multiplied in
//				data[i+0] = output[j+2];
//				data[i+1] = output[j+1];
//				data[i+2] = output[j+0];
				data[i+0] = (char)(output[j+2]*(output[j+3]/255.f));
				data[i+1] = (char)(output[j+1]*(output[j+3]/255.f));
				data[i+2] = (char)(output[j+0]*(output[j+3]/255.f));
			}
		}
		delete [] output;
	}
	else
		image = new CImage(ECF_R8G8B8,
				core::dimension2d<u32>(width, height), output);

	delete [] input;

	return image;

	#endif
}