Blender V2.61 - r43446
|
00001 /* 00002 * ***** BEGIN GPL LICENSE BLOCK ***** 00003 * 00004 * This program is free software; you can redistribute it and/or 00005 * modify it under the terms of the GNU General Public License 00006 * as published by the Free Software Foundation; either version 2 00007 * of the License, or (at your option) any later version. 00008 * 00009 * This program is distributed in the hope that it will be useful, 00010 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00012 * GNU General Public License for more details. 00013 * 00014 * You should have received a copy of the GNU General Public License 00015 * along with this program; if not, write to the Free Software Foundation, 00016 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 00017 * 00018 * ***** END GPL LICENSE BLOCK ***** 00019 */ 00020 00026 #include <stdio.h> 00027 #include <stdlib.h> 00028 #include <string.h> 00029 00030 #include "MEM_guardedalloc.h" 00031 00032 #include "BLI_fileops.h" 00033 #include "BLI_string.h" 00034 #include "BLI_utildefines.h" 00035 00036 #include "BKE_customdata_file.h" 00037 #include "BKE_global.h" 00038 00039 00040 /************************* File Format Definitions ***************************/ 00041 00042 #define CDF_ENDIAN_LITTLE 0 00043 #define CDF_ENDIAN_BIG 1 00044 00045 #define CDF_DATA_FLOAT 0 00046 00047 typedef struct CDataFileHeader { 00048 char ID[4]; /* "BCDF" */ 00049 char endian; /* little, big */ 00050 char version; /* non-compatible versions */ 00051 char subversion; /* compatible sub versions */ 00052 char pad; /* padding */ 00053 00054 int structbytes; /* size of this struct in bytes */ 00055 int type; /* image, mesh */ 00056 int totlayer; /* number of layers in the file */ 00057 } CDataFileHeader; 00058 00059 typedef struct CDataFileImageHeader { 00060 int structbytes; /* size of this struct in bytes */ 00061 int width; /* image width */ 00062 int height; /* image height */ 00063 int tile_size; /* tile size (required power of 2) */ 00064 } CDataFileImageHeader; 00065 00066 typedef struct CDataFileMeshHeader { 00067 int structbytes; /* size of this struct in bytes */ 00068 } CDataFileMeshHeader; 00069 00070 struct CDataFileLayer { 00071 int structbytes; /* size of this struct in bytes */ 00072 int datatype; /* only float for now */ 00073 uint64_t datasize; /* size of data in layer */ 00074 int type; /* layer type */ 00075 char name[CDF_LAYER_NAME_MAX]; /* layer name */ 00076 }; 00077 00078 /**************************** Other Definitions ******************************/ 00079 00080 #define CDF_VERSION 0 00081 #define CDF_SUBVERSION 0 00082 #define CDF_TILE_SIZE 64 00083 00084 struct CDataFile { 00085 int type; 00086 00087 CDataFileHeader header; 00088 union { 00089 CDataFileImageHeader image; 00090 CDataFileMeshHeader mesh; 00091 } btype; 00092 00093 CDataFileLayer *layer; 00094 int totlayer; 00095 00096 FILE *readf; 00097 FILE *writef; 00098 int switchendian; 00099 size_t dataoffset; 00100 }; 00101 00102 /********************************* Create/Free *******************************/ 00103 00104 static int cdf_endian(void) 00105 { 00106 if(ENDIAN_ORDER == L_ENDIAN) 00107 return CDF_ENDIAN_LITTLE; 00108 else 00109 return CDF_ENDIAN_BIG; 00110 } 00111 00112 /*static int cdf_data_type_size(int datatype) 00113 { 00114 if(datatype == CDF_DATA_FLOAT) 00115 return sizeof(float); 00116 00117 return 0; 00118 }*/ 00119 00120 CDataFile *cdf_create(int type) 00121 { 00122 CDataFile *cdf= MEM_callocN(sizeof(CDataFile), "CDataFile"); 00123 00124 cdf->type= type; 00125 00126 return cdf; 00127 } 00128 00129 void cdf_free(CDataFile *cdf) 00130 { 00131 cdf_read_close(cdf); 00132 cdf_write_close(cdf); 00133 00134 if(cdf->layer) 00135 MEM_freeN(cdf->layer); 00136 00137 MEM_freeN(cdf); 00138 } 00139 00140 /********************************* Read/Write ********************************/ 00141 00142 static int cdf_read_header(CDataFile *cdf) 00143 { 00144 CDataFileHeader *header; 00145 CDataFileImageHeader *image; 00146 CDataFileMeshHeader *mesh; 00147 CDataFileLayer *layer; 00148 FILE *f= cdf->readf; 00149 size_t offset = 0; 00150 int a; 00151 00152 header= &cdf->header; 00153 00154 if(!fread(header, sizeof(CDataFileHeader), 1, cdf->readf)) 00155 return 0; 00156 00157 if(memcmp(header->ID, "BCDF", sizeof(header->ID)) != 0) 00158 return 0; 00159 if(header->version > CDF_VERSION) 00160 return 0; 00161 00162 cdf->switchendian= header->endian != cdf_endian(); 00163 header->endian= cdf_endian(); 00164 00165 if(cdf->switchendian) { 00166 SWITCH_INT(header->type); 00167 SWITCH_INT(header->totlayer); 00168 SWITCH_INT(header->structbytes); 00169 } 00170 00171 if(!ELEM(header->type, CDF_TYPE_IMAGE, CDF_TYPE_MESH)) 00172 return 0; 00173 00174 offset += header->structbytes; 00175 header->structbytes= sizeof(CDataFileHeader); 00176 00177 if(fseek(f, offset, SEEK_SET) != 0) 00178 return 0; 00179 00180 if(header->type == CDF_TYPE_IMAGE) { 00181 image= &cdf->btype.image; 00182 if(!fread(image, sizeof(CDataFileImageHeader), 1, f)) 00183 return 0; 00184 00185 if(cdf->switchendian) { 00186 SWITCH_INT(image->width); 00187 SWITCH_INT(image->height); 00188 SWITCH_INT(image->tile_size); 00189 SWITCH_INT(image->structbytes); 00190 } 00191 00192 offset += image->structbytes; 00193 image->structbytes= sizeof(CDataFileImageHeader); 00194 } 00195 else if(header->type == CDF_TYPE_MESH) { 00196 mesh= &cdf->btype.mesh; 00197 if(!fread(mesh, sizeof(CDataFileMeshHeader), 1, f)) 00198 return 0; 00199 00200 if(cdf->switchendian) 00201 SWITCH_INT(mesh->structbytes); 00202 00203 offset += mesh->structbytes; 00204 mesh->structbytes= sizeof(CDataFileMeshHeader); 00205 } 00206 00207 if(fseek(f, offset, SEEK_SET) != 0) 00208 return 0; 00209 00210 cdf->layer= MEM_callocN(sizeof(CDataFileLayer)*header->totlayer, "CDataFileLayer"); 00211 cdf->totlayer= header->totlayer; 00212 00213 for(a=0; a<header->totlayer; a++) { 00214 layer= &cdf->layer[a]; 00215 00216 if(!fread(layer, sizeof(CDataFileLayer), 1, f)) 00217 return 0; 00218 00219 if(cdf->switchendian) { 00220 SWITCH_INT(layer->type); 00221 SWITCH_INT(layer->datatype); 00222 SWITCH_INT64(layer->datasize); 00223 SWITCH_INT(layer->structbytes); 00224 } 00225 00226 if(layer->datatype != CDF_DATA_FLOAT) 00227 return 0; 00228 00229 offset += layer->structbytes; 00230 layer->structbytes= sizeof(CDataFileLayer); 00231 00232 if(fseek(f, offset, SEEK_SET) != 0) 00233 return 0; 00234 } 00235 00236 cdf->dataoffset= offset; 00237 00238 return 1; 00239 } 00240 00241 static int cdf_write_header(CDataFile *cdf) 00242 { 00243 CDataFileHeader *header; 00244 CDataFileImageHeader *image; 00245 CDataFileMeshHeader *mesh; 00246 CDataFileLayer *layer; 00247 FILE *f= cdf->writef; 00248 int a; 00249 00250 header= &cdf->header; 00251 00252 if(!fwrite(header, sizeof(CDataFileHeader), 1, f)) 00253 return 0; 00254 00255 if(header->type == CDF_TYPE_IMAGE) { 00256 image= &cdf->btype.image; 00257 if(!fwrite(image, sizeof(CDataFileImageHeader), 1, f)) 00258 return 0; 00259 } 00260 else if(header->type == CDF_TYPE_MESH) { 00261 mesh= &cdf->btype.mesh; 00262 if(!fwrite(mesh, sizeof(CDataFileMeshHeader), 1, f)) 00263 return 0; 00264 } 00265 00266 for(a=0; a<header->totlayer; a++) { 00267 layer= &cdf->layer[a]; 00268 00269 if(!fwrite(layer, sizeof(CDataFileLayer), 1, f)) 00270 return 0; 00271 } 00272 00273 return 1; 00274 } 00275 00276 int cdf_read_open(CDataFile *cdf, const char *filename) 00277 { 00278 FILE *f; 00279 00280 f= fopen(filename, "rb"); 00281 if(!f) 00282 return 0; 00283 00284 cdf->readf= f; 00285 00286 if(!cdf_read_header(cdf)) { 00287 cdf_read_close(cdf); 00288 return 0; 00289 } 00290 00291 if(cdf->header.type != cdf->type) { 00292 cdf_read_close(cdf); 00293 return 0; 00294 } 00295 00296 return 1; 00297 } 00298 00299 int cdf_read_layer(CDataFile *cdf, CDataFileLayer *blay) 00300 { 00301 size_t offset; 00302 int a; 00303 00304 /* seek to right location in file */ 00305 offset= cdf->dataoffset; 00306 for(a=0; a<cdf->totlayer; a++) { 00307 if(&cdf->layer[a] == blay) 00308 break; 00309 else 00310 offset += cdf->layer[a].datasize; 00311 } 00312 00313 return (fseek(cdf->readf, offset, SEEK_SET) == 0); 00314 } 00315 00316 int cdf_read_data(CDataFile *cdf, unsigned int size, void *data) 00317 { 00318 float *fdata; 00319 unsigned int a; 00320 00321 /* read data */ 00322 if(!fread(data, size, 1, cdf->readf)) 00323 return 0; 00324 00325 /* switch endian if necessary */ 00326 if(cdf->switchendian) { 00327 fdata= data; 00328 00329 for(a=0; a<size/sizeof(float); a++) 00330 SWITCH_INT(fdata[a]) 00331 } 00332 00333 return 1; 00334 } 00335 00336 void cdf_read_close(CDataFile *cdf) 00337 { 00338 if(cdf->readf) { 00339 fclose(cdf->readf); 00340 cdf->readf= NULL; 00341 } 00342 } 00343 00344 int cdf_write_open(CDataFile *cdf, const char *filename) 00345 { 00346 CDataFileHeader *header; 00347 CDataFileImageHeader *image; 00348 CDataFileMeshHeader *mesh; 00349 FILE *f; 00350 00351 f= fopen(filename, "wb"); 00352 if(!f) 00353 return 0; 00354 00355 cdf->writef= f; 00356 00357 /* fill header */ 00358 header= &cdf->header; 00359 /* strcpy(, "BCDF"); // terminator out of range */ 00360 header->ID[0]= 'B'; header->ID[1]= 'C'; header->ID[2]= 'D'; header->ID[3]= 'F'; 00361 header->endian= cdf_endian(); 00362 header->version= CDF_VERSION; 00363 header->subversion= CDF_SUBVERSION; 00364 00365 header->structbytes= sizeof(CDataFileHeader); 00366 header->type= cdf->type; 00367 header->totlayer= cdf->totlayer; 00368 00369 if(cdf->type == CDF_TYPE_IMAGE) { 00370 /* fill image header */ 00371 image= &cdf->btype.image; 00372 image->structbytes= sizeof(CDataFileImageHeader); 00373 image->tile_size= CDF_TILE_SIZE; 00374 } 00375 else if(cdf->type == CDF_TYPE_MESH) { 00376 /* fill mesh header */ 00377 mesh= &cdf->btype.mesh; 00378 mesh->structbytes= sizeof(CDataFileMeshHeader); 00379 } 00380 00381 cdf_write_header(cdf); 00382 00383 return 1; 00384 } 00385 00386 int cdf_write_layer(CDataFile *UNUSED(cdf), CDataFileLayer *UNUSED(blay)) 00387 { 00388 return 1; 00389 } 00390 00391 int cdf_write_data(CDataFile *cdf, unsigned int size, void *data) 00392 { 00393 /* write data */ 00394 if(!fwrite(data, size, 1, cdf->writef)) 00395 return 0; 00396 00397 return 1; 00398 } 00399 00400 void cdf_write_close(CDataFile *cdf) 00401 { 00402 if(cdf->writef) { 00403 fclose(cdf->writef); 00404 cdf->writef= NULL; 00405 } 00406 } 00407 00408 void cdf_remove(const char *filename) 00409 { 00410 BLI_delete(filename, 0, 0); 00411 } 00412 00413 /********************************** Layers ***********************************/ 00414 00415 CDataFileLayer *cdf_layer_find(CDataFile *cdf, int type, const char *name) 00416 { 00417 CDataFileLayer *layer; 00418 int a; 00419 00420 for(a=0; a<cdf->totlayer; a++) { 00421 layer= &cdf->layer[a]; 00422 00423 if(layer->type == type && strcmp(layer->name, name) == 0) 00424 return layer; 00425 } 00426 00427 return NULL; 00428 } 00429 00430 CDataFileLayer *cdf_layer_add(CDataFile *cdf, int type, const char *name, size_t datasize) 00431 { 00432 CDataFileLayer *newlayer, *layer; 00433 00434 /* expand array */ 00435 newlayer= MEM_callocN(sizeof(CDataFileLayer)*(cdf->totlayer+1), "CDataFileLayer"); 00436 memcpy(newlayer, cdf->layer, sizeof(CDataFileLayer)*cdf->totlayer); 00437 cdf->layer= newlayer; 00438 00439 cdf->totlayer++; 00440 00441 /* fill in new layer */ 00442 layer= &cdf->layer[cdf->totlayer-1]; 00443 layer->structbytes= sizeof(CDataFileLayer); 00444 layer->datatype= CDF_DATA_FLOAT; 00445 layer->datasize= datasize; 00446 layer->type= type; 00447 BLI_strncpy(layer->name, name, CDF_LAYER_NAME_MAX); 00448 00449 return layer; 00450 } 00451