コード例 #1
0
//==============================================================================
static ANKI_USE_RESULT Error loadUncompressedTga(
	File& fs, U32& width, U32& height, U32& bpp, DArray<U8>& data,
	GenericMemoryPoolAllocator<U8>& alloc)
{
	Array<U8, 6> header6;

	// read the info from header
	ANKI_CHECK(fs.read((char*)&header6[0], sizeof(header6)));

	width  = header6[1] * 256 + header6[0];
	height = header6[3] * 256 + header6[2];
	bpp = header6[4];

	if((width == 0) || (height == 0) || ((bpp != 24) && (bpp != 32)))
	{
		ANKI_LOGE("Invalid image information");
		return ErrorCode::USER_DATA;
	}

	// read the data
	I bytesPerPxl = (bpp / 8);
	I imageSize = bytesPerPxl * width * height;
	data.create(alloc, imageSize);

	ANKI_CHECK(fs.read(reinterpret_cast<char*>(&data[0]), imageSize));

	// swap red with blue
	for(I i = 0; i < imageSize; i += bytesPerPxl)
	{
		U32 temp = data[i];
		data[i] = data[i + 2];
		data[i + 2] = temp;
	}

	return ErrorCode::NONE;
}
コード例 #2
0
//==============================================================================
static ANKI_USE_RESULT Error loadCompressedTga(
	File& fs, U32& width, U32& height, U32& bpp, DArray<U8>& data,
	GenericMemoryPoolAllocator<U8>& alloc)
{
	Array<U8, 6> header6;
	ANKI_CHECK(fs.read(reinterpret_cast<char*>(&header6[0]), sizeof(header6)));

	width  = header6[1] * 256 + header6[0];
	height = header6[3] * 256 + header6[2];
	bpp	= header6[4];

	if((width <= 0) || (height <= 0) || ((bpp != 24) && (bpp != 32)))
	{
		ANKI_LOGE("Invalid texture information");
		return ErrorCode::USER_DATA;
	}

	I bytesPerPxl = (bpp / 8);
	I imageSize = bytesPerPxl * width * height;
	data.create(alloc, imageSize);

	U pixelcount = height * width;
	U currentpixel = 0;
	U currentbyte = 0;
	U8 colorbuffer[4];

	do
	{
		U8 chunkheader = 0;

		ANKI_CHECK(fs.read((char*)&chunkheader, sizeof(U8)));

		if(chunkheader < 128)
		{
			chunkheader++;
			for(int counter = 0; counter < chunkheader; counter++)
			{
				ANKI_CHECK(fs.read((char*)&colorbuffer[0], bytesPerPxl));

				data[currentbyte] = colorbuffer[2];
				data[currentbyte + 1] = colorbuffer[1];
				data[currentbyte + 2] = colorbuffer[0];

				if(bytesPerPxl == 4)
				{
					data[currentbyte + 3] = colorbuffer[3];
				}

				currentbyte += bytesPerPxl;
				currentpixel++;

				if(currentpixel > pixelcount)
				{
					ANKI_LOGE("Too many pixels read");
					return ErrorCode::USER_DATA;
				}
			}
		}
		else
		{
			chunkheader -= 127;
			ANKI_CHECK(fs.read((char*)&colorbuffer[0], bytesPerPxl));

			for(int counter = 0; counter < chunkheader; counter++)
			{
				data[currentbyte] = colorbuffer[2];
				data[currentbyte + 1] = colorbuffer[1];
				data[currentbyte + 2] = colorbuffer[0];

				if(bytesPerPxl == 4)
				{
					data[currentbyte + 3] = colorbuffer[3];
				}

				currentbyte += bytesPerPxl;
				currentpixel++;

				if(currentpixel > pixelcount)
				{
					ANKI_LOGE("Too many pixels read");
					data.destroy(alloc);
					return ErrorCode::USER_DATA;
				}
			}
		}
	} while(currentpixel < pixelcount);

	return ErrorCode::NONE;
}
コード例 #3
0
//==============================================================================
static ANKI_USE_RESULT Error loadAnkiTexture(
	const CString& filename, 
	U32 maxTextureSize,
	ImageLoader::DataCompression& preferredCompression,
	DArray<ImageLoader::Surface>& surfaces,
	GenericMemoryPoolAllocator<U8>& alloc,
	U8& depth, 
	U8& mipLevels, 
	ImageLoader::TextureType& textureType,
	ImageLoader::ColorFormat& colorFormat)
{
	File file;
	ANKI_CHECK(file.open(filename, 
		File::OpenFlag::READ | File::OpenFlag::BINARY 
		| File::OpenFlag::LITTLE_ENDIAN));

	//
	// Read and check the header
	//
	AnkiTextureHeader header;
	ANKI_CHECK(file.read(&header, sizeof(AnkiTextureHeader)));

	if(std::memcmp(&header.m_magic[0], "ANKITEX1", 8) != 0)
	{
		ANKI_LOGE("Wrong magic word");
		return ErrorCode::USER_DATA;
	}

	if(header.m_width == 0 
		|| !isPowerOfTwo(header.m_width) 
		|| header.m_width > 4096
		|| header.m_height == 0 
		|| !isPowerOfTwo(header.m_height) 
		|| header.m_height > 4096)
	{
		ANKI_LOGE("Incorrect width/height value");
		return ErrorCode::USER_DATA;
	}

	if(header.m_depth < 1 || header.m_depth > 16)
	{
		ANKI_LOGE("Zero or too big depth");
		return ErrorCode::USER_DATA;
	}

	if(header.m_type < ImageLoader::TextureType::_2D 
		|| header.m_type > ImageLoader::TextureType::_2D_ARRAY)
	{
		ANKI_LOGE("Incorrect header: texture type");
		return ErrorCode::USER_DATA;
	}

	if(header.m_colorFormat < ImageLoader::ColorFormat::RGB8 
		|| header.m_colorFormat > ImageLoader::ColorFormat::RGBA8)
	{
		ANKI_LOGE("Incorrect header: color format");
		return ErrorCode::USER_DATA;
	}

	if((header.m_compressionFormats & preferredCompression) 
		== ImageLoader::DataCompression::NONE)
	{
		ANKI_LOGI("File does not contain the requested compression");

		// Fallback
		preferredCompression = ImageLoader::DataCompression::RAW;

		if((header.m_compressionFormats & preferredCompression) 
			== ImageLoader::DataCompression::NONE)
		{
			ANKI_LOGI("File does not contain raw compression");
			return ErrorCode::USER_DATA;
		}
	}

	if(header.m_normal != 0 && header.m_normal != 1)
	{
		ANKI_LOGE("Incorrect header: normal");
		return ErrorCode::USER_DATA;
	}

	// Check mip levels
	U size = min(header.m_width, header.m_height);
	U maxsize = max(header.m_width, header.m_height);
	mipLevels = 0;
	U tmpMipLevels = 0;
	while(size >= 4) // The minimum size is 4x4
	{
		++tmpMipLevels;

		if(maxsize <= maxTextureSize)
		{
			++mipLevels;
		}

		size /= 2;
		maxsize /= 2;
	}

	if(header.m_mipLevels > tmpMipLevels)
	{
		ANKI_LOGE("Incorrect number of mip levels");
		return ErrorCode::USER_DATA;
	}

	mipLevels = min<U>(mipLevels, header.m_mipLevels);

	colorFormat = header.m_colorFormat;

	switch(header.m_type)
	{
	case ImageLoader::TextureType::_2D:
		depth = 1;
		break;
	case ImageLoader::TextureType::CUBE:
		depth = 6;
		break;
	case ImageLoader::TextureType::_3D:
	case ImageLoader::TextureType::_2D_ARRAY:
		depth = header.m_depth;
		break;
	default:
		ANKI_ASSERT(0);
	}

	textureType = header.m_type;

	//
	// Move file pointer
	//

	if(preferredCompression == ImageLoader::DataCompression::RAW)
	{
		// Do nothing
	}
	else if(preferredCompression == ImageLoader::DataCompression::S3TC)
	{
		if((header.m_compressionFormats & ImageLoader::DataCompression::RAW)
			!= ImageLoader::DataCompression::NONE)
		{
			// If raw compression is present then skip it
			ANKI_CHECK(file.seek(
				calcSizeOfSegment(header, ImageLoader::DataCompression::RAW), 
				File::SeekOrigin::CURRENT));
		}
	}
	else if(preferredCompression == ImageLoader::DataCompression::ETC)
	{
		if((header.m_compressionFormats & ImageLoader::DataCompression::RAW)
			!= ImageLoader::DataCompression::NONE)
		{
			// If raw compression is present then skip it
			ANKI_CHECK(file.seek(
				calcSizeOfSegment(header, ImageLoader::DataCompression::RAW), 
				File::SeekOrigin::CURRENT));
		}

		if((header.m_compressionFormats & ImageLoader::DataCompression::S3TC)
			!= ImageLoader::DataCompression::NONE)
		{
			// If s3tc compression is present then skip it
			ANKI_CHECK(file.seek(
				calcSizeOfSegment(header, ImageLoader::DataCompression::S3TC), 
				File::SeekOrigin::CURRENT));
		}
	}

	//
	// It's time to read
	//

	// Allocate the surfaces 
	surfaces.create(alloc, mipLevels * depth);

	// Read all surfaces
	U mipWidth = header.m_width;
	U mipHeight = header.m_height;
	U index = 0;
	for(U mip = 0; mip < header.m_mipLevels; mip++)
	{
		for(U d = 0; d < depth; d++)
		{
			U dataSize = calcSurfaceSize(
				mipWidth, mipHeight, preferredCompression, 
				header.m_colorFormat);

			// Check if this mipmap can be skipped because of size
			if(max(mipWidth, mipHeight) <= maxTextureSize)
			{
				ImageLoader::Surface& surf = surfaces[index++];
				surf.m_width = mipWidth;
				surf.m_height = mipHeight;

				surf.m_data.create(alloc, dataSize);

				ANKI_CHECK(file.read(&surf.m_data[0], dataSize));
			}
			else
			{
				ANKI_CHECK(file.seek(dataSize, File::SeekOrigin::CURRENT));
			}
		}

		mipWidth /= 2;
		mipHeight /= 2;
	}

	return ErrorCode::NONE;
}