1 #define NOMINMAX
2 #include <climits>
3 #pragma warning(push)
4 #pragma warning(disable: 4595)
5 #include <nvimage/Image.h>
6 #include <nvimage/DirectDrawSurface.h>
7 #include <nvmath/Color.h>
8 #include <nvtt/nvtt.h>
9 #pragma warning(pop)
10 #include "xr_image.h"
11 #include "xr_file_system.h"
12 
13 using namespace xray_re;
14 
load_dds(const std::string & path)15 bool xr_image::load_dds(const std::string& path)
16 {
17 	nv::DirectDrawSurface dds(path.c_str());
18 	if (!dds.isValid() || !dds.isTexture2D())
19 		return false;
20 	nv::Image image;
21 	dds.mipmap(&image, 0, 0);
22 	m_width = image.width();
23 	m_height = image.height();
24 	m_data = new rgba32[m_width*m_height];
25 	for (unsigned i = m_height*m_width; i > 0;) {
26 		const nv::Color32& pix = image.pixel(--i);
27 		m_data[i] = pix.u;
28 	}
29 	return true;
30 }
31 
load_dds(const char * path,const char * name)32 bool xr_image::load_dds(const char* path, const char* name)
33 {
34 	xr_file_system& fs = xr_file_system::instance();
35 	std::string full_path;
36 	if (!fs.resolve_path(path, name, full_path))
37 		return false;
38 	return load_dds(full_path);
39 }
40 
save_dds(const char * path,const std::string & name,const irect * rect) const41 bool xr_image::save_dds(const char* path, const std::string& name, const irect* rect) const
42 {
43 	xr_memory_writer* w = new xr_memory_writer();
44 	bool status = save_dds(*w, rect) && w->save_to(path, name);
45 	delete w;
46 	return status;
47 }
48 
49 struct dds_writer: public nvtt::OutputHandler {
50 			dds_writer(xr_writer& _w);
51 
52 	virtual void	beginImage(int size, int width, int height, int depth, int face, int miplevel);
53 	virtual bool	writeData(const void* data, int size);
54 	xr_writer&	w;
55 };
56 
dds_writer(xr_writer & _w)57 inline dds_writer::dds_writer(xr_writer& _w): w(_w) {}
58 
beginImage(int size,int width,int height,int depth,int face,int miplevel)59 void dds_writer::beginImage(int size, int width, int height, int depth, int face, int miplevel)
60 {
61 }
62 
writeData(const void * data,int size)63 bool dds_writer::writeData(const void* data, int size)
64 {
65 	w.w_raw(data, size_t(size & INT_MAX));
66 	return true;
67 }
68 
save_dds(xr_writer & w,const irect * rect) const69 bool xr_image::save_dds(xr_writer& w, const irect* rect) const
70 {
71 #if 1
72 	int width, height;
73 	rgba32* data;
74 	if (rect) {
75 		width = int((rect->x2 - rect->x1 + 1) & INT_MAX);
76 		height = int((rect->y2 - rect->y1 + 1) & INT_MAX);
77 		data = new rgba32[width * height];
78 		const rgba32* src_data = &m_data[rect->y1*m_width + rect->x1];
79 		for (int i = 0; i != height; ++i) {
80 			memcpy(&data[i*width], src_data, width*sizeof(rgba32));
81 			src_data += m_width;
82 		}
83 	} else {
84 		width = m_width;
85 		height = m_height;
86 		data = m_data;
87 	}
88 #else
89 	int width = int(m_width & INT_MAX);
90 	int height = int(m_height & INT_MAX);
91 	const rgba32* data = m_data;
92 #endif
93 
94 	nvtt::InputOptions in_opts;
95 	in_opts.setTextureLayout(nvtt::TextureType_2D, width, height);
96 	in_opts.setWrapMode(nvtt::WrapMode_Clamp);
97 	in_opts.setMipmapData(data, width, height);
98 	if (data != m_data)
99 		delete[] data;
100 	in_opts.setNormalMap(false);
101 	in_opts.setConvertToNormalMap(false);
102 	in_opts.setGamma(2.2f, 2.2f);
103 	in_opts.setNormalizeMipmaps(false);
104 
105 	nvtt::CompressionOptions comp_opts;
106 	comp_opts.setFormat(nvtt::Format_BC3);
107 	comp_opts.setQuality(nvtt::Quality_Highest);
108 
109 	nvtt::OutputOptions out_opts;
110 	dds_writer dds(w);
111 	out_opts.setOutputHandler(&dds);
112 	out_opts.setErrorHandler(0);
113 
114 	return nvtt::Compressor().process(in_opts, comp_opts, out_opts);
115 }
116