Blender V2.61 - r43446

customdata_file.c

Go to the documentation of this file.
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