Blender  V2.93
dds_api.cpp
Go to the documentation of this file.
1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version 2
5  * of the License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software Foundation,
14  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15  */
16 
21 #include "BLI_utildefines.h"
22 
23 #include <DirectDrawSurface.h>
24 #include <FlipDXT.h>
25 #include <Stream.h>
26 #include <cstddef>
27 #include <cstdio> /* printf */
28 #include <dds_api.h>
29 #include <fstream>
30 
31 #if defined(WIN32)
32 # include "utfconv.h"
33 #endif
34 
35 #include "IMB_allocimbuf.h"
36 #include "IMB_imbuf.h"
37 #include "IMB_imbuf_types.h"
38 #include "imbuf.h"
39 
40 #include "IMB_colormanagement.h"
42 
43 extern "C" {
44 
45 bool imb_save_dds(struct ImBuf *ibuf, const char *name, int /*flags*/)
46 {
47  return false; /* todo: finish this function */
48 
49  /* check image buffer */
50  if (ibuf == nullptr) {
51  return false;
52  }
53  if (ibuf->rect == nullptr) {
54  return false;
55  }
56 
57  /* open file for writing */
58  std::ofstream fildes;
59 
60 #if defined(WIN32)
61  wchar_t *wname = alloc_utf16_from_8(name, 0);
62  fildes.open(wname);
63  free(wname);
64 #else
65  fildes.open(name);
66 #endif
67 
68  /* write header */
69  fildes << "DDS ";
70  fildes.close();
71 
72  return true;
73 }
74 
75 bool imb_is_a_dds(const unsigned char *mem, const size_t size)
76 {
77  if (size < 8) {
78  return false;
79  }
80  /* heuristic check to see if mem contains a DDS file */
81  /* header.fourcc == FOURCC_DDS */
82  if ((mem[0] != 'D') || (mem[1] != 'D') || (mem[2] != 'S') || (mem[3] != ' ')) {
83  return false;
84  }
85  /* header.size == 124 */
86  if ((mem[4] != 124) || mem[5] || mem[6] || mem[7]) {
87  return false;
88  }
89  return true;
90 }
91 
92 struct ImBuf *imb_load_dds(const unsigned char *mem,
93  size_t size,
94  int flags,
95  char colorspace[IM_MAX_SPACE])
96 {
97  struct ImBuf *ibuf = nullptr;
98  DirectDrawSurface dds((unsigned char *)mem, size); /* reads header */
99  unsigned char bits_per_pixel;
100  unsigned int *rect;
101  Image img;
102  unsigned int numpixels = 0;
103  int col;
104  unsigned char *cp = (unsigned char *)&col;
105  Color32 pixel;
106  Color32 *pixels = nullptr;
107 
108  /* OCIO_TODO: never was able to save DDS, so can't test loading
109  * but profile used to be set to sRGB and can't see rect_float here, so
110  * default byte space should work fine
111  */
113 
114  if (!imb_is_a_dds(mem, size)) {
115  return nullptr;
116  }
117 
118  /* check if DDS is valid and supported */
119  if (!dds.isValid()) {
120  /* no need to print error here, just testing if it is a DDS */
121  if (flags & IB_test) {
122  return nullptr;
123  }
124 
125  printf("DDS: not valid; header follows\n");
126  dds.printInfo();
127  return nullptr;
128  }
129  if (!dds.isSupported()) {
130  printf("DDS: format not supported\n");
131  return nullptr;
132  }
133  if ((dds.width() > 65535) || (dds.height() > 65535)) {
134  printf("DDS: dimensions too large\n");
135  return nullptr;
136  }
137 
138  /* convert DDS into ImBuf */
139  dds.mipmap(&img, 0, 0); /* load first face, first mipmap */
140  pixels = img.pixels();
141  numpixels = dds.width() * dds.height();
142  bits_per_pixel = 24;
143  if (img.format() == Image::Format_ARGB) {
144  /* check that there is effectively an alpha channel */
145  for (unsigned int i = 0; i < numpixels; i++) {
146  pixel = pixels[i];
147  if (pixel.a != 255) {
148  bits_per_pixel = 32;
149  break;
150  }
151  }
152  }
153  ibuf = IMB_allocImBuf(dds.width(), dds.height(), bits_per_pixel, 0);
154  if (ibuf == nullptr) {
155  return nullptr; /* memory allocation failed */
156  }
157 
158  ibuf->ftype = IMB_FTYPE_DDS;
159  ibuf->dds_data.fourcc = dds.fourCC();
160  ibuf->dds_data.nummipmaps = dds.mipmapCount();
161 
162  if ((flags & IB_test) == 0) {
163  if (!imb_addrectImBuf(ibuf)) {
164  return ibuf;
165  }
166  if (ibuf->rect == nullptr) {
167  return ibuf;
168  }
169 
170  rect = ibuf->rect;
171  cp[3] = 0xff; /* default alpha if alpha channel is not present */
172 
173  for (unsigned int i = 0; i < numpixels; i++) {
174  pixel = pixels[i];
175  cp[0] = pixel.r; /* set R component of col */
176  cp[1] = pixel.g; /* set G component of col */
177  cp[2] = pixel.b; /* set B component of col */
178  if (dds.hasAlpha()) {
179  cp[3] = pixel.a; /* set A component of col */
180  }
181  rect[i] = col;
182  }
183 
184  if (ibuf->dds_data.fourcc != FOURCC_DDS) {
185  ibuf->dds_data.data = (unsigned char *)dds.readData(ibuf->dds_data.size);
186 
187  /* flip compressed texture */
188  if (ibuf->dds_data.data) {
189  FlipDXTCImage(dds.width(),
190  dds.height(),
191  ibuf->dds_data.nummipmaps,
192  dds.fourCC(),
193  ibuf->dds_data.data,
194  ibuf->dds_data.size,
195  &ibuf->dds_data.nummipmaps);
196  }
197  }
198  else {
199  ibuf->dds_data.data = nullptr;
200  ibuf->dds_data.size = 0;
201  }
202 
203  /* flip uncompressed texture */
204  IMB_flipy(ibuf);
205  }
206 
207  return ibuf;
208 }
209 
210 } /* extern "C" */
void BLI_kdtree_nd_() free(KDTree *tree)
Definition: kdtree_impl.h:116
static const uint FOURCC_DDS
int FlipDXTCImage(unsigned int width, unsigned int height, unsigned int levels, int fourcc, uint8_t *data, int data_size, unsigned int *r_num_valid_levels)
Definition: FlipDXT.cpp:171
Header file for allocimbuf.c.
@ COLOR_ROLE_DEFAULT_BYTE
struct ImBuf * IMB_allocImBuf(unsigned int x, unsigned int y, unsigned char planes, unsigned int flags)
Definition: allocimbuf.c:478
#define IM_MAX_SPACE
Definition: IMB_imbuf.h:65
bool imb_addrectImBuf(struct ImBuf *ibuf)
Definition: allocimbuf.c:407
void IMB_flipy(struct ImBuf *ibuf)
Definition: rotate.c:33
Contains defines and structs used throughout the imbuf module.
@ IB_test
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
Definition: btDbvt.cpp:52
Definition: Color.h:33
unsigned char g
Definition: Color.h:90
unsigned char b
Definition: Color.h:90
unsigned char r
Definition: Color.h:90
unsigned char a
Definition: Color.h:90
void mipmap(Image *img, uint f, uint m)
void * readData(uint &size)
Format format() const
Definition: Image.cpp:114
const Color32 * pixels() const
Definition: Image.cpp:86
void colorspace_set_default_role(char *colorspace, int size, int role)
bool imb_is_a_dds(const unsigned char *mem, const size_t size)
Definition: dds_api.cpp:75
struct ImBuf * imb_load_dds(const unsigned char *mem, size_t size, int flags, char colorspace[IM_MAX_SPACE])
Definition: dds_api.cpp:92
bool imb_save_dds(struct ImBuf *ibuf, const char *name, int)
Definition: dds_api.cpp:45
uint col
unsigned int size
unsigned int nummipmaps
unsigned char * data
unsigned int fourcc
struct DDSData dds_data
enum eImbFileType ftype
unsigned int * rect
wchar_t * alloc_utf16_from_8(const char *in8, size_t add)
Definition: utfconv.c:296