Logo
  • Main Page
  • Related Pages
  • Modules
  • Classes
  • Files

mmstafffile.cpp

Go to the documentation of this file.
00001 /***************************************************************************
00002  *   Copyright (C) 2005-2007 Stefan Schwarzer, Jens Schneider,             *
00003  *                           Matthias Hardt, Guido Madaus                  *
00004  *                                                                         *
00005  *   Copyright (C) 2007-2008 BerLinux Solutions GbR                        *
00006  *                           Stefan Schwarzer & Guido Madaus               *
00007  *                                                                         *
00008  *   Copyright (C) 2009-2012 BerLinux Solutions GmbH                       *
00009  *                                                                         *
00010  *   Authors:                                                              *
00011  *      Stefan Schwarzer   <stefan.schwarzer@diskohq.org>,                 *
00012  *      Matthias Hardt     <matthias.hardt@diskohq.org>,                   *
00013  *      Jens Schneider     <jens.schneider@diskohq.org>,                   *
00014  *      Guido Madaus       <guido.madaus@diskohq.org>,                     *
00015  *      Patrick Helterhoff <patrick.helterhoff@diskohq.org>,               *
00016  *      René Bählkow       <rene.baehlkow@diskohq.org>                     *
00017  *                                                                         *
00018  *   This library is free software; you can redistribute it and/or         *
00019  *   modify it under the terms of the GNU Lesser General Public            *
00020  *   License version 2.1 as published by the Free Software Foundation.     *
00021  *                                                                         *
00022  *   This library is distributed in the hope that it will be useful,       *
00023  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
00024  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU     *
00025  *   Lesser General Public License for more details.                       *
00026  *                                                                         *
00027  *   You should have received a copy of the GNU Lesser General Public      *
00028  *   License along with this library; if not, write to the                 *
00029  *   Free Software Foundation, Inc.,                                       *
00030  *   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA            *
00031  **************************************************************************/
00032 
00033 #include "mmstools/mmstafffile.h"
00034 #include "mmstools/tools.h"
00035 #include <sys/types.h>
00036 #include <sys/stat.h>
00037 #include <unistd.h>
00038 #include <libxml/parser.h>
00039 #include <libxml/tree.h>
00040 #include <cstring>
00041 #include <iostream>
00042 
00043 #ifdef __HAVE_PNG__
00044 #include <png.h>
00045 #endif
00046 
00047 #ifdef __HAVE_JPEG__
00048 #include <csetjmp>
00049 extern "C" {
00050 #include <jpeglib.h>
00051 }
00052 #endif
00053 
00054 #ifdef __HAVE_TIFF__
00055 extern "C" {
00056 #include <tiffio.h>
00057 }
00058 #endif
00059 
00060 MMSTaffFile::MMSTaffFile(string taff_filename, TAFF_DESCRIPTION *taff_desc,
00061                          string external_filename, MMSTAFF_EXTERNAL_TYPE external_type,
00062                          bool ignore_blank_values, bool trace, bool print_warnings,
00063                          bool force_rewrite_taff, bool auto_rewrite_taff) {
00064     this->taff_filename = taff_filename;
00065     this->taff_desc = taff_desc;
00066     this->taff_buf = NULL;
00067     this->taff_buf_size = 0;
00068     this->taff_buf_pos = 0;
00069     this->loaded = false;
00070     this->correct_version = false;
00071     this->external_filename = external_filename;
00072     this->external_type = external_type;
00073     this->ignore_blank_values = ignore_blank_values;
00074     this->trace = trace;
00075     this->print_warnings = print_warnings;
00076     this->destination_pixelformat = MMSTAFF_PF_ARGB;
00077     this->destination_premultiplied = true;
00078     this->mirror_size = 0;
00079     this->rotate_180 = false;
00080     this->correct_version = false;
00081     this->current_tag = -1;
00082     this->current_tag_pos = 0;
00083 
00084     if (!this->taff_desc)
00085         if (this->external_type == MMSTAFF_EXTERNAL_TYPE_IMAGE)
00086             this->taff_desc = &mmstaff_image_taff_description;
00087 
00088     if ((this->taff_filename == "")&&(this->external_filename == ""))
00089         return;
00090 
00091     // read the file into taff_buf
00092     bool ret = false;
00093     if (!force_rewrite_taff)
00094         ret = readFile();
00095     if (!ret)
00096         // failed or rewrite, try to convert from external_filename
00097         if ((force_rewrite_taff)||(auto_rewrite_taff)) {
00098             if (convertExternal2TAFF()) {
00099                 if (this->taff_filename != "") {
00100                     // auto read in
00101                     readFile();
00102                 }
00103             }
00104         }
00105 }
00106 
00107 MMSTaffFile::~MMSTaffFile() {
00108     if (this->taff_buf)
00109         free(this->taff_buf);
00110 }
00111 
00112 bool MMSTaffFile::writeBuffer(MMSFile *mmsfile, void *ptr, size_t *ritems, size_t size, size_t nitems, bool *write_status) {
00113 
00114     if (mmsfile) {
00115         // writing to file
00116         if (!mmsfile->writeBuffer(ptr, ritems, size, nitems)) {
00117             // error while writing file
00118             printf("TAFF: Error while writing to file %s\n", mmsfile->getName().c_str());
00119             if (write_status) *write_status = false;
00120             return false;
00121         }
00122     }
00123     else {
00124         // writing to taff_buf
00125         memcpy(&this->taff_buf[taff_buf_pos], ptr, size * nitems);
00126         this->taff_buf_pos+= size * nitems;
00127 
00128         //TODO: check the taff_buf_size and realloc the buffer if taff_buf_size is to small
00129     }
00130 
00131     return true;
00132 }
00133 
00134 bool MMSTaffFile::postprocessImage(void **buf, int *width, int *height, int *pitch,
00135                                         int *size, bool *alphachannel) {
00136 
00137     // should i pre-multiply with alpha channel?
00138     if (this->destination_premultiplied && (*alphachannel == true)) {
00139         unsigned int *src = (unsigned int*)*buf;
00140         for (int i = *width * *height; i > 0; i--) {
00141             register unsigned int s = *src;
00142             register unsigned int sa = s >> 24;
00143             if (sa != 0xff)
00144                 // source alpha is > 0x00 and < 0xff
00145                 *src = ((((s & 0x00ff00ff) * sa) >> 8) & 0x00ff00ff) |
00146                        ((((s & 0x0000ff00) * sa) >> 8) & 0x0000ff00) |
00147                        ((((s & 0xff000000))));
00148             src++;
00149         }
00150     }
00151 
00152     // should create a mirror effect?
00153     if (this->mirror_size > 0) {
00154         // yes
00155         unsigned int *dst = (unsigned int*)*buf;
00156         dst+=*width * *height;
00157         unsigned int *src = dst - *width;
00158         unsigned int alpha = 170;
00159         unsigned int alphaX = 0x050 / this->mirror_size;
00160         if (0x050 % this->mirror_size >= (this->mirror_size >> 1))
00161             alphaX++;
00162         if (alphaX == 0) alphaX = 1;
00163         for (int i = 0; i < this->mirror_size; i++) {
00164             for (int j = 0; j < *width; j++) {
00165                 register unsigned int s = *src;
00166                 register unsigned int sa = s >> 24;
00167                 *dst = (s & 0x00ffffff) | (((sa > alpha)?(sa-alpha):0)<<24);
00168                 dst++;
00169                 src++;
00170             }
00171             src-=(*width) << 1;
00172             alpha+=alphaX;
00173         }
00174 
00175         // set new values
00176         *height = (*height) + this->mirror_size;
00177         *size = (*pitch) * (*height);
00178     }
00179 
00180     if (this->rotate_180) {
00181         // rotate the image by 180 degree
00182         rotateUIntBuffer180((unsigned int*)*buf, *pitch, *width, *height);
00183     }
00184 
00185     // have to convert the pixelformat?
00186     bool has_alpha = false;
00187     switch (this->destination_pixelformat) {
00188     case MMSTAFF_PF_ARGB:
00189         if (*alphachannel) {
00190             // no convertion, only have to check if we have really an alpha channel
00191             unsigned int *src = (unsigned int*)*buf;
00192             for (int i = *width * *height; i > 0; i--) {
00193                 register unsigned int s = *src;
00194                 s = s >> 24;
00195                 if (s != 0xff) has_alpha = true;
00196                 if (has_alpha) break;
00197                 src++;
00198             }
00199         }
00200         break;
00201     case MMSTAFF_PF_AiRGB: {
00202             // invert the alpha channel
00203             unsigned int *src = (unsigned int*)*buf;
00204             for (int i = *width * *height; i > 0; i--) {
00205                 register unsigned int s = *src;
00206                 register unsigned int a = s;
00207                 a = ~a;
00208                 a = a & 0xff000000;
00209                 if (a && !has_alpha) has_alpha = true;
00210                 s = s & 0x00ffffff;
00211                 s = s | a;
00212                 *src = s;
00213                 src++;
00214             }
00215         }
00216         break;
00217     case MMSTAFF_PF_AYUV: {
00218             // convert RGB to YUV color space
00219             unsigned int *src = (unsigned int*)*buf;
00220             for (int i = *width * *height; i > 0; i--) {
00221                 register unsigned int s = *src;
00222                 register int r = (s >> 16) & 0xff;
00223                 register int g = (s >> 8) & 0xff;
00224                 register int b = s  & 0xff;
00225                 if (!has_alpha)
00226                     if ((s >> 24) != 0xff) has_alpha = true;
00227                 s = s & 0xff000000;                                     //A
00228                 if (s) {
00229                     s = s | (((((66*r+129*g+25*b+128)>>8)+16) & 0xff) << 16);   //Y
00230                     s = s | (((((-38*r-74*g+112*b+128)>>8)+128) & 0xff) << 8);  //U (Cb)
00231                     s = s | ((((112*r-94*g-18*b+128)>>8)+128) & 0xff);          //V (Cr)
00232                 }
00233                 *src = s;
00234                 src++;
00235             }
00236         }
00237         break;
00238     case MMSTAFF_PF_ARGB4444: {
00239             // divide ARGB data into halves
00240             *pitch = (*pitch) >> 1;
00241             *size = (*size) >> 1;
00242             void *newbuf = malloc(*size);
00243             if (!newbuf) {
00244                 free(*buf);
00245                 *buf = NULL;
00246                 return false;
00247             }
00248 
00249             // convert it
00250             unsigned int *src = (unsigned int*)*buf;
00251             unsigned short int *dst = (unsigned short int*)newbuf;
00252             for (int i = *width * *height; i > 0; i--) {
00253                 register unsigned int s = *src;
00254                 register unsigned short int d;
00255                 if (!has_alpha)
00256                     if ((s >> 28) != 0x0f) has_alpha = true;
00257                 d =   ((s & 0xf0000000) >> 16)
00258                     | ((s & 0x00f00000) >> 12)
00259                     | ((s & 0x0000f000) >> 8)
00260                     | ((s & 0x000000f0) >> 4);
00261                 *dst = d;
00262                 src++;
00263                 dst++;
00264             }
00265 
00266             // switch buffers
00267             free(*buf);
00268             *buf = newbuf;
00269         }
00270         break;
00271     case MMSTAFF_PF_RGB16: {
00272             // convert into RGB16 format (remove alpha channel)
00273             *pitch = (*pitch) >> 1;
00274             *size = (*size) >> 1;
00275             void *newbuf = malloc(*size);
00276             if (!newbuf) {
00277                 free(*buf);
00278                 *buf = NULL;
00279                 return false;
00280             }
00281 
00282             // convert it
00283             unsigned int *src = (unsigned int*)*buf;
00284             unsigned short int *dst = (unsigned short int*)newbuf;
00285             for (int i = *width * *height; i > 0; i--) {
00286                 // get src
00287                 register unsigned int SRC = *src;
00288                 register unsigned int A = SRC >> 24;
00289                 register unsigned int SA= 0x100 - A;
00290                 register unsigned short int d;
00291 
00292                 // set background color to black
00293                 unsigned int r = 0;
00294                 unsigned int g = 0;
00295                 unsigned int b = 0;
00296 
00297                 // invert src alpha
00298                 r = SA * r;
00299                 g = SA * g;
00300                 b = (SA * b) >> 5;
00301 
00302                 // add src to dst
00303                 r += (A*(SRC & 0xf80000)) >> 19;
00304                 g += (A*(SRC & 0xfc00)) >> 5;
00305                 b += (A*(SRC & 0xf8)) >> 8;
00306                 d =   ((r & 0xffe000)   ? 0xf800 : ((r >> 8) << 11))
00307                     | ((g & 0xfff80000) ? 0x07e0 : ((g >> 13) << 5))
00308                     | ((b & 0xff00)     ? 0x1f   : (b >> 3));
00309                 *dst = d;
00310                 src++;
00311                 dst++;
00312             }
00313 
00314             // switch buffers
00315             free(*buf);
00316             *buf = newbuf;
00317         }
00318         break;
00319     case MMSTAFF_PF_ABGR: {
00320             // change the positions of red and blue
00321             // for example disko's ABGR is equal to GL_RGBA in OpenGL
00322             unsigned int *src = (unsigned int*)*buf;
00323             for (int i = *width * *height; i > 0; i--) {
00324                 register unsigned int s = *src;
00325                 register unsigned int rb = s & 0x00ff00ff;
00326                 if (!has_alpha)
00327                     if ((s >> 24) != 0xff) has_alpha = true;
00328                 s = s & 0xff00ff00;
00329                 s = s | (rb << 16);
00330                 s = s | (rb >> 16);
00331                 *src = s;
00332                 src++;
00333             }
00334         }
00335         break;
00336     default: break;
00337     }
00338 
00339     if (*alphachannel) {
00340         // per input parameter we assumed, that we have an alpha channel
00341         // here we overwrite it with the result from the previous check
00342         // so it can be, that we have an image with alpha channel but all alpha values are 0xff
00343         // in this case we mark the image with "no alpha channel"
00344         *alphachannel = has_alpha;
00345     }
00346 
00347     return true;
00348 }
00349 
00350 
00351 
00352 #ifdef __HAVE_PNG__
00353 // PNG callback function (read)
00354 // so we are able to read data with MMSFile class instead of standard FILE*
00355 void MMSTaff_read_png_data_callback(png_structp png_ptr, png_bytep data, png_size_t length) {
00356     MMSFile *file = (MMSFile *)png_get_io_ptr(png_ptr);
00357     size_t ritems;
00358     file->readBuffer((void *)data, &ritems, 1, length);
00359 }
00360 #endif
00361 
00362 
00363 
00364 bool MMSTaffFile::readPNG(const char *filename, void **buf, int *width, int *height, int *pitch,
00365                               int *size, bool *alphachannel) {
00366 #ifdef __HAVE_PNG__
00367     MMSFile         *file;
00368     char            png_sig[8];
00369     png_structp     png_ptr = NULL;
00370     png_infop       info_ptr = NULL;
00371     png_infop       end_info_ptr = NULL;
00372     png_bytep       *row_pointers = NULL;
00373 
00374     // check if file does exist and if it is an png format
00375     *buf = NULL;
00376     file = new MMSFile(filename);
00377     if (!file) {
00378         return false;
00379     }
00380     if (file->getLastError()) {
00381         return false;
00382     }
00383 
00384     size_t ritems = 0;
00385     if (file->readBuffer(png_sig, &ritems, 1, sizeof(png_sig))) {
00386         if (ritems != sizeof(png_sig)) {
00387             delete file;
00388             return false;
00389         }
00390     }
00391     else {
00392         delete file;
00393         return false;
00394     }
00395 
00396 #if PNG_LIBPNG_VER_MINOR == 2
00397     if (!png_check_sig((png_byte*)png_sig, sizeof(png_sig))) {
00398 #else
00399     if (png_sig_cmp((png_byte*)png_sig, 0, sizeof(png_sig)) != 0) {
00400 #endif
00401         delete file;
00402         return false;
00403     }
00404 
00405 
00406     // init png structs and abend handler
00407     png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
00408     if (!png_ptr) {
00409         delete file;
00410         return false;
00411     }
00412     png_set_sig_bytes(png_ptr, sizeof(png_sig));
00413 
00414     // set read callback function
00415     png_set_read_fn(png_ptr, file, MMSTaff_read_png_data_callback);
00416 
00417     if(setjmp(png_jmpbuf(png_ptr))) {
00418         // abend from libpng
00419         printf("png read error\n");
00420         png_destroy_read_struct(&png_ptr, (info_ptr)?&info_ptr:NULL, (end_info_ptr)?&end_info_ptr:NULL);
00421         if (row_pointers) free(row_pointers);
00422         if (*buf) free(*buf);
00423         *buf = NULL;
00424         delete file;
00425         return false;
00426     }
00427 
00428     info_ptr = png_create_info_struct(png_ptr);
00429     if (!info_ptr) {
00430         png_destroy_read_struct(&png_ptr, NULL, NULL);
00431         delete file;
00432         return false;
00433     }
00434 
00435     end_info_ptr = png_create_info_struct(png_ptr);
00436     if (!end_info_ptr) {
00437         png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
00438         delete file;
00439         return false;
00440     }
00441 
00442     // read png infos
00443     png_read_info(png_ptr, info_ptr);
00444     png_uint_32 w;
00445     png_uint_32 h;
00446     int bit_depth;
00447     int color_type;
00448     png_get_IHDR(png_ptr, info_ptr, &w, &h, &bit_depth, &color_type, NULL, NULL, NULL);
00449 
00450     // check the png format
00451     if ((bit_depth != 8 && bit_depth != 16)
00452         || (color_type != PNG_COLOR_TYPE_PALETTE && color_type != PNG_COLOR_TYPE_GRAY
00453             && color_type != PNG_COLOR_TYPE_RGB && color_type != PNG_COLOR_TYPE_RGB_ALPHA)) {
00454         // format not supported
00455         png_destroy_read_struct(&png_ptr, &info_ptr, &end_info_ptr);
00456         delete file;
00457         return false;
00458     }
00459 
00460     // set input transformations
00461     if (bit_depth == 16) {
00462         // strip to 8 bit channels
00463         png_set_strip_16(png_ptr);
00464     }
00465     png_set_filler(png_ptr, 0xFF, PNG_FILLER_AFTER);
00466 
00467 #if __BYTE_ORDER == __BIG_ENDIAN
00468     png_set_swap_alpha(png_ptr);
00469 #else
00470     png_set_bgr(png_ptr);
00471 #endif
00472 
00473     png_set_interlace_handling(png_ptr);
00474     if (color_type == PNG_COLOR_TYPE_PALETTE) {
00475         // convert palette to rgb data
00476         png_set_palette_to_rgb(png_ptr);
00477     }
00478     if (color_type == PNG_COLOR_TYPE_GRAY) {
00479         // convert grayscale to rgb data
00480         png_set_gray_to_rgb(png_ptr);
00481     }
00482 
00483     *alphachannel = true;
00484     if (color_type != PNG_COLOR_TYPE_RGB_ALPHA && color_type != PNG_COLOR_TYPE_GRAY_ALPHA) {
00485         // image has no alpha channel, add alpha channel 0xff
00486         *alphachannel = false;
00487         png_set_add_alpha(png_ptr, 0xff, PNG_FILLER_AFTER);
00488     }
00489 
00490     png_read_update_info(png_ptr, info_ptr);
00491 
00492     // allocate memory for row pointers
00493     *width = w;
00494     *height = h;
00495     *pitch = 4 * w;
00496     *size = *pitch * h;
00497     row_pointers = (png_bytep*)malloc(*height * sizeof(png_bytep));
00498     if (!row_pointers) {
00499         png_destroy_read_struct(&png_ptr, &info_ptr, &end_info_ptr);
00500         delete file;
00501         return false;
00502     }
00503 
00504     // allocate memory for image data
00505     if (this->mirror_size > *height) this->mirror_size = *height;
00506     *buf = malloc((*size) + (*pitch) * this->mirror_size);
00507     if (!*buf) {
00508         png_destroy_read_struct(&png_ptr, &info_ptr, &end_info_ptr);
00509         free(row_pointers);
00510         delete file;
00511         return false;
00512     }
00513     char *b = (char*)*buf;
00514     for (int i = 0; i < *height; i++) {
00515         row_pointers[i]=(png_byte*)b;
00516         b+=*pitch;
00517     }
00518 
00519     // read the image data
00520     png_read_image(png_ptr, row_pointers);
00521     png_read_end(png_ptr, end_info_ptr);
00522 
00523     // all right, freeing helpers
00524     png_destroy_read_struct(&png_ptr, &info_ptr, &end_info_ptr);
00525     free(row_pointers);
00526     delete file;
00527 
00528     // at this point we have ARGB (MMSTAFF_PF_ARGB) pixels ********
00529     // so check now if i have to convert it
00530 
00531     // create mirror, rotate and convert to target pixelformat
00532     return postprocessImage(buf, width, height, pitch, size, alphachannel);
00533 #else
00534     return false;
00535 #endif
00536 }
00537 
00538 
00539 
00540 #ifdef __HAVE_JPEG__
00541 struct JPEGErrorManager {
00542   struct jpeg_error_mgr pub;            /**< "public" fields        */
00543   jmp_buf               setjmpBuffer;   /**< for return to caller   */
00544 };
00545 
00546 METHODDEF(void) JPEGErrorExit(j_common_ptr cinfo) {
00547     /* cinfo->err really points to a my_error_mgr struct, so coerce pointer */
00548     struct JPEGErrorManager *myerr = (struct JPEGErrorManager*)cinfo->err;
00549 
00550     /* Always display the message. */
00551     /* We could postpone this until after returning, if we chose. */
00552     (*cinfo->err->output_message)(cinfo);
00553 
00554     /* Return control to the setjmp point */
00555     longjmp(myerr->setjmpBuffer, 1);
00556 }
00557 #endif
00558 
00559 bool MMSTaffFile::readJPEG(const char *filename, void **buf, int *width, int *height, int *pitch,
00560                                 int *size, bool *alphachannel) {
00561 #ifdef __HAVE_JPEG__
00562     struct jpeg_decompress_struct   cinfo;
00563     struct JPEGErrorManager         jerr;
00564     FILE                            *fp;
00565     JSAMPARRAY                      rowBuf;     /**< Output row buffer */
00566     int                             rowStride;  /**< physical row width in output buffer */
00567 
00568     if((fp = fopen(filename, "rb")) == NULL) {
00569         return false;
00570     }
00571 
00572     cinfo.err = jpeg_std_error(&jerr.pub);
00573     jerr.pub.error_exit = JPEGErrorExit;
00574     if(setjmp(jerr.setjmpBuffer)) {
00575         jpeg_destroy_decompress(&cinfo);
00576         fclose(fp);
00577         return false;
00578     }
00579     jpeg_create_decompress(&cinfo);
00580     jpeg_stdio_src(&cinfo, fp);
00581 
00582     if(jpeg_read_header(&cinfo, TRUE) != JPEG_HEADER_OK) {
00583         fclose(fp);
00584         return false;
00585     }
00586 
00587     /* dimension filled by jpeg_read_header() */
00588     *width  = (int)cinfo.image_width;
00589     *height = (int)cinfo.image_height;
00590     *pitch  = *width * 4;
00591     *size   = *pitch * *height;
00592 
00593     // jpeg generally has no alpha channel
00594     *alphachannel = false;
00595 
00596     /* setting decompression parameters */
00597     cinfo.out_color_space = JCS_RGB;    /**< setting output colorspace to RGB */
00598 
00599     /* start decompression */
00600     jpeg_start_decompress(&cinfo);
00601 
00602     rowStride = cinfo.output_width * cinfo.output_components;
00603     rowBuf = (*cinfo.mem->alloc_sarray)((j_common_ptr)&cinfo, JPOOL_IMAGE, rowStride, 1);
00604 
00605     /* allocate memory for ARGB output */
00606     if(this->mirror_size > *height) this->mirror_size = *height;
00607     *buf = malloc((*size) + (*pitch) * this->mirror_size);
00608     if(!*buf) {
00609         jpeg_finish_decompress(&cinfo);
00610         jpeg_destroy_decompress(&cinfo);
00611         fclose(fp);
00612         return false;
00613     }
00614 
00615     unsigned int *src = (unsigned int*)*buf;
00616     while(cinfo.output_scanline < cinfo.output_height) {
00617         jpeg_read_scanlines(&cinfo, rowBuf, 1);
00618         unsigned char *b = *rowBuf;
00619         for(unsigned int i = 0; i < cinfo.output_width; ++i) {
00620             *src = 0xff000000 + (b[0] << 16) + (b[1] << 8) + b[2];
00621             b += 3;
00622             src++;
00623         }
00624     }
00625 
00626     jpeg_finish_decompress(&cinfo);
00627     jpeg_destroy_decompress(&cinfo);
00628     fclose(fp);
00629 
00630     /* create mirror, rotate and convert to target pixelformat */
00631     return postprocessImage(buf, width, height, pitch, size, alphachannel);
00632 #else
00633     return false;
00634 #endif
00635 }
00636 
00637 bool MMSTaffFile::readTIFF(const char *filename, void **buf, int *width, int *height, int *pitch,
00638                                 int *size, bool *alphachannel) {
00639 #ifdef __HAVE_TIFF__
00640     TIFF* tiff;
00641 
00642     if((tiff = TIFFOpen(filename, "rb")) == NULL) {
00643         return false;
00644     }
00645 
00646     TIFFGetField(tiff, TIFFTAG_IMAGEWIDTH, width);
00647     TIFFGetField(tiff, TIFFTAG_IMAGELENGTH, height);
00648     *pitch  = *width * 4;
00649     *size   = *pitch * *height;
00650 
00651     // we assume that we have an alpha channel
00652     *alphachannel = true;
00653 
00654     /* allocate memory for ARGB output */
00655     if(this->mirror_size > *height) this->mirror_size = *height;
00656     //*buf = (unsigned int*)_TIFFmalloc((*size) + (*pitch) * this->mirror_size);
00657     *buf = malloc((*size) + (*pitch) * this->mirror_size);
00658     if(!*buf) {
00659         TIFFClose(tiff);
00660         return false;
00661     }
00662 
00663     if(TIFFReadRGBAImageOriented(tiff, *width, *height, (uint32*)*buf, ORIENTATION_TOPLEFT, 0) == 0) {
00664         TIFFClose(tiff);
00665         return false;
00666     }
00667 
00668     /* convert from BGRA to ARGB */
00669     unsigned int *src = (unsigned int*)*buf;
00670     unsigned int nPixels = *width * *height;
00671     for(unsigned int i = 0; i < nPixels; ++i) {
00672         register unsigned int s = (*src ^ (*src >> 16)) & 0xff;
00673         *src = *src ^ (s | (s << 16));
00674         src++;
00675     }
00676 
00677     //_TIFFfree(*buf);
00678     TIFFClose(tiff);
00679 
00680     /* create mirror, rotate and convert to target pixelformat */
00681     return postprocessImage(buf, width, height, pitch, size, alphachannel);
00682 #else
00683     return false;
00684 #endif
00685 }
00686 
00687 
00688 bool MMSTaffFile::convertString2TaffAttributeType(TAFF_ATTRTYPE attrType, char *attrValStr, bool *attrValStr_valid,
00689                                 bool *int_val_set, bool *byte_val_set, int *int_val,
00690                                 const char *attrname, int attrid, const char *nodename, int nodeline) {
00691     xmlChar *attrVal = (xmlChar *)attrValStr;
00692     if (!attrValStr) return false;
00693     if (!attrValStr_valid) return false;
00694     *attrValStr_valid = true;
00695     if (int_val_set)  *int_val_set = false;
00696     if (byte_val_set) *byte_val_set = false;
00697 
00698     bool check_ok = true;
00699 
00700 
00701     string validvals = "";
00702     bool badval = false;
00703     switch (attrType) {
00704     case TAFF_ATTRTYPE_NONE:
00705     case TAFF_ATTRTYPE_STRING:
00706     case TAFF_ATTRTYPE_BINDATA:
00707         break;
00708 
00709     case TAFF_ATTRTYPE_NE_STRING:
00710         badval = (!*attrVal);
00711         if (badval) {
00712             validvals = "any characters, but not empty";
00713             check_ok = false;
00714         }
00715         break;
00716 
00717     case TAFF_ATTRTYPE_BOOL:
00718         if (!byte_val_set || !int_val) return false;
00719         badval = ((xmlStrcmp(attrVal, (xmlChar *)"true"))&&(xmlStrcmp(attrVal, (xmlChar *)"false")));
00720         if (badval) {
00721             validvals = "\"true\", \"false\"";
00722             check_ok = false;
00723         }
00724         else {
00725             *byte_val_set = true;
00726             if (xmlStrcmp(attrVal, (xmlChar *)"true")==0)
00727                 *int_val = 0xff;
00728             else
00729                 *int_val = 0;
00730         }
00731         break;
00732 
00733     case TAFF_ATTRTYPE_UCHAR:
00734     case TAFF_ATTRTYPE_UCHAR100:
00735         if (!byte_val_set || !int_val) return false;
00736         badval = ((xmlStrlen(attrVal) < 1)||(xmlStrlen(attrVal) > 3));
00737         if (!badval) {
00738             char iv[3+1];
00739             *int_val = atoi((char*)attrVal);
00740             sprintf(iv, "%d", *int_val);
00741             badval = (xmlStrcmp(attrVal, (xmlChar *)iv));
00742             if (!badval) {
00743                 if (attrType == TAFF_ATTRTYPE_UCHAR100)
00744                     badval = (*int_val<0||*int_val>100);
00745                 else
00746                     badval = (*int_val<0||*int_val>255);
00747             }
00748             *byte_val_set = !badval;
00749         }
00750         if (badval) {
00751             if (attrType == TAFF_ATTRTYPE_UCHAR100)
00752                 validvals = "\"0\"..\"100\"";
00753             else
00754                 validvals = "\"0\"..\"255\"";
00755             check_ok = false;
00756         }
00757         break;
00758 
00759     case TAFF_ATTRTYPE_INT:
00760         if (!int_val_set || !int_val) return false;
00761         char iv[11+1];
00762         *int_val = atoi((char*)attrVal);
00763         sprintf(iv, "%d", *int_val);
00764         badval = (xmlStrcmp(attrVal, (xmlChar *)iv));
00765         *int_val_set = !badval;
00766         if (badval) {
00767             validvals = "\"-2147483648\"..\"2147483647\"";
00768             check_ok = false;
00769         }
00770         break;
00771 
00772     case TAFF_ATTRTYPE_STATE:
00773         if (!byte_val_set || !int_val) return false;
00774         badval = ((xmlStrcmp(attrVal, (xmlChar *)"true"))&&(xmlStrcmp(attrVal, (xmlChar *)"false"))
00775                 &&(xmlStrcmp(attrVal, (xmlChar *)"auto")));
00776         if (badval) {
00777             validvals = "\"true\", \"false\", \"auto\"";
00778             check_ok = false;
00779         }
00780         else {
00781             *byte_val_set = true;
00782             if (xmlStrcmp(attrVal, (xmlChar *)"true")==0)
00783                 *int_val = 0xff;
00784             else
00785             if (xmlStrcmp(attrVal, (xmlChar *)"auto")==0)
00786                 *int_val = 0x01;
00787             else
00788                 *int_val = 0;
00789         }
00790         break;
00791 
00792     case TAFF_ATTRTYPE_SEQUENCE_MODE: {
00793         if (!byte_val_set || !int_val) return false;
00794         bool sm_true            = !xmlStrcmp(attrVal, (xmlChar *)"true");
00795         bool sm_false           = !xmlStrcmp(attrVal, (xmlChar *)"false");
00796         bool sm_linear          = !xmlStrcmp(attrVal, (xmlChar *)"linear");
00797         bool sm_log             = !xmlStrcmp(attrVal, (xmlChar *)"log");
00798         bool sm_log_soft_start  = !xmlStrcmp(attrVal, (xmlChar *)"log_soft_start");
00799         bool sm_log_soft_end    = !xmlStrcmp(attrVal, (xmlChar *)"log_soft_end");
00800         badval = (!sm_true && !sm_false && !sm_linear && !sm_log && !sm_log_soft_start && !sm_log_soft_end);
00801         if (badval) {
00802             validvals = "\"true\", \"false\", \"linear\", \"log\", \"log_soft_start\", \"log_soft_end\"";
00803             check_ok = false;
00804         }
00805         else {
00806             *byte_val_set = true;
00807             if (sm_true)
00808                 *int_val = 0xff;
00809             else
00810             if (sm_linear)
00811                 *int_val = 0x01;
00812             else
00813             if (sm_log)
00814                 *int_val = 0x02;
00815             else
00816             if (sm_log_soft_start)
00817                 *int_val = 0x03;
00818             else
00819             if (sm_log_soft_end)
00820                 *int_val = 0x04;
00821             else
00822                 *int_val = 0;
00823         }
00824         }
00825         break;
00826 
00827     case TAFF_ATTRTYPE_COLOR:
00828         if (!int_val_set || !int_val) return false;
00829         MMSFBColor color;
00830         badval = (!getMMSFBColorFromString((const char*)attrVal, &color));
00831         if (badval) {
00832             validvals = "argb values in hex format, syntax: \"#rrggbbaa\"";
00833             check_ok = false;
00834         }
00835         else {
00836             *int_val_set = true;
00837             *int_val = (int)color.getARGB();
00838         }
00839         break;
00840     }
00841 
00842     // check if the value is blank and i have to ignore it
00843     if (this->ignore_blank_values) {
00844         if (!*attrVal) {
00845             *attrValStr_valid = false;
00846             if (int_val_set)  *int_val_set = false;
00847             if (byte_val_set) *byte_val_set = false;
00848             return true;
00849         }
00850     }
00851 
00852     if (!check_ok) {
00853         printf("Error: Value \"%s\" is invalid for the attribute \"%s\" of tag \"%s\", line %d of file %s\n       valid values: %s\n",
00854                         attrVal, (attrname)?attrname:"?", (nodename)?nodename:"?", nodeline, external_filename.c_str(), validvals.c_str());
00855         *attrValStr_valid = false;
00856         if (int_val_set)  *int_val_set = false;
00857         if (byte_val_set) *byte_val_set = false;
00858         return false;
00859     }
00860 
00861     // all right
00862     if (this->trace)
00863         printf(" Attribute \"%s\" found, ID=%d, value=\"%s\"\n", (attrname)?attrname:"?", attrid, attrVal);
00864 
00865     return true;
00866 }
00867 
00868 
00869 bool MMSTaffFile::convertXML2TAFF_throughDoc(int depth, void *void_node, MMSFile *taff_file) {
00870 
00871     bool wok = true;
00872     xmlNode *node = (xmlNode*) void_node;
00873     xmlNode *cur_node;
00874     if (depth==0)
00875         /* work with root */
00876         cur_node = node;
00877     else
00878         /* iterate through childs */
00879         cur_node = node->children;
00880 
00881     while (cur_node) {
00882 
00883         int tagid = 0;
00884         bool tag_found = false;
00885 
00886         while (this->taff_desc->tagtable[tagid].name) {
00887             if (xmlStrcmp(cur_node->name, (const xmlChar *)this->taff_desc->tagtable[tagid].name)==0) {
00888                 /* tag found in XML and tagtable, check the type? */
00889                 if (this->taff_desc->tagtable[tagid].typeattr)
00890                 {
00891                     /* searching the typeattr and type */
00892                     for (xmlAttr *cur_attr = cur_node->properties; cur_attr; cur_attr = cur_attr->next) {
00893                         if (xmlStrcmp(cur_attr->name, (const xmlChar *)this->taff_desc->tagtable[tagid].typeattr)==0) {
00894                             xmlChar *attrVal = xmlGetProp(cur_node, cur_attr->name);
00895                             if (attrVal) {
00896                                 if (xmlStrcmp(attrVal, (const xmlChar *)this->taff_desc->tagtable[tagid].type)==0) {
00897                                     tag_found = true;
00898                                     break;
00899                                 }
00900                                 xmlFree(attrVal);
00901                             }
00902                         }
00903                     }
00904                 }
00905                 else
00906                     tag_found = true;
00907 
00908                 if (tag_found)
00909                     break;
00910             }
00911             tagid++;
00912         }
00913 
00914         if (tag_found) {
00915 
00916             if (this->trace)
00917                 printf("Tag \"%s\" found, ID=%d\n", cur_node->name, tagid);
00918 
00919             /* writing the new tag */
00920             if (taff_file) {
00921                 size_t ritems;
00922                 unsigned char wb[2];
00923                 wb[0]=MMSTAFF_TAGTABLE_TYPE_TAG;
00924                 wb[1]=(unsigned char)tagid;
00925                 writeBuffer(taff_file, wb, &ritems, 1, 2, &wok);
00926             }
00927 
00928             /* get variables */
00929             for (xmlAttr *cur_attr = cur_node->properties; cur_attr; cur_attr = cur_attr->next) {
00930 
00931                 int attrid = 0;
00932                 TAFF_ATTRDESC *attr = this->taff_desc->tagtable[tagid].attr;
00933                 bool attr_found = false;
00934 
00935                 if (!attr) continue;
00936 
00937                 xmlChar *attrVal = xmlGetProp(cur_node, cur_attr->name);
00938                 if (!attrVal) continue;
00939 
00940                 while (attr[attrid].name)
00941                 {
00942                     if (xmlStrcmp(cur_attr->name, (const xmlChar *)attr[attrid].name)==0) {
00943                         attr_found = true;
00944                         break;
00945                     }
00946                     attrid++;
00947                 }
00948 
00949                 if (attr_found) {
00950 
00951                     // now check the type of the variable
00952                     bool attrValStr_valid;
00953                     bool int_val_set;
00954                     bool byte_val_set;
00955                     int  int_val;
00956 
00957                     if (!convertString2TaffAttributeType(attr[attrid].type, (char *)attrVal, &attrValStr_valid,
00958                                                     &int_val_set, &byte_val_set, &int_val,
00959                                                     (const char *)cur_attr->name, attrid,
00960                                                     (const char *)cur_node->name, cur_node->line)) {
00961                         // check failed
00962                         return false;
00963                     }
00964 
00965                     if (!attrValStr_valid && !int_val_set && !byte_val_set) {
00966                         // no values to process
00967                         continue;
00968                     }
00969 
00970 
00971                     // attribute value is determined, write it now
00972                     if (taff_file) {
00973                         if (!int_val_set && !byte_val_set) {
00974                             /* get the length of the value INCLUDING the 0x00 because of fast read & parse of the TAFF */
00975                             int attrvallen = xmlStrlen(attrVal) + 1;
00976 
00977                             size_t ritems;
00978                             unsigned char wb[3];
00979                             wb[0]=MMSTAFF_TAGTABLE_TYPE_ATTR;
00980                             wb[1]=(unsigned char)attrid;
00981                             if (attrvallen >= 0xff) {
00982                                 /* in this case set 0xff as mark and append the full integer */
00983                                 wb[2]=0xff;
00984                                 writeBuffer(taff_file, wb, &ritems, 1, 3, &wok);
00985                                 writeBuffer(taff_file, &attrvallen, &ritems, 1, sizeof(int), &wok);
00986                             }
00987                             else {
00988                                 /* in this case write only one byte length */
00989                                 wb[2]=(unsigned char)attrvallen;
00990                                 writeBuffer(taff_file, wb, &ritems, 1, 3, &wok);
00991                             }
00992                             writeBuffer(taff_file, attrVal, &ritems, 1, attrvallen, &wok);
00993                         }
00994                         else
00995                         if (int_val_set) {
00996                             // writing value as INTEGER
00997                             size_t ritems;
00998                             unsigned char wb[3];
00999                             wb[0]=MMSTAFF_TAGTABLE_TYPE_ATTR;
01000                             wb[1]=(unsigned char)attrid;
01001                             wb[2]=sizeof(int);
01002                             writeBuffer(taff_file, wb, &ritems, 1, 3, &wok);
01003                             writeBuffer(taff_file, &int_val, &ritems, 1, sizeof(int), &wok);
01004                         }
01005                         else {
01006                             // writing value as single BYTE
01007                             size_t ritems;
01008                             unsigned char wb[3];
01009                             wb[0]=MMSTAFF_TAGTABLE_TYPE_ATTR;
01010                             wb[1]=(unsigned char)attrid;
01011                             wb[2]=sizeof(char);
01012                             writeBuffer(taff_file, wb, &ritems, 1, 3, &wok);
01013                             unsigned char byte_val = int_val;
01014                             writeBuffer(taff_file, &byte_val, &ritems, 1, sizeof(char), &wok);
01015                         }
01016                     }
01017                 }
01018                 else {
01019                     /* attribute is not defined, so we cannot found an ID of it */
01020                     /* we store it with ID 0xff and its real name */
01021                     if (this->trace)
01022                         printf(" Attribute \"%s\" found without ID, value=\"%s\"\n", cur_attr->name, attrVal);
01023 
01024                     if (this->print_warnings)
01025                         printf("Warning: Attribute \"%s\" is not defined for tag \"%s\", line %d of file %s\n         We store it with the real name.\n",
01026                                 cur_attr->name, cur_node->name, cur_node->line, external_filename.c_str());
01027 
01028                     /* write attribute value */
01029                     if (taff_file) {
01030                         /* get the length of the value INCLUDING the 0x00 because of fast read & parse of the TAFF */
01031                         int attrnamlen = xmlStrlen(cur_attr->name) + 1;
01032                         int attrvallen = xmlStrlen(attrVal) + 1;
01033 
01034                         size_t ritems;
01035                         unsigned char wb[3];
01036                         wb[0]=MMSTAFF_TAGTABLE_TYPE_ATTR;
01037                         wb[1]=MMSTAFF_ATTR_WITHOUT_ID;
01038                         writeBuffer(taff_file, wb, &ritems, 1, 2, &wok);
01039                         writeBuffer(taff_file, &attrnamlen, &ritems, 1, sizeof(int), &wok);
01040                         writeBuffer(taff_file, (char*)cur_attr->name, &ritems, 1, attrnamlen, &wok);
01041                         if (attrvallen >= 0xff) {
01042                             /* in this case set 0xff as mark and append the full integer */
01043                             wb[0]=0xff;
01044                             writeBuffer(taff_file, wb, &ritems, 1, 1, &wok);
01045                             writeBuffer(taff_file, &attrvallen, &ritems, 1, sizeof(int), &wok);
01046                         }
01047                         else {
01048                             /* in this case write only one byte length */
01049                             wb[0]=(unsigned char)attrvallen;
01050                             writeBuffer(taff_file, wb, &ritems, 1, 1, &wok);
01051                         }
01052                         writeBuffer(taff_file, attrVal, &ritems, 1, attrvallen, &wok);
01053                     }
01054                 }
01055 
01056                 xmlFree(attrVal);
01057             }
01058 
01059             /* call recursive to find childs */
01060             if (!convertXML2TAFF_throughDoc(depth+1, cur_node, taff_file))
01061                 return false;
01062 
01063             /* writing the close tag */
01064             if (taff_file) {
01065                 size_t ritems;
01066                 unsigned char wb[2];
01067                 wb[0]=MMSTAFF_TAGTABLE_TYPE_CLOSETAG;
01068                 wb[1]=(unsigned char)tagid;
01069                 writeBuffer(taff_file, wb, &ritems, 1, 2, &wok);
01070             }
01071         }
01072         else {
01073             if (xmlStrcmp(cur_node->name, (const xmlChar *)"text")&&xmlStrcmp(cur_node->name, (const xmlChar *)"comment")) {
01074                 printf("Error: Tag \"%s\" is not defined, line %d of file %s\n", cur_node->name, cur_node->line, external_filename.c_str());
01075                 return false;
01076             }
01077         }
01078 
01079         if (depth==0)
01080             break;
01081         else
01082             cur_node = cur_node->next;
01083     }
01084 
01085     // return with write status
01086     return wok;
01087 }
01088 
01089 bool MMSTaffFile::convertXML2TAFF() {
01090 
01091     bool   rc = false;
01092     xmlDoc *parser = NULL;
01093 
01094     LIBXML_TEST_VERSION
01095 
01096     /* check input parameters */
01097     if (!this->taff_desc || this->external_filename.empty()) {
01098         return false;
01099     }
01100 
01101     /* read the XML file */
01102     parser = xmlReadFile(this->external_filename.c_str(),
01103             NULL,
01104             XML_PARSE_PEDANTIC |
01105             XML_PARSE_NOBLANKS | XML_PARSE_NONET | XML_PARSE_NODICT |
01106             XML_PARSE_NOXINCNODE
01107 #if LIBXML_VERSION >= 20700
01108             | XML_PARSE_NOBASEFIX
01109 #endif
01110             );
01111 
01112     if (parser) {
01113 
01114         /* open binary destination file */
01115         MMSFile *taff_file = NULL;
01116         if (this->taff_filename!="") {
01117             taff_file = new MMSFile(this->taff_filename.c_str(), MMSFM_WRITE);
01118             size_t ritems;
01119             bool wok = true;
01120             writeBuffer(taff_file, (void*)TAFF_IDENT, &ritems, 1, strlen(TAFF_IDENT), &wok);
01121             writeBuffer(taff_file, &(this->taff_desc->type), &ritems, 1, sizeof(this->taff_desc->type), &wok);
01122             writeBuffer(taff_file, &(this->taff_desc->version), &ritems, 1, sizeof(this->taff_desc->version), &wok);
01123             if (!wok) {
01124                 // write error, close file and free
01125                 delete taff_file;
01126                 xmlFreeDoc(parser);
01127 
01128                 // reset the file
01129                 taff_file = new MMSFile(this->taff_filename.c_str(), MMSFM_WRITE);
01130                 if (taff_file) delete taff_file;
01131 
01132                 return false;
01133             }
01134         }
01135 
01136         // get the first element
01137         xmlNode* node = xmlDocGetRootElement(parser);
01138 
01139         // through the doc
01140         rc = convertXML2TAFF_throughDoc(0, node, taff_file);
01141 
01142         // close file and free
01143         if (taff_file)
01144             delete taff_file;
01145         xmlFreeDoc(parser);
01146 
01147         if (!rc) {
01148             // failed, reset the file
01149             taff_file = new MMSFile(this->taff_filename.c_str(), MMSFM_WRITE);
01150             if (taff_file) delete taff_file;
01151         }
01152     }
01153     else {
01154         printf("Error: cannot read external file %s\n", this->external_filename.c_str());
01155     }
01156 
01157     return rc;
01158 }
01159 
01160 bool MMSTaffFile::convertIMAGE2TAFF() {
01161     bool    rc = false;
01162     void    *imgBuf;
01163     int     imgWidth;
01164     int     imgHeight;
01165     int     imgPitch;
01166     int     imgSize;
01167     bool    imgAlphaChannel;
01168 
01169     /* check input parameters */
01170     if (!this->taff_desc || this->external_filename.empty()) {
01171         return false;
01172     }
01173 
01174     /* check file extension (if this fails try readPNG() and/or readJPEG() and/or readTIFF()) */
01175     if(strToUpr(this->external_filename).rfind(".PNG") == this->external_filename.size() - 4) {
01176 #ifdef __HAVE_PNG__
01177         rc = readPNG(this->external_filename.c_str(), &imgBuf, &imgWidth, &imgHeight, &imgPitch, &imgSize, &imgAlphaChannel);
01178 #else
01179         cout << "Disko was built without PNG support: skipping " << this->external_filename << endl;
01180         return false;
01181 #endif
01182     } else if((strToUpr(this->external_filename).rfind(".JPG") == this->external_filename.size() - 4) ||
01183               (strToUpr(this->external_filename).rfind(".JPEG") == this->external_filename.size() - 5)) {
01184 #ifdef __HAVE_JPEG__
01185         rc = readJPEG(this->external_filename.c_str(), &imgBuf, &imgWidth, &imgHeight, &imgPitch, &imgSize, &imgAlphaChannel);
01186 #else
01187         cout << "Disko was built without JPEG support: skipping " << this->external_filename << endl;
01188         return false;
01189 #endif
01190     } else if((strToUpr(this->external_filename).rfind(".TIF") == this->external_filename.size() - 4) ||
01191               (strToUpr(this->external_filename).rfind(".TIFF") == this->external_filename.size() - 5)) {
01192 #ifdef __HAVE_TIFF__
01193         rc = readTIFF(this->external_filename.c_str(), &imgBuf, &imgWidth, &imgHeight, &imgPitch, &imgSize, &imgAlphaChannel);
01194 #else
01195         cout << "Disko was built without TIFF support: skipping " << this->external_filename << endl;
01196         return false;
01197 #endif
01198     } else {
01199 #ifdef __HAVE_PNG__
01200         rc = readPNG(this->external_filename.c_str(), &imgBuf, &imgWidth, &imgHeight, &imgPitch, &imgSize, &imgAlphaChannel);
01201 #endif
01202 #ifdef __HAVE_JPEG__
01203         if(!rc) {
01204             rc = readJPEG(this->external_filename.c_str(), &imgBuf, &imgWidth, &imgHeight, &imgPitch, &imgSize, &imgAlphaChannel);
01205         }
01206 #endif
01207 #ifdef __HAVE_TIFF__
01208         if(!rc) {
01209             rc = readTIFF(this->external_filename.c_str(), &imgBuf, &imgWidth, &imgHeight, &imgPitch, &imgSize, &imgAlphaChannel);
01210         }
01211 #endif
01212     }
01213 
01214     if(rc) {
01215         // open binary destination file
01216         MMSFile *taff_file = NULL;
01217         bool wok = true;
01218         size_t ritems;
01219         if (!this->taff_filename.empty()) {
01220             taff_file = new MMSFile(this->taff_filename.c_str(), MMSFM_WRITE);
01221             writeBuffer(taff_file, (void*)TAFF_IDENT, &ritems, 1, strlen(TAFF_IDENT), &wok);
01222         }
01223 
01224         if (!taff_file) {
01225             // no regular file, so setup the buffer so that we have not to resize it
01226             this->taff_buf_size = imgSize + 256;
01227             this->taff_buf_pos = 0;
01228             if (this->taff_buf) free(this->taff_buf);
01229             this->taff_buf = (unsigned char *)malloc(this->taff_buf_size);
01230         }
01231 
01232         // write type and version
01233         writeBuffer(taff_file, &(this->taff_desc->type), &ritems, 1, sizeof(this->taff_desc->type), &wok);
01234         writeBuffer(taff_file, &(this->taff_desc->version), &ritems, 1, sizeof(this->taff_desc->version), &wok);
01235 
01236         // write the tag
01237         unsigned char wb[3];
01238         wb[0]=MMSTAFF_TAGTABLE_TYPE_TAG;
01239         wb[1]=MMSTAFF_IMAGE_TAGTABLE_TAG_RAWIMAGE;
01240         writeBuffer(taff_file, wb, &ritems, 1, 2, &wok);
01241 
01242         // write attributes: width
01243         wb[0]=MMSTAFF_TAGTABLE_TYPE_ATTR;
01244         wb[1]=MMSTAFF_IMAGE_RAWIMAGE_ATTR::MMSTAFF_IMAGE_RAWIMAGE_ATTR_IDS_width;
01245         wb[2]=sizeof(int);
01246         writeBuffer(taff_file, wb, &ritems, 1, 3, &wok);
01247         writeBuffer(taff_file, &imgWidth, &ritems, 1, sizeof(int), &wok);
01248 
01249         // write attributes: height
01250         wb[0]=MMSTAFF_TAGTABLE_TYPE_ATTR;
01251         wb[1]=MMSTAFF_IMAGE_RAWIMAGE_ATTR::MMSTAFF_IMAGE_RAWIMAGE_ATTR_IDS_height;
01252         wb[2]=sizeof(int);
01253         writeBuffer(taff_file, wb, &ritems, 1, 3, &wok);
01254         writeBuffer(taff_file, &imgHeight, &ritems, 1, sizeof(int), &wok);
01255 
01256         // write attributes: pitch
01257         wb[0]=MMSTAFF_TAGTABLE_TYPE_ATTR;
01258         wb[1]=MMSTAFF_IMAGE_RAWIMAGE_ATTR::MMSTAFF_IMAGE_RAWIMAGE_ATTR_IDS_pitch;
01259         wb[2]=sizeof(int);
01260         writeBuffer(taff_file, wb, &ritems, 1, 3, &wok);
01261         writeBuffer(taff_file, &imgPitch, &ritems, 1, sizeof(int), &wok);
01262 
01263         // write attributes: size
01264         wb[0]=MMSTAFF_TAGTABLE_TYPE_ATTR;
01265         wb[1]=MMSTAFF_IMAGE_RAWIMAGE_ATTR::MMSTAFF_IMAGE_RAWIMAGE_ATTR_IDS_size;
01266         wb[2]=sizeof(int);
01267         writeBuffer(taff_file, wb, &ritems, 1, 3, &wok);
01268         writeBuffer(taff_file, &imgSize, &ritems, 1, sizeof(int), &wok);
01269 
01270         // write attributes: pixelformat
01271         wb[0]=MMSTAFF_TAGTABLE_TYPE_ATTR;
01272         wb[1]=MMSTAFF_IMAGE_RAWIMAGE_ATTR::MMSTAFF_IMAGE_RAWIMAGE_ATTR_IDS_pixelformat;
01273         wb[2]=sizeof(int);
01274         writeBuffer(taff_file, wb, &ritems, 1, 3, &wok);
01275         int pf = (int)this->destination_pixelformat;
01276         writeBuffer(taff_file, &pf, &ritems, 1, sizeof(int), &wok);
01277 
01278         // write attributes: premultiplied
01279         wb[0]=MMSTAFF_TAGTABLE_TYPE_ATTR;
01280         wb[1]=MMSTAFF_IMAGE_RAWIMAGE_ATTR::MMSTAFF_IMAGE_RAWIMAGE_ATTR_IDS_premultiplied;
01281         wb[2]=sizeof(bool);
01282         writeBuffer(taff_file, wb, &ritems, 1, 3, &wok);
01283         bool pm = (this->destination_premultiplied);
01284         writeBuffer(taff_file, &pm, &ritems, 1, sizeof(bool), &wok);
01285 
01286         // write attributes: mirror_size
01287         wb[0]=MMSTAFF_TAGTABLE_TYPE_ATTR;
01288         wb[1]=MMSTAFF_IMAGE_RAWIMAGE_ATTR::MMSTAFF_IMAGE_RAWIMAGE_ATTR_IDS_mirror_size;
01289         wb[2]=sizeof(int);
01290         writeBuffer(taff_file, wb, &ritems, 1, 3, &wok);
01291         int ms = (int)this->mirror_size;
01292         writeBuffer(taff_file, &ms, &ritems, 1, sizeof(int), &wok);
01293 
01294         // write attributes: alphachannel
01295         wb[0]=MMSTAFF_TAGTABLE_TYPE_ATTR;
01296         wb[1]=MMSTAFF_IMAGE_RAWIMAGE_ATTR::MMSTAFF_IMAGE_RAWIMAGE_ATTR_IDS_alphachannel;
01297         wb[2]=sizeof(bool);
01298         writeBuffer(taff_file, wb, &ritems, 1, 3, &wok);
01299         writeBuffer(taff_file, &imgAlphaChannel, &ritems, 1, sizeof(bool), &wok);
01300 
01301         // write attributes: rotate_180
01302         wb[0]=MMSTAFF_TAGTABLE_TYPE_ATTR;
01303         wb[1]=MMSTAFF_IMAGE_RAWIMAGE_ATTR::MMSTAFF_IMAGE_RAWIMAGE_ATTR_IDS_rotate_180;
01304         wb[2]=sizeof(bool);
01305         writeBuffer(taff_file, wb, &ritems, 1, 3, &wok);
01306         bool rot = (this->rotate_180);
01307         writeBuffer(taff_file, &rot, &ritems, 1, sizeof(bool), &wok);
01308 
01309         // write attributes: data
01310         wb[0]=MMSTAFF_TAGTABLE_TYPE_ATTR;
01311         wb[1]=MMSTAFF_IMAGE_RAWIMAGE_ATTR::MMSTAFF_IMAGE_RAWIMAGE_ATTR_IDS_data;
01312         wb[2]=0xff;
01313         writeBuffer(taff_file, wb, &ritems, 1, 3, &wok);
01314         writeBuffer(taff_file, &imgSize, &ritems, 1, sizeof(int), &wok);
01315         writeBuffer(taff_file, imgBuf, &ritems, 1, imgSize, &wok);
01316 
01317         // write the close tag
01318         wb[0]=MMSTAFF_TAGTABLE_TYPE_CLOSETAG;
01319         wb[1]=MMSTAFF_IMAGE_TAGTABLE_TAG_RAWIMAGE;
01320         writeBuffer(taff_file, wb, &ritems, 1, 2, &wok);
01321 
01322         // set rc
01323         rc = wok;
01324 
01325         // close file and free
01326         if (taff_file) {
01327             delete taff_file;
01328         }
01329         else {
01330             // no regular file, set buffer values
01331             this->taff_buf_size = this->taff_buf_pos;
01332             this->taff_buf_pos = 0;
01333             getFirstTag();
01334             this->loaded = true;
01335         }
01336         free(imgBuf);
01337 
01338         if (!rc) {
01339             // failed, reset the file
01340             if (!this->taff_filename.empty()) {
01341                 taff_file = new MMSFile(this->taff_filename.c_str(), MMSFM_WRITE);
01342                 if (taff_file) delete taff_file;
01343             }
01344         }
01345     }
01346     else {
01347         printf("Error: cannot read external file %s\n", this->external_filename.c_str());
01348     }
01349 
01350     return rc;
01351 }
01352 
01353 bool MMSTaffFile::convertExternal2TAFF() {
01354     switch (this->external_type) {
01355     case MMSTAFF_EXTERNAL_TYPE_XML:
01356         return convertXML2TAFF();
01357     case MMSTAFF_EXTERNAL_TYPE_IMAGE:
01358         return convertIMAGE2TAFF();
01359     }
01360     return false;
01361 }
01362 
01363 bool MMSTaffFile::convertTAFF2XML_throughDoc(int depth, int tagid, MMSFile *external_file) {
01364     size_t ritems;
01365     char wb[8*1024];
01366 
01367     TAFF_TAGTABLE *tagt = &(this->taff_desc->tagtable[tagid]);
01368     TAFF_ATTRDESC *attr = tagt->attr;
01369 
01370     if (this->trace)
01371         printf("Tag \"%s\" found, ID=%d\n", tagt->name, tagid);
01372 
01373     /* write tag */
01374     if (external_file) {
01375         *wb = '\n';
01376         memset(&wb[1], ' ', depth*4);
01377         sprintf(&wb[1+depth*4], "<%s", tagt->name);
01378         writeBuffer(external_file, wb, &ritems, 1, strlen(wb));
01379     }
01380 
01381     /* write attributes */
01382     char *attrval_str;
01383     int  attrval_int;
01384     char *attr_name;
01385     int  attrid;
01386     while ((attrid = getNextAttribute(&attrval_str, &attrval_int, &attr_name)) >= 0) {
01387         if (attrid != MMSTAFF_ATTR_WITHOUT_ID) {
01388             string attrval;
01389             switch (attr[attrid].type) {
01390             case TAFF_ATTRTYPE_BOOL:
01391                 if (attrval_int)
01392                     attrval = "true";
01393                 else
01394                     attrval = "false";
01395                 break;
01396             case TAFF_ATTRTYPE_UCHAR:
01397             case TAFF_ATTRTYPE_UCHAR100:
01398             case TAFF_ATTRTYPE_INT:
01399                 attrval = iToStr(attrval_int);
01400                 break;
01401             case TAFF_ATTRTYPE_STATE:
01402                 if ((attrval_int & 0xff) == 0x01)
01403                     attrval = "auto";
01404                 else
01405                 if (attrval_int)
01406                     attrval = "true";
01407                 else
01408                     attrval = "false";
01409                 break;
01410             case TAFF_ATTRTYPE_SEQUENCE_MODE:
01411                 if ((attrval_int & 0xff) == 0x01)
01412                     attrval = "linear";
01413                 else
01414                 if ((attrval_int & 0xff) == 0x02)
01415                     attrval = "log";
01416                 else
01417                 if ((attrval_int & 0xff) == 0x03)
01418                     attrval = "log_soft_start";
01419                 else
01420                 if ((attrval_int & 0xff) == 0x04)
01421                     attrval = "log_soft_end";
01422                 else
01423                 if (attrval_int)
01424                     attrval = "true";
01425                 else
01426                     attrval = "false";
01427                 break;
01428             case TAFF_ATTRTYPE_COLOR:
01429                 attrval = getMMSFBColorString(MMSFBColor((unsigned int)attrval_int));
01430                 break;
01431             default:
01432                 attrval = attrval_str;
01433                 break;
01434             }
01435 
01436             if (this->trace)
01437                 printf(" Attribute \"%s\" found, ID=%d, value=\"%s\"\n", attr[attrid].name, attrid, attrval.c_str());
01438 
01439             if (external_file) {
01440                 *wb = '\n';
01441                 memset(&wb[1], ' ', depth*4+4);
01442                 sprintf(&wb[1+depth*4+4], "%s = \"%s\"", attr[attrid].name, attrval.c_str());
01443                 writeBuffer(external_file, wb, &ritems, 1, strlen(wb));
01444             }
01445         }
01446         else {
01447             if (this->trace)
01448                 printf(" Attribute \"%s\" found without ID, value=\"%s\"\n", attr_name, attrval_str);
01449 
01450             if (external_file) {
01451                 *wb = '\n';
01452                 memset(&wb[1], ' ', depth*4+4);
01453                 sprintf(&wb[1+depth*4+4], "%s = \"%s\"", attr_name, attrval_str);
01454                 writeBuffer(external_file, wb, &ritems, 1, strlen(wb));
01455             }
01456         }
01457     }
01458 
01459     /* close tag */
01460     if (external_file) {
01461         sprintf(wb, ">\n");
01462         writeBuffer(external_file, wb, &ritems, 1, strlen(wb));
01463     }
01464 
01465     /* through my child tags */
01466     while (1) {
01467         bool eof;
01468         int tid = getNextTag(eof);
01469         if (tid < 0) {
01470             /* close tag */
01471             if (external_file) {
01472                 memset(wb, ' ', depth*4);
01473                 sprintf(&wb[depth*4], "</%s>\n", tagt->name);
01474                 writeBuffer(external_file, wb, &ritems, 1, strlen(wb));
01475             }
01476             return true;
01477         }
01478         if (convertTAFF2XML_throughDoc(depth+1, tid, external_file)==false)
01479             return false;
01480     }
01481 }
01482 
01483 bool MMSTaffFile::convertTAFF2XML() {
01484     if (!this->loaded) return false;
01485 
01486     /* get root tag */
01487     int tagid = getFirstTag();
01488     if (tagid < 0) return false;
01489 
01490     /* open binary destination file */
01491     MMSFile *external_file = NULL;
01492     if (this->external_filename!="")
01493         external_file = new MMSFile(this->external_filename.c_str(), MMSFM_WRITE);
01494 
01495     /* start with root */
01496     bool rc = convertTAFF2XML_throughDoc(0, tagid, external_file);
01497 
01498     if (external_file)
01499         delete external_file;
01500 
01501     return rc;
01502 }
01503 
01504 bool MMSTaffFile::convertTAFF2External() {
01505     switch (this->external_type) {
01506     case MMSTAFF_EXTERNAL_TYPE_XML:
01507         return convertTAFF2XML();
01508     case MMSTAFF_EXTERNAL_TYPE_IMAGE:
01509         printf("TAFF: Currently we cannot convert taff to image\n");
01510         return false;
01511     }
01512     return false;
01513 }
01514 
01515 bool MMSTaffFile::readFile() {
01516     if (this->taff_buf) {
01517         free(this->taff_buf);
01518         this->taff_buf = NULL;
01519     }
01520     this->loaded = false;
01521 
01522     if (!this->taff_desc) return false;
01523     if (this->taff_filename=="") return false;
01524 
01525     // load the file
01526     MMSFile *taff_file = new MMSFile(this->taff_filename.c_str(), MMSFM_READ, false);
01527     if (!taff_file) return false;
01528     size_t ritems;
01529     char taff_ident[32];
01530     if (!taff_file->readBuffer((void*)taff_ident, &ritems, 1, strlen(TAFF_IDENT))) {
01531         // read error
01532         this->taff_buf = NULL;
01533         delete taff_file;
01534         return false;
01535     }
01536     if (ritems == 0) {
01537         // file is empty
01538         printf("TAFF: File is empty (%s)\n", this->taff_filename.c_str());
01539         this->taff_buf = NULL;
01540         delete taff_file;
01541         return false;
01542     }
01543     if (memcmp(taff_ident, TAFF_IDENT, strlen(TAFF_IDENT))!=0) {
01544         // the first bytes of the file are different from TAFF_IDENT
01545         printf("TAFF: TAFF_IDENT mismatch (%s)\n", this->taff_filename.c_str());
01546         this->taff_buf = NULL;
01547         delete taff_file;
01548         return false;
01549     }
01550     if (!taff_file->readBufferEx((void**)&(this->taff_buf), &ritems)) {
01551         // read error
01552         this->taff_buf = NULL;
01553         delete taff_file;
01554         return false;
01555     }
01556     delete taff_file;
01557 
01558     if (ritems < 40) {
01559         // wrong size
01560         free(this->taff_buf);
01561         this->taff_buf = NULL;
01562         return false;
01563     }
01564 
01565     // check the version of the file
01566     this->correct_version = false;
01567     if (strcmp((char*)this->taff_buf, (char*)&(this->taff_desc->type))) {
01568         // wrong type
01569         printf("TAFF: Wrong TAFF type (%s)\n", this->taff_filename.c_str());
01570         free(this->taff_buf);
01571         this->taff_buf = NULL;
01572         return false;
01573     }
01574     if (memcmp(this->taff_buf+sizeof(this->taff_desc->type), &(this->taff_desc->version), sizeof(this->taff_desc->version))) {
01575         // wrong version
01576         free(this->taff_buf);
01577         this->taff_buf = NULL;
01578         return false;
01579     }
01580     this->correct_version = true;
01581 
01582     // compare the modification time of the taff and external file
01583     if (this->external_filename!="") {
01584         struct stat statbuf1;
01585         struct stat statbuf2;
01586         if (stat(this->taff_filename.c_str(), &statbuf1)!=0) {
01587             free(this->taff_buf);
01588             this->taff_buf = NULL;
01589             return false;
01590         }
01591         if (stat(this->external_filename.c_str(), &statbuf2)==0) {
01592             if (statbuf2.st_mtime <= time(NULL)) {
01593                 // ok, external file created in the past
01594                 if (statbuf2.st_mtime >= statbuf1.st_mtime) {
01595                     // external file has been modified, therefore the taff file maybe not up-to-date
01596                     free(this->taff_buf);
01597                     this->taff_buf = NULL;
01598                     return false;
01599                 }
01600             }
01601         }
01602     }
01603 
01604     // all right
01605     this->taff_buf_size = ritems;
01606     getFirstTag();
01607     this->loaded = true;
01608     return true;
01609 }
01610 
01611 bool MMSTaffFile::isLoaded() {
01612     return this->loaded;
01613 }
01614 
01615 bool MMSTaffFile::checkVersion() {
01616     return this->correct_version;
01617 }
01618 
01619 void MMSTaffFile::setExternal(string external_filename, MMSTAFF_EXTERNAL_TYPE external_type) {
01620     this->external_filename = external_filename;
01621     this->external_type = external_type;
01622 }
01623 
01624 void MMSTaffFile::setTrace(bool trace) {
01625     this->trace = trace;
01626 }
01627 
01628 void MMSTaffFile::setPrintWarnings(bool print_warnings) {
01629     this->print_warnings = print_warnings;
01630 }
01631 
01632 void MMSTaffFile::setDestinationPixelFormat(MMSTAFF_PF pixelformat, bool premultiplied) {
01633     this->destination_pixelformat = pixelformat;
01634     this->destination_premultiplied = premultiplied;
01635 }
01636 
01637 void MMSTaffFile::setMirrorEffect(int size) {
01638     this->mirror_size = size;
01639 }
01640 
01641 void MMSTaffFile::rotate180(bool rotate_180) {
01642     this->rotate_180 = rotate_180;
01643 }
01644 
01645 int MMSTaffFile::getFirstTag() {
01646     this->taff_buf_pos = sizeof(this->taff_desc->type) + sizeof(this->taff_desc->version);
01647     this->current_tag = -1;
01648     this->current_tag_pos = 0;
01649 
01650     if (this->taff_buf[this->taff_buf_pos] == MMSTAFF_TAGTABLE_TYPE_TAG) {
01651         bool eof;
01652         return getNextTag(eof);
01653     }
01654 
01655     return this->current_tag;
01656 }
01657 
01658 int MMSTaffFile::getNextTag(bool &eof) {
01659     /* searching for next tag */
01660     eof = false;
01661     while (this->taff_buf_pos < this->taff_buf_size) {
01662         switch (this->taff_buf[this->taff_buf_pos]) {
01663         case MMSTAFF_TAGTABLE_TYPE_TAG:
01664             this->current_tag = this->taff_buf[this->taff_buf_pos+1];
01665             this->current_tag_pos = this->taff_buf_pos;
01666             this->taff_buf_pos+=2;
01667             return this->current_tag;
01668         case MMSTAFF_TAGTABLE_TYPE_ATTR: {
01669                 this->taff_buf_pos+=2;
01670                 int len;
01671 
01672                 /* check if name of attribute is stored instead of id */
01673                 if (this->taff_buf[this->taff_buf_pos-1] == MMSTAFF_ATTR_WITHOUT_ID) {
01674                     len = MMSTAFF_INT32_FROM_UCHAR_STREAM(&this->taff_buf[this->taff_buf_pos]);
01675                     this->taff_buf_pos+=sizeof(int);
01676                     this->taff_buf_pos+=len;
01677                 }
01678 
01679                 /* get the length of the value */
01680                 len = (int)this->taff_buf[this->taff_buf_pos];
01681                 this->taff_buf_pos++;
01682                 if (len >= 0xff) {
01683                     len = MMSTAFF_INT32_FROM_UCHAR_STREAM(&this->taff_buf[this->taff_buf_pos]);
01684                     this->taff_buf_pos+=sizeof(int);
01685                 }
01686                 this->taff_buf_pos+=len;
01687             }
01688             break;
01689         case MMSTAFF_TAGTABLE_TYPE_CLOSETAG:
01690             this->current_tag = -1;
01691             this->taff_buf_pos+=2;
01692             eof = false;
01693             return this->current_tag;
01694         default:
01695             this->current_tag = -1;
01696             this->current_tag_pos = 0;
01697             eof = true;
01698             return this->current_tag;
01699         }
01700     }
01701     this->current_tag = -1;
01702     this->current_tag_pos = 0;
01703     eof = true;
01704     return this->current_tag;
01705 }
01706 
01707 int MMSTaffFile::getCurrentTag(const char **name) {
01708     if (name) *name = this->taff_desc->tagtable[this->current_tag].name;
01709     return this->current_tag;
01710 }
01711 
01712 const char *MMSTaffFile::getCurrentTagName() {
01713     return this->taff_desc->tagtable[this->current_tag].name;
01714 }
01715 
01716 MMSTaffFile *MMSTaffFile::copyCurrentTag() {
01717     MMSTaffFile *mytafff = NULL;
01718     int tag_cnt, closetag_cnt;
01719 
01720     if (!this->current_tag_pos)
01721         return NULL;
01722 
01723     /* save buffer positions */
01724     int saved_taff_buf_pos = this->taff_buf_pos;
01725     int saved_current_tag = this->current_tag;
01726     int saved_current_tag_pos = this->current_tag_pos;
01727 
01728     /* go to the position after the current tag */
01729     this->taff_buf_pos = this->current_tag_pos;
01730 
01731     /* searching the close tag of this tag */
01732     tag_cnt = 0;
01733     closetag_cnt = 0;
01734     do {
01735         bool eof;
01736         if (getNextTag(eof) < 0) {
01737             if (eof) break;
01738             closetag_cnt++;
01739         }
01740         else
01741             tag_cnt++;
01742     } while (tag_cnt > closetag_cnt);
01743 
01744     /* all right? */
01745     if (tag_cnt == closetag_cnt) {
01746         /* yes, allocate memory and copy buffer */
01747         mytafff = new MMSTaffFile("", this->taff_desc, "", this->external_type,
01748                                   this->ignore_blank_values, this->trace, false);
01749         if (mytafff) {
01750             int len = this->taff_buf_pos - saved_current_tag_pos;
01751             mytafff->taff_buf_size = sizeof(this->taff_desc->type) + sizeof(this->taff_desc->version) + len;
01752             mytafff->taff_buf = (unsigned char *)malloc(mytafff->taff_buf_size);
01753             if (mytafff->taff_buf) {
01754                 /* copy & init */
01755                 memcpy(mytafff->taff_buf, this->taff_buf, sizeof(this->taff_desc->type) + sizeof(this->taff_desc->version));
01756                 memcpy(&(mytafff->taff_buf[sizeof(this->taff_desc->type) + sizeof(this->taff_desc->version)]),
01757                        &(this->taff_buf[saved_current_tag_pos]), len);
01758                 mytafff->getFirstTag();
01759                 mytafff->loaded = true;
01760                 mytafff->correct_version = true;
01761             }
01762             else {
01763                 /* out of memory */
01764                 delete mytafff;
01765                 mytafff = NULL;
01766             }
01767         }
01768     }
01769 
01770     /* restore the old buffer positions */
01771     this->taff_buf_pos = saved_taff_buf_pos;
01772     this->current_tag = saved_current_tag;
01773     this->current_tag_pos = saved_current_tag_pos;
01774 
01775     return mytafff;
01776 }
01777 
01778 
01779 bool MMSTaffFile::hasAttributes() {
01780     char *value_str;
01781     int value_int;
01782     char *name;
01783     return (getFirstAttribute(&value_str, &value_int, &name) >= 0);
01784 }
01785 
01786 
01787 int MMSTaffFile::getFirstAttribute(char **value_str, int *value_int, char **name) {
01788     if (!this->current_tag_pos)
01789         return -1;
01790 
01791     /* go to the position after the current tag */
01792     this->taff_buf_pos = this->current_tag_pos;
01793     this->taff_buf_pos+=2;
01794 
01795     /* get the attribute */
01796     if (this->taff_buf[this->taff_buf_pos] == MMSTAFF_TAGTABLE_TYPE_ATTR)
01797         return getNextAttribute(value_str, value_int, name);
01798 
01799     return -1;
01800 }
01801 
01802 int MMSTaffFile::getNextAttribute(char **value_str, int *value_int, char **name) {
01803     /* searching for next attribute */
01804     do {
01805         switch (this->taff_buf[this->taff_buf_pos]) {
01806         case MMSTAFF_TAGTABLE_TYPE_ATTR: {
01807                 int attrid = (int)this->taff_buf[this->taff_buf_pos+1];
01808                 int len;
01809                 this->taff_buf_pos+=2;
01810 
01811                 /* check if name of attribute is stored instead of id */
01812                 if (attrid == MMSTAFF_ATTR_WITHOUT_ID) {
01813                     len = MMSTAFF_INT32_FROM_UCHAR_STREAM(&this->taff_buf[this->taff_buf_pos]);
01814                     this->taff_buf_pos+=sizeof(int);
01815                     if (name)
01816                         *name = (char*)&this->taff_buf[this->taff_buf_pos];
01817                     this->taff_buf_pos+=len;
01818                 }
01819                 else
01820                     if (name) *name=NULL;
01821 
01822                 /* get the length of the value */
01823                 len = (int)this->taff_buf[this->taff_buf_pos];
01824                 this->taff_buf_pos++;
01825                 if (len >= 0xff) {
01826                     len = MMSTAFF_INT32_FROM_UCHAR_STREAM(&this->taff_buf[this->taff_buf_pos]);
01827                     this->taff_buf_pos+=sizeof(int);
01828                 }
01829 
01830                 /* check the type of value and set the return values */
01831                 if (attrid != MMSTAFF_ATTR_WITHOUT_ID) {
01832                     TAFF_ATTRDESC *attr = this->taff_desc->tagtable[current_tag].attr;
01833                     switch (attr[attrid].type) {
01834                     case TAFF_ATTRTYPE_BOOL:
01835                     case TAFF_ATTRTYPE_UCHAR:
01836                     case TAFF_ATTRTYPE_UCHAR100:
01837                     case TAFF_ATTRTYPE_STATE:
01838                     case TAFF_ATTRTYPE_SEQUENCE_MODE:
01839                         *value_str = NULL;
01840                         {   unsigned char v = this->taff_buf[this->taff_buf_pos];
01841                             *value_int = (int)v; }
01842                         break;
01843                     case TAFF_ATTRTYPE_INT:
01844                     case TAFF_ATTRTYPE_COLOR:
01845                         *value_str = NULL;
01846                         *value_int = MMSTAFF_INT32_FROM_UCHAR_STREAM(&this->taff_buf[this->taff_buf_pos]);
01847                         break;
01848                     default:
01849                         *value_str = (char*)&this->taff_buf[this->taff_buf_pos];
01850                         break;
01851                     }
01852                 }
01853                 else
01854                 if (name) {
01855                     *value_str = (char*)&this->taff_buf[this->taff_buf_pos];
01856                 }
01857                 this->taff_buf_pos+=len;
01858 
01859                 if (!((attrid == MMSTAFF_ATTR_WITHOUT_ID)&&(!name)))
01860                     /* return attribute ID */
01861                     return attrid;
01862 
01863                 /* attribute has no ID and name is not set, go to the next attribute */
01864                 break;
01865             }
01866             break;
01867         default:
01868             return -1;
01869         }
01870     } while (this->taff_buf_pos < this->taff_buf_size);
01871     return -1;
01872 }
01873 
01874 bool MMSTaffFile::getAttribute(int id, char **value_str, int *value_int) {
01875     char *attr_name;
01876     int attrid = getFirstAttribute(value_str, value_int, &attr_name);
01877     while (attrid >= 0) {
01878         if (attrid == id)
01879             return true;
01880         attrid = getNextAttribute(value_str, value_int, &attr_name);
01881     }
01882     return false;
01883 }
01884 
01885 char *MMSTaffFile::getAttributeString(int id) {
01886     char *value_str = NULL;
01887     int  value_int;
01888     if (getAttribute(id, &value_str, &value_int))
01889         if (value_str)
01890             return value_str;
01891     return NULL;
01892 }
01893 
01894 
01895 TAFF_ATTRDESC MMSTAFF_IMAGE_RAWIMAGE_ATTR_I[]   = MMSTAFF_IMAGE_RAWIMAGE_ATTR_INIT;
01896 
01897 TAFF_TAGTABLE mmstaff_image_taff_tagtable[] = {
01898     {   "rawimage",     NULL,   NULL,           MMSTAFF_IMAGE_RAWIMAGE_ATTR_I   },
01899     {   NULL,           NULL,   NULL,           NULL                            }
01900 };
01901 
01902 TAFF_DESCRIPTION mmstaff_image_taff_description = { "mmstaff_image", 4, mmstaff_image_taff_tagtable };
01903 
01904 

Generated by doxygen