60 # include <ft2build.h>
61 # include FT_FREETYPE_H
87 #include "RConfigure.h"
92 # include <X11/Xlib.h>
95 # include "Windows4root.h"
99 # define X_DISPLAY_MISSING 1
101 # include <afterbase.h>
103 # include <win32/config.h>
104 # include <win32/afterbase.h>
105 # define X_DISPLAY_MISSING 1
107 # include <afterimage.h>
117 ASVisual *TASImage::fgVisual = 0;
118 Bool_t TASImage::fgInit = kFALSE;
120 static ASFontManager *gFontManager = 0;
121 static unsigned long kAllPlanes = ~0;
122 THashTable *TASImage::fgPlugList =
new THashTable(50);
125 static char *gIconPaths[7] = {0, 0, 0, 0, 0, 0, 0};
128 const Float_t kScale = 0.985;
132 #if defined(__GNUC__) && __GNUC__ >= 4 && ((__GNUC_MINOR__ == 2 && __GNUC_PATCHLEVEL__ >= 1) || (__GNUC_MINOR__ >= 3)) && !__INTEL_COMPILER
133 #pragma GCC diagnostic ignored "-Wstrict-aliasing"
154 #define _alphaBlend(bot, top) {\
155 __argb32__ *T = (__argb32__*)(top);\
156 __argb32__ *B = (__argb32__*)(bot);\
161 B->a = ((B->a*aa)>>8) + T->a;\
162 B->r = (B->r*aa + T->r*T->a)>>8;\
163 B->g = (B->g*aa + T->g*T->a)>>8;\
164 B->b = (B->b*aa + T->b*T->a)>>8;\
170 ClassImp(TASImagePlugin);
175 void TASImage::DestroyImage()
178 destroy_asimage(&fImage);
181 if (fIsGray && fGrayImage) {
182 destroy_asimage(&fGrayImage);
193 void TASImage::SetDefaults()
205 fZoomUpdate = kZoomOps;
209 fPaletteEnabled = kFALSE;
212 set_application_name((
char*)(gProgName ? gProgName :
"ROOT"));
228 TASImage::TASImage(UInt_t w, UInt_t h) : TImage(w, h)
231 fImage = create_asimage(w ? w : 20, h ? h : 20, 0);
240 TASImage::TASImage(
const char *file, EImageFileTypes) : TImage(file)
243 TString fname = file;
244 gSystem->ExpandPathName(fname);
245 ReadImage(fname.Data());
253 TASImage::TASImage(
const char *name,
const Double_t *imageData, UInt_t width,
254 UInt_t height, TImagePalette *palette) : TImage(name)
257 SetImage(imageData, width, height, palette);
266 TASImage::TASImage(
const char *name,
const TArrayD &imageData, UInt_t width,
267 TImagePalette *palette) : TImage(name)
270 SetImage(imageData, width, palette);
279 TASImage::TASImage(
const char *name,
const TVectorD &imageData, UInt_t width,
280 TImagePalette *palette) : TImage(name)
283 SetImage(imageData, width, palette);
289 TASImage::TASImage(
const TASImage &img) : TImage(img)
294 fImage = clone_asimage(img.fImage, SCL_DO_ALL);
295 fScaledImage = fScaledImage ? (TASImage*)img.fScaledImage->Clone(
"") : 0;
296 fGrayImage = fGrayImage ? clone_asimage(img.fGrayImage, SCL_DO_ALL) : 0;
298 if (img.fImage->alt.vector) {
299 Int_t size = img.fImage->width * img.fImage->height *
sizeof(double);
300 fImage->alt.vector = (
double*)malloc(size);
301 memcpy(fImage->alt.vector, img.fImage->alt.vector, size);
304 fZoomUpdate = kNoZoom;
305 fZoomOffX = img.fZoomOffX;
306 fZoomOffY = img.fZoomOffY;
307 fZoomWidth = img.fZoomWidth;
308 fZoomHeight = img.fZoomHeight;
309 fEditable = img.fEditable;
310 fIsGray = img.fIsGray;
317 TASImage &TASImage::operator=(
const TASImage &img)
319 if (
this != &img && img.IsValid()) {
320 TImage::operator=(img);
324 fImage = clone_asimage(img.fImage, SCL_DO_ALL);
325 fScaledImage = fScaledImage ? (TASImage*)img.fScaledImage->Clone(
"") : 0;
326 fGrayImage = fGrayImage ? clone_asimage(img.fGrayImage, SCL_DO_ALL) : 0;
328 if (img.fImage->alt.vector) {
329 Int_t size = img.fImage->width * img.fImage->height *
sizeof(double);
330 fImage->alt.vector = (
double*)malloc(size);
331 memcpy(fImage->alt.vector, img.fImage->alt.vector, size);
334 fScaledImage = img.fScaledImage ? (TASImage*)img.fScaledImage->Clone(
"") : 0;
335 fZoomUpdate = kNoZoom;
336 fZoomOffX = img.fZoomOffX;
337 fZoomOffY = img.fZoomOffY;
338 fZoomWidth = img.fZoomWidth;
339 fZoomHeight = img.fZoomHeight;
340 fEditable = img.fEditable;
341 fIsGray = img.fIsGray;
351 TASImage::~TASImage()
361 static void init_icon_paths()
363 TString icon_path = gEnv->GetValue(
"Gui.IconPath",
"");
364 if (icon_path.IsNull()) {
366 gSystem->PrependPathName(gSystem->HomeDirectory(), icon_path);
368 icon_path =
".:" + icon_path +
":" + TROOT::GetIconPath() +
":" + EXTRAICONPATH;
370 icon_path =
".;" + icon_path +
";" + TROOT::GetIconPath() +
";" + EXTRAICONPATH;
378 const char *delim =
":";
380 const char *delim =
";";
382 while (icon_path.Tokenize(token, from, delim) && cnt < 6) {
383 char *path = gSystem->ExpandPathName(token.Data());
385 gIconPaths[cnt] = path;
395 const char *TASImage::TypeFromMagicNumber(
const char *file)
398 FILE *fp = fopen(file,
"rb");
399 const char *ret =
"";
403 if (!fread(&magic, 1, 1, fp)) {
411 if (!fread(&magic, 1, 1, fp)) {
415 if (!fread(&magic, 1, 1, fp)) {
420 ret = (magic == 1) ?
"ico" :
"cur";
425 if (!fread(&magic, 1, 1, fp)) {
430 if (magic == 0x21) ret =
"ps";
431 else if (magic == 0x50) ret =
"pdf";
478 void TASImage::ReadImage(
const char *filename, EImageFileTypes )
481 Warning(
"Scale",
"Visual not initiated");
485 Bool_t xpm = filename && (filename[0] ==
'/' &&
486 filename[1] ==
'*') && filename[2] ==
' ';
489 SetImageBuffer((
char**)&filename, TImage::kXpm);
494 if (!gIconPaths[0]) {
498 set_output_threshold(0);
500 static ASImageImportParams iparams;
504 iparams.filter = SCL_DO_ALL;
505 iparams.gamma = SCREEN_GAMMA;
506 iparams.gamma_table = NULL;
507 iparams.compression = GetImageCompression();
508 iparams.format = ASA_ASImage;
509 iparams.search_path = gIconPaths;
510 iparams.subimage = 0;
511 iparams.return_animation_delay = -1;
515 if (filename) dot = strrchr(filename,
'.');
518 TString fname = filename;
521 if (filename) ext = TypeFromMagicNumber(filename);
527 if (!ext.IsNull() && ext.IsDigit()) {
528 iparams.subimage = ext.Atoi();
529 fname = fname(0, fname.Length() - ext.Length() - 1);
530 ext = strrchr(fname.Data(),
'.') + 1;
533 image = file2ASImage_extra(fname.Data(), &iparams);
545 unsigned char *bitmap = 0;
547 TImagePlugin *plug = (TImagePlugin*)fgPlugList->FindObject(ext.Data());
550 TPluginHandler *handler = gROOT->GetPluginManager()->FindHandler(
"TImagePlugin", ext);
551 if (!handler || ((handler->LoadPlugin() == -1))) {
554 plug = (TImagePlugin*)handler->ExecPlugin(1, ext.Data());
560 fgPlugList->Add(plug);
564 if (plug->InheritsFrom(TASImagePlugin::Class())) {
565 image = ((TASImagePlugin*)plug)->File2ASImage(fname.Data());
568 bitmap = plug->ReadFile(fname.Data(), w, h);
570 image = bitmap2asimage(bitmap, w, h, 0, 0);
579 fName.Form(
"%s.", gSystem->BaseName(fname.Data()));
586 fZoomUpdate = kNoZoom;
590 fZoomWidth = fImage->width;
591 fZoomHeight = fImage->height;
647 void TASImage::WriteImage(
const char *file, EImageFileTypes type)
650 Error(
"WriteImage",
"no image loaded");
654 if (!file || !*file) {
655 Error(
"WriteImage",
"no file name specified");
660 if ((s = strrchr(file,
'.'))) {
662 EImageFileTypes t = GetFileType(s);
664 Error(
"WriteImage",
"cannot determine a valid file type");
671 if (type == kUnknown) {
672 Error(
"WriteImage",
"not a valid file type was specified");
677 MapFileTypes(type, mytype);
678 ASImageFileTypes atype = (ASImageFileTypes)mytype;
681 EImageQuality quality = GetImageQuality();
682 MapQuality(quality, aquality);
684 static TString fname;
686 static ASImageExportParams parms;
687 ASImage *im = fScaledImage ? fScaledImage->fImage : fImage;
691 parms.xpm.type = atype;
692 parms.xpm.flags = EXPORT_ALPHA;
693 parms.xpm.dither = 4;
694 parms.xpm.opaque_threshold = 127;
695 parms.xpm.max_colors = 512;
698 ASImage2bmp(im, fname.Data(), 0);
701 ASImage2xcf(im, fname.Data(), 0);
704 parms.png.type = atype;
705 parms.png.flags = EXPORT_ALPHA;
706 parms.png.compression = !GetImageCompression() ? -1 : int(GetImageCompression());
709 parms.jpeg.type = atype;
710 parms.jpeg.flags = 0;
711 parms.jpeg.quality = aquality;
714 parms.gif.type = atype;
715 parms.gif.flags = EXPORT_ALPHA;
716 parms.gif.dither = 0;
717 parms.gif.opaque_threshold = 0;
721 parms.gif.type = atype;
722 parms.gif.flags = EXPORT_ALPHA | EXPORT_APPEND;
723 parms.gif.dither = 0;
724 parms.gif.opaque_threshold = 0;
725 parms.gif.animate_repeats = 0;
730 const TString sufix = s;
731 const UInt_t sLength = sufix.Length();
738 parms.gif.flags |= EXPORT_ANIMATION_REPEATS;
739 parms.gif.animate_repeats = 0;
740 }
else if(sufix==
"") {
746 }
else if(!sufix.Contains(
"+")) {
752 }
else if(sLength>1 && sufix.BeginsWith(
"+") && sufix.CountChar(
'+')==1) {
757 parms.gif.flags |= EXPORT_ANIMATION_REPEATS;
758 parms.gif.animate_repeats = atoi(s);
759 }
else if(sLength>3 && sufix.BeginsWith(
"+") && sufix.EndsWith(
"++") && !TString(sufix(1,sLength-3)).Contains(
"+")) {
767 parms.gif.flags |= EXPORT_ANIMATION_REPEATS;
768 parms.gif.animate_repeats = 0;
769 }
else if(sLength>3 && sufix.CountChar(
'+')==2 && TString(sufix(1,sLength-2)).Contains(
"++")) {
773 const TString sDelay = sufix(0,sufix.First(
'+'));
774 const TString sRepeats = sufix(sufix.First(
'+')+2,sLength-(sufix.First(
'+')+2));
775 delay = atoi(sDelay);
776 parms.gif.flags |= EXPORT_ANIMATION_REPEATS;
777 parms.gif.animate_repeats = atoi(sRepeats);
779 Error(
"WriteImage",
"gif suffix %s not yet supported", s);
783 parms.gif.animate_delay = delay;
785 int i1 = fname.Index(
"gif+");
787 fname = fname(0, i1 + 3);
790 Error(
"WriteImage",
"unexpected gif extension structure %s", fname.Data());
796 parms.tiff.type = atype;
797 parms.tiff.flags = EXPORT_ALPHA;
798 parms.tiff.rows_per_strip = 0;
799 parms.tiff.compression_type = aquality <= 50 ? TIFF_COMPRESSION_JPEG :
800 TIFF_COMPRESSION_NONE;
801 parms.tiff.jpeg_quality = 100;
802 parms.tiff.opaque_threshold = 0;
805 Error(
"WriteImage",
"file type %s not yet supported", s);
809 if (!ASImage2file(im, 0, fname.Data(), atype, &parms)) {
810 Error(
"WriteImage",
"error writing file %s", file);
818 TImage::EImageFileTypes TASImage::GetFileType(
const char *ext)
828 if (s ==
"jpg" || s ==
"jpeg")
844 if (s.Contains(
"gif+"))
862 void TASImage::MapFileTypes(EImageFileTypes &type, UInt_t &astype, Bool_t toas)
867 astype = ASIT_Xpm;
break;
868 case kZCompressedXpm:
869 astype = ASIT_ZCompressedXpm;
break;
870 case kGZCompressedXpm:
871 astype = ASIT_GZCompressedXpm;
break;
873 astype = ASIT_Png;
break;
875 astype = ASIT_Jpeg;
break;
877 astype = ASIT_Xcf;
break;
879 astype = ASIT_Ppm;
break;
881 astype = ASIT_Pnm;
break;
883 astype = ASIT_Bmp;
break;
885 astype = ASIT_Ico;
break;
887 astype = ASIT_Cur;
break;
889 astype = ASIT_Gif;
break;
891 astype = ASIT_Gif;
break;
893 astype = ASIT_Tiff;
break;
895 astype = ASIT_Xbm;
break;
897 astype = ASIT_Targa;
break;
899 astype = ASIT_XMLScript;
break;
901 astype = ASIT_Unknown;
907 case ASIT_ZCompressedXpm:
908 type = kZCompressedXpm;
break;
909 case ASIT_GZCompressedXpm:
910 type = kGZCompressedXpm;
break;
947 void TASImage::MapQuality(EImageQuality &quality, UInt_t &asquality, Bool_t toas)
952 asquality = 25;
break;
954 asquality = 75;
break;
956 asquality = 50;
break;
958 asquality = 100;
break;
963 quality = kImgDefault;
964 if (asquality > 0 && asquality <= 25)
966 if (asquality > 26 && asquality <= 50)
968 if (asquality > 51 && asquality <= 75)
970 if (asquality > 76 && asquality <= 100)
984 void TASImage::SetImage(
const Double_t *imageData, UInt_t width, UInt_t height,
985 TImagePalette *palette)
987 TAttImage::SetPalette(palette);
990 Warning(
"SetImage",
"Visual not initiated");
999 fMinValue = fMaxValue = *imageData;
1000 for (Int_t pixel = 1; pixel < Int_t(width * height); pixel++) {
1001 if (fMinValue > *(imageData + pixel)) fMinValue = *(imageData + pixel);
1002 if (fMaxValue < *(imageData + pixel)) fMaxValue = *(imageData + pixel);
1006 const TImagePalette &pal = GetPalette();
1008 ASVectorPalette asPalette;
1010 asPalette.npoints = pal.fNumPoints;
1012 for (col = 0; col < 4; col++)
1013 asPalette.channels[col] =
new UShort_t[asPalette.npoints];
1015 memcpy(asPalette.channels[0], pal.fColorBlue, pal.fNumPoints *
sizeof(UShort_t));
1016 memcpy(asPalette.channels[1], pal.fColorGreen, pal.fNumPoints *
sizeof(UShort_t));
1017 memcpy(asPalette.channels[2], pal.fColorRed, pal.fNumPoints *
sizeof(UShort_t));
1018 memcpy(asPalette.channels[3], pal.fColorAlpha, pal.fNumPoints *
sizeof(UShort_t));
1020 asPalette.points =
new Double_t[asPalette.npoints];
1021 for (Int_t point = 0; point < Int_t(asPalette.npoints); point++)
1022 asPalette.points[point] = fMinValue + (fMaxValue - fMinValue) * pal.fPoints[point];
1024 fImage = create_asimage_from_vector(fgVisual, (Double_t*)imageData, width,
1025 height, &asPalette, ASA_ASImage,
1026 GetImageCompression(), GetImageQuality());
1028 delete [] asPalette.points;
1029 for (col = 0; col < 4; col++)
1030 delete [] asPalette.channels[col];
1036 fZoomHeight = height;
1037 fPaletteEnabled = kTRUE;
1048 void TASImage::SetImage(
const TArrayD &imageData, UInt_t width, TImagePalette *palette)
1050 SetImage(imageData.GetArray(), width, imageData.GetSize() / width, palette);
1061 void TASImage::SetImage(
const TVectorD &imageData, UInt_t width, TImagePalette *palette)
1063 SetImage(imageData.GetMatrixArray(), width,
1064 imageData.GetNoElements() / width, palette);
1071 void TASImage::FromPad(TVirtualPad *pad, Int_t x, Int_t y, UInt_t w, UInt_t h)
1074 Error(
"FromPad",
"pad cannot be 0");
1078 if (!InitVisual()) {
1079 Warning(
"FromPad",
"Visual not initiated");
1083 SetName(pad->GetName());
1086 delete fScaledImage;
1089 if (gROOT->IsBatch()) {
1090 TVirtualPS *psave = gVirtualPS;
1091 gVirtualPS = (TVirtualPS*)gROOT->ProcessLineFast(
"new TImageDump()");
1092 gVirtualPS->Open(pad->GetName(), 114);
1093 gVirtualPS->SetBit(BIT(11));
1095 TASImage *itmp = (TASImage*)gVirtualPS->GetStream();
1097 if (itmp && itmp->fImage) {
1101 TVirtualPad *sav = gPad;
1106 if (itmp && itmp->fImage && (itmp !=
this)) {
1107 fImage = clone_asimage(itmp->fImage, SCL_DO_ALL);
1108 if (itmp->fImage->alt.argb32) {
1109 UInt_t sz = itmp->fImage->width*itmp->fImage->height;
1110 fImage->alt.argb32 = (ARGB32*)safemalloc(sz*
sizeof(ARGB32));
1111 memcpy(fImage->alt.argb32, itmp->fImage->alt.argb32, sz*4);
1120 gVirtualX->Update(1);
1122 gSystem->Sleep(100);
1123 gSystem->ProcessEvents();
1125 gSystem->ProcessEvents();
1128 TVirtualPad *canvas = (TVirtualPad*)pad->GetCanvas();
1129 Int_t wid = (pad == canvas) ? pad->GetCanvasID() : pad->GetPixmapID();
1130 gVirtualX->SelectWindow(wid);
1132 Window_t wd = (Window_t)gVirtualX->GetCurrentWindow();
1135 if (w == 0) w = TMath::Abs(pad->UtoPixel(1.));
1136 if (h == 0) h = pad->VtoPixel(0.);
1138 static int x11 = -1;
1139 if (x11 < 0) x11 = gVirtualX->InheritsFrom(
"TGX11");
1142 fImage = pixmap2asimage(fgVisual, wd, x, y, w, h, kAllPlanes, 0, 0);
1144 unsigned char *bits = gVirtualX->GetColorBits(wd, 0, 0, w, h);
1149 fImage = bitmap2asimage(bits, w, h, 0, 0);
1167 void TASImage::Draw(Option_t *option)
1170 Error(
"Draw",
"no image set");
1174 TString opt = option;
1176 if (opt.Contains(
"n") || !gPad || !gPad->IsEditable()) {
1179 w = (fImage->width > 64) ? (Int_t)fImage->width : w;
1180 h = (fImage->height > 64) ? (Int_t)fImage->height : h;
1182 Float_t cx = 1./gStyle->GetScreenFactor();
1183 w = Int_t(w*cx) + 4;
1184 h = Int_t(h*cx) + 28;
1185 TString rname = GetName();
1186 rname.ReplaceAll(
".",
"");
1187 rname += Form(
"\", \"%s (%d x %d)", rname.Data(), fImage->width, fImage->height);
1188 rname =
"new TCanvas(\"" + rname + Form(
"\", %d, %d);", w, h);
1189 gROOT->ProcessLineFast(rname.Data());
1192 if (!opt.Contains(
"x")) {
1193 Double_t left = gPad->GetLeftMargin();
1194 Double_t right = gPad->GetRightMargin();
1195 Double_t top = gPad->GetTopMargin();
1196 Double_t bottom = gPad->GetBottomMargin();
1198 gPad->Range(-left / (1.0 - left - right),
1199 -bottom / (1.0 - top - bottom),
1200 1 + right / (1.0 - left - right),
1201 1 + top / ( 1.0 - top - bottom));
1202 gPad->RangeAxis(0, 0, 1, 1);
1205 TFrame *frame = gPad->GetFrame();
1207 frame->SetBorderMode(0);
1208 frame->SetFillColor(gPad->GetFillColor());
1209 frame->SetLineColor(gPad->GetFillColor());
1213 TObject::Draw(option);
1219 void TASImage::Image2Drawable(ASImage *im, Drawable_t wid, Int_t x, Int_t y,
1220 Int_t xsrc, Int_t ysrc, UInt_t wsrc, UInt_t hsrc,
1225 wsrc = wsrc ? wsrc : im->width;
1226 hsrc = hsrc ? hsrc : im->height;
1228 static int x11 = -1;
1229 if (x11 < 0) x11 = gVirtualX->InheritsFrom(
"TGX11");
1231 Pixmap_t mask = kNone;
1236 UInt_t ww = wsrc - ow + (ow ? 8 : 0);
1243 char *bits =
new char[ww*hh];
1245 ASImageDecoder *imdec = start_image_decoding(fgVisual, im, SCL_DO_ALPHA,
1246 xsrc, ysrc, ww, 0, 0);
1248 for (yy = 0; yy < hh; yy++) {
1249 imdec->decode_image_scanline(imdec);
1250 CARD32 *a = imdec->buffer.alpha;
1252 for (xx = 0; xx < ww; xx++) {
1254 SETBIT(bits[i], bit);
1256 CLRBIT(bits[i], bit);
1267 stop_image_decoding(&imdec);
1269 mask = gVirtualX->CreateBitmap(gVirtualX->GetDefaultRootWindow(),
1270 (
const char *)bits, ww, hh);
1275 static GContext_t gc = 0;
1277 gv.fMask = kGCClipMask | kGCClipXOrigin | kGCClipYOrigin;
1278 gv.fClipMask = mask;
1279 gv.fClipXOrigin = x;
1280 gv.fClipYOrigin = y;
1283 gc = gVirtualX->CreateGC(gVirtualX->GetDefaultRootWindow(), &gv);
1285 gVirtualX->ChangeGC(gc, &gv);
1288 if (x11 && (!gPad || gPad->GetGLDevice() == -1)) {
1289 asimage2drawable(fgVisual, wid, im, (GC)gc, xsrc, ysrc, x, y, wsrc, hsrc, 1);
1292 unsigned char *bits = (
unsigned char *)im->alt.argb32;
1294 img = tile_asimage(fgVisual, im, xsrc, ysrc, wsrc, hsrc,
1295 0, ASA_ARGB32, 0, ASIMAGE_QUALITY_DEFAULT);
1297 bits = (
unsigned char *)img->alt.argb32;
1301 TString option(opt);
1304 if (gPad && gPad->GetGLDevice() != -1) {
1305 if (TVirtualPadPainter *painter = gPad->GetPainter())
1306 painter->DrawPixels(bits, wsrc, hsrc, x, y, !option.Contains(
"opaque"));
1308 Pixmap_t pic = gVirtualX->CreatePixmapFromData(bits, wsrc, hsrc);
1310 if (!option.Contains(
"opaque")) {
1314 gVirtualX->CopyArea(pic, wid, gc, 0, 0, wsrc, hsrc, x, y);
1315 gVirtualX->DeletePixmap(pic);
1321 destroy_asimage(&img);
1326 if (gv.fClipMask != kNone) gVirtualX->DeletePixmap(gv.fClipMask);
1328 gv.fMask = kGCClipMask;
1329 gv.fClipMask = kNone;
1330 if (gc) gVirtualX->ChangeGC(gc, &gv);
1341 void TASImage::PaintImage(Drawable_t wid, Int_t x, Int_t y, Int_t xsrc, Int_t ysrc,
1342 UInt_t wsrc, UInt_t hsrc, Option_t *opt)
1344 Image2Drawable(fScaledImage ? fScaledImage->fImage : fImage, wid, x, y,
1345 xsrc, ysrc, wsrc, hsrc, opt);
1361 void TASImage::Paint(Option_t *option)
1364 Error(
"Paint",
"no image set");
1368 if (!InitVisual()) {
1369 Warning(
"Paint",
"Visual not initiated");
1373 Int_t tile_x = 0, tile_y = 0;
1374 CARD32 tile_tint = 0;
1375 Bool_t tile = kFALSE;
1376 Bool_t expand = kFALSE;
1378 TString opt = option;
1381 if (opt.Contains(
"t")) {
1383 if (sscanf(opt.Data() + opt.Index(
"t"),
"t%d,%d,%s", &tile_x, &tile_y,
1386 if (parse_argb_color(stint, (CARD32*)&tile_tint) == stint)
1389 Error(
"Paint",
"tile option error");
1391 }
else if (opt.Contains(
"x")) {
1393 fConstRatio = kFALSE;
1394 }
else if (opt.Contains(
"z")) {
1395 fPaletteEnabled = kTRUE;
1397 if (!fImage->alt.vector) {
1402 ASImage *image = fImage;
1405 Int_t to_w = gPad->UtoPixel(1.);
1406 Int_t to_h = gPad->VtoPixel(0.);
1410 to_h = (Int_t)(to_h * (1.0 - gPad->GetBottomMargin() - gPad->GetTopMargin() ) + 0.5);
1411 to_w = (Int_t)(to_w * (1.0 - gPad->GetLeftMargin() - gPad->GetRightMargin() ) + 0.5);
1414 if ((to_w < 25 || to_h < 25) && !expand) {
1415 Error(
"Paint",
"pad too small to display an image");
1419 if (GetConstRatio()) {
1420 if ((Double_t)to_w / (Double_t)fZoomWidth <
1421 (Double_t)to_h / (Double_t)fZoomHeight)
1422 to_h = Int_t(Double_t(fZoomHeight) * to_w / fZoomWidth);
1424 to_w = Int_t(Double_t(fZoomWidth) * to_h / fZoomHeight);
1427 Int_t pal_Ax = to_w + gPad->UtoAbsPixel(gPad->GetLeftMargin()) +
1428 (gPad->UtoAbsPixel(gPad->GetRightMargin()) / 10);
1429 Int_t pal_Ay = gPad->YtoAbsPixel(1.0);
1430 Int_t pal_x = to_w + gPad->UtoPixel(gPad->GetLeftMargin()) +
1431 (gPad->UtoPixel(gPad->GetRightMargin()) / 10);
1432 Int_t pal_y = gPad->YtoPixel(1.0);
1433 Int_t pal_w = gPad->UtoPixel(gPad->GetRightMargin()) / 3;
1436 ASImage *grad_im = 0;
1438 if (fImage->alt.vector && fPaletteEnabled) {
1441 const TImagePalette &pal = GetPalette();
1443 grad.npoints = pal.fNumPoints;
1444 grad.type = GRADIENT_Top2Bottom;
1445 grad.color =
new ARGB32[grad.npoints];
1446 grad.offset =
new double[grad.npoints];
1448 for (Int_t pt = 0; pt < grad.npoints; pt++) {
1449 Int_t oldPt = grad.npoints - pt -1;
1450 grad.offset[pt] = 1 - pal.fPoints[oldPt];
1451 grad.color[pt] = (((ARGB32)(pal.fColorBlue[oldPt] & 0xff00)) >> 8) |
1452 (((ARGB32)(pal.fColorGreen[oldPt] & 0xff00)) ) |
1453 (((ARGB32)(pal.fColorRed[oldPt] & 0xff00)) << 8) |
1454 (((ARGB32)(pal.fColorAlpha[oldPt] & 0xff00)) << 16);
1457 grad_im = make_gradient(fgVisual, &grad , UInt_t(pal_w),
1458 pal_h, SCL_DO_COLOR,
1459 ASA_ARGB32, GetImageCompression(), GetImageQuality());
1461 delete [] grad.color;
1462 delete [] grad.offset;
1466 delete fScaledImage;
1467 fScaledImage = (TASImage*)TImage::Create();
1468 if (!fScaledImage)
return;
1469 fScaledImage->fImage = tile_asimage(fgVisual, fImage, tile_x, tile_y,
1470 to_w, to_h, tile_tint, ASA_ASImage,
1471 GetImageCompression(), GetImageQuality());
1472 image = fScaledImage->fImage;
1474 }
else if (fZoomUpdate == kZoomOps) {
1479 if (Int_t(fImage->width) != to_w || Int_t(fImage->height) != to_h ||
1480 fImage->width != fZoomWidth || fImage->height != fZoomHeight) {
1482 if (fScaledImage && (Int_t(fScaledImage->GetWidth()) != to_w ||
1483 Int_t(fScaledImage->GetHeight()) != to_h ||
1486 delete fScaledImage;
1490 if (!fScaledImage) {
1491 fScaledImage = (TASImage*)TImage::Create();
1492 if (!fScaledImage)
return;
1494 if (fZoomWidth && fZoomHeight &&
1495 ((fImage->width != fZoomWidth) || (fImage->height != fZoomHeight))) {
1497 ASImage *tmpImage = 0;
1499 tmpImage = tile_asimage(fgVisual, fImage, fZoomOffX,
1500 fImage->height - fZoomHeight - fZoomOffY,
1501 fZoomWidth, fZoomHeight, 0, ASA_ASImage,
1502 GetImageCompression(), GetImageQuality());
1505 fScaledImage->fImage = scale_asimage(fgVisual, tmpImage, to_w, to_h,
1506 ASA_ASImage, GetImageCompression(),
1508 destroy_asimage(&tmpImage);
1512 fScaledImage->fImage = scale_asimage(fgVisual, fImage, to_w, to_h,
1513 ASA_ASImage, GetImageCompression(),
1517 image = fScaledImage->fImage;
1523 Error(
"Paint",
"image could not be rendered to display");
1527 int tox = expand ? 0 : int(gPad->UtoPixel(1.) * gPad->GetLeftMargin());
1528 int toy = expand ? 0 : int(gPad->VtoPixel(0.) * gPad->GetTopMargin());
1530 if (!gROOT->IsBatch()) {
1531 Window_t wid = (Window_t)gVirtualX->GetWindowID(gPad->GetPixmapID());
1532 Image2Drawable(fScaledImage ? fScaledImage->fImage : fImage, wid, tox, toy);
1534 if (grad_im && fPaletteEnabled) {
1536 Image2Drawable(grad_im, wid, pal_x, pal_y);
1541 double min = fMinValue;
1542 double max = fMaxValue;
1543 axis.SetLineColor(0);
1544 Double_t pal_Xpos = gPad->AbsPixeltoX(pal_Ax + pal_w);
1545 axis.PaintAxis(pal_Xpos, gPad->PixeltoY(pal_Ay + pal_h - 1),
1546 pal_Xpos, gPad->PixeltoY(pal_Ay),
1547 min, max, ndiv,
"+LU");
1550 axis.SetLineColor(1);
1551 axis.PaintAxis(pal_Xpos, gPad->AbsPixeltoY(pal_Ay + pal_h),
1552 pal_Xpos, gPad->AbsPixeltoY(pal_Ay + 1),
1553 min, max, ndiv,
"+L");
1559 if (gVirtualPS->InheritsFrom(
"TImageDump")) {
1560 TImage *dump = (TImage *)gVirtualPS->GetStream();
1562 dump->Merge(fScaledImage ? fScaledImage :
this,
"alphablend",
1563 gPad->XtoAbsPixel(0), gPad->YtoAbsPixel(1));
1567 tgrad.fImage = grad_im;
1568 dump->Merge(&tgrad,
"alphablend", pal_Ax, pal_Ay);
1573 double min = fMinValue;
1574 double max = fMaxValue;
1575 axis.SetLineColor(1);
1576 Double_t pal_Xpos = gPad->AbsPixeltoX(pal_Ax + pal_w);
1577 axis.PaintAxis(pal_Xpos, gPad->AbsPixeltoY(pal_Ay + pal_h),
1578 pal_Xpos, gPad->AbsPixeltoY(pal_Ay + 1),
1579 min, max, ndiv,
"+L");
1582 }
else if (gVirtualPS->InheritsFrom(
"TPDF")) {
1583 Warning(
"Paint",
"PDF not implemented yet");
1585 }
else if (gVirtualPS->InheritsFrom(
"TSVG")) {
1586 Warning(
"Paint",
"SVG not implemented yet");
1591 TObjArray *colors = (TObjArray*) gROOT->GetListOfColors();
1594 if ((color = (TColor*)colors->FindObject(
"Image_PS")) == 0)
1595 color =
new TColor(colors->GetEntries(), 1., 1., 1.,
"Image_PS");
1597 gVirtualPS->SetFillColor(color->GetNumber());
1598 gVirtualPS->SetFillStyle(1001);
1600 Double_t dx = gPad->GetX2()-gPad->GetX1();
1601 Double_t dy = gPad->GetY2()-gPad->GetY1();
1602 Double_t x1,x2,y1,y2;
1606 x2 = x1+dx/image->width;
1608 y2 = y1+dy/image->height;
1610 x1 = gPad->GetX1()+dx*gPad->GetLeftMargin();
1611 x2 = x1+(dx*(1-gPad->GetRightMargin()-gPad->GetLeftMargin()))/image->width;
1612 y1 = gPad->GetY2()-dy*gPad->GetTopMargin();
1613 y2 = y1+(dy*(1-gPad->GetTopMargin()-gPad->GetBottomMargin()))/image->height;
1616 gVirtualPS->CellArrayBegin(image->width, image->height, x1, x2, y1, y2);
1618 ASImageDecoder *imdec = start_image_decoding(fgVisual, image, SCL_DO_ALL,
1619 0, 0, image->width, image->height, 0);
1621 for (Int_t yt = 0; yt < (Int_t)image->height; yt++) {
1622 imdec->decode_image_scanline(imdec);
1623 for (Int_t xt = 0; xt < (Int_t)image->width; xt++)
1624 gVirtualPS->CellArrayFill(imdec->buffer.red[xt],
1625 imdec->buffer.green[xt],
1626 imdec->buffer.blue[xt]);
1628 stop_image_decoding(&imdec);
1629 gVirtualPS->CellArrayEnd();
1633 Double_t xconv = (gPad->AbsPixeltoX(pal_Ax + pal_w) - gPad->AbsPixeltoX(pal_Ax)) / grad_im->width;
1634 Double_t yconv = (gPad->AbsPixeltoY(pal_Ay - pal_h) - gPad->AbsPixeltoY(pal_Ay)) / grad_im->height;
1635 x1 = gPad->AbsPixeltoX(pal_Ax);
1637 y2 = gPad->AbsPixeltoY(pal_Ay);
1639 gVirtualPS->CellArrayBegin(grad_im->width, grad_im->height,
1642 imdec = start_image_decoding(fgVisual, grad_im, SCL_DO_ALL,
1643 0, 0, grad_im->width, grad_im->height, 0);
1645 for (Int_t yt = 0; yt < (Int_t)grad_im->height; yt++) {
1646 imdec->decode_image_scanline(imdec);
1647 for (Int_t xt = 0; xt < (Int_t)grad_im->width; xt++)
1648 gVirtualPS->CellArrayFill(imdec->buffer.red[xt],
1649 imdec->buffer.green[xt],
1650 imdec->buffer.blue[xt]);
1653 stop_image_decoding(&imdec);
1654 gVirtualPS->CellArrayEnd();
1659 double min = fMinValue;
1660 double max = fMaxValue;
1661 axis.SetLineColor(1);
1662 Double_t pal_Xpos = gPad->AbsPixeltoX(pal_Ax + pal_w);
1663 axis.PaintAxis(pal_Xpos, gPad->AbsPixeltoY(pal_Ay + pal_h),
1664 pal_Xpos, gPad->AbsPixeltoY(pal_Ay + 1),
1665 min, max, ndiv,
"+L");
1671 destroy_asimage(&grad_im);
1678 Int_t TASImage::DistancetoPrimitive(Int_t px, Int_t py)
1680 Int_t pxl, pyl, pxt, pyt;
1682 Int_t px1 = gPad->XtoAbsPixel(0);
1683 Int_t py1 = gPad->YtoAbsPixel(0);
1684 Int_t px2 = gPad->XtoAbsPixel(1);
1685 Int_t py2 = gPad->YtoAbsPixel(1);
1687 if (px1 < px2) {pxl = px1; pxt = px2;}
1688 else {pxl = px2; pxt = px1;}
1689 if (py1 < py2) {pyl = py1; pyt = py2;}
1690 else {pyl = py2; pyt = py1;}
1692 if ((px > pxl && px < pxt) && (py > pyl && py < pyt))
1701 void TASImage::ExecuteEvent(Int_t event, Int_t px, Int_t py)
1703 static TBox *ZoomBox;
1708 gPad->ExecuteEvent(event, px, py);
1712 gPad->SetCursor(kCross);
1714 static Int_t px1old, py1old, px2old, py2old;
1715 static Int_t px1, py1, px2, py2, pxl, pyl, pxt, pyt;
1717 if (!IsValid())
return;
1719 if (event == kButton1Motion || event == kButton1Down ||
1720 event == kButton1Up) {
1723 Int_t imgX = px - gPad->XtoAbsPixel(0);
1724 Int_t imgY = py - gPad->YtoAbsPixel(1);
1726 if (imgX < 0) px = px - imgX;
1727 if (imgY < 0) py = py - imgY;
1729 ASImage *image = fImage;
1730 if (fScaledImage) image = fScaledImage->fImage;
1732 if (imgX >= (
int)image->width) px = px - imgX + image->width - 1;
1733 if (imgY >= (
int)image->height) py = py - imgY + image->height - 1;
1738 px1 = gPad->XtoAbsPixel(gPad->GetX1());
1739 py1 = gPad->YtoAbsPixel(gPad->GetY1());
1740 px2 = gPad->XtoAbsPixel(gPad->GetX2());
1741 py2 = gPad->YtoAbsPixel(gPad->GetY2());
1742 px1old = px; py1old = py;
1745 case kButton1Motion:
1747 px2old = TMath::Max(px2old, px1);
1748 px2old = TMath::Min(px2old, px2);
1750 py2old = TMath::Max(py2old, py2);
1751 py2old = TMath::Min(py2old, py1);
1752 pxl = TMath::Min(px1old, px2old);
1753 pxt = TMath::Max(px1old, px2old);
1754 pyl = TMath::Max(py1old, py2old);
1755 pyt = TMath::Min(py1old, py2old);
1758 ZoomBox->SetX1(gPad->AbsPixeltoX(pxl));
1759 ZoomBox->SetY1(gPad->AbsPixeltoY(pyl));
1760 ZoomBox->SetX2(gPad->AbsPixeltoX(pxt));
1761 ZoomBox->SetY2(gPad->AbsPixeltoY(pyt));
1764 ZoomBox =
new TBox(pxl, pyl, pxt, pyt);
1765 ZoomBox->SetFillStyle(0);
1766 ZoomBox->Draw(
"l*");
1768 gPad->Modified(kTRUE);
1774 if ( TMath::Abs(pxl - pxt) < 5 || TMath::Abs(pyl - pyt) < 5)
1782 Double_t xfact = (fScaledImage) ? (Double_t)fScaledImage->fImage->width / fZoomWidth : 1;
1783 Double_t yfact = (fScaledImage) ? (Double_t)fScaledImage->fImage->height / fZoomHeight : 1;
1785 Int_t imgX1 = px1old - gPad->XtoAbsPixel(0);
1786 Int_t imgY1 = py1old - gPad->YtoAbsPixel(1);
1787 Int_t imgX2 = px - gPad->XtoAbsPixel(0);
1788 Int_t imgY2 = py - gPad->YtoAbsPixel(1);
1790 imgY1 = image->height - 1 - imgY1;
1791 imgY2 = image->height - 1 - imgY2;
1792 imgX1 = (Int_t)(imgX1 / xfact) + fZoomOffX;
1793 imgY1 = (Int_t)(imgY1 / yfact) + fZoomOffY;
1794 imgX2 = (Int_t)(imgX2 / xfact) + fZoomOffX;
1795 imgY2 = (Int_t)(imgY2 / yfact) + fZoomOffY;
1797 Zoom((imgX1 < imgX2) ? imgX1 : imgX2, (imgY1 < imgY2) ? imgY1 : imgY2,
1798 TMath::Abs(imgX1 - imgX2) + 1, TMath::Abs(imgY1 - imgY2) + 1);
1804 gPad->Modified(kTRUE);
1814 char *TASImage::GetObjectInfo(Int_t px, Int_t py)
const
1816 static char info[64];
1819 if (!IsValid())
return info;
1822 px -= gPad->XtoAbsPixel(0);
1823 py -= gPad->YtoAbsPixel(1);
1826 if (px < 0 || py < 0)
return info;
1828 ASImage *image = fImage;
1829 if (fScaledImage) image = fScaledImage->fImage;
1830 if (px >= (
int)image->width || py >= (
int)image->height)
1833 py = image->height - 1 - py;
1836 px = (Int_t)(px / (Double_t)fScaledImage->fImage->width * fZoomWidth ) + fZoomOffX;
1837 py = (Int_t)(py / (Double_t)fScaledImage->fImage->height * fZoomHeight) + fZoomOffY;
1840 if (fImage->alt.vector) {
1841 snprintf(info,64,
"x: %d y: %d %.5g",
1842 px, py, fImage->alt.vector[px + py * fImage->width]);
1844 snprintf(info,64,
"x: %d y: %d", px, py);
1855 void TASImage::SetPalette(
const TImagePalette *palette)
1857 TAttImage::SetPalette(palette);
1859 if (!InitVisual()) {
1860 Warning(
"SetPalette",
"Visual not initiated");
1865 Warning(
"SetPalette",
"Image not valid");
1869 if (fImage->alt.vector == 0)
1873 const TImagePalette &pal = GetPalette();
1875 ASVectorPalette asPalette;
1876 asPalette.npoints = pal.fNumPoints;
1877 asPalette.channels[0] =
new CARD16 [asPalette.npoints];
1878 asPalette.channels[1] =
new CARD16 [asPalette.npoints];
1879 asPalette.channels[2] =
new CARD16 [asPalette.npoints];
1880 asPalette.channels[3] =
new CARD16 [asPalette.npoints];
1881 memcpy(asPalette.channels[0], pal.fColorBlue, pal.fNumPoints *
sizeof(UShort_t));
1882 memcpy(asPalette.channels[1], pal.fColorGreen, pal.fNumPoints *
sizeof(UShort_t));
1883 memcpy(asPalette.channels[2], pal.fColorRed, pal.fNumPoints *
sizeof(UShort_t));
1884 memcpy(asPalette.channels[3], pal.fColorAlpha, pal.fNumPoints *
sizeof(UShort_t));
1886 asPalette.points =
new double[asPalette.npoints];
1887 for (Int_t point = 0; point < Int_t(asPalette.npoints); point++)
1888 asPalette.points[point] = fMinValue + (fMaxValue - fMinValue) * pal.fPoints[point];
1891 colorize_asimage_vector(fgVisual, fImage, &asPalette, ASA_ASImage, GetImageQuality());
1893 delete [] asPalette.points;
1894 for (Int_t col = 0; col < 4; col++)
1895 delete [] asPalette.channels[col];
1898 delete fScaledImage;
1911 void TASImage::Scale(UInt_t toWidth, UInt_t toHeight)
1914 Warning(
"Scale",
"Image not initiated");
1918 if (!InitVisual()) {
1919 Warning(
"Scale",
"Visual not initiated");
1927 if (toWidth > 30000)
1929 if (toHeight > 30000)
1932 ASImage *img = scale_asimage(fgVisual, fImage, toWidth, toHeight,
1933 ASA_ASImage, GetImageCompression(),
1938 fZoomUpdate = kZoomOps;
1945 void TASImage::Slice(UInt_t xStart, UInt_t xEnd, UInt_t yStart, UInt_t yEnd,
1946 UInt_t toWidth, UInt_t toHeight)
1949 Warning(
"Scale",
"Image not initiated");
1953 if (!InitVisual()) {
1954 Warning(
"Scale",
"Visual not initiated");
1962 if (toWidth > 30000)
1964 if (toHeight > 30000)
1967 ASImage *img = slice_asimage(fgVisual, fImage, xStart, xEnd,
1968 yStart, yEnd, toWidth, toHeight,
1969 ASA_ASImage, GetImageCompression(),
1975 fZoomUpdate = kZoomOps;
1981 void TASImage::Tile(UInt_t toWidth, UInt_t toHeight)
1984 Warning(
"Tile",
"Image not initiated");
1988 if (!InitVisual()) {
1989 Warning(
"Tile",
"Visual not initiated");
1997 if (toWidth > 30000)
1999 if (toHeight > 30000)
2002 ASImage *img = tile_asimage(fgVisual, fImage, 0, 0, toWidth, toHeight, 0,
2003 ASA_ASImage, GetImageCompression(), GetImageQuality());
2007 fZoomUpdate = kZoomOps;
2021 void TASImage::Zoom(UInt_t offX, UInt_t offY, UInt_t width, UInt_t height)
2024 Warning(
"Zoom",
"Image not valid");
2027 fZoomUpdate = kZoom;
2029 fZoomWidth = (width == 0) ? 1 : ((width > fImage->width) ? fImage->width : width);
2030 fZoomHeight = (height == 0) ? 1 : ((height > fImage->height) ? fImage->height : height);
2032 if (fZoomOffX + fZoomWidth > fImage->width)
2033 fZoomOffX = fImage->width - fZoomWidth;
2035 if (fZoomOffY + fZoomHeight > fImage->height)
2036 fZoomOffY = fImage->height - fZoomHeight;
2043 void TASImage::UnZoom()
2046 Warning(
"UnZoom",
"Image not valid");
2049 fZoomUpdate = kZoom;
2052 fZoomWidth = fImage->width;
2053 fZoomHeight = fImage->height;
2055 delete fScaledImage;
2071 void TASImage::Flip(Int_t flip)
2074 Warning(
"Flip",
"Image not valid");
2077 if (!InitVisual()) {
2078 Warning(
"Flip",
"Visual not initiated");
2082 if (fImage->alt.vector) {
2083 Warning(
"Flip",
"flip does not work for data images");
2087 Int_t rflip = flip/90;
2089 UInt_t w = fImage->width;
2090 UInt_t h = fImage->height;
2097 ASImage *img = flip_asimage(fgVisual, fImage, 0, 0, w, h, rflip,
2098 ASA_ASImage, GetImageCompression(),
2118 void TASImage::Mirror(Bool_t vert)
2121 Warning(
"Mirror",
"Image not valid");
2125 if (!InitVisual()) {
2126 Warning(
"Mirror",
"Visual not initiated");
2130 if (fImage->alt.vector) {
2131 Warning(
"Mirror",
"mirror does not work for data images");
2135 ASImage *img = mirror_asimage(fgVisual, fImage, 0, 0,
2136 fImage->width, fImage->height, vert,
2137 ASA_ASImage, GetImageCompression(),
2148 UInt_t TASImage::GetWidth()
const
2150 return fImage ? fImage->width : 0;
2157 UInt_t TASImage::GetHeight()
const
2159 return fImage ? fImage->height : 0;
2166 UInt_t TASImage::GetScaledWidth()
const
2168 return fScaledImage ? fScaledImage->fImage->width : GetWidth();
2175 UInt_t TASImage::GetScaledHeight()
const
2177 return fScaledImage ? fScaledImage->fImage->height : GetHeight();
2184 void TASImage::GetZoomPosition(UInt_t &x, UInt_t &y, UInt_t &w, UInt_t &h)
const
2195 Bool_t TASImage::InitVisual()
2199 Bool_t inbatch = fgVisual && (fgVisual->dpy == (
void*)1);
2200 Bool_t noX = gROOT->IsBatch() || gVirtualX->InheritsFrom(
"TGWin32");
2203 if (inbatch && !noX) {
2204 destroy_asvisual(fgVisual, kFALSE);
2208 if (fgVisual && fgVisual->dpy) {
2213 if (!fgVisual && noX) {
2215 fgVisual = create_asvisual(0, 0, 0, 0);
2216 fgVisual->dpy = (Display*)1;
2222 fgVisual = create_asvisual(0, 0, 0, 0);
2223 fgVisual->dpy = (Display*)1;
2225 disp = (Display*) gVirtualX->GetDisplay();
2226 Int_t screen = gVirtualX->GetScreen();
2227 Int_t depth = gVirtualX->GetDepth();
2228 Visual *vis = (Visual*) gVirtualX->GetVisual();
2229 Colormap cmap = (Colormap) gVirtualX->GetColormap();
2231 if (vis == 0 || cmap == 0) {
2232 fgVisual = create_asvisual(0, 0, 0, 0);
2234 fgVisual = create_asvisual_for_id(disp, screen, depth,
2235 XVisualIDFromVisual(vis), cmap, 0);
2239 fgVisual = create_asvisual(0, 0, 0, 0);
2240 fgVisual->dpy = (Display*)1;
2249 void TASImage::StartPaletteEditor()
2252 Warning(
"StartPaletteEditor",
"Image not valid");
2255 if (fImage->alt.vector == 0) {
2256 Warning(
"StartPaletteEditor",
"palette can be modified only for data images");
2261 TAttImage::StartPaletteEditor();
2268 Pixmap_t TASImage::GetPixmap()
2270 if (!InitVisual()) {
2271 Warning(
"GetPixmap",
"Visual not initiated");
2277 ASImage *img = fScaledImage ? fScaledImage->fImage : fImage;
2279 static int x11 = -1;
2280 if (x11 < 0) x11 = gVirtualX->InheritsFrom(
"TGX11");
2283 ret = (Pixmap_t)asimage2pixmap(fgVisual, gVirtualX->GetDefaultRootWindow(),
2286 if (!fImage->alt.argb32) {
2289 ret = gVirtualX->CreatePixmapFromData((
unsigned char*)fImage->alt.argb32,
2290 fImage->width, fImage->height);
2300 Pixmap_t TASImage::GetMask()
2304 if (!InitVisual()) {
2305 Warning(
"GetMask",
"Visual not initiated");
2309 ASImage *img = fScaledImage ? fScaledImage->fImage : fImage;
2312 Warning(
"GetMask",
"No image");
2316 UInt_t hh = img->height;
2317 UInt_t ow = img->width%8;
2318 UInt_t ww = img->width - ow + (ow ? 8 : 0);
2325 char *bits =
new char[ww*hh];
2327 ASImageDecoder *imdec = start_image_decoding(fgVisual, img, SCL_DO_ALPHA,
2334 for (y = 0; y < hh; y++) {
2335 imdec->decode_image_scanline(imdec);
2336 CARD32 *a = imdec->buffer.alpha;
2338 for (x = 0; x < ww; x++) {
2340 SETBIT(bits[i], bit);
2342 CLRBIT(bits[i], bit);
2352 stop_image_decoding(&imdec);
2353 pxmap = gVirtualX->CreateBitmap(gVirtualX->GetDefaultRootWindow(), (
const char *)bits,
2362 void TASImage::SetImage(Pixmap_t pxm, Pixmap_t mask)
2364 if (!InitVisual()) {
2365 Warning(
"SetImage",
"Visual not initiated");
2370 delete fScaledImage;
2375 gVirtualX->GetWindowSize(pxm, xy, xy, w, h);
2377 if (fName.IsNull()) fName.Form(
"img_%dx%d",w, h);
2379 static int x11 = -1;
2380 if (x11 < 0) x11 = gVirtualX->InheritsFrom(
"TGX11");
2383 fImage = picture2asimage(fgVisual, pxm, mask, 0, 0, w, h, kAllPlanes, 1, 0);
2385 unsigned char *bits = gVirtualX->GetColorBits(pxm, 0, 0, w, h);
2392 fImage = bitmap2asimage(bits, w, h, 0, 0);
2396 unsigned char *mask_bits = gVirtualX->GetColorBits(mask, 0, 0, w, h);
2397 fImage = bitmap2asimage(bits, w, h, 0, mask_bits);
2398 delete [] mask_bits;
2406 TArrayL *TASImage::GetPixels(Int_t x, Int_t y, UInt_t width, UInt_t height)
2409 Warning(
"GetPixels",
"Wrong Image");
2413 ASImage *img = fScaledImage ? fScaledImage->fImage : fImage;
2414 ASImageDecoder *imdec;
2416 width = !width ? img->width : width;
2417 height = !height ? img->height : height;
2428 if ((x >= (
int)img->width) || (y >= (
int)img->height)) {
2432 if ((
int)(x + width) > (
int)img->width) {
2433 width = img->width - x;
2436 if ((
int)(y + height) > (
int)img->height) {
2437 height = img->height - y;
2440 if ((imdec = start_image_decoding(0, fImage, SCL_DO_ALL, 0, y,
2441 img->width, height, 0)) == 0) {
2442 Warning(
"GetPixels",
"Failed to create image decoder");
2446 TArrayL *ret =
new TArrayL(width * height);
2452 for (UInt_t k = 0; k < height; k++) {
2453 imdec->decode_image_scanline(imdec);
2455 for (UInt_t i = 0; i < width; ++i) {
2456 if ((r == (Int_t)imdec->buffer.red[i]) &&
2457 (g == (Int_t)imdec->buffer.green[i]) &&
2458 (b == (Int_t)imdec->buffer.blue[i])) {
2460 r = (Int_t)imdec->buffer.red[i];
2461 g = (Int_t)imdec->buffer.green[i];
2462 b = (Int_t)imdec->buffer.blue[i];
2463 p = (Long_t)TColor::RGB2Pixel(r, g, b);
2465 ret->AddAt(p, k*width + i);
2469 stop_image_decoding(&imdec);
2478 Double_t *TASImage::GetVecArray()
2481 Warning(
"GetVecArray",
"Bad Image");
2484 if (fImage->alt.vector) {
2485 return fImage->alt.vector;
2500 TArrayD *TASImage::GetArray(UInt_t w, UInt_t h, TImagePalette *palette)
2503 Warning(
"GetArray",
"Bad Image");
2509 if (fImage->alt.vector) {
2510 ret =
new TArrayD(fImage->width*fImage->height, fImage->alt.vector);
2514 ASImageDecoder *imdec;
2516 w = w ? w : fImage->width;
2517 h = h ? h : fImage->height;
2519 if ((fImage->width != w) || (fImage->height != h)) {
2523 ASImage *img = fScaledImage ? fScaledImage->fImage : fImage;
2525 if ((imdec = start_image_decoding(0, img, SCL_DO_ALL, 0, 0,
2526 img->width, 0, 0)) == 0) {
2527 Warning(
"GetArray",
"Failed to create image decoder");
2531 ret =
new TArrayD(w * h);
2538 for (UInt_t k = 0; k < h; k++) {
2539 imdec->decode_image_scanline(imdec);
2541 for (UInt_t i = 0; i < w; ++i) {
2542 if ((r == imdec->buffer.red[i]) &&
2543 (g == imdec->buffer.green[i]) &&
2544 (b == imdec->buffer.blue[i])) {
2546 r = imdec->buffer.red[i];
2547 g = imdec->buffer.green[i];
2548 b = imdec->buffer.blue[i];
2549 if (palette) p = palette->FindColor(r, g, b);
2551 v = palette ? palette->fPoints[p] : Double_t((r << 16) + (g << 8) + b)/0xFFFFFF;
2552 ret->AddAt(v, (h-k-1)*w + i);
2556 stop_image_decoding(&imdec);
2578 void TASImage::DrawText(Int_t x, Int_t y,
const char *text, Int_t size,
2579 const char *color,
const char *font_name,
2580 EText3DType type,
const char *fore_file, Float_t angle)
2582 UInt_t width=0, height=0;
2583 ARGB32 text_color = ARGB32_Black;
2584 ASImage *fore_im = 0;
2585 ASImage *text_im = 0;
2586 Bool_t ttfont = kFALSE;
2588 if (!InitVisual()) {
2589 Warning(
"DrawText",
"Visual not initiated");
2593 TString fn = font_name;
2597 if (fn.Last(
'/') == 0) fn = fn(1, fn.Length() - 1);
2599 const char *ttpath = gEnv->GetValue(
"Root.TTFontPath",
2600 TROOT::GetTTFFontDir());
2601 char *tmpstr = gSystem->Which(ttpath, fn, kReadPermission);
2605 if (fn.EndsWith(
".pfa") || fn.EndsWith(
".PFA") || fn.EndsWith(
".pfb") || fn.EndsWith(
".PFB") || fn.EndsWith(
".ttf") || fn.EndsWith(
".TTF") || fn.EndsWith(
".otf") || fn.EndsWith(
".OTF")) {
2610 parse_argb_color(color, &text_color);
2613 if (fImage && fImage->alt.argb32 && ttfont) {
2614 DrawTextTTF(x, y, text, size, text_color, fn.Data(), angle);
2618 if (!gFontManager) {
2619 gFontManager = create_font_manager(fgVisual->dpy, 0, 0);
2622 if (!gFontManager) {
2623 Warning(
"DrawText",
"cannot create Font Manager");
2627 ASFont *font = get_asfont(gFontManager, fn.Data(), 0, size, ASF_GuessWho);
2630 font = get_asfont(gFontManager,
"fixed", 0, size, ASF_GuessWho);
2632 Warning(
"DrawText",
"cannot find a font %s", font_name);
2637 get_text_size(text, font, (ASText3DType)type, &width, &height);
2640 fImage = create_asimage(width, height, 0);
2641 fill_asimage(fgVisual, fImage, 0, 0, width, height, 0xFFFFFFFF);
2644 text_im = draw_text(text, font, (ASText3DType)type, 0);
2646 ASImage *rimg = fImage;
2649 ASImage *tmp = file2ASImage(fore_file, 0xFFFFFFFF, SCREEN_GAMMA, 0, 0);
2651 if ((tmp->width != width) || (tmp->height != height)) {
2652 fore_im = tile_asimage(fgVisual, tmp, 0, 0, width, height, 0,
2653 ASA_ASImage, GetImageCompression(), GetImageQuality());
2655 destroy_asimage(&tmp);
2662 move_asimage_channel(fore_im, IC_ALPHA, text_im, IC_ALPHA);
2663 destroy_asimage(&text_im);
2671 ASImage *rendered_im;
2672 ASImageLayer layers[2];
2674 init_image_layers(&(layers[0]), 2);
2675 fore_im->back_color = text_color;
2676 layers[0].im = rimg;
2677 layers[0].dst_x = 0;
2678 layers[0].dst_y = 0;
2679 layers[0].clip_width = rimg->width;
2680 layers[0].clip_height = rimg->height;
2681 layers[0].bevel = 0;
2682 layers[1].im = fore_im;
2683 layers[1].dst_x = x;
2684 layers[1].dst_y = y;
2685 layers[1].clip_width = fore_im->width;
2686 layers[1].clip_height = fore_im->height;
2688 rendered_im = merge_layers(fgVisual, &(layers[0]), 2, rimg->width, rimg->height,
2689 ASA_ASImage, GetImageCompression(), GetImageQuality());
2691 destroy_asimage(&fore_im);
2693 fImage = rendered_im;
2719 void TASImage::Merge(
const TImage *im,
const char *op, Int_t x, Int_t y)
2723 if (!InitVisual()) {
2724 Warning(
"Merge",
"Visual not initiated");
2728 ASImage *rendered_im;
2729 ASImageLayer layers[2];
2731 init_image_layers(&(layers[0]), 2);
2732 layers[0].im = fImage;
2733 layers[0].dst_x = 0;
2734 layers[0].dst_y = 0;
2735 layers[0].clip_width = fImage->width;
2736 layers[0].clip_height = fImage->height;
2737 layers[0].bevel = 0;
2738 layers[1].im = ((TASImage*)im)->fImage;
2739 layers[1].dst_x = x;
2740 layers[1].dst_y = y;
2741 layers[1].clip_width = im->GetWidth();
2742 layers[1].clip_height = im->GetHeight();
2743 layers[1].merge_scanlines = blend_scanlines_name2func(op ? op :
"add");
2745 rendered_im = merge_layers(fgVisual, &(layers[0]), 2, fImage->width, fImage->height,
2746 ASA_ASImage, GetImageCompression(), GetImageQuality());
2749 fImage = rendered_im;
2758 void TASImage::Blur(Double_t hr, Double_t vr)
2760 if (!InitVisual()) {
2761 Warning(
"Blur",
"Visual not initiated");
2766 fImage = create_asimage(100, 100, 0);
2769 Warning(
"Blur",
"Failed to create image");
2773 fill_asimage(fgVisual, fImage, 0, 0, fImage->width, fImage->height, ARGB32_White);
2776 ASImage *rendered_im = blur_asimage_gauss(fgVisual, fImage, hr > 0 ? hr : 3,
2777 vr > 0 ? vr : 3, SCL_DO_ALL,
2778 ASA_ASImage, GetImageCompression(), GetImageQuality());
2780 fImage = rendered_im;
2787 TObject *TASImage::Clone(
const char *newname)
const
2789 if (!InitVisual() || !fImage) {
2790 Warning(
"Clone",
"Image not initiated");
2794 TASImage *im = (TASImage*)TImage::Create();
2797 Warning(
"Clone",
"Failed to create image");
2801 im->SetName(newname);
2803 im->fImage = clone_asimage(fImage, SCL_DO_ALL);
2804 im->fMaxValue = fMaxValue;
2805 im->fMinValue = fMinValue;
2806 im->fZoomOffX = fZoomOffX;
2807 im->fZoomOffY = fZoomOffY;
2808 im->fZoomWidth = fZoomWidth;
2809 im->fZoomHeight = fZoomHeight;
2810 im->fZoomUpdate = fZoomUpdate;
2811 im->fScaledImage = fScaledImage ? (TASImage*)fScaledImage->Clone(
"") : 0;
2813 if (fImage->alt.argb32) {
2814 UInt_t sz = fImage->width * fImage->height;
2815 im->fImage->alt.argb32 = (ARGB32*)safemalloc(sz*
sizeof(ARGB32));
2816 memcpy(im->fImage->alt.argb32, fImage->alt.argb32, sz *
sizeof(ARGB32));
2833 Double_t *TASImage::Vectorize(UInt_t max_colors, UInt_t dither, Int_t opaque_threshold)
2835 if (!InitVisual()) {
2836 Warning(
"Vectorize",
"Visual not initiated");
2841 fImage = create_asimage(100, 100, 0);
2844 Warning(
"Vectorize",
"Failed to create image");
2848 fill_asimage(fgVisual, fImage, 0, 0, fImage->width, fImage->height, ARGB32_White);
2853 UInt_t r=0, g=0, b=0;
2855 dither = dither > 7 ? 7 : dither;
2857 res = colormap_asimage(fImage, &cmap, max_colors, dither, opaque_threshold);
2859 Double_t *vec =
new Double_t[fImage->height*fImage->width];
2865 for (UInt_t y = 0; y < fImage->height; y++) {
2866 for (UInt_t x = 0; x < fImage->width; x++) {
2867 int i = y*fImage->width + x;
2869 g = INDEX_SHIFT_GREEN(cmap.entries[res[i]].green);
2870 b = INDEX_SHIFT_BLUE(cmap.entries[res[i]].blue);
2871 r = INDEX_SHIFT_RED(cmap.entries[res[i]].red);
2873 v = MAKE_INDEXED_COLOR24(r,g,b);
2875 tmp = Double_t(v)/0x0FFF;
2876 vec[(fImage->height - y - 1)*fImage->width + x] = tmp;
2877 if (fMinValue > tmp) fMinValue = tmp;
2878 if (fMaxValue < tmp) fMaxValue = tmp;
2881 TImagePalette *pal = new TImagePalette(cmap.count);
2883 for (UInt_t j = 0; j < cmap.count; j++) {
2884 g = INDEX_SHIFT_GREEN(cmap.entries[j].green);
2885 b = INDEX_SHIFT_BLUE(cmap.entries[j].blue);
2886 r = INDEX_SHIFT_RED(cmap.entries[j].red);
2887 v = MAKE_INDEXED_COLOR24(r,g,b);
2889 v = (v>>12) & 0x0FFF;
2890 pal->fPoints[j] = Double_t(v)/0x0FFF;
2892 pal->fColorRed[j] = cmap.entries[j].red << 8;
2893 pal->fColorGreen[j] = cmap.entries[j].green << 8;
2894 pal->fColorBlue[j] = cmap.entries[j].blue << 8;
2895 pal->fColorAlpha[j] = 0xFF00;
2898 destroy_colormap(&cmap, kTRUE);
2901 fImage->alt.vector = vec;
2904 if (res) safefree(res);
2905 return (Double_t*)fImage->alt.vector;
2946 void TASImage::HSV(UInt_t hue, UInt_t radius, Int_t H, Int_t S, Int_t V,
2947 Int_t x, Int_t y, UInt_t width, UInt_t height)
2949 if (!InitVisual()) {
2950 Warning(
"HSV",
"Visual not initiated");
2955 fImage = create_asimage(width ? width : 20, height ? height : 20, 0);
2958 Warning(
"HSV",
"Failed to create image");
2964 fill_asimage(fgVisual, fImage, 0, 0, fImage->width, fImage->height, ARGB32_White);
2967 width = !width ? fImage->width : width;
2968 height = !height ? fImage->height : height;
2970 ASImage *rendered_im = 0;
2973 rendered_im = adjust_asimage_hsv(fgVisual, fImage, x, y, width, height,
2974 hue, radius, H, S, V, ASA_ASImage, 100,
2975 ASIMAGE_QUALITY_TOP);
2978 Warning(
"HSV",
"Failed to create rendered image");
2983 fImage = rendered_im;
3009 void TASImage::Gradient(UInt_t angle,
const char *colors,
const char *offsets,
3010 Int_t x, Int_t y, UInt_t width, UInt_t height)
3012 if (!InitVisual()) {
3013 Warning(
"Gradient",
"Visual not initiated");
3017 ASImage *rendered_im = 0;
3018 ASGradient gradient;
3020 int reverse = 0, npoints1 = 0, npoints2 = 0;
3024 TString str = colors;
3027 if ((angle > 2 * 180 * 15 / 16) || (angle < 2 * 180 * 1 / 16)) {
3028 gradient.type = GRADIENT_Left2Right;
3029 }
else if (angle < 2 * 180 * 3 / 16) {
3030 gradient.type = GRADIENT_TopLeft2BottomRight;
3031 }
else if (angle < 2 * 180 * 5 / 16) {
3032 gradient.type = GRADIENT_Top2Bottom;
3033 }
else if (angle < 2 * 180 * 7 / 16) {
3034 gradient.type = GRADIENT_BottomLeft2TopRight; reverse = 1;
3035 }
else if (angle < 2 * 180 * 9 / 16) {
3036 gradient.type = GRADIENT_Left2Right; reverse = 1;
3037 }
else if (angle < 2 * 180 * 11 / 16) {
3038 gradient.type = GRADIENT_TopLeft2BottomRight; reverse = 1;
3039 }
else if (angle < 2 * 180 * 13 / 16) {
3040 gradient.type = GRADIENT_Top2Bottom; reverse = 1;
3042 gradient.type = GRADIENT_BottomLeft2TopRight;
3045 for (p = (
char*)colors; isspace((
int)*p); p++) { }
3047 for (npoints1 = 0; *p; npoints1++) {
3049 for ( ; *p && !isspace((
int)*p); p++) { }
3051 for ( ; isspace((
int)*p); p++) { }
3054 for (p = (
char*)offsets; isspace((
int)*p); p++) { }
3056 for (npoints2 = 0; *p; npoints2++) {
3058 for ( ; *p && !isspace((
int)*p); p++) { }
3060 for ( ; isspace((
int)*p); p++) { }
3065 if (offsets && (npoints1 > npoints2)) npoints1 = npoints2;
3068 width = fImage ? fImage->width : 20;
3071 height = fImage ? fImage->height : 20;
3074 gradient.color =
new ARGB32[npoints1];
3075 gradient.offset =
new double[npoints1];
3077 for (p = (
char*)colors; isspace((
int)*p); p++) { }
3079 for (npoints1 = 0; *p; ) {
3083 for ( ; *p && !isspace((
int)*p); p++) { }
3085 for ( ; isspace((
int)*p); p++) { }
3087 col = str(pb - colors, p - pb);
3089 if (parse_argb_color(col.Data(), gradient.color + npoints1) != col) {
3092 Warning(
"Gradient",
"Failed to parse color [%s] - defaulting to black", pb);
3097 for (p = (
char*)offsets; isspace((
int)*p); p++) { }
3099 for (npoints2 = 0; *p; ) {
3103 for ( ; *p && !isspace((
int)*p); p++) { }
3106 gradient.offset[npoints2] = strtod(pb, &pb);
3108 if (pb == p) npoints2++;
3110 for ( ; isspace((
int)*p); p++) { }
3113 for (npoints2 = 0; npoints2 < npoints1; npoints2++) {
3114 gradient.offset[npoints2] = (double)npoints2 / (npoints1 - 1);
3117 gradient.npoints = npoints1;
3119 if (npoints2 && (gradient.npoints > npoints2)) {
3120 gradient.npoints = npoints2;
3123 for (i = 0; i < gradient.npoints/2; i++) {
3124 int i2 = gradient.npoints - 1 - i;
3125 ARGB32 c = gradient.color[i];
3126 double o = gradient.offset[i];
3127 gradient.color[i] = gradient.color[i2];
3128 gradient.color[i2] = c;
3129 gradient.offset[i] = gradient.offset[i2];
3130 gradient.offset[i2] = o;
3132 for (i = 0; i < gradient.npoints; i++) {
3133 gradient.offset[i] = 1.0 - gradient.offset[i];
3136 rendered_im = make_gradient(fgVisual, &gradient, width, height, SCL_DO_ALL,
3137 ASA_ASImage, GetImageCompression(), GetImageQuality());
3139 delete [] gradient.color;
3140 delete [] gradient.offset;
3144 Warning(
"Gradient",
"Failed to create gradient image");
3149 fImage = rendered_im;
3153 ASImageLayer layers[2];
3155 init_image_layers(&(layers[0]), 2);
3156 layers[0].im = fImage;
3157 layers[0].dst_x = 0;
3158 layers[0].dst_y = 0;
3159 layers[0].clip_width = fImage->width;
3160 layers[0].clip_height = fImage->height;
3161 layers[0].bevel = 0;
3162 layers[1].im = rendered_im;
3163 layers[1].dst_x = x;
3164 layers[1].dst_y = y;
3165 layers[1].clip_width = width;
3166 layers[1].clip_height = height;
3167 layers[1].merge_scanlines = alphablend_scanlines;
3169 ASImage *merge_im = merge_layers(fgVisual, &(layers[0]), 2, fImage->width, fImage->height,
3170 ASA_ASImage, GetImageCompression(), GetImageQuality());
3172 Warning(
"Gradient",
"Failed to create merged image");
3176 destroy_asimage(&rendered_im);
3186 static CARD8 MakeComponentHilite(
int cmp)
3191 cmp = (cmp * 12) / 10;
3193 return (cmp > 255) ? 255 : cmp;
3200 static ARGB32 GetHilite(ARGB32 background)
3202 return ((MakeComponentHilite((background>>24) & 0x000000FF) << 24) & 0xFF000000) |
3203 ((MakeComponentHilite((background & 0x00FF0000) >> 16) << 16) & 0x00FF0000) |
3204 ((MakeComponentHilite((background & 0x0000FF00) >> 8) << 8) & 0x0000FF00) |
3205 ((MakeComponentHilite((background & 0x000000FF))) & 0x000000FF);
3212 static ARGB32 GetShadow(ARGB32 background)
3214 return (background >> 1) & 0x7F7F7F7F;
3221 static ARGB32 GetAverage(ARGB32 foreground, ARGB32 background)
3225 a = ARGB32_ALPHA8(foreground) + ARGB32_ALPHA8(background);
3227 r = ARGB32_RED8(foreground) + ARGB32_RED8(background);
3229 g = ARGB32_GREEN8(foreground) + ARGB32_GREEN8(background);
3231 b = ARGB32_BLUE8(foreground) + ARGB32_BLUE8(background);
3234 return MAKE_ARGB32(a, r, g, b);
3249 void TASImage::Bevel(Int_t x, Int_t y, UInt_t width, UInt_t height,
3250 const char *hi_color,
const char *lo_color, UShort_t thick,
3253 if (!InitVisual()) {
3254 Warning(
"Bevel",
"Visual not initiated");
3261 ARGB32 hi=ARGB32_White, lo=ARGB32_White;
3262 parse_argb_color(hi_color, &hi);
3263 parse_argb_color(lo_color, &lo);
3266 bevel.lo_color = hi;
3267 bevel.lolo_color = GetHilite(hi);
3268 bevel.hi_color = lo;
3269 bevel.hihi_color = GetShadow(lo);
3271 bevel.hi_color = hi;
3272 bevel.hihi_color = GetHilite(hi);
3273 bevel.lo_color = lo;
3274 bevel.lolo_color = GetShadow(lo);
3276 bevel.hilo_color = GetAverage(hi, lo);
3278 int extra_hilite = 2;
3279 bevel.left_outline = bevel.top_outline = bevel.right_outline = bevel.bottom_outline = thick;
3280 bevel.left_inline = bevel.top_inline = bevel.right_inline = bevel.bottom_inline = extra_hilite + 1;
3282 if (bevel.top_outline > 1) {
3283 bevel.top_inline += bevel.top_outline - 1;
3286 if (bevel.left_outline > 1) {
3287 bevel.left_inline += bevel.left_outline - 1;
3290 if (bevel.right_outline > 1) {
3291 bevel.right_inline += bevel.right_outline - 1;
3294 if (bevel.bottom_outline > 1) {
3295 bevel.bottom_inline += bevel.bottom_outline - 1;
3299 ARGB32 fill = ((hi>>24) != 0xff) || ((lo>>24) != 0xff) ? bevel.hilo_color : (bevel.hilo_color | 0xff000000);
3302 fImage = create_asimage(width ? width : 20, height ? height : 20, 0);
3305 Warning(
"Bevel",
"Failed to create image");
3311 fill_asimage(fgVisual, fImage, 0, 0, fImage->width, fImage->height, fill);
3314 width = !width ? fImage->width : width;
3315 height = !height ? fImage->height : height;
3317 ASImageLayer layers[2];
3318 init_image_layers(&(layers[0]), 2);
3320 layers[0].im = fImage;
3321 layers[0].dst_x = 0;
3322 layers[0].dst_y = 0;
3323 layers[0].clip_width = fImage->width;
3324 layers[0].clip_height = fImage->height;
3325 layers[0].bevel = 0;
3327 UInt_t w = width - (bevel.left_outline + bevel.right_outline);
3328 UInt_t h = height - (bevel.top_outline + bevel.bottom_outline);
3329 ASImage *bevel_im = create_asimage(w, h, 0);
3332 Warning(
"Bevel",
"Failed to create bevel image");
3336 layers[1].im = bevel_im;
3337 fill_asimage(fgVisual, bevel_im, 0, 0, w, h, fill);
3339 layers[1].dst_x = x;
3340 layers[1].dst_y = y;
3341 layers[1].clip_width = width;
3342 layers[1].clip_height = height;
3343 layers[1].bevel = &bevel;
3344 layers[1].merge_scanlines = alphablend_scanlines;
3346 merge_im = merge_layers(fgVisual, &(layers[0]), 2, fImage->width, fImage->height,
3347 ASA_ASImage, GetImageCompression(), GetImageQuality());
3348 destroy_asimage(&bevel_im);
3351 Warning(
"Bevel",
"Failed to image");
3365 void TASImage::Pad(
const char *col, UInt_t l, UInt_t r, UInt_t t, UInt_t b)
3370 if (!InitVisual()) {
3371 Warning(
"Pad",
"Visual not initiated");
3376 fImage = create_asimage(100, 100, 0);
3379 Warning(
"Pad",
"Failed to create image");
3385 fill_asimage(fgVisual, fImage, 0, 0, fImage->width, fImage->height, ARGB32_White);
3388 ARGB32 color = ARGB32_White;
3389 parse_argb_color(col, &color);
3393 w = l + fImage->width + r;
3394 h = t + fImage->height + b;
3396 ASImage *img = pad_asimage(fgVisual, fImage, x, y, w, h, color,
3397 ASA_ASImage, GetImageCompression(), GetImageQuality());
3400 Warning(
"Pad",
"Failed to create output image");
3407 fZoomUpdate = kZoomOps;
3414 void TASImage::Crop(Int_t x, Int_t y, UInt_t width, UInt_t height)
3416 if (!InitVisual()) {
3417 Warning(
"Crop",
"Visual not initiated");
3422 Warning(
"Crop",
"No image");
3429 width = x + width > fImage->width ? fImage->width - x : width;
3430 height = y + height > fImage->height ? fImage->height - y : height;
3432 if ((width == fImage->width) && (height == fImage->height)) {
3433 Warning(
"Crop",
"input size larger than image");
3436 ASImageDecoder *imdec = start_image_decoding(fgVisual, fImage, SCL_DO_ALL,
3437 x, y, width, height, 0);
3440 Warning(
"Crop",
"Failed to start image decoding");
3444 ASImage *img = create_asimage(width, height, 0);
3448 Warning(
"Crop",
"Failed to create image");
3452 ASImageOutput *imout = start_image_output(fgVisual, img, ASA_ASImage,
3453 GetImageCompression(), GetImageQuality());
3456 Warning(
"Crop",
"Failed to start image output");
3457 destroy_asimage(&img);
3458 if (imdec)
delete [] imdec;
3466 for (UInt_t i = 0; i < height; i++) {
3467 imdec->decode_image_scanline(imdec);
3468 imout->output_image_scanline(imout, &(imdec->buffer), 1);
3471 stop_image_decoding(&imdec);
3472 stop_image_output(&imout);
3481 fZoomUpdate = kZoomOps;
3491 void TASImage::Append(
const TImage *im,
const char *option,
const char *color )
3495 if (!InitVisual()) {
3496 Warning(
"Append",
"Visual not initiated");
3501 fImage = ((TASImage*)im)->fImage;
3505 TString opt = option;
3508 UInt_t width = fImage->width;
3509 UInt_t height = fImage->height;
3512 Pad(color, 0, im->GetWidth(), 0, 0);
3513 Merge(im,
"alphablend", width, 0);
3514 }
else if (opt ==
"/") {
3515 Pad(color, 0, 0, 0, im->GetHeight());
3516 Merge(im,
"alphablend", 0, height);
3532 void TASImage::BeginPaint(Bool_t mode)
3534 if (!InitVisual()) {
3535 Warning(
"BeginPaint",
"Visual not initiated");
3545 if (!fPaintMode || fImage->alt.argb32) {
3549 ASImage *img = tile_asimage(fgVisual, fImage, 0, 0, fImage->width, fImage->height,
3550 0, ASA_ARGB32, 0, ASIMAGE_QUALITY_DEFAULT);
3553 Warning(
"BeginPaint",
"Failed to create image");
3564 void TASImage::EndPaint()
3567 Warning(
"EndPaint",
"no image");
3571 if (!fImage->alt.argb32)
return;
3573 ASImage *img = tile_asimage(fgVisual, fImage, 0, 0, fImage->width, fImage->height,
3574 0, ASA_ASImage, 0, ASIMAGE_QUALITY_DEFAULT);
3577 Warning(
"EndPaint",
"Failed to create image");
3581 fPaintMode = kFALSE;
3591 UInt_t *TASImage::GetArgbArray()
3594 Warning(
"GetArgbArray",
"no image");
3598 ASImage *img = fScaledImage ? fScaledImage->fImage : fImage;
3601 if (!img->alt.argb32) {
3603 fScaledImage->BeginPaint();
3604 img = fScaledImage->fImage;
3611 return (UInt_t *)img->alt.argb32;
3619 UInt_t *TASImage::GetRgbaArray()
3622 Warning(
"GetRgbaArray",
"no image");
3626 ASImage *img = fScaledImage ? fScaledImage->fImage : fImage;
3629 if (!img->alt.argb32) {
3631 fScaledImage->BeginPaint();
3632 img = fScaledImage->fImage;
3642 UInt_t a, rgb, rgba, argb;
3645 UInt_t *ret =
new UInt_t[img->width*img->height];
3647 for (i = 0; i < img->height; i++) {
3648 for (j = 0; j < img->width; j++) {
3650 argb = img->alt.argb32[idx];
3652 rgb = argb & 0x00ffffff;
3653 rgba = (rgb << 8) + a;
3665 UInt_t *TASImage::GetScanline(UInt_t y)
3668 Warning(
"GetScanline",
"no image");
3672 ASImage *img = fScaledImage ? fScaledImage->fImage : fImage;
3673 CARD32 *ret =
new CARD32[img->width];
3675 ASImageDecoder *imdec = start_image_decoding(fgVisual, img, SCL_DO_ALL,
3676 0, y, img->width, 1, 0);
3680 Warning(
"GetScanline",
"Failed to start image decoding");
3688 imdec->decode_image_scanline(imdec);
3689 memcpy(imdec->buffer.buffer, ret, img->width*
sizeof(CARD32));
3690 stop_image_decoding(&imdec);
3696 return (UInt_t*)ret;
3705 #if defined(R__GNU) && defined(__i386__) && !defined(__sun)
3706 #define _MEMSET_(dst, lng, val) __asm__("movl %0,%%eax \n"\
3707 "movl %1,%%edi \n" \
3708 "movl %2,%%ecx \n" \
3713 :"g" (val), "g" (dst), "g" (lng) \
3714 :"eax","edi","ecx" \
3718 #define _MEMSET_(dst, lng, val) do {\
3719 for( UInt_t j=0; j < lng; j++) *((dst)+j) = val; } while (0)
3723 #define FillSpansInternal(npt, ppt, widths, color) do {\
3724 UInt_t yy = ppt[0].fY*fImage->width;\
3725 for (UInt_t i = 0; i < npt; i++) {\
3726 _MEMSET_(&fImage->alt.argb32[Idx(yy + ppt[i].fX)], widths[i], color);\
3727 yy += ((i+1 < npt) && (ppt[i].fY != ppt[i+1].fY) ? fImage->width : 0);\
3735 void TASImage::FillRectangleInternal(UInt_t col, Int_t x, Int_t y, UInt_t width, UInt_t height)
3738 if (!InitVisual()) {
3739 Warning(
"FillRectangle",
"Visual not initiated");
3744 Warning(
"FillRectangle",
"no image");
3748 if (!fImage->alt.argb32) {
3752 if (!fImage->alt.argb32) {
3753 Warning(
"FillRectangle",
"Failed to get pixel array");
3757 ARGB32 color = (ARGB32)col;
3759 if (width == 0) width = 1;
3760 if (height == 0) height = 1;
3771 Bool_t has_alpha = (color & 0xff000000) != 0xff000000;
3773 x = x > (int)fImage->width ? (Int_t)fImage->width : x;
3774 y = y > (int)fImage->height ? (Int_t)fImage->height : y;
3776 width = x + width > fImage->width ? fImage->width - x : width;
3777 height = y + height > fImage->height ? fImage->height - y : height;
3779 if (!fImage->alt.argb32) {
3780 fill_asimage(fgVisual, fImage, x, y, width, height, color);
3782 int yyy = y*fImage->width;
3784 ARGB32 *p0 = fImage->alt.argb32 + yyy + x;
3786 for (UInt_t i = 0; i < height; i++) {
3787 _MEMSET_(p, width, color);
3791 for (UInt_t i = y; i < y + height; i++) {
3795 _alphaBlend(&fImage->alt.argb32[Idx(yyy + j)], &color);
3797 yyy += fImage->width;
3813 void TASImage::FillRectangle(
const char *col, Int_t x, Int_t y, UInt_t width, UInt_t height)
3815 if (!InitVisual()) {
3816 Warning(
"Fill",
"Visual not initiated");
3820 ARGB32 color = ARGB32_White;
3823 parse_argb_color(col, &color);
3827 fImage = create_asimage(width ? width : 20, height ? height : 20, 0);
3832 FillRectangleInternal((UInt_t)color, x, y, width, height);
3839 void TASImage::DrawVLine(UInt_t x, UInt_t y1, UInt_t y2, UInt_t col, UInt_t thick)
3841 ARGB32 color = (ARGB32)col;
3844 if (!thick) thick = 1;
3852 thick += (x - half);
3856 y2 = y2 >= fImage->height ? fImage->height - 1 : y2;
3857 y1 = y1 >= fImage->height ? fImage->height - 1 : y1;
3858 x = x + thick >= fImage->width ? fImage->width - thick - 1 : x;
3860 int yy = y1*fImage->width;
3861 for (UInt_t y = y1; y <= y2; y++) {
3862 for (UInt_t w = 0; w < thick; w++) {
3863 if (x + w < fImage->width) {
3864 _alphaBlend(&fImage->alt.argb32[Idx(yy + (x + w))], &color);
3867 yy += fImage->width;
3874 void TASImage::DrawHLine(UInt_t y, UInt_t x1, UInt_t x2, UInt_t col, UInt_t thick)
3876 ARGB32 color = (ARGB32)col;
3879 if (!thick) thick = 1;
3887 thick += (y - half);
3891 y = y + thick >= fImage->height ? fImage->height - thick - 1 : y;
3892 x2 = x2 >= fImage->width ? fImage->width - 1 : x2;
3893 x1 = x1 >= fImage->width ? fImage->width - 1 : x1;
3895 int yy = y*fImage->width;
3896 for (UInt_t w = 0; w < thick; w++) {
3897 for (UInt_t x = x1; x <= x2; x++) {
3898 if (y + w < fImage->height) {
3899 _alphaBlend(&fImage->alt.argb32[Idx(yy + x)], &color);
3902 yy += fImage->width;
3909 void TASImage::DrawLine(UInt_t x1, UInt_t y1, UInt_t x2, UInt_t y2,
3910 const char *col, UInt_t thick)
3912 ARGB32 color = ARGB32_White;
3913 parse_argb_color(col, &color);
3914 DrawLineInternal(x1, y1, x2, y2, (UInt_t)color, thick);
3920 void TASImage::DrawLineInternal(UInt_t x1, UInt_t y1, UInt_t x2, UInt_t y2,
3921 UInt_t col, UInt_t thick)
3925 int x, y, xend, yend;
3931 if (!InitVisual()) {
3932 Warning(
"DrawLine",
"Visual not initiated");
3937 Warning(
"DrawLine",
"no image");
3941 if (!fImage->alt.argb32) {
3945 if (!fImage->alt.argb32) {
3946 Warning(
"DrawLine",
"Failed to get pixel array");
3950 ARGB32 color = (ARGB32)col;
3952 dx = TMath::Abs(Int_t(x2) - Int_t(x1));
3953 dy = TMath::Abs(Int_t(y2) - Int_t(y1));
3955 if (!dx && !dy)
return;
3958 DrawVLine(x1, y2 > y1 ? y1 : y2,
3959 y2 > y1 ? y2 : y1, color, thick);
3964 DrawHLine(y1, x2 > x1 ? x1 : x2,
3965 x2 > x1 ? x2 : x1, color, thick);
3970 DrawWideLine(x1, y1, x2, y2, color, thick);
3975 UInt_t ddy = dy << 1;
3977 i2 = i1 - (dx << 1);
3992 yy = y*fImage->width;
3993 _alphaBlend(&fImage->alt.argb32[Idx(yy + x)], &color);
3994 q = (y2 - y1) * ydir;
4000 _alphaBlend(&fImage->alt.argb32[idx], &color);
4004 yy += fImage->width;
4013 _alphaBlend(&fImage->alt.argb32[idx], &color);
4017 yy -= fImage->width;
4025 UInt_t ddx = dx << 1;
4027 i2 = i1 - (dy << 1);
4042 yy = y*fImage->width;
4043 _alphaBlend(&fImage->alt.argb32[Idx(yy + x)], &color);
4044 q = (x2 - x1) * xdir;
4049 _alphaBlend(&fImage->alt.argb32[idx], &color);
4051 yy += fImage->width;
4063 _alphaBlend(&fImage->alt.argb32[idx], &color);
4065 yy += fImage->width;
4081 void TASImage::DrawRectangle(UInt_t x, UInt_t y, UInt_t w, UInt_t h,
4082 const char *col, UInt_t thick)
4084 if (!InitVisual()) {
4085 Warning(
"DrawRectangle",
"Visual not initiated");
4094 fImage = create_asimage(w, h, 0);
4095 FillRectangle(col, 0, 0, w, h);
4099 if (!fImage->alt.argb32) {
4103 if (!fImage->alt.argb32) {
4104 Warning(
"DrawRectangle",
"Failed to get pixel array");
4108 ARGB32 color = ARGB32_White;
4109 parse_argb_color(col, &color);
4111 DrawHLine(y, x, x + w, (UInt_t)color, thick);
4112 DrawVLine(x + w, y, y + h, (UInt_t)color, thick);
4113 DrawHLine(y + h, x, x + w, (UInt_t)color, thick);
4114 DrawVLine(x, y, y + h, (UInt_t)color, thick);
4121 void TASImage::DrawBox(Int_t x1, Int_t y1, Int_t x2, Int_t y2,
const char *col,
4122 UInt_t thick, Int_t mode)
4124 Int_t x = TMath::Min(x1, x2);
4125 Int_t y = TMath::Min(y1, y2);
4126 Int_t w = TMath::Abs(x2 - x1);
4127 Int_t h = TMath::Abs(y2 - y1);
4129 ARGB32 color = ARGB32_White;
4134 fImage = create_asimage(w, h, 0);
4135 FillRectangle(col, 0, 0, w, h);
4140 parse_argb_color(col, &color);
4141 DrawVLine(x1, y1, y2, color, 1);
4146 parse_argb_color(col, &color);
4147 DrawHLine(y1, x1, x2, color, 1);
4153 case TVirtualX::kHollow:
4154 DrawRectangle(x, y, w, h, col, thick);
4157 case TVirtualX::kFilled:
4158 FillRectangle(col, x, y, w, h);
4162 FillRectangle(col, x, y, w, h);
4170 void TASImage::DrawDashHLine(UInt_t y, UInt_t x1, UInt_t x2, UInt_t nDash,
4171 const char *pDash, UInt_t col, UInt_t thick)
4176 ARGB32 color = (ARGB32)col;
4186 thick += (y - half);
4189 thick = thick <= 0 ? 1 : thick;
4191 y = y + thick >= fImage->height ? fImage->height - thick - 1 : y;
4192 x2 = x2 >= fImage->width ? fImage->width - 1 : x2;
4193 x1 = x1 >= fImage->width ? fImage->width - 1 : x1;
4197 x1 = x2 < x1 ? x2 : x1;
4198 x2 = x2 < tmp ? tmp : x2;
4200 for (UInt_t x = x1; x <= x2; x++) {
4201 for (UInt_t w = 0; w < thick; w++) {
4202 if (y + w < fImage->height) {
4204 _alphaBlend(&fImage->alt.argb32[Idx((y + w)*fImage->width + x)], &color);
4210 if (i >= pDash[iDash]) {
4214 if (iDash >= nDash) {
4224 void TASImage::DrawDashVLine(UInt_t x, UInt_t y1, UInt_t y2, UInt_t nDash,
4225 const char *pDash, UInt_t col, UInt_t thick)
4230 ARGB32 color = (ARGB32)col;
4240 thick += (x - half);
4243 thick = thick <= 0 ? 1 : thick;
4245 y2 = y2 >= fImage->height ? fImage->height - 1 : y2;
4246 y1 = y1 >= fImage->height ? fImage->height - 1 : y1;
4250 y1 = y2 < y1 ? y2 : y1;
4251 y2 = y2 < tmp ? tmp : y2;
4253 x = x + thick >= fImage->width ? fImage->width - thick - 1 : x;
4255 int yy = y1*fImage->width;
4256 for (UInt_t y = y1; y <= y2; y++) {
4257 for (UInt_t w = 0; w < thick; w++) {
4258 if (x + w < fImage->width) {
4260 _alphaBlend(&fImage->alt.argb32[Idx(yy + (x + w))], &color);
4266 if (i >= pDash[iDash]) {
4270 if (iDash >= nDash) {
4274 yy += fImage->width;
4281 void TASImage::DrawDashZLine(UInt_t x1, UInt_t y1, UInt_t x2, UInt_t y2,
4282 UInt_t nDash,
const char *tDash, UInt_t color)
4286 int x, y, xend, yend;
4293 dx = TMath::Abs(Int_t(x2) - Int_t(x1));
4294 dy = TMath::Abs(Int_t(y2) - Int_t(y1));
4296 char *pDash =
new char[nDash];
4299 double ac = TMath::Cos(TMath::ATan2(dy, dx));
4301 for (i = 0; i < (int)nDash; i++) {
4302 pDash[i] = TMath::Nint(tDash[i] * ac);
4305 UInt_t ddy = dy << 1;
4307 i2 = i1 - (dx << 1);
4323 yy = y*fImage->width;
4324 _alphaBlend(&fImage->alt.argb32[Idx(y*fImage->width + x)], &color);
4325 q = (y2 - y1) * ydir;
4330 if ((iDash%2) == 0) {
4331 _alphaBlend(&fImage->alt.argb32[idx], &color);
4335 yy += fImage->width;
4342 if (i >= pDash[iDash]) {
4346 if (iDash >= nDash) {
4354 if ((iDash%2) == 0) {
4355 _alphaBlend(&fImage->alt.argb32[idx], &color);
4359 yy -= fImage->width;
4366 if (i >= pDash[iDash]) {
4370 if (iDash >= nDash) {
4377 double as = TMath::Sin(TMath::ATan2(dy, dx));
4379 for (i = 0; i < (int)nDash; i++) {
4380 pDash[i] = TMath::Nint(tDash[i] * as);
4383 UInt_t ddx = dx << 1;
4385 i2 = i1 - (dy << 1);
4401 yy = y*fImage->width;
4402 _alphaBlend(&fImage->alt.argb32[Idx(y*fImage->width + x)], &color);
4403 q = (x2 - x1) * xdir;
4408 if ((iDash%2) == 0) {
4409 _alphaBlend(&fImage->alt.argb32[idx], &color);
4412 yy += fImage->width;
4422 if (i >= pDash[iDash]) {
4426 if (iDash >= nDash) {
4434 if ((iDash%2) == 0) {
4435 _alphaBlend(&fImage->alt.argb32[idx], &color);
4438 yy += fImage->width;
4448 if (i >= pDash[iDash]) {
4452 if (iDash >= nDash) {
4465 void TASImage::DrawDashZTLine(UInt_t x1, UInt_t y1, UInt_t x2, UInt_t y2,
4466 UInt_t nDash,
const char *tDash, UInt_t color, UInt_t thick)
4470 double x, y, xend=0, yend=0, x0, y0;
4475 dx = TMath::Abs(Int_t(x2) - Int_t(x1));
4476 dy = TMath::Abs(Int_t(y2) - Int_t(y1));
4478 double *xDash =
new double[nDash];
4479 double *yDash =
new double[nDash];
4480 double a = TMath::ATan2(dy, dx);
4481 double ac = TMath::Cos(a);
4482 double as = TMath::Sin(a);
4484 for (i = 0; i < (int)nDash; i++) {
4485 xDash[i] = tDash[i] * ac;
4486 yDash[i] = tDash[i] * as;
4490 xDash[i] = xDash[i]/2;
4491 yDash[i] = yDash[i]/2;
4493 xDash[i] = xDash[i]*2;
4494 yDash[i] = yDash[i]*2;
4511 q = (y2 - y1) * ydir;
4518 while ((x < xend) && (y < yend)) {
4522 if ((iDash%2) == 0) {
4523 DrawWideLine(TMath::Nint(x0), TMath::Nint(y0),
4524 TMath::Nint(x), TMath::Nint(y), color, thick);
4532 if (iDash >= nDash) {
4537 while ((x < xend) && (y > yend)) {
4541 if ((iDash%2) == 0) {
4542 DrawWideLine(TMath::Nint(x0), TMath::Nint(y0),
4543 TMath::Nint(x), TMath::Nint(y), color, thick);
4551 if (iDash >= nDash) {
4570 q = (x2 - x1) * xdir;
4577 while ((x < xend) && (y < yend)) {
4581 if ((iDash%2) == 0) {
4582 DrawWideLine(TMath::Nint(x0), TMath::Nint(y0),
4583 TMath::Nint(x), TMath::Nint(y), color, thick);
4591 if (iDash >= nDash) {
4596 while ((x > xend) && (y < yend)) {
4600 if ((iDash%2) == 0) {
4601 DrawWideLine(TMath::Nint(x0), TMath::Nint(y0),
4602 TMath::Nint(x), TMath::Nint(y), color, thick);
4610 if (iDash >= nDash) {
4623 void TASImage::DrawDashLine(UInt_t x1, UInt_t y1, UInt_t x2, UInt_t y2, UInt_t nDash,
4624 const char *pDash,
const char *col, UInt_t thick)
4627 if (!InitVisual()) {
4628 Warning(
"DrawDashLine",
"Visual not initiated");
4633 Warning(
"DrawDashLine",
"no image");
4637 if (!fImage->alt.argb32) {
4641 if (!fImage->alt.argb32) {
4642 Warning(
"DrawDashLine",
"Failed to get pixel array");
4646 if ((nDash < 2) || !pDash || (nDash%2)) {
4647 Warning(
"DrawDashLine",
"Wrong input parameters n=%d %ld", nDash, (Long_t)
sizeof(pDash)-1);
4651 ARGB32 color = ARGB32_White;
4652 parse_argb_color(col, &color);
4655 DrawDashVLine(x1, y1, y2, nDash, pDash, (UInt_t)color, thick);
4656 }
else if (y1 == y2) {
4657 DrawDashHLine(y1, x1, x2, nDash, pDash, (UInt_t)color, thick);
4659 if (thick < 2) DrawDashZLine(x1, y1, x2, y2, nDash, pDash, (UInt_t)color);
4660 else DrawDashZTLine(x1, y1, x2, y2, nDash, pDash, (UInt_t)color, thick);
4667 void TASImage::DrawPolyLine(UInt_t nn, TPoint *xy,
const char *col, UInt_t thick,
4668 TImage::ECoordMode mode)
4670 ARGB32 color = ARGB32_White;
4671 parse_argb_color(col, &color);
4673 Int_t x0 = xy[0].GetX();
4674 Int_t y0 = xy[0].GetY();
4678 for (UInt_t i = 1; i < nn; i++) {
4679 x = (mode == kCoordModePrevious) ? x + xy[i].GetX() : xy[i].GetX();
4680 y = (mode == kCoordModePrevious) ? y + xy[i].GetY() : xy[i].GetY();
4682 DrawLineInternal(x0, y0, x, y, (UInt_t)color, thick);
4692 void TASImage::PutPixel(Int_t x, Int_t y,
const char *col)
4694 if (!InitVisual()) {
4695 Warning(
"PutPixel",
"Visual not initiated");
4700 Warning(
"PutPixel",
"no image");
4704 if (!fImage->alt.argb32) {
4708 if (!fImage->alt.argb32) {
4709 Warning(
"PutPixel",
"Failed to get pixel array");
4714 parse_argb_color(col, &color);
4716 if ((x < 0) || (y < 0) || (x >= (
int)fImage->width) || (y >= (
int)fImage->height)) {
4717 Warning(
"PutPixel",
"Out of range width=%d x=%d, height=%d y=%d",
4718 fImage->width, x, fImage->height, y);
4721 _alphaBlend(&fImage->alt.argb32[Idx(y*fImage->width + x)], &color);
4727 void TASImage::PolyPoint(UInt_t npt, TPoint *ppt,
const char *col, TImage::ECoordMode mode)
4729 if (!InitVisual()) {
4730 Warning(
"PolyPoint",
"Visual not initiated");
4735 Warning(
"PolyPoint",
"no image");
4739 if (!fImage->alt.argb32) {
4743 if (!fImage->alt.argb32) {
4744 Warning(
"PolyPoint",
"Failed to get pixel array");
4749 Warning(
"PolyPoint",
"No points specified");
4756 parse_argb_color(col, &color);
4759 if (mode == kCoordModePrevious) {
4760 ipt =
new TPoint[npt];
4762 for (i = 0; i < npt; i++) {
4763 ipt[i].fX += ppt[i].fX;
4764 ipt[i].fY += ppt[i].fY;
4769 for (i = 0; i < npt; i++) {
4770 x = ipt ? ipt[i].fX : ppt[i].fX;
4771 y = ipt ? ipt[i].fY : ppt[i].fY;
4773 if ((x < 0) || (y < 0) || (x >= (
int)fImage->width) || (y >= (
int)fImage->height)) {
4776 _alphaBlend(&fImage->alt.argb32[Idx(y*fImage->width + x)], &color);
4787 void TASImage::DrawSegments(UInt_t nseg, Segment_t *seg,
const char *col, UInt_t thick)
4789 if (!nseg || !seg) {
4790 Warning(
"DrawSegments",
"Invalid data nseg=%d seg=0x%lx", nseg, (Long_t)seg);
4796 for (UInt_t i = 0; i < nseg; i++) {
4797 pt[0].fX = seg->fX1;
4798 pt[1].fX = seg->fX2;
4799 pt[0].fY = seg->fY1;
4800 pt[1].fY = seg->fY2;
4802 DrawPolyLine(2, pt, col, thick, kCoordModeOrigin);
4810 void TASImage::FillSpans(UInt_t npt, TPoint *ppt, UInt_t *widths,
const char *col,
4811 const char *stipple, UInt_t w, UInt_t h)
4813 if (!InitVisual()) {
4814 Warning(
"FillSpans",
"Visual not initiated");
4819 Warning(
"FillSpans",
"no image");
4823 if (!fImage->alt.argb32) {
4827 if (!fImage->alt.argb32) {
4828 Warning(
"FillSpans",
"Failed to get pixel array");
4832 if (!npt || !ppt || !widths || (stipple && (!w || !h))) {
4833 Warning(
"FillSpans",
"Invalid input data npt=%d ppt=0x%lx col=%s widths=0x%lx stipple=0x%lx w=%d h=%d",
4834 npt, (Long_t)ppt, col, (Long_t)widths, (Long_t)stipple, w, h);
4839 parse_argb_color(col, &color);
4844 for (UInt_t i = 0; i < npt; i++) {
4845 yy = ppt[i].fY*fImage->width;
4846 for (UInt_t j = 0; j < widths[i]; j++) {
4847 if ((ppt[i].fX >= (Int_t)fImage->width) || (ppt[i].fX < 0) ||
4848 (ppt[i].fY >= (Int_t)fImage->height) || (ppt[i].fY < 0))
continue;
4854 _alphaBlend(&fImage->alt.argb32[idx], &color);
4856 Int_t ii = (ppt[i].fY%h)*w + x%w;
4858 if (stipple[ii >> 3] & (1 << (ii%8))) {
4859 _alphaBlend(&fImage->alt.argb32[idx], &color);
4869 void TASImage::FillSpans(UInt_t npt, TPoint *ppt, UInt_t *widths, TImage *tile)
4871 if (!InitVisual()) {
4872 Warning(
"FillSpans",
"Visual not initiated");
4877 Warning(
"FillSpans",
"no image");
4881 if (!fImage->alt.argb32) {
4885 if (!fImage->alt.argb32) {
4886 Warning(
"FillSpans",
"Failed to get pixel array");
4890 if (!npt || !ppt || !widths || !tile) {
4891 Warning(
"FillSpans",
"Invalid input data npt=%d ppt=0x%lx widths=0x%lx tile=0x%lx",
4892 npt, (Long_t)ppt, (Long_t)widths, (Long_t)tile);
4899 UInt_t *arr = tile->GetArgbArray();
4905 for (UInt_t i = 0; i < npt; i++) {
4906 yyy = ppt[i].fY*fImage->width;
4908 for (UInt_t j = 0; j < widths[i]; j++) {
4909 if ((ppt[i].fX >= (Int_t)fImage->width) || (ppt[i].fX < 0) ||
4910 (ppt[i].fY >= (Int_t)fImage->height) || (ppt[i].fY < 0))
continue;
4913 xx = x%tile->GetWidth();
4914 yy = ppt[i].fY%tile->GetHeight();
4915 ii = yy*tile->GetWidth() + xx;
4916 _alphaBlend(&fImage->alt.argb32[idx], &arr[ii]);
4918 yyy += fImage->width;;
4925 void TASImage::CropSpans(UInt_t npt, TPoint *ppt, UInt_t *widths)
4927 if (!InitVisual()) {
4928 Warning(
"CropSpans",
"Visual not initiated");
4933 Warning(
"CropSpans",
"no image");
4937 if (!fImage->alt.argb32) {
4941 if (!fImage->alt.argb32) {
4942 Warning(
"CropSpans",
"Failed to get pixel array");
4946 if (!npt || !ppt || !widths) {
4947 Warning(
"CropSpans",
"No points specified npt=%d ppt=0x%lx widths=0x%lx", npt, (Long_t)ppt, (Long_t)widths);
4952 int y1 = ppt[npt-1].fY;
4957 UInt_t sz = fImage->width*fImage->height;
4958 UInt_t yy = y*fImage->width;
4960 for (y = 0; (int)y < y0; y++) {
4961 for (x = 0; x < fImage->width; x++) {
4963 if (idx < sz) fImage->alt.argb32[idx] = 0;
4965 yy += fImage->width;
4968 for (i = 0; i < npt; i++) {
4969 for (x = 0; (int)x < ppt[i].fX; x++) {
4970 idx = Idx(ppt[i].fY*fImage->width + x);
4971 if (idx < sz) fImage->alt.argb32[idx] = 0;
4973 for (x = ppt[i].fX + widths[i] + 1; x < fImage->width; x++) {
4974 idx = Idx(ppt[i].fY*fImage->width + x);
4975 if (idx < sz) fImage->alt.argb32[idx] = 0;
4979 yy = y1*fImage->width;
4980 for (y = y1; y < fImage->height; y++) {
4981 for (x = 0; x < fImage->width; x++) {
4983 if (idx < sz) fImage->alt.argb32[idx] = 0;
4985 yy += fImage->width;
5013 void TASImage::CopyArea(TImage *dst, Int_t xsrc, Int_t ysrc, UInt_t w, UInt_t h,
5014 Int_t xdst, Int_t ydst, Int_t gfunc, EColorChan)
5016 if (!InitVisual()) {
5017 Warning(
"CopyArea",
"Visual not initiated");
5022 Warning(
"CopyArea",
"no image");
5027 ASImage *out = ((TASImage*)dst)->GetImage();
5033 xsrc = xsrc < 0 ? 0 : xsrc;
5034 ysrc = ysrc < 0 ? 0 : ysrc;
5036 if ((xsrc >= (
int)fImage->width) || (ysrc >= (
int)fImage->height))
return;
5038 w = xsrc + w > fImage->width ? fImage->width - xsrc : w;
5039 h = ysrc + h > fImage->height ? fImage->height - ysrc : h;
5040 UInt_t yy = (ysrc + y)*fImage->width;
5042 if (!fImage->alt.argb32) {
5045 if (!out->alt.argb32) {
5047 out = ((TASImage*)dst)->GetImage();
5050 if (fImage->alt.argb32 && out->alt.argb32) {
5051 for (y = 0; y < (int)h; y++) {
5052 for (x = 0; x < (int)w; x++) {
5053 idx = Idx(yy + x + xsrc);
5054 if ((x + xdst < 0) || (ydst + y < 0) ||
5055 (x + xdst >= (
int)out->width) || (y + ydst >= (
int)out->height) )
continue;
5057 idx2 = Idx((ydst + y)*out->width + x + xdst);
5059 switch ((EGraphicsFunction)gfunc) {
5061 out->alt.argb32[idx2] = 0;
5064 out->alt.argb32[idx2] &= fImage->alt.argb32[idx];
5067 out->alt.argb32[idx2] = fImage->alt.argb32[idx] & (~out->alt.argb32[idx2]);
5069 case kGXandInverted:
5070 out->alt.argb32[idx2] &= ~fImage->alt.argb32[idx];
5075 out->alt.argb32[idx2] ^= fImage->alt.argb32[idx];
5078 out->alt.argb32[idx2] |= fImage->alt.argb32[idx];
5081 out->alt.argb32[idx2] = (~fImage->alt.argb32[idx]) & (~out->alt.argb32[idx2]);
5084 out->alt.argb32[idx2] ^= ~fImage->alt.argb32[idx];
5087 out->alt.argb32[idx2] = ~out->alt.argb32[idx2];
5090 out->alt.argb32[idx2] = fImage->alt.argb32[idx] | (~out->alt.argb32[idx2]);
5092 case kGXcopyInverted:
5093 out->alt.argb32[idx2] = ~fImage->alt.argb32[idx];
5096 out->alt.argb32[idx2] |= ~fImage->alt.argb32[idx];
5099 out->alt.argb32[idx2] = (~fImage->alt.argb32[idx]) | (~out->alt.argb32[idx2]);
5102 out->alt.argb32[idx2] = 0xFFFFFFFF;
5106 out->alt.argb32[idx2] = fImage->alt.argb32[idx];
5110 yy += fImage->width;
5127 void TASImage::DrawCellArray(Int_t x1, Int_t y1, Int_t x2, Int_t y2, Int_t nx,
5128 Int_t ny, UInt_t *ic)
5130 int i, j, ix, iy, w, h;
5132 ARGB32 color = 0xFFFFFFFF;
5135 w = TMath::Max((x2-x1)/(nx),1);
5136 h = TMath::Max((y1-y2)/(ny),1);
5139 for (i = 0; i < nx; i++) {
5141 for (j = 0; j < ny; j++) {
5142 icol = (ARGB32)ic[i + (nx*j)];
5143 if (icol != color) {
5146 FillRectangleInternal((UInt_t)color, ix, iy, w, h);
5156 UInt_t TASImage::AlphaBlend(UInt_t bot, UInt_t top)
5160 _alphaBlend(&ret, &top);
5167 const ASVisual *TASImage::GetVisual()
5175 static int GetPolyYBounds(TPoint *pts,
int n,
int *by,
int *ty)
5179 TPoint *ptsStart = pts;
5182 ymin = ymax = (pts++)->fY;
5185 if (pts->fY < ymin) {
5189 if (pts->fY > ymax) {
5197 return (ptMin - ptsStart);
5204 Bool_t TASImage::GetPolygonSpans(UInt_t npt, TPoint *ppt, UInt_t *nspans,
5205 TPoint **outPoint, UInt_t **outWidth)
5213 int mr = 0, m1r = 0;
5214 int incr1l = 0, incr2l = 0;
5215 int incr1r = 0, incr2r = 0;
5220 int nextleft, nextright;
5223 TPoint *firstPoint=0;
5224 UInt_t *firstWidth=0;
5232 if (!InitVisual()) {
5233 Warning(
"GetPolygonSpans",
"Visual not initiated");
5238 Warning(
"GetPolygonSpans",
"no image");
5242 if (!fImage->alt.argb32) {
5246 if (!fImage->alt.argb32) {
5247 Warning(
"GetPolygonSpans",
"Failed to get pixel array");
5251 if ((npt < 3) || !ppt) {
5252 Warning(
"GetPolygonSpans",
"No points specified npt=%d ppt=0x%lx", npt, (Long_t)ppt);
5258 imin = GetPolyYBounds(ppt, npt, &ymin, &ymax);
5260 dy = ymax - ymin + 1;
5261 if ((npt < 3) || (dy < 0))
return kFALSE;
5263 ptsOut = firstPoint =
new TPoint[dy];
5264 width = firstWidth =
new UInt_t[dy];
5267 nextleft = nextright = imin;
5268 y = ppt[nextleft].fY;
5273 if (ppt[nextleft].fY == y) {
5279 if (nextleft >= (
int)npt) {
5285 BRESINITPGON(ppt[nextleft].fY - ppt[left].fY,
5286 ppt[left].fX, ppt[nextleft].fX,
5287 xl, dl, ml, m1l, incr1l, incr2l);
5291 if (ppt[nextright].fY == y) {
5297 if (nextright < 0) {
5303 BRESINITPGON(ppt[nextright].fY - ppt[right].fY,
5304 ppt[right].fX, ppt[nextright].fX,
5305 xr, dr, mr, m1r, incr1r, incr2r);
5310 i = TMath::Min(ppt[nextleft].fY, ppt[nextright].fY) - y;
5314 delete [] firstWidth;
5315 delete [] firstPoint;
5324 *(width++) = xr - xl;
5325 (ptsOut++)->fX = xl;
5327 *(width++) = xl - xr;
5328 (ptsOut++)->fX = xr;
5333 BRESINCRPGON(dl, xl, ml, m1l, incr1l, incr2l);
5334 BRESINCRPGON(dr, xr, mr, m1r, incr1r, incr2r);
5336 }
while (y != ymax);
5338 *nspans = UInt_t(ptsOut - firstPoint);
5339 *outPoint = firstPoint;
5340 *outWidth = firstWidth;
5349 void TASImage::FillPolygon(UInt_t npt, TPoint *ppt,
const char *col,
5350 const char *stipple, UInt_t w, UInt_t h)
5353 TPoint *firstPoint = 0;
5354 UInt_t *firstWidth = 0;
5356 Bool_t del = GetPolygonSpans(npt, ppt, &nspans, &firstPoint, &firstWidth);
5357 ARGB32 color = ARGB32_White;
5358 parse_argb_color(col, &color);
5361 if (!stipple && ((color & 0xff000000)==0xff000000)) {
5362 FillSpansInternal(nspans, firstPoint, firstWidth, color);
5364 FillSpans(nspans, firstPoint, firstWidth, col, stipple, w, h);
5368 delete [] firstWidth;
5369 delete [] firstPoint;
5372 if (firstWidth)
delete [] firstWidth;
5373 if (firstPoint)
delete [] firstPoint;
5381 void TASImage::FillPolygon(UInt_t npt, TPoint *ppt, TImage *tile)
5384 TPoint *firstPoint = 0;
5385 UInt_t *firstWidth = 0;
5387 Bool_t del = GetPolygonSpans(npt, ppt, &nspans, &firstPoint, &firstWidth);
5390 FillSpans(nspans, firstPoint, firstWidth, tile);
5393 delete [] firstWidth;
5394 delete [] firstPoint;
5397 if (firstWidth)
delete [] firstWidth;
5398 if (firstPoint)
delete [] firstPoint;
5405 void TASImage::CropPolygon(UInt_t npt, TPoint *ppt)
5408 TPoint *firstPoint = 0;
5409 UInt_t *firstWidth = 0;
5411 Bool_t del = GetPolygonSpans(npt, ppt, &nspans, &firstPoint, &firstWidth);
5414 CropSpans(nspans, firstPoint, firstWidth);
5417 delete [] firstWidth;
5418 delete [] firstPoint;
5421 if (firstWidth)
delete [] firstWidth;
5422 if (firstPoint)
delete [] firstPoint;
5426 static const UInt_t NUMPTSTOBUFFER = 512;
5431 void TASImage::DrawFillArea(UInt_t count, TPoint *ptsIn,
const char *col,
5432 const char *stipple, UInt_t w, UInt_t h)
5434 if (!InitVisual()) {
5435 Warning(
"DrawFillArea",
"Visual not initiated");
5440 Warning(
"DrawFillArea",
"no image");
5444 if (!fImage->alt.argb32) {
5448 if (!fImage->alt.argb32) {
5449 Warning(
"DrawFillArea",
"Failed to get pixel array");
5453 if ((count < 3) || !ptsIn) {
5454 Warning(
"DrawFillArea",
"No points specified npt=%d ppt=0x%lx", count, (Long_t)ptsIn);
5459 FillPolygon(count, ptsIn, col, stipple, w, h);
5463 ARGB32 color = ARGB32_White;
5464 parse_argb_color(col, &color);
5466 EdgeTableEntry *pAET;
5473 TPoint firstPoint[NUMPTSTOBUFFER];
5474 UInt_t firstWidth[NUMPTSTOBUFFER];
5475 EdgeTableEntry *pPrevAET;
5478 EdgeTableEntry *pETEs;
5479 ScanLineListBlock SLLBlock;
5482 static const UInt_t gEdgeTableEntryCacheSize = 200;
5483 static EdgeTableEntry gEdgeTableEntryCache[gEdgeTableEntryCacheSize];
5485 if (count < gEdgeTableEntryCacheSize) {
5486 pETEs = (EdgeTableEntry*)&gEdgeTableEntryCache;
5489 pETEs =
new EdgeTableEntry[count];
5493 ptsOut = firstPoint;
5495 CreateETandAET(count, ptsIn, &ET, &AET, pETEs, &SLLBlock);
5496 pSLL = ET.scanlines.next;
5498 for (y = ET.ymin; y < ET.ymax; y++) {
5499 if (pSLL && y == pSLL->scanline) {
5500 loadAET(&AET, pSLL->edgelist);
5507 ptsOut->fX = pAET->bres.minor_axis;
5512 *width++ = pAET->next->bres.minor_axis - pAET->bres.minor_axis;
5514 if (nPts == NUMPTSTOBUFFER) {
5515 if (!stipple && ((color & 0xff000000)==0xff000000)) {
5516 FillSpansInternal(nPts, firstPoint, firstWidth, color);
5518 FillSpans(nPts, firstPoint, firstWidth, col, stipple, w, h);
5520 ptsOut = firstPoint;
5524 EVALUATEEDGEEVENODD(pAET, pPrevAET, y)
5525 EVALUATEEDGEEVENODD(pAET, pPrevAET, y)
5527 InsertionSort(&AET);
5531 if (!stipple && ((color & 0xff000000)==0xff000000)) {
5532 FillSpansInternal(nPts, firstPoint, firstWidth, color);
5534 FillSpans(nPts, firstPoint, firstWidth, col, stipple, w, h);
5538 if (del)
delete [] pETEs;
5539 FreeStorage(SLLBlock.next);
5545 void TASImage::DrawFillArea(UInt_t count, TPoint *ptsIn, TImage *tile)
5547 if (!InitVisual()) {
5548 Warning(
"DrawFillArea",
"Visual not initiated");
5553 Warning(
"DrawFillArea",
"no image");
5557 if (!fImage->alt.argb32) {
5561 if (!fImage->alt.argb32) {
5562 Warning(
"DrawFillArea",
"Failed to get pixel array");
5566 if ((count < 3) || !ptsIn) {
5567 Warning(
"DrawFillArea",
"No points specified npt=%d ppt=0x%lx", count, (Long_t)ptsIn);
5572 FillPolygon(count, ptsIn, tile);
5576 EdgeTableEntry *pAET;
5583 TPoint firstPoint[NUMPTSTOBUFFER];
5584 UInt_t firstWidth[NUMPTSTOBUFFER];
5585 EdgeTableEntry *pPrevAET;
5588 EdgeTableEntry *pETEs;
5589 ScanLineListBlock SLLBlock;
5591 pETEs =
new EdgeTableEntry[count];
5593 ptsOut = firstPoint;
5595 CreateETandAET(count, ptsIn, &ET, &AET, pETEs, &SLLBlock);
5596 pSLL = ET.scanlines.next;
5598 for (y = ET.ymin; y < ET.ymax; y++) {
5599 if (pSLL && y == pSLL->scanline) {
5600 loadAET(&AET, pSLL->edgelist);
5607 ptsOut->fX = pAET->bres.minor_axis;
5612 *width++ = pAET->next->bres.minor_axis - pAET->bres.minor_axis;
5614 if (nPts == NUMPTSTOBUFFER) {
5615 FillSpans(nPts, firstPoint, firstWidth, tile);
5616 ptsOut = firstPoint;
5620 EVALUATEEDGEEVENODD(pAET, pPrevAET, y)
5621 EVALUATEEDGEEVENODD(pAET, pPrevAET, y)
5623 InsertionSort(&AET);
5625 FillSpans(nPts, firstPoint, firstWidth, tile);
5628 FreeStorage(SLLBlock.next);
5634 static ASDrawContext *create_draw_context_argb32(ASImage *im, ASDrawTool *brush)
5636 ASDrawContext *ctx =
new ASDrawContext;
5638 ctx->canvas_width = im->width;
5639 ctx->canvas_height = im->height;
5640 ctx->canvas = im->alt.argb32;
5641 ctx->scratch_canvas = 0;
5643 ctx->flags = ASDrawCTX_CanvasIsARGB;
5644 asim_set_custom_brush_colored( ctx, brush);
5651 static void destroy_asdraw_context32( ASDrawContext *ctx )
5654 if (ctx->scratch_canvas) free(ctx->scratch_canvas);
5659 static const UInt_t kBrushCacheSize = 20;
5660 static CARD32 gBrushCache[kBrushCacheSize*kBrushCacheSize];
5665 void TASImage::DrawWideLine(UInt_t x1, UInt_t y1, UInt_t x2, UInt_t y2,
5666 UInt_t color, UInt_t thick)
5668 Int_t sz = thick*thick;
5670 Bool_t use_cache = thick < kBrushCacheSize;
5673 matrix = gBrushCache;
5675 matrix =
new CARD32[sz];
5678 for (
int i = 0; i < sz; i++) {
5679 matrix[i] = (CARD32)color;
5683 brush.matrix = matrix;
5684 brush.width = thick;
5685 brush.height = thick;
5686 brush.center_y = brush.center_x = thick/2;
5695 if (xx1 == fImage->width) --xx1;
5696 if (yy1 == fImage->height) --yy1;
5697 if (xx2 == fImage->width) --xx2;
5698 if (yy2 == fImage->height) --yy2;
5699 ASDrawContext *ctx = create_draw_context_argb32(fImage, &brush);
5700 asim_move_to(ctx, xx1, yy1);
5701 asim_line_to(ctx, xx2, yy2);
5706 destroy_asdraw_context32(ctx);
5712 void TASImage::DrawGlyph(
void *bitmap, UInt_t color, Int_t bx, Int_t by)
5714 static UInt_t col[5];
5715 Int_t x, y, yy, y0, xx;
5716 Bool_t has_alpha = (color & 0xff000000) != 0xff000000;
5720 FT_Bitmap *source = (FT_Bitmap*)bitmap;
5721 UChar_t d = 0, *s = source->buffer;
5723 Int_t dots = Int_t(source->width * source->rows);
5727 yy = y0 = by > 0 ? by * fImage->width : 0;
5728 for (y = 0; y < (int) source->rows; y++) {
5730 if ((byy >= (
int)fImage->height) || (byy <0))
continue;
5732 for (x = 0; x < (int) source->width; x++) {
5734 if ((bxx >= (
int)fImage->width) || (bxx < 0))
continue;
5736 idx = Idx(bxx + yy);
5737 r += ((fImage->alt.argb32[idx] & 0xff0000) >> 16);
5738 g += ((fImage->alt.argb32[idx] & 0x00ff00) >> 8);
5739 b += (fImage->alt.argb32[idx] & 0x0000ff);
5741 yy += fImage->width;
5749 col[0] = (r << 16) + (g << 8) + b;
5751 Int_t col4r = (col[4] & 0xff0000) >> 16;
5752 Int_t col4g = (col[4] & 0x00ff00) >> 8;
5753 Int_t col4b = (col[4] & 0x0000ff);
5756 for (x = 3; x > 0; x--) {
5758 Int_t colxr = (col4r*x + r*xx) >> 2;
5759 Int_t colxg = (col4g*x + g*xx) >> 2;
5760 Int_t colxb = (col4b*x + b*xx) >> 2;
5761 col[x] = (colxr << 16) + (colxg << 8) + colxb;
5767 Int_t clipx1=0, clipx2=0, clipy1=0, clipy2=0;
5768 Bool_t noClip = kTRUE;
5771 Float_t is = gStyle->GetImageScaling();
5772 clipx1 = gPad->XtoAbsPixel(gPad->GetX1())*is;
5773 clipx2 = gPad->XtoAbsPixel(gPad->GetX2())*is;
5774 clipy1 = gPad->YtoAbsPixel(gPad->GetY1())*is;
5775 clipy2 = gPad->YtoAbsPixel(gPad->GetY2())*is;
5779 for (y = 0; y < (int) source->rows; y++) {
5782 for (x = 0; x < (int) source->width; x++) {
5786 d = ((d + 10) * 5) >> 8;
5790 if ( noClip || ((x < (
int) source->width) &&
5791 (bxx < (
int)clipx2) && (bxx >= (
int)clipx1) &&
5792 (byy >= (
int)clipy2) && (byy < (
int)clipy1) )) {
5793 idx = Idx(bxx + yy);
5794 acolor = (ARGB32)col[d];
5796 _alphaBlend(&fImage->alt.argb32[idx], &acolor);
5798 fImage->alt.argb32[idx] = acolor;
5803 yy += fImage->width;
5810 void TASImage::DrawText(TText *text, Int_t x, Int_t y)
5813 if (!fImage)
return;
5816 if (!InitVisual()) {
5817 Warning(
"DrawText",
"Visual not initiated");
5821 if (!fImage->alt.argb32) {
5825 if (!TTF::IsInitialized()) TTF::Init();
5828 TTF::SetTextFont(text->GetTextFont());
5830 Int_t wh = gPad->XtoPixel(gPad->GetX2());
5831 Int_t hh = gPad->YtoPixel(gPad->GetY1());
5836 ttfsize = text->GetTextSize()*wh;
5838 ttfsize = text->GetTextSize()*hh;
5840 TTF::SetTextSize(ttfsize*kScale);
5843 TTF::SetRotationMatrix(text->GetTextAngle());
5846 const wchar_t *wcsTitle =
reinterpret_cast<const wchar_t *
>(text->GetWcsTitle());
5847 if (wcsTitle != NULL) {
5848 TTF::PrepareString(wcsTitle);
5850 TTF::PrepareString(text->GetTitle());
5852 TTF::LayoutGlyphs();
5855 TColor *col = gROOT->GetColor(text->GetTextColor());
5857 col = gROOT->GetColor(1);
5860 ARGB32 color = ARGB32_White;
5861 parse_argb_color(col->AsHexString(), &color);
5865 Int_t txalh = text->GetTextAlign()/10;
5866 Int_t txalv = text->GetTextAlign()%10;
5914 if (align == 1 || align == 2 || align == 3) {
5915 ftal.y = TTF::GetAscent();
5916 }
else if (align == 4 || align == 5 || align == 6) {
5917 ftal.y = TTF::GetAscent()/2;
5923 if (align == 3 || align == 6 || align == 9) {
5924 ftal.x = TTF::GetWidth();
5925 }
else if (align == 2 || align == 5 || align == 8) {
5926 ftal.x = TTF::GetWidth()/2;
5931 FT_Vector_Transform(&ftal, TTF::GetRotMatrix());
5932 ftal.x = (ftal.x >> 6);
5933 ftal.y = (ftal.y >> 6);
5935 TTF::TTGlyph *glyph = TTF::GetGlyphs();
5937 for (
int n = 0; n < TTF::GetNumGlyphs(); n++, glyph++) {
5938 if (FT_Glyph_To_Bitmap(&glyph->fImage, ft_render_mode_normal, 0, 1 ))
continue;
5940 FT_BitmapGlyph bitmap = (FT_BitmapGlyph)glyph->fImage;
5941 FT_Bitmap *source = &bitmap->bitmap;
5943 Int_t bx = x - ftal.x + bitmap->left;
5944 Int_t by = y + ftal.y - bitmap->top;
5946 DrawGlyph(source, color, bx, by);
5953 void TASImage::DrawTextTTF(Int_t x, Int_t y,
const char *text, Int_t size,
5954 UInt_t color,
const char *font_name, Float_t angle)
5956 if (!TTF::IsInitialized()) TTF::Init();
5958 TTF::SetTextFont(font_name);
5959 TTF::SetTextSize(size);
5960 TTF::SetRotationMatrix(angle);
5961 TTF::PrepareString(text);
5962 TTF::LayoutGlyphs();
5964 TTF::TTGlyph *glyph = TTF::GetGlyphs();
5968 Int_t Yoff = 0;
if (TTF::GetBox().yMin < 0) Yoff = -TTF::GetBox().yMin;
5969 Int_t h = TTF::GetBox().yMax + Yoff;
5971 for (
int n = 0; n < TTF::GetNumGlyphs(); n++, glyph++) {
5972 if (FT_Glyph_To_Bitmap(&glyph->fImage, ft_render_mode_normal, 0, 1 ))
continue;
5974 FT_BitmapGlyph bitmap = (FT_BitmapGlyph)glyph->fImage;
5975 FT_Bitmap *source = &bitmap->bitmap;
5977 Int_t bx = x + bitmap->left;
5978 Int_t by = y + h - bitmap->top;
5979 DrawGlyph(source, color, bx, by);
5988 void TASImage::GetImageBuffer(
char **buffer,
int *size, EImageFileTypes type)
5990 static ASImageExportParams params;
5991 Bool_t ret = kFALSE;
5994 ASImage *img = fScaledImage ? fScaledImage->fImage : fImage;
6000 ret = ASImage2xpmRawBuff(img, (CARD8 **)buffer, size, 0);
6003 ret = ASImage2PNGBuff(img, (CARD8 **)buffer, size, ¶ms);
6040 Bool_t TASImage::SetImageBuffer(
char **buffer, EImageFileTypes type)
6044 static ASImageImportParams params;
6048 params.filter = SCL_DO_ALL;
6050 params.gamma_table = 0;
6051 params.compression = 0;
6052 params.format = ASA_ASImage;
6053 params.search_path = 0;
6054 params.subimage = 0;
6059 char *ptr = buffer[0];
6060 while (isspace((
int)*ptr)) ++ptr;
6062 fImage = xpm_data2ASImage((
const char**)buffer, ¶ms);
6064 fImage = xpmRawBuff2ASImage((
const char*)*buffer, ¶ms);
6069 fImage = PNGBuff2ASimage((CARD8 *)*buffer, ¶ms);
6077 if (fName.IsNull()) {
6078 fName.Form(
"img_%dx%d.%d", fImage->width, fImage->height, gRandom->Integer(1000));
6087 void TASImage::CreateThumbnail()
6096 if (!InitVisual()) {
6100 static char *buf = 0;
6104 if (fImage->width > fImage->height) {
6106 h = (fImage->height*sz)/fImage->width;
6109 w = (fImage->width*sz)/fImage->height;
6115 img = scale_asimage(fgVisual, fImage, w, h, ASA_ASImage,
6116 GetImageCompression(), GetImageQuality());
6122 ASImage *rendered_im;
6123 ASImageLayer layers[2];
6124 init_image_layers(&(layers[0]), 2);
6126 layers[0].dst_x = 0;
6127 layers[0].dst_y = 0;
6128 layers[0].clip_width = img->width;
6129 layers[0].clip_height = img->height;
6130 layers[0].bevel = 0;
6132 layers[1].dst_x = 0;
6133 layers[1].dst_y = 0;
6134 layers[1].clip_width = img->width;
6135 layers[1].clip_height = img->height;
6136 layers[1].merge_scanlines = blend_scanlines_name2func(
"tint");
6137 rendered_im = merge_layers(fgVisual, &(layers[0]), 2, img->width, img->height,
6138 ASA_ASImage, GetImageCompression(), GetImageQuality());
6139 destroy_asimage(&img);
6143 ASImage *padimg = 0;
6148 padimg = pad_asimage(fgVisual, img, 0, d, sz, sz, 0x00ffffff,
6149 ASA_ASImage, GetImageCompression(), GetImageQuality());
6152 padimg = pad_asimage(fgVisual, img, d, 0, sz, sz, 0x00ffffff,
6153 ASA_ASImage, GetImageCompression(), GetImageQuality());
6157 destroy_asimage(&img);
6162 ASImage2xpmRawBuff(padimg, (CARD8 **)ptr, &size, 0);
6165 destroy_asimage(&padimg);
6171 void TASImage::Streamer(TBuffer &b)
6173 Bool_t image_type = 0;
6179 if (b.IsReading()) {
6180 Version_t version = b.ReadVersion(&R__s, &R__c);
6185 if ( version == 1 ) {
6186 Int_t fileVersion = b.GetVersionOwner();
6187 if (fileVersion > 0 && fileVersion < 50000 ) {
6188 TImage::Streamer(b);
6195 if ( fileVersion < 40200 ) {
6198 fZoomUpdate = zoomUpdate;
6204 fPaintMode = paintMode;
6206 b.CheckByteCount(R__s, R__c, TASImage::IsA());
6211 TNamed::Streamer(b);
6214 if (image_type != 0) {
6216 buffer =
new char[size];
6217 b.ReadFastArray(buffer, size);
6218 SetImageBuffer(&buffer, TImage::kPng);
6221 TAttImage::Streamer(b);
6225 Double_t *vec =
new Double_t[size];
6226 b.ReadFastArray(vec, size);
6227 SetImage(vec, w, h, &fPalette);
6230 b.CheckByteCount(R__s, R__c, TASImage::IsA());
6235 R__c = b.WriteVersion(TASImage::IsA(), kTRUE);
6237 if (fName.IsNull()) {
6238 fName.Form(
"img_%dx%d.%d", fImage->width, fImage->height, gRandom->Integer(1000));
6240 TNamed::Streamer(b);
6242 image_type = fImage->alt.vector ? 0 : 1;
6245 if (image_type != 0) {
6246 GetImageBuffer(&buffer, &size, TImage::kPng);
6248 b.WriteFastArray(buffer, size);
6251 TAttImage::Streamer(b);
6253 b << fImage->height;
6254 b.WriteFastArray(fImage->alt.vector, fImage->width*fImage->height);
6256 b.SetByteCount(R__c, kTRUE);
6263 void TASImage::Browse(TBrowser *)
6265 if (fImage->alt.vector) {
6276 const char *TASImage::GetTitle()
const
6278 if (!gDirectory || !gDirectory->IsWritable()) {
6282 TASImage *mutble = (TASImage *)
this;
6284 if (fTitle.IsNull()) {
6285 mutble->SetTitle(fName.Data());
6288 return fTitle.Data();
6294 void TASImage::SetTitle(
const char *title)
6296 if (fTitle.IsNull()) {
6300 if (fTitle.IsNull()) {
6304 int start = fTitle.Index(
"/*") + 3;
6305 int stop = fTitle.Index(
"*/") - 1;
6307 if ((start > 0) && (stop - start > 0)) {
6308 fTitle.Replace(start, stop - start, title);
6315 void TASImage::DrawCubeBezier(Int_t x1, Int_t y1, Int_t x2, Int_t y2,
6316 Int_t x3, Int_t y3,
const char *col, UInt_t thick)
6318 Int_t sz = thick*thick;
6320 Bool_t use_cache = thick < kBrushCacheSize;
6322 ARGB32 color = ARGB32_White;
6323 parse_argb_color(col, &color);
6326 matrix = gBrushCache;
6328 matrix =
new CARD32[sz];
6331 for (
int i = 0; i < sz; i++) {
6332 matrix[i] = (CARD32)color;
6336 brush.matrix = matrix;
6337 brush.width = thick;
6338 brush.height = thick;
6339 brush.center_y = brush.center_x = thick/2;
6341 ASDrawContext *ctx = 0;
6343 ctx = create_draw_context_argb32(fImage, &brush);
6344 asim_cube_bezier(ctx, x1, y1, x2, y2, x3, y3);
6349 destroy_asdraw_context32(ctx);
6356 void TASImage::DrawStraightEllips(Int_t x, Int_t y, Int_t rx, Int_t ry,
6357 const char *col, Int_t thick)
6359 thick = !thick ? 1 : thick;
6360 Int_t sz = thick*thick;
6362 Bool_t use_cache = (thick > 0) && ((UInt_t)thick < kBrushCacheSize);
6364 ARGB32 color = ARGB32_White;
6365 parse_argb_color(col, &color);
6368 matrix = gBrushCache;
6370 matrix =
new CARD32[sz];
6373 for (
int i = 0; i < sz; i++) {
6374 matrix[i] = (CARD32)color;
6378 brush.matrix = matrix;
6379 brush.width = thick > 0 ? thick : 1;
6380 brush.height = thick > 0 ? thick : 1;
6381 brush.center_y = brush.center_x = thick > 0 ? thick/2 : 0;
6383 ASDrawContext *ctx = create_draw_context_argb32(fImage, &brush);
6384 asim_straight_ellips(ctx, x, y, rx, ry, thick < 0);
6389 destroy_asdraw_context32(ctx);
6396 void TASImage::DrawCircle(Int_t x, Int_t y, Int_t r,
const char *col, Int_t thick)
6398 thick = !thick ? 1 : thick;
6399 Int_t sz = thick*thick;
6401 Bool_t use_cache = (thick > 0) && ((UInt_t)thick < kBrushCacheSize);
6403 ARGB32 color = ARGB32_White;
6404 parse_argb_color(col, &color);
6408 matrix = gBrushCache;
6410 matrix =
new CARD32[sz];
6413 for (
int i = 0; i < sz; i++) {
6414 matrix[i] = (CARD32)color;
6418 brush.matrix = matrix;
6419 brush.height = brush.width = thick > 0 ? thick : 1;
6420 brush.center_y = brush.center_x = thick > 0 ? thick/2 : 0;
6422 ASDrawContext *ctx = create_draw_context_argb32(fImage, &brush);
6423 asim_circle(ctx, x, y, r, thick < 0);
6429 destroy_asdraw_context32(ctx);
6436 void TASImage::DrawEllips(Int_t x, Int_t y, Int_t rx, Int_t ry, Int_t angle,
6437 const char *col, Int_t thick)
6439 thick = !thick ? 1 : thick;
6440 Int_t sz = thick*thick;
6442 Bool_t use_cache = (thick > 0) && ((UInt_t)thick < kBrushCacheSize);
6444 ARGB32 color = ARGB32_White;
6445 parse_argb_color(col, &color);
6448 matrix = gBrushCache;
6450 matrix =
new CARD32[sz];
6453 for (
int i = 0; i < sz; i++) {
6454 matrix[i] = (CARD32)color;
6458 brush.matrix = matrix;
6459 brush.width = thick > 0 ? thick : 1;
6460 brush.height = thick > 0 ? thick : 1;
6461 brush.center_y = brush.center_x = thick > 0 ? thick/2 : 0;
6463 ASDrawContext *ctx = create_draw_context_argb32(fImage, &brush);
6464 asim_ellips(ctx, x, y, rx, ry, angle, thick < 0);
6469 destroy_asdraw_context32(ctx);
6476 void TASImage::DrawEllips2(Int_t x, Int_t y, Int_t rx, Int_t ry, Int_t angle,
6477 const char *col, Int_t thick)
6479 thick = !thick ? 1 : thick;
6480 Int_t sz = thick*thick;
6482 Bool_t use_cache = (thick > 0) && ((UInt_t)thick < kBrushCacheSize);
6484 ARGB32 color = ARGB32_White;
6485 parse_argb_color(col, &color);
6488 matrix = gBrushCache;
6490 matrix =
new CARD32[sz];
6493 for (
int i = 0; i < sz; i++) {
6494 matrix[i] = (CARD32)color;
6498 brush.matrix = matrix;
6499 brush.width = thick > 0 ? thick : 1;
6500 brush.height = thick > 0 ? thick : 1;
6501 brush.center_y = brush.center_x = thick > 0 ? thick/2 : 0;
6503 ASDrawContext *ctx = create_draw_context_argb32(fImage, &brush);
6504 asim_ellips2(ctx, x, y, rx, ry, angle, thick < 0);
6509 destroy_asdraw_context32(ctx);
6515 void TASImage::FloodFill(Int_t , Int_t ,
const char * ,
6516 const char * ,
const char * )
6523 void TASImage::Gray(Bool_t on)
6525 if (fIsGray == on) {
6530 Warning(
"Gray",
"Image not initiated");
6534 if (!InitVisual()) {
6535 Warning(
"Gray",
"Visual not initiated");
6539 if (!fGrayImage && !on) {
6543 delete fScaledImage;
6548 fImage = fGrayImage;
6556 UInt_t l, r, g, b, idx;
6560 if (fImage->alt.argb32) {
6561 fGrayImage = tile_asimage(fgVisual, fImage, 0, 0, fImage->width, fImage->height,
6562 0, ASA_ARGB32, 0, ASIMAGE_QUALITY_DEFAULT);
6564 for (i = 0; i < fImage->height; i++) {
6565 for (j = 0; j < fImage->width; j++) {
6568 r = ((fImage->alt.argb32[idx] & 0xff0000) >> 16);
6569 g = ((fImage->alt.argb32[idx] & 0x00ff00) >> 8);
6570 b = (fImage->alt.argb32[idx] & 0x0000ff);
6571 l = (57*r + 181*g + 18*b)/256;
6572 fGrayImage->alt.argb32[idx] = (l << 16) + (l << 8) + l;
6577 fGrayImage = create_asimage(fImage->width, fImage->height, 0);
6579 ASImageDecoder *imdec = start_image_decoding(fgVisual, fImage, SCL_DO_ALL,
6580 0, 0, fImage->width, fImage->height, 0);
6588 ASImageOutput *imout = start_image_output(fgVisual, fGrayImage, ASA_ASImage,
6589 GetImageCompression(), GetImageQuality());
6591 Warning(
"ToGray",
"Failed to start image output");
6592 delete fScaledImage;
6598 CARD32 *aa = imdec->buffer.alpha;
6599 CARD32 *rr = imdec->buffer.red;
6600 CARD32 *gg = imdec->buffer.green;
6601 CARD32 *bb = imdec->buffer.blue;
6604 prepare_scanline(fImage->width, 0, &result, fgVisual->BGR_mode);
6606 for (i = 0; i < fImage->height; i++) {
6607 imdec->decode_image_scanline(imdec);
6608 result.flags = imdec->buffer.flags;
6609 result.back_color = imdec->buffer.back_color;
6611 for (j = 0; j < fImage->width; j++) {
6612 l = (57*rr[j] + 181*gg[j]+ 18*bb[j])/256;
6613 result.alpha[j] = aa[j];
6615 result.green[j] = l;
6618 imout->output_image_scanline(imout, &result, 1);
6621 stop_image_decoding(&imdec);
6622 stop_image_output(&imout);
6629 fImage = fGrayImage;
6637 void TASImage::FromWindow(Drawable_t wid, Int_t x, Int_t y, UInt_t w, UInt_t h)
6645 gVirtualX->Update(1);
6648 gSystem->ProcessEvents();
6650 gSystem->ProcessEvents();
6654 gVirtualX->GetWindowSize(wid, xy, xy, w, h);
6657 if ((x >= (Int_t)w) || (y >= (Int_t)h)) {
6661 if (!InitVisual()) {
6662 Warning(
"FromWindow",
"Visual not initiated");
6667 delete fScaledImage;
6670 static int x11 = -1;
6671 if (x11 < 0) x11 = gVirtualX->InheritsFrom(
"TGX11");
6674 fImage = pixmap2asimage(fgVisual, wid, x, y, w, h, kAllPlanes, 0, 0);
6676 unsigned char *bits = gVirtualX->GetColorBits(wid, 0, 0, w, h);
6681 fImage = bitmap2asimage(bits, w, h, 0, 0);
6689 void TASImage::FromGLBuffer(UChar_t* buf, UInt_t w, UInt_t h)
6692 delete fScaledImage;
6695 UChar_t* xx =
new UChar_t[4*w];
6696 for (UInt_t i = 0; i < h/2; ++i) {
6697 memcpy(xx, buf + 4*w*i, 4*w);
6698 memcpy(buf + 4*w*i, buf + 4*w*(h-i-1), 4*w);
6699 memcpy(buf + 4*w*(h-i-1), xx, 4*w);
6703 fImage = bitmap2asimage(buf, w, h, 0, 0);
6710 void TASImage::SetPaletteEnabled(Bool_t on)
6716 if (!fImage->alt.vector && on) {
6719 fPaletteEnabled = on;
6722 Double_t left = gPad->GetLeftMargin();
6723 Double_t right = gPad->GetRightMargin();
6724 Double_t top = gPad->GetTopMargin();
6725 Double_t bottom = gPad->GetBottomMargin();
6727 gPad->Range(-left / (1.0 - left - right),
6728 -bottom / (1.0 - top - bottom),
6729 1 + right / (1.0 - left - right),
6730 1 + top / ( 1.0 - top - bottom));
6731 gPad->RangeAxis(0, 0, 1, 1);
6739 void TASImage::SavePrimitive(std::ostream &out, Option_t * )
6744 UInt_t w = GetWidth();
6745 UInt_t h = GetHeight();
6749 Double_t scale = 500./GetWidth();
6750 h = TMath::Nint(GetHeight()*scale);
6754 GetImageBuffer(&buf, &sz, TImage::kXpm);
6756 TString name = GetName();
6757 name.ReplaceAll(
".",
"_");
6762 str.ReplaceAll(
"static",
"const");
6763 TString xpm =
"xpm_";
6766 str.ReplaceAll(
"asxpm", xpm.Data());
6767 out << std::endl << str << std::endl << std::endl;
6770 out << xpm <<
"_img = TImage::Create();" << std::endl;
6771 out <<
" " << xpm <<
"_img->SetImageBuffer( (char **)" << xpm <<
", TImage::kXpm);" << std::endl;
6772 out <<
" " << xpm <<
"_img->Draw();" << std::endl;
6783 Bool_t TASImage::SetJpegDpi(
const char *name, UInt_t set)
6785 static char buf[32];
6786 FILE *fp = fopen(name,
"rb+");
6789 printf(
"file %s : failed to open\n", name);
6793 if (!fread(buf, 1, 20, fp)) {
6798 char dpi1 = (set & 0xffff) >> 8;
6799 char dpi2 = set & 0xff;
6804 for (i = 0; i < 20; i++) {
6805 if ((buf[i] == 0x4a) && (buf[i+1] == 0x46) && (buf[i+2] == 0x49) &&
6806 (buf[i+3] == 0x46) && (buf[i+4] == 0x00) ) {
6812 if (i == 20 || dpi+4 >= 20) {
6814 printf(
"file %s : wrong JPEG format\n", name);
6821 buf[dpi + 1] = dpi1;
6822 buf[dpi + 2] = dpi2;
6825 buf[dpi + 3] = dpi1;
6826 buf[dpi + 4] = dpi2;
6829 fwrite(buf, 1, 20, fp);
6839 Int_t TASImage::Idx(Int_t idx)
6842 return TMath::Min(idx,(Int_t)(fImage->width*fImage->height));