style cleanup
[blender.git] / source / blender / imbuf / intern / dds / dds_api.cpp
1 /*
2  * ***** BEGIN GPL LICENSE BLOCK *****
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  *
18  * Contributors: Amorilia (amorilia@users.sourceforge.net)
19  *
20  * ***** END GPL LICENSE BLOCK *****
21  */
22
23 /** \file blender/imbuf/intern/dds/dds_api.cpp
24  *  \ingroup imbdds
25  */
26
27
28 #include <stddef.h>
29 #include <dds_api.h>
30 #include <Stream.h>
31 #include <DirectDrawSurface.h>
32 #include <FlipDXT.h>
33 #include <stdio.h> // printf
34 #include <fstream>
35
36 #if defined (WIN32) && !defined(FREE_WINDOWS)
37 #include "utfconv.h"
38 #endif
39
40 extern "C" {
41
42 #include "imbuf.h"
43 #include "IMB_imbuf_types.h"
44 #include "IMB_imbuf.h"
45 #include "IMB_allocimbuf.h"
46
47 #include "IMB_colormanagement.h"
48 #include "IMB_colormanagement_intern.h"
49
50 int imb_save_dds(struct ImBuf * ibuf, const char *name, int flags)
51 {
52         return(0); /* todo: finish this function */
53
54         /* check image buffer */
55         if (ibuf == 0) return (0);
56         if (ibuf->rect == 0) return (0);
57
58         /* open file for writing */
59         std::ofstream fildes;
60
61 #if defined (WIN32) && !defined(FREE_WINDOWS)
62         wchar_t *wname = alloc_utf16_from_8(name, 0);
63         fildes.open(wname);
64         free(wname);
65 #else
66         fildes.open(name);
67 #endif
68
69         /* write header */
70         fildes << "DDS ";
71         fildes.close();
72
73         return(1);
74 }
75
76 int imb_is_a_dds(unsigned char *mem) // note: use at most first 32 bytes
77 {
78         /* heuristic check to see if mem contains a DDS file */
79         /* header.fourcc == FOURCC_DDS */
80         if ((mem[0] != 'D') || (mem[1] != 'D') || (mem[2] != 'S') || (mem[3] != ' ')) return(0);
81         /* header.size == 124 */
82         if ((mem[4] != 124) || mem[5] || mem[6] || mem[7]) return(0);
83         return(1);
84 }
85
86 struct ImBuf *imb_load_dds(unsigned char *mem, size_t size, int flags, char colorspace[IM_MAX_SPACE])
87 {
88         struct ImBuf * ibuf = 0;
89         DirectDrawSurface dds(mem, size); /* reads header */
90         unsigned char bits_per_pixel;
91         unsigned int *rect;
92         Image img;
93         unsigned int numpixels = 0;
94         int col;
95         unsigned char *cp = (unsigned char *) &col;
96         Color32 pixel;
97         Color32 *pixels = 0;
98
99         /* OCIO_TODO: never was able to save DDS, so can'ttest loading
100          *            but profile used to be set to sRGB and can't see rect_float here, so
101          *            default byte space should work fine
102          */
103         colorspace_set_default_role(colorspace, IM_MAX_SPACE, COLOR_ROLE_DEFAULT_BYTE);
104
105         if (!imb_is_a_dds(mem))
106                 return (0);
107
108         /* check if DDS is valid and supported */
109         if (!dds.isValid()) {
110                 /* no need to print error here, just testing if it is a DDS */
111                 if (flags & IB_test)
112                         return (0);
113
114                 printf("DDS: not valid; header follows\n");
115                 dds.printInfo();
116                 return(0);
117         }
118         if (!dds.isSupported()) {
119                 printf("DDS: format not supported\n");
120                 return(0);
121         }
122         if ((dds.width() > 65535) || (dds.height() > 65535)) {
123                 printf("DDS: dimensions too large\n");
124                 return(0);
125         }
126
127         /* convert DDS into ImBuf */
128         dds.mipmap(&img, 0, 0); /* load first face, first mipmap */
129         pixels = img.pixels();
130         numpixels = dds.width() * dds.height();
131         bits_per_pixel = 24;
132         if (img.format() == Image::Format_ARGB) {
133                 /* check that there is effectively an alpha channel */
134                 for (unsigned int i = 0; i < numpixels; i++) {
135                         pixel = pixels[i];
136                         if (pixel.a != 255) {
137                                 bits_per_pixel = 32;
138                                 break;
139                         };
140                 };
141         };
142         ibuf = IMB_allocImBuf(dds.width(), dds.height(), bits_per_pixel, 0); 
143         if (ibuf == 0) return(0); /* memory allocation failed */
144
145         ibuf->ftype = DDS;
146         ibuf->dds_data.fourcc = dds.fourCC();
147         ibuf->dds_data.nummipmaps = dds.mipmapCount();
148
149         if ((flags & IB_test) == 0) {
150                 if (!imb_addrectImBuf(ibuf)) return(ibuf);
151                 if (ibuf->rect == 0) return(ibuf);
152
153                 rect = ibuf->rect;
154                 cp[3] = 0xff; /* default alpha if alpha channel is not present */
155
156                 for (unsigned int i = 0; i < numpixels; i++) {
157                         pixel = pixels[i];
158                         cp[0] = pixel.r; /* set R component of col */
159                         cp[1] = pixel.g; /* set G component of col */
160                         cp[2] = pixel.b; /* set B component of col */
161                         if (dds.hasAlpha())
162                                 cp[3] = pixel.a; /* set A component of col */
163                         rect[i] = col;
164                 }
165
166                 if (ibuf->dds_data.fourcc != FOURCC_DDS) {
167                         ibuf->dds_data.data = (unsigned char *)dds.readData(ibuf->dds_data.size);
168
169                         /* flip compressed texture */
170                         FlipDXTCImage(dds.width(), dds.height(), dds.mipmapCount(), dds.fourCC(), ibuf->dds_data.data);
171                 }
172                 else {
173                         ibuf->dds_data.data = NULL;
174                         ibuf->dds_data.size = 0;
175                 }
176
177                 /* flip uncompressed texture */
178                 IMB_flipy(ibuf);
179         }
180
181         return(ibuf);
182 }
183
184 } // extern "C"