00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
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
00092 bool ret = false;
00093 if (!force_rewrite_taff)
00094 ret = readFile();
00095 if (!ret)
00096
00097 if ((force_rewrite_taff)||(auto_rewrite_taff)) {
00098 if (convertExternal2TAFF()) {
00099 if (this->taff_filename != "") {
00100
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
00116 if (!mmsfile->writeBuffer(ptr, ritems, size, nitems)) {
00117
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
00125 memcpy(&this->taff_buf[taff_buf_pos], ptr, size * nitems);
00126 this->taff_buf_pos+= size * nitems;
00127
00128
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
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
00145 *src = ((((s & 0x00ff00ff) * sa) >> 8) & 0x00ff00ff) |
00146 ((((s & 0x0000ff00) * sa) >> 8) & 0x0000ff00) |
00147 ((((s & 0xff000000))));
00148 src++;
00149 }
00150 }
00151
00152
00153 if (this->mirror_size > 0) {
00154
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
00176 *height = (*height) + this->mirror_size;
00177 *size = (*pitch) * (*height);
00178 }
00179
00180 if (this->rotate_180) {
00181
00182 rotateUIntBuffer180((unsigned int*)*buf, *pitch, *width, *height);
00183 }
00184
00185
00186 bool has_alpha = false;
00187 switch (this->destination_pixelformat) {
00188 case MMSTAFF_PF_ARGB:
00189 if (*alphachannel) {
00190
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
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
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;
00228 if (s) {
00229 s = s | (((((66*r+129*g+25*b+128)>>8)+16) & 0xff) << 16);
00230 s = s | (((((-38*r-74*g+112*b+128)>>8)+128) & 0xff) << 8);
00231 s = s | ((((112*r-94*g-18*b+128)>>8)+128) & 0xff);
00232 }
00233 *src = s;
00234 src++;
00235 }
00236 }
00237 break;
00238 case MMSTAFF_PF_ARGB4444: {
00239
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
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
00267 free(*buf);
00268 *buf = newbuf;
00269 }
00270 break;
00271 case MMSTAFF_PF_RGB16: {
00272
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
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
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
00293 unsigned int r = 0;
00294 unsigned int g = 0;
00295 unsigned int b = 0;
00296
00297
00298 r = SA * r;
00299 g = SA * g;
00300 b = (SA * b) >> 5;
00301
00302
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
00315 free(*buf);
00316 *buf = newbuf;
00317 }
00318 break;
00319 case MMSTAFF_PF_ABGR: {
00320
00321
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
00341
00342
00343
00344 *alphachannel = has_alpha;
00345 }
00346
00347 return true;
00348 }
00349
00350
00351
00352 #ifdef __HAVE_PNG__
00353
00354
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
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
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
00415 png_set_read_fn(png_ptr, file, MMSTaff_read_png_data_callback);
00416
00417 if(setjmp(png_jmpbuf(png_ptr))) {
00418
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
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
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
00455 png_destroy_read_struct(&png_ptr, &info_ptr, &end_info_ptr);
00456 delete file;
00457 return false;
00458 }
00459
00460
00461 if (bit_depth == 16) {
00462
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
00476 png_set_palette_to_rgb(png_ptr);
00477 }
00478 if (color_type == PNG_COLOR_TYPE_GRAY) {
00479
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
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
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
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
00520 png_read_image(png_ptr, row_pointers);
00521 png_read_end(png_ptr, end_info_ptr);
00522
00523
00524 png_destroy_read_struct(&png_ptr, &info_ptr, &end_info_ptr);
00525 free(row_pointers);
00526 delete file;
00527
00528
00529
00530
00531
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;
00543 jmp_buf setjmpBuffer;
00544 };
00545
00546 METHODDEF(void) JPEGErrorExit(j_common_ptr cinfo) {
00547
00548 struct JPEGErrorManager *myerr = (struct JPEGErrorManager*)cinfo->err;
00549
00550
00551
00552 (*cinfo->err->output_message)(cinfo);
00553
00554
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;
00566 int rowStride;
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
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
00627 *width = (int)cinfo.image_width;
00628 *height = (int)cinfo.image_height;
00629 *pitch = *width * 4;
00630 *size = *pitch * *height;
00631
00632
00633 *alphachannel = false;
00634
00635
00636 cinfo.out_color_space = JCS_RGB;
00637
00638
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
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
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
00703 *alphachannel = true;
00704
00705
00706 if(this->mirror_size > *height) this->mirror_size = *height;
00707
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
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
00729 TIFFClose(tiff);
00730
00731
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
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
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
00927 cur_node = node;
00928 else
00929
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
00940 if (this->taff_desc->tagtable[tagid].typeattr)
00941 {
00942
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
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
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
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
01013 return false;
01014 }
01015
01016 if (!attrValStr_valid && !int_val_set && !byte_val_set) {
01017
01018 continue;
01019 }
01020
01021
01022
01023 if (taff_file) {
01024 if (!int_val_set && !byte_val_set) {
01025
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
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
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
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
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
01071
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
01080 if (taff_file) {
01081
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
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
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
01111 if (!convertXML2TAFF_throughDoc(depth+1, cur_node, taff_file))
01112 return false;
01113
01114
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
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
01148 if (!this->taff_desc || this->external_filename.empty()) {
01149 return false;
01150 }
01151
01152
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
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
01176 delete taff_file;
01177 xmlFreeDoc(parser);
01178
01179
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
01188 xmlNode* node = xmlDocGetRootElement(parser);
01189
01190
01191 rc = convertXML2TAFF_throughDoc(0, node, taff_file);
01192
01193
01194 if (taff_file)
01195 delete taff_file;
01196 xmlFreeDoc(parser);
01197
01198 if (!rc) {
01199
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
01221 if (!this->taff_desc || this->external_filename.empty()) {
01222 return false;
01223 }
01224
01225
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
01374 rc = wok;
01375
01376
01377 if (taff_file) {
01378 delete taff_file;
01379 }
01380 else {
01381
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
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
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
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
01511 if (external_file) {
01512 sprintf(wb, ">\n");
01513 writeBuffer(external_file, wb, &ritems, 1, strlen(wb));
01514 }
01515
01516
01517 while (1) {
01518 bool eof;
01519 int tid = getNextTag(eof);
01520 if (tid < 0) {
01521
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
01538 int tagid = getFirstTag();
01539 if (tagid < 0) return false;
01540
01541
01542 MMSFile *external_file = NULL;
01543 if (this->external_filename!="")
01544 external_file = new MMSFile(this->external_filename.c_str(), MMSFM_WRITE);
01545
01546
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
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
01583 this->taff_buf = NULL;
01584 delete taff_file;
01585 return false;
01586 }
01587 if (ritems == 0) {
01588
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
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
01603 this->taff_buf = NULL;
01604 delete taff_file;
01605 return false;
01606 }
01607 delete taff_file;
01608
01609 if (ritems < 40) {
01610
01611 free(this->taff_buf);
01612 this->taff_buf = NULL;
01613 return false;
01614 }
01615
01616
01617 this->correct_version = false;
01618 if (strcmp((char*)this->taff_buf, (char*)&(this->taff_desc->type))) {
01619
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
01627 free(this->taff_buf);
01628 this->taff_buf = NULL;
01629 return false;
01630 }
01631 this->correct_version = true;
01632
01633
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
01645 if (statbuf2.st_mtime >= statbuf1.st_mtime) {
01646
01647 free(this->taff_buf);
01648 this->taff_buf = NULL;
01649 return false;
01650 }
01651 }
01652 }
01653 }
01654
01655
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
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
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
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
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
01780 this->taff_buf_pos = this->current_tag_pos;
01781
01782
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
01796 if (tag_cnt == closetag_cnt) {
01797
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
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
01815 delete mytafff;
01816 mytafff = NULL;
01817 }
01818 }
01819 }
01820
01821
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
01843 this->taff_buf_pos = this->current_tag_pos;
01844 this->taff_buf_pos+=2;
01845
01846
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
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
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
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
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
01912 return attrid;
01913
01914
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