Blender  V2.59
dds_api.cpp
Go to the documentation of this file.
00001 /*
00002  * $Id: dds_api.cpp 36541 2011-05-07 20:53:49Z jesterking $
00003  *
00004  * ***** BEGIN GPL LICENSE BLOCK *****
00005  *
00006  * This program is free software; you can redistribute it and/or
00007  * modify it under the terms of the GNU General Public License
00008  * as published by the Free Software Foundation; either version 2
00009  * of the License, or (at your option) any later version.
00010  *
00011  * This program is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  * GNU General Public License for more details.
00015  *
00016  * You should have received a copy of the GNU General Public License
00017  * along with this program; if not, write to the Free Software Foundation,
00018  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00019  *
00020  * Contributors: Amorilia (amorilia@users.sourceforge.net)
00021  *
00022  * ***** END GPL LICENSE BLOCK *****
00023  */
00024 
00030 #include <stddef.h>
00031 #include <dds_api.h>
00032 #include <Stream.h>
00033 #include <DirectDrawSurface.h>
00034 #include <stdio.h> // printf
00035 #include <fstream>
00036 
00037 extern "C" {
00038 
00039 #include "imbuf.h"
00040 #include "IMB_imbuf_types.h"
00041 #include "IMB_imbuf.h"
00042 #include "IMB_allocimbuf.h"
00043 
00044 
00045 int imb_save_dds(struct ImBuf * ibuf, const char *name, int flags)
00046 {
00047         return(0); /* todo: finish this function */
00048 
00049         /* check image buffer */
00050         if (ibuf == 0) return (0);
00051         if (ibuf->rect == 0) return (0);
00052 
00053         /* open file for writing */
00054         std::ofstream fildes(name);
00055 
00056         /* write header */
00057         fildes << "DDS ";
00058         fildes.close();
00059 
00060         return(1);
00061 }
00062 
00063 int imb_is_a_dds(unsigned char *mem) // note: use at most first 32 bytes
00064 {
00065         /* heuristic check to see if mem contains a DDS file */
00066         /* header.fourcc == FOURCC_DDS */
00067         if ((mem[0] != 'D') || (mem[1] != 'D') || (mem[2] != 'S') || (mem[3] != ' ')) return(0);
00068         /* header.size == 124 */
00069         if ((mem[4] != 124) || mem[5] || mem[6] || mem[7]) return(0);
00070         return(1);
00071 }
00072 
00073 struct ImBuf *imb_load_dds(unsigned char *mem, size_t size, int flags)
00074 {
00075         struct ImBuf * ibuf = 0;
00076         DirectDrawSurface dds(mem, size); /* reads header */
00077         unsigned char bits_per_pixel;
00078         unsigned int *rect;
00079         Image img;
00080         unsigned int numpixels = 0;
00081         int col;
00082         unsigned char *cp = (unsigned char *) &col;
00083         Color32 pixel;
00084         Color32 *pixels = 0;
00085 
00086         if(!imb_is_a_dds(mem))
00087                 return (0);
00088 
00089         /* check if DDS is valid and supported */
00090         if (!dds.isValid()) {
00091                 /* no need to print error here, just testing if it is a DDS */
00092                 if(flags & IB_test)
00093                         return (0);
00094 
00095                 printf("DDS: not valid; header follows\n");
00096                 dds.printInfo();
00097                 return(0);
00098         }
00099         if (!dds.isSupported()) {
00100                 printf("DDS: format not supported\n");
00101                 return(0);
00102         }
00103         if ((dds.width() > 65535) || (dds.height() > 65535)) {
00104                 printf("DDS: dimensions too large\n");
00105                 return(0);
00106         }
00107 
00108         /* convert DDS into ImBuf */
00109         dds.mipmap(&img, 0, 0); /* load first face, first mipmap */
00110         pixels = img.pixels();
00111         numpixels = dds.width() * dds.height();
00112         bits_per_pixel = 24;
00113         if (img.format() == Image::Format_ARGB) {
00114                 /* check that there is effectively an alpha channel */
00115                 for (unsigned int i = 0; i < numpixels; i++) {
00116                         pixel = pixels[i];
00117                         if (pixel.a != 255) {
00118                                 bits_per_pixel = 32;
00119                                 break;
00120                         };
00121                 };
00122         };
00123         ibuf = IMB_allocImBuf(dds.width(), dds.height(), bits_per_pixel, 0); 
00124         if (ibuf == 0) return(0); /* memory allocation failed */
00125 
00126         ibuf->ftype = DDS;
00127         ibuf->profile = IB_PROFILE_SRGB;
00128 
00129         if ((flags & IB_test) == 0) {
00130                 if (!imb_addrectImBuf(ibuf)) return(ibuf);
00131                 if (ibuf->rect == 0) return(ibuf);
00132 
00133                 rect = ibuf->rect;
00134                 cp[3] = 0xff; /* default alpha if alpha channel is not present */
00135 
00136                 for (unsigned int i = 0; i < numpixels; i++) {
00137                         pixel = pixels[i];
00138                         cp[0] = pixel.r; /* set R component of col */
00139                         cp[1] = pixel.g; /* set G component of col */
00140                         cp[2] = pixel.b; /* set B component of col */
00141                         if (bits_per_pixel == 32)
00142                                 cp[3] = pixel.a; /* set A component of col */
00143                         rect[i] = col;
00144                 }
00145                 IMB_flipy(ibuf);
00146         }
00147 
00148         return(ibuf);
00149 }
00150 
00151 } // extern "C"