Jelajahi Sumber

Added support for writing .dds files.

Branimir Karadžić 8 tahun lalu
induk
melakukan
f63dc66de2
3 mengubah file dengan 127 tambahan dan 3 penghapusan
  1. 10 1
      include/bimg/bimg.h
  2. 105 1
      src/image.cpp
  3. 12 1
      tools/texturec/texturec.cpp

+ 10 - 1
include/bimg/bimg.h

@@ -9,7 +9,7 @@
 #include <stdint.h> // uint32_t
 #include <stdlib.h> // NULL
 
-#define BIMG_API_VERSION UINT32_C(3)
+#define BIMG_API_VERSION UINT32_C(4)
 
 namespace bx
 {
@@ -425,6 +425,15 @@ namespace bimg
 		, bx::Error* _err = NULL
 		);
 
+	///
+	int32_t imageWriteDds(
+		  bx::WriterI* _writer
+		, ImageContainer& _imageContainer
+		, const void* _data
+		, uint32_t _size
+		, bx::Error* _err
+		);
+
 	///
 	int32_t imageWriteKtx(
 		  bx::WriterI* _writer

+ 105 - 1
src/image.cpp

@@ -1961,7 +1961,7 @@ namespace bimg
 		{ DDS_FORMAT_B4G4R4A4_UNORM,      TextureFormat::RGBA4,      false },
 		{ DDS_FORMAT_B5G5R5A1_UNORM,      TextureFormat::RGB5A1,     false },
 		{ DDS_FORMAT_R10G10B10A2_UNORM,   TextureFormat::RGB10A2,    false },
-		{ DDS_FORMAT_R11G11B10_FLOAT,     TextureFormat::RG11B10F, false },
+		{ DDS_FORMAT_R11G11B10_FLOAT,     TextureFormat::RG11B10F,   false },
 	};
 
 	struct TranslateDdsPixelFormat
@@ -3205,6 +3205,110 @@ namespace bimg
 		return total;
 	}
 
+	static int32_t imageWriteDdsHeader(bx::WriterI* _writer, TextureFormat::Enum _format, bool _cubeMap, uint32_t _width, uint32_t _height, uint32_t _depth, uint8_t _numMips, bx::Error* _err)
+	{
+		uint32_t dxgiFormat = 0;
+		for (uint32_t ii = 0; ii < BX_COUNTOF(s_translateDxgiFormat); ++ii)
+		{
+			if (s_translateDxgiFormat[ii].m_textureFormat == _format)
+			{
+				dxgiFormat = s_translateDxgiFormat[ii].m_format;
+				break;
+			}
+		}
+
+		if (0 == dxgiFormat)
+		{
+			BX_ERROR_SET(_err, BIMG_ERROR, "DDS: DXGI format not supported.");
+			return 0;
+		}
+
+		const uint32_t bpp = getBitsPerPixel(_format);
+
+		uint32_t total = 0;
+		total += bx::write(_writer, uint32_t(DDS_MAGIC), _err);
+		total += bx::write(_writer, uint32_t(DDS_HEADER_SIZE), _err);
+		total += bx::write(_writer, uint32_t(0
+			| DDSD_HEIGHT
+			| DDSD_WIDTH
+			| DDSD_DEPTH
+			| DDSD_PITCH
+			| DDSD_MIPMAPCOUNT
+			| DDSD_PIXELFORMAT
+			| DDSD_CAPS
+			)
+			, _err
+			);
+		total += bx::write(_writer, _height, _err);
+		total += bx::write(_writer, _width, _err);
+		total += bx::write(_writer, _width*bpp/8, _err);
+		total += bx::write(_writer, _depth, _err);
+		total += bx::write(_writer, uint32_t(_numMips), _err);
+
+		total += bx::writeRep(_writer, 0, 44, _err);
+
+		total += bx::write(_writer, uint32_t(8*sizeof(uint32_t) ), _err); // pixelFormatSize
+		total += bx::write(_writer, uint32_t(DDPF_FOURCC), _err);
+		total += bx::write(_writer, uint32_t(DDS_DX10), _err);
+		total += bx::write(_writer, bpp, _err);
+		total += bx::writeRep(_writer, 0, 4*sizeof(uint32_t), _err); // bitmask
+
+		uint32_t caps[4] =
+		{
+			uint32_t(DDSCAPS_TEXTURE | (1 < _numMips ? DDSCAPS_MIPMAP : 0) ),
+			uint32_t(_cubeMap ? DDSCAPS2_CUBEMAP|DDS_CUBEMAP_ALLFACES : 0),
+			0,
+			0,
+		};
+		total += bx::write(_writer, caps, sizeof(caps) );
+
+		total += bx::writeRep(_writer, 0, 4, _err);
+
+		total += bx::write(_writer, dxgiFormat);
+
+		total += bx::write(_writer, uint32_t(0), _err); // dims
+		total += bx::write(_writer, uint32_t(0), _err); // miscFlags
+		total += bx::write(_writer, uint32_t(1), _err); // arraySize
+		total += bx::write(_writer, uint32_t(0), _err); // miscFlags2
+
+		return total;
+	}
+
+	int32_t imageWriteDds(bx::WriterI* _writer, ImageContainer& _imageContainer, const void* _data, uint32_t _size, bx::Error* _err)
+	{
+		BX_ERROR_SCOPE(_err);
+
+		int32_t total = 0;
+		total += imageWriteDdsHeader(_writer
+			, TextureFormat::Enum(_imageContainer.m_format)
+			, _imageContainer.m_cubeMap
+			, _imageContainer.m_width
+			, _imageContainer.m_height
+			, _imageContainer.m_depth
+			, _imageContainer.m_numMips
+			, _err
+			);
+
+		if (!_err->isOk() )
+		{
+			return total;
+		}
+
+		for (uint8_t side = 0, numSides = _imageContainer.m_cubeMap ? 6 : 1; side < numSides && _err->isOk(); ++side)
+		{
+			for (uint8_t lod = 0, num = _imageContainer.m_numMips; lod < num && _err->isOk(); ++lod)
+			{
+				ImageMip mip;
+				if (imageGetRawData(_imageContainer, side, lod, _data, _size, mip) )
+				{
+					total += bx::write(_writer, mip.m_data, mip.m_size, _err);
+				}
+			}
+		}
+
+		return total;
+	}
+
 	static int32_t imageWriteKtxHeader(bx::WriterI* _writer, TextureFormat::Enum _format, bool _cubeMap, uint32_t _width, uint32_t _height, uint32_t _depth, uint8_t _numMips, bx::Error* _err)
 	{
 		BX_ERROR_SCOPE(_err);

+ 12 - 1
tools/texturec/texturec.cpp

@@ -589,6 +589,7 @@ int main(int _argc, const char* _argv[])
 
 	const char* saveAs = cmdLine.findOption("as");
 	saveAs = NULL == saveAs ? bx::strFindI(outputFileName, ".ktx") : saveAs;
+	saveAs = NULL == saveAs ? bx::strFindI(outputFileName, ".dds") : saveAs;
 	if (NULL == saveAs)
 	{
 		help("Output file format must be specified.");
@@ -683,10 +684,20 @@ int main(int _argc, const char* _argv[])
 		{
 			if (NULL != bx::strFindI(saveAs, "ktx") )
 			{
-				bimg::imageWriteKtx(&writer, *output, output->m_data, output->m_size);
+				bimg::imageWriteKtx(&writer, *output, output->m_data, output->m_size, &err);
+			}
+			else if (NULL != bx::strFindI(saveAs, "dds") )
+			{
+				bimg::imageWriteDds(&writer, *output, output->m_data, output->m_size, &err);
 			}
 
 			bx::close(&writer);
+
+			if (!err.isOk() )
+			{
+				help(NULL, err);
+				return EXIT_FAILURE;
+			}
 		}
 		else
 		{