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-2013 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     MMSFile         *file=NULL;
00569     size_t ritems = 0;
00570     char *fileBuffer=NULL;
00571 
00572     if (strToUpr(string(filename).substr(0,7)) == "HTTP://") {
00573         // check if file does exist and if it is an png format
00574         file = new MMSFile(filename);
00575         if (!file) {
00576             return false;
00577         }
00578         if (file->getLastError()) {
00579             return false;
00580         }
00581 
00582         if (!file->readBufferEx((void **)&fileBuffer, &ritems)) {
00583             delete file;
00584             return false;
00585         }
00586 
00587         if((fp = fmemopen(fileBuffer, ritems, "rb")) == NULL) {
00588             free(fileBuffer);
00589             fileBuffer = NULL;
00590             delete file;
00591             return false;
00592         }
00593     } else {
00594         if((fp = fopen(filename, "rb")) == NULL) {
00595             return false;
00596         }
00597     }
00598 
00599     cinfo.err = jpeg_std_error(&jerr.pub);
00600     jerr.pub.error_exit = JPEGErrorExit;
00601     if(setjmp(jerr.setjmpBuffer)) {
00602         jpeg_destroy_decompress(&cinfo);
00603         fclose(fp);
00604         if (file) {
00605             if (fileBuffer)
00606                 free(fileBuffer);
00607             fileBuffer = NULL;
00608             delete file;
00609         }
00610         return false;
00611     }
00612     jpeg_create_decompress(&cinfo);
00613     jpeg_stdio_src(&cinfo, fp);
00614 
00615     if(jpeg_read_header(&cinfo, TRUE) != JPEG_HEADER_OK) {
00616         fclose(fp);
00617         if (file) {
00618             if (fileBuffer)
00619                 free(fileBuffer);
00620             fileBuffer = NULL;
00621             delete file;
00622         }
00623         return false;
00624     }
00625 
00626     /* dimension filled by jpeg_read_header() */
00627     *width  = (int)cinfo.image_width;
00628     *height = (int)cinfo.image_height;
00629     *pitch  = *width * 4;
00630     *size   = *pitch * *height;
00631 
00632     // jpeg generally has no alpha channel
00633     *alphachannel = false;
00634 
00635     /* setting decompression parameters */
00636     cinfo.out_color_space = JCS_RGB;    /**< setting output colorspace to RGB */
00637 
00638     /* start decompression */
00639     jpeg_start_decompress(&cinfo);
00640 
00641     rowStride = cinfo.output_width * cinfo.output_components;
00642     rowBuf = (*cinfo.mem->alloc_sarray)((j_common_ptr)&cinfo, JPOOL_IMAGE, rowStride, 1);
00643 
00644     /* allocate memory for ARGB output */
00645     if(this->mirror_size > *height) this->mirror_size = *height;
00646     *buf = malloc((*size) + (*pitch) * this->mirror_size);
00647     if(!*buf) {
00648         jpeg_finish_decompress(&cinfo);
00649         jpeg_destroy_decompress(&cinfo);
00650         fclose(fp);
00651         if (file) {
00652             if (fileBuffer)
00653                 free(fileBuffer);
00654             fileBuffer = NULL;
00655             delete file;
00656         }
00657         return false;
00658     }
00659 
00660     unsigned int *src = (unsigned int*)*buf;
00661     while(cinfo.output_scanline < cinfo.output_height) {
00662         jpeg_read_scanlines(&cinfo, rowBuf, 1);
00663         unsigned char *b = *rowBuf;
00664         for(unsigned int i = 0; i < cinfo.output_width; ++i) {
00665             *src = 0xff000000 + (b[0] << 16) + (b[1] << 8) + b[2];
00666             b += 3;
00667             src++;
00668         }
00669     }
00670 
00671     jpeg_finish_decompress(&cinfo);
00672     jpeg_destroy_decompress(&cinfo);
00673     fclose(fp);
00674     if (file) {
00675         if (fileBuffer)
00676             free(fileBuffer);
00677         fileBuffer = NULL;
00678         delete file;
00679     }
00680 
00681     /* create mirror, rotate and convert to target pixelformat */
00682     return postprocessImage(buf, width, height, pitch, size, alphachannel);
00683 #else
00684     return false;
00685 #endif
00686 }
00687 
00688 bool MMSTaffFile::readTIFF(const char *filename, void **buf, int *width, int *height, int *pitch,
00689                                 int *size, bool *alphachannel) {
00690 #ifdef __HAVE_TIFF__
00691     TIFF* tiff;
00692 
00693     if((tiff = TIFFOpen(filename, "rb")) == NULL) {
00694         return false;
00695     }
00696 
00697     TIFFGetField(tiff, TIFFTAG_IMAGEWIDTH, width);
00698     TIFFGetField(tiff, TIFFTAG_IMAGELENGTH, height);
00699     *pitch  = *width * 4;
00700     *size   = *pitch * *height;
00701 
00702     // we assume that we have an alpha channel
00703     *alphachannel = true;
00704 
00705     /* allocate memory for ARGB output */
00706     if(this->mirror_size > *height) this->mirror_size = *height;
00707     //*buf = (unsigned int*)_TIFFmalloc((*size) + (*pitch) * this->mirror_size);
00708     *buf = malloc((*size) + (*pitch) * this->mirror_size);
00709     if(!*buf) {
00710         TIFFClose(tiff);
00711         return false;
00712     }
00713 
00714     if(TIFFReadRGBAImageOriented(tiff, *width, *height, (uint32*)*buf, ORIENTATION_TOPLEFT, 0) == 0) {
00715         TIFFClose(tiff);
00716         return false;
00717     }
00718 
00719     /* convert from BGRA to ARGB */
00720     unsigned int *src = (unsigned int*)*buf;
00721     unsigned int nPixels = *width * *height;
00722     for(unsigned int i = 0; i < nPixels; ++i) {
00723         register unsigned int s = (*src ^ (*src >> 16)) & 0xff;
00724         *src = *src ^ (s | (s << 16));
00725         src++;
00726     }
00727 
00728     //_TIFFfree(*buf);
00729     TIFFClose(tiff);
00730 
00731     /* create mirror, rotate and convert to target pixelformat */
00732     return postprocessImage(buf, width, height, pitch, size, alphachannel);
00733 #else
00734     return false;
00735 #endif
00736 }
00737 
00738 
00739 bool MMSTaffFile::convertString2TaffAttributeType(TAFF_ATTRTYPE attrType, char *attrValStr, bool *attrValStr_valid,
00740                                 bool *int_val_set, bool *byte_val_set, int *int_val,
00741                                 const char *attrname, int attrid, const char *nodename, int nodeline) {
00742     xmlChar *attrVal = (xmlChar *)attrValStr;
00743     if (!attrValStr) return false;
00744     if (!attrValStr_valid) return false;
00745     *attrValStr_valid = true;
00746     if (int_val_set)  *int_val_set = false;
00747     if (byte_val_set) *byte_val_set = false;
00748 
00749     bool check_ok = true;
00750 
00751 
00752     string validvals = "";
00753     bool badval = false;
00754     switch (attrType) {
00755     case TAFF_ATTRTYPE_NONE:
00756     case TAFF_ATTRTYPE_STRING:
00757     case TAFF_ATTRTYPE_BINDATA:
00758         break;
00759 
00760     case TAFF_ATTRTYPE_NE_STRING:
00761         badval = (!*attrVal);
00762         if (badval) {
00763             validvals = "any characters, but not empty";
00764             check_ok = false;
00765         }
00766         break;
00767 
00768     case TAFF_ATTRTYPE_BOOL:
00769         if (!byte_val_set || !int_val) return false;
00770         badval = ((xmlStrcmp(attrVal, (xmlChar *)"true"))&&(xmlStrcmp(attrVal, (xmlChar *)"false")));
00771         if (badval) {
00772             validvals = "\"true\", \"false\"";
00773             check_ok = false;
00774         }
00775         else {
00776             *byte_val_set = true;
00777             if (xmlStrcmp(attrVal, (xmlChar *)"true")==0)
00778                 *int_val = 0xff;
00779             else
00780                 *int_val = 0;
00781         }
00782         break;
00783 
00784     case TAFF_ATTRTYPE_UCHAR:
00785     case TAFF_ATTRTYPE_UCHAR100:
00786         if (!byte_val_set || !int_val) return false;
00787         badval = ((xmlStrlen(attrVal) < 1)||(xmlStrlen(attrVal) > 3));
00788         if (!badval) {
00789             char iv[3+1];
00790             *int_val = atoi((char*)attrVal);
00791             sprintf(iv, "%d", *int_val);
00792             badval = (xmlStrcmp(attrVal, (xmlChar *)iv));
00793             if (!badval) {
00794                 if (attrType == TAFF_ATTRTYPE_UCHAR100)
00795                     badval = (*int_val<0||*int_val>100);
00796                 else
00797                     badval = (*int_val<0||*int_val>255);
00798             }
00799             *byte_val_set = !badval;
00800         }
00801         if (badval) {
00802             if (attrType == TAFF_ATTRTYPE_UCHAR100)
00803                 validvals = "\"0\"..\"100\"";
00804             else
00805                 validvals = "\"0\"..\"255\"";
00806             check_ok = false;
00807         }
00808         break;
00809 
00810     case TAFF_ATTRTYPE_INT:
00811         if (!int_val_set || !int_val) return false;
00812         char iv[11+1];
00813         *int_val = atoi((char*)attrVal);
00814         sprintf(iv, "%d", *int_val);
00815         badval = (xmlStrcmp(attrVal, (xmlChar *)iv));
00816         *int_val_set = !badval;
00817         if (badval) {
00818             validvals = "\"-2147483648\"..\"2147483647\"";
00819             check_ok = false;
00820         }
00821         break;
00822 
00823     case TAFF_ATTRTYPE_STATE:
00824         if (!byte_val_set || !int_val) return false;
00825         badval = ((xmlStrcmp(attrVal, (xmlChar *)"true"))&&(xmlStrcmp(attrVal, (xmlChar *)"false"))
00826                 &&(xmlStrcmp(attrVal, (xmlChar *)"auto")));
00827         if (badval) {
00828             validvals = "\"true\", \"false\", \"auto\"";
00829             check_ok = false;
00830         }
00831         else {
00832             *byte_val_set = true;
00833             if (xmlStrcmp(attrVal, (xmlChar *)"true")==0)
00834                 *int_val = 0xff;
00835             else
00836             if (xmlStrcmp(attrVal, (xmlChar *)"auto")==0)
00837                 *int_val = 0x01;
00838             else
00839                 *int_val = 0;
00840         }
00841         break;
00842 
00843     case TAFF_ATTRTYPE_SEQUENCE_MODE: {
00844         if (!byte_val_set || !int_val) return false;
00845         bool sm_true            = !xmlStrcmp(attrVal, (xmlChar *)"true");
00846         bool sm_false           = !xmlStrcmp(attrVal, (xmlChar *)"false");
00847         bool sm_linear          = !xmlStrcmp(attrVal, (xmlChar *)"linear");
00848         bool sm_log             = !xmlStrcmp(attrVal, (xmlChar *)"log");
00849         bool sm_log_soft_start  = !xmlStrcmp(attrVal, (xmlChar *)"log_soft_start");
00850         bool sm_log_soft_end    = !xmlStrcmp(attrVal, (xmlChar *)"log_soft_end");
00851         badval = (!sm_true && !sm_false && !sm_linear && !sm_log && !sm_log_soft_start && !sm_log_soft_end);
00852         if (badval) {
00853             validvals = "\"true\", \"false\", \"linear\", \"log\", \"log_soft_start\", \"log_soft_end\"";
00854             check_ok = false;
00855         }
00856         else {
00857             *byte_val_set = true;
00858             if (sm_true)
00859                 *int_val = 0xff;
00860             else
00861             if (sm_linear)
00862                 *int_val = 0x01;
00863             else
00864             if (sm_log)
00865                 *int_val = 0x02;
00866             else
00867             if (sm_log_soft_start)
00868                 *int_val = 0x03;
00869             else
00870             if (sm_log_soft_end)
00871                 *int_val = 0x04;
00872             else
00873                 *int_val = 0;
00874         }
00875         }
00876         break;
00877 
00878     case TAFF_ATTRTYPE_COLOR:
00879         if (!int_val_set || !int_val) return false;
00880         MMSFBColor color;
00881         badval = (!getMMSFBColorFromString((const char*)attrVal, &color));
00882         if (badval) {
00883             validvals = "argb values in hex format, syntax: \"#rrggbbaa\"";
00884             check_ok = false;
00885         }
00886         else {
00887             *int_val_set = true;
00888             *int_val = (int)color.getARGB();
00889         }
00890         break;
00891     }
00892 
00893     // check if the value is blank and i have to ignore it
00894     if (this->ignore_blank_values) {
00895         if (!*attrVal) {
00896             *attrValStr_valid = false;
00897             if (int_val_set)  *int_val_set = false;
00898             if (byte_val_set) *byte_val_set = false;
00899             return true;
00900         }
00901     }
00902 
00903     if (!check_ok) {
00904         printf("Error: Value \"%s\" is invalid for the attribute \"%s\" of tag \"%s\", line %d of file %s\n       valid values: %s\n",
00905                         attrVal, (attrname)?attrname:"?", (nodename)?nodename:"?", nodeline, external_filename.c_str(), validvals.c_str());
00906         *attrValStr_valid = false;
00907         if (int_val_set)  *int_val_set = false;
00908         if (byte_val_set) *byte_val_set = false;
00909         return false;
00910     }
00911 
00912     // all right
00913     if (this->trace)
00914         printf(" Attribute \"%s\" found, ID=%d, value=\"%s\"\n", (attrname)?attrname:"?", attrid, attrVal);
00915 
00916     return true;
00917 }
00918 
00919 
00920 bool MMSTaffFile::convertXML2TAFF_throughDoc(int depth, void *void_node, MMSFile *taff_file) {
00921 
00922     bool wok = true;
00923     xmlNode *node = (xmlNode*) void_node;
00924     xmlNode *cur_node;
00925     if (depth==0)
00926         /* work with root */
00927         cur_node = node;
00928     else
00929         /* iterate through childs */
00930         cur_node = node->children;
00931 
00932     while (cur_node) {
00933 
00934         int tagid = 0;
00935         bool tag_found = false;
00936 
00937         while (this->taff_desc->tagtable[tagid].name) {
00938             if (xmlStrcmp(cur_node->name, (const xmlChar *)this->taff_desc->tagtable[tagid].name)==0) {
00939                 /* tag found in XML and tagtable, check the type? */
00940                 if (this->taff_desc->tagtable[tagid].typeattr)
00941                 {
00942                     /* searching the typeattr and type */
00943                     for (xmlAttr *cur_attr = cur_node->properties; cur_attr; cur_attr = cur_attr->next) {
00944                         if (xmlStrcmp(cur_attr->name, (const xmlChar *)this->taff_desc->tagtable[tagid].typeattr)==0) {
00945                             xmlChar *attrVal = xmlGetProp(cur_node, cur_attr->name);
00946                             if (attrVal) {
00947                                 if (xmlStrcmp(attrVal, (const xmlChar *)this->taff_desc->tagtable[tagid].type)==0) {
00948                                     tag_found = true;
00949                                     break;
00950                                 }
00951                                 xmlFree(attrVal);
00952                             }
00953                         }
00954                     }
00955                 }
00956                 else
00957                     tag_found = true;
00958 
00959                 if (tag_found)
00960                     break;
00961             }
00962             tagid++;
00963         }
00964 
00965         if (tag_found) {
00966 
00967             if (this->trace)
00968                 printf("Tag \"%s\" found, ID=%d\n", cur_node->name, tagid);
00969 
00970             /* writing the new tag */
00971             if (taff_file) {
00972                 size_t ritems;
00973                 unsigned char wb[2];
00974                 wb[0]=MMSTAFF_TAGTABLE_TYPE_TAG;
00975                 wb[1]=(unsigned char)tagid;
00976                 writeBuffer(taff_file, wb, &ritems, 1, 2, &wok);
00977             }
00978 
00979             /* get variables */
00980             for (xmlAttr *cur_attr = cur_node->properties; cur_attr; cur_attr = cur_attr->next) {
00981 
00982                 int attrid = 0;
00983                 TAFF_ATTRDESC *attr = this->taff_desc->tagtable[tagid].attr;
00984                 bool attr_found = false;
00985 
00986                 if (!attr) continue;
00987 
00988                 xmlChar *attrVal = xmlGetProp(cur_node, cur_attr->name);
00989                 if (!attrVal) continue;
00990 
00991                 while (attr[attrid].name)
00992                 {
00993                     if (xmlStrcmp(cur_attr->name, (const xmlChar *)attr[attrid].name)==0) {
00994                         attr_found = true;
00995                         break;
00996                     }
00997                     attrid++;
00998                 }
00999 
01000                 if (attr_found) {
01001 
01002                     // now check the type of the variable
01003                     bool attrValStr_valid;
01004                     bool int_val_set;
01005                     bool byte_val_set;
01006                     int  int_val;
01007 
01008                     if (!convertString2TaffAttributeType(attr[attrid].type, (char *)attrVal, &attrValStr_valid,
01009                                                     &int_val_set, &byte_val_set, &int_val,
01010                                                     (const char *)cur_attr->name, attrid,
01011                                                     (const char *)cur_node->name, cur_node->line)) {
01012                         // check failed
01013                         return false;
01014                     }
01015 
01016                     if (!attrValStr_valid && !int_val_set && !byte_val_set) {
01017                         // no values to process
01018                         continue;
01019                     }
01020 
01021 
01022                     // attribute value is determined, write it now
01023                     if (taff_file) {
01024                         if (!int_val_set && !byte_val_set) {
01025                             /* get the length of the value INCLUDING the 0x00 because of fast read & parse of the TAFF */
01026                             int attrvallen = xmlStrlen(attrVal) + 1;
01027 
01028                             size_t ritems;
01029                             unsigned char wb[3];
01030                             wb[0]=MMSTAFF_TAGTABLE_TYPE_ATTR;
01031                             wb[1]=(unsigned char)attrid;
01032                             if (attrvallen >= 0xff) {
01033                                 /* in this case set 0xff as mark and append the full integer */
01034                                 wb[2]=0xff;
01035                                 writeBuffer(taff_file, wb, &ritems, 1, 3, &wok);
01036                                 writeBuffer(taff_file, &attrvallen, &ritems, 1, sizeof(int), &wok);
01037                             }
01038                             else {
01039                                 /* in this case write only one byte length */
01040                                 wb[2]=(unsigned char)attrvallen;
01041                                 writeBuffer(taff_file, wb, &ritems, 1, 3, &wok);
01042                             }
01043                             writeBuffer(taff_file, attrVal, &ritems, 1, attrvallen, &wok);
01044                         }
01045                         else
01046                         if (int_val_set) {
01047                             // writing value as INTEGER
01048                             size_t ritems;
01049                             unsigned char wb[3];
01050                             wb[0]=MMSTAFF_TAGTABLE_TYPE_ATTR;
01051                             wb[1]=(unsigned char)attrid;
01052                             wb[2]=sizeof(int);
01053                             writeBuffer(taff_file, wb, &ritems, 1, 3, &wok);
01054                             writeBuffer(taff_file, &int_val, &ritems, 1, sizeof(int), &wok);
01055                         }
01056                         else {
01057                             // writing value as single BYTE
01058                             size_t ritems;
01059                             unsigned char wb[3];
01060                             wb[0]=MMSTAFF_TAGTABLE_TYPE_ATTR;
01061                             wb[1]=(unsigned char)attrid;
01062                             wb[2]=sizeof(char);
01063                             writeBuffer(taff_file, wb, &ritems, 1, 3, &wok);
01064                             unsigned char byte_val = int_val;
01065                             writeBuffer(taff_file, &byte_val, &ritems, 1, sizeof(char), &wok);
01066                         }
01067                     }
01068                 }
01069                 else {
01070                     /* attribute is not defined, so we cannot found an ID of it */
01071                     /* we store it with ID 0xff and its real name */
01072                     if (this->trace)
01073                         printf(" Attribute \"%s\" found without ID, value=\"%s\"\n", cur_attr->name, attrVal);
01074 
01075                     if (this->print_warnings)
01076                         printf("Warning: Attribute \"%s\" is not defined for tag \"%s\", line %d of file %s\n         We store it with the real name.\n",
01077                                 cur_attr->name, cur_node->name, cur_node->line, external_filename.c_str());
01078 
01079                     /* write attribute value */
01080                     if (taff_file) {
01081                         /* get the length of the value INCLUDING the 0x00 because of fast read & parse of the TAFF */
01082                         int attrnamlen = xmlStrlen(cur_attr->name) + 1;
01083                         int attrvallen = xmlStrlen(attrVal) + 1;
01084 
01085                         size_t ritems;
01086                         unsigned char wb[3];
01087                         wb[0]=MMSTAFF_TAGTABLE_TYPE_ATTR;
01088                         wb[1]=MMSTAFF_ATTR_WITHOUT_ID;
01089                         writeBuffer(taff_file, wb, &ritems, 1, 2, &wok);
01090                         writeBuffer(taff_file, &attrnamlen, &ritems, 1, sizeof(int), &wok);
01091                         writeBuffer(taff_file, (char*)cur_attr->name, &ritems, 1, attrnamlen, &wok);
01092                         if (attrvallen >= 0xff) {
01093                             /* in this case set 0xff as mark and append the full integer */
01094                             wb[0]=0xff;
01095                             writeBuffer(taff_file, wb, &ritems, 1, 1, &wok);
01096                             writeBuffer(taff_file, &attrvallen, &ritems, 1, sizeof(int), &wok);
01097                         }
01098                         else {
01099                             /* in this case write only one byte length */
01100                             wb[0]=(unsigned char)attrvallen;
01101                             writeBuffer(taff_file, wb, &ritems, 1, 1, &wok);
01102                         }
01103                         writeBuffer(taff_file, attrVal, &ritems, 1, attrvallen, &wok);
01104                     }
01105                 }
01106 
01107                 xmlFree(attrVal);
01108             }
01109 
01110             /* call recursive to find childs */
01111             if (!convertXML2TAFF_throughDoc(depth+1, cur_node, taff_file))
01112                 return false;
01113 
01114             /* writing the close tag */
01115             if (taff_file) {
01116                 size_t ritems;
01117                 unsigned char wb[2];
01118                 wb[0]=MMSTAFF_TAGTABLE_TYPE_CLOSETAG;
01119                 wb[1]=(unsigned char)tagid;
01120                 writeBuffer(taff_file, wb, &ritems, 1, 2, &wok);
01121             }
01122         }
01123         else {
01124             if (xmlStrcmp(cur_node->name, (const xmlChar *)"text")&&xmlStrcmp(cur_node->name, (const xmlChar *)"comment")) {
01125                 printf("Error: Tag \"%s\" is not defined, line %d of file %s\n", cur_node->name, cur_node->line, external_filename.c_str());
01126                 return false;
01127             }
01128         }
01129 
01130         if (depth==0)
01131             break;
01132         else
01133             cur_node = cur_node->next;
01134     }
01135 
01136     // return with write status
01137     return wok;
01138 }
01139 
01140 bool MMSTaffFile::convertXML2TAFF() {
01141 
01142     bool   rc = false;
01143     xmlDoc *parser = NULL;
01144 
01145     LIBXML_TEST_VERSION
01146 
01147     /* check input parameters */
01148     if (!this->taff_desc || this->external_filename.empty()) {
01149         return false;
01150     }
01151 
01152     /* read the XML file */
01153     parser = xmlReadFile(this->external_filename.c_str(),
01154             NULL,
01155             XML_PARSE_PEDANTIC |
01156             XML_PARSE_NOBLANKS | XML_PARSE_NONET | XML_PARSE_NODICT |
01157             XML_PARSE_NOXINCNODE
01158 #if LIBXML_VERSION >= 20700
01159             | XML_PARSE_NOBASEFIX
01160 #endif
01161             );
01162 
01163     if (parser) {
01164 
01165         /* open binary destination file */
01166         MMSFile *taff_file = NULL;
01167         if (this->taff_filename!="") {
01168             taff_file = new MMSFile(this->taff_filename.c_str(), MMSFM_WRITE);
01169             size_t ritems;
01170             bool wok = true;
01171             writeBuffer(taff_file, (void*)TAFF_IDENT, &ritems, 1, strlen(TAFF_IDENT), &wok);
01172             writeBuffer(taff_file, &(this->taff_desc->type), &ritems, 1, sizeof(this->taff_desc->type), &wok);
01173             writeBuffer(taff_file, &(this->taff_desc->version), &ritems, 1, sizeof(this->taff_desc->version), &wok);
01174             if (!wok) {
01175                 // write error, close file and free
01176                 delete taff_file;
01177                 xmlFreeDoc(parser);
01178 
01179                 // reset the file
01180                 taff_file = new MMSFile(this->taff_filename.c_str(), MMSFM_WRITE);
01181                 if (taff_file) delete taff_file;
01182 
01183                 return false;
01184             }
01185         }
01186 
01187         // get the first element
01188         xmlNode* node = xmlDocGetRootElement(parser);
01189 
01190         // through the doc
01191         rc = convertXML2TAFF_throughDoc(0, node, taff_file);
01192 
01193         // close file and free
01194         if (taff_file)
01195             delete taff_file;
01196         xmlFreeDoc(parser);
01197 
01198         if (!rc) {
01199             // failed, reset the file
01200             taff_file = new MMSFile(this->taff_filename.c_str(), MMSFM_WRITE);
01201             if (taff_file) delete taff_file;
01202         }
01203     }
01204     else {
01205         printf("Error: cannot read external file %s\n", this->external_filename.c_str());
01206     }
01207 
01208     return rc;
01209 }
01210 
01211 bool MMSTaffFile::convertIMAGE2TAFF() {
01212     bool    rc = false;
01213     void    *imgBuf;
01214     int     imgWidth;
01215     int     imgHeight;
01216     int     imgPitch;
01217     int     imgSize;
01218     bool    imgAlphaChannel;
01219 
01220     /* check input parameters */
01221     if (!this->taff_desc || this->external_filename.empty()) {
01222         return false;
01223     }
01224 
01225     /* check file extension (if this fails try readPNG() and/or readJPEG() and/or readTIFF()) */
01226     if(strToUpr(this->external_filename).rfind(".PNG") == this->external_filename.size() - 4) {
01227 #ifdef __HAVE_PNG__
01228         rc = readPNG(this->external_filename.c_str(), &imgBuf, &imgWidth, &imgHeight, &imgPitch, &imgSize, &imgAlphaChannel);
01229 #else
01230         cout << "Disko was built without PNG support: skipping " << this->external_filename << endl;
01231         return false;
01232 #endif
01233     } else if((strToUpr(this->external_filename).rfind(".JPG") == this->external_filename.size() - 4) ||
01234               (strToUpr(this->external_filename).rfind(".JPEG") == this->external_filename.size() - 5)) {
01235 #ifdef __HAVE_JPEG__
01236         rc = readJPEG(this->external_filename.c_str(), &imgBuf, &imgWidth, &imgHeight, &imgPitch, &imgSize, &imgAlphaChannel);
01237 #else
01238         cout << "Disko was built without JPEG support: skipping " << this->external_filename << endl;
01239         return false;
01240 #endif
01241     } else if((strToUpr(this->external_filename).rfind(".TIF") == this->external_filename.size() - 4) ||
01242               (strToUpr(this->external_filename).rfind(".TIFF") == this->external_filename.size() - 5)) {
01243 #ifdef __HAVE_TIFF__
01244         rc = readTIFF(this->external_filename.c_str(), &imgBuf, &imgWidth, &imgHeight, &imgPitch, &imgSize, &imgAlphaChannel);
01245 #else
01246         cout << "Disko was built without TIFF support: skipping " << this->external_filename << endl;
01247         return false;
01248 #endif
01249     } else {
01250 #ifdef __HAVE_PNG__
01251         rc = readPNG(this->external_filename.c_str(), &imgBuf, &imgWidth, &imgHeight, &imgPitch, &imgSize, &imgAlphaChannel);
01252 #endif
01253 #ifdef __HAVE_JPEG__
01254         if(!rc) {
01255             rc = readJPEG(this->external_filename.c_str(), &imgBuf, &imgWidth, &imgHeight, &imgPitch, &imgSize, &imgAlphaChannel);
01256         }
01257 #endif
01258 #ifdef __HAVE_TIFF__
01259         if(!rc) {
01260             rc = readTIFF(this->external_filename.c_str(), &imgBuf, &imgWidth, &imgHeight, &imgPitch, &imgSize, &imgAlphaChannel);
01261         }
01262 #endif
01263     }
01264 
01265     if(rc) {
01266         // open binary destination file
01267         MMSFile *taff_file = NULL;
01268         bool wok = true;
01269         size_t ritems;
01270         if (!this->taff_filename.empty()) {
01271             taff_file = new MMSFile(this->taff_filename.c_str(), MMSFM_WRITE);
01272             writeBuffer(taff_file, (void*)TAFF_IDENT, &ritems, 1, strlen(TAFF_IDENT), &wok);
01273         }
01274 
01275         if (!taff_file) {
01276             // no regular file, so setup the buffer so that we have not to resize it
01277             this->taff_buf_size = imgSize + 256;
01278             this->taff_buf_pos = 0;
01279             if (this->taff_buf) free(this->taff_buf);
01280             this->taff_buf = (unsigned char *)malloc(this->taff_buf_size);
01281         }
01282 
01283         // write type and version
01284         writeBuffer(taff_file, &(this->taff_desc->type), &ritems, 1, sizeof(this->taff_desc->type), &wok);
01285         writeBuffer(taff_file, &(this->taff_desc->version), &ritems, 1, sizeof(this->taff_desc->version), &wok);
01286 
01287         // write the tag
01288         unsigned char wb[3];
01289         wb[0]=MMSTAFF_TAGTABLE_TYPE_TAG;
01290         wb[1]=MMSTAFF_IMAGE_TAGTABLE_TAG_RAWIMAGE;
01291         writeBuffer(taff_file, wb, &ritems, 1, 2, &wok);
01292 
01293         // write attributes: width
01294         wb[0]=MMSTAFF_TAGTABLE_TYPE_ATTR;
01295         wb[1]=MMSTAFF_IMAGE_RAWIMAGE_ATTR::MMSTAFF_IMAGE_RAWIMAGE_ATTR_IDS_width;
01296         wb[2]=sizeof(int);
01297         writeBuffer(taff_file, wb, &ritems, 1, 3, &wok);
01298         writeBuffer(taff_file, &imgWidth, &ritems, 1, sizeof(int), &wok);
01299 
01300         // write attributes: height
01301         wb[0]=MMSTAFF_TAGTABLE_TYPE_ATTR;
01302         wb[1]=MMSTAFF_IMAGE_RAWIMAGE_ATTR::MMSTAFF_IMAGE_RAWIMAGE_ATTR_IDS_height;
01303         wb[2]=sizeof(int);
01304         writeBuffer(taff_file, wb, &ritems, 1, 3, &wok);
01305         writeBuffer(taff_file, &imgHeight, &ritems, 1, sizeof(int), &wok);
01306 
01307         // write attributes: pitch
01308         wb[0]=MMSTAFF_TAGTABLE_TYPE_ATTR;
01309         wb[1]=MMSTAFF_IMAGE_RAWIMAGE_ATTR::MMSTAFF_IMAGE_RAWIMAGE_ATTR_IDS_pitch;
01310         wb[2]=sizeof(int);
01311         writeBuffer(taff_file, wb, &ritems, 1, 3, &wok);
01312         writeBuffer(taff_file, &imgPitch, &ritems, 1, sizeof(int), &wok);
01313 
01314         // write attributes: size
01315         wb[0]=MMSTAFF_TAGTABLE_TYPE_ATTR;
01316         wb[1]=MMSTAFF_IMAGE_RAWIMAGE_ATTR::MMSTAFF_IMAGE_RAWIMAGE_ATTR_IDS_size;
01317         wb[2]=sizeof(int);
01318         writeBuffer(taff_file, wb, &ritems, 1, 3, &wok);
01319         writeBuffer(taff_file, &imgSize, &ritems, 1, sizeof(int), &wok);
01320 
01321         // write attributes: pixelformat
01322         wb[0]=MMSTAFF_TAGTABLE_TYPE_ATTR;
01323         wb[1]=MMSTAFF_IMAGE_RAWIMAGE_ATTR::MMSTAFF_IMAGE_RAWIMAGE_ATTR_IDS_pixelformat;
01324         wb[2]=sizeof(int);
01325         writeBuffer(taff_file, wb, &ritems, 1, 3, &wok);
01326         int pf = (int)this->destination_pixelformat;
01327         writeBuffer(taff_file, &pf, &ritems, 1, sizeof(int), &wok);
01328 
01329         // write attributes: premultiplied
01330         wb[0]=MMSTAFF_TAGTABLE_TYPE_ATTR;
01331         wb[1]=MMSTAFF_IMAGE_RAWIMAGE_ATTR::MMSTAFF_IMAGE_RAWIMAGE_ATTR_IDS_premultiplied;
01332         wb[2]=sizeof(bool);
01333         writeBuffer(taff_file, wb, &ritems, 1, 3, &wok);
01334         bool pm = (this->destination_premultiplied);
01335         writeBuffer(taff_file, &pm, &ritems, 1, sizeof(bool), &wok);
01336 
01337         // write attributes: mirror_size
01338         wb[0]=MMSTAFF_TAGTABLE_TYPE_ATTR;
01339         wb[1]=MMSTAFF_IMAGE_RAWIMAGE_ATTR::MMSTAFF_IMAGE_RAWIMAGE_ATTR_IDS_mirror_size;
01340         wb[2]=sizeof(int);
01341         writeBuffer(taff_file, wb, &ritems, 1, 3, &wok);
01342         int ms = (int)this->mirror_size;
01343         writeBuffer(taff_file, &ms, &ritems, 1, sizeof(int), &wok);
01344 
01345         // write attributes: alphachannel
01346         wb[0]=MMSTAFF_TAGTABLE_TYPE_ATTR;
01347         wb[1]=MMSTAFF_IMAGE_RAWIMAGE_ATTR::MMSTAFF_IMAGE_RAWIMAGE_ATTR_IDS_alphachannel;
01348         wb[2]=sizeof(bool);
01349         writeBuffer(taff_file, wb, &ritems, 1, 3, &wok);
01350         writeBuffer(taff_file, &imgAlphaChannel, &ritems, 1, sizeof(bool), &wok);
01351 
01352         // write attributes: rotate_180
01353         wb[0]=MMSTAFF_TAGTABLE_TYPE_ATTR;
01354         wb[1]=MMSTAFF_IMAGE_RAWIMAGE_ATTR::MMSTAFF_IMAGE_RAWIMAGE_ATTR_IDS_rotate_180;
01355         wb[2]=sizeof(bool);
01356         writeBuffer(taff_file, wb, &ritems, 1, 3, &wok);
01357         bool rot = (this->rotate_180);
01358         writeBuffer(taff_file, &rot, &ritems, 1, sizeof(bool), &wok);
01359 
01360         // write attributes: data
01361         wb[0]=MMSTAFF_TAGTABLE_TYPE_ATTR;
01362         wb[1]=MMSTAFF_IMAGE_RAWIMAGE_ATTR::MMSTAFF_IMAGE_RAWIMAGE_ATTR_IDS_data;
01363         wb[2]=0xff;
01364         writeBuffer(taff_file, wb, &ritems, 1, 3, &wok);
01365         writeBuffer(taff_file, &imgSize, &ritems, 1, sizeof(int), &wok);
01366         writeBuffer(taff_file, imgBuf, &ritems, 1, imgSize, &wok);
01367 
01368         // write the close tag
01369         wb[0]=MMSTAFF_TAGTABLE_TYPE_CLOSETAG;
01370         wb[1]=MMSTAFF_IMAGE_TAGTABLE_TAG_RAWIMAGE;
01371         writeBuffer(taff_file, wb, &ritems, 1, 2, &wok);
01372 
01373         // set rc
01374         rc = wok;
01375 
01376         // close file and free
01377         if (taff_file) {
01378             delete taff_file;
01379         }
01380         else {
01381             // no regular file, set buffer values
01382             this->taff_buf_size = this->taff_buf_pos;
01383             this->taff_buf_pos = 0;
01384             getFirstTag();
01385             this->loaded = true;
01386         }
01387         free(imgBuf);
01388 
01389         if (!rc) {
01390             // failed, reset the file
01391             if (!this->taff_filename.empty()) {
01392                 taff_file = new MMSFile(this->taff_filename.c_str(), MMSFM_WRITE);
01393                 if (taff_file) delete taff_file;
01394             }
01395         }
01396     }
01397     else {
01398         printf("Error: cannot read external file %s\n", this->external_filename.c_str());
01399     }
01400 
01401     return rc;
01402 }
01403 
01404 bool MMSTaffFile::convertExternal2TAFF() {
01405     switch (this->external_type) {
01406     case MMSTAFF_EXTERNAL_TYPE_XML:
01407         return convertXML2TAFF();
01408     case MMSTAFF_EXTERNAL_TYPE_IMAGE:
01409         return convertIMAGE2TAFF();
01410     }
01411     return false;
01412 }
01413 
01414 bool MMSTaffFile::convertTAFF2XML_throughDoc(int depth, int tagid, MMSFile *external_file) {
01415     size_t ritems;
01416     char wb[8*1024];
01417 
01418     TAFF_TAGTABLE *tagt = &(this->taff_desc->tagtable[tagid]);
01419     TAFF_ATTRDESC *attr = tagt->attr;
01420 
01421     if (this->trace)
01422         printf("Tag \"%s\" found, ID=%d\n", tagt->name, tagid);
01423 
01424     /* write tag */
01425     if (external_file) {
01426         *wb = '\n';
01427         memset(&wb[1], ' ', depth*4);
01428         sprintf(&wb[1+depth*4], "<%s", tagt->name);
01429         writeBuffer(external_file, wb, &ritems, 1, strlen(wb));
01430     }
01431 
01432     /* write attributes */
01433     char *attrval_str;
01434     int  attrval_int;
01435     char *attr_name;
01436     int  attrid;
01437     while ((attrid = getNextAttribute(&attrval_str, &attrval_int, &attr_name)) >= 0) {
01438         if (attrid != MMSTAFF_ATTR_WITHOUT_ID) {
01439             string attrval;
01440             switch (attr[attrid].type) {
01441             case TAFF_ATTRTYPE_BOOL:
01442                 if (attrval_int)
01443                     attrval = "true";
01444                 else
01445                     attrval = "false";
01446                 break;
01447             case TAFF_ATTRTYPE_UCHAR:
01448             case TAFF_ATTRTYPE_UCHAR100:
01449             case TAFF_ATTRTYPE_INT:
01450                 attrval = iToStr(attrval_int);
01451                 break;
01452             case TAFF_ATTRTYPE_STATE:
01453                 if ((attrval_int & 0xff) == 0x01)
01454                     attrval = "auto";
01455                 else
01456                 if (attrval_int)
01457                     attrval = "true";
01458                 else
01459                     attrval = "false";
01460                 break;
01461             case TAFF_ATTRTYPE_SEQUENCE_MODE:
01462                 if ((attrval_int & 0xff) == 0x01)
01463                     attrval = "linear";
01464                 else
01465                 if ((attrval_int & 0xff) == 0x02)
01466                     attrval = "log";
01467                 else
01468                 if ((attrval_int & 0xff) == 0x03)
01469                     attrval = "log_soft_start";
01470                 else
01471                 if ((attrval_int & 0xff) == 0x04)
01472                     attrval = "log_soft_end";
01473                 else
01474                 if (attrval_int)
01475                     attrval = "true";
01476                 else
01477                     attrval = "false";
01478                 break;
01479             case TAFF_ATTRTYPE_COLOR:
01480                 attrval = getMMSFBColorString(MMSFBColor((unsigned int)attrval_int));
01481                 break;
01482             default:
01483                 attrval = attrval_str;
01484                 break;
01485             }
01486 
01487             if (this->trace)
01488                 printf(" Attribute \"%s\" found, ID=%d, value=\"%s\"\n", attr[attrid].name, attrid, attrval.c_str());
01489 
01490             if (external_file) {
01491                 *wb = '\n';
01492                 memset(&wb[1], ' ', depth*4+4);
01493                 sprintf(&wb[1+depth*4+4], "%s = \"%s\"", attr[attrid].name, attrval.c_str());
01494                 writeBuffer(external_file, wb, &ritems, 1, strlen(wb));
01495             }
01496         }
01497         else {
01498             if (this->trace)
01499                 printf(" Attribute \"%s\" found without ID, value=\"%s\"\n", attr_name, attrval_str);
01500 
01501             if (external_file) {
01502                 *wb = '\n';
01503                 memset(&wb[1], ' ', depth*4+4);
01504                 sprintf(&wb[1+depth*4+4], "%s = \"%s\"", attr_name, attrval_str);
01505                 writeBuffer(external_file, wb, &ritems, 1, strlen(wb));
01506             }
01507         }
01508     }
01509 
01510     /* close tag */
01511     if (external_file) {
01512         sprintf(wb, ">\n");
01513         writeBuffer(external_file, wb, &ritems, 1, strlen(wb));
01514     }
01515 
01516     /* through my child tags */
01517     while (1) {
01518         bool eof;
01519         int tid = getNextTag(eof);
01520         if (tid < 0) {
01521             /* close tag */
01522             if (external_file) {
01523                 memset(wb, ' ', depth*4);
01524                 sprintf(&wb[depth*4], "</%s>\n", tagt->name);
01525                 writeBuffer(external_file, wb, &ritems, 1, strlen(wb));
01526             }
01527             return true;
01528         }
01529         if (convertTAFF2XML_throughDoc(depth+1, tid, external_file)==false)
01530             return false;
01531     }
01532 }
01533 
01534 bool MMSTaffFile::convertTAFF2XML() {
01535     if (!this->loaded) return false;
01536 
01537     /* get root tag */
01538     int tagid = getFirstTag();
01539     if (tagid < 0) return false;
01540 
01541     /* open binary destination file */
01542     MMSFile *external_file = NULL;
01543     if (this->external_filename!="")
01544         external_file = new MMSFile(this->external_filename.c_str(), MMSFM_WRITE);
01545 
01546     /* start with root */
01547     bool rc = convertTAFF2XML_throughDoc(0, tagid, external_file);
01548 
01549     if (external_file)
01550         delete external_file;
01551 
01552     return rc;
01553 }
01554 
01555 bool MMSTaffFile::convertTAFF2External() {
01556     switch (this->external_type) {
01557     case MMSTAFF_EXTERNAL_TYPE_XML:
01558         return convertTAFF2XML();
01559     case MMSTAFF_EXTERNAL_TYPE_IMAGE:
01560         printf("TAFF: Currently we cannot convert taff to image\n");
01561         return false;
01562     }
01563     return false;
01564 }
01565 
01566 bool MMSTaffFile::readFile() {
01567     if (this->taff_buf) {
01568         free(this->taff_buf);
01569         this->taff_buf = NULL;
01570     }
01571     this->loaded = false;
01572 
01573     if (!this->taff_desc) return false;
01574     if (this->taff_filename=="") return false;
01575 
01576     // load the file
01577     MMSFile *taff_file = new MMSFile(this->taff_filename.c_str(), MMSFM_READ, false);
01578     if (!taff_file) return false;
01579     size_t ritems;
01580     char taff_ident[32];
01581     if (!taff_file->readBuffer((void*)taff_ident, &ritems, 1, strlen(TAFF_IDENT))) {
01582         // read error
01583         this->taff_buf = NULL;
01584         delete taff_file;
01585         return false;
01586     }
01587     if (ritems == 0) {
01588         // file is empty
01589         printf("TAFF: File is empty (%s)\n", this->taff_filename.c_str());
01590         this->taff_buf = NULL;
01591         delete taff_file;
01592         return false;
01593     }
01594     if (memcmp(taff_ident, TAFF_IDENT, strlen(TAFF_IDENT))!=0) {
01595         // the first bytes of the file are different from TAFF_IDENT
01596         printf("TAFF: TAFF_IDENT mismatch (%s)\n", this->taff_filename.c_str());
01597         this->taff_buf = NULL;
01598         delete taff_file;
01599         return false;
01600     }
01601     if (!taff_file->readBufferEx((void**)&(this->taff_buf), &ritems)) {
01602         // read error
01603         this->taff_buf = NULL;
01604         delete taff_file;
01605         return false;
01606     }
01607     delete taff_file;
01608 
01609     if (ritems < 40) {
01610         // wrong size
01611         free(this->taff_buf);
01612         this->taff_buf = NULL;
01613         return false;
01614     }
01615 
01616     // check the version of the file
01617     this->correct_version = false;
01618     if (strcmp((char*)this->taff_buf, (char*)&(this->taff_desc->type))) {
01619         // wrong type
01620         printf("TAFF: Wrong TAFF type (%s)\n", this->taff_filename.c_str());
01621         free(this->taff_buf);
01622         this->taff_buf = NULL;
01623         return false;
01624     }
01625     if (memcmp(this->taff_buf+sizeof(this->taff_desc->type), &(this->taff_desc->version), sizeof(this->taff_desc->version))) {
01626         // wrong version
01627         free(this->taff_buf);
01628         this->taff_buf = NULL;
01629         return false;
01630     }
01631     this->correct_version = true;
01632 
01633     // compare the modification time of the taff and external file
01634     if (this->external_filename!="") {
01635         struct stat statbuf1;
01636         struct stat statbuf2;
01637         if (stat(this->taff_filename.c_str(), &statbuf1)!=0) {
01638             free(this->taff_buf);
01639             this->taff_buf = NULL;
01640             return false;
01641         }
01642         if (stat(this->external_filename.c_str(), &statbuf2)==0) {
01643             if (statbuf2.st_mtime <= time(NULL)) {
01644                 // ok, external file created in the past
01645                 if (statbuf2.st_mtime >= statbuf1.st_mtime) {
01646                     // external file has been modified, therefore the taff file maybe not up-to-date
01647                     free(this->taff_buf);
01648                     this->taff_buf = NULL;
01649                     return false;
01650                 }
01651             }
01652         }
01653     }
01654 
01655     // all right
01656     this->taff_buf_size = ritems;
01657     getFirstTag();
01658     this->loaded = true;
01659     return true;
01660 }
01661 
01662 bool MMSTaffFile::isLoaded() {
01663     return this->loaded;
01664 }
01665 
01666 bool MMSTaffFile::checkVersion() {
01667     return this->correct_version;
01668 }
01669 
01670 void MMSTaffFile::setExternal(string external_filename, MMSTAFF_EXTERNAL_TYPE external_type) {
01671     this->external_filename = external_filename;
01672     this->external_type = external_type;
01673 }
01674 
01675 void MMSTaffFile::setTrace(bool trace) {
01676     this->trace = trace;
01677 }
01678 
01679 void MMSTaffFile::setPrintWarnings(bool print_warnings) {
01680     this->print_warnings = print_warnings;
01681 }
01682 
01683 void MMSTaffFile::setDestinationPixelFormat(MMSTAFF_PF pixelformat, bool premultiplied) {
01684     this->destination_pixelformat = pixelformat;
01685     this->destination_premultiplied = premultiplied;
01686 }
01687 
01688 void MMSTaffFile::setMirrorEffect(int size) {
01689     this->mirror_size = size;
01690 }
01691 
01692 void MMSTaffFile::rotate180(bool rotate_180) {
01693     this->rotate_180 = rotate_180;
01694 }
01695 
01696 int MMSTaffFile::getFirstTag() {
01697     this->taff_buf_pos = sizeof(this->taff_desc->type) + sizeof(this->taff_desc->version);
01698     this->current_tag = -1;
01699     this->current_tag_pos = 0;
01700 
01701     if (this->taff_buf[this->taff_buf_pos] == MMSTAFF_TAGTABLE_TYPE_TAG) {
01702         bool eof;
01703         return getNextTag(eof);
01704     }
01705 
01706     return this->current_tag;
01707 }
01708 
01709 int MMSTaffFile::getNextTag(bool &eof) {
01710     /* searching for next tag */
01711     eof = false;
01712     while (this->taff_buf_pos < this->taff_buf_size) {
01713         switch (this->taff_buf[this->taff_buf_pos]) {
01714         case MMSTAFF_TAGTABLE_TYPE_TAG:
01715             this->current_tag = this->taff_buf[this->taff_buf_pos+1];
01716             this->current_tag_pos = this->taff_buf_pos;
01717             this->taff_buf_pos+=2;
01718             return this->current_tag;
01719         case MMSTAFF_TAGTABLE_TYPE_ATTR: {
01720                 this->taff_buf_pos+=2;
01721                 int len;
01722 
01723                 /* check if name of attribute is stored instead of id */
01724                 if (this->taff_buf[this->taff_buf_pos-1] == MMSTAFF_ATTR_WITHOUT_ID) {
01725                     len = MMSTAFF_INT32_FROM_UCHAR_STREAM(&this->taff_buf[this->taff_buf_pos]);
01726                     this->taff_buf_pos+=sizeof(int);
01727                     this->taff_buf_pos+=len;
01728                 }
01729 
01730                 /* get the length of the value */
01731                 len = (int)this->taff_buf[this->taff_buf_pos];
01732                 this->taff_buf_pos++;
01733                 if (len >= 0xff) {
01734                     len = MMSTAFF_INT32_FROM_UCHAR_STREAM(&this->taff_buf[this->taff_buf_pos]);
01735                     this->taff_buf_pos+=sizeof(int);
01736                 }
01737                 this->taff_buf_pos+=len;
01738             }
01739             break;
01740         case MMSTAFF_TAGTABLE_TYPE_CLOSETAG:
01741             this->current_tag = -1;
01742             this->taff_buf_pos+=2;
01743             eof = false;
01744             return this->current_tag;
01745         default:
01746             this->current_tag = -1;
01747             this->current_tag_pos = 0;
01748             eof = true;
01749             return this->current_tag;
01750         }
01751     }
01752     this->current_tag = -1;
01753     this->current_tag_pos = 0;
01754     eof = true;
01755     return this->current_tag;
01756 }
01757 
01758 int MMSTaffFile::getCurrentTag(const char **name) {
01759     if (name) *name = this->taff_desc->tagtable[this->current_tag].name;
01760     return this->current_tag;
01761 }
01762 
01763 const char *MMSTaffFile::getCurrentTagName() {
01764     return this->taff_desc->tagtable[this->current_tag].name;
01765 }
01766 
01767 MMSTaffFile *MMSTaffFile::copyCurrentTag() {
01768     MMSTaffFile *mytafff = NULL;
01769     int tag_cnt, closetag_cnt;
01770 
01771     if (!this->current_tag_pos)
01772         return NULL;
01773 
01774     /* save buffer positions */
01775     int saved_taff_buf_pos = this->taff_buf_pos;
01776     int saved_current_tag = this->current_tag;
01777     int saved_current_tag_pos = this->current_tag_pos;
01778 
01779     /* go to the position after the current tag */
01780     this->taff_buf_pos = this->current_tag_pos;
01781 
01782     /* searching the close tag of this tag */
01783     tag_cnt = 0;
01784     closetag_cnt = 0;
01785     do {
01786         bool eof;
01787         if (getNextTag(eof) < 0) {
01788             if (eof) break;
01789             closetag_cnt++;
01790         }
01791         else
01792             tag_cnt++;
01793     } while (tag_cnt > closetag_cnt);
01794 
01795     /* all right? */
01796     if (tag_cnt == closetag_cnt) {
01797         /* yes, allocate memory and copy buffer */
01798         mytafff = new MMSTaffFile("", this->taff_desc, "", this->external_type,
01799                                   this->ignore_blank_values, this->trace, false);
01800         if (mytafff) {
01801             int len = this->taff_buf_pos - saved_current_tag_pos;
01802             mytafff->taff_buf_size = sizeof(this->taff_desc->type) + sizeof(this->taff_desc->version) + len;
01803             mytafff->taff_buf = (unsigned char *)malloc(mytafff->taff_buf_size);
01804             if (mytafff->taff_buf) {
01805                 /* copy & init */
01806                 memcpy(mytafff->taff_buf, this->taff_buf, sizeof(this->taff_desc->type) + sizeof(this->taff_desc->version));
01807                 memcpy(&(mytafff->taff_buf[sizeof(this->taff_desc->type) + sizeof(this->taff_desc->version)]),
01808                        &(this->taff_buf[saved_current_tag_pos]), len);
01809                 mytafff->getFirstTag();
01810                 mytafff->loaded = true;
01811                 mytafff->correct_version = true;
01812             }
01813             else {
01814                 /* out of memory */
01815                 delete mytafff;
01816                 mytafff = NULL;
01817             }
01818         }
01819     }
01820 
01821     /* restore the old buffer positions */
01822     this->taff_buf_pos = saved_taff_buf_pos;
01823     this->current_tag = saved_current_tag;
01824     this->current_tag_pos = saved_current_tag_pos;
01825 
01826     return mytafff;
01827 }
01828 
01829 
01830 bool MMSTaffFile::hasAttributes() {
01831     char *value_str;
01832     int value_int;
01833     char *name;
01834     return (getFirstAttribute(&value_str, &value_int, &name) >= 0);
01835 }
01836 
01837 
01838 int MMSTaffFile::getFirstAttribute(char **value_str, int *value_int, char **name) {
01839     if (!this->current_tag_pos)
01840         return -1;
01841 
01842     /* go to the position after the current tag */
01843     this->taff_buf_pos = this->current_tag_pos;
01844     this->taff_buf_pos+=2;
01845 
01846     /* get the attribute */
01847     if (this->taff_buf[this->taff_buf_pos] == MMSTAFF_TAGTABLE_TYPE_ATTR)
01848         return getNextAttribute(value_str, value_int, name);
01849 
01850     return -1;
01851 }
01852 
01853 int MMSTaffFile::getNextAttribute(char **value_str, int *value_int, char **name) {
01854     /* searching for next attribute */
01855     do {
01856         switch (this->taff_buf[this->taff_buf_pos]) {
01857         case MMSTAFF_TAGTABLE_TYPE_ATTR: {
01858                 int attrid = (int)this->taff_buf[this->taff_buf_pos+1];
01859                 int len;
01860                 this->taff_buf_pos+=2;
01861 
01862                 /* check if name of attribute is stored instead of id */
01863                 if (attrid == MMSTAFF_ATTR_WITHOUT_ID) {
01864                     len = MMSTAFF_INT32_FROM_UCHAR_STREAM(&this->taff_buf[this->taff_buf_pos]);
01865                     this->taff_buf_pos+=sizeof(int);
01866                     if (name)
01867                         *name = (char*)&this->taff_buf[this->taff_buf_pos];
01868                     this->taff_buf_pos+=len;
01869                 }
01870                 else
01871                     if (name) *name=NULL;
01872 
01873                 /* get the length of the value */
01874                 len = (int)this->taff_buf[this->taff_buf_pos];
01875                 this->taff_buf_pos++;
01876                 if (len >= 0xff) {
01877                     len = MMSTAFF_INT32_FROM_UCHAR_STREAM(&this->taff_buf[this->taff_buf_pos]);
01878                     this->taff_buf_pos+=sizeof(int);
01879                 }
01880 
01881                 /* check the type of value and set the return values */
01882                 if (attrid != MMSTAFF_ATTR_WITHOUT_ID) {
01883                     TAFF_ATTRDESC *attr = this->taff_desc->tagtable[current_tag].attr;
01884                     switch (attr[attrid].type) {
01885                     case TAFF_ATTRTYPE_BOOL:
01886                     case TAFF_ATTRTYPE_UCHAR:
01887                     case TAFF_ATTRTYPE_UCHAR100:
01888                     case TAFF_ATTRTYPE_STATE:
01889                     case TAFF_ATTRTYPE_SEQUENCE_MODE:
01890                         *value_str = NULL;
01891                         {   unsigned char v = this->taff_buf[this->taff_buf_pos];
01892                             *value_int = (int)v; }
01893                         break;
01894                     case TAFF_ATTRTYPE_INT:
01895                     case TAFF_ATTRTYPE_COLOR:
01896                         *value_str = NULL;
01897                         *value_int = MMSTAFF_INT32_FROM_UCHAR_STREAM(&this->taff_buf[this->taff_buf_pos]);
01898                         break;
01899                     default:
01900                         *value_str = (char*)&this->taff_buf[this->taff_buf_pos];
01901                         break;
01902                     }
01903                 }
01904                 else
01905                 if (name) {
01906                     *value_str = (char*)&this->taff_buf[this->taff_buf_pos];
01907                 }
01908                 this->taff_buf_pos+=len;
01909 
01910                 if (!((attrid == MMSTAFF_ATTR_WITHOUT_ID)&&(!name)))
01911                     /* return attribute ID */
01912                     return attrid;
01913 
01914                 /* attribute has no ID and name is not set, go to the next attribute */
01915                 break;
01916             }
01917             break;
01918         default:
01919             return -1;
01920         }
01921     } while (this->taff_buf_pos < this->taff_buf_size);
01922     return -1;
01923 }
01924 
01925 bool MMSTaffFile::getAttribute(int id, char **value_str, int *value_int) {
01926     char *attr_name;
01927     int attrid = getFirstAttribute(value_str, value_int, &attr_name);
01928     while (attrid >= 0) {
01929         if (attrid == id)
01930             return true;
01931         attrid = getNextAttribute(value_str, value_int, &attr_name);
01932     }
01933     return false;
01934 }
01935 
01936 char *MMSTaffFile::getAttributeString(int id) {
01937     char *value_str = NULL;
01938     int  value_int;
01939     if (getAttribute(id, &value_str, &value_int))
01940         if (value_str)
01941             return value_str;
01942     return NULL;
01943 }
01944 
01945 
01946 TAFF_ATTRDESC MMSTAFF_IMAGE_RAWIMAGE_ATTR_I[]   = MMSTAFF_IMAGE_RAWIMAGE_ATTR_INIT;
01947 
01948 TAFF_TAGTABLE mmstaff_image_taff_tagtable[] = {
01949     {   "rawimage",     NULL,   NULL,           MMSTAFF_IMAGE_RAWIMAGE_ATTR_I   },
01950     {   NULL,           NULL,   NULL,           NULL                            }
01951 };
01952 
01953 TAFF_DESCRIPTION mmstaff_image_taff_description = { "mmstaff_image", 4, mmstaff_image_taff_tagtable };
01954 
01955 

Generated by doxygen