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