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