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
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056 #include "TASImage.h"
00057 #include "TASImagePlugin.h"
00058 #include "TROOT.h"
00059 #include "TMath.h"
00060 #include "TSystem.h"
00061 #include "TVirtualX.h"
00062 #include "TVirtualPad.h"
00063 #include "TArrayD.h"
00064 #include "TVectorD.h"
00065 #include "TVirtualPS.h"
00066 #include "TGaxis.h"
00067 #include "TColor.h"
00068 #include "TObjArray.h"
00069 #include "TArrayL.h"
00070 #include "TPoint.h"
00071 #include "TFrame.h"
00072 #include "TTF.h"
00073 #include "TRandom.h"
00074 #include "Riostream.h"
00075 #include "THashTable.h"
00076 #include "TPluginManager.h"
00077 #include "TEnv.h"
00078 #include "TStyle.h"
00079 #include "TText.h"
00080
00081
00082 #ifndef WIN32
00083 # include <X11/Xlib.h>
00084 #else
00085 # include "Windows4root.h"
00086 #endif
00087 extern "C" {
00088 #ifndef WIN32
00089 # include <afterbase.h>
00090 #else
00091 # include <win32/config.h>
00092 # include <win32/afterbase.h>
00093 # define X_DISPLAY_MISSING 1
00094 #endif
00095 # include <afterimage.h>
00096 # include <bmp.h>
00097 # include <draw.h>
00098 }
00099
00100
00101 #include "TASPolyUtils.c"
00102
00103
00104 ASVisual *TASImage::fgVisual = 0;
00105 Bool_t TASImage::fgInit = kFALSE;
00106
00107 static ASFontManager *gFontManager = 0;
00108 static unsigned long kAllPlanes = ~0;
00109 THashTable *TASImage::fgPlugList = new THashTable(50);
00110
00111
00112 static char *gIconPaths[7] = {0, 0, 0, 0, 0, 0, 0};
00113
00114
00115
00116 #if defined(__GNUC__) && __GNUC__ >= 4 && ((__GNUC_MINOR__ == 2 && __GNUC_PATCHLEVEL__ >= 1) || (__GNUC_MINOR__ >= 3)) && !__INTEL_COMPILER
00117 #pragma GCC diagnostic ignored "-Wstrict-aliasing"
00118 #endif
00119
00120 #ifdef R__BYTESWAP
00121 typedef struct {
00122 unsigned char b;
00123 unsigned char g;
00124 unsigned char r;
00125 unsigned char a;
00126 } __argb32__;
00127 #else
00128 typedef struct {
00129 unsigned char a;
00130 unsigned char r;
00131 unsigned char g;
00132 unsigned char b;
00133 } __argb32__;
00134 #endif
00135
00136
00137
00138 #define _alphaBlend(bot, top) {\
00139 __argb32__ *t = (__argb32__*)(top);\
00140 __argb32__ *b = (__argb32__*)(bot);\
00141 int aa = 255-t->a;\
00142 if (!aa) {\
00143 *bot = *top;\
00144 } else { \
00145 b->a = ((b->a*aa)>>8) + t->a;\
00146 b->r = (b->r*aa + t->r*t->a)>>8;\
00147 b->g = (b->g*aa + t->g*t->a)>>8;\
00148 b->b = (b->b*aa + t->b*t->a)>>8;\
00149 }\
00150 }\
00151
00152
00153 ClassImp(TASImage)
00154 ClassImp(TASImagePlugin)
00155
00156
00157
00158 void TASImage::DestroyImage()
00159 {
00160
00161
00162 if (fImage) {
00163 destroy_asimage(&fImage);
00164 }
00165
00166 if (fIsGray && fGrayImage) {
00167 destroy_asimage(&fGrayImage);
00168 }
00169
00170 fIsGray = kFALSE;
00171 fGrayImage = 0;
00172 fImage = 0;
00173 }
00174
00175
00176
00177 void TASImage::SetDefaults()
00178 {
00179
00180
00181 fImage = 0;
00182 fScaledImage = 0;
00183 fMaxValue = 1;
00184 fMinValue = 0;
00185 fEditable = kFALSE;
00186 fPaintMode = 1;
00187 fZoomOffX = 0;
00188 fZoomOffY = 0;
00189 fZoomWidth = 0;
00190 fZoomHeight = 0;
00191 fZoomUpdate = kZoomOps;
00192
00193 fGrayImage = 0;
00194 fIsGray = kFALSE;
00195 fPaletteEnabled = kFALSE;
00196
00197 if (!fgInit) {
00198 set_application_name((char*)(gProgName ? gProgName : "ROOT"));
00199 fgInit = kTRUE;
00200 }
00201 }
00202
00203
00204
00205 TASImage::TASImage()
00206 {
00207
00208
00209 SetDefaults();
00210 }
00211
00212
00213
00214 TASImage::TASImage(UInt_t w, UInt_t h) : TImage(w, h)
00215 {
00216
00217
00218 SetDefaults();
00219 fImage = create_asimage(w ? w : 20, h ? h : 20, 0);
00220 UnZoom();
00221 }
00222
00223
00224
00225 TASImage::TASImage(const char *file, EImageFileTypes) : TImage(file)
00226 {
00227
00228
00229
00230
00231 SetDefaults();
00232 TString fname = file;
00233 gSystem->ExpandPathName(fname);
00234 ReadImage(fname.Data());
00235 }
00236
00237
00238
00239 TASImage::TASImage(const char *name, const Double_t *imageData, UInt_t width,
00240 UInt_t height, TImagePalette *palette) : TImage(name)
00241 {
00242
00243
00244
00245
00246 SetDefaults();
00247 SetImage(imageData, width, height, palette);
00248 }
00249
00250
00251
00252 TASImage::TASImage(const char *name, const TArrayD &imageData, UInt_t width,
00253 TImagePalette *palette) : TImage(name)
00254 {
00255
00256
00257
00258
00259
00260 SetDefaults();
00261 SetImage(imageData, width, palette);
00262 }
00263
00264
00265
00266 TASImage::TASImage(const char *name, const TVectorD &imageData, UInt_t width,
00267 TImagePalette *palette) : TImage(name)
00268 {
00269
00270
00271
00272
00273
00274 SetDefaults();
00275 SetImage(imageData, width, palette);
00276 }
00277
00278
00279
00280 TASImage::TASImage(const TASImage &img) : TImage(img)
00281 {
00282
00283
00284 SetDefaults();
00285
00286 if (img.IsValid()) {
00287 fImage = clone_asimage(img.fImage, SCL_DO_ALL);
00288 fScaledImage = fScaledImage ? (TASImage*)img.fScaledImage->Clone("") : 0;
00289 fGrayImage = fGrayImage ? clone_asimage(img.fGrayImage, SCL_DO_ALL) : 0;
00290
00291 if (img.fImage->alt.vector) {
00292 Int_t size = img.fImage->width * img.fImage->height * sizeof(double);
00293 fImage->alt.vector = (double*)malloc(size);
00294 memcpy(fImage->alt.vector, img.fImage->alt.vector, size);
00295 }
00296
00297 fZoomUpdate = kNoZoom;
00298 fZoomOffX = img.fZoomOffX;
00299 fZoomOffY = img.fZoomOffY;
00300 fZoomWidth = img.fZoomWidth;
00301 fZoomHeight = img.fZoomHeight;
00302 fEditable = img.fEditable;
00303 fIsGray = img.fIsGray;
00304 }
00305 }
00306
00307
00308
00309 TASImage &TASImage::operator=(const TASImage &img)
00310 {
00311
00312
00313 SetDefaults();
00314
00315 if (this != &img && img.IsValid()) {
00316 TImage::operator=(img);
00317
00318 DestroyImage();
00319 delete fScaledImage;
00320 fImage = clone_asimage(img.fImage, SCL_DO_ALL);
00321 fScaledImage = fScaledImage ? (TASImage*)img.fScaledImage->Clone("") : 0;
00322 fGrayImage = fGrayImage ? clone_asimage(img.fGrayImage, SCL_DO_ALL) : 0;
00323
00324 if (img.fImage->alt.vector) {
00325 Int_t size = img.fImage->width * img.fImage->height * sizeof(double);
00326 fImage->alt.vector = (double*)malloc(size);
00327 memcpy(fImage->alt.vector, img.fImage->alt.vector, size);
00328 }
00329
00330 fScaledImage = img.fScaledImage ? (TASImage*)img.fScaledImage->Clone("") : 0;
00331 fZoomUpdate = kNoZoom;
00332 fZoomOffX = img.fZoomOffX;
00333 fZoomOffY = img.fZoomOffY;
00334 fZoomWidth = img.fZoomWidth;
00335 fZoomHeight = img.fZoomHeight;
00336 fEditable = img.fEditable;
00337 fIsGray = img.fIsGray;
00338 fPaintMode = 1;
00339 }
00340
00341 return *this;
00342 }
00343
00344
00345
00346 TASImage::~TASImage()
00347 {
00348
00349
00350 DestroyImage();
00351 delete fScaledImage;
00352 fScaledImage = 0;
00353 }
00354
00355
00356
00357 static void init_icon_paths()
00358 {
00359
00360
00361 const char *icons = "/icons";
00362 #ifdef R__WIN32
00363 icons = "\\icons";
00364 #endif
00365
00366 TString homeIcons = gSystem->HomeDirectory();
00367 homeIcons += icons;
00368
00369 TString rootIcons = gSystem->Getenv("ROOTSYS");
00370 rootIcons += icons;
00371
00372 TString guiIcons = gEnv->GetValue("Gui.IconPath", "");
00373
00374 gIconPaths[0] = StrDup(".");
00375 gIconPaths[1] = StrDup(homeIcons.Data());
00376 gIconPaths[2] = StrDup(rootIcons.Data());
00377 gIconPaths[3] = StrDup(guiIcons.Data());
00378
00379 #ifdef ROOTICONPATH
00380 gIconPaths[4] = ROOTICONPATH;
00381 #endif
00382
00383 #ifdef EXTRAICONPATH
00384 gIconPaths[5] = EXTRAICONPATH;
00385 #endif
00386
00387 gIconPaths[6] = 0;
00388 }
00389
00390
00391
00392 const char *TASImage::TypeFromMagicNumber(const char *file)
00393 {
00394
00395
00396 UChar_t magic;
00397 FILE *fp = fopen(file, "rb");
00398 const char *ret = "";
00399
00400 if (!fp) return 0;
00401
00402 if (!fread(&magic, 1, 1, fp)) {
00403 fclose(fp);
00404 return 0;
00405 }
00406
00407 switch (magic) {
00408 case 0x00:
00409 {
00410 if (!fread(&magic, 1, 1, fp)) return 0;
00411 if (!fread(&magic, 1, 1, fp)) return 0;
00412
00413 ret = (magic == 1) ? "ico" : "cur";
00414 break;
00415 }
00416 case 0x25:
00417 {
00418 if (!fread(&magic, 1, 1, fp)) return 0;
00419 if (magic == 0x21) ret = "ps";
00420 else if (magic == 0x50) ret = "pdf";
00421 break;
00422 }
00423 case 0x42:
00424 ret = "bmp";
00425 break;
00426 case 0x47:
00427 ret = "gif";
00428 break;
00429 case 0x54:
00430 ret = "tga";
00431 break;
00432 case 0x49:
00433 ret = "tiff";
00434 break;
00435 case 0x89:
00436 ret = "png";
00437 break;
00438 case 0xff:
00439 ret = "jpg";
00440 break;
00441 default:
00442 ret = "";
00443 }
00444
00445 fclose(fp);
00446 return ret;
00447 }
00448
00449
00450
00451 void TASImage::ReadImage(const char *filename, EImageFileTypes )
00452 {
00453
00454
00455
00456
00457
00458
00459
00460
00461
00462
00463
00464
00465
00466
00467
00468
00469 if (!InitVisual()) {
00470 Warning("Scale", "Visual not initiated");
00471 return;
00472 }
00473
00474 Bool_t xpm = filename && (filename[0] == '/' &&
00475 filename[1] == '*') && filename[2] == ' ';
00476
00477 if (xpm) {
00478 SetImageBuffer((char**)&filename, TImage::kXpm);
00479 fName = "XPM_image";
00480 return;
00481 }
00482
00483 if (!gIconPaths[0]) {
00484 init_icon_paths();
00485 }
00486
00487 set_output_threshold(0);
00488
00489 static ASImageImportParams iparams;
00490 iparams.flags = 0;
00491 iparams.width = 0;
00492 iparams.height = 0;
00493 iparams.filter = SCL_DO_ALL;
00494 iparams.gamma = SCREEN_GAMMA;
00495 iparams.gamma_table = NULL;
00496 iparams.compression = GetImageCompression();
00497 iparams.format = ASA_ASImage;
00498 iparams.search_path = gIconPaths;
00499 iparams.subimage = 0;
00500 iparams.return_animation_delay = -1;
00501
00502 TString ext;
00503 const char *dot;
00504 if (filename) dot = strrchr(filename, '.');
00505 else dot = 0;
00506 ASImage *image = 0;
00507 TString fname = filename;
00508
00509 if (!dot) {
00510 if (filename) ext = TypeFromMagicNumber(filename);
00511 else ext = dot + 1;
00512 } else {
00513 ext = dot + 1;
00514 }
00515
00516 if (!ext.IsNull() && ext.IsDigit()) {
00517 iparams.subimage = ext.Atoi();
00518 fname = fname(0, fname.Length() - ext.Length() - 1);
00519 ext = strrchr(fname.Data(), '.') + 1;
00520 }
00521
00522 image = file2ASImage_extra(fname.Data(), &iparams);
00523
00524 if (image) {
00525 goto end;
00526 } else {
00527 if (ext.IsNull()) {
00528 return;
00529 }
00530 ext.ToLower();
00531 ext.Strip();
00532 UInt_t w = 0;
00533 UInt_t h = 0;
00534 unsigned char *bitmap = 0;
00535
00536 TImagePlugin *plug = (TImagePlugin*)fgPlugList->FindObject(ext.Data());
00537
00538 if (!plug) {
00539 TPluginHandler *handler = gROOT->GetPluginManager()->FindHandler("TImagePlugin", ext);
00540 if (!handler || ((handler->LoadPlugin() == -1))) {
00541 return;
00542 }
00543 plug = (TImagePlugin*)handler->ExecPlugin(1, ext.Data());
00544
00545 if (!plug) {
00546 return;
00547 }
00548
00549 fgPlugList->Add(plug);
00550 }
00551
00552 if (plug) {
00553 if (plug->InheritsFrom(TASImagePlugin::Class())) {
00554 image = ((TASImagePlugin*)plug)->File2ASImage(fname.Data());
00555 if (image) goto end;
00556 }
00557 bitmap = plug->ReadFile(fname.Data(), w, h);
00558 if (bitmap) {
00559 image = bitmap2asimage(bitmap, w, h, 0, 0);
00560 }
00561 if (!image) {
00562 return;
00563 }
00564 }
00565 }
00566
00567 end:
00568 fName.Form("%s.", gSystem->BaseName(fname.Data()));
00569
00570 DestroyImage();
00571 delete fScaledImage;
00572 fScaledImage = 0;
00573
00574 fImage = image;
00575 fZoomUpdate = kNoZoom;
00576 fEditable = kFALSE;
00577 fZoomOffX = 0;
00578 fZoomOffY = 0;
00579 fZoomWidth = fImage->width;
00580 fZoomHeight = fImage->height;
00581 fPaintMode = 1;
00582 }
00583
00584
00585
00586 void TASImage::WriteImage(const char *file, EImageFileTypes type)
00587 {
00588
00589
00590
00591
00592
00593
00594
00595
00596
00597
00598
00599
00600
00601
00602
00603
00604
00605
00606
00607
00608
00609
00610
00611
00612
00613
00614
00615
00616
00617
00618
00619
00620 if (!IsValid()) {
00621 Error("WriteImage", "no image loaded");
00622 return;
00623 }
00624
00625 if (!file || !*file) {
00626 Error("WriteImage", "no file name specified");
00627 return;
00628 }
00629
00630 const char *s;
00631 if ((s = strrchr(file, '.'))) {
00632 s++;
00633 EImageFileTypes t = GetFileType(s);
00634 if (t == kUnknown) {
00635 Error("WriteImage", "cannot determine a valid file type");
00636 return;
00637 }
00638 if (t != kUnknown)
00639 type = t;
00640 }
00641
00642 if (type == kUnknown) {
00643 Error("WriteImage", "not a valid file type was specified");
00644 return;
00645 }
00646
00647 UInt_t mytype;
00648 MapFileTypes(type, mytype);
00649 ASImageFileTypes atype = (ASImageFileTypes)mytype;
00650
00651 UInt_t aquality;
00652 EImageQuality quality = GetImageQuality();
00653 MapQuality(quality, aquality);
00654
00655 static TString fname;
00656 fname = file;
00657 static ASImageExportParams parms;
00658 ASImage *im = fScaledImage ? fScaledImage->fImage : fImage;
00659
00660 switch (type) {
00661 case kXpm:
00662 parms.xpm.type = atype;
00663 parms.xpm.flags = EXPORT_ALPHA;
00664 parms.xpm.dither = 4;
00665 parms.xpm.opaque_threshold = 127;
00666 parms.xpm.max_colors = 512;
00667 break;
00668 case kBmp:
00669 ASImage2bmp(im, fname.Data(), 0);
00670 return;
00671 case kXcf:
00672 ASImage2xcf(im, fname.Data(), 0);
00673 return;
00674 case kPng:
00675 parms.png.type = atype;
00676 parms.png.flags = EXPORT_ALPHA;
00677 parms.png.compression = !GetImageCompression() ? -1 : int(GetImageCompression());
00678 break;
00679 case kJpeg:
00680 parms.jpeg.type = atype;
00681 parms.jpeg.flags = 0;
00682 parms.jpeg.quality = aquality;
00683 break;
00684 case kGif:
00685 parms.gif.type = atype;
00686 parms.gif.flags = EXPORT_ALPHA;
00687 parms.gif.dither = 0;
00688 parms.gif.opaque_threshold = 0;
00689 break;
00690 case kAnimGif:
00691 {
00692 parms.gif.type = atype;
00693 parms.gif.flags = EXPORT_ALPHA | EXPORT_APPEND;
00694 parms.gif.dither = 0;
00695 parms.gif.opaque_threshold = 0;
00696 parms.gif.animate_repeats = 0;
00697
00698 s += 4;
00699 int delay = atoi(s);
00700
00701 if (delay < 0) {
00702 delay = 0;
00703 }
00704 if (s[0] == '+') {
00705 parms.gif.flags |= EXPORT_ANIMATION_REPEATS;
00706 s++;
00707 parms.gif.animate_repeats = atoi(s);
00708 }
00709
00710 parms.gif.animate_delay = delay;
00711
00712 int i1 = fname.Index("gif+");
00713 if (i1 != kNPOS) {
00714 fname = fname(0, i1 + 3);
00715 }
00716 break;
00717 }
00718 case kTiff:
00719 parms.tiff.type = atype;
00720 parms.tiff.flags = EXPORT_ALPHA;
00721 parms.tiff.rows_per_strip = 0;
00722 parms.tiff.compression_type = aquality <= 50 ? TIFF_COMPRESSION_JPEG :
00723 TIFF_COMPRESSION_NONE;
00724 parms.tiff.jpeg_quality = 100;
00725 parms.tiff.opaque_threshold = 0;
00726 break;
00727 default:
00728 Error("WriteImage", "file type %s not yet supported", s);
00729 return;
00730 }
00731
00732 if (!ASImage2file(im, 0, fname.Data(), atype, &parms)) {
00733 Error("WriteImage", "error writing file %s", file);
00734 }
00735 }
00736
00737
00738
00739 TImage::EImageFileTypes TASImage::GetFileType(const char *ext)
00740 {
00741
00742
00743
00744 TString s(ext);
00745 s.Strip();
00746 s.ToLower();
00747
00748 if (s == "xpm")
00749 return kXpm;
00750 if (s == "png")
00751 return kPng;
00752 if (s == "jpg" || s == "jpeg")
00753 return kJpeg;
00754 if (s == "xcf")
00755 return kXcf;
00756 if (s == "ppm")
00757 return kPpm;
00758 if (s == "pnm")
00759 return kPnm;
00760 if (s == "bmp")
00761 return kBmp;
00762 if (s == "ico")
00763 return kIco;
00764 if (s == "cur")
00765 return kCur;
00766 if (s == "gif")
00767 return kGif;
00768 if (s.Contains("gif+"))
00769 return kAnimGif;
00770 if (s == "tiff")
00771 return kTiff;
00772 if (s == "xbm")
00773 return kXbm;
00774 if (s == "tga")
00775 return kTga;
00776 if (s == "xml")
00777 return kXml;
00778
00779 return kUnknown;
00780 }
00781
00782
00783
00784 void TASImage::MapFileTypes(EImageFileTypes &type, UInt_t &astype, Bool_t toas)
00785 {
00786
00787
00788
00789 if (toas) {
00790 switch (type) {
00791 case kXpm:
00792 astype = ASIT_Xpm; break;
00793 case kZCompressedXpm:
00794 astype = ASIT_ZCompressedXpm; break;
00795 case kGZCompressedXpm:
00796 astype = ASIT_GZCompressedXpm; break;
00797 case kPng:
00798 astype = ASIT_Png; break;
00799 case kJpeg:
00800 astype = ASIT_Jpeg; break;
00801 case kXcf:
00802 astype = ASIT_Xcf; break;
00803 case kPpm:
00804 astype = ASIT_Ppm; break;
00805 case kPnm:
00806 astype = ASIT_Pnm; break;
00807 case kBmp:
00808 astype = ASIT_Bmp; break;
00809 case kIco:
00810 astype = ASIT_Ico; break;
00811 case kCur:
00812 astype = ASIT_Cur; break;
00813 case kGif:
00814 astype = ASIT_Gif; break;
00815 case kAnimGif:
00816 astype = ASIT_Gif; break;
00817 case kTiff:
00818 astype = ASIT_Tiff; break;
00819 case kXbm:
00820 astype = ASIT_Xbm; break;
00821 case kTga:
00822 astype = ASIT_Targa; break;
00823 case kXml:
00824 astype = ASIT_XMLScript; break;
00825 default:
00826 astype = ASIT_Unknown;
00827 }
00828 } else {
00829 switch (astype) {
00830 case ASIT_Xpm:
00831 type = kXpm; break;
00832 case ASIT_ZCompressedXpm:
00833 type = kZCompressedXpm; break;
00834 case ASIT_GZCompressedXpm:
00835 type = kGZCompressedXpm; break;
00836 case ASIT_Png:
00837 type = kPng; break;
00838 case ASIT_Jpeg:
00839 type = kJpeg; break;
00840 case ASIT_Xcf:
00841 type = kXcf; break;
00842 case ASIT_Ppm:
00843 type = kPpm; break;
00844 case ASIT_Pnm:
00845 type = kPnm; break;
00846 case ASIT_Bmp:
00847 type = kBmp; break;
00848 case ASIT_Ico:
00849 type = kIco; break;
00850 case ASIT_Cur:
00851 type = kCur; break;
00852 case ASIT_Gif:
00853 type = kGif; break;
00854 case ASIT_Tiff:
00855 type = kTiff; break;
00856 case ASIT_Xbm:
00857 type = kXbm; break;
00858 case ASIT_XMLScript:
00859 type = kXml; break;
00860 case ASIT_Targa:
00861 type = kTga; break;
00862 default:
00863 type = kUnknown;
00864 }
00865 }
00866 }
00867
00868
00869
00870 void TASImage::MapQuality(EImageQuality &quality, UInt_t &asquality, Bool_t toas)
00871 {
00872
00873
00874
00875 if (toas) {
00876 switch (quality) {
00877 case kImgPoor:
00878 asquality = 25; break;
00879 case kImgFast:
00880 asquality = 75; break;
00881 case kImgGood:
00882 asquality = 50; break;
00883 case kImgBest:
00884 asquality = 100; break;
00885 default:
00886 asquality = 0;
00887 }
00888 } else {
00889 quality = kImgDefault;
00890 if (asquality > 0 && asquality <= 25)
00891 quality = kImgPoor;
00892 if (asquality > 26 && asquality <= 50)
00893 quality = kImgFast;
00894 if (asquality > 51 && asquality <= 75)
00895 quality = kImgGood;
00896 if (asquality > 76 && asquality <= 100)
00897 quality = kImgBest;
00898 }
00899 }
00900
00901
00902
00903 void TASImage::SetImage(const Double_t *imageData, UInt_t width, UInt_t height,
00904 TImagePalette *palette)
00905 {
00906
00907
00908
00909
00910
00911
00912
00913 TAttImage::SetPalette(palette);
00914
00915 if (!InitVisual()) {
00916 Warning("SetImage", "Visual not initiated");
00917 return;
00918 }
00919
00920 DestroyImage();
00921 delete fScaledImage;
00922 fScaledImage = 0;
00923
00924
00925 fMinValue = fMaxValue = *imageData;
00926 for (Int_t pixel = 1; pixel < Int_t(width * height); pixel++) {
00927 if (fMinValue > *(imageData + pixel)) fMinValue = *(imageData + pixel);
00928 if (fMaxValue < *(imageData + pixel)) fMaxValue = *(imageData + pixel);
00929 }
00930
00931
00932 const TImagePalette &pal = GetPalette();
00933
00934 ASVectorPalette asPalette;
00935
00936 asPalette.npoints = pal.fNumPoints;
00937 Int_t col;
00938 for (col = 0; col < 4; col++)
00939 asPalette.channels[col] = new UShort_t[asPalette.npoints];
00940
00941 memcpy(asPalette.channels[0], pal.fColorBlue, pal.fNumPoints * sizeof(UShort_t));
00942 memcpy(asPalette.channels[1], pal.fColorGreen, pal.fNumPoints * sizeof(UShort_t));
00943 memcpy(asPalette.channels[2], pal.fColorRed, pal.fNumPoints * sizeof(UShort_t));
00944 memcpy(asPalette.channels[3], pal.fColorAlpha, pal.fNumPoints * sizeof(UShort_t));
00945
00946 asPalette.points = new Double_t[asPalette.npoints];
00947 for (Int_t point = 0; point < Int_t(asPalette.npoints); point++)
00948 asPalette.points[point] = fMinValue + (fMaxValue - fMinValue) * pal.fPoints[point];
00949
00950 fImage = create_asimage_from_vector(fgVisual, (Double_t*)imageData, width,
00951 height, &asPalette, ASA_ASImage,
00952 GetImageCompression(), GetImageQuality());
00953
00954 delete [] asPalette.points;
00955 for (col = 0; col < 4; col++)
00956 delete [] asPalette.channels[col];
00957
00958 fZoomUpdate = 0;
00959 fZoomOffX = 0;
00960 fZoomOffY = 0;
00961 fZoomWidth = width;
00962 fZoomHeight = height;
00963 fPaletteEnabled = kTRUE;
00964 }
00965
00966
00967
00968 void TASImage::SetImage(const TArrayD &imageData, UInt_t width, TImagePalette *palette)
00969 {
00970
00971
00972
00973
00974
00975
00976
00977 SetImage(imageData.GetArray(), width, imageData.GetSize() / width, palette);
00978 }
00979
00980
00981
00982 void TASImage::SetImage(const TVectorD &imageData, UInt_t width, TImagePalette *palette)
00983 {
00984
00985
00986
00987
00988
00989
00990
00991 SetImage(imageData.GetMatrixArray(), width,
00992 imageData.GetNoElements() / width, palette);
00993 }
00994
00995
00996
00997 void TASImage::FromPad(TVirtualPad *pad, Int_t x, Int_t y, UInt_t w, UInt_t h)
00998 {
00999
01000
01001
01002 if (!pad) {
01003 Error("FromPad", "pad cannot be 0");
01004 return;
01005 }
01006
01007 if (!InitVisual()) {
01008 Warning("FromPad", "Visual not initiated");
01009 return;
01010 }
01011
01012 SetName(pad->GetName());
01013
01014 DestroyImage();
01015 delete fScaledImage;
01016 fScaledImage = 0;
01017
01018 if (gROOT->IsBatch()) {
01019 TVirtualPS *psave = gVirtualPS;
01020 gVirtualPS = (TVirtualPS*)gROOT->ProcessLineFast("new TImageDump()");
01021 gVirtualPS->Open(pad->GetName(), 114);
01022 gVirtualPS->SetBit(BIT(11));
01023
01024 TASImage *itmp = (TASImage*)gVirtualPS->GetStream();
01025
01026 if (itmp && itmp->fImage) {
01027 itmp->BeginPaint();
01028 }
01029
01030 TVirtualPad *sav = gPad;
01031 gPad = pad;
01032 pad->Paint();
01033 gPad = sav;
01034
01035 if (itmp && itmp->fImage && (itmp != this)) {
01036 fImage = clone_asimage(itmp->fImage, SCL_DO_ALL);
01037 if (itmp->fImage->alt.argb32) {
01038 UInt_t sz = itmp->fImage->width*itmp->fImage->height;
01039 fImage->alt.argb32 = (ARGB32*)safemalloc(sz*sizeof(ARGB32));
01040 memcpy(fImage->alt.argb32, itmp->fImage->alt.argb32, sz*4);
01041 }
01042 }
01043 delete gVirtualPS;
01044 gVirtualPS = psave;
01045 return;
01046 }
01047
01048 if (w == 0) {
01049 w = TMath::Abs(pad->UtoPixel(1.));
01050 }
01051
01052 if (h == 0) {
01053 h = pad->VtoPixel(0.);
01054 }
01055
01056 gVirtualX->Update(1);
01057 if (!gThreadXAR) {
01058 gSystem->ProcessEvents();
01059 gSystem->Sleep(10);
01060 gSystem->ProcessEvents();
01061 }
01062
01063 TVirtualPad *canvas = (TVirtualPad*)pad->GetCanvas();
01064 Int_t wid = (pad == canvas) ? pad->GetCanvasID() : pad->GetPixmapID();
01065 gVirtualX->SelectWindow(wid);
01066
01067 Window_t wd = (Window_t)gVirtualX->GetCurrentWindow();
01068 if (!wd) return;
01069
01070 static int x11 = -1;
01071 if (x11 < 0) x11 = gVirtualX->InheritsFrom("TGX11");
01072
01073 if (x11) {
01074 fImage = pixmap2asimage(fgVisual, wd, x, y, w, h, kAllPlanes, 0, 0);
01075 } else {
01076 unsigned char *bits = gVirtualX->GetColorBits(wd, 0, 0, w, h);
01077
01078 if (!bits) {
01079 return;
01080 }
01081 fImage = bitmap2asimage(bits, w, h, 0, 0);
01082 delete [] bits;
01083 }
01084 }
01085
01086
01087
01088 void TASImage::Draw(Option_t *option)
01089 {
01090
01091
01092
01093
01094
01095
01096
01097
01098
01099
01100
01101
01102 if (!fImage) {
01103 Error("Draw", "no image set");
01104 return;
01105 }
01106
01107 TString opt = option;
01108 opt.ToLower();
01109 if (opt.Contains("n") || !gPad || !gPad->IsEditable()) {
01110 Int_t w = -64;
01111 Int_t h = 64;
01112 w = (fImage->width > 64) ? (Int_t)fImage->width : w;
01113 h = (fImage->height > 64) ? (Int_t)fImage->height : h;
01114
01115 Float_t cx = 1./gStyle->GetScreenFactor();
01116 w = Int_t(w*cx) + 4;
01117 h = Int_t(h*cx) + 28;
01118 TString rname = GetName();
01119 rname.ReplaceAll(".", "");
01120 rname += Form("\", \"%s (%d x %d)", rname.Data(), fImage->width, fImage->height);
01121 rname = "new TCanvas(\"" + rname + Form("\", %d, %d);", w, h);
01122 gROOT->ProcessLineFast(rname.Data());
01123 }
01124
01125 if (!opt.Contains("x")) {
01126 Double_t left = gPad->GetLeftMargin();
01127 Double_t right = gPad->GetRightMargin();
01128 Double_t top = gPad->GetTopMargin();
01129 Double_t bottom = gPad->GetBottomMargin();
01130
01131 gPad->Range(-left / (1.0 - left - right),
01132 -bottom / (1.0 - top - bottom),
01133 1 + right / (1.0 - left - right),
01134 1 + top / ( 1.0 - top - bottom));
01135 gPad->RangeAxis(0, 0, 1, 1);
01136 }
01137
01138 TFrame *frame = gPad->GetFrame();
01139 frame->SetBorderMode(0);
01140 frame->SetFillColor(gPad->GetFillColor());
01141 frame->SetLineColor(gPad->GetFillColor());
01142 frame->Draw();
01143
01144 TObject::Draw(option);
01145 }
01146
01147
01148
01149 void TASImage::Image2Drawable(ASImage *im, Drawable_t wid, Int_t x, Int_t y,
01150 Int_t xsrc, Int_t ysrc, UInt_t wsrc, UInt_t hsrc,
01151 Option_t *opt)
01152 {
01153
01154
01155 if (!im) return;
01156
01157 wsrc = wsrc ? wsrc : im->width;
01158 hsrc = hsrc ? hsrc : im->height;
01159
01160 static int x11 = -1;
01161 if (x11 < 0) x11 = gVirtualX->InheritsFrom("TGX11");
01162
01163 Pixmap_t mask = kNone;
01164
01165 if (x11) {
01166 UInt_t hh = hsrc;
01167 UInt_t ow = wsrc%8;
01168 UInt_t ww = wsrc - ow + (ow ? 8 : 0);
01169
01170 UInt_t bit = 0;
01171 int i = 0;
01172 UInt_t yy = 0;
01173 UInt_t xx = 0;
01174
01175 char *bits = new char[ww*hh];
01176
01177 ASImageDecoder *imdec = start_image_decoding(fgVisual, im, SCL_DO_ALPHA,
01178 xsrc, ysrc, ww, 0, 0);
01179 if (imdec) {
01180 for (yy = 0; yy < hh; yy++) {
01181 imdec->decode_image_scanline(imdec);
01182 CARD32 *a = imdec->buffer.alpha;
01183
01184 for (xx = 0; xx < ww; xx++) {
01185 if (a[xx]) {
01186 SETBIT(bits[i], bit);
01187 } else {
01188 CLRBIT(bits[i], bit);
01189 }
01190 bit++;
01191 if (bit == 8) {
01192 bit = 0;
01193 i++;
01194 }
01195 }
01196 }
01197 }
01198
01199 stop_image_decoding(&imdec);
01200
01201 mask = gVirtualX->CreateBitmap(gVirtualX->GetDefaultRootWindow(),
01202 (const char *)bits, ww, hh);
01203 delete [] bits;
01204 }
01205
01206 GCValues_t gv;
01207 static GContext_t gc = 0;
01208
01209 gv.fMask = kGCClipMask | kGCClipXOrigin | kGCClipYOrigin;
01210 gv.fClipMask = mask;
01211 gv.fClipXOrigin = x;
01212 gv.fClipYOrigin = y;
01213
01214 if (!gc) {
01215 gc = gVirtualX->CreateGC(gVirtualX->GetDefaultRootWindow(), &gv);
01216 } else {
01217 gVirtualX->ChangeGC(gc, &gv);
01218 }
01219
01220 if (x11) {
01221 asimage2drawable(fgVisual, wid, im, (GC)gc, xsrc, ysrc, x, y, wsrc, hsrc, 1);
01222 } else {
01223 ASImage *img = 0;
01224 unsigned char *bits = (unsigned char *)im->alt.argb32;
01225 if (!bits) {
01226 img = tile_asimage(fgVisual, im, xsrc, ysrc, wsrc, hsrc,
01227 0, ASA_ARGB32, 0, ASIMAGE_QUALITY_DEFAULT);
01228 bits = (unsigned char *)img->alt.argb32;
01229 }
01230
01231 Pixmap_t pic = gVirtualX->CreatePixmapFromData(bits, wsrc, hsrc);
01232 if (pic) {
01233 TString option = opt;
01234 option.ToLower();
01235 if (!option.Contains("opaque")) {
01236 SETBIT(wsrc,31);
01237 SETBIT(hsrc,31);
01238 }
01239 gVirtualX->CopyArea(pic, wid, gc, 0, 0, wsrc, hsrc, x, y);
01240 gVirtualX->DeletePixmap(pic);
01241 } else {
01242 return;
01243 }
01244 if (img) {
01245 destroy_asimage(&img);
01246 }
01247 }
01248
01249
01250 if (gv.fClipMask != kNone) gVirtualX->DeletePixmap(gv.fClipMask);
01251
01252 gv.fMask = kGCClipMask;
01253 gv.fClipMask = kNone;
01254 if (gc) gVirtualX->ChangeGC(gc, &gv);
01255 }
01256
01257
01258
01259 void TASImage::PaintImage(Drawable_t wid, Int_t x, Int_t y, Int_t xsrc, Int_t ysrc,
01260 UInt_t wsrc, UInt_t hsrc, Option_t *opt)
01261 {
01262
01263
01264
01265
01266
01267
01268
01269 Image2Drawable(fScaledImage ? fScaledImage->fImage : fImage, wid, x, y,
01270 xsrc, ysrc, wsrc, hsrc, opt);
01271 }
01272
01273
01274
01275 void TASImage::Paint(Option_t *option)
01276 {
01277
01278
01279
01280
01281
01282
01283
01284
01285
01286
01287
01288
01289 if (!fImage) {
01290 Error("Paint", "no image set");
01291 return;
01292 }
01293
01294 if (!InitVisual()) {
01295 Warning("Paint", "Visual not initiated");
01296 return;
01297 }
01298
01299 Int_t tile_x = 0, tile_y = 0;
01300 CARD32 tile_tint = 0;
01301 Bool_t tile = kFALSE;
01302 Bool_t expand = kFALSE;
01303
01304 TString opt = option;
01305 opt.ToLower();
01306
01307 if (opt.Contains("t")) {
01308 char stint[64];
01309 if (sscanf(opt.Data() + opt.Index("t"), "t%d,%d,%s", &tile_x, &tile_y,
01310 stint) <= 3) {
01311 tile = kTRUE;
01312 if (parse_argb_color(stint, (CARD32*)&tile_tint) == stint)
01313 tile_tint = 0;
01314 } else {
01315 Error("Paint", "tile option error");
01316 }
01317 } else if (opt.Contains("x")) {
01318 expand = kTRUE;
01319 fConstRatio = kFALSE;
01320 } else if (opt.Contains("z")) {
01321 fPaletteEnabled = kTRUE;
01322
01323 if (!fImage->alt.vector) {
01324 Vectorize(256);
01325 }
01326 }
01327
01328 ASImage *image = fImage;
01329
01330
01331 Int_t to_w = gPad->UtoPixel(1.);
01332 Int_t to_h = gPad->VtoPixel(0.);
01333
01334
01335 if (!expand) {
01336 to_h = (Int_t)(to_h * (1.0 - gPad->GetBottomMargin() - gPad->GetTopMargin() ) + 0.5);
01337 to_w = (Int_t)(to_w * (1.0 - gPad->GetLeftMargin() - gPad->GetRightMargin() ) + 0.5);
01338 }
01339
01340 if ((to_w < 25 || to_h < 25) && !expand) {
01341 Error("Paint", "pad too small to display an image");
01342 return;
01343 }
01344
01345 if (GetConstRatio()) {
01346 if ((Double_t)to_w / (Double_t)fZoomWidth <
01347 (Double_t)to_h / (Double_t)fZoomHeight)
01348 to_h = Int_t(Double_t(fZoomHeight) * to_w / fZoomWidth);
01349 else
01350 to_w = Int_t(Double_t(fZoomWidth) * to_h / fZoomHeight);
01351 }
01352
01353 Int_t pal_Ax = to_w + gPad->UtoAbsPixel(gPad->GetLeftMargin()) +
01354 (gPad->UtoAbsPixel(gPad->GetRightMargin()) / 10);
01355 Int_t pal_Ay = gPad->YtoAbsPixel(1.0);
01356 Int_t pal_x = to_w + gPad->UtoPixel(gPad->GetLeftMargin()) +
01357 (gPad->UtoPixel(gPad->GetRightMargin()) / 10);
01358 Int_t pal_y = gPad->YtoPixel(1.0);
01359 Int_t pal_w = gPad->UtoPixel(gPad->GetRightMargin()) / 3;
01360 Int_t pal_h = to_h;
01361
01362 ASImage *grad_im = 0;
01363
01364 if (fImage->alt.vector && fPaletteEnabled) {
01365
01366 ASGradient grad;
01367 const TImagePalette &pal = GetPalette();
01368
01369 grad.npoints = pal.fNumPoints;
01370 grad.type = GRADIENT_Top2Bottom;
01371 grad.color = new ARGB32[grad.npoints];
01372 grad.offset = new double[grad.npoints];
01373
01374 for (Int_t pt = 0; pt < grad.npoints; pt++) {
01375 Int_t oldPt = grad.npoints - pt -1;
01376 grad.offset[pt] = 1 - pal.fPoints[oldPt];
01377 grad.color[pt] = (((ARGB32)(pal.fColorBlue[oldPt] & 0xff00)) >> 8) |
01378 (((ARGB32)(pal.fColorGreen[oldPt] & 0xff00)) ) |
01379 (((ARGB32)(pal.fColorRed[oldPt] & 0xff00)) << 8) |
01380 (((ARGB32)(pal.fColorAlpha[oldPt] & 0xff00)) << 16);
01381 }
01382
01383 grad_im = make_gradient(fgVisual, &grad , UInt_t(pal_w),
01384 pal_h, SCL_DO_COLOR,
01385 ASA_ARGB32, GetImageCompression(), GetImageQuality());
01386
01387 delete [] grad.color;
01388 delete [] grad.offset;
01389 }
01390
01391 if (tile) {
01392 delete fScaledImage;
01393 fScaledImage = (TASImage*)TImage::Create();
01394 fScaledImage->fImage = tile_asimage(fgVisual, fImage, tile_x, tile_y,
01395 to_w, to_h, tile_tint, ASA_ASImage,
01396 GetImageCompression(), GetImageQuality());
01397 image = fScaledImage->fImage;
01398
01399 } else if (fZoomUpdate == kZoomOps) {
01400 image = fImage;
01401
01402 } else {
01403
01404 if (Int_t(fImage->width) != to_w || Int_t(fImage->height) != to_h ||
01405 fImage->width != fZoomWidth || fImage->height != fZoomHeight) {
01406
01407 if (fScaledImage && (Int_t(fScaledImage->GetWidth()) != to_w ||
01408 Int_t(fScaledImage->GetHeight()) != to_h ||
01409 fZoomUpdate)) {
01410
01411 delete fScaledImage;
01412 fScaledImage = 0;
01413 }
01414
01415 if (!fScaledImage) {
01416 fScaledImage = (TASImage*)TImage::Create();
01417
01418 if (fZoomWidth && fZoomHeight &&
01419 ((fImage->width != fZoomWidth) || (fImage->height != fZoomHeight))) {
01420
01421 ASImage *tmpImage = 0;
01422
01423 tmpImage = tile_asimage(fgVisual, fImage, fZoomOffX,
01424 fImage->height - fZoomHeight - fZoomOffY,
01425 fZoomWidth, fZoomHeight, 0, ASA_ASImage,
01426 GetImageCompression(), GetImageQuality());
01427
01428 if (tmpImage) {
01429 fScaledImage->fImage = scale_asimage(fgVisual, tmpImage, to_w, to_h,
01430 ASA_ASImage, GetImageCompression(),
01431 GetImageQuality());
01432 destroy_asimage(&tmpImage);
01433 }
01434 } else {
01435
01436 fScaledImage->fImage = scale_asimage(fgVisual, fImage, to_w, to_h,
01437 ASA_ASImage, GetImageCompression(),
01438 GetImageQuality());
01439 }
01440 }
01441 image = fScaledImage->fImage;
01442 }
01443 }
01444 fZoomUpdate = 0;
01445
01446 if (!image) {
01447 Error("Paint", "image could not be rendered to display");
01448 return;
01449 }
01450
01451 int tox = expand ? 0 : int(gPad->UtoPixel(1.) * gPad->GetLeftMargin());
01452 int toy = expand ? 0 : int(gPad->VtoPixel(0.) * gPad->GetTopMargin());
01453
01454 if (!gROOT->IsBatch()) {
01455 Window_t wid = (Window_t)gVirtualX->GetWindowID(gPad->GetPixmapID());
01456 Image2Drawable(fScaledImage ? fScaledImage->fImage : fImage, wid, tox, toy);
01457
01458 if (grad_im && fPaletteEnabled) {
01459
01460 Image2Drawable(grad_im, wid, pal_x, pal_y);
01461
01462
01463 TGaxis axis;
01464 Int_t ndiv = 510;
01465 double min = fMinValue;
01466 double max = fMaxValue;
01467 axis.SetLineColor(0);
01468 Double_t pal_Xpos = gPad->AbsPixeltoX(pal_Ax + pal_w);
01469 axis.PaintAxis(pal_Xpos, gPad->PixeltoY(pal_Ay + pal_h - 1),
01470 pal_Xpos, gPad->PixeltoY(pal_Ay),
01471 min, max, ndiv, "+LU");
01472 min = fMinValue;
01473 max = fMaxValue;
01474 axis.SetLineColor(1);
01475 axis.PaintAxis(pal_Xpos, gPad->AbsPixeltoY(pal_Ay + pal_h),
01476 pal_Xpos, gPad->AbsPixeltoY(pal_Ay + 1),
01477 min, max, ndiv, "+L");
01478 }
01479 }
01480
01481
01482 if (gVirtualPS) {
01483 if (gVirtualPS->InheritsFrom("TImageDump")) {
01484 TImage *dump = (TImage *)gVirtualPS->GetStream();
01485 dump->Merge(fScaledImage ? fScaledImage : this, "alphablend",
01486 gPad->XtoAbsPixel(0), gPad->YtoAbsPixel(1));
01487
01488 if (grad_im) {
01489 TASImage tgrad;
01490 tgrad.fImage = grad_im;
01491 dump->Merge(&tgrad, "alphablend", pal_Ax, pal_Ay);
01492
01493
01494 TGaxis axis;
01495 Int_t ndiv = 510;
01496 double min = fMinValue;
01497 double max = fMaxValue;
01498 axis.SetLineColor(1);
01499 Double_t pal_Xpos = gPad->AbsPixeltoX(pal_Ax + pal_w);
01500 axis.PaintAxis(pal_Xpos, gPad->AbsPixeltoY(pal_Ay + pal_h),
01501 pal_Xpos, gPad->AbsPixeltoY(pal_Ay + 1),
01502 min, max, ndiv, "+L");
01503 }
01504 return;
01505 } else if (gVirtualPS->InheritsFrom("TPDF")) {
01506 Warning("Paint", "PDF not implemeted yet");
01507 return;
01508 } else if (gVirtualPS->InheritsFrom("TSVG")) {
01509 Warning("Paint", "SVG not implemeted yet");
01510 return;
01511 }
01512
01513
01514 TObjArray *colors = (TObjArray*) gROOT->GetListOfColors();
01515 TColor *color = 0;
01516
01517 if ((color = (TColor*)colors->FindObject("Image_PS")) == 0)
01518 color = new TColor(colors->GetEntries(), 1., 1., 1., "Image_PS");
01519
01520 gVirtualPS->SetFillColor(color->GetNumber());
01521 gVirtualPS->SetFillStyle(1001);
01522
01523 Double_t dx = gPad->GetX2()-gPad->GetX1();
01524 Double_t dy = gPad->GetY2()-gPad->GetY1();
01525 Double_t x1,x2,y1,y2;
01526
01527 if (expand) {
01528 x1 = gPad->GetX1();
01529 x2 = x1+dx/image->width;
01530 y1 = gPad->GetY2();
01531 y2 = y1+dy/image->height;
01532 } else {
01533 x1 = gPad->GetX1()+dx*gPad->GetLeftMargin();
01534 x2 = x1+(dx*(1-gPad->GetRightMargin()-gPad->GetLeftMargin()))/image->width;
01535 y1 = gPad->GetY2()-dy*gPad->GetTopMargin();
01536 y2 = y1+(dy*(1-gPad->GetTopMargin()-gPad->GetBottomMargin()))/image->height;
01537 }
01538
01539 gVirtualPS->CellArrayBegin(image->width, image->height, x1, x2, y1, y2);
01540
01541 ASImageDecoder *imdec = start_image_decoding(fgVisual, image, SCL_DO_ALL,
01542 0, 0, image->width, image->height, 0);
01543 for (Int_t yt = 0; yt < (Int_t)image->height; yt++) {
01544 imdec->decode_image_scanline(imdec);
01545 for (Int_t xt = 0; xt < (Int_t)image->width; xt++)
01546 gVirtualPS->CellArrayFill(imdec->buffer.red[xt],
01547 imdec->buffer.green[xt],
01548 imdec->buffer.blue[xt]);
01549 }
01550 stop_image_decoding(&imdec);
01551 gVirtualPS->CellArrayEnd();
01552
01553
01554 if (grad_im) {
01555 Double_t xconv = (gPad->AbsPixeltoX(pal_Ax + pal_w) - gPad->AbsPixeltoX(pal_Ax)) / grad_im->width;
01556 Double_t yconv = (gPad->AbsPixeltoY(pal_Ay - pal_h) - gPad->AbsPixeltoY(pal_Ay)) / grad_im->height;
01557 x1 = gPad->AbsPixeltoX(pal_Ax);
01558 x2 = x1 + xconv;
01559 y2 = gPad->AbsPixeltoY(pal_Ay);
01560 y1 = y2 - yconv;
01561 gVirtualPS->CellArrayBegin(grad_im->width, grad_im->height,
01562 x1, x2, y1, y2);
01563
01564 imdec = start_image_decoding(fgVisual, grad_im, SCL_DO_ALL,
01565 0, 0, grad_im->width, grad_im->height, 0);
01566 for (Int_t yt = 0; yt < (Int_t)grad_im->height; yt++) {
01567 imdec->decode_image_scanline(imdec);
01568 for (Int_t xt = 0; xt < (Int_t)grad_im->width; xt++)
01569 gVirtualPS->CellArrayFill(imdec->buffer.red[xt],
01570 imdec->buffer.green[xt],
01571 imdec->buffer.blue[xt]);
01572 }
01573 stop_image_decoding(&imdec);
01574 gVirtualPS->CellArrayEnd();
01575
01576
01577 TGaxis axis;
01578 Int_t ndiv = 510;
01579 double min = fMinValue;
01580 double max = fMaxValue;
01581 axis.SetLineColor(1);
01582 Double_t pal_Xpos = gPad->AbsPixeltoX(pal_Ax + pal_w);
01583 axis.PaintAxis(pal_Xpos, gPad->AbsPixeltoY(pal_Ay + pal_h),
01584 pal_Xpos, gPad->AbsPixeltoY(pal_Ay + 1),
01585 min, max, ndiv, "+L");
01586
01587 }
01588 }
01589
01590 if (grad_im) {
01591 destroy_asimage(&grad_im);
01592 }
01593 }
01594
01595
01596
01597 Int_t TASImage::DistancetoPrimitive(Int_t px, Int_t py)
01598 {
01599
01600
01601 Int_t pxl, pyl, pxt, pyt;
01602
01603 Int_t px1 = gPad->XtoAbsPixel(0);
01604 Int_t py1 = gPad->YtoAbsPixel(0);
01605 Int_t px2 = gPad->XtoAbsPixel(1);
01606 Int_t py2 = gPad->YtoAbsPixel(1);
01607
01608 if (px1 < px2) {pxl = px1; pxt = px2;}
01609 else {pxl = px2; pxt = px1;}
01610 if (py1 < py2) {pyl = py1; pyt = py2;}
01611 else {pyl = py2; pyt = py1;}
01612
01613 if ((px > pxl && px < pxt) && (py > pyl && py < pyt))
01614 return 0;
01615
01616 return 999999;
01617 }
01618
01619
01620
01621 void TASImage::ExecuteEvent(Int_t event, Int_t px, Int_t py)
01622 {
01623
01624
01625 if (IsEditable()) {
01626 gPad->ExecuteEvent(event, px, py);
01627 return;
01628 }
01629
01630 gPad->SetCursor(kCross);
01631
01632 static Int_t stx, sty;
01633 static Int_t oldx, oldy;
01634
01635 if (!IsValid()) return;
01636
01637 if (event == kButton1Motion || event == kButton1Down ||
01638 event == kButton1Up) {
01639
01640
01641 Int_t imgX = px - gPad->XtoAbsPixel(0);
01642 Int_t imgY = py - gPad->YtoAbsPixel(1);
01643
01644 if (imgX < 0) px = px - imgX;
01645 if (imgY < 0) py = py - imgY;
01646
01647 ASImage *image = fImage;
01648 if (fScaledImage) image = fScaledImage->fImage;
01649
01650 if (imgX >= (int)image->width) px = px - imgX + image->width - 1;
01651 if (imgY >= (int)image->height) py = py - imgY + image->height - 1;
01652
01653 switch (event) {
01654
01655 case kButton1Down:
01656 gVirtualX->SetLineColor(-1);
01657
01658 stx = oldx = px;
01659 sty = oldy = py;
01660 break;
01661
01662 case kButton1Motion:
01663 gVirtualX->DrawBox(oldx, oldy, stx, sty, TVirtualX::kHollow);
01664 oldx = px;
01665 oldy = py;
01666 gVirtualX->DrawBox(oldx, oldy, stx, sty, TVirtualX::kHollow);
01667 break;
01668
01669 case kButton1Up:
01670
01671 if ( TMath::Abs(stx - px) < 5 || TMath::Abs(sty - py) < 5)
01672 return;
01673
01674 Double_t xfact = (fScaledImage) ? (Double_t)fScaledImage->fImage->width / fZoomWidth : 1;
01675 Double_t yfact = (fScaledImage) ? (Double_t)fScaledImage->fImage->height / fZoomHeight : 1;
01676
01677 Int_t imgX1 = stx - gPad->XtoAbsPixel(0);
01678 Int_t imgY1 = sty - gPad->YtoAbsPixel(1);
01679 Int_t imgX2 = px - gPad->XtoAbsPixel(0);
01680 Int_t imgY2 = py - gPad->YtoAbsPixel(1);
01681
01682 imgY1 = image->height - 1 - imgY1;
01683 imgY2 = image->height - 1 - imgY2;
01684 imgX1 = (Int_t)(imgX1 / xfact) + fZoomOffX;
01685 imgY1 = (Int_t)(imgY1 / yfact) + fZoomOffY;
01686 imgX2 = (Int_t)(imgX2 / xfact) + fZoomOffX;
01687 imgY2 = (Int_t)(imgY2 / yfact) + fZoomOffY;
01688
01689 Zoom((imgX1 < imgX2) ? imgX1 : imgX2, (imgY1 < imgY2) ? imgY1 : imgY2,
01690 TMath::Abs(imgX1 - imgX2) + 1, TMath::Abs(imgY1 - imgY2) + 1);
01691
01692 gVirtualX->SetLineColor(-1);
01693 gPad->Modified(kTRUE);
01694 gPad->Update();
01695 break;
01696 }
01697 }
01698 }
01699
01700
01701
01702 char *TASImage::GetObjectInfo(Int_t px, Int_t py) const
01703 {
01704
01705
01706 static char info[64];
01707 info[0] = 0;
01708
01709 if (!IsValid()) return info;
01710
01711
01712 px -= gPad->XtoAbsPixel(0);
01713 py -= gPad->YtoAbsPixel(1);
01714
01715
01716 if (px < 0 || py < 0) return info;
01717
01718 ASImage *image = fImage;
01719 if (fScaledImage) image = fScaledImage->fImage;
01720 if (px >= (int)image->width || py >= (int)image->height)
01721 return info;
01722
01723 py = image->height - 1 - py;
01724
01725 if (fScaledImage) {
01726 px = (Int_t)(px / (Double_t)fScaledImage->fImage->width * fZoomWidth ) + fZoomOffX;
01727 py = (Int_t)(py / (Double_t)fScaledImage->fImage->height * fZoomHeight) + fZoomOffY;
01728 }
01729
01730 if (fImage->alt.vector) {
01731 snprintf(info,64,"x: %d y: %d %.5g",
01732 px, py, fImage->alt.vector[px + py * fImage->width]);
01733 } else {
01734 snprintf(info,64,"x: %d y: %d", px, py);
01735 }
01736
01737 return info;
01738 }
01739
01740
01741
01742 void TASImage::SetPalette(const TImagePalette *palette)
01743 {
01744
01745
01746
01747
01748 TAttImage::SetPalette(palette);
01749
01750 if (!InitVisual()) {
01751 Warning("SetPalette", "Visual not initiated");
01752 return;
01753 }
01754
01755 if (!IsValid()) {
01756 Warning("SetPalette", "Image not valid");
01757 return;
01758 }
01759
01760 if (fImage->alt.vector == 0)
01761 return;
01762
01763
01764 const TImagePalette &pal = GetPalette();
01765
01766 ASVectorPalette asPalette;
01767 asPalette.npoints = pal.fNumPoints;
01768 asPalette.channels[0] = new CARD16 [asPalette.npoints];
01769 asPalette.channels[1] = new CARD16 [asPalette.npoints];
01770 asPalette.channels[2] = new CARD16 [asPalette.npoints];
01771 asPalette.channels[3] = new CARD16 [asPalette.npoints];
01772 memcpy(asPalette.channels[0], pal.fColorBlue, pal.fNumPoints * sizeof(UShort_t));
01773 memcpy(asPalette.channels[1], pal.fColorGreen, pal.fNumPoints * sizeof(UShort_t));
01774 memcpy(asPalette.channels[2], pal.fColorRed, pal.fNumPoints * sizeof(UShort_t));
01775 memcpy(asPalette.channels[3], pal.fColorAlpha, pal.fNumPoints * sizeof(UShort_t));
01776
01777 asPalette.points = new double[asPalette.npoints];
01778 for (Int_t point = 0; point < Int_t(asPalette.npoints); point++)
01779 asPalette.points[point] = fMinValue + (fMaxValue - fMinValue) * pal.fPoints[point];
01780
01781
01782 colorize_asimage_vector(fgVisual, fImage, &asPalette, ASA_ASImage, GetImageQuality());
01783
01784 delete [] asPalette.points;
01785 for (Int_t col = 0; col < 4; col++)
01786 delete [] asPalette.channels[col];
01787
01788
01789 delete fScaledImage;
01790 fScaledImage = 0;
01791 }
01792
01793
01794
01795 void TASImage::Scale(UInt_t toWidth, UInt_t toHeight)
01796 {
01797
01798
01799
01800
01801
01802
01803
01804
01805 if (!IsValid()) {
01806 Warning("Scale", "Image not initiated");
01807 return;
01808 }
01809
01810 if (!InitVisual()) {
01811 Warning("Scale", "Visual not initiated");
01812 return;
01813 }
01814
01815 if (toWidth < 1)
01816 toWidth = 1;
01817 if (toHeight < 1 )
01818 toHeight = 1;
01819 if (toWidth > 30000)
01820 toWidth = 30000;
01821 if (toHeight > 30000)
01822 toHeight = 30000;
01823
01824 ASImage *img = scale_asimage(fgVisual, fImage, toWidth, toHeight,
01825 ASA_ASImage, GetImageCompression(),
01826 GetImageQuality());
01827 DestroyImage();
01828 fImage = img;
01829 UnZoom();
01830 fZoomUpdate = kZoomOps;
01831 }
01832
01833
01834
01835 void TASImage::Slice(UInt_t xStart, UInt_t xEnd, UInt_t yStart, UInt_t yEnd,
01836 UInt_t toWidth, UInt_t toHeight)
01837 {
01838
01839
01840
01841 if (!IsValid()) {
01842 Warning("Scale", "Image not initiated");
01843 return;
01844 }
01845
01846 if (!InitVisual()) {
01847 Warning("Scale", "Visual not initiated");
01848 return;
01849 }
01850
01851 if (toWidth < 1)
01852 toWidth = 1;
01853 if (toHeight < 1 )
01854 toHeight = 1;
01855 if (toWidth > 30000)
01856 toWidth = 30000;
01857 if (toHeight > 30000)
01858 toHeight = 30000;
01859
01860 ASImage *img = slice_asimage(fgVisual, fImage, xStart, xEnd,
01861 yStart, yEnd, toWidth, toHeight,
01862 ASA_ASImage, GetImageCompression(),
01863 GetImageQuality());
01864
01865 DestroyImage();
01866 fImage = img;
01867 UnZoom();
01868 fZoomUpdate = kZoomOps;
01869 }
01870
01871
01872
01873 void TASImage::Tile(UInt_t toWidth, UInt_t toHeight)
01874 {
01875
01876
01877 if (!IsValid()) {
01878 Warning("Tile", "Image not initiated");
01879 return;
01880 }
01881
01882 if (!InitVisual()) {
01883 Warning("Tile", "Visual not initiated");
01884 return;
01885 }
01886
01887 if (toWidth < 1)
01888 toWidth = 1;
01889 if (toHeight < 1 )
01890 toHeight = 1;
01891 if (toWidth > 30000)
01892 toWidth = 30000;
01893 if (toHeight > 30000)
01894 toHeight = 30000;
01895
01896 ASImage *img = tile_asimage(fgVisual, fImage, 0, 0, toWidth, toHeight, 0,
01897 ASA_ASImage, GetImageCompression(), GetImageQuality());
01898 DestroyImage();
01899 fImage = img;
01900 UnZoom();
01901 fZoomUpdate = kZoomOps;
01902 }
01903
01904
01905
01906 void TASImage::Zoom(UInt_t offX, UInt_t offY, UInt_t width, UInt_t height)
01907 {
01908
01909
01910
01911
01912
01913
01914
01915
01916
01917
01918 if (!IsValid()) {
01919 Warning("Zoom", "Image not valid");
01920 return;
01921 }
01922 fZoomUpdate = kZoom;
01923
01924 fZoomWidth = (width == 0) ? 1 : ((width > fImage->width) ? fImage->width : width);
01925 fZoomHeight = (height == 0) ? 1 : ((height > fImage->height) ? fImage->height : height);
01926 fZoomOffX = offX;
01927 if (fZoomOffX + fZoomWidth > fImage->width)
01928 fZoomOffX = fImage->width - fZoomWidth;
01929 fZoomOffY = offY;
01930 if (fZoomOffY + fZoomHeight > fImage->height)
01931 fZoomOffY = fImage->height - fZoomHeight;
01932 }
01933
01934
01935
01936 void TASImage::UnZoom()
01937 {
01938
01939
01940
01941 if (!IsValid()) {
01942 Warning("UnZoom", "Image not valid");
01943 return;
01944 }
01945 fZoomUpdate = kZoom;
01946 fZoomOffX = 0;
01947 fZoomOffY = 0;
01948 fZoomWidth = fImage->width;
01949 fZoomHeight = fImage->height;
01950
01951 delete fScaledImage;
01952 fScaledImage = 0;
01953 }
01954
01955
01956
01957 void TASImage::Flip(Int_t flip)
01958 {
01959
01960
01961
01962
01963
01964
01965
01966
01967
01968
01969 if (!IsValid()) {
01970 Warning("Flip", "Image not valid");
01971 return;
01972 }
01973 if (!InitVisual()) {
01974 Warning("Flip", "Visual not initiated");
01975 return;
01976 }
01977
01978 if (fImage->alt.vector) {
01979 Warning("Flip", "flip does not work for data images");
01980 return;
01981 }
01982
01983 Int_t rflip = flip/90;
01984
01985 UInt_t w = fImage->width;
01986 UInt_t h = fImage->height;
01987
01988 if (rflip & 1) {
01989 w = fImage->height;
01990 h = fImage->width;
01991 }
01992
01993 ASImage *img = flip_asimage(fgVisual, fImage, 0, 0, w, h, rflip,
01994 ASA_ASImage, GetImageCompression(),
01995 GetImageQuality());
01996 DestroyImage();
01997 fImage = img;
01998 UnZoom();
01999 }
02000
02001
02002
02003 void TASImage::Mirror(Bool_t vert)
02004 {
02005
02006
02007
02008
02009
02010
02011
02012
02013
02014
02015
02016 if (!IsValid()) {
02017 Warning("Mirror", "Image not valid");
02018 return;
02019 }
02020
02021 if (!InitVisual()) {
02022 Warning("Mirrow", "Visual not initiated");
02023 return;
02024 }
02025
02026 if (fImage->alt.vector) {
02027 Warning("Mirror", "mirror does not work for data images");
02028 return;
02029 }
02030
02031 ASImage *img = mirror_asimage(fgVisual, fImage, 0, 0,
02032 fImage->width, fImage->height, vert,
02033 ASA_ASImage, GetImageCompression(),
02034 GetImageQuality());
02035 DestroyImage();
02036 fImage = img;
02037 UnZoom();
02038 }
02039
02040
02041
02042 UInt_t TASImage::GetWidth() const
02043 {
02044
02045
02046
02047 return fImage ? fImage->width : 0;
02048 }
02049
02050
02051
02052 UInt_t TASImage::GetHeight() const
02053 {
02054
02055
02056
02057 return fImage ? fImage->height : 0;
02058 }
02059
02060
02061
02062 UInt_t TASImage::GetScaledWidth() const
02063 {
02064
02065
02066
02067 return fScaledImage ? fScaledImage->fImage->width : GetWidth();
02068 }
02069
02070
02071
02072 UInt_t TASImage::GetScaledHeight() const
02073 {
02074
02075
02076
02077 return fScaledImage ? fScaledImage->fImage->height : GetHeight();
02078 }
02079
02080
02081
02082 void TASImage::GetZoomPosition(UInt_t &x, UInt_t &y, UInt_t &w, UInt_t &h) const
02083 {
02084
02085
02086
02087 x = fZoomOffX;
02088 y = fZoomOffY;
02089 w = fZoomWidth;
02090 h = fZoomHeight;
02091 }
02092
02093
02094
02095 Bool_t TASImage::InitVisual()
02096 {
02097
02098
02099 Display *disp;
02100
02101 Bool_t inbatch = fgVisual && (fgVisual->dpy == (void*)1);
02102 Bool_t noX = gROOT->IsBatch() || gVirtualX->InheritsFrom("TGWin32");
02103
02104
02105 if (inbatch && !noX) {
02106 destroy_asvisual(fgVisual, kFALSE);
02107 fgVisual = 0;
02108 }
02109
02110 if (fgVisual && fgVisual->dpy) {
02111 return kTRUE;
02112 }
02113
02114
02115 if (!fgVisual && noX) {
02116 disp = 0;
02117 fgVisual = create_asvisual(0, 0, 0, 0);
02118 fgVisual->dpy = (Display*)1;
02119 return kTRUE;
02120 }
02121
02122 disp = (Display*) gVirtualX->GetDisplay();
02123 Int_t screen = gVirtualX->GetScreen();
02124 Int_t depth = gVirtualX->GetDepth();
02125 Visual *vis = (Visual*) gVirtualX->GetVisual();
02126 Colormap cmap = (Colormap) gVirtualX->GetColormap();
02127 #ifndef WIN32
02128 if (vis == 0 || cmap == 0) {
02129 fgVisual = create_asvisual(0, 0, 0, 0);
02130 } else {
02131 fgVisual = create_asvisual_for_id(disp, screen, depth,
02132 XVisualIDFromVisual(vis), cmap, 0);
02133 }
02134 #else
02135 fgVisual = create_asvisual(0, 0, 0, 0);
02136 fgVisual->dpy = (Display*)1;
02137 #endif
02138
02139 return kTRUE;
02140 }
02141
02142
02143
02144 void TASImage::StartPaletteEditor()
02145 {
02146
02147
02148 if (!IsValid()) {
02149 Warning("StartPaletteEditor", "Image not valid");
02150 return;
02151 }
02152 if (fImage->alt.vector == 0) {
02153 Warning("StartPaletteEditor", "palette can be modified only for data images");
02154 return;
02155 }
02156
02157
02158 TAttImage::StartPaletteEditor();
02159 }
02160
02161
02162
02163 Pixmap_t TASImage::GetPixmap()
02164 {
02165
02166
02167
02168 if (!InitVisual()) {
02169 Warning("GetPixmap", "Visual not initiated");
02170 return 0;
02171 }
02172
02173 Pixmap_t ret;
02174
02175 ASImage *img = fScaledImage ? fScaledImage->fImage : fImage;
02176
02177 static int x11 = -1;
02178 if (x11 < 0) x11 = gVirtualX->InheritsFrom("TGX11");
02179
02180 if (x11) {
02181 ret = (Pixmap_t)asimage2pixmap(fgVisual, gVirtualX->GetDefaultRootWindow(),
02182 img, 0, kTRUE);
02183 } else {
02184 if (!fImage->alt.argb32) {
02185 BeginPaint();
02186 }
02187 ret = gVirtualX->CreatePixmapFromData((unsigned char*)fImage->alt.argb32,
02188 fImage->width, fImage->height);
02189 }
02190
02191 return ret;
02192 }
02193
02194
02195
02196 Pixmap_t TASImage::GetMask()
02197 {
02198
02199
02200
02201 Pixmap_t pxmap = 0;
02202
02203 if (!InitVisual()) {
02204 Warning("GetMask", "Visual not initiated");
02205 return pxmap;
02206 }
02207
02208 ASImage *img = fScaledImage ? fScaledImage->fImage : fImage;
02209
02210 if (!img) {
02211 Warning("GetMask", "No image");
02212 return pxmap;
02213 }
02214
02215 UInt_t hh = img->height;
02216 UInt_t ow = img->width%8;
02217 UInt_t ww = img->width - ow + (ow ? 8 : 0);
02218
02219 UInt_t bit = 0;
02220 int i = 0;
02221 UInt_t y = 0;
02222 UInt_t x = 0;
02223
02224 char *bits = new char[ww*hh];
02225
02226 ASImageDecoder *imdec = start_image_decoding(fgVisual, img, SCL_DO_ALPHA,
02227 0, 0, ww, 0, 0);
02228 if(!imdec) {
02229 delete [] bits;
02230 return 0;
02231 }
02232
02233 for (y = 0; y < hh; y++) {
02234 imdec->decode_image_scanline(imdec);
02235 CARD32 *a = imdec->buffer.alpha;
02236
02237 for (x = 0; x < ww; x++) {
02238 if (a[x]) {
02239 SETBIT(bits[i], bit);
02240 } else {
02241 CLRBIT(bits[i], bit);
02242 }
02243 bit++;
02244 if (bit == 8) {
02245 bit = 0;
02246 i++;
02247 }
02248 }
02249 }
02250
02251 stop_image_decoding(&imdec);
02252 pxmap = gVirtualX->CreateBitmap(gVirtualX->GetDefaultRootWindow(), (const char *)bits,
02253 ww, hh);
02254 delete [] bits;
02255 return pxmap;
02256 }
02257
02258
02259
02260 void TASImage::SetImage(Pixmap_t pxm, Pixmap_t mask)
02261 {
02262
02263
02264 if (!InitVisual()) {
02265 Warning("SetImage", "Visual not initiated");
02266 return;
02267 }
02268
02269 DestroyImage();
02270 delete fScaledImage;
02271 fScaledImage = 0;
02272
02273 Int_t xy;
02274 UInt_t w, h;
02275 gVirtualX->GetWindowSize(pxm, xy, xy, w, h);
02276
02277 if (fName.IsNull()) fName.Form("img_%dx%d",w, h);
02278
02279 static int x11 = -1;
02280 if (x11 < 0) x11 = gVirtualX->InheritsFrom("TGX11");
02281
02282 if (x11) {
02283 fImage = picture2asimage(fgVisual, pxm, mask, 0, 0, w, h, kAllPlanes, 1, 0);
02284 } else {
02285 unsigned char *bits = gVirtualX->GetColorBits(pxm, 0, 0, w, h);
02286 if (!bits) {
02287 return;
02288 }
02289
02290
02291 if (!mask) {
02292 fImage = bitmap2asimage(bits, w, h, 0, 0);
02293 delete [] bits;
02294 return;
02295 }
02296 unsigned char *mask_bits = gVirtualX->GetColorBits(mask, 0, 0, w, h);
02297 fImage = bitmap2asimage(bits, w, h, 0, mask_bits);
02298 delete [] mask_bits;
02299 delete [] bits;
02300 }
02301 }
02302
02303
02304
02305 TArrayL *TASImage::GetPixels(Int_t x, Int_t y, UInt_t width, UInt_t height)
02306 {
02307
02308
02309 if (!fImage) {
02310 Warning("GetPixels", "Wrong Image");
02311 return 0;
02312 }
02313
02314 ASImage *img = fScaledImage ? fScaledImage->fImage : fImage;
02315 ASImageDecoder *imdec;
02316
02317 width = !width ? img->width : width;
02318 height = !height ? img->height : height;
02319
02320 if (x < 0) {
02321 width -= x;
02322 x = 0 ;
02323 }
02324 if (y < 0) {
02325 height -= y;
02326 y = 0;
02327 }
02328
02329 if ((x >= (int)img->width) || (y >= (int)img->height)) {
02330 return 0;
02331 }
02332
02333 if ((int)(x + width) > (int)img->width) {
02334 width = img->width - x;
02335 }
02336
02337 if ((int)(y + height) > (int)img->height) {
02338 height = img->height - y;
02339 }
02340
02341 if ((imdec = start_image_decoding(0, fImage, SCL_DO_ALL, 0, y,
02342 img->width, height, 0)) == 0) {
02343 Warning("GetPixels", "Failed to create image decoder");
02344 return 0;
02345 }
02346
02347 TArrayL *ret = new TArrayL(width * height);
02348 Int_t r = 0;
02349 Int_t g = 0;
02350 Int_t b = 0;
02351 Long_t p = 0;
02352
02353 for (UInt_t k = 0; k < height; k++) {
02354 imdec->decode_image_scanline(imdec);
02355
02356 for (UInt_t i = 0; i < width; ++i) {
02357 if ((r == (Int_t)imdec->buffer.red[i]) &&
02358 (g == (Int_t)imdec->buffer.green[i]) &&
02359 (b == (Int_t)imdec->buffer.blue[i])) {
02360 } else {
02361 r = (Int_t)imdec->buffer.red[i];
02362 g = (Int_t)imdec->buffer.green[i];
02363 b = (Int_t)imdec->buffer.blue[i];
02364 p = (Long_t)TColor::RGB2Pixel(r, g, b);
02365 }
02366 ret->AddAt(p, k*width + i);
02367 }
02368 }
02369
02370 stop_image_decoding(&imdec);
02371 return ret;
02372 }
02373
02374
02375
02376 Double_t *TASImage::GetVecArray()
02377 {
02378
02379
02380
02381
02382 if (!fImage) {
02383 Warning("GetVecArray", "Bad Image");
02384 return 0;
02385 }
02386 if (fImage->alt.vector) {
02387 return fImage->alt.vector;
02388 }
02389
02390 return 0;
02391 }
02392
02393
02394
02395 TArrayD *TASImage::GetArray(UInt_t w, UInt_t h, TImagePalette *palette)
02396 {
02397
02398
02399
02400
02401
02402
02403 if (!fImage) {
02404 Warning("GetArray", "Bad Image");
02405 return 0;
02406 }
02407
02408 TArrayD *ret;
02409
02410 if (fImage->alt.vector) {
02411 ret = new TArrayD(fImage->width*fImage->height, fImage->alt.vector);
02412 return ret;
02413 }
02414
02415 ASImageDecoder *imdec;
02416
02417 w = w ? w : fImage->width;
02418 h = h ? h : fImage->height;
02419
02420 if ((fImage->width != w) || (fImage->height != h)) {
02421 Scale(w, h);
02422 }
02423
02424 ASImage *img = fScaledImage ? fScaledImage->fImage : fImage;
02425
02426 if ((imdec = start_image_decoding(0, img, SCL_DO_ALL, 0, 0,
02427 img->width, 0, 0)) == 0) {
02428 Warning("GetArray", "Failed to create image decoder");
02429 return 0;
02430 }
02431
02432 ret = new TArrayD(w * h);
02433 CARD32 r = 0;
02434 CARD32 g = 0;
02435 CARD32 b = 0;
02436 Int_t p = 0;
02437 Double_t v = 0;
02438
02439 for (UInt_t k = 0; k < h; k++) {
02440 imdec->decode_image_scanline(imdec);
02441
02442 for (UInt_t i = 0; i < w; ++i) {
02443 if ((r == imdec->buffer.red[i]) &&
02444 (g == imdec->buffer.green[i]) &&
02445 (b == imdec->buffer.blue[i])) {
02446 } else {
02447 r = imdec->buffer.red[i];
02448 g = imdec->buffer.green[i];
02449 b = imdec->buffer.blue[i];
02450 if (palette) p = palette->FindColor(r, g, b);
02451 }
02452 v = palette ? palette->fPoints[p] : Double_t((r << 16) + (g << 8) + b)/0xFFFFFF;
02453 ret->AddAt(v, (h-k-1)*w + i);
02454 }
02455 }
02456
02457 stop_image_decoding(&imdec);
02458 return ret;
02459 }
02460
02461
02462
02463 void TASImage::DrawText(Int_t x, Int_t y, const char *text, Int_t size,
02464 const char *color, const char *font_name,
02465 EText3DType type, const char *fore_file, Float_t angle)
02466 {
02467
02468
02469
02470
02471
02472
02473
02474
02475
02476 UInt_t width, height;
02477 ARGB32 text_color = ARGB32_Black;
02478 ASImage *fore_im = 0;
02479 ASImage *text_im = 0;
02480 Bool_t ttfont = kFALSE;
02481
02482 if (!InitVisual()) {
02483 Warning("DrawText", "Visual not initiated");
02484 return;
02485 }
02486
02487 TString fn = font_name;
02488 fn.Strip();
02489 char *tmpstr = 0;
02490
02491 if (fn.EndsWith(".ttf") || fn.EndsWith(".TTF")) {
02492 tmpstr = gSystem->ExpandPathName(fn.Data());
02493 fn = tmpstr;
02494 ttfont = kTRUE;
02495 }
02496 delete [] tmpstr;
02497
02498 if (color) {
02499 parse_argb_color(color, &text_color);
02500 }
02501
02502 if (fImage && fImage->alt.argb32 && ttfont) {
02503 DrawTextTTF(x, y, text, size, text_color, fn.Data(), angle);
02504 return;
02505 }
02506
02507 if (!gFontManager) {
02508 gFontManager = create_font_manager(fgVisual->dpy, 0, 0);
02509 }
02510
02511 if (!gFontManager) {
02512 Warning("DrawText", "cannot create Font Manager");
02513 return;
02514 }
02515
02516 ASFont *font = get_asfont(gFontManager, fn.Data(), 0, size, ASF_GuessWho);
02517
02518 if (!font) {
02519 font = get_asfont(gFontManager, "fixed", 0, size, ASF_GuessWho);
02520 if (!font) {
02521 Warning("DrawText", "cannot find a font %s", font_name);
02522 return;
02523 }
02524 }
02525
02526 get_text_size(text, font, (ASText3DType)type, &width, &height);
02527
02528 if (!fImage) {
02529 fImage = create_asimage(width, height, 0);
02530 fill_asimage(fgVisual, fImage, 0, 0, width, height, 0xFFFFFFFF);
02531 }
02532
02533 text_im = draw_text(text, font, (ASText3DType)type, 0);
02534
02535 ASImage *rimg = fImage;
02536
02537 if (fore_file) {
02538 ASImage *tmp = file2ASImage(fore_file, 0xFFFFFFFF, SCREEN_GAMMA, 0, 0);
02539 if (tmp) {
02540 if ((tmp->width != width) || (tmp->height != height)) {
02541 fore_im = tile_asimage(fgVisual, tmp, 0, 0, width, height, 0,
02542 ASA_ASImage, GetImageCompression(), GetImageQuality());
02543 }
02544 destroy_asimage(&tmp);
02545 } else {
02546 fore_im = tmp;
02547 }
02548 }
02549
02550 if (fore_im) {
02551 move_asimage_channel(fore_im, IC_ALPHA, text_im, IC_ALPHA);
02552 destroy_asimage(&text_im);
02553 } else {
02554 fore_im = text_im ;
02555 }
02556
02557 release_font(font);
02558
02559 if (fore_im) {
02560 ASImage *rendered_im;
02561 ASImageLayer layers[2];
02562
02563 init_image_layers(&(layers[0]), 2);
02564 fore_im->back_color = text_color;
02565 layers[0].im = rimg;
02566 layers[0].dst_x = 0;
02567 layers[0].dst_y = 0;
02568 layers[0].clip_width = rimg->width;
02569 layers[0].clip_height = rimg->height;
02570 layers[0].bevel = 0;
02571 layers[1].im = fore_im;
02572 layers[1].dst_x = x;
02573 layers[1].dst_y = y;
02574 layers[1].clip_width = fore_im->width;
02575 layers[1].clip_height = fore_im->height;
02576
02577 rendered_im = merge_layers(fgVisual, &(layers[0]), 2, rimg->width, rimg->height,
02578 ASA_ASImage, GetImageCompression(), GetImageQuality());
02579
02580 destroy_asimage(&fore_im);
02581 DestroyImage();
02582 fImage = rendered_im;
02583 UnZoom();
02584 }
02585 }
02586
02587
02588
02589 void TASImage::Merge(const TImage *im, const char *op, Int_t x, Int_t y)
02590 {
02591
02592
02593
02594
02595
02596
02597
02598
02599
02600
02601
02602
02603
02604
02605
02606
02607
02608
02609
02610 if (!im) return;
02611
02612 if (!InitVisual()) {
02613 Warning("Merge", "Visual not initiated");
02614 return;
02615 }
02616
02617 ASImage *rendered_im;
02618 ASImageLayer layers[2];
02619
02620 init_image_layers(&(layers[0]), 2);
02621 layers[0].im = fImage;
02622 layers[0].dst_x = 0;
02623 layers[0].dst_y = 0;
02624 layers[0].clip_width = fImage->width;
02625 layers[0].clip_height = fImage->height;
02626 layers[0].bevel = 0;
02627 layers[1].im = ((TASImage*)im)->fImage;
02628 layers[1].dst_x = x;
02629 layers[1].dst_y = y;
02630 layers[1].clip_width = im->GetWidth();
02631 layers[1].clip_height = im->GetHeight();
02632 layers[1].merge_scanlines = blend_scanlines_name2func(op ? op : "add");
02633
02634 rendered_im = merge_layers(fgVisual, &(layers[0]), 2, fImage->width, fImage->height,
02635 ASA_ASImage, GetImageCompression(), GetImageQuality());
02636
02637 DestroyImage();
02638 fImage = rendered_im;
02639 UnZoom();
02640 }
02641
02642
02643
02644 void TASImage::Blur(Double_t hr, Double_t vr)
02645 {
02646
02647
02648
02649
02650 if (!InitVisual()) {
02651 Warning("Blur", "Visual not initiated");
02652 return;
02653 }
02654
02655 if (!fImage) {
02656 fImage = create_asimage(100, 100, 0);
02657
02658 if (!fImage) {
02659 Warning("Blur", "Failed to create image");
02660 return;
02661 }
02662
02663 fill_asimage(fgVisual, fImage, 0, 0, fImage->width, fImage->height, ARGB32_White);
02664 }
02665
02666 ASImage *rendered_im = blur_asimage_gauss(fgVisual, fImage, hr > 0 ? hr : 3,
02667 vr > 0 ? vr : 3, SCL_DO_ALL,
02668 ASA_ASImage, GetImageCompression(), GetImageQuality());
02669 DestroyImage();
02670 fImage = rendered_im;
02671 UnZoom();
02672 }
02673
02674
02675
02676 TObject *TASImage::Clone(const char *newname) const
02677 {
02678
02679
02680 if (!InitVisual() || !fImage) {
02681 Warning("Clone", "Image not initiated");
02682 return 0;
02683 }
02684
02685 TASImage *im = (TASImage*)TImage::Create();
02686
02687 if (!im) {
02688 Warning("Clone", "Failed to create image");
02689 return 0;
02690 }
02691
02692 im->SetName(newname);
02693
02694 im->fImage = clone_asimage(fImage, SCL_DO_ALL);
02695 im->fMaxValue = fMaxValue;
02696 im->fMinValue = fMinValue;
02697 im->fZoomOffX = fZoomOffX;
02698 im->fZoomOffY = fZoomOffY;
02699 im->fZoomWidth = fZoomWidth;
02700 im->fZoomHeight = fZoomHeight;
02701 im->fZoomUpdate = fZoomUpdate;
02702 im->fScaledImage = fScaledImage ? (TASImage*)fScaledImage->Clone("") : 0;
02703
02704 if (fImage->alt.argb32) {
02705 UInt_t sz = fImage->width * fImage->height;
02706 im->fImage->alt.argb32 = (ARGB32*)safemalloc(sz*sizeof(ARGB32));
02707 memcpy(im->fImage->alt.argb32, fImage->alt.argb32, sz * sizeof(ARGB32));
02708 }
02709
02710 return im;
02711 }
02712
02713
02714
02715 Double_t *TASImage::Vectorize(UInt_t max_colors, UInt_t dither, Int_t opaque_threshold)
02716 {
02717
02718
02719
02720
02721
02722
02723
02724
02725
02726
02727 if (!InitVisual()) {
02728 Warning("Vectorize", "Visual not initiated");
02729 return 0;
02730 }
02731
02732 if (!fImage) {
02733 fImage = create_asimage(100, 100, 0);
02734
02735 if (!fImage) {
02736 Warning("Vectorize", "Failed to create image");
02737 return 0;
02738 }
02739
02740 fill_asimage(fgVisual, fImage, 0, 0, fImage->width, fImage->height, ARGB32_White);
02741 }
02742
02743 ASColormap cmap;
02744 int *res;
02745 UInt_t r, g, b;
02746
02747 dither = dither > 7 ? 7 : dither;
02748
02749 res = colormap_asimage(fImage, &cmap, max_colors, dither, opaque_threshold);
02750
02751 Double_t *vec = new Double_t[fImage->height*fImage->width];
02752 UInt_t v;
02753 Double_t tmp;
02754 fMinValue = 2;
02755 fMaxValue = -1;
02756
02757 for (UInt_t y = 0; y < fImage->height; y++) {
02758 for (UInt_t x = 0; x < fImage->width; x++) {
02759 int i = y*fImage->width + x;
02760 g = INDEX_SHIFT_GREEN(cmap.entries[res[i]].green);
02761 b = INDEX_SHIFT_BLUE(cmap.entries[res[i]].blue);
02762 r = INDEX_SHIFT_RED(cmap.entries[res[i]].red);
02763 v = MAKE_INDEXED_COLOR24(r,g,b);
02764 v = (v>>12)&0x0FFF;
02765 tmp = Double_t(v)/0x0FFF;
02766 vec[(fImage->height - y - 1)*fImage->width + x] = tmp;
02767 if (fMinValue > tmp) fMinValue = tmp;
02768 if (fMaxValue < tmp) fMaxValue = tmp;
02769 }
02770 }
02771 TImagePalette *pal = new TImagePalette(cmap.count);
02772
02773 for (UInt_t j = 0; j < cmap.count; j++) {
02774 g = INDEX_SHIFT_GREEN(cmap.entries[j].green);
02775 b = INDEX_SHIFT_BLUE(cmap.entries[j].blue);
02776 r = INDEX_SHIFT_RED(cmap.entries[j].red);
02777 v = MAKE_INDEXED_COLOR24(r,g,b);
02778
02779 v = (v>>12) & 0x0FFF;
02780 pal->fPoints[j] = Double_t(v)/0x0FFF;
02781
02782 pal->fColorRed[j] = cmap.entries[j].red << 8;
02783 pal->fColorGreen[j] = cmap.entries[j].green << 8;
02784 pal->fColorBlue[j] = cmap.entries[j].blue << 8;
02785 pal->fColorAlpha[j] = 0xFF00;
02786 }
02787
02788 destroy_colormap(&cmap, kTRUE);
02789
02790 fPalette = *pal;
02791 fImage->alt.vector = vec;
02792 UnZoom();
02793 if (res) delete res;
02794 return (Double_t*)fImage->alt.vector;
02795 }
02796
02797
02798
02799 void TASImage::HSV(UInt_t hue, UInt_t radius, Int_t H, Int_t S, Int_t V,
02800 Int_t x, Int_t y, UInt_t width, UInt_t height)
02801 {
02802
02803
02804
02805
02806
02807
02808
02809
02810
02811
02812
02813
02814
02815
02816
02817
02818
02819
02820
02821
02822
02823
02824
02825
02826
02827
02828
02829
02830
02831
02832
02833
02834
02835
02836
02837
02838 if (!InitVisual()) {
02839 Warning("HSV", "Visual not initiated");
02840 return;
02841 }
02842
02843 if (!fImage) {
02844 fImage = create_asimage(width ? width : 20, height ? height : 20, 0);
02845
02846 if (!fImage) {
02847 Warning("HSV", "Failed to create image");
02848 return;
02849 }
02850
02851 x = 0;
02852 y = 0;
02853 fill_asimage(fgVisual, fImage, 0, 0, fImage->width, fImage->height, ARGB32_White);
02854 }
02855
02856 width = !width ? fImage->width : width;
02857 height = !height ? fImage->height : height;
02858
02859 ASImage *rendered_im = 0;
02860
02861 if (H || S || V) {
02862 rendered_im = adjust_asimage_hsv(fgVisual, fImage, x, y, width, height,
02863 hue, radius, H, S, V, ASA_ASImage, 100,
02864 ASIMAGE_QUALITY_TOP);
02865 }
02866 if (!rendered_im) {
02867 Warning("HSV", "Failed to create rendered image");
02868 return;
02869 }
02870
02871 DestroyImage();
02872 fImage = rendered_im;
02873 UnZoom();
02874 }
02875
02876
02877
02878 void TASImage::Gradient(UInt_t angle, const char *colors, const char *offsets,
02879 Int_t x, Int_t y, UInt_t width, UInt_t height)
02880 {
02881
02882
02883
02884
02885
02886
02887
02888
02889
02890
02891
02892
02893
02894
02895
02896
02897
02898
02899
02900
02901
02902 if (!InitVisual()) {
02903 Warning("Gradient", "Visual not initiated");
02904 return;
02905 }
02906
02907 ASImage *rendered_im = 0;
02908 ASGradient gradient;
02909
02910 int reverse = 0, npoints1 = 0, npoints2 = 0;
02911 char *p;
02912 char *pb;
02913 char ch;
02914 TString str = colors;
02915 TString col;
02916
02917 if ((angle > 2 * 180 * 15 / 16) || (angle < 2 * 180 * 1 / 16)) {
02918 gradient.type = GRADIENT_Left2Right;
02919 } else if (angle < 2 * 180 * 3 / 16) {
02920 gradient.type = GRADIENT_TopLeft2BottomRight;
02921 } else if (angle < 2 * 180 * 5 / 16) {
02922 gradient.type = GRADIENT_Top2Bottom;
02923 } else if (angle < 2 * 180 * 7 / 16) {
02924 gradient.type = GRADIENT_BottomLeft2TopRight; reverse = 1;
02925 } else if (angle < 2 * 180 * 9 / 16) {
02926 gradient.type = GRADIENT_Left2Right; reverse = 1;
02927 } else if (angle < 2 * 180 * 11 / 16) {
02928 gradient.type = GRADIENT_TopLeft2BottomRight; reverse = 1;
02929 } else if (angle < 2 * 180 * 13 / 16) {
02930 gradient.type = GRADIENT_Top2Bottom; reverse = 1;
02931 } else {
02932 gradient.type = GRADIENT_BottomLeft2TopRight;
02933 }
02934
02935 for (p = (char*)colors; isspace((int)*p); p++) { }
02936
02937 for (npoints1 = 0; *p; npoints1++) {
02938 if (*p) {
02939 for ( ; *p && !isspace((int)*p); p++) { }
02940 }
02941 for ( ; isspace((int)*p); p++) { }
02942 }
02943 if (offsets) {
02944 for (p = (char*)offsets; isspace((int)*p); p++) { }
02945
02946 for (npoints2 = 0; *p; npoints2++) {
02947 if (*p) {
02948 for ( ; *p && !isspace((int)*p); p++) { }
02949 }
02950 for ( ; isspace((int)*p); p++) { }
02951 }
02952 }
02953 if (npoints1 > 1) {
02954 int i;
02955 if (offsets && (npoints1 > npoints2)) npoints1 = npoints2;
02956
02957 if (!width) {
02958 width = fImage ? fImage->width : 20;
02959 }
02960 if (!height) {
02961 height = fImage ? fImage->height : 20;
02962 }
02963
02964 gradient.color = new ARGB32[npoints1];
02965 gradient.offset = new double[npoints1];
02966
02967 for (p = (char*)colors; isspace((int)*p); p++) { }
02968
02969 for (npoints1 = 0; *p; ) {
02970 pb = p;
02971
02972 if (*p) {
02973 for ( ; *p && !isspace((int)*p); p++) { }
02974 }
02975 for ( ; isspace((int)*p); p++) { }
02976
02977 col = str(pb - colors, p - pb);
02978
02979 if (parse_argb_color(col.Data(), gradient.color + npoints1) != col) {
02980 npoints1++;
02981 } else {
02982 Warning("Gradient", "Failed to parse color [%s] - defaulting to black", pb);
02983 }
02984 }
02985
02986 if (offsets) {
02987 for (p = (char*)offsets; isspace((int)*p); p++) { }
02988
02989 for (npoints2 = 0; *p; ) {
02990 pb = p;
02991
02992 if (*p) {
02993 for ( ; *p && !isspace((int)*p); p++) { }
02994 }
02995 ch = *p; *p = '\0';
02996 gradient.offset[npoints2] = strtod(pb, &pb);
02997
02998 if (pb == p) npoints2++;
02999 *p = ch;
03000 for ( ; isspace((int)*p); p++) { }
03001 }
03002 } else {
03003 for (npoints2 = 0; npoints2 < npoints1; npoints2++) {
03004 gradient.offset[npoints2] = (double)npoints2 / (npoints1 - 1);
03005 }
03006 }
03007 gradient.npoints = npoints1;
03008
03009 if (npoints2 && (gradient.npoints > npoints2)) {
03010 gradient.npoints = npoints2;
03011 }
03012 if (reverse) {
03013 for (i = 0; i < gradient.npoints/2; i++) {
03014 int i2 = gradient.npoints - 1 - i;
03015 ARGB32 c = gradient.color[i];
03016 double o = gradient.offset[i];
03017 gradient.color[i] = gradient.color[i2];
03018 gradient.color[i2] = c;
03019 gradient.offset[i] = gradient.offset[i2];
03020 gradient.offset[i2] = o;
03021 }
03022 for (i = 0; i < gradient.npoints; i++) {
03023 gradient.offset[i] = 1.0 - gradient.offset[i];
03024 }
03025 }
03026 rendered_im = make_gradient(fgVisual, &gradient, width, height, SCL_DO_ALL,
03027 ASA_ASImage, GetImageCompression(), GetImageQuality());
03028
03029 delete [] gradient.color;
03030 delete [] gradient.offset;
03031 }
03032
03033 if (!rendered_im) {
03034 Warning("Gradient", "Failed to create gradient image");
03035 return;
03036 }
03037
03038 if (!fImage) {
03039 fImage = rendered_im;
03040 return;
03041 }
03042
03043 ASImageLayer layers[2];
03044
03045 init_image_layers(&(layers[0]), 2);
03046 layers[0].im = fImage;
03047 layers[0].dst_x = 0;
03048 layers[0].dst_y = 0;
03049 layers[0].clip_width = fImage->width;
03050 layers[0].clip_height = fImage->height;
03051 layers[0].bevel = 0;
03052 layers[1].im = rendered_im;
03053 layers[1].dst_x = x;
03054 layers[1].dst_y = y;
03055 layers[1].clip_width = width;
03056 layers[1].clip_height = height;
03057 layers[1].merge_scanlines = alphablend_scanlines;
03058
03059 ASImage *merge_im = merge_layers(fgVisual, &(layers[0]), 2, fImage->width, fImage->height,
03060 ASA_ASImage, GetImageCompression(), GetImageQuality());
03061 if (!merge_im) {
03062 Warning("Gradient", "Failed to create merged image");
03063 return;
03064 }
03065
03066 destroy_asimage(&rendered_im);
03067 DestroyImage();
03068 fImage = merge_im;
03069 UnZoom();
03070 }
03071
03072
03073
03074 static CARD8 MakeComponentHilite(int cmp)
03075 {
03076
03077
03078
03079 if (cmp < 51) {
03080 cmp = 51;
03081 }
03082 cmp = (cmp * 12) / 10;
03083
03084 return (cmp > 255) ? 255 : cmp;
03085 }
03086
03087
03088
03089 static ARGB32 GetHilite(ARGB32 background)
03090 {
03091
03092
03093
03094 return ((MakeComponentHilite((background>>24) & 0x000000FF) << 24) & 0xFF000000) |
03095 ((MakeComponentHilite((background & 0x00FF0000) >> 16) << 16) & 0x00FF0000) |
03096 ((MakeComponentHilite((background & 0x0000FF00) >> 8) << 8) & 0x0000FF00) |
03097 ((MakeComponentHilite((background & 0x000000FF))) & 0x000000FF);
03098 }
03099
03100
03101
03102 static ARGB32 GetShadow(ARGB32 background)
03103 {
03104
03105
03106
03107 return (background >> 1) & 0x7F7F7F7F;
03108 }
03109
03110
03111
03112 static ARGB32 GetAverage(ARGB32 foreground, ARGB32 background)
03113 {
03114
03115
03116
03117 CARD16 a, r, g, b;
03118
03119 a = ARGB32_ALPHA8(foreground) + ARGB32_ALPHA8(background);
03120 a = (a<<3)/10;
03121 r = ARGB32_RED8(foreground) + ARGB32_RED8(background);
03122 r = (r<<3)/10;
03123 g = ARGB32_GREEN8(foreground) + ARGB32_GREEN8(background);
03124 g = (g<<3)/10;
03125 b = ARGB32_BLUE8(foreground) + ARGB32_BLUE8(background);
03126 b = (b<<3)/10;
03127
03128 return MAKE_ARGB32(a, r, g, b);
03129 }
03130
03131
03132
03133 void TASImage::Bevel(Int_t x, Int_t y, UInt_t width, UInt_t height,
03134 const char *hi_color, const char *lo_color, UShort_t thick,
03135 Bool_t reverse)
03136 {
03137
03138
03139
03140
03141
03142
03143
03144
03145
03146 if (!InitVisual()) {
03147 Warning("Bevel", "Visual not initiated");
03148 return;
03149 }
03150
03151 ASImageBevel bevel;
03152 bevel.type = 0;
03153
03154 ARGB32 hi, lo;
03155 parse_argb_color(hi_color, &hi);
03156 parse_argb_color(lo_color, &lo);
03157
03158 if (reverse) {
03159 bevel.lo_color = hi;
03160 bevel.lolo_color = GetHilite(hi);
03161 bevel.hi_color = lo;
03162 bevel.hihi_color = GetShadow(lo);
03163 } else {
03164 bevel.hi_color = hi;
03165 bevel.hihi_color = GetHilite(hi);
03166 bevel.lo_color = lo;
03167 bevel.lolo_color = GetShadow(lo);
03168 }
03169 bevel.hilo_color = GetAverage(hi, lo);
03170
03171 int extra_hilite = 2;
03172 bevel.left_outline = bevel.top_outline = bevel.right_outline = bevel.bottom_outline = thick;
03173 bevel.left_inline = bevel.top_inline = bevel.right_inline = bevel.bottom_inline = extra_hilite + 1;
03174
03175 if (bevel.top_outline > 1) {
03176 bevel.top_inline += bevel.top_outline - 1;
03177 }
03178
03179 if (bevel.left_outline > 1) {
03180 bevel.left_inline += bevel.left_outline - 1;
03181 }
03182
03183 if (bevel.right_outline > 1) {
03184 bevel.right_inline += bevel.right_outline - 1;
03185 }
03186
03187 if (bevel.bottom_outline > 1) {
03188 bevel.bottom_inline += bevel.bottom_outline - 1;
03189 }
03190
03191 ASImage *merge_im;
03192 ARGB32 fill = ((hi>>24) != 0xff) || ((lo>>24) != 0xff) ? bevel.hilo_color : (bevel.hilo_color | 0xff000000);
03193
03194 if (!fImage) {
03195 fImage = create_asimage(width ? width : 20, height ? height : 20, 0);
03196
03197 if (!fImage) {
03198 Warning("Bevel", "Failed to create image");
03199 return;
03200 }
03201
03202 x = 0;
03203 y = 0;
03204 fill_asimage(fgVisual, fImage, 0, 0, fImage->width, fImage->height, fill);
03205 }
03206
03207 width = !width ? fImage->width : width;
03208 height = !height ? fImage->height : height;
03209
03210 ASImageLayer layers[2];
03211 init_image_layers(&(layers[0]), 2);
03212
03213 layers[0].im = fImage;
03214 layers[0].dst_x = 0;
03215 layers[0].dst_y = 0;
03216 layers[0].clip_width = fImage->width;
03217 layers[0].clip_height = fImage->height;
03218 layers[0].bevel = 0;
03219
03220 UInt_t w = width - (bevel.left_outline + bevel.right_outline);
03221 UInt_t h = height - (bevel.top_outline + bevel.bottom_outline);
03222 ASImage *bevel_im = create_asimage(w, h, 0);
03223
03224 if (!bevel_im) {
03225 Warning("Bevel", "Failed to create bevel image");
03226 return;
03227 }
03228
03229 layers[1].im = bevel_im;
03230 fill_asimage(fgVisual, bevel_im, 0, 0, w, h, fill);
03231
03232 layers[1].dst_x = x;
03233 layers[1].dst_y = y;
03234 layers[1].clip_width = width;
03235 layers[1].clip_height = height;
03236 layers[1].bevel = &bevel;
03237 layers[1].merge_scanlines = alphablend_scanlines;
03238
03239 merge_im = merge_layers(fgVisual, &(layers[0]), 2, fImage->width, fImage->height,
03240 ASA_ASImage, GetImageCompression(), GetImageQuality());
03241 destroy_asimage(&bevel_im);
03242
03243 if (!merge_im) {
03244 Warning("Bevel", "Failed to image");
03245 return;
03246 }
03247
03248 DestroyImage();
03249 fImage = merge_im;
03250 UnZoom();
03251 }
03252
03253
03254
03255 void TASImage::Pad(const char *col, UInt_t l, UInt_t r, UInt_t t, UInt_t b)
03256 {
03257
03258
03259
03260 Int_t x, y;
03261 UInt_t w, h;
03262
03263 if (!InitVisual()) {
03264 Warning("Pad", "Visual not initiated");
03265 return;
03266 }
03267
03268 if (!fImage) {
03269 fImage = create_asimage(100, 100, 0);
03270
03271 if (!fImage) {
03272 Warning("Pad", "Failed to create image");
03273 return;
03274 }
03275
03276 x = 0;
03277 y = 0;
03278 fill_asimage(fgVisual, fImage, 0, 0, fImage->width, fImage->height, ARGB32_White);
03279 }
03280
03281 ARGB32 color;
03282 parse_argb_color(col, &color);
03283
03284 x = l;
03285 y = t;
03286 w = l + fImage->width + r;
03287 h = t + fImage->height + b;
03288
03289 ASImage *img = pad_asimage(fgVisual, fImage, x, y, w, h, color,
03290 ASA_ASImage, GetImageCompression(), GetImageQuality());
03291
03292 if (!img) {
03293 Warning("Pad", "Failed to create output image");
03294 return;
03295 }
03296
03297 DestroyImage();
03298 fImage = img;
03299 UnZoom();
03300 fZoomUpdate = kZoomOps;
03301 }
03302
03303
03304
03305 void TASImage::Crop(Int_t x, Int_t y, UInt_t width, UInt_t height)
03306 {
03307
03308
03309 if (!InitVisual()) {
03310 Warning("Crop", "Visual not initiated");
03311 return;
03312 }
03313
03314 if (!fImage) {
03315 Warning("Crop", "No image");
03316 return;
03317 }
03318
03319 x = x < 0 ? 0 : x;
03320 y = y < 0 ? 0 : y;
03321
03322 width = x + width > fImage->width ? fImage->width - x : width;
03323 height = y + height > fImage->height ? fImage->height - y : height;
03324
03325 if ((width == fImage->width) && (height == fImage->height)) {
03326 Warning("Crop", "input size larger than image");
03327 return;
03328 }
03329 ASImageDecoder *imdec = start_image_decoding(fgVisual, fImage, SCL_DO_ALL,
03330 x, y, width, height, 0);
03331
03332 if (!imdec) {
03333 Warning("Crop", "Failed to start image decoding");
03334 return;
03335 }
03336
03337 ASImage *img = create_asimage(width, height, 0);
03338
03339 if (!img) {
03340 delete [] imdec;
03341 Warning("Crop", "Failed to create image");
03342 return;
03343 }
03344
03345 ASImageOutput *imout = start_image_output(fgVisual, img, ASA_ASImage,
03346 GetImageCompression(), GetImageQuality());
03347
03348 if (!imout) {
03349 Warning("Crop", "Failed to start image output");
03350 destroy_asimage(&img);
03351 if (imdec) delete [] imdec;
03352 return;
03353 }
03354
03355 #ifdef HAVE_MMX
03356 mmx_init();
03357 #endif
03358
03359 for (UInt_t i = 0; i < height; i++) {
03360 imdec->decode_image_scanline(imdec);
03361 imout->output_image_scanline(imout, &(imdec->buffer), 1);
03362 }
03363
03364 stop_image_decoding(&imdec);
03365 stop_image_output(&imout);
03366
03367 #ifdef HAVE_MMX
03368 mmx_off();
03369 #endif
03370
03371 DestroyImage();
03372 fImage = img;
03373 UnZoom();
03374 fZoomUpdate = kZoomOps;
03375 }
03376
03377
03378
03379 void TASImage::Append(const TImage *im, const char *option, const char *color )
03380 {
03381
03382
03383
03384
03385
03386
03387 if (!im) return;
03388
03389 if (!InitVisual()) {
03390 Warning("Append", "Visual not initiated");
03391 return;
03392 }
03393
03394 if (!fImage) {
03395 fImage = ((TASImage*)im)->fImage;
03396 return;
03397 }
03398
03399 TString opt = option;
03400 opt.Strip();
03401
03402 UInt_t width = fImage->width;
03403 UInt_t height = fImage->height;
03404
03405 if (opt == "+") {
03406 Pad(color, 0, im->GetWidth(), 0, 0);
03407 Merge(im, "alphablend", width, 0);
03408 } else if (opt == "/") {
03409 Pad(color, 0, 0, 0, im->GetHeight());
03410 Merge(im, "alphablend", 0, height);
03411 } else {
03412 return;
03413 }
03414
03415 UnZoom();
03416 }
03417
03418
03419
03420 void TASImage::BeginPaint(Bool_t mode)
03421 {
03422
03423
03424
03425
03426
03427
03428 if (!InitVisual()) {
03429 Warning("BeginPaint", "Visual not initiated");
03430 return;
03431 }
03432
03433 if (!fImage) {
03434 return;
03435 }
03436
03437 fPaintMode = mode;
03438
03439 if (!fPaintMode || fImage->alt.argb32) {
03440 return;
03441 }
03442
03443 ASImage *img = tile_asimage(fgVisual, fImage, 0, 0, fImage->width, fImage->height,
03444 0, ASA_ARGB32, 0, ASIMAGE_QUALITY_DEFAULT);
03445
03446 if (!img) {
03447 Warning("BeginPaint", "Failed to create image");
03448 return;
03449 }
03450
03451 DestroyImage();
03452 fImage = img;
03453 }
03454
03455
03456
03457 void TASImage::EndPaint()
03458 {
03459
03460
03461 if (!fImage) {
03462 Warning("EndPaint", "no image");
03463 return;
03464 }
03465
03466 if (!fImage->alt.argb32) return;
03467
03468 ASImage *img = tile_asimage(fgVisual, fImage, 0, 0, fImage->width, fImage->height,
03469 0, ASA_ASImage, 0, ASIMAGE_QUALITY_DEFAULT);
03470
03471 if (!img) {
03472 Warning("EndPaint", "Failed to create image");
03473 return;
03474 }
03475
03476 fPaintMode = kFALSE;
03477 DestroyImage();
03478 fImage = img;
03479 }
03480
03481
03482
03483 UInt_t *TASImage::GetArgbArray()
03484 {
03485
03486
03487
03488
03489 if (!fImage) {
03490 Warning("GetArgbArray", "no image");
03491 return 0;
03492 }
03493
03494 ASImage *img = fScaledImage ? fScaledImage->fImage : fImage;
03495 if (!img) return 0;
03496
03497 if (!img->alt.argb32) {
03498 if (fScaledImage) {
03499 fScaledImage->BeginPaint();
03500 img = fScaledImage->fImage;
03501 } else {
03502 BeginPaint();
03503 img = fImage;
03504 }
03505 }
03506
03507 return (UInt_t *)img->alt.argb32;
03508 }
03509
03510
03511
03512 UInt_t *TASImage::GetRgbaArray()
03513 {
03514
03515
03516
03517
03518 if (!fImage) {
03519 Warning("GetRgbaArray", "no image");
03520 return 0;
03521 }
03522
03523 ASImage *img = fScaledImage ? fScaledImage->fImage : fImage;
03524 if (!img) return 0;
03525
03526 if (!img->alt.argb32) {
03527 if (fScaledImage) {
03528 fScaledImage->BeginPaint();
03529 img = fScaledImage->fImage;
03530 } else {
03531 BeginPaint();
03532 img = fImage;
03533 }
03534 }
03535
03536 UInt_t i, j;
03537 Int_t y = 0;
03538 Int_t idx = 0;
03539 UInt_t a, rgb, rgba, argb;
03540 y = 0;
03541
03542 UInt_t *ret = new UInt_t[img->width*img->height];
03543
03544 for (i = 0; i < img->height; i++) {
03545 for (j = 0; j < img->width; j++) {
03546 idx = y + j;
03547 argb = img->alt.argb32[idx];
03548 a = argb >> 24;
03549 rgb = argb & 0x00ffffff;
03550 rgba = (rgb << 8) + a;
03551 ret[idx] = rgba;
03552 }
03553 y += img->width;
03554 }
03555
03556 return ret;
03557 }
03558
03559
03560
03561 UInt_t *TASImage::GetScanline(UInt_t y)
03562 {
03563
03564
03565 if (!fImage) {
03566 Warning("GetScanline", "no image");
03567 return 0;
03568 }
03569
03570 ASImage *img = fScaledImage ? fScaledImage->fImage : fImage;
03571 CARD32 *ret = new CARD32[img->width];
03572
03573 ASImageDecoder *imdec = start_image_decoding(fgVisual, img, SCL_DO_ALL,
03574 0, y, img->width, 1, 0);
03575
03576 if (!imdec) {
03577 delete [] ret;
03578 Warning("GetScanline", "Failed to start image decoding");
03579 return 0;
03580 }
03581
03582 #ifdef HAVE_MMX
03583 mmx_init();
03584 #endif
03585
03586 imdec->decode_image_scanline(imdec);
03587 memcpy(imdec->buffer.buffer, ret, img->width*sizeof(CARD32));
03588 stop_image_decoding(&imdec);
03589
03590 #ifdef HAVE_MMX
03591 mmx_off();
03592 #endif
03593
03594 return (UInt_t*)ret;
03595 }
03596
03597
03598
03599
03600
03601
03602
03603 #if defined(R__GNU) && defined(__i386__) && !defined(__sun)
03604 #define _MEMSET_(dst, lng, val) __asm__("movl %0,%%eax \n"\
03605 "movl %1,%%edi \n" \
03606 "movl %2,%%ecx \n" \
03607 "cld \n" \
03608 "rep \n" \
03609 "stosl %%eax,(%%edi) \n" \
03610 : \
03611 :"g" (val), "g" (dst), "g" (lng) \
03612 :"eax","edi","ecx" \
03613 )
03614
03615 #else
03616 #define _MEMSET_(dst, lng, val) do {\
03617 for( UInt_t j=0; j < lng; j++) *((dst)+j) = val; } while (0)
03618
03619 #endif
03620
03621 #define FillSpansInternal(npt, ppt, widths, color) do {\
03622 UInt_t yy = ppt[0].fY*fImage->width;\
03623 for (UInt_t i = 0; i < npt; i++) {\
03624 _MEMSET_(&fImage->alt.argb32[yy + ppt[i].fX], widths[i], color);\
03625 yy += ((i+1 < npt) && (ppt[i].fY != ppt[i+1].fY) ? fImage->width : 0);\
03626 }\
03627 } while (0)
03628
03629
03630
03631 void TASImage::FillRectangleInternal(UInt_t col, Int_t x, Int_t y, UInt_t width, UInt_t height)
03632 {
03633
03634
03635
03636 ARGB32 color = (ARGB32)col;
03637
03638 if (width == 0) width = 1;
03639 if (height == 0) height = 1;
03640
03641 if (x < 0) {
03642 width += x;
03643 x = 0;
03644 }
03645 if (y < 0) {
03646 height += y;
03647 y = 0;
03648 }
03649
03650 Bool_t has_alpha = (color & 0xff000000) != 0xff000000;
03651
03652 x = x > (int)fImage->width ? (Int_t)fImage->width : x;
03653 y = y > (int)fImage->height ? (Int_t)fImage->height : y;
03654
03655 width = x + width > fImage->width ? fImage->width - x : width;
03656 height = y + height > fImage->height ? fImage->height - y : height;
03657
03658 if (!fImage->alt.argb32) {
03659 fill_asimage(fgVisual, fImage, x, y, width, height, color);
03660 } else {
03661 int yyy = y*fImage->width;
03662 if (!has_alpha) {
03663 ARGB32 *p0 = fImage->alt.argb32 + yyy + x;
03664 ARGB32 *p = p0;
03665 for (UInt_t i = 0; i < height; i++) {
03666 _MEMSET_(p, width, color);
03667 p += fImage->width;
03668 }
03669 } else {
03670 for (UInt_t i = y; i < y + height; i++) {
03671 int j = x + width;
03672 while (j > x) {
03673 j--;
03674 _alphaBlend(&fImage->alt.argb32[yyy + j], &color);
03675 }
03676 }
03677 yyy += fImage->width;
03678 }
03679 }
03680 }
03681
03682
03683
03684 void TASImage::FillRectangle(const char *col, Int_t x, Int_t y, UInt_t width, UInt_t height)
03685 {
03686
03687
03688
03689
03690
03691
03692
03693
03694 if (!InitVisual()) {
03695 Warning("Fill", "Visual not initiated");
03696 return;
03697 }
03698
03699 ARGB32 color = ARGB32_White;
03700
03701 if (col) {
03702 parse_argb_color(col, &color);
03703 }
03704
03705 if (!fImage) {
03706 fImage = create_asimage(width ? width : 20, height ? height : 20, 0);
03707 x = 0;
03708 y = 0;
03709 }
03710
03711 FillRectangleInternal((UInt_t)color, x, y, width, height);
03712 UnZoom();
03713 }
03714
03715
03716
03717 void TASImage::DrawVLine(UInt_t x, UInt_t y1, UInt_t y2, UInt_t col, UInt_t thick)
03718 {
03719
03720
03721 ARGB32 color = (ARGB32)col;
03722 UInt_t half = 0;
03723
03724 if (!thick) thick = 1;
03725
03726 if (thick > 1) {
03727 half = thick >> 1;
03728 if (x > half) {
03729 x = x - half;
03730 } else {
03731 x = 0;
03732 thick += (x - half);
03733 }
03734 }
03735
03736 y2 = y2 >= fImage->height ? fImage->height - 1 : y2;
03737 y1 = y1 >= fImage->height ? fImage->height - 1 : y1;
03738 x = x + thick >= fImage->width ? fImage->width - thick - 1 : x;
03739
03740 int yy = y1*fImage->width;
03741 for (UInt_t y = y1; y <= y2; y++) {
03742 for (UInt_t w = 0; w < thick; w++) {
03743 if (x + w < fImage->width) {
03744 _alphaBlend(&fImage->alt.argb32[yy + (x + w)], &color);
03745 }
03746 }
03747 yy += fImage->width;
03748 }
03749 }
03750
03751
03752
03753 void TASImage::DrawHLine(UInt_t y, UInt_t x1, UInt_t x2, UInt_t col, UInt_t thick)
03754 {
03755
03756
03757 ARGB32 color = (ARGB32)col;
03758 UInt_t half = 0;
03759
03760 if (!thick) thick = 1;
03761
03762 if (thick > 1) {
03763 half = thick >> 1;
03764 if (y > half) {
03765 y = y - half;
03766 } else {
03767 y = 0;
03768 thick += (y - half);
03769 }
03770 }
03771
03772 y = y + thick >= fImage->height ? fImage->height - thick - 1 : y;
03773 x2 = x2 >= fImage->width ? fImage->width - 1 : x2;
03774 x1 = x1 >= fImage->width ? fImage->width - 1 : x1;
03775
03776 int yy = y*fImage->width;
03777 for (UInt_t w = 0; w < thick; w++) {
03778 for (UInt_t x = x1; x <= x2; x++) {
03779 if (y + w < fImage->height) {
03780 _alphaBlend(&fImage->alt.argb32[yy + x], &color);
03781 }
03782 }
03783 yy += fImage->width;
03784 }
03785 }
03786
03787
03788
03789 void TASImage::DrawLine(UInt_t x1, UInt_t y1, UInt_t x2, UInt_t y2,
03790 const char *col, UInt_t thick)
03791 {
03792
03793
03794 ARGB32 color;
03795 parse_argb_color(col, &color);
03796 DrawLineInternal(x1, y1, x2, y2, (UInt_t)color, thick);
03797 }
03798
03799
03800
03801 void TASImage::DrawLineInternal(UInt_t x1, UInt_t y1, UInt_t x2, UInt_t y2,
03802 UInt_t col, UInt_t thick)
03803 {
03804
03805
03806 int dx, dy, d;
03807 int i1, i2;
03808 int x, y, xend, yend;
03809 int xdir, ydir;
03810 int wid, q;
03811 int idx;
03812 int yy;
03813
03814 if (!InitVisual()) {
03815 Warning("DrawLine", "Visual not initiated");
03816 return;
03817 }
03818
03819 if (!fImage) {
03820 Warning("DrawLine", "no image");
03821 return;
03822 }
03823
03824 if (!fImage->alt.argb32) {
03825 BeginPaint();
03826 }
03827
03828 if (!fImage->alt.argb32) {
03829 Warning("DrawLine", "Failed to get pixel array");
03830 return;
03831 }
03832
03833 ARGB32 color = (ARGB32)col;
03834
03835 dx = TMath::Abs(Int_t(x2) - Int_t(x1));
03836 dy = TMath::Abs(Int_t(y2) - Int_t(y1));
03837
03838 if (!dx) {
03839 DrawVLine(x1, y2 > y1 ? y1 : y2,
03840 y2 > y1 ? y2 : y1, color, thick);
03841 return;
03842 }
03843
03844 if (!dy) {
03845 DrawHLine(y1, x2 > x1 ? x1 : x2,
03846 x2 > x1 ? x2 : x1, color, thick);
03847 return;
03848 }
03849
03850 if (thick > 1) {
03851 DrawWideLine(x1, y1, x2, y2, color, thick);
03852 return;
03853 }
03854
03855 wid = 1;
03856
03857 if (dy <= dx) {
03858 UInt_t ddy = dy << 1;
03859 i1 = ddy;
03860 i2 = i1 - (dx << 1);
03861 d = i1 - dx;
03862
03863 if (x1 > x2) {
03864 x = x2;
03865 y = y2;
03866 ydir = -1;
03867 xend = x1;
03868 } else {
03869 x = x1;
03870 y = y1;
03871 ydir = 1;
03872 xend = x2;
03873 }
03874
03875 yy = y*fImage->width;
03876 _alphaBlend(&fImage->alt.argb32[yy + x], &color);
03877 q = (y2 - y1) * ydir;
03878
03879 if (q > 0) {
03880 while (x < xend) {
03881 idx = yy + x;
03882 _alphaBlend(&fImage->alt.argb32[idx], &color);
03883 x++;
03884
03885 if (d >= 0) {
03886 yy += fImage->width;
03887 d += i2;
03888 } else {
03889 d += i1;
03890 }
03891 }
03892 } else {
03893 while (x < xend) {
03894 idx = yy + x;
03895 _alphaBlend(&fImage->alt.argb32[idx], &color);
03896 x++;
03897
03898 if (d >= 0) {
03899 yy -= fImage->width;
03900 d += i2;
03901 } else {
03902 d += i1;
03903 }
03904 }
03905 }
03906 } else {
03907 UInt_t ddx = dx << 1;
03908 i1 = ddx;
03909 i2 = i1 - (dy << 1);
03910 d = i1 - dy;
03911
03912 if (y1 > y2) {
03913 y = y2;
03914 x = x2;
03915 yend = y1;
03916 xdir = -1;
03917 } else {
03918 y = y1;
03919 x = x1;
03920 yend = y2;
03921 xdir = 1;
03922 }
03923
03924 yy = y*fImage->width;
03925 _alphaBlend(&fImage->alt.argb32[yy + x], &color);
03926 q = (x2 - x1) * xdir;
03927
03928 if (q > 0) {
03929 while (y < yend) {
03930 idx = yy + x;
03931 _alphaBlend(&fImage->alt.argb32[idx], &color);
03932 y++;
03933 yy += fImage->width;
03934
03935 if (d >= 0) {
03936 x++;
03937 d += i2;
03938 } else {
03939 d += i1;
03940 }
03941 }
03942 } else {
03943 while (y < yend) {
03944 idx = yy + x;
03945 _alphaBlend(&fImage->alt.argb32[idx], &color);
03946 y++;
03947 yy += fImage->width;
03948
03949 if (d >= 0) {
03950 x--;
03951 d += i2;
03952 } else {
03953 d += i1;
03954 }
03955 }
03956 }
03957 }
03958 }
03959
03960
03961
03962 void TASImage::DrawRectangle(UInt_t x, UInt_t y, UInt_t w, UInt_t h,
03963 const char *col, UInt_t thick)
03964 {
03965
03966
03967 if (!InitVisual()) {
03968 Warning("DrawRectangle", "Visual not initiated");
03969 return;
03970 }
03971
03972 if (!fImage) {
03973 w = w ? w : 20;
03974 h = h ? h : 20;
03975 x = 0;
03976 y = 0;
03977 fImage = create_asimage(w, h, 0);
03978 FillRectangle(col, 0, 0, w, h);
03979 return;
03980 }
03981
03982 if (!fImage->alt.argb32) {
03983 BeginPaint();
03984 }
03985
03986 if (!fImage->alt.argb32) {
03987 Warning("DrawRectangle", "Failed to get pixel array");
03988 return;
03989 }
03990
03991 ARGB32 color;
03992 parse_argb_color(col, &color);
03993
03994 DrawHLine(y, x, x + w, (UInt_t)color, thick);
03995 DrawVLine(x + w, y, y + h, (UInt_t)color, thick);
03996 DrawHLine(y + h, x, x + w, (UInt_t)color, thick);
03997 DrawVLine(x, y, y + h, (UInt_t)color, thick);
03998 UnZoom();
03999 }
04000
04001
04002
04003 void TASImage::DrawBox(Int_t x1, Int_t y1, Int_t x2, Int_t y2, const char *col,
04004 UInt_t thick, Int_t mode)
04005 {
04006
04007
04008 Int_t x = TMath::Min(x1, x2);
04009 Int_t y = TMath::Min(y1, y2);
04010 Int_t w = TMath::Abs(x2 - x1);
04011 Int_t h = TMath::Abs(y2 - y1);
04012
04013 ARGB32 color;
04014
04015 if (!fImage) {
04016 w = w ? x+w : x+20;
04017 h = h ? y+h : y+20;
04018 fImage = create_asimage(w, h, 0);
04019 FillRectangle(col, 0, 0, w, h);
04020 return;
04021 }
04022
04023 if (x1 == x2) {
04024 parse_argb_color(col, &color);
04025 DrawVLine(x1, y1, y2, color, 1);
04026 return;
04027 }
04028
04029 if (y1 == y2) {
04030 parse_argb_color(col, &color);
04031 DrawHLine(y1, x1, x2, color, 1);
04032 return;
04033 }
04034
04035
04036 switch (mode) {
04037 case TVirtualX::kHollow:
04038 DrawRectangle(x, y, w, h, col, thick);
04039 break;
04040
04041 case TVirtualX::kFilled:
04042 FillRectangle(col, x, y, w, h);
04043 break;
04044
04045 default:
04046 FillRectangle(col, x, y, w, h);
04047 break;
04048 }
04049 }
04050
04051
04052
04053 void TASImage::DrawDashHLine(UInt_t y, UInt_t x1, UInt_t x2, UInt_t nDash,
04054 const char *pDash, UInt_t col, UInt_t thick)
04055 {
04056
04057
04058 UInt_t iDash = 0;
04059 int i = 0;
04060
04061 ARGB32 color = (ARGB32)col;
04062
04063 UInt_t half = 0;
04064
04065 if (thick > 1) {
04066 half = thick >> 1;
04067 if (y > half) {
04068 y = y - half;
04069 } else {
04070 y = 0;
04071 thick += (y - half);
04072 }
04073 }
04074 thick = thick <= 0 ? 1 : thick;
04075
04076 y = y + thick >= fImage->height ? fImage->height - thick - 1 : y;
04077 x2 = x2 >= fImage->width ? fImage->width - 1 : x2;
04078 x1 = x1 >= fImage->width ? fImage->width - 1 : x1;
04079
04080
04081 UInt_t tmp = x1;
04082 x1 = x2 < x1 ? x2 : x1;
04083 x2 = x2 < tmp ? tmp : x2;
04084
04085 int yy = y*fImage->width;
04086 for (UInt_t w = 0; w < thick; w++) {
04087 for (UInt_t x = x1; x <= x2; x++) {
04088 if (y + w < fImage->height) {
04089 if ((iDash%2)==0) {
04090 _alphaBlend(&fImage->alt.argb32[yy + x], &color);
04091 }
04092 }
04093 i++;
04094
04095 if (i >= pDash[iDash]) {
04096 iDash++;
04097 i = 0;
04098 }
04099 if (iDash >= nDash) {
04100 iDash = 0;
04101 i = 0;
04102 }
04103 }
04104 yy += fImage->width;
04105 }
04106 }
04107
04108
04109
04110 void TASImage::DrawDashVLine(UInt_t x, UInt_t y1, UInt_t y2, UInt_t nDash,
04111 const char *pDash, UInt_t col, UInt_t thick)
04112 {
04113
04114
04115 UInt_t iDash = 0;
04116 int i = 0;
04117
04118 ARGB32 color = (ARGB32)col;
04119
04120 UInt_t half = 0;
04121
04122 if (thick > 1) {
04123 half = thick >> 1;
04124 if (x > half) {
04125 x = x - half;
04126 } else {
04127 x = 0;
04128 thick += (x - half);
04129 }
04130 }
04131 thick = thick <= 0 ? 1 : thick;
04132
04133 y2 = y2 >= fImage->height ? fImage->height - 1 : y2;
04134 y1 = y1 >= fImage->height ? fImage->height - 1 : y1;
04135
04136
04137 UInt_t tmp = y1;
04138 y1 = y2 < y1 ? y2 : y1;
04139 y2 = y2 < tmp ? tmp : y2;
04140
04141 x = x + thick >= fImage->width ? fImage->width - thick - 1 : x;
04142
04143 int yy = y1*fImage->width;
04144 for (UInt_t y = y1; y <= y2; y++) {
04145 for (UInt_t w = 0; w < thick; w++) {
04146 if (x + w < fImage->width) {
04147 if ((iDash%2)==0) {
04148 _alphaBlend(&fImage->alt.argb32[yy + (x + w)], &color);
04149 }
04150 }
04151 }
04152 i++;
04153
04154 if (i >= pDash[iDash]) {
04155 iDash++;
04156 i = 0;
04157 }
04158 if (iDash >= nDash) {
04159 iDash = 0;
04160 i = 0;
04161 }
04162 yy += fImage->width;
04163 }
04164 }
04165
04166
04167
04168 void TASImage::DrawDashZLine(UInt_t x1, UInt_t y1, UInt_t x2, UInt_t y2,
04169 UInt_t nDash, const char *tDash, UInt_t color)
04170 {
04171
04172
04173 int dx, dy, d;
04174 int i, i1, i2;
04175 int x, y, xend, yend;
04176 int xdir, ydir;
04177 int q;
04178 UInt_t iDash = 0;
04179 int yy;
04180 int idx;
04181
04182 dx = TMath::Abs(Int_t(x2) - Int_t(x1));
04183 dy = TMath::Abs(Int_t(y2) - Int_t(y1));
04184
04185 char *pDash = new char[nDash];
04186
04187 if (dy <= dx) {
04188 double ac = TMath::Cos(TMath::ATan2(dy, dx));
04189
04190 for (i = 0; i < (int)nDash; i++) {
04191 pDash[i] = TMath::Nint(tDash[i] * ac);
04192 }
04193
04194 UInt_t ddy = dy << 1;
04195 i1 = ddy;
04196 i2 = i1 - (dx << 1);
04197 d = i1 - dx;
04198 i = 0;
04199
04200 if (x1 > x2) {
04201 x = x2;
04202 y = y2;
04203 ydir = -1;
04204 xend = x1;
04205 } else {
04206 x = x1;
04207 y = y1;
04208 ydir = 1;
04209 xend = x2;
04210 }
04211
04212 yy = y*fImage->width;
04213 _alphaBlend(&fImage->alt.argb32[y*fImage->width + x], &color);
04214 q = (y2 - y1) * ydir;
04215
04216 if (q > 0) {
04217 while (x < xend) {
04218 idx = yy + x;
04219 if ((iDash%2) == 0) {
04220 _alphaBlend(&fImage->alt.argb32[idx], &color);
04221 }
04222 x++;
04223 if (d >= 0) {
04224 yy += fImage->width;
04225 d += i2;
04226 } else {
04227 d += i1;
04228 }
04229
04230 i++;
04231 if (i >= pDash[iDash]) {
04232 iDash++;
04233 i = 0;
04234 }
04235 if (iDash >= nDash) {
04236 iDash = 0;
04237 i = 0;
04238 }
04239 }
04240 } else {
04241 while (x < xend) {
04242 idx = yy + x;
04243 if ((iDash%2) == 0) {
04244 _alphaBlend(&fImage->alt.argb32[idx], &color);
04245 }
04246 x++;
04247 if (d >= 0) {
04248 yy -= fImage->width;
04249 d += i2;
04250 } else {
04251 d += i1;
04252 }
04253
04254 i++;
04255 if (i >= pDash[iDash]) {
04256 iDash++;
04257 i = 0;
04258 }
04259 if (iDash >= nDash) {
04260 iDash = 0;
04261 i = 0;
04262 }
04263 }
04264 }
04265 } else {
04266 double as = TMath::Sin(TMath::ATan2(dy, dx));
04267
04268 for (i = 0; i < (int)nDash; i++) {
04269 pDash[i] = TMath::Nint(tDash[i] * as);
04270 }
04271
04272 UInt_t ddx = dx << 1;
04273 i1 = ddx;
04274 i2 = i1 - (dy << 1);
04275 d = i1 - dy;
04276 i = 0;
04277
04278 if (y1 > y2) {
04279 y = y2;
04280 x = x2;
04281 yend = y1;
04282 xdir = -1;
04283 } else {
04284 y = y1;
04285 x = x1;
04286 yend = y2;
04287 xdir = 1;
04288 }
04289
04290 yy = y*fImage->width;
04291 _alphaBlend(&fImage->alt.argb32[y*fImage->width + x], &color);
04292 q = (x2 - x1) * xdir;
04293
04294 if (q > 0) {
04295 while (y < yend) {
04296 idx = yy + x;
04297 if ((iDash%2) == 0) {
04298 _alphaBlend(&fImage->alt.argb32[idx], &color);
04299 }
04300 y++;
04301 yy += fImage->width;
04302
04303 if (d >= 0) {
04304 x++;
04305 d += i2;
04306 } else {
04307 d += i1;
04308 }
04309
04310 i++;
04311 if (i >= pDash[iDash]) {
04312 iDash++;
04313 i = 0;
04314 }
04315 if (iDash >= nDash) {
04316 iDash = 0;
04317 i = 0;
04318 }
04319 }
04320 } else {
04321 while (y < yend) {
04322 idx = yy + x;
04323 if ((iDash%2) == 0) {
04324 _alphaBlend(&fImage->alt.argb32[idx], &color);
04325 }
04326 y++;
04327 yy += fImage->width;
04328
04329 if (d >= 0) {
04330 x--;
04331 d += i2;
04332 } else {
04333 d += i1;
04334 }
04335
04336 i++;
04337 if (i >= pDash[iDash]) {
04338 iDash++;
04339 i = 0;
04340 }
04341 if (iDash >= nDash) {
04342 iDash = 0;
04343 i = 0;
04344 }
04345 }
04346 }
04347 }
04348 delete [] pDash;
04349 }
04350
04351
04352
04353 void TASImage::DrawDashZTLine(UInt_t x1, UInt_t y1, UInt_t x2, UInt_t y2,
04354 UInt_t nDash, const char *tDash, UInt_t color, UInt_t thick)
04355 {
04356
04357
04358 int dx, dy;
04359 int i;
04360 double x, y, xend=0, yend=0, x0, y0;
04361 int xdir, ydir;
04362 int q;
04363 UInt_t iDash = 0;
04364
04365 dx = TMath::Abs(Int_t(x2) - Int_t(x1));
04366 dy = TMath::Abs(Int_t(y2) - Int_t(y1));
04367
04368 double *xDash = new double[nDash];
04369 double *yDash = new double[nDash];
04370 double a = TMath::ATan2(dy, dx);
04371 double ac = TMath::Cos(a);
04372 double as = TMath::Sin(a);
04373
04374 for (i = 0; i < (int)nDash; i++) {
04375 xDash[i] = tDash[i] * ac;
04376 yDash[i] = tDash[i] * as;
04377
04378
04379 if ((i%2) == 0) {
04380 xDash[i] = xDash[i]/2;
04381 yDash[i] = yDash[i]/2;
04382 } else {
04383 xDash[i] = xDash[i]*2;
04384 yDash[i] = yDash[i]*2;
04385 }
04386 }
04387
04388 if (dy <= dx) {
04389 if (x1 > x2) {
04390 x = x2;
04391 y = y2;
04392 ydir = -1;
04393 xend = x1;
04394 } else {
04395 x = x1;
04396 y = y1;
04397 ydir = 1;
04398 xend = x2;
04399 }
04400
04401 q = (y2 - y1) * ydir;
04402 x0 = x;
04403 y0 = y;
04404 iDash = 0;
04405 yend = y + q;
04406
04407 if (q > 0) {
04408 while ((x < xend) && (y < yend)) {
04409 x += xDash[iDash];
04410 y += yDash[iDash];
04411
04412 if ((iDash%2) == 0) {
04413 DrawWideLine(TMath::Nint(x0), TMath::Nint(y0),
04414 TMath::Nint(x), TMath::Nint(y), color, thick);
04415 } else {
04416 x0 = x;
04417 y0 = y;
04418 }
04419
04420 iDash++;
04421
04422 if (iDash >= nDash) {
04423 iDash = 0;
04424 }
04425 }
04426 } else {
04427 while ((x < xend) && (y > yend)) {
04428 x += xDash[iDash];
04429 y -= yDash[iDash];
04430
04431 if ((iDash%2) == 0) {
04432 DrawWideLine(TMath::Nint(x0), TMath::Nint(y0),
04433 TMath::Nint(x), TMath::Nint(y), color, thick);
04434 } else {
04435 x0 = x;
04436 y0 = y;
04437 }
04438
04439 iDash++;
04440
04441 if (iDash >= nDash) {
04442 iDash = 0;
04443 }
04444 }
04445 }
04446 } else {
04447
04448 if (y1 > y2) {
04449 y = y2;
04450 x = x2;
04451 yend = y1;
04452 xdir = -1;
04453 } else {
04454 y = y1;
04455 x = x1;
04456 yend = y2;
04457 xdir = 1;
04458 }
04459
04460 q = (x2 - x1) * xdir;
04461 x0 = x;
04462 y0 = y;
04463 iDash = 0;
04464
04465 if (q > 0) {
04466 while ((x < xend) && (y < yend)) {
04467 x += xDash[iDash];
04468 y += yDash[iDash];
04469
04470 if ((iDash%2) == 0) {
04471 DrawWideLine(TMath::Nint(x0), TMath::Nint(y0),
04472 TMath::Nint(x), TMath::Nint(y), color, thick);
04473 } else {
04474 x0 = x;
04475 y0 = y;
04476 }
04477
04478 iDash++;
04479
04480 if (iDash >= nDash) {
04481 iDash = 0;
04482 }
04483 }
04484 } else {
04485 while ((x > xend) && (y < yend)) {
04486 x -= xDash[iDash];
04487 y += yDash[iDash];
04488
04489 if ((iDash%2) == 0) {
04490 DrawWideLine(TMath::Nint(x0), TMath::Nint(y0),
04491 TMath::Nint(x), TMath::Nint(y), color, thick);
04492 } else {
04493 x0 = x;
04494 y0 = y;
04495 }
04496
04497 iDash++;
04498
04499 if (iDash >= nDash) {
04500 iDash = 0;
04501 }
04502 }
04503 }
04504 }
04505 delete [] xDash;
04506 delete [] yDash;
04507 }
04508
04509
04510
04511 void TASImage::DrawDashLine(UInt_t x1, UInt_t y1, UInt_t x2, UInt_t y2, UInt_t nDash,
04512 const char *pDash, const char *col, UInt_t thick)
04513
04514 {
04515
04516
04517 if (!InitVisual()) {
04518 Warning("DrawDashLine", "Visual not initiated");
04519 return;
04520 }
04521
04522 if (!fImage) {
04523 Warning("DrawDashLine", "no image");
04524 return;
04525 }
04526
04527 if (!fImage->alt.argb32) {
04528 BeginPaint();
04529 }
04530
04531 if (!fImage->alt.argb32) {
04532 Warning("DrawDashLine", "Failed to get pixel array");
04533 return;
04534 }
04535
04536 if ((nDash < 2) || !pDash || (nDash%2)) {
04537 Warning("DrawDashLine", "Wrong input parameters n=%d %ld", nDash, (Long_t)sizeof(pDash)-1);
04538 return;
04539 }
04540
04541 ARGB32 color;
04542 parse_argb_color(col, &color);
04543
04544 if (x1 == x2) {
04545 DrawDashVLine(x1, y1, y2, nDash, pDash, (UInt_t)color, thick);
04546 } else if (y1 == y2) {
04547 DrawDashHLine(y1, x1, x2, nDash, pDash, (UInt_t)color, thick);
04548 } else {
04549 if (thick < 2) DrawDashZLine(x1, y1, x2, y2, nDash, pDash, (UInt_t)color);
04550 else DrawDashZTLine(x1, y1, x2, y2, nDash, pDash, (UInt_t)color, thick);
04551 }
04552 }
04553
04554
04555
04556 void TASImage::DrawPolyLine(UInt_t nn, TPoint *xy, const char *col, UInt_t thick,
04557 TImage::ECoordMode mode)
04558 {
04559
04560
04561 ARGB32 color;
04562 parse_argb_color(col, &color);
04563
04564 Int_t x0 = xy[0].GetX();
04565 Int_t y0 = xy[0].GetY();
04566 Int_t x = 0;
04567 Int_t y = 0;
04568
04569 for (UInt_t i = 1; i < nn; i++) {
04570 x = (mode == kCoordModePrevious) ? x + xy[i].GetX() : xy[i].GetX();
04571 y = (mode == kCoordModePrevious) ? y + xy[i].GetY() : xy[i].GetY();
04572
04573 DrawLineInternal(x0, y0, x, y, (UInt_t)color, thick);
04574
04575 x0 = x;
04576 y0 = y;
04577 }
04578 }
04579
04580
04581
04582 void TASImage::PutPixel(Int_t x, Int_t y, const char *col)
04583 {
04584
04585
04586 if (!InitVisual()) {
04587 Warning("PutPixel", "Visual not initiated");
04588 return;
04589 }
04590
04591 if (!fImage) {
04592 Warning("PutPixel", "no image");
04593 return;
04594 }
04595
04596 if (!fImage->alt.argb32) {
04597 BeginPaint();
04598 }
04599
04600 if (!fImage->alt.argb32) {
04601 Warning("PutPixel", "Failed to get pixel array");
04602 return;
04603 }
04604
04605 ARGB32 color;
04606 parse_argb_color(col, &color);
04607
04608 if ((x < 0) || (y < 0) || (x >= (int)fImage->width) || (y >= (int)fImage->height)) {
04609 Warning("PutPixel", "Out of range width=%d x=%d, height=%d y=%d",
04610 fImage->width, x, fImage->height, y);
04611 return;
04612 }
04613 _alphaBlend(&fImage->alt.argb32[y*fImage->width + x], &color);
04614 }
04615
04616
04617
04618 void TASImage::PolyPoint(UInt_t npt, TPoint *ppt, const char *col, TImage::ECoordMode mode)
04619 {
04620
04621
04622 if (!InitVisual()) {
04623 Warning("PolyPoint", "Visual not initiated");
04624 return;
04625 }
04626
04627 if (!fImage) {
04628 Warning("PolyPoint", "no image");
04629 return;
04630 }
04631
04632 if (!fImage->alt.argb32) {
04633 BeginPaint();
04634 }
04635
04636 if (!fImage->alt.argb32) {
04637 Warning("PolyPoint", "Failed to get pixel array");
04638 return;
04639 }
04640
04641 if (!npt || !ppt) {
04642 Warning("PolyPoint", "No points specified");
04643 return;
04644 }
04645
04646 TPoint *ipt = 0;
04647 UInt_t i = 0;
04648 ARGB32 color;
04649 parse_argb_color(col, &color);
04650
04651
04652 if (mode == kCoordModePrevious) {
04653 ipt = new TPoint[npt];
04654
04655 for (i = 0; i < npt; i++) {
04656 ipt[i].fX += ppt[i].fX;
04657 ipt[i].fY += ppt[i].fY;
04658 }
04659 }
04660 int x, y;
04661
04662 for (i = 0; i < npt; i++) {
04663 x = ipt ? ipt[i].fX : ppt[i].fX;
04664 y = ipt ? ipt[i].fY : ppt[i].fY;
04665
04666 if ((x < 0) || (y < 0) || (x >= (int)fImage->width) || (y >= (int)fImage->height)) {
04667 continue;
04668 }
04669 _alphaBlend(&fImage->alt.argb32[y*fImage->width + x], &color);
04670 }
04671
04672 if (ipt) {
04673 delete [] ipt;
04674 }
04675 }
04676
04677
04678
04679 void TASImage::DrawSegments(UInt_t nseg, Segment_t *seg, const char *col, UInt_t thick)
04680 {
04681
04682
04683 if (!nseg || !seg) {
04684 Warning("DrawSegments", "Ivalid data nseg=%d seg=0x%lx", nseg, (Long_t)seg);
04685 return;
04686 }
04687
04688 TPoint pt[2];
04689
04690 for (UInt_t i = 0; i < nseg; i++) {
04691 pt[0].fX = seg->fX1;
04692 pt[1].fX = seg->fX2;
04693 pt[0].fY = seg->fY1;
04694 pt[1].fY = seg->fY2;
04695
04696 DrawPolyLine(2, pt, col, thick, kCoordModeOrigin);
04697 seg++;
04698 }
04699 }
04700
04701
04702
04703 void TASImage::FillSpans(UInt_t npt, TPoint *ppt, UInt_t *widths, const char *col,
04704 const char *stipple, UInt_t w, UInt_t h)
04705 {
04706
04707
04708 if (!InitVisual()) {
04709 Warning("FillSpans", "Visual not initiated");
04710 return;
04711 }
04712
04713 if (!fImage) {
04714 Warning("FillSpans", "no image");
04715 return;
04716 }
04717
04718 if (!fImage->alt.argb32) {
04719 BeginPaint();
04720 }
04721
04722 if (!fImage->alt.argb32) {
04723 Warning("FillSpans", "Failed to get pixel array");
04724 return;
04725 }
04726
04727 if (!npt || !ppt || !widths || (stipple && (!w || !h))) {
04728 Warning("FillSpans", "Invalid input data npt=%d ppt=0x%lx col=%s widths=0x%lx stipple=0x%lx w=%d h=%d",
04729 npt, (Long_t)ppt, col, (Long_t)widths, (Long_t)stipple, w, h);
04730 return;
04731 }
04732
04733 ARGB32 color;
04734 parse_argb_color(col, &color);
04735 Int_t idx = 0;
04736 UInt_t x = 0;
04737 UInt_t yy;
04738
04739 for (UInt_t i = 0; i < npt; i++) {
04740 yy = ppt[i].fY*fImage->width;
04741 for (UInt_t j = 0; j < widths[i]; j++) {
04742 if ((ppt[i].fX >= (Int_t)fImage->width) || (ppt[i].fX < 0) ||
04743 (ppt[i].fY >= (Int_t)fImage->height) || (ppt[i].fY < 0)) continue;
04744
04745 x = ppt[i].fX + j;
04746 idx = yy + x;
04747
04748 if (!stipple) {
04749 _alphaBlend(&fImage->alt.argb32[idx], &color);
04750 } else {
04751 Int_t ii = (ppt[i].fY%h)*w + x%w;
04752
04753 if (stipple[ii >> 3] & (1 << (ii%8))) {
04754 _alphaBlend(&fImage->alt.argb32[idx], &color);
04755 }
04756 }
04757 }
04758 }
04759 }
04760
04761
04762
04763 void TASImage::FillSpans(UInt_t npt, TPoint *ppt, UInt_t *widths, TImage *tile)
04764 {
04765
04766
04767 if (!InitVisual()) {
04768 Warning("FillSpans", "Visual not initiated");
04769 return;
04770 }
04771
04772 if (!fImage) {
04773 Warning("FillSpans", "no image");
04774 return;
04775 }
04776
04777 if (!fImage->alt.argb32) {
04778 BeginPaint();
04779 }
04780
04781 if (!fImage->alt.argb32) {
04782 Warning("FillSpans", "Failed to get pixel array");
04783 return;
04784 }
04785
04786 if (!npt || !ppt || !widths || !tile) {
04787 Warning("FillSpans", "Invalid input data npt=%d ppt=0x%lx widths=0x%lx tile=0x%lx",
04788 npt, (Long_t)ppt, (Long_t)widths, (Long_t)tile);
04789 return;
04790 }
04791
04792 Int_t idx = 0;
04793 Int_t ii = 0;
04794 UInt_t x = 0;
04795 UInt_t *arr = tile->GetArgbArray();
04796 UInt_t xx = 0;
04797 UInt_t yy = 0;
04798 UInt_t yyy = 0;
04799
04800 for (UInt_t i = 0; i < npt; i++) {
04801 yyy = ppt[i].fY*fImage->width;
04802
04803 for (UInt_t j = 0; j < widths[i]; j++) {
04804 if ((ppt[i].fX >= (Int_t)fImage->width) || (ppt[i].fX < 0) ||
04805 (ppt[i].fY >= (Int_t)fImage->height) || (ppt[i].fY < 0)) continue;
04806 x = ppt[i].fX + j;
04807 idx = yyy + x;
04808 xx = x%tile->GetWidth();
04809 yy = ppt[i].fY%tile->GetHeight();
04810 ii = yy*tile->GetWidth() + xx;
04811 _alphaBlend(&fImage->alt.argb32[idx], &arr[ii]);
04812 }
04813 yyy += fImage->width;;
04814 }
04815 }
04816
04817
04818
04819 void TASImage::CropSpans(UInt_t npt, TPoint *ppt, UInt_t *widths)
04820 {
04821
04822
04823 if (!InitVisual()) {
04824 Warning("CropSpans", "Visual not initiated");
04825 return;
04826 }
04827
04828 if (!fImage) {
04829 Warning("CropSpans", "no image");
04830 return;
04831 }
04832
04833 if (!fImage->alt.argb32) {
04834 BeginPaint();
04835 }
04836
04837 if (!fImage->alt.argb32) {
04838 Warning("CropSpans", "Failed to get pixel array");
04839 return;
04840 }
04841
04842 if (!npt || !ppt || !widths) {
04843 Warning("CropSpans", "No points specified npt=%d ppt=0x%lx widths=0x%lx", npt, (Long_t)ppt, (Long_t)widths);
04844 return;
04845 }
04846
04847 int y0 = ppt[0].fY;
04848 int y1 = ppt[npt-1].fY;
04849 UInt_t y = 0;
04850 UInt_t x = 0;
04851 UInt_t i = 0;
04852 UInt_t idx = 0;
04853 UInt_t sz = fImage->width*fImage->height;
04854 UInt_t yy = y*fImage->width;
04855
04856 for (y = 0; (int)y < y0; y++) {
04857 for (x = 0; x < fImage->width; x++) {
04858 idx = yy + x;
04859 if (idx < sz) fImage->alt.argb32[idx] = 0;
04860 }
04861 yy += fImage->width;
04862 }
04863
04864 for (i = 0; i < npt; i++) {
04865 for (x = 0; (int)x < ppt[i].fX; x++) {
04866 idx = ppt[i].fY*fImage->width + x;
04867 if (idx < sz) fImage->alt.argb32[idx] = 0;
04868 }
04869 for (x = ppt[i].fX + widths[i] + 1; x < fImage->width; x++) {
04870 idx = ppt[i].fY*fImage->width + x;
04871 if (idx < sz) fImage->alt.argb32[idx] = 0;
04872 }
04873 }
04874
04875 yy = y1*fImage->width;
04876 for (y = y1; y < fImage->height; y++) {
04877 for (x = 0; x < fImage->width; x++) {
04878 idx = yy + x;
04879 if (idx < sz) fImage->alt.argb32[idx] = 0;
04880 }
04881 yy += fImage->width;
04882 }
04883 }
04884
04885
04886
04887 void TASImage::CopyArea(TImage *dst, Int_t xsrc, Int_t ysrc, UInt_t w, UInt_t h,
04888 Int_t xdst, Int_t ydst, Int_t gfunc, EColorChan)
04889 {
04890
04891
04892
04893
04894
04895
04896
04897
04898
04899
04900
04901
04902
04903
04904
04905
04906
04907
04908
04909
04910
04911
04912 if (!InitVisual()) {
04913 Warning("CopyArea", "Visual not initiated");
04914 return;
04915 }
04916
04917 if (!fImage) {
04918 Warning("CopyArea", "no image");
04919 return;
04920 }
04921 if (!dst) return;
04922
04923 ASImage *out = ((TASImage*)dst)->GetImage();
04924
04925 int x = 0;
04926 int y = 0;
04927 int idx = 0;
04928 int idx2 = 0;
04929 xsrc = xsrc < 0 ? 0 : xsrc;
04930 ysrc = ysrc < 0 ? 0 : ysrc;
04931
04932 if ((xsrc >= (int)fImage->width) || (ysrc >= (int)fImage->height)) return;
04933
04934 w = xsrc + w > fImage->width ? fImage->width - xsrc : w;
04935 h = ysrc + h > fImage->height ? fImage->height - ysrc : h;
04936 UInt_t yy = (ysrc + y)*fImage->width;
04937
04938 if (!fImage->alt.argb32) {
04939 BeginPaint();
04940 }
04941 if (!out->alt.argb32) {
04942 dst->BeginPaint();
04943 out = ((TASImage*)dst)->GetImage();
04944 }
04945
04946 if (fImage->alt.argb32 && out->alt.argb32) {
04947 for (y = 0; y < (int)h; y++) {
04948 for (x = 0; x < (int)w; x++) {
04949 idx = yy + x + xsrc;
04950 if ((x + xdst < 0) || (ydst + y < 0) ||
04951 (x + xdst >= (int)out->width) || (y + ydst >= (int)out->height) ) continue;
04952
04953 idx2 = (ydst + y)*out->width + x + xdst;
04954
04955 switch ((EGraphicsFunction)gfunc) {
04956 case kGXclear:
04957 out->alt.argb32[idx2] = 0;
04958 break;
04959 case kGXand:
04960 out->alt.argb32[idx2] &= fImage->alt.argb32[idx];
04961 break;
04962 case kGXandReverse:
04963 out->alt.argb32[idx2] = fImage->alt.argb32[idx] & (~out->alt.argb32[idx2]);
04964 break;
04965 case kGXandInverted:
04966 out->alt.argb32[idx2] &= ~fImage->alt.argb32[idx];
04967 break;
04968 case kGXnoop:
04969 break;
04970 case kGXxor:
04971 out->alt.argb32[idx2] ^= fImage->alt.argb32[idx];
04972 break;
04973 case kGXor:
04974 out->alt.argb32[idx2] |= fImage->alt.argb32[idx];
04975 break;
04976 case kGXnor:
04977 out->alt.argb32[idx2] = (~fImage->alt.argb32[idx]) & (~out->alt.argb32[idx2]);
04978 break;
04979 case kGXequiv:
04980 out->alt.argb32[idx2] ^= ~fImage->alt.argb32[idx];
04981 break;
04982 case kGXinvert:
04983 out->alt.argb32[idx2] = ~out->alt.argb32[idx2];
04984 break;
04985 case kGXorReverse:
04986 out->alt.argb32[idx2] = fImage->alt.argb32[idx] | (~out->alt.argb32[idx2]);
04987 break;
04988 case kGXcopyInverted:
04989 out->alt.argb32[idx2] = ~fImage->alt.argb32[idx];
04990 break;
04991 case kGXorInverted:
04992 out->alt.argb32[idx2] |= ~fImage->alt.argb32[idx];
04993 break;
04994 case kGXnand:
04995 out->alt.argb32[idx2] = (~fImage->alt.argb32[idx]) | (~out->alt.argb32[idx2]);
04996 break;
04997 case kGXset:
04998 out->alt.argb32[idx2] = 0xFFFFFFFF;
04999 break;
05000 case kGXcopy:
05001 default:
05002 out->alt.argb32[idx2] = fImage->alt.argb32[idx];
05003 break;
05004 }
05005 }
05006 yy += fImage->width;
05007 }
05008 }
05009 }
05010
05011
05012
05013 void TASImage::DrawCellArray(Int_t x1, Int_t y1, Int_t x2, Int_t y2, Int_t nx,
05014 Int_t ny, UInt_t *ic)
05015 {
05016
05017
05018
05019
05020
05021
05022
05023
05024
05025
05026 int i, j, ix, iy, w, h;
05027
05028 ARGB32 color = 0xFFFFFFFF;
05029 ARGB32 icol;
05030
05031 w = TMath::Max((x2-x1)/(nx),1);
05032 h = TMath::Max((y1-y2)/(ny),1);
05033 ix = x1;
05034
05035 for (i = 0; i < nx; i++) {
05036 iy = y1 - h;
05037 for (j = 0; j < ny; j++) {
05038 icol = (ARGB32)ic[i + (nx*j)];
05039 if (icol != color) {
05040 color = icol;
05041 }
05042 FillRectangleInternal((UInt_t)color, ix, iy, w, h);
05043 iy = iy - h;
05044 }
05045 ix = ix + w;
05046 }
05047 }
05048
05049
05050
05051 UInt_t TASImage::AlphaBlend(UInt_t bot, UInt_t top)
05052 {
05053
05054
05055 UInt_t ret = bot;
05056
05057 _alphaBlend(&ret, &top);
05058 return ret;
05059 }
05060
05061
05062
05063 const ASVisual *TASImage::GetVisual()
05064 {
05065
05066
05067 return fgVisual;
05068 }
05069
05070
05071
05072 static int GetPolyYBounds(TPoint *pts, int n, int *by, int *ty)
05073 {
05074
05075
05076 register TPoint *ptMin;
05077 int ymin, ymax;
05078 TPoint *ptsStart = pts;
05079
05080 ptMin = pts;
05081 ymin = ymax = (pts++)->fY;
05082
05083 while (--n > 0) {
05084 if (pts->fY < ymin) {
05085 ptMin = pts;
05086 ymin = pts->fY;
05087 }
05088 if (pts->fY > ymax) {
05089 ymax = pts->fY;
05090 }
05091 pts++;
05092 }
05093
05094 *by = ymin;
05095 *ty = ymax;
05096 return (ptMin - ptsStart);
05097 }
05098
05099
05100
05101 Bool_t TASImage::GetPolygonSpans(UInt_t npt, TPoint *ppt, UInt_t *nspans,
05102 TPoint **outPoint, UInt_t **outWidth)
05103 {
05104
05105
05106
05107 int xl = 0;
05108 int xr = 0;
05109 int dl = 0;
05110 int dr = 0;
05111 int ml = 0;
05112 int m1l = 0;
05113 int mr = 0, m1r = 0;
05114 int incr1l = 0, incr2l = 0;
05115 int incr1r = 0, incr2r = 0;
05116 int dy;
05117 int y;
05118 int left, right;
05119 int i;
05120 int nextleft, nextright;
05121 TPoint *ptsOut;
05122 UInt_t *width;
05123 TPoint *firstPoint=0;
05124 UInt_t *firstWidth=0;
05125 int imin;
05126 int ymin;
05127 int ymax;
05128 Bool_t ret = kTRUE;
05129
05130 *nspans = 0;
05131
05132 if (!InitVisual()) {
05133 Warning("GetPolygonSpans", "Visual not initiated");
05134 return kFALSE;
05135 }
05136
05137 if (!fImage) {
05138 Warning("GetPolygonSpans", "no image");
05139 return kFALSE;
05140 }
05141
05142 if (!fImage->alt.argb32) {
05143 BeginPaint();
05144 }
05145
05146 if (!fImage->alt.argb32) {
05147 Warning("GetPolygonSpans", "Failed to get pixel array");
05148 return kFALSE;
05149 }
05150
05151 if ((npt < 3) || !ppt) {
05152 Warning("GetPolygonSpans", "No points specified npt=%d ppt=0x%lx", npt, (Long_t)ppt);
05153 return kFALSE;
05154 }
05155
05156
05157
05158 imin = GetPolyYBounds(ppt, npt, &ymin, &ymax);
05159
05160 dy = ymax - ymin + 1;
05161 if ((npt < 3) || (dy < 0)) return kFALSE;
05162
05163 ptsOut = firstPoint = new TPoint[dy];
05164 width = firstWidth = new UInt_t[dy];
05165 ret = kTRUE;
05166
05167 nextleft = nextright = imin;
05168 y = ppt[nextleft].fY;
05169
05170
05171 do {
05172
05173 if (ppt[nextleft].fY == y) {
05174 left = nextleft;
05175
05176
05177
05178 nextleft++;
05179 if (nextleft >= (int)npt) {
05180 nextleft = 0;
05181 }
05182
05183
05184
05185 BRESINITPGON(ppt[nextleft].fY - ppt[left].fY,
05186 ppt[left].fX, ppt[nextleft].fX,
05187 xl, dl, ml, m1l, incr1l, incr2l);
05188 }
05189
05190
05191 if (ppt[nextright].fY == y) {
05192 right = nextright;
05193
05194
05195
05196 nextright--;
05197 if (nextright < 0) {
05198 nextright = npt-1;
05199 }
05200
05201
05202
05203 BRESINITPGON(ppt[nextright].fY - ppt[right].fY,
05204 ppt[right].fX, ppt[nextright].fX,
05205 xr, dr, mr, m1r, incr1r, incr2r);
05206 }
05207
05208
05209
05210 i = min(ppt[nextleft].fY, ppt[nextright].fY) - y;
05211
05212
05213 if (i < 0) {
05214 delete [] firstWidth;
05215 delete [] firstPoint;
05216 return kTRUE;
05217 }
05218
05219 while (i-- > 0) {
05220 ptsOut->fY = y;
05221
05222
05223 if (xl < xr) {
05224 *(width++) = xr - xl;
05225 (ptsOut++)->fX = xl;
05226 } else {
05227 *(width++) = xl - xr;
05228 (ptsOut++)->fX = xr;
05229 }
05230 y++;
05231
05232
05233 BRESINCRPGON(dl, xl, ml, m1l, incr1l, incr2l);
05234 BRESINCRPGON(dr, xr, mr, m1r, incr1r, incr2r);
05235 }
05236 } while (y != ymax);
05237
05238 *nspans = UInt_t(ptsOut - firstPoint);
05239 *outPoint = firstPoint;
05240 *outWidth = firstWidth;
05241
05242 return ret;
05243 }
05244
05245
05246
05247 void TASImage::FillPolygon(UInt_t npt, TPoint *ppt, const char *col,
05248 const char *stipple, UInt_t w, UInt_t h)
05249 {
05250
05251
05252
05253 UInt_t nspans = 0;
05254 TPoint *firstPoint = 0;
05255 UInt_t *firstWidth = 0;
05256
05257 Bool_t del = GetPolygonSpans(npt, ppt, &nspans, &firstPoint, &firstWidth);
05258 ARGB32 color;
05259 parse_argb_color(col, &color);
05260
05261 if (nspans) {
05262 if (!stipple && ((color & 0xff000000)==0xff000000)) {
05263 FillSpansInternal(nspans, firstPoint, firstWidth, color);
05264 } else {
05265 FillSpans(nspans, firstPoint, firstWidth, col, stipple, w, h);
05266 }
05267
05268 if (del) {
05269 delete [] firstWidth;
05270 delete [] firstPoint;
05271 }
05272 } else {
05273 if (firstWidth) delete [] firstWidth;
05274 if (firstPoint) delete [] firstPoint;
05275 }
05276 }
05277
05278
05279
05280 void TASImage::FillPolygon(UInt_t npt, TPoint *ppt, TImage *tile)
05281 {
05282
05283
05284
05285 UInt_t nspans = 0;
05286 TPoint *firstPoint = 0;
05287 UInt_t *firstWidth = 0;
05288
05289 Bool_t del = GetPolygonSpans(npt, ppt, &nspans, &firstPoint, &firstWidth);
05290
05291 if (nspans) {
05292 FillSpans(nspans, firstPoint, firstWidth, tile);
05293
05294 if (del) {
05295 delete [] firstWidth;
05296 delete [] firstPoint;
05297 }
05298 } else {
05299 if (firstWidth) delete [] firstWidth;
05300 if (firstPoint) delete [] firstPoint;
05301 }
05302 }
05303
05304
05305
05306 void TASImage::CropPolygon(UInt_t npt, TPoint *ppt)
05307 {
05308
05309
05310 UInt_t nspans = 0;
05311 TPoint *firstPoint = 0;
05312 UInt_t *firstWidth = 0;
05313
05314 Bool_t del = GetPolygonSpans(npt, ppt, &nspans, &firstPoint, &firstWidth);
05315
05316 if (nspans) {
05317 CropSpans(nspans, firstPoint, firstWidth);
05318
05319 if (del) {
05320 delete [] firstWidth;
05321 delete [] firstPoint;
05322 }
05323 } else {
05324 if (firstWidth) delete [] firstWidth;
05325 if (firstPoint) delete [] firstPoint;
05326 }
05327 }
05328
05329 static const UInt_t NUMPTSTOBUFFER = 512;
05330
05331
05332
05333 void TASImage::DrawFillArea(UInt_t count, TPoint *ptsIn, const char *col,
05334 const char *stipple, UInt_t w, UInt_t h)
05335 {
05336
05337
05338 if (!InitVisual()) {
05339 Warning("DrawFillArea", "Visual not initiated");
05340 return;
05341 }
05342
05343 if (!fImage) {
05344 Warning("DrawFillArea", "no image");
05345 return;
05346 }
05347
05348 if (!fImage->alt.argb32) {
05349 BeginPaint();
05350 }
05351
05352 if (!fImage->alt.argb32) {
05353 Warning("DrawFillArea", "Failed to get pixel array");
05354 return;
05355 }
05356
05357 if ((count < 3) || !ptsIn) {
05358 Warning("DrawFillArea", "No points specified npt=%d ppt=0x%lx", count, (Long_t)ptsIn);
05359 return;
05360 }
05361
05362 if (count < 5) {
05363 FillPolygon(count, ptsIn, col, stipple, w, h);
05364 return;
05365 }
05366
05367 ARGB32 color;
05368 parse_argb_color(col, &color);
05369
05370 EdgeTableEntry *pAET;
05371 int y;
05372 UInt_t nPts = 0;
05373
05374 ScanLineList *pSLL;
05375 TPoint *ptsOut;
05376 UInt_t *width;
05377 TPoint firstPoint[NUMPTSTOBUFFER];
05378 UInt_t firstWidth[NUMPTSTOBUFFER];
05379 EdgeTableEntry *pPrevAET;
05380 EdgeTable ET;
05381 EdgeTableEntry AET;
05382 EdgeTableEntry *pETEs;
05383 ScanLineListBlock SLLBlock;
05384 Bool_t del = kTRUE;
05385
05386 static const UInt_t gEdgeTableEntryCacheSize = 200;
05387 static EdgeTableEntry gEdgeTableEntryCache[gEdgeTableEntryCacheSize];
05388
05389 if (count < gEdgeTableEntryCacheSize) {
05390 pETEs = (EdgeTableEntry*)&gEdgeTableEntryCache;
05391 del = kFALSE;
05392 } else {
05393 pETEs = new EdgeTableEntry[count];
05394 del = kTRUE;
05395 }
05396
05397 ptsOut = firstPoint;
05398 width = firstWidth;
05399 CreateETandAET(count, ptsIn, &ET, &AET, pETEs, &SLLBlock);
05400 pSLL = ET.scanlines.next;
05401
05402 for (y = ET.ymin; y < ET.ymax; y++) {
05403 if (pSLL && y == pSLL->scanline) {
05404 loadAET(&AET, pSLL->edgelist);
05405 pSLL = pSLL->next;
05406 }
05407 pPrevAET = &AET;
05408 pAET = AET.next;
05409
05410 while (pAET) {
05411 ptsOut->fX = pAET->bres.minor_axis;
05412 ptsOut->fY = y;
05413 ptsOut++;
05414 nPts++;
05415
05416 *width++ = pAET->next->bres.minor_axis - pAET->bres.minor_axis;
05417
05418 if (nPts == NUMPTSTOBUFFER) {
05419 if (!stipple && ((color & 0xff000000)==0xff000000)) {
05420 FillSpansInternal(nPts, firstPoint, firstWidth, color);
05421 } else {
05422 FillSpans(nPts, firstPoint, firstWidth, col, stipple, w, h);
05423 }
05424 ptsOut = firstPoint;
05425 width = firstWidth;
05426 nPts = 0;
05427 }
05428 EVALUATEEDGEEVENODD(pAET, pPrevAET, y)
05429 EVALUATEEDGEEVENODD(pAET, pPrevAET, y)
05430 }
05431 InsertionSort(&AET);
05432 }
05433
05434 if (nPts) {
05435 if (!stipple && ((color & 0xff000000)==0xff000000)) {
05436 FillSpansInternal(nPts, firstPoint, firstWidth, color);
05437 } else {
05438 FillSpans(nPts, firstPoint, firstWidth, col, stipple, w, h);
05439 }
05440 }
05441
05442 if (del) delete [] pETEs;
05443 FreeStorage(SLLBlock.next);
05444 }
05445
05446
05447
05448 void TASImage::DrawFillArea(UInt_t count, TPoint *ptsIn, TImage *tile)
05449 {
05450
05451
05452 if (!InitVisual()) {
05453 Warning("DrawFillArea", "Visual not initiated");
05454 return;
05455 }
05456
05457 if (!fImage) {
05458 Warning("DrawFillArea", "no image");
05459 return;
05460 }
05461
05462 if (!fImage->alt.argb32) {
05463 BeginPaint();
05464 }
05465
05466 if (!fImage->alt.argb32) {
05467 Warning("DrawFillArea", "Failed to get pixel array");
05468 return;
05469 }
05470
05471 if ((count < 3) || !ptsIn) {
05472 Warning("DrawFillArea", "No points specified npt=%d ppt=0x%lx", count, (Long_t)ptsIn);
05473 return;
05474 }
05475
05476 if (count < 5) {
05477 FillPolygon(count, ptsIn, tile);
05478 return;
05479 }
05480
05481 EdgeTableEntry *pAET;
05482 int y;
05483 UInt_t nPts = 0;
05484
05485 ScanLineList *pSLL;
05486 TPoint *ptsOut;
05487 UInt_t *width;
05488 TPoint firstPoint[NUMPTSTOBUFFER];
05489 UInt_t firstWidth[NUMPTSTOBUFFER];
05490 EdgeTableEntry *pPrevAET;
05491 EdgeTable ET;
05492 EdgeTableEntry AET;
05493 EdgeTableEntry *pETEs;
05494 ScanLineListBlock SLLBlock;
05495
05496 pETEs = new EdgeTableEntry[count];
05497
05498 ptsOut = firstPoint;
05499 width = firstWidth;
05500 CreateETandAET(count, ptsIn, &ET, &AET, pETEs, &SLLBlock);
05501 pSLL = ET.scanlines.next;
05502
05503 for (y = ET.ymin; y < ET.ymax; y++) {
05504 if (pSLL && y == pSLL->scanline) {
05505 loadAET(&AET, pSLL->edgelist);
05506 pSLL = pSLL->next;
05507 }
05508 pPrevAET = &AET;
05509 pAET = AET.next;
05510
05511 while (pAET) {
05512 ptsOut->fX = pAET->bres.minor_axis;
05513 ptsOut->fY = y;
05514 ptsOut++;
05515 nPts++;
05516
05517 *width++ = pAET->next->bres.minor_axis - pAET->bres.minor_axis;
05518
05519 if (nPts == NUMPTSTOBUFFER) {
05520 FillSpans(nPts, firstPoint, firstWidth, tile);
05521 ptsOut = firstPoint;
05522 width = firstWidth;
05523 nPts = 0;
05524 }
05525 EVALUATEEDGEEVENODD(pAET, pPrevAET, y)
05526 EVALUATEEDGEEVENODD(pAET, pPrevAET, y)
05527 }
05528 InsertionSort(&AET);
05529 }
05530 FillSpans(nPts, firstPoint, firstWidth, tile);
05531
05532 delete [] pETEs;
05533 FreeStorage(SLLBlock.next);
05534 }
05535
05536
05537
05538 static ASDrawContext *create_draw_context_argb32(ASImage *im, ASDrawTool *brush)
05539 {
05540
05541
05542 ASDrawContext *ctx = new ASDrawContext;
05543
05544 ctx->canvas_width = im->width;
05545 ctx->canvas_height = im->height;
05546 ctx->canvas = im->alt.argb32;
05547 ctx->scratch_canvas = 0;
05548
05549 ctx->flags = ASDrawCTX_CanvasIsARGB;
05550 asim_set_custom_brush_colored( ctx, brush);
05551 return ctx;
05552 }
05553
05554
05555
05556 static void destroy_asdraw_context32( ASDrawContext *ctx )
05557 {
05558
05559
05560 if (ctx) {
05561 if (ctx->scratch_canvas) free(ctx->scratch_canvas);
05562 delete ctx;
05563 }
05564 }
05565
05566 static const UInt_t kBrushCacheSize = 20;
05567 static CARD32 gBrushCache[kBrushCacheSize*kBrushCacheSize];
05568
05569
05570
05571 void TASImage::DrawWideLine(UInt_t x1, UInt_t y1, UInt_t x2, UInt_t y2,
05572 UInt_t color, UInt_t thick)
05573 {
05574
05575
05576 Int_t sz = thick*thick;
05577 CARD32 *matrix;
05578 Bool_t use_cache = thick < kBrushCacheSize;
05579
05580 if (use_cache) {
05581 matrix = gBrushCache;
05582 } else {
05583 matrix = new CARD32[sz];
05584 }
05585
05586 for (int i = 0; i < sz; i++) {
05587 matrix[i] = (CARD32)color;
05588 };
05589
05590 ASDrawTool brush;
05591 brush.matrix = matrix;
05592 brush.width = thick;
05593 brush.height = thick;
05594 brush.center_y = brush.center_x = thick/2;
05595
05596 ASDrawContext *ctx = create_draw_context_argb32(fImage, &brush);
05597 asim_move_to(ctx, x1, y1);
05598 asim_line_to(ctx, x2, y2);
05599
05600 if (!use_cache) {
05601 delete [] matrix;
05602 }
05603 destroy_asdraw_context32(ctx);
05604 }
05605
05606
05607
05608 void TASImage::DrawGlyph(void *bitmap, UInt_t color, Int_t bx, Int_t by)
05609 {
05610
05611
05612 static UInt_t col[5];
05613 Int_t x, y, yy, y0, xx;
05614
05615 ULong_t r, g, b;
05616 int idx = 0;
05617 FT_Bitmap *source = (FT_Bitmap*)bitmap;
05618 UChar_t d = 0, *s = source->buffer;
05619
05620 Int_t dots = Int_t(source->width * source->rows);
05621 r = g = b = 0;
05622 Int_t bxx, byy;
05623
05624 yy = y0 = by > 0 ? by * fImage->width : 0;
05625 for (y = 0; y < (int) source->rows; y++) {
05626 byy = by + y;
05627 if ((byy >= (int)fImage->height) || (byy <0)) continue;
05628
05629 for (x = 0; x < (int) source->width; x++) {
05630 bxx = bx + x;
05631 if ((bxx >= (int)fImage->width) || (bxx < 0)) continue;
05632
05633 idx = bxx + yy;
05634 r += ((fImage->alt.argb32[idx] & 0xff0000) >> 16);
05635 g += ((fImage->alt.argb32[idx] & 0x00ff00) >> 8);
05636 b += (fImage->alt.argb32[idx] & 0x0000ff);
05637 }
05638 yy += fImage->width;
05639 }
05640 if (dots != 0) {
05641 r /= dots;
05642 g /= dots;
05643 b /= dots;
05644 }
05645
05646 col[0] = (r << 16) + (g << 8) + b;
05647 col[4] = color;
05648 Int_t col4r = (col[4] & 0xff0000) >> 16;
05649 Int_t col4g = (col[4] & 0x00ff00) >> 8;
05650 Int_t col4b = (col[4] & 0x0000ff);
05651
05652
05653 for (x = 3; x > 0; x--) {
05654 xx = 4-x;
05655 Int_t colxr = (col4r*x + r*xx) >> 2;
05656 Int_t colxg = (col4g*x + g*xx) >> 2;
05657 Int_t colxb = (col4b*x + b*xx) >> 2;
05658 col[x] = (colxr << 16) + (colxg << 8) + colxb;
05659 }
05660
05661 yy = y0;
05662 for (y = 0; y < (int) source->rows; y++) {
05663 byy = by + y;
05664 if ((byy >= (int)fImage->height) || (byy <0)) continue;
05665
05666 for (x = 0; x < (int) source->width; x++) {
05667 bxx = bx + x;
05668
05669
05670 d = *s++ & 0xff;
05671 d = ((d + 10) * 5) >> 8;
05672 if (d > 4) d = 4;
05673
05674 if (d && (x < (int) source->width) && (bxx < (int)fImage->width) && (bxx >= 0)) {
05675 idx = bxx + yy;
05676 fImage->alt.argb32[idx] = (ARGB32)col[d];
05677 }
05678 }
05679 yy += fImage->width;
05680 }
05681 }
05682
05683
05684
05685 void TASImage::DrawText(TText *text, Int_t x, Int_t y)
05686 {
05687
05688
05689 if (!text) return;
05690 if (!fImage) return;
05691 if (!gPad) return;
05692
05693 if (!InitVisual()) {
05694 Warning("DrawText", "Visual not initiated");
05695 return;
05696 }
05697
05698 if (!fImage->alt.argb32) {
05699 BeginPaint();
05700 }
05701
05702 if (!TTF::IsInitialized()) TTF::Init();
05703
05704
05705 TTF::SetTextFont(text->GetTextFont());
05706
05707 Int_t wh = gPad->XtoPixel(gPad->GetX2());
05708 Int_t hh = gPad->YtoPixel(gPad->GetY1());
05709
05710
05711 Int_t ttfsize;
05712
05713 if (wh < hh) {
05714 ttfsize = (Int_t)(text->GetTextSize()*wh);
05715 } else {
05716 ttfsize = (Int_t)(text->GetTextSize()*hh);
05717 }
05718 TTF::SetTextSize(ttfsize);
05719
05720
05721 TTF::SetRotationMatrix(text->GetTextAngle());
05722
05723
05724 TTF::PrepareString(text->GetTitle());
05725 TTF::LayoutGlyphs();
05726
05727
05728 TColor *col = gROOT->GetColor(text->GetTextColor());
05729 if (!col) {
05730 col = gROOT->GetColor(1);
05731 }
05732 ARGB32 color;
05733 parse_argb_color(col->AsHexString(), &color);
05734
05735
05736 Int_t align = 0;
05737 Int_t txalh = text->GetTextAlign()/10;
05738 Int_t txalv = text->GetTextAlign()%10;
05739
05740 switch (txalh) {
05741 case 0 :
05742 case 1 :
05743 switch (txalv) {
05744 case 1 :
05745 align = 7;
05746 break;
05747 case 2 :
05748 align = 4;
05749 break;
05750 case 3 :
05751 align = 1;
05752 break;
05753 }
05754 break;
05755 case 2 :
05756 switch (txalv) {
05757 case 1 :
05758 align = 8;
05759 break;
05760 case 2 :
05761 align = 5;
05762 break;
05763 case 3 :
05764 align = 2;
05765 break;
05766 }
05767 break;
05768 case 3 :
05769 switch (txalv) {
05770 case 1 :
05771 align = 9;
05772 break;
05773 case 2 :
05774 align = 6;
05775 break;
05776 case 3 :
05777 align = 3;
05778 break;
05779 }
05780 break;
05781 }
05782
05783 FT_Vector ftal;
05784
05785
05786 if (align == 1 || align == 2 || align == 3) {
05787 ftal.y = TTF::GetAscent();
05788 } else if (align == 4 || align == 5 || align == 6) {
05789 ftal.y = TTF::GetAscent()/2;
05790 } else {
05791 ftal.y = 0;
05792 }
05793
05794
05795 if (align == 3 || align == 6 || align == 9) {
05796 ftal.x = TTF::GetWidth();
05797 } else if (align == 2 || align == 5 || align == 8) {
05798 ftal.x = TTF::GetWidth()/2;
05799 } else {
05800 ftal.x = 0;
05801 }
05802
05803 FT_Vector_Transform(&ftal, TTF::GetRotMatrix());
05804 ftal.x = (ftal.x >> 6);
05805 ftal.y = (ftal.y >> 6);
05806
05807 TTGlyph *glyph = TTF::GetGlyphs();
05808
05809 for (int n = 0; n < TTF::GetNumGlyphs(); n++, glyph++) {
05810 if (FT_Glyph_To_Bitmap(&glyph->fImage, ft_render_mode_normal, 0, 1 )) continue;
05811
05812 FT_BitmapGlyph bitmap = (FT_BitmapGlyph)glyph->fImage;
05813 FT_Bitmap *source = &bitmap->bitmap;
05814
05815 Int_t bx = x - ftal.x + bitmap->left;
05816 Int_t by = y + ftal.y - bitmap->top;
05817
05818 DrawGlyph(source, color, bx, by);
05819 }
05820 }
05821
05822
05823
05824 void TASImage::DrawTextTTF(Int_t x, Int_t y, const char *text, Int_t size,
05825 UInt_t color, const char *font_name, Float_t angle)
05826 {
05827
05828
05829 if (!TTF::IsInitialized()) TTF::Init();
05830
05831 TTF::SetTextFont(font_name);
05832 TTF::SetTextSize(size);
05833 TTF::SetRotationMatrix(angle);
05834 TTF::PrepareString(text);
05835 TTF::LayoutGlyphs();
05836
05837 TTGlyph *glyph = TTF::GetGlyphs();
05838
05839
05840 Int_t Xoff = 0; if (TTF::GetBox().xMin < 0) Xoff = -TTF::GetBox().xMin;
05841 Int_t Yoff = 0; if (TTF::GetBox().yMin < 0) Yoff = -TTF::GetBox().yMin;
05842 Int_t h = TTF::GetBox().yMax + Yoff;
05843
05844 for (int n = 0; n < TTF::GetNumGlyphs(); n++, glyph++) {
05845 if (FT_Glyph_To_Bitmap(&glyph->fImage, ft_render_mode_normal, 0, 1 )) continue;
05846
05847 FT_BitmapGlyph bitmap = (FT_BitmapGlyph)glyph->fImage;
05848 FT_Bitmap *source = &bitmap->bitmap;
05849
05850 Int_t bx = x + bitmap->left;
05851 Int_t by = y + h - bitmap->top;
05852 DrawGlyph(source, color, bx, by);
05853 }
05854 }
05855
05856
05857
05858 void TASImage::GetImageBuffer(char **buffer, int *size, EImageFileTypes type)
05859 {
05860
05861
05862
05863
05864 static ASImageExportParams params;
05865 Bool_t ret = kFALSE;
05866 int isize = 0;
05867 char *ibuff = 0;
05868 ASImage *img = fScaledImage ? fScaledImage->fImage : fImage;
05869
05870 if (!img) return;
05871
05872 switch (type) {
05873 case TImage::kXpm:
05874 ret = ASImage2xpmRawBuff(img, (CARD8 **)buffer, size, 0);
05875 break;
05876 default:
05877 ret = ASImage2PNGBuff(img, (CARD8 **)buffer, size, ¶ms);
05878 }
05879
05880 if (!ret) {
05881 *size = isize;
05882 *buffer = ibuff;
05883 }
05884 }
05885
05886
05887
05888 Bool_t TASImage::SetImageBuffer(char **buffer, EImageFileTypes type)
05889 {
05890
05891
05892
05893
05894
05895
05896
05897
05898
05899
05900
05901
05902
05903
05904
05905
05906
05907
05908
05909
05910
05911
05912
05913
05914
05915
05916 DestroyImage();
05917
05918 static ASImageImportParams params;
05919 params.flags = 0;
05920 params.width = 0;
05921 params.height = 0 ;
05922 params.filter = SCL_DO_ALL;
05923 params.gamma = 0;
05924 params.gamma_table = 0;
05925 params.compression = 0;
05926 params.format = ASA_ASImage;
05927 params.search_path = 0;
05928 params.subimage = 0;
05929
05930 switch (type) {
05931 case TImage::kXpm:
05932 {
05933 char *ptr = buffer[0];
05934 while (isspace((int)*ptr)) ++ptr;
05935 if (atoi(ptr)) {
05936 fImage = xpm_data2ASImage((const char**)buffer, ¶ms);
05937 } else {
05938 fImage = xpmRawBuff2ASImage((const char*)*buffer, ¶ms);
05939 }
05940 break;
05941 }
05942 default:
05943 fImage = PNGBuff2ASimage((CARD8 *)*buffer, ¶ms);
05944 break;
05945 }
05946
05947 if (!fImage) {
05948 return kFALSE;
05949 }
05950
05951 if (fName.IsNull()) {
05952 fName.Form("img_%dx%d.%d", fImage->width, fImage->height, gRandom->Integer(1000));
05953 }
05954 UnZoom();
05955 return kTRUE;
05956 }
05957
05958
05959
05960 void TASImage::CreateThumbnail()
05961 {
05962
05963
05964 int size;
05965 const int sz = 64;
05966
05967 if (!fImage) {
05968 return;
05969 }
05970
05971 if (!InitVisual()) {
05972 return;
05973 }
05974
05975 static char *buf = 0;
05976 int w, h;
05977 ASImage *img = 0;
05978
05979 if (fImage->width > fImage->height) {
05980 w = sz;
05981 h = (fImage->height*sz)/fImage->width;
05982 } else {
05983 h = sz;
05984 w = (fImage->width*sz)/fImage->height;
05985 }
05986
05987 w = w < 8 ? 8 : w;
05988 h = h < 8 ? 8 : h;
05989
05990 img = scale_asimage(fgVisual, fImage, w, h, ASA_ASImage,
05991 GetImageCompression(), GetImageQuality());
05992 if (!img) {
05993 return;
05994 }
05995
05996
05997 ASImage *rendered_im;
05998 ASImageLayer layers[2];
05999 init_image_layers(&(layers[0]), 2);
06000 layers[0].im = img;
06001 layers[0].dst_x = 0;
06002 layers[0].dst_y = 0;
06003 layers[0].clip_width = img->width;
06004 layers[0].clip_height = img->height;
06005 layers[0].bevel = 0;
06006 layers[1].im = img;
06007 layers[1].dst_x = 0;
06008 layers[1].dst_y = 0;
06009 layers[1].clip_width = img->width;
06010 layers[1].clip_height = img->height;
06011 layers[1].merge_scanlines = blend_scanlines_name2func("tint");
06012 rendered_im = merge_layers(fgVisual, &(layers[0]), 2, img->width, img->height,
06013 ASA_ASImage, GetImageCompression(), GetImageQuality());
06014 destroy_asimage(&img);
06015 img = rendered_im;
06016
06017
06018 ASImage *padimg = 0;
06019 int d = 0;
06020
06021 if (w == sz) {
06022 d = (sz - h) >> 1;
06023 padimg = pad_asimage(fgVisual, img, 0, d, sz, sz, 0x00ffffff,
06024 ASA_ASImage, GetImageCompression(), GetImageQuality());
06025 } else {
06026 d = (sz - w) >> 1;
06027 padimg = pad_asimage(fgVisual, img, d, 0, sz, sz, 0x00ffffff,
06028 ASA_ASImage, GetImageCompression(), GetImageQuality());
06029 }
06030
06031 if (!padimg) {
06032 destroy_asimage(&img);
06033 return;
06034 }
06035
06036 void *ptr = &buf;
06037 ASImage2xpmRawBuff(padimg, (CARD8 **)ptr, &size, 0);
06038 fTitle = buf;
06039
06040 destroy_asimage(&padimg);
06041 }
06042
06043
06044
06045 void TASImage::Streamer(TBuffer &b)
06046 {
06047
06048
06049 Bool_t image_type = 0;
06050 char *buffer = 0;
06051 int size = 0;
06052 int w, h;
06053 UInt_t R__s, R__c;
06054
06055 if (b.IsReading()) {
06056 Version_t version = b.ReadVersion(&R__s, &R__c);
06057 if (version == 0) {
06058 return;
06059 }
06060
06061 if ( version == 1 ) {
06062 Int_t fileVersion = b.GetVersionOwner();
06063 if (fileVersion > 0 && fileVersion < 50000 ) {
06064 TImage::Streamer(b);
06065 b >> fMaxValue;
06066 b >> fMinValue;
06067 b >> fZoomOffX;
06068 b >> fZoomOffY;
06069 b >> fZoomWidth;
06070 b >> fZoomHeight;
06071 if ( fileVersion < 40200 ) {
06072 Bool_t zoomUpdate;
06073 b >> zoomUpdate;
06074 fZoomUpdate = zoomUpdate;
06075 } else {
06076 b >> fZoomUpdate;
06077 b >> fEditable;
06078 Bool_t paintMode;
06079 b >> paintMode;
06080 fPaintMode = paintMode;
06081 }
06082 b.CheckByteCount(R__s, R__c, TASImage::IsA());
06083 return;
06084 }
06085 }
06086
06087 TNamed::Streamer(b);
06088 b >> image_type;
06089
06090 if (image_type != 0) {
06091 b >> size;
06092 buffer = new char[size];
06093 b.ReadFastArray(buffer, size);
06094 SetImageBuffer(&buffer, TImage::kPng);
06095 delete [] buffer;
06096 } else {
06097 TAttImage::Streamer(b);
06098 b >> w;
06099 b >> h;
06100 size = w*h;
06101 Double_t *vec = new Double_t[size];
06102 b.ReadFastArray(vec, size);
06103 SetImage(vec, w, h, &fPalette);
06104 delete [] vec;
06105 }
06106 b.CheckByteCount(R__s, R__c, TASImage::IsA());
06107 } else {
06108 if (!fImage) {
06109 return;
06110 }
06111 R__c = b.WriteVersion(TASImage::IsA(), kTRUE);
06112
06113 if (fName.IsNull()) {
06114 fName.Form("img_%dx%d.%d", fImage->width, fImage->height, gRandom->Integer(1000));
06115 }
06116 TNamed::Streamer(b);
06117
06118 image_type = fImage->alt.vector ? 0 : 1;
06119 b << image_type;
06120
06121 if (image_type != 0) {
06122 GetImageBuffer(&buffer, &size, TImage::kPng);
06123 b << size;
06124 b.WriteFastArray(buffer, size);
06125 delete buffer;
06126 } else {
06127 TAttImage::Streamer(b);
06128 b << fImage->width;
06129 b << fImage->height;
06130 b.WriteFastArray(fImage->alt.vector, fImage->width*fImage->height);
06131 }
06132 b.SetByteCount(R__c, kTRUE);
06133 }
06134 }
06135
06136
06137
06138 void TASImage::Browse(TBrowser *)
06139 {
06140
06141
06142 if (fImage->alt.vector) {
06143 Draw("n");
06144 } else {
06145 Draw("nxxx");
06146 }
06147 CreateThumbnail();
06148 }
06149
06150
06151
06152 const char *TASImage::GetTitle() const
06153 {
06154
06155
06156 if (!gDirectory || !gDirectory->IsWritable()) {
06157 return 0;
06158 }
06159
06160 TASImage *mutble = (TASImage *)this;
06161
06162 if (fTitle.IsNull()) {
06163 mutble->SetTitle(fName.Data());
06164 }
06165
06166 return fTitle.Data();
06167 }
06168
06169
06170
06171 void TASImage::SetTitle(const char *title)
06172 {
06173
06174
06175 if (fTitle.IsNull()) {
06176 CreateThumbnail();
06177 }
06178
06179 if (fTitle.IsNull()) {
06180 return;
06181 }
06182
06183 int start = fTitle.Index("/*") + 3;
06184 int stop = fTitle.Index("*/") - 1;
06185
06186 if ((start > 0) && (stop - start > 0)) {
06187 fTitle.Replace(start, stop - start, title);
06188 }
06189 }
06190
06191
06192
06193 void TASImage::DrawCubeBezier(Int_t x1, Int_t y1, Int_t x2, Int_t y2,
06194 Int_t x3, Int_t y3, const char *col, UInt_t thick)
06195 {
06196
06197
06198 Int_t sz = thick*thick;
06199 CARD32 *matrix;
06200 Bool_t use_cache = thick < kBrushCacheSize;
06201
06202 ARGB32 color;
06203 parse_argb_color(col, &color);
06204
06205 if (use_cache) {
06206 matrix = gBrushCache;
06207 } else {
06208 matrix = new CARD32[sz];
06209 }
06210
06211 for (int i = 0; i < sz; i++) {
06212 matrix[i] = (CARD32)color;
06213 };
06214
06215 ASDrawTool brush;
06216 brush.matrix = matrix;
06217 brush.width = thick;
06218 brush.height = thick;
06219 brush.center_y = brush.center_x = thick/2;
06220
06221 ASDrawContext *ctx = 0;
06222
06223 ctx = create_draw_context_argb32(fImage, &brush);
06224 asim_cube_bezier(ctx, x1, y1, x2, y2, x3, y3);
06225
06226 if (!use_cache) {
06227 delete [] matrix;
06228 }
06229 destroy_asdraw_context32(ctx);
06230 }
06231
06232
06233
06234 void TASImage::DrawStraightEllips(Int_t x, Int_t y, Int_t rx, Int_t ry,
06235 const char *col, Int_t thick)
06236 {
06237
06238
06239
06240 thick = !thick ? 1 : thick;
06241 Int_t sz = thick*thick;
06242 CARD32 *matrix;
06243 Bool_t use_cache = (thick > 0) && ((UInt_t)thick < kBrushCacheSize);
06244
06245 ARGB32 color;
06246 parse_argb_color(col, &color);
06247
06248 if (use_cache) {
06249 matrix = gBrushCache;
06250 } else {
06251 matrix = new CARD32[sz];
06252 }
06253
06254 for (int i = 0; i < sz; i++) {
06255 matrix[i] = (CARD32)color;
06256 };
06257
06258 ASDrawTool brush;
06259 brush.matrix = matrix;
06260 brush.width = thick > 0 ? thick : 1;
06261 brush.height = thick > 0 ? thick : 1;
06262 brush.center_y = brush.center_x = thick > 0 ? thick/2 : 0;
06263
06264 ASDrawContext *ctx = create_draw_context_argb32(fImage, &brush);
06265 asim_straight_ellips(ctx, x, y, rx, ry, thick < 0);
06266
06267 if (!use_cache) {
06268 delete [] matrix;
06269 }
06270 destroy_asdraw_context32(ctx);
06271 }
06272
06273
06274
06275 void TASImage::DrawCircle(Int_t x, Int_t y, Int_t r, const char *col, Int_t thick)
06276 {
06277
06278
06279
06280 thick = !thick ? 1 : thick;
06281 Int_t sz = thick*thick;
06282 CARD32 *matrix;
06283 Bool_t use_cache = (thick > 0) && ((UInt_t)thick < kBrushCacheSize);
06284
06285 ARGB32 color;
06286 parse_argb_color(col, &color);
06287
06288
06289 if (use_cache) {
06290 matrix = gBrushCache;
06291 } else {
06292 matrix = new CARD32[sz];
06293 }
06294
06295 for (int i = 0; i < sz; i++) {
06296 matrix[i] = (CARD32)color;
06297 }
06298
06299 ASDrawTool brush;
06300 brush.matrix = matrix;
06301 brush.height = brush.width = thick > 0 ? thick : 1;
06302 brush.center_y = brush.center_x = thick > 0 ? thick/2 : 0;
06303
06304 ASDrawContext *ctx = create_draw_context_argb32(fImage, &brush);
06305 asim_circle(ctx, x, y, r, thick < 0);
06306
06307
06308 if (!use_cache) {
06309 delete [] matrix;
06310 }
06311 destroy_asdraw_context32(ctx);
06312 }
06313
06314
06315
06316 void TASImage::DrawEllips(Int_t x, Int_t y, Int_t rx, Int_t ry, Int_t angle,
06317 const char *col, Int_t thick)
06318 {
06319
06320
06321
06322 thick = !thick ? 1 : thick;
06323 Int_t sz = thick*thick;
06324 CARD32 *matrix;
06325 Bool_t use_cache = (thick > 0) && ((UInt_t)thick < kBrushCacheSize);
06326
06327 ARGB32 color;
06328 parse_argb_color(col, &color);
06329
06330 if (use_cache) {
06331 matrix = gBrushCache;
06332 } else {
06333 matrix = new CARD32[sz];
06334 }
06335
06336 for (int i = 0; i < sz; i++) {
06337 matrix[i] = (CARD32)color;
06338 };
06339
06340 ASDrawTool brush;
06341 brush.matrix = matrix;
06342 brush.width = thick > 0 ? thick : 1;
06343 brush.height = thick > 0 ? thick : 1;
06344 brush.center_y = brush.center_x = thick > 0 ? thick/2 : 0;
06345
06346 ASDrawContext *ctx = create_draw_context_argb32(fImage, &brush);
06347 asim_ellips(ctx, x, y, rx, ry, angle, thick < 0);
06348
06349 if (!use_cache) {
06350 delete [] matrix;
06351 }
06352 destroy_asdraw_context32(ctx);
06353 }
06354
06355
06356
06357 void TASImage::DrawEllips2(Int_t x, Int_t y, Int_t rx, Int_t ry, Int_t angle,
06358 const char *col, Int_t thick)
06359 {
06360
06361
06362
06363 thick = !thick ? 1 : thick;
06364 Int_t sz = thick*thick;
06365 CARD32 *matrix;
06366 Bool_t use_cache = (thick > 0) && ((UInt_t)thick < kBrushCacheSize);
06367
06368 ARGB32 color;
06369 parse_argb_color(col, &color);
06370
06371 if (use_cache) {
06372 matrix = gBrushCache;
06373 } else {
06374 matrix = new CARD32[sz];
06375 }
06376
06377 for (int i = 0; i < sz; i++) {
06378 matrix[i] = (CARD32)color;
06379 };
06380
06381 ASDrawTool brush;
06382 brush.matrix = matrix;
06383 brush.width = thick > 0 ? thick : 1;
06384 brush.height = thick > 0 ? thick : 1;
06385 brush.center_y = brush.center_x = thick > 0 ? thick/2 : 0;
06386
06387 ASDrawContext *ctx = create_draw_context_argb32(fImage, &brush);
06388 asim_ellips2(ctx, x, y, rx, ry, angle, thick < 0);
06389
06390 if (!use_cache) {
06391 delete [] matrix;
06392 }
06393 destroy_asdraw_context32(ctx);
06394 }
06395
06396
06397
06398 void TASImage::FloodFill(Int_t , Int_t , const char * ,
06399 const char * , const char * )
06400 {
06401
06402 }
06403
06404
06405
06406 void TASImage::Gray(Bool_t on)
06407 {
06408
06409
06410 if (fIsGray == on) {
06411 return;
06412 }
06413
06414 if (!IsValid()) {
06415 Warning("Gray", "Image not initiated");
06416 return;
06417 }
06418
06419 if (!InitVisual()) {
06420 Warning("Gray", "Visual not initiated");
06421 return;
06422 }
06423
06424 if (!fGrayImage && !on) {
06425 return;
06426 }
06427 ASImage *sav = 0;
06428 delete fScaledImage;
06429 fScaledImage = 0;
06430
06431 if (fGrayImage) {
06432 sav = fImage;
06433 fImage = fGrayImage;
06434 fGrayImage = sav;
06435 fIsGray = on;
06436 return;
06437 }
06438
06439 if (!on) return;
06440
06441 UInt_t l, r, g, b, idx;
06442 int y = 0;
06443 UInt_t i, j;
06444
06445 if (fImage->alt.argb32) {
06446 fGrayImage = tile_asimage(fgVisual, fImage, 0, 0, fImage->width, fImage->height,
06447 0, ASA_ARGB32, 0, ASIMAGE_QUALITY_DEFAULT);
06448
06449 for (i = 0; i < fImage->height; i++) {
06450 for (j = 0; j < fImage->width; j++) {
06451 idx = y + j;
06452
06453 r = ((fImage->alt.argb32[idx] & 0xff0000) >> 16);
06454 g = ((fImage->alt.argb32[idx] & 0x00ff00) >> 8);
06455 b = (fImage->alt.argb32[idx] & 0x0000ff);
06456 l = (57*r + 181*g + 18*b)/256;
06457 fGrayImage->alt.argb32[idx] = (l << 16) + (l << 8) + l;
06458 }
06459 y += fImage->width;
06460 }
06461 } else {
06462 fGrayImage = create_asimage(fImage->width, fImage->height, 0);
06463
06464 ASImageDecoder *imdec = start_image_decoding(fgVisual, fImage, SCL_DO_ALL,
06465 0, 0, fImage->width, fImage->height, 0);
06466
06467 if (!imdec) {
06468 return;
06469 }
06470 #ifdef HAVE_MMX
06471 mmx_init();
06472 #endif
06473 ASImageOutput *imout = start_image_output(fgVisual, fGrayImage, ASA_ASImage,
06474 GetImageCompression(), GetImageQuality());
06475 if (!imout) {
06476 Warning("ToGray", "Failed to start image output");
06477 delete fScaledImage;
06478 fScaledImage = 0;
06479 delete [] imdec;
06480 return;
06481 }
06482
06483 CARD32 *aa = imdec->buffer.alpha;
06484 CARD32 *rr = imdec->buffer.red;
06485 CARD32 *gg = imdec->buffer.green;
06486 CARD32 *bb = imdec->buffer.blue;
06487
06488 ASScanline result;
06489 ASScanline *sl = prepare_scanline(fImage->width, 0, &result, fgVisual->BGR_mode);
06490 if (sl) delete sl;
06491
06492 for (i = 0; i < fImage->height; i++) {
06493 imdec->decode_image_scanline(imdec);
06494 result.flags = imdec->buffer.flags;
06495 result.back_color = imdec->buffer.back_color;
06496
06497 for (j = 0; j < fImage->width; j++) {
06498 l = (57*rr[j] + 181*gg[j]+ 18*bb[j])/256;
06499 result.alpha[j] = aa[j];
06500 result.red[j] = l;
06501 result.green[j] = l;
06502 result.blue[j] = l;
06503 }
06504 imout->output_image_scanline(imout, &result, 1);
06505 }
06506
06507 stop_image_decoding(&imdec);
06508 stop_image_output(&imout);
06509 #ifdef HAVE_MMX
06510 mmx_off();
06511 #endif
06512 }
06513
06514 sav = fImage;
06515 fImage = fGrayImage;
06516 fGrayImage = sav;
06517 fIsGray = kTRUE;
06518 }
06519
06520
06521
06522 void TASImage::FromWindow(Drawable_t wid, Int_t x, Int_t y, UInt_t w, UInt_t h)
06523 {
06524
06525
06526 Int_t xy;
06527
06528 x = x < 0 ? 0 : x;
06529 y = y < 0 ? 0 : y;
06530
06531
06532 gVirtualX->Update(1);
06533 if (!gThreadXAR) {
06534 gSystem->ProcessEvents();
06535 gSystem->Sleep(10);
06536 gSystem->ProcessEvents();
06537 }
06538
06539 if (!w || !h) {
06540 gVirtualX->GetWindowSize(wid, xy, xy, w, h);
06541 }
06542
06543 if ((x >= (Int_t)w) || (y >= (Int_t)h)) {
06544 return;
06545 }
06546
06547 if (!InitVisual()) {
06548 Warning("FromWindow", "Visual not initiated");
06549 return;
06550 }
06551
06552 DestroyImage();
06553 delete fScaledImage;
06554 fScaledImage = 0;
06555
06556 static int x11 = -1;
06557 if (x11 < 0) x11 = gVirtualX->InheritsFrom("TGX11");
06558
06559 if (x11) {
06560 fImage = pixmap2asimage(fgVisual, wid, x, y, w, h, kAllPlanes, 0, 0);
06561 } else {
06562 unsigned char *bits = gVirtualX->GetColorBits(wid, 0, 0, w, h);
06563
06564 if (!bits) {
06565 return;
06566 }
06567 fImage = bitmap2asimage(bits, w, h, 0, 0);
06568 delete [] bits;
06569 }
06570 }
06571
06572
06573
06574 void TASImage::FromGLBuffer(UChar_t* buf, UInt_t w, UInt_t h)
06575 {
06576
06577
06578 DestroyImage();
06579 delete fScaledImage;
06580 fScaledImage = 0;
06581
06582 UChar_t* xx = new UChar_t[4*w];
06583 for (UInt_t i = 0; i < h/2; ++i) {
06584 memcpy(xx, buf + 4*w*i, 4*w);
06585 memcpy(buf + 4*w*i, buf + 4*w*(h-i-1), 4*w);
06586 memcpy(buf + 4*w*(h-i-1), xx, 4*w);
06587 }
06588 delete [] xx;
06589
06590 fImage = bitmap2asimage(buf, w, h, 0, 0);
06591 }
06592
06593
06594
06595 void TASImage::SetPaletteEnabled(Bool_t on)
06596 {
06597
06598
06599
06600 if (!fImage) {
06601 return;
06602 }
06603
06604 if (!fImage->alt.vector && on) {
06605 Vectorize();
06606 }
06607 fPaletteEnabled = on;
06608
06609 if (on) {
06610 Double_t left = gPad->GetLeftMargin();
06611 Double_t right = gPad->GetRightMargin();
06612 Double_t top = gPad->GetTopMargin();
06613 Double_t bottom = gPad->GetBottomMargin();
06614
06615 gPad->Range(-left / (1.0 - left - right),
06616 -bottom / (1.0 - top - bottom),
06617 1 + right / (1.0 - left - right),
06618 1 + top / ( 1.0 - top - bottom));
06619 gPad->RangeAxis(0, 0, 1, 1);
06620 }
06621
06622 }
06623
06624
06625
06626 void TASImage::SavePrimitive(ostream &out, Option_t * )
06627 {
06628
06629
06630 char *buf;
06631 int sz;
06632
06633 UInt_t w = GetWidth();
06634 UInt_t h = GetHeight();
06635
06636 if (w > 500) {
06637 w = 500;
06638 Double_t scale = 500./GetWidth();
06639 h = TMath::Nint(GetHeight()*scale);
06640 Scale(w, h);
06641 }
06642
06643 GetImageBuffer(&buf, &sz, TImage::kXpm);
06644
06645 TString name = GetName();
06646 name.ReplaceAll(".", "_");
06647 TString str = buf;
06648 static int ii = 0;
06649 ii++;
06650
06651 str.ReplaceAll("static", "");
06652 TString xpm = "xpm_";
06653 xpm += name;
06654 xpm += ii;
06655 str.ReplaceAll("asxpm", xpm.Data());
06656 out << endl << str << endl << endl;
06657 out << " TImage *";
06658 out << name << " = TImage::Create();" << endl;
06659 out << " " << name << "->SetImageBuffer(" << xpm << ", TImage::kXpm);" << endl;
06660 out << " " << name << "->Draw();" << endl;
06661 }
06662
06663
06664
06665 Bool_t TASImage::SetJpegDpi(const char *name, UInt_t set)
06666 {
06667
06668
06669
06670
06671
06672 static char buf[32];
06673 FILE *fp = fopen(name, "rb+");
06674
06675 if (!fp) {
06676 printf("file %s : failed to open\n", name);
06677 return kFALSE;
06678 }
06679
06680 if (!fread(buf, 1, 20, fp)) {
06681 fclose(fp);
06682 return kFALSE;
06683 }
06684
06685 char dpi1 = (set & 0xffff) >> 8;
06686 char dpi2 = set & 0xff;
06687
06688 int i = 0;
06689
06690 int dpi = 0;
06691 for (i = 0; i < 20; i++) {
06692 if ((buf[i] == 0x4a) && (buf[i+1] == 0x46) && (buf[i+2] == 0x49) &&
06693 (buf[i+3] == 0x46) && (buf[i+4] == 0x00) ) {
06694 dpi = i + 7;
06695 break;
06696 }
06697 }
06698
06699 if (i == 20 || dpi+4 >= 20) {
06700 fclose(fp);
06701 printf("file %s : wrong JPEG format\n", name);
06702 return kFALSE;
06703 }
06704
06705 buf[dpi] = 1;
06706
06707
06708 buf[dpi + 1] = dpi1;
06709 buf[dpi + 2] = dpi2;
06710
06711
06712 buf[dpi + 3] = dpi1;
06713 buf[dpi + 4] = dpi2;
06714
06715 rewind(fp);
06716 fwrite(buf, 1, 20, fp);
06717 fclose(fp);
06718
06719 return kTRUE;
06720 }