Blender  V3.3
dds_api.cpp
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later */
2 
7 #include "BLI_utildefines.h"
8 
9 #include <DirectDrawSurface.h>
10 #include <FlipDXT.h>
11 #include <Stream.h>
12 #include <cstddef>
13 #include <cstdio> /* printf */
14 #include <dds_api.h>
15 #include <fstream>
16 
17 #if defined(WIN32)
18 # include "utfconv.h"
19 #endif
20 
21 #include "IMB_allocimbuf.h"
22 #include "IMB_imbuf.h"
23 #include "IMB_imbuf_types.h"
24 #include "imbuf.h"
25 
26 #include "IMB_colormanagement.h"
28 
29 extern "C" {
30 
31 bool imb_save_dds(struct ImBuf *ibuf, const char *name, int /*flags*/)
32 {
33  return false; /* TODO: finish this function. */
34 
35  /* check image buffer */
36  if (ibuf == nullptr) {
37  return false;
38  }
39  if (ibuf->rect == nullptr) {
40  return false;
41  }
42 
43  /* open file for writing */
44  std::ofstream fildes;
45 
46 #if defined(WIN32)
47  wchar_t *wname = alloc_utf16_from_8(name, 0);
48  fildes.open(wname);
49  free(wname);
50 #else
51  fildes.open(name);
52 #endif
53 
54  /* write header */
55  fildes << "DDS ";
56  fildes.close();
57 
58  return true;
59 }
60 
61 bool imb_is_a_dds(const unsigned char *mem, const size_t size)
62 {
63  if (size < 8) {
64  return false;
65  }
66  /* heuristic check to see if mem contains a DDS file */
67  /* header.fourcc == FOURCC_DDS */
68  if ((mem[0] != 'D') || (mem[1] != 'D') || (mem[2] != 'S') || (mem[3] != ' ')) {
69  return false;
70  }
71  /* header.size == 124 */
72  if ((mem[4] != 124) || mem[5] || mem[6] || mem[7]) {
73  return false;
74  }
75  return true;
76 }
77 
78 struct ImBuf *imb_load_dds(const unsigned char *mem,
79  size_t size,
80  int flags,
81  char colorspace[IM_MAX_SPACE])
82 {
83  struct ImBuf *ibuf = nullptr;
84  DirectDrawSurface dds((unsigned char *)mem, size); /* reads header */
85  unsigned char bits_per_pixel;
86  unsigned int *rect;
87  Image img;
88  unsigned int numpixels = 0;
89  int col;
90  unsigned char *cp = (unsigned char *)&col;
91  Color32 pixel;
92  Color32 *pixels = nullptr;
93 
94  /* OCIO_TODO: never was able to save DDS, so can't test loading
95  * but profile used to be set to sRGB and can't see rect_float here, so
96  * default byte space should work fine
97  */
99 
100  if (!imb_is_a_dds(mem, size)) {
101  return nullptr;
102  }
103 
104  /* check if DDS is valid and supported */
105  if (!dds.isValid()) {
106  /* no need to print error here, just testing if it is a DDS */
107  if (flags & IB_test) {
108  return nullptr;
109  }
110 
111  printf("DDS: not valid; header follows\n");
112  dds.printInfo();
113  return nullptr;
114  }
115  if (!dds.isSupported()) {
116  printf("DDS: format not supported\n");
117  return nullptr;
118  }
119  if ((dds.width() > 65535) || (dds.height() > 65535)) {
120  printf("DDS: dimensions too large\n");
121  return nullptr;
122  }
123 
124  /* convert DDS into ImBuf */
125  dds.mipmap(&img, 0, 0); /* load first face, first mipmap */
126  pixels = img.pixels();
127  numpixels = dds.width() * dds.height();
128  bits_per_pixel = 24;
129  if (img.format() == Image::Format_ARGB) {
130  /* check that there is effectively an alpha channel */
131  for (unsigned int i = 0; i < numpixels; i++) {
132  pixel = pixels[i];
133  if (pixel.a != 255) {
134  bits_per_pixel = 32;
135  break;
136  }
137  }
138  }
139  ibuf = IMB_allocImBuf(dds.width(), dds.height(), bits_per_pixel, 0);
140  if (ibuf == nullptr) {
141  return nullptr; /* memory allocation failed */
142  }
143 
144  ibuf->ftype = IMB_FTYPE_DDS;
145  ibuf->dds_data.fourcc = dds.fourCC();
146  ibuf->dds_data.nummipmaps = dds.mipmapCount();
147 
148  if ((flags & IB_test) == 0) {
149  if (!imb_addrectImBuf(ibuf)) {
150  return ibuf;
151  }
152  if (ibuf->rect == nullptr) {
153  return ibuf;
154  }
155 
156  rect = ibuf->rect;
157  cp[3] = 0xff; /* default alpha if alpha channel is not present */
158 
159  for (unsigned int i = 0; i < numpixels; i++) {
160  pixel = pixels[i];
161  cp[0] = pixel.r; /* set R component of col */
162  cp[1] = pixel.g; /* set G component of col */
163  cp[2] = pixel.b; /* set B component of col */
164  if (dds.hasAlpha()) {
165  cp[3] = pixel.a; /* set A component of col */
166  }
167  rect[i] = col;
168  }
169 
170  if (ibuf->dds_data.fourcc != FOURCC_DDS) {
171  ibuf->dds_data.data = (unsigned char *)dds.readData(ibuf->dds_data.size);
172 
173  /* flip compressed texture */
174  if (ibuf->dds_data.data) {
175  FlipDXTCImage(dds.width(),
176  dds.height(),
177  ibuf->dds_data.nummipmaps,
178  dds.fourCC(),
179  ibuf->dds_data.data,
180  ibuf->dds_data.size,
181  &ibuf->dds_data.nummipmaps);
182  }
183  }
184  else {
185  ibuf->dds_data.data = nullptr;
186  ibuf->dds_data.size = 0;
187  }
188 
189  /* flip uncompressed texture */
190  IMB_flipy(ibuf);
191  }
192 
193  return ibuf;
194 }
195 
196 } /* extern "C" */
void BLI_kdtree_nd_() free(KDTree *tree)
Definition: kdtree_impl.h:102
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:144
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:500
#define IM_MAX_SPACE
Definition: IMB_imbuf.h:49
bool imb_addrectImBuf(struct ImBuf *ibuf)
Definition: allocimbuf.c:387
void IMB_flipy(struct ImBuf *ibuf)
Definition: rotate.c:16
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:19
unsigned char g
Definition: Color.h:75
unsigned char b
Definition: Color.h:75
unsigned char r
Definition: Color.h:75
unsigned char a
Definition: Color.h:75
void mipmap(Image *img, uint f, uint m)
void * readData(uint &size)
Format format() const
Definition: Image.cpp:100
const Color32 * pixels() const
Definition: Image.cpp:72
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:61
struct ImBuf * imb_load_dds(const unsigned char *mem, size_t size, int flags, char colorspace[IM_MAX_SPACE])
Definition: dds_api.cpp:78
bool imb_save_dds(struct ImBuf *ibuf, const char *name, int)
Definition: dds_api.cpp:31
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:291