ソースを参照

Added support for .hdr image write.

Branimir Karadžić 7 年 前
コミット
29a05c292b
3 ファイル変更74 行追加4 行削除
  1. 13 1
      include/bimg/bimg.h
  2. 41 0
      src/image.cpp
  3. 20 3
      tools/texturec/texturec.cpp

+ 13 - 1
include/bimg/bimg.h

@@ -9,7 +9,7 @@
 #include <stdint.h> // uint32_t
 #include <stdlib.h> // NULL
 
-#define BIMG_API_VERSION UINT32_C(6)
+#define BIMG_API_VERSION UINT32_C(7)
 
 namespace bx
 {
@@ -493,6 +493,18 @@ namespace bimg
 		, bx::Error* _err
 		);
 
+	///
+	int32_t imageWriteHdr(
+		  bx::WriterI* _writer
+		, uint32_t _width
+		, uint32_t _height
+		, uint32_t _srcPitch
+		, const void* _src
+		, TextureFormat::Enum _format
+		, bool _yflip
+		, bx::Error* _err
+		);
+
 	///
 	int32_t imageWriteDds(
 		  bx::WriterI* _writer

+ 41 - 0
src/image.cpp

@@ -5000,6 +5000,47 @@ namespace bimg
 		return total;
 	}
 
+	int32_t imageWriteHdr(bx::WriterI* _writer, uint32_t _width, uint32_t _height, uint32_t _srcPitch, const void* _src, TextureFormat::Enum _format, bool _yflip, bx::Error* _err)
+	{
+		BX_ERROR_SCOPE(_err);
+
+		int32_t total = 0;
+		total += bx::write(_writer, "#?RADIANCE\n" , _err);
+		total += bx::write(_writer, "FORMAT=32-bit_rle_rgbe\n" , _err);
+		total += bx::write(_writer, '\n' , _err);
+
+		total += bx::writePrintf(_writer, "%cY %d +X %d\n", _yflip ? '+' : '-', _height, _width);
+
+		UnpackFn unpack = getUnpack(_format);
+		const uint32_t bpp  = getBitsPerPixel(_format);
+
+		const uint8_t* data = (const uint8_t*)_src;
+		for (uint32_t yy = 0; yy < _height && _err->isOk(); ++yy)
+		{
+			for (uint32_t xx = 0; xx < _width && _err->isOk(); ++xx)
+			{
+				float rgba[4];
+				unpack(rgba, &data[xx*bpp/8]);
+
+				const float maxVal = bx::max(rgba[0], rgba[1], rgba[2]);
+				const float exp    = bx::ceil(bx::log2(maxVal) );
+				const float toRgb8 = 255.0f * 1.0f/bx::ldexp(1.0f, int(exp) );
+
+				uint8_t rgbe[4];
+				rgbe[0] = uint8_t(rgba[0] * toRgb8);
+				rgbe[1] = uint8_t(rgba[1] * toRgb8);
+				rgbe[2] = uint8_t(rgba[2] * toRgb8);
+				rgbe[3] = uint8_t(exp+128.0f);
+
+				total += bx::write(_writer, rgbe, 4, _err);
+			}
+
+			data += _srcPitch;
+		}
+
+		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)
 	{
 		BX_ERROR_SCOPE(_err);

+ 20 - 3
tools/texturec/texturec.cpp

@@ -770,7 +770,7 @@ void help(const char* _error = NULL, bool _showHelp = true)
 		  "    *.exr (input, output)  OpenEXR.\n"
 		  "    *.gif (input)          Graphics Interchange Format.\n"
 		  "    *.jpg (input)          JPEG Interchange Format.\n"
-		  "    *.hdr (input)          Radiance RGBE.\n"
+		  "    *.hdr (input, output)  Radiance RGBE.\n"
 		  "    *.ktx (input, output)  Khronos Texture.\n"
 		  "    *.png (input, output)  Portable Network Graphics.\n"
 		  "    *.psd (input)          Photoshop Document.\n"
@@ -881,6 +881,7 @@ int main(int _argc, const char* _argv[])
 	saveAs = NULL == saveAs ? bx::strFindI(outputFileName, ".dds") : saveAs;
 	saveAs = NULL == saveAs ? bx::strFindI(outputFileName, ".png") : saveAs;
 	saveAs = NULL == saveAs ? bx::strFindI(outputFileName, ".exr") : saveAs;
+	saveAs = NULL == saveAs ? bx::strFindI(outputFileName, ".hdr") : saveAs;
 	if (NULL == saveAs)
 	{
 		help("Output file format must be specified.");
@@ -1044,7 +1045,8 @@ int main(int _argc, const char* _argv[])
 					, mip.m_data
 					, output->m_format
 					, false
-					, &err);
+					, &err
+					);
 			}
 			else if (NULL != bx::strFindI(saveAs, "exr") )
 			{
@@ -1057,7 +1059,22 @@ int main(int _argc, const char* _argv[])
 					, mip.m_data
 					, output->m_format
 					, false
-					, &err);
+					, &err
+					);
+			}
+			else if (NULL != bx::strFindI(saveAs, "hdr") )
+			{
+				bimg::ImageMip mip;
+				bimg::imageGetRawData(*output, 0, 0, output->m_data, output->m_size, mip);
+				bimg::imageWriteHdr(&writer
+					, mip.m_width
+					, mip.m_height
+					, mip.m_width*8
+					, mip.m_data
+					, output->m_format
+					, false
+					, &err
+					);
 			}
 
 			bx::close(&writer);