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