Forráskód Böngészése

texturec: Synced with bgfx code.

Branimir Karadžić 8 éve
szülő
commit
b0bdc18c27
1 módosított fájl, 360 hozzáadás és 289 törlés
  1. 360 289
      tools/texturec/texturec.cpp

+ 360 - 289
tools/texturec/texturec.cpp

@@ -20,6 +20,320 @@
 #include <bx/crtimpl.h>
 #include <bx/uint32_t.h>
 
+struct Options
+{
+	Options()
+		: maxSize(UINT32_MAX)
+		, edge(0.0f)
+		, format(bimg::TextureFormat::Count)
+		, mips(false)
+		, normalMap(false)
+		, iqa(false)
+		, sdf(false)
+	{
+	}
+
+	uint32_t maxSize;
+	float edge;
+	bimg::TextureFormat::Enum format;
+	bool mips;
+	bool normalMap;
+	bool iqa;
+	bool sdf;
+};
+
+bimg::ImageContainer* convert(bx::AllocatorI* _allocator, const void* _inputData, uint32_t _inputSize, const Options& _options)
+{
+	const uint8_t* inputData = (uint8_t*)_inputData;
+
+	bimg::ImageContainer* output = NULL;
+	bimg::ImageContainer* input  = bimg::imageParse(_allocator, inputData, _inputSize);
+
+	if (NULL != input)
+	{
+		bimg::TextureFormat::Enum format = input->m_format;
+
+		if (bimg::TextureFormat::Count != _options.format)
+		{
+			format = _options.format;
+		}
+
+		if (input->m_width  > _options.maxSize
+		||  input->m_height > _options.maxSize)
+		{
+			bimg::ImageContainer* src = bimg::imageConvert(_allocator, bimg::TextureFormat::RGBA32F, *input);
+
+			uint32_t width;
+			uint32_t height;
+
+			if (input->m_width > input->m_height)
+			{
+				width  = _options.maxSize;
+				height = input->m_height * width / input->m_width;
+			}
+			else
+			{
+				height = _options.maxSize;
+				width  = input->m_width * height / input->m_height;
+			}
+
+			bimg::ImageContainer* dst = bimg::imageAlloc(_allocator
+				, bimg::TextureFormat::RGBA32F
+				, uint16_t(width)
+				, uint16_t(height)
+				, 1, 1, false, false
+				);
+
+			bimg::imageResizeRgba32fLinear(dst, src);
+
+			bimg::imageFree(src);
+			bimg::imageFree(input);
+
+			input = bimg::imageConvert(_allocator, format, *dst);
+			bimg::imageFree(dst);
+		}
+
+		bimg::ImageMip mip;
+		if (bimg::imageGetRawData(*input, 0, 0, input->m_data, input->m_size, mip) )
+		{
+			uint8_t numMips = _options.mips
+				? bimg::imageGetNumMips(format, uint16_t(mip.m_width), uint16_t(mip.m_height) )
+				: 1
+				;
+
+			void* temp = NULL;
+
+			if (_options.normalMap)
+			{
+				output = bimg::imageAlloc(_allocator, format, uint16_t(mip.m_width), uint16_t(mip.m_height), 0, 1, false, _options.mips);
+
+				bimg::ImageMip dstMip;
+				bimg::imageGetRawData(*output, 0, 0, NULL, 0, dstMip);
+
+				if (mip.m_width  != dstMip.m_width
+				&&  mip.m_height != dstMip.m_height)
+				{
+					printf("Invalid input image size %dx%d, it must be at least %dx%d to be converted to %s format.\n"
+						, mip.m_width
+						, mip.m_height
+						, dstMip.m_width
+						, dstMip.m_height
+						, getName(format)
+						);
+					return NULL;
+				}
+
+				uint32_t size = bimg::imageGetSize(
+						NULL
+					, uint16_t(dstMip.m_width)
+					, uint16_t(dstMip.m_height)
+					, 0
+					, false
+					, false
+					, 1
+					, bimg::TextureFormat::RGBA32F
+					);
+				temp = BX_ALLOC(_allocator, size);
+				float* rgba = (float*)temp;
+				float* rgbaDst = (float*)BX_ALLOC(_allocator, size);
+
+				bimg::imageDecodeToRgba32f(_allocator
+					, rgba
+					, mip.m_data
+					, mip.m_width
+					, mip.m_height
+					, mip.m_width*mip.m_bpp/8
+					, mip.m_format
+					);
+
+				if (bimg::TextureFormat::BC5 != mip.m_format)
+				{
+					for (uint32_t yy = 0; yy < mip.m_height; ++yy)
+					{
+						for (uint32_t xx = 0; xx < mip.m_width; ++xx)
+						{
+							const uint32_t offset = (yy*mip.m_width + xx) * 4;
+							float* inout = &rgba[offset];
+							inout[0] = inout[0] * 2.0f - 1.0f;
+							inout[1] = inout[1] * 2.0f - 1.0f;
+							inout[2] = inout[2] * 2.0f - 1.0f;
+							inout[3] = inout[3] * 2.0f - 1.0f;
+						}
+					}
+				}
+
+				bimg::imageRgba32f11to01(rgbaDst, dstMip.m_width, dstMip.m_height, dstMip.m_width*16, rgba);
+				bimg::imageEncodeFromRgba32f(_allocator, output->m_data, rgbaDst, dstMip.m_width, dstMip.m_height, format);
+
+				for (uint8_t lod = 1; lod < numMips; ++lod)
+				{
+					bimg::imageRgba32fDownsample2x2NormalMap(rgba, dstMip.m_width, dstMip.m_height, dstMip.m_width*16, rgba);
+					bimg::imageRgba32f11to01(rgbaDst, dstMip.m_width, dstMip.m_height, dstMip.m_width*16, rgba);
+					bimg::imageGetRawData(*output, 0, lod, output->m_data, output->m_size, dstMip);
+					uint8_t* data = const_cast<uint8_t*>(dstMip.m_data);
+					bimg::imageEncodeFromRgba32f(_allocator, data, rgbaDst, dstMip.m_width, dstMip.m_height, format);
+				}
+
+				BX_FREE(_allocator, rgbaDst);
+			}
+			else if (8 != bimg::getBlockInfo(input->m_format).rBits)
+			{
+				output = bimg::imageAlloc(_allocator, format, uint16_t(mip.m_width), uint16_t(mip.m_height), 0, 1, false, _options.mips);
+
+				bimg::ImageMip dstMip;
+				bimg::imageGetRawData(*output, 0, 0, NULL, 0, dstMip);
+
+				if (mip.m_width  != dstMip.m_width
+				&&  mip.m_height != dstMip.m_height)
+				{
+					printf("Invalid input image size %dx%d, it must be at least %dx%d to be converted to %s format.\n"
+						, mip.m_width
+						, mip.m_height
+						, dstMip.m_width
+						, dstMip.m_height
+						, getName(format)
+						);
+					return NULL;
+				}
+
+				uint32_t size = bimg::imageGetSize(
+						NULL
+					, uint16_t(dstMip.m_width)
+					, uint16_t(dstMip.m_height)
+					, 0
+					, false
+					, false
+					, 1
+					, bimg::TextureFormat::RGBA32F
+					);
+				temp = BX_ALLOC(_allocator, size);
+				float* rgba = (float*)temp;
+				float* rgbaDst = (float*)BX_ALLOC(_allocator, size);
+
+				bimg::imageDecodeToRgba32f(_allocator
+					, rgba
+					, mip.m_data
+					, mip.m_width
+					, mip.m_height
+					, mip.m_width*mip.m_bpp/8
+					, mip.m_format
+					);
+				bimg::imageEncodeFromRgba32f(_allocator, output->m_data, rgba, dstMip.m_width, dstMip.m_height, format);
+
+				bimg::imageRgba32fToLinear(rgba
+					, mip.m_width
+					, mip.m_height
+					, mip.m_width*mip.m_bpp/8
+					, rgba
+					);
+
+				for (uint8_t lod = 1; lod < numMips; ++lod)
+				{
+					bimg::imageRgba32fLinearDownsample2x2(rgba, dstMip.m_width, dstMip.m_height, dstMip.m_width*16, rgba);
+					bimg::imageGetRawData(*output, 0, lod, output->m_data, output->m_size, dstMip);
+					uint8_t* data = const_cast<uint8_t*>(dstMip.m_data);
+
+					bimg::imageRgba32fToGamma(rgbaDst
+						, mip.m_width
+						, mip.m_height
+						, mip.m_width*mip.m_bpp/8
+						, rgba
+						);
+
+					bimg::imageEncodeFromRgba32f(_allocator, data, rgbaDst, dstMip.m_width, dstMip.m_height, format);
+				}
+
+				BX_FREE(_allocator, rgbaDst);
+			}
+			else
+			{
+				output = bimg::imageAlloc(_allocator, format, uint16_t(mip.m_width), uint16_t(mip.m_height), 0, 1, false, _options.mips);
+
+				bimg::ImageMip dstMip;
+				bimg::imageGetRawData(*output, 0, 0, NULL, 0, dstMip);
+
+				if (mip.m_width  != dstMip.m_width
+				&&  mip.m_height != dstMip.m_height)
+				{
+					printf("Invalid input image size %dx%d, it must be at least %dx%d to be converted to %s format.\n"
+						, mip.m_width
+						, mip.m_height
+						, dstMip.m_width
+						, dstMip.m_height
+						, getName(format)
+						);
+					return NULL;
+				}
+
+				uint32_t size = bimg::imageGetSize(
+						NULL
+					, uint16_t(dstMip.m_width)
+					, uint16_t(dstMip.m_height)
+					, 0
+					, false
+					, false
+					, 1
+					, bimg::TextureFormat::RGBA8
+					);
+				temp = BX_ALLOC(_allocator, size);
+				bx::memSet(temp, 0, size);
+				uint8_t* rgba = (uint8_t*)temp;
+
+				bimg::imageDecodeToRgba8(rgba
+					, mip.m_data
+					, mip.m_width
+					, mip.m_height
+					, mip.m_width*mip.m_bpp/8
+					, mip.m_format
+					);
+
+				void* ref = NULL;
+				if (_options.iqa)
+				{
+					ref = BX_ALLOC(_allocator, size);
+					bx::memCopy(ref, rgba, size);
+				}
+
+				bimg::imageEncodeFromRgba8(output->m_data, rgba, dstMip.m_width, dstMip.m_height, format);
+
+				for (uint8_t lod = 1; lod < numMips; ++lod)
+				{
+					bimg::imageRgba8Downsample2x2(rgba, dstMip.m_width, dstMip.m_height, dstMip.m_width*4, rgba);
+					bimg::imageGetRawData(*output, 0, lod, output->m_data, output->m_size, dstMip);
+					uint8_t* data = const_cast<uint8_t*>(dstMip.m_data);
+					bimg::imageEncodeFromRgba8(data, rgba, dstMip.m_width, dstMip.m_height, format);
+				}
+
+				if (NULL != ref)
+				{
+					bimg::imageDecodeToRgba8(rgba
+						, output->m_data
+						, mip.m_width
+						, mip.m_height
+						, mip.m_width*mip.m_bpp/8
+						, format
+						);
+
+					float result = bimg::imageQualityRgba8(
+						  ref
+						, rgba
+						, uint16_t(mip.m_width)
+						, uint16_t(mip.m_height)
+						);
+
+					printf("%f\n", result);
+
+					BX_FREE(_allocator, ref);
+				}
+			}
+
+			BX_FREE(_allocator, temp);
+		}
+	}
+
+	return output;
+}
+
 void help(const char* _error = NULL)
 {
 	if (NULL != _error)
@@ -53,6 +367,8 @@ void help(const char* _error = NULL)
 		  "  -n, --normalmap          Input texture is normal map.\n"
 		  "      --sdf <edge>         Compute SDF texture.\n"
 		  "      --iqa                Image Quality Assesment\n"
+		  "      --max <max size>     Maximum width/height (image will be scaled down and\n"
+		  "                           aspect ratio will be preserved.\n"
 
 		  "\n"
 		  "For additional information, see https://github.com/bkaradzic/bgfx\n"
@@ -83,19 +399,24 @@ int main(int _argc, const char* _argv[])
 		return EXIT_FAILURE;
 	}
 
-	bool sdf = false;
-	double edge = 16.0;
+	Options options;
+
 	const char* edgeOpt = cmdLine.findOption("sdf");
 	if (NULL != edgeOpt)
 	{
-		sdf  = true;
-		edge = atof(edgeOpt);
+		options.sdf  = true;
+		options.edge = (float)atof(edgeOpt);
 	}
-	BX_UNUSED(sdf, edge);
 
-	const bool mips      = cmdLine.hasArg('m',  "mips");
-	const bool normalMap = cmdLine.hasArg('n',  "normalmap");
-	const bool iqa       = cmdLine.hasArg('\0', "iqa");
+	options.mips      = cmdLine.hasArg('m',  "mips");
+	options.normalMap = cmdLine.hasArg('n',  "normalmap");
+	options.iqa       = cmdLine.hasArg('\0', "iqa");
+
+	const char* maxSize = cmdLine.findOption("max");
+	if (NULL != maxSize)
+	{
+		options.maxSize = atoi(maxSize);
+	}
 
 	bx::CrtFileReader reader;
 	if (!bx::open(&reader, inputFileName) )
@@ -104,6 +425,19 @@ int main(int _argc, const char* _argv[])
 		return EXIT_FAILURE;
 	}
 
+	options.format = bimg::TextureFormat::Count;
+	const char* type = cmdLine.findOption('t');
+	if (NULL != type)
+	{
+		options.format = bimg::getFormat(type);
+
+		if (!bimg::isValid(options.format) )
+		{
+			help("Invalid format specified.");
+			return EXIT_FAILURE;
+		}
+	}
+
 	bx::CrtAllocator allocator;
 
 	uint32_t inputSize = (uint32_t)bx::getSize(&reader);
@@ -112,297 +446,34 @@ int main(int _argc, const char* _argv[])
 	bx::read(&reader, inputData, inputSize);
 	bx::close(&reader);
 
-	{
-		bimg::ImageContainer* input = bimg::imageParse(&allocator, inputData, inputSize);
-
-		if (NULL != input)
-		{
-			BX_FREE(&allocator, inputData);
-
-			const char* type = cmdLine.findOption('t');
-			bimg::TextureFormat::Enum format = input->m_format;
-
-			if (NULL != type)
-			{
-				format = bimg::getFormat(type);
-
-				if (!bimg::isValid(format) )
-				{
-					help("Invalid format specified.");
-					return EXIT_FAILURE;
-				}
-			}
+	bimg::ImageContainer* output = convert(&allocator, inputData, inputSize, options);
 
-			bimg::ImageContainer* output = NULL;
+	BX_FREE(&allocator, inputData);
 
-			bimg::ImageMip mip;
-			if (bimg::imageGetRawData(*input, 0, 0, input->m_data, input->m_size, mip) )
+	if (NULL != output)
+	{
+		bx::CrtFileWriter writer;
+		if (bx::open(&writer, outputFileName) )
+		{
+			if (NULL != bx::stristr(outputFileName, ".ktx") )
 			{
-				uint8_t numMips = mips
-					? bimg::imageGetNumMips(format, uint16_t(mip.m_width), uint16_t(mip.m_height) )
-					: 1
-					;
-
-				void* temp = NULL;
-
-				if (normalMap)
-				{
-					output = bimg::imageAlloc(&allocator, format, uint16_t(mip.m_width), uint16_t(mip.m_height), 0, 1, false, mips);
-
-					bimg::ImageMip dstMip;
-					bimg::imageGetRawData(*output, 0, 0, NULL, 0, dstMip);
-
-					if (mip.m_width  != dstMip.m_width
-					&&  mip.m_height != dstMip.m_height)
-					{
-						printf("Invalid input image size %dx%d, it must be at least %dx%d to be converted to %s format.\n"
-							, mip.m_width
-							, mip.m_height
-							, dstMip.m_width
-							, dstMip.m_height
-							, getName(format)
-							);
-						return EXIT_FAILURE;
-					}
-
-					uint32_t size = bimg::imageGetSize(
-						  NULL
-						, uint16_t(dstMip.m_width)
-						, uint16_t(dstMip.m_height)
-						, 0
-						, false
-						, false
-						, 1
-						, bimg::TextureFormat::RGBA32F
-						);
-					temp = BX_ALLOC(&allocator, size);
-					float* rgba = (float*)temp;
-					float* rgbaDst = (float*)BX_ALLOC(&allocator, size);
-
-					bimg::imageDecodeToRgba32f(&allocator
-						, rgba
-						, mip.m_data
-						, mip.m_width
-						, mip.m_height
-						, mip.m_width*mip.m_bpp/8
-						, mip.m_format
-						);
-
-					if (bimg::TextureFormat::BC5 != mip.m_format)
-					{
-						for (uint32_t yy = 0; yy < mip.m_height; ++yy)
-						{
-							for (uint32_t xx = 0; xx < mip.m_width; ++xx)
-							{
-								const uint32_t offset = (yy*mip.m_width + xx) * 4;
-								float* inout = &rgba[offset];
-								inout[0] = inout[0] * 2.0f - 1.0f;
-								inout[1] = inout[1] * 2.0f - 1.0f;
-								inout[2] = inout[2] * 2.0f - 1.0f;
-								inout[3] = inout[3] * 2.0f - 1.0f;
-							}
-						}
-					}
-
-					bimg::imageRgba32f11to01(rgbaDst, dstMip.m_width, dstMip.m_height, dstMip.m_width*16, rgba);
-					bimg::imageEncodeFromRgba32f(&allocator, output->m_data, rgbaDst, dstMip.m_width, dstMip.m_height, format);
-
-					for (uint8_t lod = 1; lod < numMips; ++lod)
-					{
-						bimg::imageRgba32fDownsample2x2NormalMap(rgba, dstMip.m_width, dstMip.m_height, dstMip.m_width*16, rgba);
-						bimg::imageRgba32f11to01(rgbaDst, dstMip.m_width, dstMip.m_height, dstMip.m_width*16, rgba);
-						bimg::imageGetRawData(*output, 0, lod, output->m_data, output->m_size, dstMip);
-						uint8_t* data = const_cast<uint8_t*>(dstMip.m_data);
-						bimg::imageEncodeFromRgba32f(&allocator, data, rgbaDst, dstMip.m_width, dstMip.m_height, format);
-					}
-
-					BX_FREE(&allocator, rgbaDst);
-				}
-				else if (8 != getBlockInfo(input->m_format).rBits)
-				{
-					output = imageAlloc(&allocator, format, uint16_t(mip.m_width), uint16_t(mip.m_height), 0, 1, false, mips);
-
-					bimg::ImageMip dstMip;
-					bimg::imageGetRawData(*output, 0, 0, NULL, 0, dstMip);
-
-					if (mip.m_width  != dstMip.m_width
-					&&  mip.m_height != dstMip.m_height)
-					{
-						printf("Invalid input image size %dx%d, it must be at least %dx%d to be converted to %s format.\n"
-							, mip.m_width
-							, mip.m_height
-							, dstMip.m_width
-							, dstMip.m_height
-							, getName(format)
-							);
-						return EXIT_FAILURE;
-					}
-
-					uint32_t size = bimg::imageGetSize(
-						  NULL
-						, uint16_t(dstMip.m_width)
-						, uint16_t(dstMip.m_height)
-						, 0
-						, false
-						, false
-						, 1
-						, bimg::TextureFormat::RGBA32F
-						);
-					temp = BX_ALLOC(&allocator, size);
-					float* rgba = (float*)temp;
-					float* rgbaDst = (float*)BX_ALLOC(&allocator, size);
-
-					bimg::imageDecodeToRgba32f(&allocator
-						, rgba
-						, mip.m_data
-						, mip.m_width
-						, mip.m_height
-						, mip.m_width*mip.m_bpp/8
-						, mip.m_format
-						);
-					bimg::imageEncodeFromRgba32f(&allocator, output->m_data, rgba, dstMip.m_width, dstMip.m_height, format);
-
-					bimg::imageRgba32fToLinear(rgba
-						, mip.m_width
-						, mip.m_height
-						, mip.m_width*mip.m_bpp/8
-						, rgba
-						);
-
-					for (uint8_t lod = 1; lod < numMips; ++lod)
-					{
-						bimg::imageRgba32fLinearDownsample2x2(rgba, dstMip.m_width, dstMip.m_height, dstMip.m_width*16, rgba);
-						bimg::imageGetRawData(*output, 0, lod, output->m_data, output->m_size, dstMip);
-						uint8_t* data = const_cast<uint8_t*>(dstMip.m_data);
-
-						bimg::imageRgba32fToGamma(rgbaDst
-							, mip.m_width
-							, mip.m_height
-							, mip.m_width*mip.m_bpp/8
-							, rgba
-							);
-
-						bimg::imageEncodeFromRgba32f(&allocator, data, rgbaDst, dstMip.m_width, dstMip.m_height, format);
-					}
-
-					BX_FREE(&allocator, rgbaDst);
-				}
-				else
-				{
-					output = imageAlloc(&allocator, format, uint16_t(mip.m_width), uint16_t(mip.m_height), 0, 1, false, mips);
-
-					bimg::ImageMip dstMip;
-					bimg::imageGetRawData(*output, 0, 0, NULL, 0, dstMip);
-
-					if (mip.m_width  != dstMip.m_width
-					&&  mip.m_height != dstMip.m_height)
-					{
-						printf("Invalid input image size %dx%d, it must be at least %dx%d to be converted to %s format.\n"
-							, mip.m_width
-							, mip.m_height
-							, dstMip.m_width
-							, dstMip.m_height
-							, getName(format)
-							);
-						return EXIT_FAILURE;
-					}
-
-					uint32_t size = bimg::imageGetSize(
-						  NULL
-						, uint16_t(dstMip.m_width)
-						, uint16_t(dstMip.m_height)
-						, 0
-						, false
-						, false
-						, 1
-						, bimg::TextureFormat::RGBA8
-						);
-					temp = BX_ALLOC(&allocator, size);
-					bx::memSet(temp, 0, size);
-					uint8_t* rgba = (uint8_t*)temp;
-
-					bimg::imageDecodeToRgba8(rgba
-						, mip.m_data
-						, mip.m_width
-						, mip.m_height
-						, mip.m_width*mip.m_bpp/8
-						, mip.m_format
-						);
-
-					void* ref = NULL;
-					if (iqa)
-					{
-						ref = BX_ALLOC(&allocator, size);
-						bx::memCopy(ref, rgba, size);
-					}
-
-					bimg::imageEncodeFromRgba8(output->m_data, rgba, dstMip.m_width, dstMip.m_height, format);
-
-					for (uint8_t lod = 1; lod < numMips; ++lod)
-					{
-						bimg::imageRgba8Downsample2x2(rgba, dstMip.m_width, dstMip.m_height, dstMip.m_width*4, rgba);
-						bimg::imageGetRawData(*output, 0, lod, output->m_data, output->m_size, dstMip);
-						uint8_t* data = const_cast<uint8_t*>(dstMip.m_data);
-						bimg::imageEncodeFromRgba8(data, rgba, dstMip.m_width, dstMip.m_height, format);
-					}
-
-					if (NULL != ref)
-					{
-						bimg::imageDecodeToRgba8(rgba
-							, output->m_data
-							, mip.m_width
-							, mip.m_height
-							, mip.m_width*mip.m_bpp/8
-							, format
-							);
-
-						float result = bimg::imageQualityRgba8(
-							  ref
-							, rgba
-							, mip.m_width
-							, mip.m_height
-							);
-
-						printf("%f\n", result);
-
-						BX_FREE(&allocator, ref);
-					}
-				}
-
-				BX_FREE(&allocator, temp);
+				bimg::imageWriteKtx(&writer, *output, output->m_data, output->m_size);
 			}
 
-			if (NULL != output)
-			{
-				bx::CrtFileWriter writer;
-				if (bx::open(&writer, outputFileName) )
-				{
-					if (NULL != bx::stristr(outputFileName, ".ktx") )
-					{
-						imageWriteKtx(&writer, *output, output->m_data, output->m_size);
-					}
-
-					bx::close(&writer);
-				}
-				else
-				{
-					help("Failed to open output file.");
-					return EXIT_FAILURE;
-				}
-
-				bimg::imageFree(output);
-			}
-			else
-			{
-				help("No output generated.");
-				return EXIT_FAILURE;
-			}
+			bx::close(&writer);
 		}
 		else
 		{
-			help("Failed to load input file.");
+			help("Failed to open output file.");
 			return EXIT_FAILURE;
 		}
+
+		bimg::imageFree(output);
+	}
+	else
+	{
+		help("No output generated.");
+		return EXIT_FAILURE;
 	}
 
 	return EXIT_SUCCESS;