ROOT  6.06/09
Reference Guide
TASImage.cxx
Go to the documentation of this file.
1 // @(#)root/asimage:$Id: TASImage.cxx,v 1.54 2006/03/13 15:18:56 rdm E
2 // Author: Fons Rademakers, Reiner Rohlfs, Valeriy Onuchin 28/11/2001
3 
4 /*************************************************************************
5  * Copyright (C) 1995-2001, Rene Brun, Fons Rademakers and Reiner Rohlfs *
6  * All rights reserved. *
7  * *
8  * For the licensing terms see $ROOTSYS/LICENSE. *
9  * For the list of contributors see $ROOTSYS/README/CREDITS. *
10  *************************************************************************/
11 
12 /**************************************************************************
13  * Some parts of this source are based on libAfterImage 2.00.00
14  * (http://www.afterstep.org/)
15  *
16  * Copyright (c) 2002 Sasha Vasko <sasha@aftercode.net>
17  * Copyright (c) 1998, 1999 Ethan Fischer <allanon@crystaltokyo.com>
18  *
19  * This program is free software; you can redistribute it and/or modify
20  * it under the terms of the GNU Library General Public License as
21  * published by the Free Software Foundation; either version 2 of the
22  * License, or (at your option) any later version.
23  *
24  * This program is distributed in the hope that it will be useful,
25  * but WITHOUT ANY WARRANTY; without even the implied warranty of
26  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
27  * GNU General Public License for more details.
28  *
29  * You should have received a copy of the GNU Library General Public
30  * License along with this program; if not, write to the Free Software
31  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
32  *
33  **************************************************************************/
34 
35 /** \class TASImage
36 \ingroup asimage
37 
38 Image class.
39 
40 TASImage is the concrete interface to the image processing library
41 libAfterImage.
42 
43 It allows reading and writing of images in different formats, several image
44 manipulations (scaling, tiling, merging, etc.) and displaying in pads. The size
45 of the image on the screen does not depend on the original size of the image but
46 on the size of the pad. Therefore it is very easy to resize the image on the
47 screen by resizing the pad.
48 
49 Besides reading an image from a file an image can be defined by a two
50 dimensional array of values. A palette defines the color of each value.
51 
52 The image can be zoomed by defining a rectangle with the mouse. The color
53 palette can be modified with a GUI, just select StartPaletteEditor() from the
54 context menu.
55 
56 Several examples showing how to use this class are available in the
57 ROOT tutorials: `$ROOTSYS/tutorials/image/`
58 */
59 
60 # include <ft2build.h>
61 # include FT_FREETYPE_H
62 # include FT_GLYPH_H
63 #include "TASImage.h"
64 #include "TASImagePlugin.h"
65 #include "TROOT.h"
66 #include "TMath.h"
67 #include "TSystem.h"
68 #include "TVirtualX.h"
69 #include "TVirtualPad.h"
70 #include "TArrayD.h"
71 #include "TVectorD.h"
72 #include "TVirtualPS.h"
73 #include "TGaxis.h"
74 #include "TColor.h"
75 #include "TObjArray.h"
76 #include "TArrayL.h"
77 #include "TPoint.h"
78 #include "TFrame.h"
79 #include "TTF.h"
80 #include "TRandom.h"
81 #include "Riostream.h"
82 #include "THashTable.h"
83 #include "TPluginManager.h"
84 #include "TEnv.h"
85 #include "TStyle.h"
86 #include "TText.h"
87 #include "RConfigure.h"
88 #include "TVirtualPadPainter.h"
89 
90 #ifndef WIN32
91 #ifndef R__HAS_COCOA
92 # include <X11/Xlib.h>
93 #endif
94 #else
95 # include "Windows4root.h"
96 #endif
97 extern "C" {
98 #ifndef WIN32
99 #ifdef R__HAS_COCOA
100 # define X_DISPLAY_MISSING 1
101 #endif
102 # include <afterbase.h>
103 #else
104 # include <win32/config.h>
105 # include <win32/afterbase.h>
106 # define X_DISPLAY_MISSING 1
107 #endif
108 # include <afterimage.h>
109 # include <bmp.h>
110 # include <draw.h>
111 }
112 
113 // auxiliary functions for general polygon filling
114 #include "TASPolyUtils.c"
115 
116 
117 ASVisual *TASImage::fgVisual = 0;
119 
120 static ASFontManager *gFontManager = 0;
121 static unsigned long kAllPlanes = ~0;
122 THashTable *TASImage::fgPlugList = new THashTable(50);
123 
124 // default icon paths
125 static char *gIconPaths[7] = {0, 0, 0, 0, 0, 0, 0};
126 
127 ///////////////////////////// alpha-blending macros ///////////////////////////////
128 
129 #if defined(__GNUC__) && __GNUC__ >= 4 && ((__GNUC_MINOR__ == 2 && __GNUC_PATCHLEVEL__ >= 1) || (__GNUC_MINOR__ >= 3)) && !__INTEL_COMPILER
130 #pragma GCC diagnostic ignored "-Wstrict-aliasing"
131 #endif
132 
133 #ifdef R__BYTESWAP
134 typedef struct {
135  unsigned char b;
136  unsigned char g;
137  unsigned char r;
138  unsigned char a;
139 } __argb32__;
140 #else
141 typedef struct {
142  unsigned char a;
143  unsigned char r;
144  unsigned char g;
145  unsigned char b;
146 } __argb32__;
147 #endif
148 
149 
150 //______________________________________________________________________________
151 #define _alphaBlend(bot, top) {\
152  __argb32__ *t = (__argb32__*)(top);\
153  __argb32__ *b = (__argb32__*)(bot);\
154  int aa = 255-t->a;\
155  if (!aa) {\
156  *bot = *top;\
157  } else { \
158  b->a = ((b->a*aa)>>8) + t->a;\
159  b->r = (b->r*aa + t->r*t->a)>>8;\
160  b->g = (b->g*aa + t->g*t->a)>>8;\
161  b->b = (b->b*aa + t->b*t->a)>>8;\
162  }\
163 }\
164 
165 
168 
169 ////////////////////////////////////////////////////////////////////////////////
170 /// Destroy image.
171 
172 void TASImage::DestroyImage()
173 {
174  if (fImage) {
175  destroy_asimage(&fImage);
176  }
177 
178  if (fIsGray && fGrayImage) {
179  destroy_asimage(&fGrayImage);
180  }
181 
182  fIsGray = kFALSE;
183  fGrayImage = 0;
184  fImage = 0;
185 }
186 
187 ////////////////////////////////////////////////////////////////////////////////
188 /// Set default parameters.
189 
191 {
192  fImage = 0;
193  fScaledImage = 0;
194  fMaxValue = 1;
195  fMinValue = 0;
196  fEditable = kFALSE;
197  fPaintMode = 1;
198  fZoomOffX = 0;
199  fZoomOffY = 0;
200  fZoomWidth = 0;
201  fZoomHeight = 0;
203 
204  fGrayImage = 0;
205  fIsGray = kFALSE;
207 
208  if (!fgInit) {
209  set_application_name((char*)(gProgName ? gProgName : "ROOT"));
210  fgInit = kTRUE;
211  }
212 }
213 
214 ////////////////////////////////////////////////////////////////////////////////
215 /// Default image constructor.
216 
218 {
219  SetDefaults();
220 }
221 
222 ////////////////////////////////////////////////////////////////////////////////
223 /// Create an empty image.
224 
226 {
227  SetDefaults();
228  fImage = create_asimage(w ? w : 20, h ? h : 20, 0);
229  UnZoom();
230 }
231 
232 ////////////////////////////////////////////////////////////////////////////////
233 /// Create an image object and read from specified file.
234 /// For more information see description of function ReadImage()
235 /// which is called by this constructor.
236 
237 TASImage::TASImage(const char *file, EImageFileTypes) : TImage(file)
238 {
239  SetDefaults();
240  TString fname = file;
241  gSystem->ExpandPathName(fname);
242  ReadImage(fname.Data());
243 }
244 
245 ////////////////////////////////////////////////////////////////////////////////
246 /// Create an image depending on the values of imageData.
247 /// For more information see function SetImage() which is called
248 /// by this constructor.
249 
250 TASImage::TASImage(const char *name, const Double_t *imageData, UInt_t width,
251  UInt_t height, TImagePalette *palette) : TImage(name)
252 {
253  SetDefaults();
254  SetImage(imageData, width, height, palette);
255 }
256 
257 ////////////////////////////////////////////////////////////////////////////////
258 /// Create an image depending on the values of imageData.
259 /// The size of the image is width X (imageData.fN / width).
260 /// For more information see function SetImage() which is called by
261 /// this constructor.
262 
263 TASImage::TASImage(const char *name, const TArrayD &imageData, UInt_t width,
264  TImagePalette *palette) : TImage(name)
265 {
266  SetDefaults();
267  SetImage(imageData, width, palette);
268 }
269 
270 ////////////////////////////////////////////////////////////////////////////////
271 /// Create an image depending on the values of imageData.
272 /// The size of the image is width X (imageData.fN / width).
273 /// For more information see function SetImage() which is called by
274 /// this constructor.
275 
276 TASImage::TASImage(const char *name, const TVectorD &imageData, UInt_t width,
277  TImagePalette *palette) : TImage(name)
278 {
279  SetDefaults();
280  SetImage(imageData, width, palette);
281 }
282 
283 ////////////////////////////////////////////////////////////////////////////////
284 /// Image copy constructor.
285 
287 {
288  SetDefaults();
289 
290  if (img.IsValid()) {
291  fImage = clone_asimage(img.fImage, SCL_DO_ALL);
293  fGrayImage = fGrayImage ? clone_asimage(img.fGrayImage, SCL_DO_ALL) : 0;
294 
295  if (img.fImage->alt.vector) {
296  Int_t size = img.fImage->width * img.fImage->height * sizeof(double);
297  fImage->alt.vector = (double*)malloc(size);
298  memcpy(fImage->alt.vector, img.fImage->alt.vector, size);
299  }
300 
302  fZoomOffX = img.fZoomOffX;
303  fZoomOffY = img.fZoomOffY;
304  fZoomWidth = img.fZoomWidth;
305  fZoomHeight = img.fZoomHeight;
306  fEditable = img.fEditable;
307  fIsGray = img.fIsGray;
308  }
309 }
310 
311 ////////////////////////////////////////////////////////////////////////////////
312 /// Image assignment operator.
313 
315 {
316  SetDefaults();
317 
318  if (this != &img && img.IsValid()) {
319  TImage::operator=(img);
320 
321  DestroyImage();
322  delete fScaledImage;
323  fImage = clone_asimage(img.fImage, SCL_DO_ALL);
325  fGrayImage = fGrayImage ? clone_asimage(img.fGrayImage, SCL_DO_ALL) : 0;
326 
327  if (img.fImage->alt.vector) {
328  Int_t size = img.fImage->width * img.fImage->height * sizeof(double);
329  fImage->alt.vector = (double*)malloc(size);
330  memcpy(fImage->alt.vector, img.fImage->alt.vector, size);
331  }
332 
333  fScaledImage = img.fScaledImage ? (TASImage*)img.fScaledImage->Clone("") : 0;
335  fZoomOffX = img.fZoomOffX;
336  fZoomOffY = img.fZoomOffY;
337  fZoomWidth = img.fZoomWidth;
338  fZoomHeight = img.fZoomHeight;
339  fEditable = img.fEditable;
340  fIsGray = img.fIsGray;
341  fPaintMode = 1;
342  }
343 
344  return *this;
345 }
346 
347 ////////////////////////////////////////////////////////////////////////////////
348 /// Image destructor, clean up image and visual.
349 
351 {
352  DestroyImage();
353  delete fScaledImage;
354  fScaledImage = 0;
355 }
356 
357 ////////////////////////////////////////////////////////////////////////////////
358 /// Set icons paths.
359 
360 static void init_icon_paths()
361 {
362  const char *icons = "/icons";
363 #ifdef R__WIN32
364  icons = "\\icons";
365 #endif
366 
367  TString homeIcons = gSystem->HomeDirectory();
368  homeIcons += icons;
369 
370  TString rootIcons = gSystem->Getenv("ROOTSYS");
371  rootIcons += icons;
372 
373  TString guiIcons = gEnv->GetValue("Gui.IconPath", "");
374 
375  gIconPaths[0] = StrDup(".");
376  gIconPaths[1] = StrDup(homeIcons.Data());
377  gIconPaths[2] = StrDup(rootIcons.Data());
378  gIconPaths[3] = StrDup(guiIcons.Data());
379 
380 #ifdef ROOTICONPATH
381  gIconPaths[4] = StrDup(ROOTICONPATH);
382 #endif
383 
384 #ifdef EXTRAICONPATH
385  gIconPaths[5] = StrDup(EXTRAICONPATH);
386 #endif
387 
388  gIconPaths[6] = 0;
389 }
390 
391 ////////////////////////////////////////////////////////////////////////////////
392 /// Guess the file type from the first byte of file.
393 
394 const char *TASImage::TypeFromMagicNumber(const char *file)
395 {
396  UChar_t magic;
397  FILE *fp = fopen(file, "rb");
398  const char *ret = "";
399 
400  if (!fp) return 0;
401 
402  if (!fread(&magic, 1, 1, fp)) {
403  fclose(fp);
404  return 0;
405  }
406 
407  switch (magic) {
408  case 0x00:
409  {
410  if (!fread(&magic, 1, 1, fp)) {
411  fclose(fp);
412  return 0;
413  }
414  if (!fread(&magic, 1, 1, fp)) {
415  fclose(fp);
416  return 0;
417  }
418 
419  ret = (magic == 1) ? "ico" : "cur";
420  break;
421  }
422  case 0x25:
423  {
424  if (!fread(&magic, 1, 1, fp)) {
425  fclose(fp);
426  return 0;
427  }
428 
429  if (magic == 0x21) ret = "ps";
430  else if (magic == 0x50) ret = "pdf";
431  break;
432  }
433  case 0x42:
434  ret = "bmp";
435  break;
436  case 0x47:
437  ret = "gif";
438  break;
439  case 0x54:
440  ret = "tga";
441  break;
442  case 0x49:
443  ret = "tiff";
444  break;
445  case 0x89:
446  ret = "png";
447  break;
448  case 0xff:
449  ret = "jpg";
450  break;
451  default:
452  ret = "";
453  }
454 
455  fclose(fp);
456  return ret;
457 }
458 
459 ////////////////////////////////////////////////////////////////////////////////
460 /// Read specified image file.
461 /// The file type is determined by the file extension (the type argument is
462 /// ignored). It will attempt to append .gz and then .Z to the filename and
463 /// find such a file. If the filename ends with extension consisting of digits
464 /// only, it will attempt to find the file with this extension stripped
465 /// off. On success this extension will be used to load subimage from
466 /// the file with that number. Subimage is supported for GIF files
467 /// (ICO, BMP, CUR, TIFF, XCF to be supported in future).
468 /// For example,
469 /// ~~~ {.cpp}
470 /// i1 = TImage::Open("anim.gif.0"); // read the first subimage
471 /// i4 = TImage::Open("anim.gif.3"); // read the forth subimage
472 /// ~~~
473 /// It is also possible to put XPM raw string (see also SetImageBuffer) as
474 /// the first input parameter ("filename"), such string is returned by
475 /// GetImageBuffer method.
476 
477 void TASImage::ReadImage(const char *filename, EImageFileTypes /*type*/)
478 {
479  if (!InitVisual()) {
480  Warning("Scale", "Visual not initiated");
481  return;
482  }
483 
484  Bool_t xpm = filename && (filename[0] == '/' &&
485  filename[1] == '*') && filename[2] == ' ';
486 
487  if (xpm) { // XPM strings in-memory array
488  SetImageBuffer((char**)&filename, TImage::kXpm);
489  fName = "XPM_image";
490  return;
491  }
492 
493  if (!gIconPaths[0]) {
494  init_icon_paths();
495  }
496  // suppress the "root : looking for image ..." messages
497  set_output_threshold(0);
498 
499  static ASImageImportParams iparams;
500  iparams.flags = 0;
501  iparams.width = 0;
502  iparams.height = 0;
503  iparams.filter = SCL_DO_ALL;
504  iparams.gamma = SCREEN_GAMMA;
505  iparams.gamma_table = NULL;
506  iparams.compression = GetImageCompression();
507  iparams.format = ASA_ASImage;
508  iparams.search_path = gIconPaths;
509  iparams.subimage = 0;
510  iparams.return_animation_delay = -1;
511 
512  TString ext;
513  const char *dot;
514  if (filename) dot = strrchr(filename, '.');
515  else dot = 0;
516  ASImage *image = 0;
517  TString fname = filename;
518 
519  if (!dot) {
520  if (filename) ext = TypeFromMagicNumber(filename);
521  else ext = dot + 1;
522  } else {
523  ext = dot + 1;
524  }
525 
526  if (!ext.IsNull() && ext.IsDigit()) { // read subimage
527  iparams.subimage = ext.Atoi();
528  fname = fname(0, fname.Length() - ext.Length() - 1);
529  ext = strrchr(fname.Data(), '.') + 1;
530  }
531 
532  image = file2ASImage_extra(fname.Data(), &iparams);
533 
534  if (image) { // it's OK
535  goto end;
536  } else { // try to read it via plugin
537  if (ext.IsNull()) {
538  return;
539  }
540  ext.ToLower();
541  ext.Strip();
542  UInt_t w = 0;
543  UInt_t h = 0;
544  unsigned char *bitmap = 0;
545 
547 
548  if (!plug) {
549  TPluginHandler *handler = gROOT->GetPluginManager()->FindHandler("TImagePlugin", ext);
550  if (!handler || ((handler->LoadPlugin() == -1))) {
551  return;
552  }
553  plug = (TImagePlugin*)handler->ExecPlugin(1, ext.Data());
554 
555  if (!plug) {
556  return;
557  }
558 
559  fgPlugList->Add(plug);
560  }
561 
562  if (plug) {
563  if (plug->InheritsFrom(TASImagePlugin::Class())) {
564  image = ((TASImagePlugin*)plug)->File2ASImage(fname.Data());
565  if (image) goto end;
566  }
567  bitmap = plug->ReadFile(fname.Data(), w, h);
568  if (bitmap) {
569  image = bitmap2asimage(bitmap, w, h, 0, 0);
570  }
571  if (!image) {
572  return;
573  }
574  }
575  }
576 
577 end:
578  fName.Form("%s.", gSystem->BaseName(fname.Data()));
579 
580  DestroyImage();
581  delete fScaledImage;
582  fScaledImage = 0;
583 
584  fImage = image;
586  fEditable = kFALSE;
587  fZoomOffX = 0;
588  fZoomOffY = 0;
589  fZoomWidth = fImage->width;
590  fZoomHeight = fImage->height;
591  fPaintMode = 1;
592 }
593 
594 ////////////////////////////////////////////////////////////////////////////////
595 /// Write image to specified file.
596 ///
597 /// If there is no file extension or if the file extension is unknown, the
598 /// type argument will be used to determine the file type. The quality and
599 /// compression is derived from the TAttImage values.
600 ///
601 /// It's possible to write image into an animated GIF file by specifying file
602 /// name as "myfile.gif+" or "myfile.gif+NN", where NN is the delay of displaying
603 /// subimages during animation in 10ms seconds units. NN is not restricted
604 /// to two digits. If NN is omitted the delay between subimages is zero.
605 /// For an animation that stops after last subimage is reached, one has to
606 /// write the last image as .gif+ (zero delay of last image) or .gif+NN
607 /// (NN*10ms delay of last image).
608 ///
609 /// For repeated animation (looping), the last subimage must be specified as:
610 /// - "myfile.gif++NN++" if you want an infinite looping gif with NN*10ms
611 /// delay of the last image.
612 /// - "myfile.gif++" for an infinite loop with zero delay of last image.
613 /// - "myfile.gif+NN++RR" if you want a finite looping gif with NN*10ms
614 /// delay of the last image and the animation to be stopped after RR
615 /// repeats. RR is not restricted to two digits.
616 ///
617 /// A deprecated version for saving the last subimage of a looping gif animation is:
618 /// - "myfile.gif++NN" for a finite loop where NN is number of repetitions
619 /// and NN*10ms the delay of last image. (No separate control of repeats and delay).
620 /// Note: If the file "myfile.gif" already exists, the new frames are appended at
621 /// the end of the file. To avoid this, delete it first with gSystem->Unlink(myfile.gif);
622 ///
623 /// The following macro creates animated gif from jpeg images with names
624 /// - imageNN.jpg, where 1<= NN <= 10
625 /// - The delays are set to 10*10ms.
626 /// ~~~ {.cpp}
627 /// {
628 /// TImage *img = 0;
629 /// gSystem->Unlink("anim.gif"); // delete existing file
630 ///
631 /// for (int i = 1; i <= 10; i++) {
632 /// delete img; // delete previous image
633 ///
634 /// // Read image data. Image can be in any format, e.g. png, gif, etc.
635 /// img = TImage::Open(Form("image%d.jpg", i));
636 ///
637 /// if (i < 10) {
638 /// img->WriteImage("anim.gif+10"); // 10 centiseconds delay
639 /// } else { // the last image written. "++" stands for infinit animation.
640 /// img->WriteImage("anim.gif++10++"); // 10 centiseconds delay of last image
641 /// }
642 /// }
643 /// }
644 /// ~~~
645 
647 {
648  if (!IsValid()) {
649  Error("WriteImage", "no image loaded");
650  return;
651  }
652 
653  if (!file || !*file) {
654  Error("WriteImage", "no file name specified");
655  return;
656  }
657 
658  const char *s;
659  if ((s = strrchr(file, '.'))) {
660  s++;
662  if (t == kUnknown) {
663  Error("WriteImage", "cannot determine a valid file type");
664  return;
665  }
666  if (t != kUnknown)
667  type = t;
668  }
669 
670  if (type == kUnknown) {
671  Error("WriteImage", "not a valid file type was specified");
672  return;
673  }
674 
675  UInt_t mytype;
676  MapFileTypes(type, mytype);
677  ASImageFileTypes atype = (ASImageFileTypes)mytype;
678 
679  UInt_t aquality;
680  EImageQuality quality = GetImageQuality();
681  MapQuality(quality, aquality);
682 
683  static TString fname;
684  fname = file;
685  static ASImageExportParams parms;
686  ASImage *im = fScaledImage ? fScaledImage->fImage : fImage;
687 
688  switch (type) {
689  case kXpm:
690  parms.xpm.type = atype;
691  parms.xpm.flags = EXPORT_ALPHA;
692  parms.xpm.dither = 4;
693  parms.xpm.opaque_threshold = 127;
694  parms.xpm.max_colors = 512;
695  break;
696  case kBmp:
697  ASImage2bmp(im, fname.Data(), 0);
698  return;
699  case kXcf:
700  ASImage2xcf(im, fname.Data(), 0);
701  return;
702  case kPng:
703  parms.png.type = atype;
704  parms.png.flags = EXPORT_ALPHA;
705  parms.png.compression = !GetImageCompression() ? -1 : int(GetImageCompression());
706  break;
707  case kJpeg:
708  parms.jpeg.type = atype;
709  parms.jpeg.flags = 0;
710  parms.jpeg.quality = aquality;
711  break;
712  case kGif:
713  parms.gif.type = atype;
714  parms.gif.flags = EXPORT_ALPHA;
715  parms.gif.dither = 0;
716  parms.gif.opaque_threshold = 0;
717  break;
718  case kAnimGif:
719  {
720  parms.gif.type = atype;
721  parms.gif.flags = EXPORT_ALPHA | EXPORT_APPEND;
722  parms.gif.dither = 0;
723  parms.gif.opaque_threshold = 0;
724  parms.gif.animate_repeats = 0;
725 
726  s += 4; // skip "gif+"
727  int delay = 0;
728 
729  const TString sufix = s; // we denote as suffix as everything that is after .gif+
730  const UInt_t sLength = sufix.Length();
731 
732  if (sufix=="+") {
733  // .gif++ implies that this is the last image of the animation
734  // and that the gif will loop forever (infinite animation)
735  // and that the delay of last image is 0ms (backward compatibility reasons)
736  delay = 0;
737  parms.gif.flags |= EXPORT_ANIMATION_REPEATS;// activate repetition
738  parms.gif.animate_repeats = 0;// 0 is code for looping forever (if EXPORT_ANIMATION_REPEATS is also set)
739  } else if(sufix=="") {
740  // .gif+ implies that this is a subimage of the animation with zero delay
741  // or the last image of an animation that will not repeat.
742  // Last image delay is zero because atoi("")=0.
743  delay = atoi(s);
744  //Nothing else needed here
745  } else if(!sufix.Contains("+")) {
746  // .gif+NN implies that this is a subimage of the animation
747  // with NN*10ms delay (latency) until the next one.
748  // You can also use this option on the last image if you do not want the gif to replay
749  delay = atoi(s);
750  //Nothing else needed here
751  } else if(sLength>1 && sufix.BeginsWith("+") && sufix.CountChar('+')==1) {
752  // .gif++NN implies that this is the last image of the animation
753  // and that it will loop NN number of times (finite animation)
754  // and that the delay of last image is NN*10ms (backward compatibility reasons).
755  delay = atoi(s);// atoi is smart enough to ignore the "+" sign before.
756  parms.gif.flags |= EXPORT_ANIMATION_REPEATS;// activate repetition
757  parms.gif.animate_repeats = atoi(s);// loops only NN times, then it stops. atoi discards + sign.
758  } else if(sLength>3 && sufix.BeginsWith("+") && sufix.EndsWith("++") && !TString(sufix(1,sLength-3)).Contains("+")) {
759  // .gif++NN++ implies that this is the last image of the animation
760  // and that the gif will loop forever (infinite animation)
761  // and that the delay of last image is NN*10ms.
762  // In contrast, .gif++ is an infinite loop but with 0 delay, whereas the option
763  // .gif++NN is a loop repeated NN times (not infinite) with NN*10ms delay
764  // between last and first loop images.
765  delay = atoi(s);// atoi discards the three plus signs
766  parms.gif.flags |= EXPORT_ANIMATION_REPEATS;// activate repetition
767  parms.gif.animate_repeats = 0;// 0 is code for looping forever (if EXPORT_ANIMATION_REPEATS is also set)
768  } else if(sLength>3 && sufix.CountChar('+')==2 && TString(sufix(1,sLength-2)).Contains("++")) {
769  // .gif+NN++RR implies that this is the last image animation
770  // and that the gif will loop RR number of times (finite animation)
771  // and that the delay of last image is NN*10ms.
772  const TString sDelay = sufix(0,sufix.First('+'));
773  const TString sRepeats = sufix(sufix.First('+')+2,sLength-(sufix.First('+')+2));
774  delay = atoi(sDelay);
775  parms.gif.flags |= EXPORT_ANIMATION_REPEATS;// activate repetition
776  parms.gif.animate_repeats = atoi(sRepeats);// loops NN times.
777  } else {
778  Error("WriteImage", "gif suffix %s not yet supported", s);
779  return;
780  }
781 
782  parms.gif.animate_delay = delay;
783 
784  int i1 = fname.Index("gif+");
785  if (i1 != kNPOS) {
786  fname = fname(0, i1 + 3);
787  }
788  else {
789  Error("WriteImage", "unexpected gif extension structure %s", fname.Data());
790  return;
791  }
792  break;
793  }
794  case kTiff:
795  parms.tiff.type = atype;
796  parms.tiff.flags = EXPORT_ALPHA;
797  parms.tiff.rows_per_strip = 0;
798  parms.tiff.compression_type = aquality <= 50 ? TIFF_COMPRESSION_JPEG :
799  TIFF_COMPRESSION_NONE;
800  parms.tiff.jpeg_quality = 100;
801  parms.tiff.opaque_threshold = 0;
802  break;
803  default:
804  Error("WriteImage", "file type %s not yet supported", s);
805  return;
806  }
807 
808  if (!ASImage2file(im, 0, fname.Data(), atype, &parms)) {
809  Error("WriteImage", "error writing file %s", file);
810  }
811 }
812 
813 ////////////////////////////////////////////////////////////////////////////////
814 /// Return file type depending on specified extension.
815 /// Protected method.
816 
818 {
819  TString s(ext);
820  s.Strip();
821  s.ToLower();
822 
823  if (s == "xpm")
824  return kXpm;
825  if (s == "png")
826  return kPng;
827  if (s == "jpg" || s == "jpeg")
828  return kJpeg;
829  if (s == "xcf")
830  return kXcf;
831  if (s == "ppm")
832  return kPpm;
833  if (s == "pnm")
834  return kPnm;
835  if (s == "bmp")
836  return kBmp;
837  if (s == "ico")
838  return kIco;
839  if (s == "cur")
840  return kCur;
841  if (s == "gif")
842  return kGif;
843  if (s.Contains("gif+"))
844  return kAnimGif;
845  if (s == "tiff")
846  return kTiff;
847  if (s == "xbm")
848  return kXbm;
849  if (s == "tga")
850  return kTga;
851  if (s == "xml")
852  return kXml;
853 
854  return kUnknown;
855 }
856 
857 ////////////////////////////////////////////////////////////////////////////////
858 /// Map file type to/from AfterImage types.
859 /// Protected method.
860 
862 {
863  if (toas) {
864  switch (type) {
865  case kXpm:
866  astype = ASIT_Xpm; break;
867  case kZCompressedXpm:
868  astype = ASIT_ZCompressedXpm; break;
869  case kGZCompressedXpm:
870  astype = ASIT_GZCompressedXpm; break;
871  case kPng:
872  astype = ASIT_Png; break;
873  case kJpeg:
874  astype = ASIT_Jpeg; break;
875  case kXcf:
876  astype = ASIT_Xcf; break;
877  case kPpm:
878  astype = ASIT_Ppm; break;
879  case kPnm:
880  astype = ASIT_Pnm; break;
881  case kBmp:
882  astype = ASIT_Bmp; break;
883  case kIco:
884  astype = ASIT_Ico; break;
885  case kCur:
886  astype = ASIT_Cur; break;
887  case kGif:
888  astype = ASIT_Gif; break;
889  case kAnimGif:
890  astype = ASIT_Gif; break;
891  case kTiff:
892  astype = ASIT_Tiff; break;
893  case kXbm:
894  astype = ASIT_Xbm; break;
895  case kTga:
896  astype = ASIT_Targa; break;
897  case kXml:
898  astype = ASIT_XMLScript; break;
899  default:
900  astype = ASIT_Unknown;
901  }
902  } else {
903  switch (astype) {
904  case ASIT_Xpm:
905  type = kXpm; break;
906  case ASIT_ZCompressedXpm:
907  type = kZCompressedXpm; break;
908  case ASIT_GZCompressedXpm:
909  type = kGZCompressedXpm; break;
910  case ASIT_Png:
911  type = kPng; break;
912  case ASIT_Jpeg:
913  type = kJpeg; break;
914  case ASIT_Xcf:
915  type = kXcf; break;
916  case ASIT_Ppm:
917  type = kPpm; break;
918  case ASIT_Pnm:
919  type = kPnm; break;
920  case ASIT_Bmp:
921  type = kBmp; break;
922  case ASIT_Ico:
923  type = kIco; break;
924  case ASIT_Cur:
925  type = kCur; break;
926  case ASIT_Gif:
927  type = kGif; break;
928  case ASIT_Tiff:
929  type = kTiff; break;
930  case ASIT_Xbm:
931  type = kXbm; break;
932  case ASIT_XMLScript:
933  type = kXml; break;
934  case ASIT_Targa:
935  type = kTga; break;
936  default:
937  type = kUnknown;
938  }
939  }
940 }
941 
942 ////////////////////////////////////////////////////////////////////////////////
943 /// Map quality to/from AfterImage quality.
944 /// Protected method.
945 
946 void TASImage::MapQuality(EImageQuality &quality, UInt_t &asquality, Bool_t toas)
947 {
948  if (toas) {
949  switch (quality) {
950  case kImgPoor:
951  asquality = 25; break;
952  case kImgFast:
953  asquality = 75; break;
954  case kImgGood:
955  asquality = 50; break;
956  case kImgBest:
957  asquality = 100; break;
958  default:
959  asquality = 0;
960  }
961  } else {
962  quality = kImgDefault;
963  if (asquality > 0 && asquality <= 25)
964  quality = kImgPoor;
965  if (asquality > 26 && asquality <= 50)
966  quality = kImgFast;
967  if (asquality > 51 && asquality <= 75)
968  quality = kImgGood;
969  if (asquality > 76 && asquality <= 100)
970  quality = kImgBest;
971  }
972 }
973 
974 ////////////////////////////////////////////////////////////////////////////////
975 /// Deletes the old image and creates a new image depending on the values
976 /// of imageData. The size of the image is width X height.
977 ///
978 /// The color of each pixel depends on the imageData of the corresponding
979 /// pixel. The palette is used to convert an image value into its color.
980 /// If palette is not defined (palette = 0) a default palette is used.
981 /// Any previously defined zooming is reset.
982 
983 void TASImage::SetImage(const Double_t *imageData, UInt_t width, UInt_t height,
984  TImagePalette *palette)
985 {
986  TAttImage::SetPalette(palette);
987 
988  if (!InitVisual()) {
989  Warning("SetImage", "Visual not initiated");
990  return;
991  }
992 
993  DestroyImage();
994  delete fScaledImage;
995  fScaledImage = 0;
996 
997  // get min and max value of image
998  fMinValue = fMaxValue = *imageData;
999  for (Int_t pixel = 1; pixel < Int_t(width * height); pixel++) {
1000  if (fMinValue > *(imageData + pixel)) fMinValue = *(imageData + pixel);
1001  if (fMaxValue < *(imageData + pixel)) fMaxValue = *(imageData + pixel);
1002  }
1003 
1004  // copy ROOT palette to asImage palette
1005  const TImagePalette &pal = GetPalette();
1006 
1007  ASVectorPalette asPalette;
1008 
1009  asPalette.npoints = pal.fNumPoints;
1010  Int_t col;
1011  for (col = 0; col < 4; col++)
1012  asPalette.channels[col] = new UShort_t[asPalette.npoints];
1013 
1014  memcpy(asPalette.channels[0], pal.fColorBlue, pal.fNumPoints * sizeof(UShort_t));
1015  memcpy(asPalette.channels[1], pal.fColorGreen, pal.fNumPoints * sizeof(UShort_t));
1016  memcpy(asPalette.channels[2], pal.fColorRed, pal.fNumPoints * sizeof(UShort_t));
1017  memcpy(asPalette.channels[3], pal.fColorAlpha, pal.fNumPoints * sizeof(UShort_t));
1018 
1019  asPalette.points = new Double_t[asPalette.npoints];
1020  for (Int_t point = 0; point < Int_t(asPalette.npoints); point++)
1021  asPalette.points[point] = fMinValue + (fMaxValue - fMinValue) * pal.fPoints[point];
1022 
1023  fImage = create_asimage_from_vector(fgVisual, (Double_t*)imageData, width,
1024  height, &asPalette, ASA_ASImage,
1026 
1027  delete [] asPalette.points;
1028  for (col = 0; col < 4; col++)
1029  delete [] asPalette.channels[col];
1030 
1031  fZoomUpdate = 0;
1032  fZoomOffX = 0;
1033  fZoomOffY = 0;
1034  fZoomWidth = width;
1035  fZoomHeight = height;
1037 }
1038 
1039 ////////////////////////////////////////////////////////////////////////////////
1040 /// Delete the old image and creates a new image depending on the values
1041 /// of imageData. The size of the image is width X (imageData.fN / width).
1042 /// The color of each pixel depends on the imageData of the corresponding
1043 /// pixel. The palette is used to convert an image value into its color.
1044 /// If palette is not defined (palette = 0) a default palette is used.
1045 /// Any previously defined zooming is reset.
1046 
1047 void TASImage::SetImage(const TArrayD &imageData, UInt_t width, TImagePalette *palette)
1048 {
1049  SetImage(imageData.GetArray(), width, imageData.GetSize() / width, palette);
1050 }
1051 
1052 ////////////////////////////////////////////////////////////////////////////////
1053 /// Delete the old image and creates a new image depending on the values
1054 /// of imageData. The size of the image is width X (imageData.fN / width).
1055 /// The color of each pixel depends on the imageData of the corresponding
1056 /// pixel. The palette is used to convert an image value into its color.
1057 /// If palette is not defined (palette = 0) a default palette is used.
1058 /// Any previously defined zooming is reset.
1059 
1060 void TASImage::SetImage(const TVectorD &imageData, UInt_t width, TImagePalette *palette)
1061 {
1062  SetImage(imageData.GetMatrixArray(), width,
1063  imageData.GetNoElements() / width, palette);
1064 }
1065 
1066 ////////////////////////////////////////////////////////////////////////////////
1067 /// Create an image from the given pad, afterwards this image can be
1068 /// saved in any of the supported image formats.
1069 
1071 {
1072  if (!pad) {
1073  Error("FromPad", "pad cannot be 0");
1074  return;
1075  }
1076 
1077  if (!InitVisual()) {
1078  Warning("FromPad", "Visual not initiated");
1079  return;
1080  }
1081 
1082  SetName(pad->GetName());
1083 
1084  DestroyImage();
1085  delete fScaledImage;
1086  fScaledImage = 0;
1087 
1088  if (gROOT->IsBatch()) { // in batch mode
1089  TVirtualPS *psave = gVirtualPS;
1090  gVirtualPS = (TVirtualPS*)gROOT->ProcessLineFast("new TImageDump()");
1091  gVirtualPS->Open(pad->GetName(), 114); // in memory
1092  gVirtualPS->SetBit(BIT(11)); //kPrintingPS
1093 
1094  TASImage *itmp = (TASImage*)gVirtualPS->GetStream();
1095 
1096  if (itmp && itmp->fImage) {
1097  itmp->BeginPaint();
1098  }
1099 
1100  TVirtualPad *sav = gPad;
1101  gPad = pad;
1102  pad->Paint();
1103  gPad = sav;
1104 
1105  if (itmp && itmp->fImage && (itmp != this)) {
1106  fImage = clone_asimage(itmp->fImage, SCL_DO_ALL);
1107  if (itmp->fImage->alt.argb32) {
1108  UInt_t sz = itmp->fImage->width*itmp->fImage->height;
1109  fImage->alt.argb32 = (ARGB32*)safemalloc(sz*sizeof(ARGB32));
1110  memcpy(fImage->alt.argb32, itmp->fImage->alt.argb32, sz*4);
1111  }
1112  }
1113  delete gVirtualPS;
1114  gVirtualPS = psave;
1115  return;
1116  }
1117 
1118  if (w == 0) {
1119  w = TMath::Abs(pad->UtoPixel(1.));
1120  }
1121 
1122  if (h == 0) {
1123  h = pad->VtoPixel(0.);
1124  }
1125  // synchronization
1126  gVirtualX->Update(1);
1127  if (!gThreadXAR) {
1129  gSystem->Sleep(10);
1131  }
1132 
1133  TVirtualPad *canvas = (TVirtualPad*)pad->GetCanvas();
1134  Int_t wid = (pad == canvas) ? pad->GetCanvasID() : pad->GetPixmapID();
1135  gVirtualX->SelectWindow(wid);
1136 
1137  Window_t wd = (Window_t)gVirtualX->GetCurrentWindow();
1138  if (!wd) return;
1139 
1140  static int x11 = -1;
1141  if (x11 < 0) x11 = gVirtualX->InheritsFrom("TGX11");
1142 
1143  if (x11) { //use built-in optimized version
1144  fImage = pixmap2asimage(fgVisual, wd, x, y, w, h, kAllPlanes, 0, 0);
1145  } else {
1146  unsigned char *bits = gVirtualX->GetColorBits(wd, 0, 0, w, h);
1147 
1148  if (!bits) { // error
1149  return;
1150  }
1151  fImage = bitmap2asimage(bits, w, h, 0, 0);
1152  delete [] bits;
1153  }
1154 }
1155 
1156 ////////////////////////////////////////////////////////////////////////////////
1157 /// Draw image.
1158 /// Support the following drawing options:
1159 /// - "T[x,y[,tint]]" : tile image (use specified offset and tint),
1160 /// e.g. "T100,100,#556655"
1161 /// with this option the zooming is not possible
1162 /// and disabled
1163 /// - "N" : display in new canvas (of original image size)
1164 /// - "X" : image is drawn expanded to pad size
1165 /// - "Z" : image is vectorized and image palette is drawn
1166 ///
1167 /// The default is to display the image in the current gPad.
1168 
1170 {
1171  if (!fImage) {
1172  Error("Draw", "no image set");
1173  return;
1174  }
1175 
1176  TString opt = option;
1177  opt.ToLower();
1178  if (opt.Contains("n") || !gPad || !gPad->IsEditable()) {
1179  Int_t w = -64;
1180  Int_t h = 64;
1181  w = (fImage->width > 64) ? (Int_t)fImage->width : w;
1182  h = (fImage->height > 64) ? (Int_t)fImage->height : h;
1183 
1184  Float_t cx = 1./gStyle->GetScreenFactor();
1185  w = Int_t(w*cx) + 4;
1186  h = Int_t(h*cx) + 28;
1187  TString rname = GetName();
1188  rname.ReplaceAll(".", "");
1189  rname += Form("\", \"%s (%d x %d)", rname.Data(), fImage->width, fImage->height);
1190  rname = "new TCanvas(\"" + rname + Form("\", %d, %d);", w, h);
1191  gROOT->ProcessLineFast(rname.Data());
1192  }
1193 
1194  if (!opt.Contains("x")) {
1195  Double_t left = gPad->GetLeftMargin();
1196  Double_t right = gPad->GetRightMargin();
1197  Double_t top = gPad->GetTopMargin();
1198  Double_t bottom = gPad->GetBottomMargin();
1199 
1200  gPad->Range(-left / (1.0 - left - right),
1201  -bottom / (1.0 - top - bottom),
1202  1 + right / (1.0 - left - right),
1203  1 + top / ( 1.0 - top - bottom));
1204  gPad->RangeAxis(0, 0, 1, 1);
1205  }
1206 
1207  TFrame *frame = gPad->GetFrame();
1208  if (frame) {
1209  frame->SetBorderMode(0);
1210  frame->SetFillColor(gPad->GetFillColor());
1211  frame->SetLineColor(gPad->GetFillColor());
1212  frame->Draw();
1213  }
1214 
1215  TObject::Draw(option);
1216 }
1217 
1218 ////////////////////////////////////////////////////////////////////////////////
1219 /// Draw asimage on drawable.
1220 
1222  Int_t xsrc, Int_t ysrc, UInt_t wsrc, UInt_t hsrc,
1223  Option_t *opt)
1224 {
1225  if (!im) return;
1226 
1227  wsrc = wsrc ? wsrc : im->width;
1228  hsrc = hsrc ? hsrc : im->height;
1229 
1230  static int x11 = -1;
1231  if (x11 < 0) x11 = gVirtualX->InheritsFrom("TGX11");
1232 
1233  Pixmap_t mask = kNone;
1234 
1235  if (x11) {
1236  UInt_t hh = hsrc;
1237  UInt_t ow = wsrc%8;
1238  UInt_t ww = wsrc - ow + (ow ? 8 : 0);
1239 
1240  UInt_t bit = 0;
1241  int i = 0;
1242  UInt_t yy = 0;
1243  UInt_t xx = 0;
1244 
1245  char *bits = new char[ww*hh]; //an array of bits
1246 
1247  ASImageDecoder *imdec = start_image_decoding(fgVisual, im, SCL_DO_ALPHA,
1248  xsrc, ysrc, ww, 0, 0);
1249  if (imdec) {
1250  for (yy = 0; yy < hh; yy++) {
1251  imdec->decode_image_scanline(imdec);
1252  CARD32 *a = imdec->buffer.alpha;
1253 
1254  for (xx = 0; xx < ww; xx++) {
1255  if (a[xx]) {
1256  SETBIT(bits[i], bit);
1257  } else {
1258  CLRBIT(bits[i], bit);
1259  }
1260  bit++;
1261  if (bit == 8) {
1262  bit = 0;
1263  i++;
1264  }
1265  }
1266  }
1267  }
1268 
1269  stop_image_decoding(&imdec);
1270 
1271  mask = gVirtualX->CreateBitmap(gVirtualX->GetDefaultRootWindow(),
1272  (const char *)bits, ww, hh);
1273  delete [] bits;
1274  }
1275 
1276  GCValues_t gv;
1277  static GContext_t gc = 0;
1278 
1280  gv.fClipMask = mask;
1281  gv.fClipXOrigin = x;
1282  gv.fClipYOrigin = y;
1283 
1284  if (!gc) {
1285  gc = gVirtualX->CreateGC(gVirtualX->GetDefaultRootWindow(), &gv);
1286  } else {
1287  gVirtualX->ChangeGC(gc, &gv);
1288  }
1289 
1290  if (x11 && (!gPad || gPad->GetGLDevice() == -1)) { //use built-in optimized version
1291  asimage2drawable(fgVisual, wid, im, (GC)gc, xsrc, ysrc, x, y, wsrc, hsrc, 1);
1292  } else {
1293  ASImage *img = 0;
1294  unsigned char *bits = (unsigned char *)im->alt.argb32;
1295  if (!bits) {
1296  img = tile_asimage(fgVisual, im, xsrc, ysrc, wsrc, hsrc,
1297  0, ASA_ARGB32, 0, ASIMAGE_QUALITY_DEFAULT);
1298  if (img)
1299  bits = (unsigned char *)img->alt.argb32;
1300  }
1301 
1302  if (bits) {
1303  TString option(opt);
1304  option.ToLower();
1305 
1306  if (gPad && gPad->GetGLDevice() != -1) {
1307  if (TVirtualPadPainter *painter = gPad->GetPainter())
1308  painter->DrawPixels(bits, wsrc, hsrc, x, y, !option.Contains("opaque"));
1309  } else {
1310  Pixmap_t pic = gVirtualX->CreatePixmapFromData(bits, wsrc, hsrc);
1311  if (pic) {
1312  if (!option.Contains("opaque")) {
1313  SETBIT(wsrc,31);
1314  SETBIT(hsrc,31);
1315  }
1316  gVirtualX->CopyArea(pic, wid, gc, 0, 0, wsrc, hsrc, x, y);
1317  gVirtualX->DeletePixmap(pic);
1318  }
1319  }
1320  }
1321 
1322  if (img) {
1323  destroy_asimage(&img);
1324  }
1325  }
1326 
1327  // free mask pixmap
1328  if (gv.fClipMask != kNone) gVirtualX->DeletePixmap(gv.fClipMask);
1329 
1330  gv.fMask = kGCClipMask;
1331  gv.fClipMask = kNone;
1332  if (gc) gVirtualX->ChangeGC(gc, &gv);
1333 }
1334 
1335 ////////////////////////////////////////////////////////////////////////////////
1336 /// Draw image on the drawable wid (pixmap, window) at x,y position.
1337 ///
1338 /// \param[in] wid : Drawable (pixmap or window) on which image is drawn.
1339 /// \param[in] x,y : Window coordinates where image is drawn.
1340 /// \param[in] xsrc, ysrc : X and Y coordinates of an image area to be drawn.
1341 /// \param[in] wsrc, hsrc : Width and height image area to be drawn.
1342 
1344  UInt_t wsrc, UInt_t hsrc, Option_t *opt)
1345 {
1347  xsrc, ysrc, wsrc, hsrc, opt);
1348 }
1349 
1350 ////////////////////////////////////////////////////////////////////////////////
1351 /// Paint image.
1352 /// Support the following drawing options:
1353 /// - "T[x,y[,tint]]" : tile image (use specified offset and tint),
1354 /// e.g. "T100,100,#556655"
1355 /// with this option the zooming is not possible
1356 /// and disabled
1357 /// - "N" : display in new canvas (of original image size)
1358 /// - "X" : image is drawn expanded to pad size
1359 /// - "Z" : image is vectorized and image palette is drawn
1360 ///
1361 /// The default is to display the image in the current gPad.
1362 
1364 {
1365  if (!fImage) {
1366  Error("Paint", "no image set");
1367  return;
1368  }
1369 
1370  if (!InitVisual()) {
1371  Warning("Paint", "Visual not initiated");
1372  return;
1373  }
1374 
1375  Int_t tile_x = 0, tile_y = 0;
1376  CARD32 tile_tint = 0;
1377  Bool_t tile = kFALSE;
1378  Bool_t expand = kFALSE;
1379 
1380  TString opt = option;
1381  opt.ToLower();
1382 
1383  if (opt.Contains("t")) {
1384  char stint[64];
1385  if (sscanf(opt.Data() + opt.Index("t"), "t%d,%d,%s", &tile_x, &tile_y,
1386  stint) <= 3) {
1387  tile = kTRUE;
1388  if (parse_argb_color(stint, (CARD32*)&tile_tint) == stint)
1389  tile_tint = 0;
1390  } else {
1391  Error("Paint", "tile option error");
1392  }
1393  } else if (opt.Contains("x")) {
1394  expand = kTRUE;
1395  fConstRatio = kFALSE;
1396  } else if (opt.Contains("z")) {
1398 
1399  if (!fImage->alt.vector) {
1400  Vectorize(256);
1401  }
1402  }
1403 
1404  ASImage *image = fImage;
1405 
1406  // Get geometry of pad
1407  Int_t to_w = gPad->UtoPixel(1.);
1408  Int_t to_h = gPad->VtoPixel(0.);
1409 
1410  // remove the size by the margin of the pad
1411  if (!expand) {
1412  to_h = (Int_t)(to_h * (1.0 - gPad->GetBottomMargin() - gPad->GetTopMargin() ) + 0.5);
1413  to_w = (Int_t)(to_w * (1.0 - gPad->GetLeftMargin() - gPad->GetRightMargin() ) + 0.5);
1414  }
1415 
1416  if ((to_w < 25 || to_h < 25) && !expand) {
1417  Error("Paint", "pad too small to display an image");
1418  return;
1419  }
1420 
1421  if (GetConstRatio()) {
1422  if ((Double_t)to_w / (Double_t)fZoomWidth <
1423  (Double_t)to_h / (Double_t)fZoomHeight)
1424  to_h = Int_t(Double_t(fZoomHeight) * to_w / fZoomWidth);
1425  else
1426  to_w = Int_t(Double_t(fZoomWidth) * to_h / fZoomHeight);
1427  }
1428  // upper left corner and size of the palette in pixels
1429  Int_t pal_Ax = to_w + gPad->UtoAbsPixel(gPad->GetLeftMargin()) +
1430  (gPad->UtoAbsPixel(gPad->GetRightMargin()) / 10);
1431  Int_t pal_Ay = gPad->YtoAbsPixel(1.0);
1432  Int_t pal_x = to_w + gPad->UtoPixel(gPad->GetLeftMargin()) +
1433  (gPad->UtoPixel(gPad->GetRightMargin()) / 10);
1434  Int_t pal_y = gPad->YtoPixel(1.0);
1435  Int_t pal_w = gPad->UtoPixel(gPad->GetRightMargin()) / 3;
1436  Int_t pal_h = to_h;
1437 
1438  ASImage *grad_im = 0;
1439 
1440  if (fImage->alt.vector && fPaletteEnabled) {
1441  // draw the palette
1442  ASGradient grad;
1443  const TImagePalette &pal = GetPalette();
1444 
1445  grad.npoints = pal.fNumPoints;
1446  grad.type = GRADIENT_Top2Bottom;
1447  grad.color = new ARGB32[grad.npoints];
1448  grad.offset = new double[grad.npoints];
1449 
1450  for (Int_t pt = 0; pt < grad.npoints; pt++) {
1451  Int_t oldPt = grad.npoints - pt -1;
1452  grad.offset[pt] = 1 - pal.fPoints[oldPt];
1453  grad.color[pt] = (((ARGB32)(pal.fColorBlue[oldPt] & 0xff00)) >> 8) |
1454  (((ARGB32)(pal.fColorGreen[oldPt] & 0xff00)) ) |
1455  (((ARGB32)(pal.fColorRed[oldPt] & 0xff00)) << 8) |
1456  (((ARGB32)(pal.fColorAlpha[oldPt] & 0xff00)) << 16);
1457  }
1458 
1459  grad_im = make_gradient(fgVisual, &grad , UInt_t(pal_w),
1460  pal_h, SCL_DO_COLOR,
1461  ASA_ARGB32, GetImageCompression(), GetImageQuality());
1462 
1463  delete [] grad.color;
1464  delete [] grad.offset;
1465  }
1466 
1467  if (tile) {
1468  delete fScaledImage;
1470  if (!fScaledImage) return;
1471  fScaledImage->fImage = tile_asimage(fgVisual, fImage, tile_x, tile_y,
1472  to_w, to_h, tile_tint, ASA_ASImage,
1474  image = fScaledImage->fImage;
1475 
1476  } else if (fZoomUpdate == kZoomOps) {
1477  image = fImage;
1478 
1479  } else {
1480  // Scale and zoom image if needed
1481  if (Int_t(fImage->width) != to_w || Int_t(fImage->height) != to_h ||
1482  fImage->width != fZoomWidth || fImage->height != fZoomHeight) {
1483 
1484  if (fScaledImage && (Int_t(fScaledImage->GetWidth()) != to_w ||
1485  Int_t(fScaledImage->GetHeight()) != to_h ||
1486  fZoomUpdate)) {
1487 
1488  delete fScaledImage;
1489  fScaledImage = 0;
1490  }
1491 
1492  if (!fScaledImage) {
1494  if (!fScaledImage) return;
1495 
1496  if (fZoomWidth && fZoomHeight &&
1497  ((fImage->width != fZoomWidth) || (fImage->height != fZoomHeight))) {
1498  // zoom and scale image
1499  ASImage *tmpImage = 0;
1500 
1501  tmpImage = tile_asimage(fgVisual, fImage, fZoomOffX,
1502  fImage->height - fZoomHeight - fZoomOffY,
1503  fZoomWidth, fZoomHeight, 0, ASA_ASImage,
1505 
1506  if (tmpImage) {
1507  fScaledImage->fImage = scale_asimage(fgVisual, tmpImage, to_w, to_h,
1508  ASA_ASImage, GetImageCompression(),
1509  GetImageQuality());
1510  destroy_asimage(&tmpImage);
1511  }
1512  } else {
1513  // scale image, no zooming
1514  fScaledImage->fImage = scale_asimage(fgVisual, fImage, to_w, to_h,
1515  ASA_ASImage, GetImageCompression(),
1516  GetImageQuality());
1517  }
1518  }
1519  image = fScaledImage->fImage;
1520  }
1521  }
1522  fZoomUpdate = 0;
1523 
1524  if (!image) {
1525  Error("Paint", "image could not be rendered to display");
1526  return;
1527  }
1528 
1529  int tox = expand ? 0 : int(gPad->UtoPixel(1.) * gPad->GetLeftMargin());
1530  int toy = expand ? 0 : int(gPad->VtoPixel(0.) * gPad->GetTopMargin());
1531 
1532  if (!gROOT->IsBatch()) {
1533  Window_t wid = (Window_t)gVirtualX->GetWindowID(gPad->GetPixmapID());
1534  Image2Drawable(fScaledImage ? fScaledImage->fImage : fImage, wid, tox, toy);
1535 
1536  if (grad_im && fPaletteEnabled) {
1537  // draw color bar
1538  Image2Drawable(grad_im, wid, pal_x, pal_y);
1539 
1540  // values of palette
1541  TGaxis axis;
1542  Int_t ndiv = 510;
1543  double min = fMinValue;
1544  double max = fMaxValue;
1545  axis.SetLineColor(0); // draw white ticks
1546  Double_t pal_Xpos = gPad->AbsPixeltoX(pal_Ax + pal_w);
1547  axis.PaintAxis(pal_Xpos, gPad->PixeltoY(pal_Ay + pal_h - 1),
1548  pal_Xpos, gPad->PixeltoY(pal_Ay),
1549  min, max, ndiv, "+LU");
1550  min = fMinValue;
1551  max = fMaxValue;
1552  axis.SetLineColor(1); // draw black ticks
1553  axis.PaintAxis(pal_Xpos, gPad->AbsPixeltoY(pal_Ay + pal_h),
1554  pal_Xpos, gPad->AbsPixeltoY(pal_Ay + 1),
1555  min, max, ndiv, "+L");
1556  }
1557  }
1558 
1559  // loop over pixmap and draw image to PostScript
1560  if (gVirtualPS) {
1561  if (gVirtualPS->InheritsFrom("TImageDump")) { // PostScript is asimage
1562  TImage *dump = (TImage *)gVirtualPS->GetStream();
1563  if (!dump) return;
1564  dump->Merge(fScaledImage ? fScaledImage : this, "alphablend",
1565  gPad->XtoAbsPixel(0), gPad->YtoAbsPixel(1));
1566 
1567  if (grad_im) {
1568  TASImage tgrad;
1569  tgrad.fImage = grad_im;
1570  dump->Merge(&tgrad, "alphablend", pal_Ax, pal_Ay);
1571 
1572  // values of palette
1573  TGaxis axis;
1574  Int_t ndiv = 510;
1575  double min = fMinValue;
1576  double max = fMaxValue;
1577  axis.SetLineColor(1); // draw black ticks
1578  Double_t pal_Xpos = gPad->AbsPixeltoX(pal_Ax + pal_w);
1579  axis.PaintAxis(pal_Xpos, gPad->AbsPixeltoY(pal_Ay + pal_h),
1580  pal_Xpos, gPad->AbsPixeltoY(pal_Ay + 1),
1581  min, max, ndiv, "+L");
1582  }
1583  return;
1584  } else if (gVirtualPS->InheritsFrom("TPDF")) {
1585  Warning("Paint", "PDF not implemented yet");
1586  return;
1587  } else if (gVirtualPS->InheritsFrom("TSVG")) {
1588  Warning("Paint", "SVG not implemented yet");
1589  return;
1590  }
1591 
1592  // get special color cell to be reused during image printing
1593  TObjArray *colors = (TObjArray*) gROOT->GetListOfColors();
1594  TColor *color = 0;
1595  // Look for color by name
1596  if ((color = (TColor*)colors->FindObject("Image_PS")) == 0)
1597  color = new TColor(colors->GetEntries(), 1., 1., 1., "Image_PS");
1598 
1599  gVirtualPS->SetFillColor(color->GetNumber());
1600  gVirtualPS->SetFillStyle(1001);
1601 
1602  Double_t dx = gPad->GetX2()-gPad->GetX1();
1603  Double_t dy = gPad->GetY2()-gPad->GetY1();
1604  Double_t x1,x2,y1,y2;
1605 
1606  if (expand) {
1607  x1 = gPad->GetX1();
1608  x2 = x1+dx/image->width;
1609  y1 = gPad->GetY2();
1610  y2 = y1+dy/image->height;
1611  } else {
1612  x1 = gPad->GetX1()+dx*gPad->GetLeftMargin();
1613  x2 = x1+(dx*(1-gPad->GetRightMargin()-gPad->GetLeftMargin()))/image->width;
1614  y1 = gPad->GetY2()-dy*gPad->GetTopMargin();
1615  y2 = y1+(dy*(1-gPad->GetTopMargin()-gPad->GetBottomMargin()))/image->height;
1616  }
1617 
1618  gVirtualPS->CellArrayBegin(image->width, image->height, x1, x2, y1, y2);
1619 
1620  ASImageDecoder *imdec = start_image_decoding(fgVisual, image, SCL_DO_ALL,
1621  0, 0, image->width, image->height, 0);
1622  if (!imdec) return;
1623  for (Int_t yt = 0; yt < (Int_t)image->height; yt++) {
1624  imdec->decode_image_scanline(imdec);
1625  for (Int_t xt = 0; xt < (Int_t)image->width; xt++)
1626  gVirtualPS->CellArrayFill(imdec->buffer.red[xt],
1627  imdec->buffer.green[xt],
1628  imdec->buffer.blue[xt]);
1629  }
1630  stop_image_decoding(&imdec);
1632 
1633  // print the color bar
1634  if (grad_im) {
1635  Double_t xconv = (gPad->AbsPixeltoX(pal_Ax + pal_w) - gPad->AbsPixeltoX(pal_Ax)) / grad_im->width;
1636  Double_t yconv = (gPad->AbsPixeltoY(pal_Ay - pal_h) - gPad->AbsPixeltoY(pal_Ay)) / grad_im->height;
1637  x1 = gPad->AbsPixeltoX(pal_Ax);
1638  x2 = x1 + xconv;
1639  y2 = gPad->AbsPixeltoY(pal_Ay);
1640  y1 = y2 - yconv;
1641  gVirtualPS->CellArrayBegin(grad_im->width, grad_im->height,
1642  x1, x2, y1, y2);
1643 
1644  imdec = start_image_decoding(fgVisual, grad_im, SCL_DO_ALL,
1645  0, 0, grad_im->width, grad_im->height, 0);
1646  if (imdec) {
1647  for (Int_t yt = 0; yt < (Int_t)grad_im->height; yt++) {
1648  imdec->decode_image_scanline(imdec);
1649  for (Int_t xt = 0; xt < (Int_t)grad_im->width; xt++)
1650  gVirtualPS->CellArrayFill(imdec->buffer.red[xt],
1651  imdec->buffer.green[xt],
1652  imdec->buffer.blue[xt]);
1653  }
1654  }
1655  stop_image_decoding(&imdec);
1657 
1658  // values of palette
1659  TGaxis axis;
1660  Int_t ndiv = 510;
1661  double min = fMinValue;
1662  double max = fMaxValue;
1663  axis.SetLineColor(1); // draw black ticks
1664  Double_t pal_Xpos = gPad->AbsPixeltoX(pal_Ax + pal_w);
1665  axis.PaintAxis(pal_Xpos, gPad->AbsPixeltoY(pal_Ay + pal_h),
1666  pal_Xpos, gPad->AbsPixeltoY(pal_Ay + 1),
1667  min, max, ndiv, "+L");
1668 
1669  }
1670  }
1671 
1672  if (grad_im) {
1673  destroy_asimage(&grad_im);
1674  }
1675 }
1676 
1677 ////////////////////////////////////////////////////////////////////////////////
1678 /// Is the mouse in the image ?
1679 
1681 {
1682  Int_t pxl, pyl, pxt, pyt;
1683 
1684  Int_t px1 = gPad->XtoAbsPixel(0);
1685  Int_t py1 = gPad->YtoAbsPixel(0);
1686  Int_t px2 = gPad->XtoAbsPixel(1);
1687  Int_t py2 = gPad->YtoAbsPixel(1);
1688 
1689  if (px1 < px2) {pxl = px1; pxt = px2;}
1690  else {pxl = px2; pxt = px1;}
1691  if (py1 < py2) {pyl = py1; pyt = py2;}
1692  else {pyl = py2; pyt = py1;}
1693 
1694  if ((px > pxl && px < pxt) && (py > pyl && py < pyt))
1695  return 0;
1696 
1697  return 999999;
1698 }
1699 
1700 ////////////////////////////////////////////////////////////////////////////////
1701 /// Execute mouse events.
1702 
1704 {
1705  static TBox *ZoomBox;
1706 
1707  if (!gPad) return;
1708 
1709  if (IsEditable()) {
1710  gPad->ExecuteEvent(event, px, py);
1711  return;
1712  }
1713 
1714  gPad->SetCursor(kCross);
1715 
1716  static Int_t px1old, py1old, px2old, py2old;
1717  static Int_t px1, py1, px2, py2, pxl, pyl, pxt, pyt;
1718 
1719  if (!IsValid()) return;
1720 
1721  if (event == kButton1Motion || event == kButton1Down ||
1722  event == kButton1Up) {
1723 
1724  // convert to image pixel on screen
1725  Int_t imgX = px - gPad->XtoAbsPixel(0);
1726  Int_t imgY = py - gPad->YtoAbsPixel(1);
1727 
1728  if (imgX < 0) px = px - imgX;
1729  if (imgY < 0) py = py - imgY;
1730 
1731  ASImage *image = fImage;
1732  if (fScaledImage) image = fScaledImage->fImage;
1733 
1734  if (imgX >= (int)image->width) px = px - imgX + image->width - 1;
1735  if (imgY >= (int)image->height) py = py - imgY + image->height - 1;
1736 
1737  switch (event) {
1738 
1739  case kButton1Down:
1740  px1 = gPad->XtoAbsPixel(gPad->GetX1());
1741  py1 = gPad->YtoAbsPixel(gPad->GetY1());
1742  px2 = gPad->XtoAbsPixel(gPad->GetX2());
1743  py2 = gPad->YtoAbsPixel(gPad->GetY2());
1744  px1old = px; py1old = py;
1745  break;
1746 
1747  case kButton1Motion:
1748  px2old = px;
1749  px2old = TMath::Max(px2old, px1);
1750  px2old = TMath::Min(px2old, px2);
1751  py2old = py;
1752  py2old = TMath::Max(py2old, py2);
1753  py2old = TMath::Min(py2old, py1);
1754  pxl = TMath::Min(px1old, px2old);
1755  pxt = TMath::Max(px1old, px2old);
1756  pyl = TMath::Max(py1old, py2old);
1757  pyt = TMath::Min(py1old, py2old);
1758 
1759  if (ZoomBox) {
1760  ZoomBox->SetX1(gPad->AbsPixeltoX(pxl));
1761  ZoomBox->SetY1(gPad->AbsPixeltoY(pyl));
1762  ZoomBox->SetX2(gPad->AbsPixeltoX(pxt));
1763  ZoomBox->SetY2(gPad->AbsPixeltoY(pyt));
1764  }
1765  else {
1766  ZoomBox = new TBox(pxl, pyl, pxt, pyt);
1767  ZoomBox->SetFillStyle(0);
1768  ZoomBox->Draw("l*");
1769  }
1770  gPad->Modified(kTRUE);
1771  gPad->Update();
1772  break;
1773 
1774  case kButton1Up:
1775  // do nothing if zoom area is too small
1776  if ( TMath::Abs(pxl - pxt) < 5 || TMath::Abs(pyl - pyt) < 5)
1777  return;
1778 
1779  pxl = 0;
1780  pxt = 0;
1781  pyl = 0;
1782  pyt = 0;
1783 
1784  Double_t xfact = (fScaledImage) ? (Double_t)fScaledImage->fImage->width / fZoomWidth : 1;
1785  Double_t yfact = (fScaledImage) ? (Double_t)fScaledImage->fImage->height / fZoomHeight : 1;
1786 
1787  Int_t imgX1 = px1old - gPad->XtoAbsPixel(0);
1788  Int_t imgY1 = py1old - gPad->YtoAbsPixel(1);
1789  Int_t imgX2 = px - gPad->XtoAbsPixel(0);
1790  Int_t imgY2 = py - gPad->YtoAbsPixel(1);
1791 
1792  imgY1 = image->height - 1 - imgY1;
1793  imgY2 = image->height - 1 - imgY2;
1794  imgX1 = (Int_t)(imgX1 / xfact) + fZoomOffX;
1795  imgY1 = (Int_t)(imgY1 / yfact) + fZoomOffY;
1796  imgX2 = (Int_t)(imgX2 / xfact) + fZoomOffX;
1797  imgY2 = (Int_t)(imgY2 / yfact) + fZoomOffY;
1798 
1799  Zoom((imgX1 < imgX2) ? imgX1 : imgX2, (imgY1 < imgY2) ? imgY1 : imgY2,
1800  TMath::Abs(imgX1 - imgX2) + 1, TMath::Abs(imgY1 - imgY2) + 1);
1801 
1802  if (ZoomBox) {
1803  ZoomBox->Delete();
1804  ZoomBox = 0;
1805  }
1806  gPad->Modified(kTRUE);
1807  gPad->Update();
1808  break;
1809  }
1810  }
1811 }
1812 
1813 ////////////////////////////////////////////////////////////////////////////////
1814 /// Get image pixel coordinates and the pixel value at the mouse pointer.
1815 
1817 {
1818  static char info[64];
1819  info[0] = 0;
1820 
1821  if (!IsValid()) return info;
1822 
1823  // convert to image pixel on screen
1824  px -= gPad->XtoAbsPixel(0);
1825  py -= gPad->YtoAbsPixel(1);
1826 
1827  // no info if mouse is outside of image
1828  if (px < 0 || py < 0) return info;
1829 
1830  ASImage *image = fImage;
1831  if (fScaledImage) image = fScaledImage->fImage;
1832  if (px >= (int)image->width || py >= (int)image->height)
1833  return info;
1834 
1835  py = image->height - 1 - py;
1836  // convert to original image size and take zooming into account
1837  if (fScaledImage) {
1838  px = (Int_t)(px / (Double_t)fScaledImage->fImage->width * fZoomWidth ) + fZoomOffX;
1839  py = (Int_t)(py / (Double_t)fScaledImage->fImage->height * fZoomHeight) + fZoomOffY;
1840  }
1841 
1842  if (fImage->alt.vector) {
1843  snprintf(info,64,"x: %d y: %d %.5g",
1844  px, py, fImage->alt.vector[px + py * fImage->width]);
1845  } else {
1846  snprintf(info,64,"x: %d y: %d", px, py);
1847  }
1848 
1849  return info;
1850 }
1851 
1852 ////////////////////////////////////////////////////////////////////////////////
1853 /// Set a new palette to an image.
1854 /// Only images that were created with the SetImage() functions can be
1855 /// modified with this function. The previously used palette is destroyed.
1856 
1858 {
1859  TAttImage::SetPalette(palette);
1860 
1861  if (!InitVisual()) {
1862  Warning("SetPalette", "Visual not initiated");
1863  return;
1864  }
1865 
1866  if (!IsValid()) {
1867  Warning("SetPalette", "Image not valid");
1868  return;
1869  }
1870 
1871  if (fImage->alt.vector == 0)
1872  return;
1873 
1874  // copy ROOT palette to asImage palette
1875  const TImagePalette &pal = GetPalette();
1876 
1877  ASVectorPalette asPalette;
1878  asPalette.npoints = pal.fNumPoints;
1879  asPalette.channels[0] = new CARD16 [asPalette.npoints];
1880  asPalette.channels[1] = new CARD16 [asPalette.npoints];
1881  asPalette.channels[2] = new CARD16 [asPalette.npoints];
1882  asPalette.channels[3] = new CARD16 [asPalette.npoints];
1883  memcpy(asPalette.channels[0], pal.fColorBlue, pal.fNumPoints * sizeof(UShort_t));
1884  memcpy(asPalette.channels[1], pal.fColorGreen, pal.fNumPoints * sizeof(UShort_t));
1885  memcpy(asPalette.channels[2], pal.fColorRed, pal.fNumPoints * sizeof(UShort_t));
1886  memcpy(asPalette.channels[3], pal.fColorAlpha, pal.fNumPoints * sizeof(UShort_t));
1887 
1888  asPalette.points = new double[asPalette.npoints];
1889  for (Int_t point = 0; point < Int_t(asPalette.npoints); point++)
1890  asPalette.points[point] = fMinValue + (fMaxValue - fMinValue) * pal.fPoints[point];
1891 
1892  // use the new palette in this image
1893  colorize_asimage_vector(fgVisual, fImage, &asPalette, ASA_ASImage, GetImageQuality());
1894 
1895  delete [] asPalette.points;
1896  for (Int_t col = 0; col < 4; col++)
1897  delete [] asPalette.channels[col];
1898 
1899 
1900  delete fScaledImage;
1901  fScaledImage = 0;
1902 }
1903 
1904 ////////////////////////////////////////////////////////////////////////////////
1905 /// Scale the original image.
1906 /// The size of the image on the screen does not change because it is defined
1907 /// by the size of the pad.
1908 /// This function can be used to change the size of an image before writing
1909 /// it into a file. The colors of the new pixels are interpolated.
1910 /// An image created with the SetImage() functions cannot be modified with
1911 /// the function SetPalette() any more after a call of this function!
1912 
1913 void TASImage::Scale(UInt_t toWidth, UInt_t toHeight)
1914 {
1915  if (!IsValid()) {
1916  Warning("Scale", "Image not initiated");
1917  return;
1918  }
1919 
1920  if (!InitVisual()) {
1921  Warning("Scale", "Visual not initiated");
1922  return;
1923  }
1924 
1925  if (toWidth < 1)
1926  toWidth = 1;
1927  if (toHeight < 1 )
1928  toHeight = 1;
1929  if (toWidth > 30000)
1930  toWidth = 30000;
1931  if (toHeight > 30000)
1932  toHeight = 30000;
1933 
1934  ASImage *img = scale_asimage(fgVisual, fImage, toWidth, toHeight,
1935  ASA_ASImage, GetImageCompression(),
1936  GetImageQuality());
1937  DestroyImage();
1938  fImage = img;
1939  UnZoom();
1941 }
1942 
1943 ////////////////////////////////////////////////////////////////////////////////
1944 /// Another method of enlarging images where corners remain unchanged,
1945 /// but middle part gets tiled.
1946 
1947 void TASImage::Slice(UInt_t xStart, UInt_t xEnd, UInt_t yStart, UInt_t yEnd,
1948  UInt_t toWidth, UInt_t toHeight)
1949 {
1950  if (!IsValid()) {
1951  Warning("Scale", "Image not initiated");
1952  return;
1953  }
1954 
1955  if (!InitVisual()) {
1956  Warning("Scale", "Visual not initiated");
1957  return;
1958  }
1959 
1960  if (toWidth < 1)
1961  toWidth = 1;
1962  if (toHeight < 1 )
1963  toHeight = 1;
1964  if (toWidth > 30000)
1965  toWidth = 30000;
1966  if (toHeight > 30000)
1967  toHeight = 30000;
1968 
1969  ASImage *img = slice_asimage(fgVisual, fImage, xStart, xEnd,
1970  yStart, yEnd, toWidth, toHeight,
1971  ASA_ASImage, GetImageCompression(),
1972  GetImageQuality());
1973 
1974  DestroyImage();
1975  fImage = img;
1976  UnZoom();
1978 }
1979 
1980 ////////////////////////////////////////////////////////////////////////////////
1981 /// Tile the original image.
1982 
1983 void TASImage::Tile(UInt_t toWidth, UInt_t toHeight)
1984 {
1985  if (!IsValid()) {
1986  Warning("Tile", "Image not initiated");
1987  return;
1988  }
1989 
1990  if (!InitVisual()) {
1991  Warning("Tile", "Visual not initiated");
1992  return;
1993  }
1994 
1995  if (toWidth < 1)
1996  toWidth = 1;
1997  if (toHeight < 1 )
1998  toHeight = 1;
1999  if (toWidth > 30000)
2000  toWidth = 30000;
2001  if (toHeight > 30000)
2002  toHeight = 30000;
2003 
2004  ASImage *img = tile_asimage(fgVisual, fImage, 0, 0, toWidth, toHeight, 0,
2005  ASA_ASImage, GetImageCompression(), GetImageQuality());
2006  DestroyImage();
2007  fImage = img;
2008  UnZoom();
2010 }
2011 
2012 ////////////////////////////////////////////////////////////////////////////////
2013 /// The area of an image displayed in a pad is defined by this function.
2014 /// Note: the size on the screen is defined by the size of the pad.
2015 /// The original image is not modified by this function.
2016 /// If width or height is larger than the original image they are reduced to
2017 /// the width and height of the image.
2018 /// If the off values are too large (off + width > image width) than the off
2019 /// values are decreased. For example: offX = image width - width
2020 /// Note: the parameters are always relative to the original image not to the
2021 /// size of an already zoomed image.
2022 
2023 void TASImage::Zoom(UInt_t offX, UInt_t offY, UInt_t width, UInt_t height)
2024 {
2025  if (!IsValid()) {
2026  Warning("Zoom", "Image not valid");
2027  return;
2028  }
2029  fZoomUpdate = kZoom;
2030 
2031  fZoomWidth = (width == 0) ? 1 : ((width > fImage->width) ? fImage->width : width);
2032  fZoomHeight = (height == 0) ? 1 : ((height > fImage->height) ? fImage->height : height);
2033  fZoomOffX = offX;
2034  if (fZoomOffX + fZoomWidth > fImage->width)
2035  fZoomOffX = fImage->width - fZoomWidth;
2036  fZoomOffY = offY;
2037  if (fZoomOffY + fZoomHeight > fImage->height)
2038  fZoomOffY = fImage->height - fZoomHeight;
2039 }
2040 
2041 ////////////////////////////////////////////////////////////////////////////////
2042 /// Un-zoom the image to original size.
2043 /// UnZoom() - performs undo for Zoom,Crop,Scale actions
2044 
2046 {
2047  if (!IsValid()) {
2048  Warning("UnZoom", "Image not valid");
2049  return;
2050  }
2051  fZoomUpdate = kZoom;
2052  fZoomOffX = 0;
2053  fZoomOffY = 0;
2054  fZoomWidth = fImage->width;
2055  fZoomHeight = fImage->height;
2056 
2057  delete fScaledImage;
2058  fScaledImage = 0;
2059 }
2060 
2061 ////////////////////////////////////////////////////////////////////////////////
2062 /// Flip image in place.
2063 ///
2064 /// Flip is either 90, 180, 270, 180 is default.
2065 /// This function manipulates the original image and destroys the
2066 /// scaled and zoomed image which will be recreated at the next call of
2067 /// the Draw function. If the image is zoomed the zoom - coordinates are
2068 /// now relative to the new image.
2069 /// This function cannot be used for images which were created with the
2070 /// SetImage() functions, because the original pixel values would be
2071 /// destroyed.
2072 
2074 {
2075  if (!IsValid()) {
2076  Warning("Flip", "Image not valid");
2077  return;
2078  }
2079  if (!InitVisual()) {
2080  Warning("Flip", "Visual not initiated");
2081  return;
2082  }
2083 
2084  if (fImage->alt.vector) {
2085  Warning("Flip", "flip does not work for data images");
2086  return;
2087  }
2088 
2089  Int_t rflip = flip/90;
2090 
2091  UInt_t w = fImage->width;
2092  UInt_t h = fImage->height;
2093 
2094  if (rflip & 1) {
2095  w = fImage->height;
2096  h = fImage->width;
2097  }
2098 
2099  ASImage *img = flip_asimage(fgVisual, fImage, 0, 0, w, h, rflip,
2100  ASA_ASImage, GetImageCompression(),
2101  GetImageQuality());
2102  DestroyImage();
2103  fImage = img;
2104  UnZoom();
2105 }
2106 
2107 ////////////////////////////////////////////////////////////////////////////////
2108 /// Mirror image in place.
2109 ///
2110 /// If vert is true mirror in vertical axis, horizontal otherwise.
2111 /// Vertical is default.
2112 /// This function manipulates the original image and destroys the
2113 /// scaled and zoomed image which will be recreated at the next call of
2114 /// the Draw function. If the image is zoomed the zoom - coordinates are
2115 /// now relative to the new image.
2116 /// This function cannot be used for images which were created with the
2117 /// SetImage() functions, because the original pixel values would be
2118 /// destroyed.
2119 
2121 {
2122  if (!IsValid()) {
2123  Warning("Mirror", "Image not valid");
2124  return;
2125  }
2126 
2127  if (!InitVisual()) {
2128  Warning("Mirror", "Visual not initiated");
2129  return;
2130  }
2131 
2132  if (fImage->alt.vector) {
2133  Warning("Mirror", "mirror does not work for data images");
2134  return;
2135  }
2136 
2137  ASImage *img = mirror_asimage(fgVisual, fImage, 0, 0,
2138  fImage->width, fImage->height, vert,
2139  ASA_ASImage, GetImageCompression(),
2140  GetImageQuality());
2141  DestroyImage();
2142  fImage = img;
2143  UnZoom();
2144 }
2145 
2146 ////////////////////////////////////////////////////////////////////////////////
2147 /// Return width of original image not of the displayed image.
2148 /// (Number of image pixels)
2149 
2151 {
2152  return fImage ? fImage->width : 0;
2153 }
2154 
2155 ////////////////////////////////////////////////////////////////////////////////
2156 /// Return height of original image not of the displayed image.
2157 /// (Number of image pixels)
2158 
2160 {
2161  return fImage ? fImage->height : 0;
2162 }
2163 
2164 ////////////////////////////////////////////////////////////////////////////////
2165 /// Return width of the displayed image not of the original image.
2166 /// (Number of screen pixels)
2167 
2169 {
2170  return fScaledImage ? fScaledImage->fImage->width : GetWidth();
2171 }
2172 
2173 ////////////////////////////////////////////////////////////////////////////////
2174 /// Return height of the displayed image not of the original image.
2175 /// (Number of screen pixels)
2176 
2178 {
2179  return fScaledImage ? fScaledImage->fImage->height : GetHeight();
2180 }
2181 
2182 ////////////////////////////////////////////////////////////////////////////////
2183 /// Return the zoom parameters.
2184 /// This is useful when the zoom has been done interactively using the mouse.
2185 
2187 {
2188  x = fZoomOffX;
2189  y = fZoomOffY;
2190  w = fZoomWidth;
2191  h = fZoomHeight;
2192 }
2193 
2194 ////////////////////////////////////////////////////////////////////////////////
2195 /// Static function to initialize the ASVisual.
2196 
2198 {
2199  Display *disp;
2200 
2201  Bool_t inbatch = fgVisual && (fgVisual->dpy == (void*)1); // was in batch
2202  Bool_t noX = gROOT->IsBatch() || gVirtualX->InheritsFrom("TGWin32");
2203 
2204  // was in batch, but switched to gui
2205  if (inbatch && !noX) {
2206  destroy_asvisual(fgVisual, kFALSE);
2207  fgVisual = 0;
2208  }
2209 
2210  if (fgVisual && fgVisual->dpy) { // already initialized
2211  return kTRUE;
2212  }
2213 
2214  // batch or win32 mode
2215  if (!fgVisual && noX) {
2216  disp = 0;
2217  fgVisual = create_asvisual(0, 0, 0, 0);
2218  fgVisual->dpy = (Display*)1; //fake (not used)
2219  return kTRUE;
2220  }
2221 
2222 #ifndef WIN32
2223 #ifdef R__HAS_COCOA
2224  fgVisual = create_asvisual(0, 0, 0, 0);
2225  fgVisual->dpy = (Display*)1; //fake (not used)
2226 #else
2227  disp = (Display*) gVirtualX->GetDisplay();
2228  Int_t screen = gVirtualX->GetScreen();
2229  Int_t depth = gVirtualX->GetDepth();
2230  Visual *vis = (Visual*) gVirtualX->GetVisual();
2231  Colormap cmap = (Colormap) gVirtualX->GetColormap();
2232 
2233  if (vis == 0 || cmap == 0) {
2234  fgVisual = create_asvisual(0, 0, 0, 0);
2235  } else {
2236  fgVisual = create_asvisual_for_id(disp, screen, depth,
2237  XVisualIDFromVisual(vis), cmap, 0);
2238  }
2239 #endif
2240 #else
2241  fgVisual = create_asvisual(0, 0, 0, 0);
2242  fgVisual->dpy = (Display*)1; //fake (not used)
2243 #endif
2244 
2245  return kTRUE;
2246 }
2247 
2248 ////////////////////////////////////////////////////////////////////////////////
2249 /// Start palette editor.
2250 
2252 {
2253  if (!IsValid()) {
2254  Warning("StartPaletteEditor", "Image not valid");
2255  return;
2256  }
2257  if (fImage->alt.vector == 0) {
2258  Warning("StartPaletteEditor", "palette can be modified only for data images");
2259  return;
2260  }
2261 
2262  // Opens a GUI to edit the color palette
2264 }
2265 
2266 ////////////////////////////////////////////////////////////////////////////////
2267 /// Returns image pixmap.
2268 /// The pixmap must deleted by user.
2269 
2271 {
2272  if (!InitVisual()) {
2273  Warning("GetPixmap", "Visual not initiated");
2274  return 0;
2275  }
2276 
2277  Pixmap_t ret;
2278 
2279  ASImage *img = fScaledImage ? fScaledImage->fImage : fImage;
2280 
2281  static int x11 = -1;
2282  if (x11 < 0) x11 = gVirtualX->InheritsFrom("TGX11");
2283 
2284  if (x11) { // use builtin version
2285  ret = (Pixmap_t)asimage2pixmap(fgVisual, gVirtualX->GetDefaultRootWindow(),
2286  img, 0, kTRUE);
2287  } else {
2288  if (!fImage->alt.argb32) {
2289  BeginPaint();
2290  }
2291  ret = gVirtualX->CreatePixmapFromData((unsigned char*)fImage->alt.argb32,
2292  fImage->width, fImage->height);
2293  }
2294 
2295  return ret;
2296 }
2297 
2298 ////////////////////////////////////////////////////////////////////////////////
2299 /// Returns image mask pixmap (alpha channel).
2300 /// The pixmap must deleted by user.
2301 
2303 {
2304  Pixmap_t pxmap = 0;
2305 
2306  if (!InitVisual()) {
2307  Warning("GetMask", "Visual not initiated");
2308  return pxmap;
2309  }
2310 
2311  ASImage *img = fScaledImage ? fScaledImage->fImage : fImage;
2312 
2313  if (!img) {
2314  Warning("GetMask", "No image");
2315  return pxmap;
2316  }
2317 
2318  UInt_t hh = img->height;
2319  UInt_t ow = img->width%8;
2320  UInt_t ww = img->width - ow + (ow ? 8 : 0);
2321 
2322  UInt_t bit = 0;
2323  int i = 0;
2324  UInt_t y = 0;
2325  UInt_t x = 0;
2326 
2327  char *bits = new char[ww*hh]; //an array of bits
2328 
2329  ASImageDecoder *imdec = start_image_decoding(fgVisual, img, SCL_DO_ALPHA,
2330  0, 0, ww, 0, 0);
2331  if (!imdec) {
2332  delete [] bits;
2333  return 0;
2334  }
2335 
2336  for (y = 0; y < hh; y++) {
2337  imdec->decode_image_scanline(imdec);
2338  CARD32 *a = imdec->buffer.alpha;
2339 
2340  for (x = 0; x < ww; x++) {
2341  if (a[x]) {
2342  SETBIT(bits[i], bit);
2343  } else {
2344  CLRBIT(bits[i], bit);
2345  }
2346  bit++;
2347  if (bit == 8) {
2348  bit = 0;
2349  i++;
2350  }
2351  }
2352  }
2353 
2354  stop_image_decoding(&imdec);
2355  pxmap = gVirtualX->CreateBitmap(gVirtualX->GetDefaultRootWindow(), (const char *)bits,
2356  ww, hh);
2357  delete [] bits;
2358  return pxmap;
2359 }
2360 
2361 ////////////////////////////////////////////////////////////////////////////////
2362 /// Create image from pixmap.
2363 
2365 {
2366  if (!InitVisual()) {
2367  Warning("SetImage", "Visual not initiated");
2368  return;
2369  }
2370 
2371  DestroyImage();
2372  delete fScaledImage;
2373  fScaledImage = 0;
2374 
2375  Int_t xy;
2376  UInt_t w, h;
2377  gVirtualX->GetWindowSize(pxm, xy, xy, w, h);
2378 
2379  if (fName.IsNull()) fName.Form("img_%dx%d",w, h);
2380 
2381  static int x11 = -1;
2382  if (x11 < 0) x11 = gVirtualX->InheritsFrom("TGX11");
2383 
2384  if (x11) { //use built-in optimized version
2385  fImage = picture2asimage(fgVisual, pxm, mask, 0, 0, w, h, kAllPlanes, 1, 0);
2386  } else {
2387  unsigned char *bits = gVirtualX->GetColorBits(pxm, 0, 0, w, h);
2388  if (!bits) { // error
2389  return;
2390  }
2391 
2392  // no mask
2393  if (!mask) {
2394  fImage = bitmap2asimage(bits, w, h, 0, 0);
2395  delete [] bits;
2396  return;
2397  }
2398  unsigned char *mask_bits = gVirtualX->GetColorBits(mask, 0, 0, w, h);
2399  fImage = bitmap2asimage(bits, w, h, 0, mask_bits);
2400  delete [] mask_bits;
2401  delete [] bits;
2402  }
2403 }
2404 
2405 ////////////////////////////////////////////////////////////////////////////////
2406 /// Return 2D array of machine dependent pixel values.
2407 
2409 {
2410  if (!fImage) {
2411  Warning("GetPixels", "Wrong Image");
2412  return 0;
2413  }
2414 
2415  ASImage *img = fScaledImage ? fScaledImage->fImage : fImage;
2416  ASImageDecoder *imdec;
2417 
2418  width = !width ? img->width : width;
2419  height = !height ? img->height : height;
2420 
2421  if (x < 0) {
2422  width -= x;
2423  x = 0 ;
2424  }
2425  if (y < 0) {
2426  height -= y;
2427  y = 0;
2428  }
2429 
2430  if ((x >= (int)img->width) || (y >= (int)img->height)) {
2431  return 0;
2432  }
2433 
2434  if ((int)(x + width) > (int)img->width) {
2435  width = img->width - x;
2436  }
2437 
2438  if ((int)(y + height) > (int)img->height) {
2439  height = img->height - y;
2440  }
2441 
2442  if ((imdec = start_image_decoding(0, fImage, SCL_DO_ALL, 0, y,
2443  img->width, height, 0)) == 0) {
2444  Warning("GetPixels", "Failed to create image decoder");
2445  return 0;
2446  }
2447 
2448  TArrayL *ret = new TArrayL(width * height);
2449  Int_t r = 0;
2450  Int_t g = 0;
2451  Int_t b = 0;
2452  Long_t p = 0;
2453 
2454  for (UInt_t k = 0; k < height; k++) {
2455  imdec->decode_image_scanline(imdec);
2456 
2457  for (UInt_t i = 0; i < width; ++i) {
2458  if ((r == (Int_t)imdec->buffer.red[i]) &&
2459  (g == (Int_t)imdec->buffer.green[i]) &&
2460  (b == (Int_t)imdec->buffer.blue[i])) {
2461  } else {
2462  r = (Int_t)imdec->buffer.red[i];
2463  g = (Int_t)imdec->buffer.green[i];
2464  b = (Int_t)imdec->buffer.blue[i];
2465  p = (Long_t)TColor::RGB2Pixel(r, g, b);
2466  }
2467  ret->AddAt(p, k*width + i);
2468  }
2469  }
2470 
2471  stop_image_decoding(&imdec);
2472  return ret;
2473 }
2474 
2475 ////////////////////////////////////////////////////////////////////////////////
2476 /// Return a pointer to internal array[width x height] of double values [0,1].
2477 /// This array is directly accessible. That allows to manipulate/change the
2478 /// image.
2479 
2481 {
2482  if (!fImage) {
2483  Warning("GetVecArray", "Bad Image");
2484  return 0;
2485  }
2486  if (fImage->alt.vector) {
2487  return fImage->alt.vector;
2488  }
2489  // vectorize
2490  return 0;
2491 }
2492 
2493 ////////////////////////////////////////////////////////////////////////////////
2494 /// In case of vectorized image return an associated array of doubles
2495 /// otherwise this method creates and returns a 2D array of doubles corresponding to palette.
2496 /// If palette is ZERO a color converted to double value [0, 1] according to formula
2497 /// ~~~ {.cpp}
2498 /// Double_t((r << 16) + (g << 8) + b)/0xFFFFFF
2499 /// ~~~
2500 /// The returned array must be deleted after usage.
2501 
2503 {
2504  if (!fImage) {
2505  Warning("GetArray", "Bad Image");
2506  return 0;
2507  }
2508 
2509  TArrayD *ret;
2510 
2511  if (fImage->alt.vector) {
2512  ret = new TArrayD(fImage->width*fImage->height, fImage->alt.vector);
2513  return ret;
2514  }
2515 
2516  ASImageDecoder *imdec;
2517 
2518  w = w ? w : fImage->width;
2519  h = h ? h : fImage->height;
2520 
2521  if ((fImage->width != w) || (fImage->height != h)) {
2522  Scale(w, h);
2523  }
2524 
2525  ASImage *img = fScaledImage ? fScaledImage->fImage : fImage;
2526 
2527  if ((imdec = start_image_decoding(0, img, SCL_DO_ALL, 0, 0,
2528  img->width, 0, 0)) == 0) {
2529  Warning("GetArray", "Failed to create image decoder");
2530  return 0;
2531  }
2532 
2533  ret = new TArrayD(w * h);
2534  CARD32 r = 0;
2535  CARD32 g = 0;
2536  CARD32 b = 0;
2537  Int_t p = 0;
2538  Double_t v = 0;
2539 
2540  for (UInt_t k = 0; k < h; k++) {
2541  imdec->decode_image_scanline(imdec);
2542 
2543  for (UInt_t i = 0; i < w; ++i) {
2544  if ((r == imdec->buffer.red[i]) &&
2545  (g == imdec->buffer.green[i]) &&
2546  (b == imdec->buffer.blue[i])) {
2547  } else {
2548  r = imdec->buffer.red[i];
2549  g = imdec->buffer.green[i];
2550  b = imdec->buffer.blue[i];
2551  if (palette) p = palette->FindColor(r, g, b);
2552  }
2553  v = palette ? palette->fPoints[p] : Double_t((r << 16) + (g << 8) + b)/0xFFFFFF;
2554  ret->AddAt(v, (h-k-1)*w + i);
2555  }
2556  }
2557 
2558  stop_image_decoding(&imdec);
2559  return ret;
2560 }
2561 
2562 ////////////////////////////////////////////////////////////////////////////////
2563 /// Draw text of size (in pixels for TrueType fonts)
2564 /// at position (x, y) with color specified by hex string.
2565 ///
2566 /// - font_name: TrueType font's filename or X font spec or alias.
2567 /// 3D style of text is one of the following:
2568 /// * 0 plain 2D text,
2569 /// * 1 embossed,
2570 /// * 2 sunken,
2571 /// * 3 shade above,
2572 /// * 4 shade below,
2573 /// * 5 embossed thick,
2574 /// * 6 sunken thick.
2575 /// * 7 outline above,
2576 /// * 8 ouline below,
2577 /// * 9 full ouline.
2578 /// - fore_file specifies foreground texture of text.
2579 
2580 void TASImage::DrawText(Int_t x, Int_t y, const char *text, Int_t size,
2581  const char *color, const char *font_name,
2582  EText3DType type, const char *fore_file, Float_t angle)
2583 {
2584  UInt_t width=0, height=0;
2585  ARGB32 text_color = ARGB32_Black;
2586  ASImage *fore_im = 0;
2587  ASImage *text_im = 0;
2588  Bool_t ttfont = kFALSE;
2589 
2590  if (!InitVisual()) {
2591  Warning("DrawText", "Visual not initiated");
2592  return;
2593  }
2594 
2595  TString fn = font_name;
2596  fn.Strip();
2597  char *tmpstr = 0;
2598 
2599  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")) {
2600  tmpstr = gSystem->ExpandPathName(fn.Data());
2601  fn = tmpstr;
2602  ttfont = kTRUE;
2603  }
2604  delete [] tmpstr;
2605 
2606  if (color) {
2607  parse_argb_color(color, &text_color);
2608  }
2609 
2610  if (fImage && fImage->alt.argb32 && ttfont) {
2611  DrawTextTTF(x, y, text, size, text_color, fn.Data(), angle);
2612  return;
2613  }
2614 
2615  if (!gFontManager) {
2616  gFontManager = create_font_manager(fgVisual->dpy, 0, 0);
2617  }
2618 
2619  if (!gFontManager) {
2620  Warning("DrawText", "cannot create Font Manager");
2621  return;
2622  }
2623 
2624  ASFont *font = get_asfont(gFontManager, fn.Data(), 0, size, ASF_GuessWho);
2625 
2626  if (!font) {
2627  font = get_asfont(gFontManager, "fixed", 0, size, ASF_GuessWho);
2628  if (!font) {
2629  Warning("DrawText", "cannot find a font %s", font_name);
2630  return;
2631  }
2632  }
2633 
2634  get_text_size(text, font, (ASText3DType)type, &width, &height);
2635 
2636  if (!fImage) {
2637  fImage = create_asimage(width, height, 0);
2638  fill_asimage(fgVisual, fImage, 0, 0, width, height, 0xFFFFFFFF);
2639  }
2640 
2641  text_im = draw_text(text, font, (ASText3DType)type, 0);
2642 
2643  ASImage *rimg = fImage;
2644 
2645  if (fore_file) {
2646  ASImage *tmp = file2ASImage(fore_file, 0xFFFFFFFF, SCREEN_GAMMA, 0, 0);
2647  if (tmp) {
2648  if ((tmp->width != width) || (tmp->height != height)) {
2649  fore_im = tile_asimage(fgVisual, tmp, 0, 0, width, height, 0,
2650  ASA_ASImage, GetImageCompression(), GetImageQuality());
2651  }
2652  destroy_asimage(&tmp);
2653  } else {
2654  fore_im = tmp;
2655  }
2656  }
2657 
2658  if (fore_im) {
2659  move_asimage_channel(fore_im, IC_ALPHA, text_im, IC_ALPHA);
2660  destroy_asimage(&text_im);
2661  } else {
2662  fore_im = text_im ;
2663  }
2664 
2665  release_font(font);
2666 
2667  if (fore_im) {
2668  ASImage *rendered_im;
2669  ASImageLayer layers[2];
2670 
2671  init_image_layers(&(layers[0]), 2);
2672  fore_im->back_color = text_color;
2673  layers[0].im = rimg;
2674  layers[0].dst_x = 0;
2675  layers[0].dst_y = 0;
2676  layers[0].clip_width = rimg->width;
2677  layers[0].clip_height = rimg->height;
2678  layers[0].bevel = 0;
2679  layers[1].im = fore_im;
2680  layers[1].dst_x = x;
2681  layers[1].dst_y = y;
2682  layers[1].clip_width = fore_im->width;
2683  layers[1].clip_height = fore_im->height;
2684 
2685  rendered_im = merge_layers(fgVisual, &(layers[0]), 2, rimg->width, rimg->height,
2686  ASA_ASImage, GetImageCompression(), GetImageQuality());
2687 
2688  destroy_asimage(&fore_im);
2689  DestroyImage();
2690  fImage = rendered_im;
2691  UnZoom();
2692  }
2693 }
2694 
2695 ////////////////////////////////////////////////////////////////////////////////
2696 /// Merge two images.
2697 ///
2698 /// op is string which specifies overlay operation. Supported operations are:
2699 ///
2700 /// - add - color addition with saturation
2701 /// - alphablend - alpha-blending
2702 /// - allanon - color values averaging
2703 /// - colorize - hue and saturate bottom image same as top image
2704 /// - darken - use lowest color value from both images
2705 /// - diff - use absolute value of the color difference between two images
2706 /// - dissipate - randomly alpha-blend images
2707 /// - hue - hue bottom image same as top image
2708 /// - lighten - use highest color value from both images
2709 /// - overlay - some weird image overlaying(see GIMP)
2710 /// - saturate - saturate bottom image same as top image
2711 /// - screen - another weird image overlaying(see GIMP)
2712 /// - sub - color substraction with saturation
2713 /// - tint - tinting image with image
2714 /// - value - value bottom image same as top image
2715 
2716 void TASImage::Merge(const TImage *im, const char *op, Int_t x, Int_t y)
2717 {
2718  if (!im) return;
2719 
2720  if (!InitVisual()) {
2721  Warning("Merge", "Visual not initiated");
2722  return;
2723  }
2724 
2725  ASImage *rendered_im;
2726  ASImageLayer layers[2];
2727 
2728  init_image_layers(&(layers[0]), 2);
2729  layers[0].im = fImage;
2730  layers[0].dst_x = 0;
2731  layers[0].dst_y = 0;
2732  layers[0].clip_width = fImage->width;
2733  layers[0].clip_height = fImage->height;
2734  layers[0].bevel = 0;
2735  layers[1].im = ((TASImage*)im)->fImage;
2736  layers[1].dst_x = x;
2737  layers[1].dst_y = y;
2738  layers[1].clip_width = im->GetWidth();
2739  layers[1].clip_height = im->GetHeight();
2740  layers[1].merge_scanlines = blend_scanlines_name2func(op ? op : "add");
2741 
2742  rendered_im = merge_layers(fgVisual, &(layers[0]), 2, fImage->width, fImage->height,
2743  ASA_ASImage, GetImageCompression(), GetImageQuality());
2744 
2745  DestroyImage();
2746  fImage = rendered_im;
2747  UnZoom();
2748 }
2749 
2750 ////////////////////////////////////////////////////////////////////////////////
2751 /// Perform Gaussian blur of the image (useful for drop shadows).
2752 /// - hr - horizontal radius of the blur
2753 /// - vr - vertical radius of the blur
2754 
2756 {
2757  if (!InitVisual()) {
2758  Warning("Blur", "Visual not initiated");
2759  return;
2760  }
2761 
2762  if (!fImage) {
2763  fImage = create_asimage(100, 100, 0);
2764 
2765  if (!fImage) {
2766  Warning("Blur", "Failed to create image");
2767  return;
2768  }
2769 
2770  fill_asimage(fgVisual, fImage, 0, 0, fImage->width, fImage->height, ARGB32_White);
2771  }
2772 
2773  ASImage *rendered_im = blur_asimage_gauss(fgVisual, fImage, hr > 0 ? hr : 3,
2774  vr > 0 ? vr : 3, SCL_DO_ALL,
2775  ASA_ASImage, GetImageCompression(), GetImageQuality());
2776  DestroyImage();
2777  fImage = rendered_im;
2778  UnZoom();
2779 }
2780 
2781 ////////////////////////////////////////////////////////////////////////////////
2782 /// Clone image.
2783 
2784 TObject *TASImage::Clone(const char *newname) const
2785 {
2786  if (!InitVisual() || !fImage) {
2787  Warning("Clone", "Image not initiated");
2788  return 0;
2789  }
2790 
2791  TASImage *im = (TASImage*)TImage::Create();
2792 
2793  if (!im) {
2794  Warning("Clone", "Failed to create image");
2795  return 0;
2796  }
2797 
2798  im->SetName(newname);
2799 
2800  im->fImage = clone_asimage(fImage, SCL_DO_ALL);
2801  im->fMaxValue = fMaxValue;
2802  im->fMinValue = fMinValue;
2803  im->fZoomOffX = fZoomOffX;
2804  im->fZoomOffY = fZoomOffY;
2805  im->fZoomWidth = fZoomWidth;
2806  im->fZoomHeight = fZoomHeight;
2807  im->fZoomUpdate = fZoomUpdate;
2809 
2810  if (fImage->alt.argb32) {
2811  UInt_t sz = fImage->width * fImage->height;
2812  im->fImage->alt.argb32 = (ARGB32*)safemalloc(sz*sizeof(ARGB32));
2813  memcpy(im->fImage->alt.argb32, fImage->alt.argb32, sz * sizeof(ARGB32));
2814  }
2815 
2816  return im;
2817 }
2818 
2819 ////////////////////////////////////////////////////////////////////////////////
2820 /// Reduce color-depth of an image and fills vector of "scientific data"
2821 /// [0...1]
2822 ///
2823 /// Colors are reduced by allocating color cells to most used colors first,
2824 /// and then approximating other colors with those allocated.
2825 ///
2826 /// \param[in] max_colors - maximum size of the colormap.
2827 /// \param[in] dither - number of bits to strip off the color data ( 0...7 )
2828 /// \param[in] opaque_threshold - alpha channel threshold at which pixel should be treated as opaque
2829 
2830 Double_t *TASImage::Vectorize(UInt_t max_colors, UInt_t dither, Int_t opaque_threshold)
2831 {
2832  if (!InitVisual()) {
2833  Warning("Vectorize", "Visual not initiated");
2834  return 0;
2835  }
2836 
2837  if (!fImage) {
2838  fImage = create_asimage(100, 100, 0);
2839 
2840  if (!fImage) {
2841  Warning("Vectorize", "Failed to create image");
2842  return 0;
2843  }
2844 
2845  fill_asimage(fgVisual, fImage, 0, 0, fImage->width, fImage->height, ARGB32_White);
2846  }
2847 
2848  ASColormap cmap;
2849  int *res;
2850  UInt_t r=0, g=0, b=0;
2851 
2852  dither = dither > 7 ? 7 : dither;
2853 
2854  res = colormap_asimage(fImage, &cmap, max_colors, dither, opaque_threshold);
2855 
2856  Double_t *vec = new Double_t[fImage->height*fImage->width];
2857  UInt_t v;
2858  Double_t tmp;
2859  fMinValue = 2;
2860  fMaxValue = -1;
2861 
2862  for (UInt_t y = 0; y < fImage->height; y++) {
2863  for (UInt_t x = 0; x < fImage->width; x++) {
2864  int i = y*fImage->width + x;
2865  if (res) {
2866  g = INDEX_SHIFT_GREEN(cmap.entries[res[i]].green);
2867  b = INDEX_SHIFT_BLUE(cmap.entries[res[i]].blue);
2868  r = INDEX_SHIFT_RED(cmap.entries[res[i]].red);
2869  }
2870  v = MAKE_INDEXED_COLOR24(r,g,b);
2871  v = (v>>12)&0x0FFF;
2872  tmp = Double_t(v)/0x0FFF;
2873  vec[(fImage->height - y - 1)*fImage->width + x] = tmp;
2874  if (fMinValue > tmp) fMinValue = tmp;
2875  if (fMaxValue < tmp) fMaxValue = tmp;
2876  }
2877  }
2878  TImagePalette *pal = new TImagePalette(cmap.count);
2879 
2880  for (UInt_t j = 0; j < cmap.count; j++) {
2881  g = INDEX_SHIFT_GREEN(cmap.entries[j].green);
2882  b = INDEX_SHIFT_BLUE(cmap.entries[j].blue);
2883  r = INDEX_SHIFT_RED(cmap.entries[j].red);
2884  v = MAKE_INDEXED_COLOR24(r,g,b);
2885 
2886  v = (v>>12) & 0x0FFF;
2887  pal->fPoints[j] = Double_t(v)/0x0FFF;
2888 
2889  pal->fColorRed[j] = cmap.entries[j].red << 8;
2890  pal->fColorGreen[j] = cmap.entries[j].green << 8;
2891  pal->fColorBlue[j] = cmap.entries[j].blue << 8;
2892  pal->fColorAlpha[j] = 0xFF00;
2893  }
2894 
2895  destroy_colormap(&cmap, kTRUE);
2896 
2897  fPalette = *pal;
2898  fImage->alt.vector = vec;
2899  UnZoom();
2900  if (res) delete res;
2901  return (Double_t*)fImage->alt.vector;
2902 }
2903 
2904 ////////////////////////////////////////////////////////////////////////////////
2905 /// This function will tile original image to specified size with offsets
2906 /// requested, and then it will go though it and adjust hue, saturation and
2907 /// value of those pixels that have specific hue, set by affected_hue/
2908 /// affected_radius parameters. When affected_radius is greater then 180
2909 /// entire image will be adjusted. Note that since grayscale colors have
2910 /// no hue - the will not get adjusted. Only saturation and value will be
2911 /// adjusted in gray pixels.
2912 ///
2913 /// Hue is measured as an angle on a 360 degree circle, The following is
2914 /// relationship of hue values to regular color names :
2915 /// - red - 0
2916 /// - yellow - 60
2917 /// - green - 120
2918 /// - cyan - 180
2919 /// - blue - 240
2920 /// - magenta - 300
2921 /// - red - 360
2922 ///
2923 /// All the hue values in parameters will be adjusted to fall within 0-360 range.
2924 ///
2925 /// \param[in] hue hue in degrees in range 0-360. This allows to limit
2926 /// impact of color adjustment to affect only limited range of hues.
2927 ///
2928 /// \param[in] radius value in degrees to be used in order to
2929 /// calculate the range of affected hues. Range is determined by
2930 /// substracting and adding this value from/to affected_hue.
2931 ///
2932 /// \param[in] H value by which to change hues in affected range.
2933 /// \param[in] S value by which to change saturation of the pixels in affected hue range.
2934 /// \param[in] V value by which to change Value(brightness) of pixels in affected hue range.
2935 ///
2936 /// \param[in] x,y position on infinite surface tiled with original image, of the
2937 /// left-top corner of the area to be used for new image.
2938 ///
2939 /// \param[in] width, height size of the area of the original image to be used for new image.
2940 /// Default is current width, height of the image.
2941 
2942 void TASImage::HSV(UInt_t hue, UInt_t radius, Int_t H, Int_t S, Int_t V,
2943  Int_t x, Int_t y, UInt_t width, UInt_t height)
2944 {
2945  if (!InitVisual()) {
2946  Warning("HSV", "Visual not initiated");
2947  return;
2948  }
2949 
2950  if (!fImage) {
2951  fImage = create_asimage(width ? width : 20, height ? height : 20, 0);
2952 
2953  if (!fImage) {
2954  Warning("HSV", "Failed to create image");
2955  return;
2956  }
2957 
2958  x = 0;
2959  y = 0;
2960  fill_asimage(fgVisual, fImage, 0, 0, fImage->width, fImage->height, ARGB32_White);
2961  }
2962 
2963  width = !width ? fImage->width : width;
2964  height = !height ? fImage->height : height;
2965 
2966  ASImage *rendered_im = 0;
2967 
2968  if (H || S || V) {
2969  rendered_im = adjust_asimage_hsv(fgVisual, fImage, x, y, width, height,
2970  hue, radius, H, S, V, ASA_ASImage, 100,
2971  ASIMAGE_QUALITY_TOP);
2972  }
2973  if (!rendered_im) {
2974  Warning("HSV", "Failed to create rendered image");
2975  return;
2976  }
2977 
2978  DestroyImage();
2979  fImage = rendered_im;
2980  UnZoom();
2981 }
2982 
2983 ////////////////////////////////////////////////////////////////////////////////
2984 /// Render multipoint gradient inside rectangle of size (width, height)
2985 /// at position (x,y) within the existing image.
2986 ///
2987 /// \param[in] angle Given in degrees. Default is 0. This is the
2988 /// direction of the gradient. Currently the only supported
2989 /// values are 0, 45, 90, 135, 180, 225, 270, 315. 0 means left
2990 /// to right, 90 means top to bottom, etc.
2991 ///
2992 /// \param[in] colors Whitespace-separated list of colors. At least two
2993 /// colors are required. Each color in this list will be visited
2994 /// in turn, at the intervals given by the offsets attribute.
2995 ///
2996 /// \param[in] offsets Whitespace-separated list of floating point values
2997 /// ranging from 0.0 to 1.0. The colors from the colors attribute
2998 /// are given these offsets, and the final gradient is rendered
2999 /// from the combination of the two. If both colors and offsets
3000 /// are given but the number of colors and offsets do not match,
3001 /// the minimum of the two will be used, and the other will be
3002 /// truncated to match. If offsets are not given, a smooth
3003 /// stepping from 0.0 to 1.0 will be used.
3004 
3005 void TASImage::Gradient(UInt_t angle, const char *colors, const char *offsets,
3006  Int_t x, Int_t y, UInt_t width, UInt_t height)
3007 {
3008  if (!InitVisual()) {
3009  Warning("Gradient", "Visual not initiated");
3010  return;
3011  }
3012 
3013  ASImage *rendered_im = 0;
3014  ASGradient gradient;
3015 
3016  int reverse = 0, npoints1 = 0, npoints2 = 0;
3017  char *p;
3018  char *pb;
3019  char ch;
3020  TString str = colors;
3021  TString col;
3022 
3023  if ((angle > 2 * 180 * 15 / 16) || (angle < 2 * 180 * 1 / 16)) {
3024  gradient.type = GRADIENT_Left2Right;
3025  } else if (angle < 2 * 180 * 3 / 16) {
3026  gradient.type = GRADIENT_TopLeft2BottomRight;
3027  } else if (angle < 2 * 180 * 5 / 16) {
3028  gradient.type = GRADIENT_Top2Bottom;
3029  } else if (angle < 2 * 180 * 7 / 16) {
3030  gradient.type = GRADIENT_BottomLeft2TopRight; reverse = 1;
3031  } else if (angle < 2 * 180 * 9 / 16) {
3032  gradient.type = GRADIENT_Left2Right; reverse = 1;
3033  } else if (angle < 2 * 180 * 11 / 16) {
3034  gradient.type = GRADIENT_TopLeft2BottomRight; reverse = 1;
3035  } else if (angle < 2 * 180 * 13 / 16) {
3036  gradient.type = GRADIENT_Top2Bottom; reverse = 1;
3037  } else {
3038  gradient.type = GRADIENT_BottomLeft2TopRight;
3039  }
3040 
3041  for (p = (char*)colors; isspace((int)*p); p++) { }
3042 
3043  for (npoints1 = 0; *p; npoints1++) {
3044  if (*p) {
3045  for ( ; *p && !isspace((int)*p); p++) { }
3046  }
3047  for ( ; isspace((int)*p); p++) { }
3048  }
3049  if (offsets) {
3050  for (p = (char*)offsets; isspace((int)*p); p++) { }
3051 
3052  for (npoints2 = 0; *p; npoints2++) {
3053  if (*p) {
3054  for ( ; *p && !isspace((int)*p); p++) { }
3055  }
3056  for ( ; isspace((int)*p); p++) { }
3057  }
3058  }
3059  if (npoints1 > 1) {
3060  int i;
3061  if (offsets && (npoints1 > npoints2)) npoints1 = npoints2;
3062 
3063  if (!width) {
3064  width = fImage ? fImage->width : 20;
3065  }
3066  if (!height) {
3067  height = fImage ? fImage->height : 20;
3068  }
3069 
3070  gradient.color = new ARGB32[npoints1];
3071  gradient.offset = new double[npoints1];
3072 
3073  for (p = (char*)colors; isspace((int)*p); p++) { }
3074 
3075  for (npoints1 = 0; *p; ) {
3076  pb = p;
3077 
3078  if (*p) {
3079  for ( ; *p && !isspace((int)*p); p++) { }
3080  }
3081  for ( ; isspace((int)*p); p++) { }
3082 
3083  col = str(pb - colors, p - pb);
3084 
3085  if (parse_argb_color(col.Data(), gradient.color + npoints1) != col) {
3086  npoints1++;
3087  } else {
3088  Warning("Gradient", "Failed to parse color [%s] - defaulting to black", pb);
3089  }
3090  }
3091 
3092  if (offsets) {
3093  for (p = (char*)offsets; isspace((int)*p); p++) { }
3094 
3095  for (npoints2 = 0; *p; ) {
3096  pb = p;
3097 
3098  if (*p) {
3099  for ( ; *p && !isspace((int)*p); p++) { }
3100  }
3101  ch = *p; *p = '\0';
3102  gradient.offset[npoints2] = strtod(pb, &pb);
3103 
3104  if (pb == p) npoints2++;
3105  *p = ch;
3106  for ( ; isspace((int)*p); p++) { }
3107  }
3108  } else {
3109  for (npoints2 = 0; npoints2 < npoints1; npoints2++) {
3110  gradient.offset[npoints2] = (double)npoints2 / (npoints1 - 1);
3111  }
3112  }
3113  gradient.npoints = npoints1;
3114 
3115  if (npoints2 && (gradient.npoints > npoints2)) {
3116  gradient.npoints = npoints2;
3117  }
3118  if (reverse) {
3119  for (i = 0; i < gradient.npoints/2; i++) {
3120  int i2 = gradient.npoints - 1 - i;
3121  ARGB32 c = gradient.color[i];
3122  double o = gradient.offset[i];
3123  gradient.color[i] = gradient.color[i2];
3124  gradient.color[i2] = c;
3125  gradient.offset[i] = gradient.offset[i2];
3126  gradient.offset[i2] = o;
3127  }
3128  for (i = 0; i < gradient.npoints; i++) {
3129  gradient.offset[i] = 1.0 - gradient.offset[i];
3130  }
3131  }
3132  rendered_im = make_gradient(fgVisual, &gradient, width, height, SCL_DO_ALL,
3133  ASA_ASImage, GetImageCompression(), GetImageQuality());
3134 
3135  delete [] gradient.color;
3136  delete [] gradient.offset;
3137  }
3138 
3139  if (!rendered_im) { // error
3140  Warning("Gradient", "Failed to create gradient image");
3141  return;
3142  }
3143 
3144  if (!fImage) {
3145  fImage = rendered_im;
3146  return;
3147  }
3148 
3149  ASImageLayer layers[2];
3150 
3151  init_image_layers(&(layers[0]), 2);
3152  layers[0].im = fImage;
3153  layers[0].dst_x = 0;
3154  layers[0].dst_y = 0;
3155  layers[0].clip_width = fImage->width;
3156  layers[0].clip_height = fImage->height;
3157  layers[0].bevel = 0;
3158  layers[1].im = rendered_im;
3159  layers[1].dst_x = x;
3160  layers[1].dst_y = y;
3161  layers[1].clip_width = width;
3162  layers[1].clip_height = height;
3163  layers[1].merge_scanlines = alphablend_scanlines;
3164 
3165  ASImage *merge_im = merge_layers(fgVisual, &(layers[0]), 2, fImage->width, fImage->height,
3166  ASA_ASImage, GetImageCompression(), GetImageQuality());
3167  if (!merge_im) {
3168  Warning("Gradient", "Failed to create merged image");
3169  return;
3170  }
3171 
3172  destroy_asimage(&rendered_im);
3173  DestroyImage();
3174  fImage = merge_im;
3175  UnZoom();
3176 }
3177 
3178 ////////////////////////////////////////////////////////////////////////////////
3179 /// Make component hilite.
3180 /// (used internally)
3181 
3182 static CARD8 MakeComponentHilite(int cmp)
3183 {
3184  if (cmp < 51) {
3185  cmp = 51;
3186  }
3187  cmp = (cmp * 12) / 10;
3188 
3189  return (cmp > 255) ? 255 : cmp;
3190 }
3191 
3192 ////////////////////////////////////////////////////////////////////////////////
3193 /// Calculate highlite color.
3194 /// (used internally)
3195 
3196 static ARGB32 GetHilite(ARGB32 background)
3197 {
3198  return ((MakeComponentHilite((background>>24) & 0x000000FF) << 24) & 0xFF000000) |
3199  ((MakeComponentHilite((background & 0x00FF0000) >> 16) << 16) & 0x00FF0000) |
3200  ((MakeComponentHilite((background & 0x0000FF00) >> 8) << 8) & 0x0000FF00) |
3201  ((MakeComponentHilite((background & 0x000000FF))) & 0x000000FF);
3202 }
3203 
3204 ////////////////////////////////////////////////////////////////////////////////
3205 /// Calculate shadow color.
3206 /// (used internally)
3207 
3208 static ARGB32 GetShadow(ARGB32 background)
3209 {
3210  return (background >> 1) & 0x7F7F7F7F;
3211 }
3212 
3213 ////////////////////////////////////////////////////////////////////////////////
3214 /// Get average.
3215 /// (used internally)
3216 
3217 static ARGB32 GetAverage(ARGB32 foreground, ARGB32 background)
3218 {
3219  CARD16 a, r, g, b;
3220 
3221  a = ARGB32_ALPHA8(foreground) + ARGB32_ALPHA8(background);
3222  a = (a<<3)/10;
3223  r = ARGB32_RED8(foreground) + ARGB32_RED8(background);
3224  r = (r<<3)/10;
3225  g = ARGB32_GREEN8(foreground) + ARGB32_GREEN8(background);
3226  g = (g<<3)/10;
3227  b = ARGB32_BLUE8(foreground) + ARGB32_BLUE8(background);
3228  b = (b<<3)/10;
3229 
3230  return MAKE_ARGB32(a, r, g, b);
3231 }
3232 
3233 
3234 ////////////////////////////////////////////////////////////////////////////////
3235 /// Bevel is used to create 3D effect while drawing buttons, or any other
3236 /// image that needs to be framed. Bevel is drawn using 2 primary colors:
3237 /// one for top and left sides - hi color, and another for bottom and
3238 /// right sides - low color. Bevel can be drawn over existing image or
3239 /// as newly created, as it is shown in code below:
3240 /// ~~~ {.cpp}
3241 /// TImage *img = TImage::Create();
3242 /// img->Bevel(0, 0, 400, 300, "#dddddd", "#000000", 3);
3243 /// ~~~
3244 
3245 void TASImage::Bevel(Int_t x, Int_t y, UInt_t width, UInt_t height,
3246  const char *hi_color, const char *lo_color, UShort_t thick,
3247  Bool_t reverse)
3248 {
3249  if (!InitVisual()) {
3250  Warning("Bevel", "Visual not initiated");
3251  return;
3252  }
3253 
3254  ASImageBevel bevel;
3255  bevel.type = 0;
3256 
3257  ARGB32 hi=ARGB32_White, lo=ARGB32_White;
3258  parse_argb_color(hi_color, &hi);
3259  parse_argb_color(lo_color, &lo);
3260 
3261  if (reverse) {
3262  bevel.lo_color = hi;
3263  bevel.lolo_color = GetHilite(hi);
3264  bevel.hi_color = lo;
3265  bevel.hihi_color = GetShadow(lo);
3266  } else {
3267  bevel.hi_color = hi;
3268  bevel.hihi_color = GetHilite(hi);
3269  bevel.lo_color = lo;
3270  bevel.lolo_color = GetShadow(lo);
3271  }
3272  bevel.hilo_color = GetAverage(hi, lo);
3273 
3274  int extra_hilite = 2;
3275  bevel.left_outline = bevel.top_outline = bevel.right_outline = bevel.bottom_outline = thick;
3276  bevel.left_inline = bevel.top_inline = bevel.right_inline = bevel.bottom_inline = extra_hilite + 1;
3277 
3278  if (bevel.top_outline > 1) {
3279  bevel.top_inline += bevel.top_outline - 1;
3280  }
3281 
3282  if (bevel.left_outline > 1) {
3283  bevel.left_inline += bevel.left_outline - 1;
3284  }
3285 
3286  if (bevel.right_outline > 1) {
3287  bevel.right_inline += bevel.right_outline - 1;
3288  }
3289 
3290  if (bevel.bottom_outline > 1) {
3291  bevel.bottom_inline += bevel.bottom_outline - 1;
3292  }
3293 
3294  ASImage *merge_im;
3295  ARGB32 fill = ((hi>>24) != 0xff) || ((lo>>24) != 0xff) ? bevel.hilo_color : (bevel.hilo_color | 0xff000000);
3296 
3297  if (!fImage) {
3298  fImage = create_asimage(width ? width : 20, height ? height : 20, 0);
3299 
3300  if (!fImage) {
3301  Warning("Bevel", "Failed to create image");
3302  return;
3303  }
3304 
3305  x = 0;
3306  y = 0;
3307  fill_asimage(fgVisual, fImage, 0, 0, fImage->width, fImage->height, fill);
3308  }
3309 
3310  width = !width ? fImage->width : width;
3311  height = !height ? fImage->height : height;
3312 
3313  ASImageLayer layers[2];
3314  init_image_layers(&(layers[0]), 2);
3315 
3316  layers[0].im = fImage;
3317  layers[0].dst_x = 0;
3318  layers[0].dst_y = 0;
3319  layers[0].clip_width = fImage->width;
3320  layers[0].clip_height = fImage->height;
3321  layers[0].bevel = 0;
3322 
3323  UInt_t w = width - (bevel.left_outline + bevel.right_outline);
3324  UInt_t h = height - (bevel.top_outline + bevel.bottom_outline);
3325  ASImage *bevel_im = create_asimage(w, h, 0);
3326 
3327  if (!bevel_im) {
3328  Warning("Bevel", "Failed to create bevel image");
3329  return;
3330  }
3331 
3332  layers[1].im = bevel_im;
3333  fill_asimage(fgVisual, bevel_im, 0, 0, w, h, fill);
3334 
3335  layers[1].dst_x = x;
3336  layers[1].dst_y = y;
3337  layers[1].clip_width = width;
3338  layers[1].clip_height = height;
3339  layers[1].bevel = &bevel;
3340  layers[1].merge_scanlines = alphablend_scanlines;
3341 
3342  merge_im = merge_layers(fgVisual, &(layers[0]), 2, fImage->width, fImage->height,
3343  ASA_ASImage, GetImageCompression(), GetImageQuality());
3344  destroy_asimage(&bevel_im);
3345 
3346  if (!merge_im) {
3347  Warning("Bevel", "Failed to image");
3348  return;
3349  }
3350 
3351  DestroyImage();
3352  fImage = merge_im;
3353  UnZoom();
3354 }
3355 
3356 
3357 ////////////////////////////////////////////////////////////////////////////////
3358 /// Enlarge image, padding it with specified color on each side in
3359 /// accordance with requested geometry.
3360 
3361 void TASImage::Pad(const char *col, UInt_t l, UInt_t r, UInt_t t, UInt_t b)
3362 {
3363  Int_t x, y;
3364  UInt_t w, h;
3365 
3366  if (!InitVisual()) {
3367  Warning("Pad", "Visual not initiated");
3368  return;
3369  }
3370 
3371  if (!fImage) {
3372  fImage = create_asimage(100, 100, 0);
3373 
3374  if (!fImage) {
3375  Warning("Pad", "Failed to create image");
3376  return;
3377  }
3378 
3379  x = 0;
3380  y = 0;
3381  fill_asimage(fgVisual, fImage, 0, 0, fImage->width, fImage->height, ARGB32_White);
3382  }
3383 
3384  ARGB32 color = ARGB32_White;
3385  parse_argb_color(col, &color);
3386 
3387  x = l;
3388  y = t;
3389  w = l + fImage->width + r;
3390  h = t + fImage->height + b;
3391 
3392  ASImage *img = pad_asimage(fgVisual, fImage, x, y, w, h, color,
3393  ASA_ASImage, GetImageCompression(), GetImageQuality());
3394 
3395  if (!img) {
3396  Warning("Pad", "Failed to create output image");
3397  return;
3398  }
3399 
3400  DestroyImage();
3401  fImage = img;
3402  UnZoom();
3404 }
3405 
3406 
3407 ////////////////////////////////////////////////////////////////////////////////
3408 /// Crop an image.
3409 
3410 void TASImage::Crop(Int_t x, Int_t y, UInt_t width, UInt_t height)
3411 {
3412  if (!InitVisual()) {
3413  Warning("Crop", "Visual not initiated");
3414  return;
3415  }
3416 
3417  if (!fImage) {
3418  Warning("Crop", "No image");
3419  return;
3420  }
3421 
3422  x = x < 0 ? 0 : x;
3423  y = y < 0 ? 0 : y;
3424 
3425  width = x + width > fImage->width ? fImage->width - x : width;
3426  height = y + height > fImage->height ? fImage->height - y : height;
3427 
3428  if ((width == fImage->width) && (height == fImage->height)) {
3429  Warning("Crop", "input size larger than image");
3430  return;
3431  }
3432  ASImageDecoder *imdec = start_image_decoding(fgVisual, fImage, SCL_DO_ALL,
3433  x, y, width, height, 0);
3434 
3435  if (!imdec) {
3436  Warning("Crop", "Failed to start image decoding");
3437  return;
3438  }
3439 
3440  ASImage *img = create_asimage(width, height, 0);
3441 
3442  if (!img) {
3443  delete [] imdec;
3444  Warning("Crop", "Failed to create image");
3445  return;
3446  }
3447 
3448  ASImageOutput *imout = start_image_output(fgVisual, img, ASA_ASImage,
3450 
3451  if (!imout) {
3452  Warning("Crop", "Failed to start image output");
3453  destroy_asimage(&img);
3454  if (imdec) delete [] imdec;
3455  return;
3456  }
3457 
3458 #ifdef HAVE_MMX
3459  mmx_init();
3460 #endif
3461 
3462  for (UInt_t i = 0; i < height; i++) {
3463  imdec->decode_image_scanline(imdec);
3464  imout->output_image_scanline(imout, &(imdec->buffer), 1);
3465  }
3466 
3467  stop_image_decoding(&imdec);
3468  stop_image_output(&imout);
3469 
3470 #ifdef HAVE_MMX
3471  mmx_off();
3472 #endif
3473 
3474  DestroyImage();
3475  fImage = img;
3476  UnZoom();
3478 }
3479 
3480 ////////////////////////////////////////////////////////////////////////////////
3481 /// Append image.
3482 ///
3483 /// option:
3484 /// - "+" - appends to the right side
3485 /// - "/" - appends to the bottom
3486 
3487 void TASImage::Append(const TImage *im, const char *option, const char *color )
3488 {
3489  if (!im) return;
3490 
3491  if (!InitVisual()) {
3492  Warning("Append", "Visual not initiated");
3493  return;
3494  }
3495 
3496  if (!fImage) {
3497  fImage = ((TASImage*)im)->fImage;
3498  return;
3499  }
3500 
3501  TString opt = option;
3502  opt.Strip();
3503 
3504  UInt_t width = fImage->width;
3505  UInt_t height = fImage->height;
3506 
3507  if (opt == "+") {
3508  Pad(color, 0, im->GetWidth(), 0, 0);
3509  Merge(im, "alphablend", width, 0);
3510  } else if (opt == "/") {
3511  Pad(color, 0, 0, 0, im->GetHeight());
3512  Merge(im, "alphablend", 0, height);
3513  } else {
3514  return;
3515  }
3516 
3517  UnZoom();
3518 }
3519 
3520 ////////////////////////////////////////////////////////////////////////////////
3521 /// BeginPaint initializes internal array[width x height] of ARGB32 pixel
3522 /// values.
3523 ///
3524 /// That provides quick access to image during paint operations.
3525 /// To RLE compress image one needs to call EndPaint method when painting
3526 /// is over.
3527 
3529 {
3530  if (!InitVisual()) {
3531  Warning("BeginPaint", "Visual not initiated");
3532  return;
3533  }
3534 
3535  if (!fImage) {
3536  return;
3537  }
3538 
3539  fPaintMode = mode;
3540 
3541  if (!fPaintMode || fImage->alt.argb32) {
3542  return;
3543  }
3544 
3545  ASImage *img = tile_asimage(fgVisual, fImage, 0, 0, fImage->width, fImage->height,
3546  0, ASA_ARGB32, 0, ASIMAGE_QUALITY_DEFAULT);
3547 
3548  if (!img) {
3549  Warning("BeginPaint", "Failed to create image");
3550  return;
3551  }
3552 
3553  DestroyImage();
3554  fImage = img;
3555 }
3556 
3557 ////////////////////////////////////////////////////////////////////////////////
3558 /// EndPaint does internal RLE compression of image data.
3559 
3561 {
3562  if (!fImage) {
3563  Warning("EndPaint", "no image");
3564  return;
3565  }
3566 
3567  if (!fImage->alt.argb32) return;
3568 
3569  ASImage *img = tile_asimage(fgVisual, fImage, 0, 0, fImage->width, fImage->height,
3570  0, ASA_ASImage, 0, ASIMAGE_QUALITY_DEFAULT);
3571 
3572  if (!img) {
3573  Warning("EndPaint", "Failed to create image");
3574  return;
3575  }
3576 
3577  fPaintMode = kFALSE;
3578  DestroyImage();
3579  fImage = img;
3580 }
3581 
3582 ////////////////////////////////////////////////////////////////////////////////
3583 /// Return a pointer to internal array[width x height] of ARGB32 values
3584 /// This array is directly accessible. That allows to manipulate/change the
3585 /// image.
3586 
3588 {
3589  if (!fImage) {
3590  Warning("GetArgbArray", "no image");
3591  return 0;
3592  }
3593 
3594  ASImage *img = fScaledImage ? fScaledImage->fImage : fImage;
3595  if (!img) return 0;
3596 
3597  if (!img->alt.argb32) {
3598  if (fScaledImage) {
3600  img = fScaledImage->fImage;
3601  } else {
3602  BeginPaint();
3603  img = fImage;
3604  }
3605  }
3606 
3607  return (UInt_t *)img->alt.argb32;
3608 }
3609 
3610 ////////////////////////////////////////////////////////////////////////////////
3611 /// Return a pointer to an array[width x height] of RGBA32 values.
3612 /// This array is created from internal ARGB32 array,
3613 /// must be deleted after usage.
3614 
3616 {
3617  if (!fImage) {
3618  Warning("GetRgbaArray", "no image");
3619  return 0;
3620  }
3621 
3622  ASImage *img = fScaledImage ? fScaledImage->fImage : fImage;
3623  if (!img) return 0;
3624 
3625  if (!img->alt.argb32) {
3626  if (fScaledImage) {
3628  img = fScaledImage->fImage;
3629  } else {
3630  BeginPaint();
3631  img = fImage;
3632  }
3633  }
3634 
3635  UInt_t i, j;
3636  Int_t y = 0;
3637  Int_t idx = 0;
3638  UInt_t a, rgb, rgba, argb;
3639  y = 0;
3640 
3641  UInt_t *ret = new UInt_t[img->width*img->height];
3642 
3643  for (i = 0; i < img->height; i++) {
3644  for (j = 0; j < img->width; j++) {
3645  idx = y + j;
3646  argb = img->alt.argb32[idx];
3647  a = argb >> 24;
3648  rgb = argb & 0x00ffffff;
3649  rgba = (rgb << 8) + a;
3650  ret[idx] = rgba;
3651  }
3652  y += img->width;
3653  }
3654 
3655  return ret;
3656 }
3657 
3658 ////////////////////////////////////////////////////////////////////////////////
3659 /// Return a pointer to scan-line.
3660 
3662 {
3663  if (!fImage) {
3664  Warning("GetScanline", "no image");
3665  return 0;
3666  }
3667 
3668  ASImage *img = fScaledImage ? fScaledImage->fImage : fImage;
3669  CARD32 *ret = new CARD32[img->width];
3670 
3671  ASImageDecoder *imdec = start_image_decoding(fgVisual, img, SCL_DO_ALL,
3672  0, y, img->width, 1, 0);
3673 
3674  if (!imdec) {
3675  delete [] ret;
3676  Warning("GetScanline", "Failed to start image decoding");
3677  return 0;
3678  }
3679 
3680 #ifdef HAVE_MMX
3681  mmx_init();
3682 #endif
3683 
3684  imdec->decode_image_scanline(imdec);
3685  memcpy(imdec->buffer.buffer, ret, img->width*sizeof(CARD32));
3686  stop_image_decoding(&imdec);
3687 
3688 #ifdef HAVE_MMX
3689  mmx_off();
3690 #endif
3691 
3692  return (UInt_t*)ret;
3693 }
3694 
3695 
3696 //______________________________________________________________________________
3697 //
3698 // Vector graphics
3699 // a couple of macros which can be "assembler accelerated"
3700 
3701 #if defined(R__GNU) && defined(__i386__) && !defined(__sun)
3702 #define _MEMSET_(dst, lng, val) __asm__("movl %0,%%eax \n"\
3703  "movl %1,%%edi \n" \
3704  "movl %2,%%ecx \n" \
3705  "cld \n" \
3706  "rep \n" \
3707  "stosl \n" \
3708  : /* no output registers */ \
3709  :"g" (val), "g" (dst), "g" (lng) \
3710  :"eax","edi","ecx" \
3711  )
3712 
3713 #else
3714  #define _MEMSET_(dst, lng, val) do {\
3715  for( UInt_t j=0; j < lng; j++) *((dst)+j) = val; } while (0)
3716 
3717 #endif
3718 
3719 #define FillSpansInternal(npt, ppt, widths, color) do {\
3720  UInt_t yy = ppt[0].fY*fImage->width;\
3721  for (UInt_t i = 0; i < npt; i++) {\
3722  _MEMSET_(&fImage->alt.argb32[yy + ppt[i].fX], widths[i], color);\
3723  yy += ((i+1 < npt) && (ppt[i].fY != ppt[i+1].fY) ? fImage->width : 0);\
3724  }\
3725 } while (0)
3726 
3727 ////////////////////////////////////////////////////////////////////////////////
3728 /// Fill rectangle of size (width, height) at position (x,y)
3729 /// within the existing image with specified color.
3730 
3732 {
3733  ARGB32 color = (ARGB32)col;
3734 
3735  if (width == 0) width = 1;
3736  if (height == 0) height = 1;
3737 
3738  if (x < 0) {
3739  width += x;
3740  x = 0;
3741  }
3742  if (y < 0) {
3743  height += y;
3744  y = 0;
3745  }
3746 
3747  Bool_t has_alpha = (color & 0xff000000) != 0xff000000;
3748 
3749  x = x > (int)fImage->width ? (Int_t)fImage->width : x;
3750  y = y > (int)fImage->height ? (Int_t)fImage->height : y;
3751 
3752  width = x + width > fImage->width ? fImage->width - x : width;
3753  height = y + height > fImage->height ? fImage->height - y : height;
3754 
3755  if (!fImage->alt.argb32) {
3756  fill_asimage(fgVisual, fImage, x, y, width, height, color);
3757  } else {
3758  int yyy = y*fImage->width;
3759  if (!has_alpha) { // use faster memset
3760  ARGB32 *p0 = fImage->alt.argb32 + yyy + x;
3761  ARGB32 *p = p0;
3762  for (UInt_t i = 0; i < height; i++) {
3763  _MEMSET_(p, width, color);
3764  p += fImage->width;
3765  }
3766  } else {
3767  for (UInt_t i = y; i < y + height; i++) {
3768  int j = x + width;
3769  while (j > x) {
3770  j--;
3771  _alphaBlend(&fImage->alt.argb32[yyy + j], &color);
3772  }
3773  }
3774  yyy += fImage->width;
3775  }
3776  }
3777 }
3778 
3779 ////////////////////////////////////////////////////////////////////////////////
3780 /// Fill rectangle of size (width, height) at position (x,y)
3781 /// within the existing image with specified color.
3782 ///
3783 /// To create new image with Fill method the following code can be used:
3784 /// ~~~ {.cpp}
3785 /// TImage *img = TImage::Create();
3786 /// img->Fill("#FF00FF", 0, 0, 400, 300);
3787 /// ~~~
3788 
3789 void TASImage::FillRectangle(const char *col, Int_t x, Int_t y, UInt_t width, UInt_t height)
3790 {
3791  if (!InitVisual()) {
3792  Warning("Fill", "Visual not initiated");
3793  return;
3794  }
3795 
3796  ARGB32 color = ARGB32_White;
3797 
3798  if (col) {
3799  parse_argb_color(col, &color);
3800  }
3801 
3802  if (!fImage) {
3803  fImage = create_asimage(width ? width : 20, height ? height : 20, 0);
3804  x = 0;
3805  y = 0;
3806  }
3807 
3808  FillRectangleInternal((UInt_t)color, x, y, width, height);
3809  UnZoom();
3810 }
3811 
3812 ////////////////////////////////////////////////////////////////////////////////
3813 /// Draw a vertical line.
3814 
3816 {
3817  ARGB32 color = (ARGB32)col;
3818  UInt_t half = 0;
3819 
3820  if (!thick) thick = 1;
3821 
3822  if (thick > 1) {
3823  half = thick >> 1;
3824  if (x > half) {
3825  x = x - half;
3826  } else {
3827  x = 0;
3828  thick += (x - half);
3829  }
3830  }
3831 
3832  y2 = y2 >= fImage->height ? fImage->height - 1 : y2;
3833  y1 = y1 >= fImage->height ? fImage->height - 1 : y1;
3834  x = x + thick >= fImage->width ? fImage->width - thick - 1 : x;
3835 
3836  int yy = y1*fImage->width;
3837  for (UInt_t y = y1; y <= y2; y++) {
3838  for (UInt_t w = 0; w < thick; w++) {
3839  if (x + w < fImage->width) {
3840  _alphaBlend(&fImage->alt.argb32[yy + (x + w)], &color);
3841  }
3842  }
3843  yy += fImage->width;
3844  }
3845 }
3846 
3847 ////////////////////////////////////////////////////////////////////////////////
3848 /// Draw an horizontal line.
3849 
3851 {
3852  ARGB32 color = (ARGB32)col;
3853  UInt_t half = 0;
3854 
3855  if (!thick) thick = 1;
3856 
3857  if (thick > 1) {
3858  half = thick >> 1;
3859  if (y > half) {
3860  y = y - half;
3861  } else {
3862  y = 0;
3863  thick += (y - half);
3864  }
3865  }
3866 
3867  y = y + thick >= fImage->height ? fImage->height - thick - 1 : y;
3868  x2 = x2 >= fImage->width ? fImage->width - 1 : x2;
3869  x1 = x1 >= fImage->width ? fImage->width - 1 : x1;
3870 
3871  int yy = y*fImage->width;
3872  for (UInt_t w = 0; w < thick; w++) {
3873  for (UInt_t x = x1; x <= x2; x++) {
3874  if (y + w < fImage->height) {
3875  _alphaBlend(&fImage->alt.argb32[yy + x], &color);
3876  }
3877  }
3878  yy += fImage->width;
3879  }
3880 }
3881 
3882 ////////////////////////////////////////////////////////////////////////////////
3883 /// Draw a line.
3884 
3886  const char *col, UInt_t thick)
3887 {
3888  ARGB32 color = ARGB32_White;
3889  parse_argb_color(col, &color);
3890  DrawLineInternal(x1, y1, x2, y2, (UInt_t)color, thick);
3891 }
3892 
3893 ////////////////////////////////////////////////////////////////////////////////
3894 /// Internal line drawing.
3895 
3897  UInt_t col, UInt_t thick)
3898 {
3899  int dx, dy, d;
3900  int i1, i2;
3901  int x, y, xend, yend;
3902  int xdir, ydir;
3903  int q;
3904  int idx;
3905  int yy;
3906 
3907  if (!InitVisual()) {
3908  Warning("DrawLine", "Visual not initiated");
3909  return;
3910  }
3911 
3912  if (!fImage) {
3913  Warning("DrawLine", "no image");
3914  return;
3915  }
3916 
3917  if (!fImage->alt.argb32) {
3918  BeginPaint();
3919  }
3920 
3921  if (!fImage->alt.argb32) {
3922  Warning("DrawLine", "Failed to get pixel array");
3923  return;
3924  }
3925 
3926  ARGB32 color = (ARGB32)col;
3927 
3928  dx = TMath::Abs(Int_t(x2) - Int_t(x1));
3929  dy = TMath::Abs(Int_t(y2) - Int_t(y1));
3930 
3931  if (!dx) {
3932  DrawVLine(x1, y2 > y1 ? y1 : y2,
3933  y2 > y1 ? y2 : y1, color, thick);
3934  return;
3935  }
3936 
3937  if (!dy) {
3938  DrawHLine(y1, x2 > x1 ? x1 : x2,
3939  x2 > x1 ? x2 : x1, color, thick);
3940  return;
3941  }
3942 
3943  if (thick > 1) {
3944  DrawWideLine(x1, y1, x2, y2, color, thick);
3945  return;
3946  }
3947 
3948  if (dy <= dx) {
3949  UInt_t ddy = dy << 1;
3950  i1 = ddy;
3951  i2 = i1 - (dx << 1);
3952  d = i1 - dx;
3953 
3954  if (x1 > x2) {
3955  x = x2;
3956  y = y2;
3957  ydir = -1;
3958  xend = x1;
3959  } else {
3960  x = x1;
3961  y = y1;
3962  ydir = 1;
3963  xend = x2;
3964  }
3965 
3966  yy = y*fImage->width;
3967  _alphaBlend(&fImage->alt.argb32[yy + x], &color);
3968  q = (y2 - y1) * ydir;
3969 
3970  if (q > 0) {
3971  while (x < xend) {
3972  idx = yy + x;
3973  _alphaBlend(&fImage->alt.argb32[idx], &color);
3974  x++;
3975 
3976  if (d >= 0) {
3977  yy += fImage->width;
3978  d += i2;
3979  } else {
3980  d += i1;
3981  }
3982  }
3983  } else {
3984  while (x < xend) {
3985  idx = yy + x;
3986  _alphaBlend(&fImage->alt.argb32[idx], &color);
3987  x++;
3988 
3989  if (d >= 0) {
3990  yy -= fImage->width;
3991  d += i2;
3992  } else {
3993  d += i1;
3994  }
3995  }
3996  }
3997  } else {
3998  UInt_t ddx = dx << 1;
3999  i1 = ddx;
4000  i2 = i1 - (dy << 1);
4001  d = i1 - dy;
4002 
4003  if (y1 > y2) {
4004  y = y2;
4005  x = x2;
4006  yend = y1;
4007  xdir = -1;
4008  } else {
4009  y = y1;
4010  x = x1;
4011  yend = y2;
4012  xdir = 1;
4013  }
4014 
4015  yy = y*fImage->width;
4016  _alphaBlend(&fImage->alt.argb32[yy + x], &color);
4017  q = (x2 - x1) * xdir;
4018 
4019  if (q > 0) {
4020  while (y < yend) {
4021  idx = yy + x;
4022  _alphaBlend(&fImage->alt.argb32[idx], &color);
4023  y++;
4024  yy += fImage->width;
4025 
4026  if (d >= 0) {
4027  x++;
4028  d += i2;
4029  } else {
4030  d += i1;
4031  }
4032  }
4033  } else {
4034  while (y < yend) {
4035  idx = yy + x;
4036  _alphaBlend(&fImage->alt.argb32[idx], &color);
4037  y++;
4038  yy += fImage->width;
4039 
4040  if (d >= 0) {
4041  x--;
4042  d += i2;
4043  } else {
4044  d += i1;
4045  }
4046  }
4047  }
4048  }
4049 }
4050 
4051 ////////////////////////////////////////////////////////////////////////////////
4052 /// Draw a rectangle.
4053 
4055  const char *col, UInt_t thick)
4056 {
4057  if (!InitVisual()) {
4058  Warning("DrawRectangle", "Visual not initiated");
4059  return;
4060  }
4061 
4062  if (!fImage) {
4063  w = w ? w : 20;
4064  h = h ? h : 20;
4065  x = 0;
4066  y = 0;
4067  fImage = create_asimage(w, h, 0);
4068  FillRectangle(col, 0, 0, w, h);
4069  return;
4070  }
4071 
4072  if (!fImage->alt.argb32) {
4073  BeginPaint();
4074  }
4075 
4076  if (!fImage->alt.argb32) {
4077  Warning("DrawRectangle", "Failed to get pixel array");
4078  return;
4079  }
4080 
4081  ARGB32 color = ARGB32_White;
4082  parse_argb_color(col, &color);
4083 
4084  DrawHLine(y, x, x + w, (UInt_t)color, thick);
4085  DrawVLine(x + w, y, y + h, (UInt_t)color, thick);
4086  DrawHLine(y + h, x, x + w, (UInt_t)color, thick);
4087  DrawVLine(x, y, y + h, (UInt_t)color, thick);
4088  UnZoom();
4089 }
4090 
4091 ////////////////////////////////////////////////////////////////////////////////
4092 /// Draw a box.
4093 
4094 void TASImage::DrawBox(Int_t x1, Int_t y1, Int_t x2, Int_t y2, const char *col,
4095  UInt_t thick, Int_t mode)
4096 {
4097  Int_t x = TMath::Min(x1, x2);
4098  Int_t y = TMath::Min(y1, y2);
4099  Int_t w = TMath::Abs(x2 - x1);
4100  Int_t h = TMath::Abs(y2 - y1);
4101 
4102  ARGB32 color = ARGB32_White;
4103 
4104  if (!fImage) {
4105  w = w ? x+w : x+20;
4106  h = h ? y+h : y+20;
4107  fImage = create_asimage(w, h, 0);
4108  FillRectangle(col, 0, 0, w, h);
4109  return;
4110  }
4111 
4112  if (x1 == x2) {
4113  parse_argb_color(col, &color);
4114  DrawVLine(x1, y1, y2, color, 1);
4115  return;
4116  }
4117 
4118  if (y1 == y2) {
4119  parse_argb_color(col, &color);
4120  DrawHLine(y1, x1, x2, color, 1);
4121  return;
4122  }
4123 
4124 
4125  switch (mode) {
4126  case TVirtualX::kHollow:
4127  DrawRectangle(x, y, w, h, col, thick);
4128  break;
4129 
4130  case TVirtualX::kFilled:
4131  FillRectangle(col, x, y, w, h);
4132  break;
4133 
4134  default:
4135  FillRectangle(col, x, y, w, h);
4136  break;
4137  }
4138 }
4139 
4140 ////////////////////////////////////////////////////////////////////////////////
4141 /// Draw a dashed horizontal line.
4142 
4144  const char *pDash, UInt_t col, UInt_t thick)
4145 {
4146  UInt_t iDash = 0; // index of current dash
4147  int i = 0;
4148 
4149  ARGB32 color = (ARGB32)col;
4150 
4151  UInt_t half = 0;
4152 
4153  if (thick > 1) {
4154  half = thick >> 1;
4155  if (y > half) {
4156  y = y - half;
4157  } else {
4158  y = 0;
4159  thick += (y - half);
4160  }
4161  }
4162  thick = thick <= 0 ? 1 : thick;
4163 
4164  y = y + thick >= fImage->height ? fImage->height - thick - 1 : y;
4165  x2 = x2 >= fImage->width ? fImage->width - 1 : x2;
4166  x1 = x1 >= fImage->width ? fImage->width - 1 : x1;
4167 
4168  // switch x1, x2
4169  UInt_t tmp = x1;
4170  x1 = x2 < x1 ? x2 : x1;
4171  x2 = x2 < tmp ? tmp : x2;
4172 
4173  for (UInt_t x = x1; x <= x2; x++) {
4174  for (UInt_t w = 0; w < thick; w++) {
4175  if (y + w < fImage->height) {
4176  if ((iDash%2)==0) {
4177  _alphaBlend(&fImage->alt.argb32[(y + w)*fImage->width + x], &color);
4178  }
4179  }
4180  }
4181  i++;
4182 
4183  if (i >= pDash[iDash]) {
4184  iDash++;
4185  i = 0;
4186  }
4187  if (iDash >= nDash) {
4188  iDash = 0;
4189  i = 0;
4190  }
4191  }
4192 }
4193 
4194 ////////////////////////////////////////////////////////////////////////////////
4195 /// Draw a dashed vertical line.
4196 
4198  const char *pDash, UInt_t col, UInt_t thick)
4199 {
4200  UInt_t iDash = 0; // index of current dash
4201  int i = 0;
4202 
4203  ARGB32 color = (ARGB32)col;
4204 
4205  UInt_t half = 0;
4206 
4207  if (thick > 1) {
4208  half = thick >> 1;
4209  if (x > half) {
4210  x = x - half;
4211  } else {
4212  x = 0;
4213  thick += (x - half);
4214  }
4215  }
4216  thick = thick <= 0 ? 1 : thick;
4217 
4218  y2 = y2 >= fImage->height ? fImage->height - 1 : y2;
4219  y1 = y1 >= fImage->height ? fImage->height - 1 : y1;
4220 
4221  // switch x1, x2
4222  UInt_t tmp = y1;
4223  y1 = y2 < y1 ? y2 : y1;
4224  y2 = y2 < tmp ? tmp : y2;
4225 
4226  x = x + thick >= fImage->width ? fImage->width - thick - 1 : x;
4227 
4228  int yy = y1*fImage->width;
4229  for (UInt_t y = y1; y <= y2; y++) {
4230  for (UInt_t w = 0; w < thick; w++) {
4231  if (x + w < fImage->width) {
4232  if ((iDash%2)==0) {
4233  _alphaBlend(&fImage->alt.argb32[yy + (x + w)], &color);
4234  }
4235  }
4236  }
4237  i++;
4238 
4239  if (i >= pDash[iDash]) {
4240  iDash++;
4241  i = 0;
4242  }
4243  if (iDash >= nDash) {
4244  iDash = 0;
4245  i = 0;
4246  }
4247  yy += fImage->width;
4248  }
4249 }
4250 
4251 ////////////////////////////////////////////////////////////////////////////////
4252 /// Draw a dashed line with one pixel width.
4253 
4255  UInt_t nDash, const char *tDash, UInt_t color)
4256 {
4257  int dx, dy, d;
4258  int i, i1, i2;
4259  int x, y, xend, yend;
4260  int xdir, ydir;
4261  int q;
4262  UInt_t iDash = 0; // index of current dash
4263  int yy;
4264  int idx;
4265 
4266  dx = TMath::Abs(Int_t(x2) - Int_t(x1));
4267  dy = TMath::Abs(Int_t(y2) - Int_t(y1));
4268 
4269  char *pDash = new char[nDash];
4270 
4271  if (dy <= dx) {
4272  double ac = TMath::Cos(TMath::ATan2(dy, dx));
4273 
4274  for (i = 0; i < (int)nDash; i++) {
4275  pDash[i] = TMath::Nint(tDash[i] * ac);
4276  }
4277 
4278  UInt_t ddy = dy << 1;
4279  i1 = ddy;
4280  i2 = i1 - (dx << 1);
4281  d = i1 - dx;
4282  i = 0;
4283 
4284  if (x1 > x2) {
4285  x = x2;
4286  y = y2;
4287  ydir = -1;
4288  xend = x1;
4289  } else {
4290  x = x1;
4291  y = y1;
4292  ydir = 1;
4293  xend = x2;
4294  }
4295 
4296  yy = y*fImage->width;
4297  _alphaBlend(&fImage->alt.argb32[y*fImage->width + x], &color);
4298  q = (y2 - y1) * ydir;
4299 
4300  if (q > 0) {
4301  while (x < xend) {
4302  idx = yy + x;
4303  if ((iDash%2) == 0) {
4304  _alphaBlend(&fImage->alt.argb32[idx], &color);
4305  }
4306  x++;
4307  if (d >= 0) {
4308  yy += fImage->width;
4309  d += i2;
4310  } else {
4311  d += i1;
4312  }
4313 
4314  i++;
4315  if (i >= pDash[iDash]) {
4316  iDash++;
4317  i = 0;
4318  }
4319  if (iDash >= nDash) {
4320  iDash = 0;
4321  i = 0;
4322  }
4323  }
4324  } else {
4325  while (x < xend) {
4326  idx = yy + x;
4327  if ((iDash%2) == 0) {
4328  _alphaBlend(&fImage->alt.argb32[idx], &color);
4329  }
4330  x++;
4331  if (d >= 0) {
4332  yy -= fImage->width;
4333  d += i2;
4334  } else {
4335  d += i1;
4336  }
4337 
4338  i++;
4339  if (i >= pDash[iDash]) {
4340  iDash++;
4341  i = 0;
4342  }
4343  if (iDash >= nDash) {
4344  iDash = 0;
4345  i = 0;
4346  }
4347  }
4348  }
4349  } else {
4350  double as = TMath::Sin(TMath::ATan2(dy, dx));
4351 
4352  for (i = 0; i < (int)nDash; i++) {
4353  pDash[i] = TMath::Nint(tDash[i] * as);
4354  }
4355 
4356  UInt_t ddx = dx << 1;
4357  i1 = ddx;
4358  i2 = i1 - (dy << 1);
4359  d = i1 - dy;
4360  i = 0;
4361 
4362  if (y1 > y2) {
4363  y = y2;
4364  x = x2;
4365  yend = y1;
4366  xdir = -1;
4367  } else {
4368  y = y1;
4369  x = x1;
4370  yend = y2;
4371  xdir = 1;
4372  }
4373 
4374  yy = y*fImage->width;
4375  _alphaBlend(&fImage->alt.argb32[y*fImage->width + x], &color);
4376  q = (x2 - x1) * xdir;
4377 
4378  if (q > 0) {
4379  while (y < yend) {
4380  idx = yy + x;
4381  if ((iDash%2) == 0) {
4382  _alphaBlend(&fImage->alt.argb32[idx], &color);
4383  }
4384  y++;
4385  yy += fImage->width;
4386 
4387  if (d >= 0) {
4388  x++;
4389  d += i2;
4390  } else {
4391  d += i1;
4392  }
4393 
4394  i++;
4395  if (i >= pDash[iDash]) {
4396  iDash++;
4397  i = 0;
4398  }
4399  if (iDash >= nDash) {
4400  iDash = 0;
4401  i = 0;
4402  }
4403  }
4404  } else {
4405  while (y < yend) {
4406  idx = yy + x;
4407  if ((iDash%2) == 0) {
4408  _alphaBlend(&fImage->alt.argb32[idx], &color);
4409  }
4410  y++;
4411  yy += fImage->width;
4412 
4413  if (d >= 0) {
4414  x--;
4415  d += i2;
4416  } else {
4417  d += i1;
4418  }
4419 
4420  i++;
4421  if (i >= pDash[iDash]) {
4422  iDash++;
4423  i = 0;
4424  }
4425  if (iDash >= nDash) {
4426  iDash = 0;
4427  i = 0;
4428  }
4429  }
4430  }
4431  }
4432  delete [] pDash;
4433 }
4434 
4435 ////////////////////////////////////////////////////////////////////////////////
4436 /// Draw a dashed line with thick pixel width.
4437 
4439  UInt_t nDash, const char *tDash, UInt_t color, UInt_t thick)
4440 {
4441  int dx, dy;
4442  int i;
4443  double x, y, xend=0, yend=0, x0, y0;
4444  int xdir, ydir;
4445  int q;
4446  UInt_t iDash = 0; // index of current dash
4447 
4448  dx = TMath::Abs(Int_t(x2) - Int_t(x1));
4449  dy = TMath::Abs(Int_t(y2) - Int_t(y1));
4450 
4451  double *xDash = new double[nDash];
4452  double *yDash = new double[nDash];
4453  double a = TMath::ATan2(dy, dx);
4454  double ac = TMath::Cos(a);
4455  double as = TMath::Sin(a);
4456 
4457  for (i = 0; i < (int)nDash; i++) {
4458  xDash[i] = tDash[i] * ac;
4459  yDash[i] = tDash[i] * as;
4460 
4461  // dirty trick (must be fixed)
4462  if ((i%2) == 0) {
4463  xDash[i] = xDash[i]/2;
4464  yDash[i] = yDash[i]/2;
4465  } else {
4466  xDash[i] = xDash[i]*2;
4467  yDash[i] = yDash[i]*2;
4468  }
4469  }
4470 
4471  if (dy <= dx) {
4472  if (x1 > x2) {
4473  x = x2;
4474  y = y2;
4475  ydir = -1;
4476  xend = x1;
4477  } else {
4478  x = x1;
4479  y = y1;
4480  ydir = 1;
4481  xend = x2;
4482  }
4483 
4484  q = (y2 - y1) * ydir;
4485  x0 = x;
4486  y0 = y;
4487  iDash = 0;
4488  yend = y + q;
4489 
4490  if (q > 0) {
4491  while ((x < xend) && (y < yend)) {
4492  x += xDash[iDash];
4493  y += yDash[iDash];
4494 
4495  if ((iDash%2) == 0) {
4497  TMath::Nint(x), TMath::Nint(y), color, thick);
4498  } else {
4499  x0 = x;
4500  y0 = y;
4501  }
4502 
4503  iDash++;
4504 
4505  if (iDash >= nDash) {
4506  iDash = 0;
4507  }
4508  }
4509  } else {
4510  while ((x < xend) && (y > yend)) {
4511  x += xDash[iDash];
4512  y -= yDash[iDash];
4513 
4514  if ((iDash%2) == 0) {
4516  TMath::Nint(x), TMath::Nint(y), color, thick);
4517  } else {
4518  x0 = x;
4519  y0 = y;
4520  }
4521 
4522  iDash++;
4523 
4524  if (iDash >= nDash) {
4525  iDash = 0;
4526  }
4527  }
4528  }
4529  } else {
4530 
4531  if (y1 > y2) {
4532  y = y2;
4533  x = x2;
4534  yend = y1;
4535  xdir = -1;
4536  } else {
4537  y = y1;
4538  x = x1;
4539  yend = y2;
4540  xdir = 1;
4541  }
4542 
4543  q = (x2 - x1) * xdir;
4544  x0 = x;
4545  y0 = y;
4546  iDash = 0;
4547  xend = x + q;
4548 
4549  if (q > 0) {
4550  while ((x < xend) && (y < yend)) {
4551  x += xDash[iDash];
4552  y += yDash[iDash];
4553 
4554  if ((iDash%2) == 0) {
4556  TMath::Nint(x), TMath::Nint(y), color, thick);
4557  } else {
4558  x0 = x;
4559  y0 = y;
4560  }
4561 
4562  iDash++;
4563 
4564  if (iDash >= nDash) {
4565  iDash = 0;
4566  }
4567  }
4568  } else {
4569  while ((x > xend) && (y < yend)) {
4570  x -= xDash[iDash];
4571  y += yDash[iDash];
4572 
4573  if ((iDash%2) == 0) {
4575  TMath::Nint(x), TMath::Nint(y), color, thick);
4576  } else {
4577  x0 = x;
4578  y0 = y;
4579  }
4580 
4581  iDash++;
4582 
4583  if (iDash >= nDash) {
4584  iDash = 0;
4585  }
4586  }
4587  }
4588  }
4589  delete [] xDash;
4590  delete [] yDash;
4591 }
4592 
4593 ////////////////////////////////////////////////////////////////////////////////
4594 /// Draw a dashed line.
4595 
4597  const char *pDash, const char *col, UInt_t thick)
4598 
4599 {
4600  if (!InitVisual()) {
4601  Warning("DrawDashLine", "Visual not initiated");
4602  return;
4603  }
4604 
4605  if (!fImage) {
4606  Warning("DrawDashLine", "no image");
4607  return;
4608  }
4609 
4610  if (!fImage->alt.argb32) {
4611  BeginPaint();
4612  }
4613 
4614  if (!fImage->alt.argb32) {
4615  Warning("DrawDashLine", "Failed to get pixel array");
4616  return;
4617  }
4618 
4619  if ((nDash < 2) || !pDash || (nDash%2)) {
4620  Warning("DrawDashLine", "Wrong input parameters n=%d %ld", nDash, (Long_t)sizeof(pDash)-1);
4621  return;
4622  }
4623 
4624  ARGB32 color = ARGB32_White;
4625  parse_argb_color(col, &color);
4626 
4627  if (x1 == x2) {
4628  DrawDashVLine(x1, y1, y2, nDash, pDash, (UInt_t)color, thick);
4629  } else if (y1 == y2) {
4630  DrawDashHLine(y1, x1, x2, nDash, pDash, (UInt_t)color, thick);
4631  } else {
4632  if (thick < 2) DrawDashZLine(x1, y1, x2, y2, nDash, pDash, (UInt_t)color);
4633  else DrawDashZTLine(x1, y1, x2, y2, nDash, pDash, (UInt_t)color, thick);
4634  }
4635 }
4636 
4637 ////////////////////////////////////////////////////////////////////////////////
4638 /// Draw a polyline.
4639 
4640 void TASImage::DrawPolyLine(UInt_t nn, TPoint *xy, const char *col, UInt_t thick,
4641  TImage::ECoordMode mode)
4642 {
4643  ARGB32 color = ARGB32_White;
4644  parse_argb_color(col, &color);
4645 
4646  Int_t x0 = xy[0].GetX();
4647  Int_t y0 = xy[0].GetY();
4648  Int_t x = 0;
4649  Int_t y = 0;
4650 
4651  for (UInt_t i = 1; i < nn; i++) {
4652  x = (mode == kCoordModePrevious) ? x + xy[i].GetX() : xy[i].GetX();
4653  y = (mode == kCoordModePrevious) ? y + xy[i].GetY() : xy[i].GetY();
4654 
4655  DrawLineInternal(x0, y0, x, y, (UInt_t)color, thick);
4656 
4657  x0 = x;
4658  y0 = y;
4659  }
4660 }
4661 
4662 ////////////////////////////////////////////////////////////////////////////////
4663 /// Draw a point at the specified position.
4664 
4665 void TASImage::PutPixel(Int_t x, Int_t y, const char *col)
4666 {
4667  if (!InitVisual()) {
4668  Warning("PutPixel", "Visual not initiated");
4669  return;
4670  }
4671 
4672  if (!fImage) {
4673  Warning("PutPixel", "no image");
4674  return;
4675  }
4676 
4677  if (!fImage->alt.argb32) {
4678  BeginPaint();
4679  }
4680 
4681  if (!fImage->alt.argb32) {
4682  Warning("PutPixel", "Failed to get pixel array");
4683  return;
4684  }
4685 
4686  ARGB32 color;
4687  parse_argb_color(col, &color);
4688 
4689  if ((x < 0) || (y < 0) || (x >= (int)fImage->width) || (y >= (int)fImage->height)) {
4690  Warning("PutPixel", "Out of range width=%d x=%d, height=%d y=%d",
4691  fImage->width, x, fImage->height, y);
4692  return;
4693  }
4694  _alphaBlend(&fImage->alt.argb32[y*fImage->width + x], &color);
4695 }
4696 
4697 ////////////////////////////////////////////////////////////////////////////////
4698 /// Draw a poly point.
4699 
4700 void TASImage::PolyPoint(UInt_t npt, TPoint *ppt, const char *col, TImage::ECoordMode mode)
4701 {
4702  if (!InitVisual()) {
4703  Warning("PolyPoint", "Visual not initiated");
4704  return;
4705  }
4706 
4707  if (!fImage) {
4708  Warning("PolyPoint", "no image");
4709  return;
4710  }
4711 
4712  if (!fImage->alt.argb32) {
4713  BeginPaint();
4714  }
4715 
4716  if (!fImage->alt.argb32) {
4717  Warning("PolyPoint", "Failed to get pixel array");
4718  return;
4719  }
4720 
4721  if (!npt || !ppt) {
4722  Warning("PolyPoint", "No points specified");
4723  return;
4724  }
4725 
4726  TPoint *ipt = 0;
4727  UInt_t i = 0;
4728  ARGB32 color;
4729  parse_argb_color(col, &color);
4730 
4731  //make pointlist origin relative
4732  if (mode == kCoordModePrevious) {
4733  ipt = new TPoint[npt];
4734 
4735  for (i = 0; i < npt; i++) {
4736  ipt[i].fX += ppt[i].fX;
4737  ipt[i].fY += ppt[i].fY;
4738  }
4739  }
4740  int x, y;
4741 
4742  for (i = 0; i < npt; i++) {
4743  x = ipt ? ipt[i].fX : ppt[i].fX;
4744  y = ipt ? ipt[i].fY : ppt[i].fY;
4745 
4746  if ((x < 0) || (y < 0) || (x >= (int)fImage->width) || (y >= (int)fImage->height)) {
4747  continue;
4748  }
4749  _alphaBlend(&fImage->alt.argb32[y*fImage->width + x], &color);
4750  }
4751 
4752  if (ipt) {
4753  delete [] ipt;
4754  }
4755 }
4756 
4757 ////////////////////////////////////////////////////////////////////////////////
4758 /// Draw segments.
4759 
4760 void TASImage::DrawSegments(UInt_t nseg, Segment_t *seg, const char *col, UInt_t thick)
4761 {
4762  if (!nseg || !seg) {
4763  Warning("DrawSegments", "Invalid data nseg=%d seg=0x%lx", nseg, (Long_t)seg);
4764  return;
4765  }
4766 
4767  TPoint pt[2];
4768 
4769  for (UInt_t i = 0; i < nseg; i++) {
4770  pt[0].fX = seg->fX1;
4771  pt[1].fX = seg->fX2;
4772  pt[0].fY = seg->fY1;
4773  pt[1].fY = seg->fY2;
4774 
4775  DrawPolyLine(2, pt, col, thick, kCoordModeOrigin);
4776  seg++;
4777  }
4778 }
4779 
4780 ////////////////////////////////////////////////////////////////////////////////
4781 /// Fill spans with specified color or/and stipple.
4782 
4783 void TASImage::FillSpans(UInt_t npt, TPoint *ppt, UInt_t *widths, const char *col,
4784  const char *stipple, UInt_t w, UInt_t h)
4785 {
4786  if (!InitVisual()) {
4787  Warning("FillSpans", "Visual not initiated");
4788  return;
4789  }
4790 
4791  if (!fImage) {
4792  Warning("FillSpans", "no image");
4793  return;
4794  }
4795 
4796  if (!fImage->alt.argb32) {
4797  BeginPaint();
4798  }
4799 
4800  if (!fImage->alt.argb32) {
4801  Warning("FillSpans", "Failed to get pixel array");
4802  return;
4803  }
4804 
4805  if (!npt || !ppt || !widths || (stipple && (!w || !h))) {
4806  Warning("FillSpans", "Invalid input data npt=%d ppt=0x%lx col=%s widths=0x%lx stipple=0x%lx w=%d h=%d",
4807  npt, (Long_t)ppt, col, (Long_t)widths, (Long_t)stipple, w, h);
4808  return;
4809  }
4810 
4811  ARGB32 color;
4812  parse_argb_color(col, &color);
4813  Int_t idx = 0;
4814  UInt_t x = 0;
4815  UInt_t yy;
4816 
4817  for (UInt_t i = 0; i < npt; i++) {
4818  yy = ppt[i].fY*fImage->width;
4819  for (UInt_t j = 0; j < widths[i]; j++) {
4820  if ((ppt[i].fX >= (Int_t)fImage->width) || (ppt[i].fX < 0) ||
4821  (ppt[i].fY >= (Int_t)fImage->height) || (ppt[i].fY < 0)) continue;
4822 
4823  x = ppt[i].fX + j;
4824  idx = yy + x;
4825 
4826  if (!stipple) {
4827  _alphaBlend(&fImage->alt.argb32[idx], &color);
4828  } else {
4829  Int_t ii = (ppt[i].fY%h)*w + x%w;
4830 
4831  if (stipple[ii >> 3] & (1 << (ii%8))) {
4832  _alphaBlend(&fImage->alt.argb32[idx], &color);
4833  }
4834  }
4835  }
4836  }
4837 }
4838 
4839 ////////////////////////////////////////////////////////////////////////////////
4840 /// Fill spans with tile image.
4841 
4842 void TASImage::FillSpans(UInt_t npt, TPoint *ppt, UInt_t *widths, TImage *tile)
4843 {
4844  if (!InitVisual()) {
4845  Warning("FillSpans", "Visual not initiated");
4846  return;
4847  }
4848 
4849  if (!fImage) {
4850  Warning("FillSpans", "no image");
4851  return;
4852  }
4853 
4854  if (!fImage->alt.argb32) {
4855  BeginPaint();
4856  }
4857 
4858  if (!fImage->alt.argb32) {
4859  Warning("FillSpans", "Failed to get pixel array");
4860  return;
4861  }
4862 
4863  if (!npt || !ppt || !widths || !tile) {
4864  Warning("FillSpans", "Invalid input data npt=%d ppt=0x%lx widths=0x%lx tile=0x%lx",
4865  npt, (Long_t)ppt, (Long_t)widths, (Long_t)tile);
4866  return;
4867  }
4868 
4869  Int_t idx = 0;
4870  Int_t ii = 0;
4871  UInt_t x = 0;
4872  UInt_t *arr = tile->GetArgbArray();
4873  if (!arr) return;
4874  UInt_t xx = 0;
4875  UInt_t yy = 0;
4876  UInt_t yyy = 0;
4877 
4878  for (UInt_t i = 0; i < npt; i++) {
4879  yyy = ppt[i].fY*fImage->width;
4880 
4881  for (UInt_t j = 0; j < widths[i]; j++) {
4882  if ((ppt[i].fX >= (Int_t)fImage->width) || (ppt[i].fX < 0) ||
4883  (ppt[i].fY >= (Int_t)fImage->height) || (ppt[i].fY < 0)) continue;
4884  x = ppt[i].fX + j;
4885  idx = yyy + x;
4886  xx = x%tile->GetWidth();
4887  yy = ppt[i].fY%tile->GetHeight();
4888  ii = yy*tile->GetWidth() + xx;
4889  _alphaBlend(&fImage->alt.argb32[idx], &arr[ii]);
4890  }
4891  yyy += fImage->width;;
4892  }
4893 }
4894 
4895 ////////////////////////////////////////////////////////////////////////////////
4896 /// Crop spans.
4897 
4898 void TASImage::CropSpans(UInt_t npt, TPoint *ppt, UInt_t *widths)
4899 {
4900  if (!InitVisual()) {
4901  Warning("CropSpans", "Visual not initiated");
4902  return;
4903  }
4904 
4905  if (!fImage) {
4906  Warning("CropSpans", "no image");
4907  return;
4908  }
4909 
4910  if (!fImage->alt.argb32) {
4911  BeginPaint();
4912  }
4913 
4914  if (!fImage->alt.argb32) {
4915  Warning("CropSpans", "Failed to get pixel array");
4916  return;
4917  }
4918 
4919  if (!npt || !ppt || !widths) {
4920  Warning("CropSpans", "No points specified npt=%d ppt=0x%lx widths=0x%lx", npt, (Long_t)ppt, (Long_t)widths);
4921  return;
4922  }
4923 
4924  int y0 = ppt[0].fY;
4925  int y1 = ppt[npt-1].fY;
4926  UInt_t y = 0;
4927  UInt_t x = 0;
4928  UInt_t i = 0;
4929  UInt_t idx = 0;
4930  UInt_t sz = fImage->width*fImage->height;
4931  UInt_t yy = y*fImage->width;
4932 
4933  for (y = 0; (int)y < y0; y++) {
4934  for (x = 0; x < fImage->width; x++) {
4935  idx = yy + x;
4936  if (idx < sz) fImage->alt.argb32[idx] = 0;
4937  }
4938  yy += fImage->width;
4939  }
4940 
4941  for (i = 0; i < npt; i++) {
4942  for (x = 0; (int)x < ppt[i].fX; x++) {
4943  idx = ppt[i].fY*fImage->width + x;
4944  if (idx < sz) fImage->alt.argb32[idx] = 0;
4945  }
4946  for (x = ppt[i].fX + widths[i] + 1; x < fImage->width; x++) {
4947  idx = ppt[i].fY*fImage->width + x;
4948  if (idx < sz) fImage->alt.argb32[idx] = 0;
4949  }
4950  }
4951 
4952  yy = y1*fImage->width;
4953  for (y = y1; y < fImage->height; y++) {
4954  for (x = 0; x < fImage->width; x++) {
4955  idx = yy + x;
4956  if (idx < sz) fImage->alt.argb32[idx] = 0;
4957  }
4958  yy += fImage->width;
4959  }
4960 }
4961 
4962 ////////////////////////////////////////////////////////////////////////////////
4963 /// Copy source region to the destination image. Copy is done according
4964 /// to specified function:
4965 /// ~~~ {.cpp}
4966 /// enum EGraphicsFunction {
4967 /// kGXclear = 0, // 0
4968 /// kGXand, // src AND dst
4969 /// kGXandReverse, // src AND NOT dst
4970 /// kGXcopy, // src (default)
4971 /// kGXandInverted, // NOT src AND dst
4972 /// kGXnoop, // dst
4973 /// kGXxor, // src XOR dst
4974 /// kGXor, // src OR dst
4975 /// kGXnor, // NOT src AND NOT dst
4976 /// kGXequiv, // NOT src XOR dst
4977 /// kGXinvert, // NOT dst
4978 /// kGXorReverse, // src OR NOT dst
4979 /// kGXcopyInverted, // NOT src
4980 /// kGXorInverted, // NOT src OR dst
4981 /// kGXnand, // NOT src OR NOT dst
4982 /// kGXset // 1
4983 /// };
4984 /// ~~~
4985 
4986 void TASImage::CopyArea(TImage *dst, Int_t xsrc, Int_t ysrc, UInt_t w, UInt_t h,
4987  Int_t xdst, Int_t ydst, Int_t gfunc, EColorChan)
4988 {
4989  if (!InitVisual()) {
4990  Warning("CopyArea", "Visual not initiated");
4991  return;
4992  }
4993 
4994  if (!fImage) {
4995  Warning("CopyArea", "no image");
4996  return;
4997  }
4998  if (!dst) return;
4999 
5000  ASImage *out = ((TASImage*)dst)->GetImage();
5001 
5002  int x = 0;
5003  int y = 0;
5004  int idx = 0;
5005  int idx2 = 0;
5006  xsrc = xsrc < 0 ? 0 : xsrc;
5007  ysrc = ysrc < 0 ? 0 : ysrc;
5008 
5009  if ((xsrc >= (int)fImage->width) || (ysrc >= (int)fImage->height)) return;
5010 
5011  w = xsrc + w > fImage->width ? fImage->width - xsrc : w;
5012  h = ysrc + h > fImage->height ? fImage->height - ysrc : h;
5013  UInt_t yy = (ysrc + y)*fImage->width;
5014 
5015  if (!fImage->alt.argb32) {
5016  BeginPaint();
5017  }
5018  if (!out->alt.argb32) {
5019  dst->BeginPaint();
5020  out = ((TASImage*)dst)->GetImage();
5021  }
5022 
5023  if (fImage->alt.argb32 && out->alt.argb32) {
5024  for (y = 0; y < (int)h; y++) {
5025  for (x = 0; x < (int)w; x++) {
5026  idx = yy + x + xsrc;
5027  if ((x + xdst < 0) || (ydst + y < 0) ||
5028  (x + xdst >= (int)out->width) || (y + ydst >= (int)out->height) ) continue;
5029 
5030  idx2 = (ydst + y)*out->width + x + xdst;
5031 
5032  switch ((EGraphicsFunction)gfunc) {
5033  case kGXclear:
5034  out->alt.argb32[idx2] = 0;
5035  break;
5036  case kGXand:
5037  out->alt.argb32[idx2] &= fImage->alt.argb32[idx];
5038  break;
5039  case kGXandReverse:
5040  out->alt.argb32[idx2] = fImage->alt.argb32[idx] & (~out->alt.argb32[idx2]);
5041  break;
5042  case kGXandInverted:
5043  out->alt.argb32[idx2] &= ~fImage->alt.argb32[idx];
5044  break;
5045  case kGXnoop:
5046  break;
5047  case kGXxor:
5048  out->alt.argb32[idx2] ^= fImage->alt.argb32[idx];
5049  break;
5050  case kGXor:
5051  out->alt.argb32[idx2] |= fImage->alt.argb32[idx];
5052  break;
5053  case kGXnor:
5054  out->alt.argb32[idx2] = (~fImage->alt.argb32[idx]) & (~out->alt.argb32[idx2]);
5055  break;
5056  case kGXequiv:
5057  out->alt.argb32[idx2] ^= ~fImage->alt.argb32[idx];
5058  break;
5059  case kGXinvert:
5060  out->alt.argb32[idx2] = ~out->alt.argb32[idx2];
5061  break;
5062  case kGXorReverse:
5063  out->alt.argb32[idx2] = fImage->alt.argb32[idx] | (~out->alt.argb32[idx2]);
5064  break;
5065  case kGXcopyInverted:
5066  out->alt.argb32[idx2] = ~fImage->alt.argb32[idx];
5067  break;
5068  case kGXorInverted:
5069  out->alt.argb32[idx2] |= ~fImage->alt.argb32[idx];
5070  break;
5071  case kGXnand:
5072  out->alt.argb32[idx2] = (~fImage->alt.argb32[idx]) | (~out->alt.argb32[idx2]);
5073  break;
5074  case kGXset:
5075  out->alt.argb32[idx2] = 0xFFFFFFFF;
5076  break;
5077  case kGXcopy:
5078  default:
5079  out->alt.argb32[idx2] = fImage->alt.argb32[idx];
5080  break;
5081  }
5082  }
5083  yy += fImage->width;
5084  }
5085  }
5086 }
5087 
5088 ////////////////////////////////////////////////////////////////////////////////
5089 /// Draw a cell array.
5090 ///
5091 /// \param[in] x1,y1 : left down corner
5092 /// \param[in] x2,y2 : right up corner
5093 /// \param[in] nx,ny : array size
5094 /// \param[in] ic : array of ARGB32 colors
5095 ///
5096 /// Draw a cell array. The drawing is done with the pixel precision
5097 /// if (X2-X1)/NX (or Y) is not a exact pixel number the position of
5098 /// the top right corner may be wrong.
5099 
5101  Int_t ny, UInt_t *ic)
5102 {
5103  int i, j, ix, iy, w, h;
5104 
5105  ARGB32 color = 0xFFFFFFFF;
5106  ARGB32 icol;
5107 
5108  w = TMath::Max((x2-x1)/(nx),1);
5109  h = TMath::Max((y1-y2)/(ny),1);
5110  ix = x1;
5111 
5112  for (i = 0; i < nx; i++) {
5113  iy = y1 - h;
5114  for (j = 0; j < ny; j++) {
5115  icol = (ARGB32)ic[i + (nx*j)];
5116  if (icol != color) {
5117  color = icol;
5118  }
5119  FillRectangleInternal((UInt_t)color, ix, iy, w, h);
5120  iy = iy - h;
5121  }
5122  ix = ix + w;
5123  }
5124 }
5125 
5126 ////////////////////////////////////////////////////////////////////////////////
5127 /// Return alpha-blended value computed from bottom and top pixel values.
5128 
5130 {
5131  UInt_t ret = bot;
5132 
5133  _alphaBlend(&ret, &top);
5134  return ret;
5135 }
5136 
5137 ////////////////////////////////////////////////////////////////////////////////
5138 /// Return visual.
5139 
5140 const ASVisual *TASImage::GetVisual()
5141 {
5142  return fgVisual;
5143 }
5144 
5145 ////////////////////////////////////////////////////////////////////////////////
5146 /// Get poly bounds along Y.
5147 
5148 static int GetPolyYBounds(TPoint *pts, int n, int *by, int *ty)
5149 {
5150  TPoint *ptMin;
5151  int ymin, ymax;
5152  TPoint *ptsStart = pts;
5153 
5154  ptMin = pts;
5155  ymin = ymax = (pts++)->fY;
5156 
5157  while (--n > 0) {
5158  if (pts->fY < ymin) {
5159  ptMin = pts;
5160  ymin = pts->fY;
5161  }
5162  if (pts->fY > ymax) {
5163  ymax = pts->fY;
5164  }
5165  pts++;
5166  }
5167 
5168  *by = ymin;
5169  *ty = ymax;
5170  return (ptMin - ptsStart);
5171 }
5172 
5173 ////////////////////////////////////////////////////////////////////////////////
5174 /// The code is based on Xserver/mi/mipolycon.c
5175 /// "Copyright 1987, 1998 The Open Group"
5176 
5178  TPoint **outPoint, UInt_t **outWidth)
5179 {
5180  int xl = 0; // x vals of leftedges
5181  int xr = 0; // x vals of right edges
5182  int dl = 0; // decision variables
5183  int dr = 0; // decision variables
5184  int ml = 0; // left edge slope
5185  int m1l = 0; // left edge slope+1
5186  int mr = 0, m1r = 0; // right edge slope and slope+1
5187  int incr1l = 0, incr2l = 0; // left edge error increments
5188  int incr1r = 0, incr2r = 0; // right edge error increments
5189  int dy; // delta y
5190  int y; // current scanline
5191  int left, right; // indices to first endpoints
5192  int i; // loop counter
5193  int nextleft, nextright; // indices to second endpoints
5194  TPoint *ptsOut; // output buffer
5195  UInt_t *width; // output buffer
5196  TPoint *firstPoint=0;
5197  UInt_t *firstWidth=0;
5198  int imin; // index of smallest vertex (in y)
5199  int ymin; // y-extents of polygon
5200  int ymax;
5201  Bool_t ret = kTRUE;
5202 
5203  *nspans = 0;
5204 
5205  if (!InitVisual()) {
5206  Warning("GetPolygonSpans", "Visual not initiated");
5207  return kFALSE;
5208  }
5209 
5210  if (!fImage) {
5211  Warning("GetPolygonSpans", "no image");
5212  return kFALSE;
5213  }
5214 
5215  if (!fImage->alt.argb32) {
5216  BeginPaint();
5217  }
5218 
5219  if (!fImage->alt.argb32) {
5220  Warning("GetPolygonSpans", "Failed to get pixel array");
5221  return kFALSE;
5222  }
5223 
5224  if ((npt < 3) || !ppt) {
5225  Warning("GetPolygonSpans", "No points specified npt=%d ppt=0x%lx", npt, (Long_t)ppt);
5226  return kFALSE;
5227  }
5228 
5229  // find leftx, bottomy, rightx, topy, and the index
5230  // of bottomy. Also translate the points.
5231  imin = GetPolyYBounds(ppt, npt, &ymin, &ymax);
5232 
5233  dy = ymax - ymin + 1;
5234  if ((npt < 3) || (dy < 0)) return kFALSE;
5235 
5236  ptsOut = firstPoint = new TPoint[dy];
5237  width = firstWidth = new UInt_t[dy];
5238  ret = kTRUE;
5239 
5240  nextleft = nextright = imin;
5241  y = ppt[nextleft].fY;
5242 
5243  // loop through all edges of the polygon
5244  do {
5245  // add a left edge if we need to
5246  if (ppt[nextleft].fY == y) {
5247  left = nextleft;
5248 
5249  // find the next edge, considering the end
5250  // conditions of the array.
5251  nextleft++;
5252  if (nextleft >= (int)npt) {
5253  nextleft = 0;
5254  }
5255 
5256  // now compute all of the random information
5257  // needed to run the iterative algorithm.
5258  BRESINITPGON(ppt[nextleft].fY - ppt[left].fY,
5259  ppt[left].fX, ppt[nextleft].fX,
5260  xl, dl, ml, m1l, incr1l, incr2l);
5261  }
5262 
5263  // add a right edge if we need to
5264  if (ppt[nextright].fY == y) {
5265  right = nextright;
5266 
5267  // find the next edge, considering the end
5268  // conditions of the array.
5269  nextright--;
5270  if (nextright < 0) {
5271  nextright = npt-1;
5272  }
5273 
5274  // now compute all of the random information
5275  // needed to run the iterative algorithm.
5276  BRESINITPGON(ppt[nextright].fY - ppt[right].fY,
5277  ppt[right].fX, ppt[nextright].fX,
5278  xr, dr, mr, m1r, incr1r, incr2r);
5279  }
5280 
5281  // generate scans to fill while we still have
5282  // a right edge as well as a left edge.
5283  i = TMath::Min(ppt[nextleft].fY, ppt[nextright].fY) - y;
5284 
5285  // in case of non-convex polygon
5286  if (i < 0) {
5287  delete [] firstWidth;
5288  delete [] firstPoint;
5289  return kTRUE;
5290  }
5291 
5292  while (i-- > 0) {
5293  ptsOut->fY = y;
5294 
5295  // reverse the edges if necessary
5296  if (xl < xr) {
5297  *(width++) = xr - xl;
5298  (ptsOut++)->fX = xl;
5299  } else {
5300  *(width++) = xl - xr;
5301  (ptsOut++)->fX = xr;
5302  }
5303  y++;
5304 
5305  // increment down the edges
5306  BRESINCRPGON(dl, xl, ml, m1l, incr1l, incr2l);
5307  BRESINCRPGON(dr, xr, mr, m1r, incr1r, incr2r);
5308  }
5309  } while (y != ymax);
5310 
5311  *nspans = UInt_t(ptsOut - firstPoint);
5312  *outPoint = firstPoint;
5313  *outWidth = firstWidth;
5314 
5315  return ret;
5316 }
5317 
5318 ////////////////////////////////////////////////////////////////////////////////
5319 /// Fill a convex polygon with background color or bitmap.
5320 /// For non convex polygon one must use DrawFillArea method
5321 
5322 void TASImage::FillPolygon(UInt_t npt, TPoint *ppt, const char *col,
5323  const char *stipple, UInt_t w, UInt_t h)
5324 {
5325  UInt_t nspans = 0;
5326  TPoint *firstPoint = 0; // output buffer
5327  UInt_t *firstWidth = 0; // output buffer
5328 
5329  Bool_t del = GetPolygonSpans(npt, ppt, &nspans, &firstPoint, &firstWidth);
5330  ARGB32 color = ARGB32_White;
5331  parse_argb_color(col, &color);
5332 
5333  if (nspans) {
5334  if (!stipple && ((color & 0xff000000)==0xff000000)) { //no stipple no alpha
5335  FillSpansInternal(nspans, firstPoint, firstWidth, color);
5336  } else {
5337  FillSpans(nspans, firstPoint, firstWidth, col, stipple, w, h);
5338  }
5339 
5340  if (del) {
5341  delete [] firstWidth;
5342  delete [] firstPoint;
5343  }
5344  } else {
5345  if (firstWidth) delete [] firstWidth;
5346  if (firstPoint) delete [] firstPoint;
5347  }
5348 }
5349 
5350 ////////////////////////////////////////////////////////////////////////////////
5351 /// Fill a convex polygon with background image.
5352 /// For non convex polygon one must use DrawFillArea method
5353 
5355 {
5356  UInt_t nspans = 0;
5357  TPoint *firstPoint = 0; // output buffer
5358  UInt_t *firstWidth = 0; // output buffer
5359 
5360  Bool_t del = GetPolygonSpans(npt, ppt, &nspans, &firstPoint, &firstWidth);
5361 
5362  if (nspans) {
5363  FillSpans(nspans, firstPoint, firstWidth, tile);
5364 
5365  if (del) {
5366  delete [] firstWidth;
5367  delete [] firstPoint;
5368  }
5369  } else {
5370  if (firstWidth) delete [] firstWidth;
5371  if (firstPoint) delete [] firstPoint;
5372  }
5373 }
5374 
5375 ////////////////////////////////////////////////////////////////////////////////
5376 /// Crop a convex polygon.
5377 
5379 {
5380  UInt_t nspans = 0;
5381  TPoint *firstPoint = 0;
5382  UInt_t *firstWidth = 0;
5383 
5384  Bool_t del = GetPolygonSpans(npt, ppt, &nspans, &firstPoint, &firstWidth);
5385 
5386  if (nspans) {
5387  CropSpans(nspans, firstPoint, firstWidth);
5388 
5389  if (del) {
5390  delete [] firstWidth;
5391  delete [] firstPoint;
5392  }
5393  } else {
5394  if (firstWidth) delete [] firstWidth;
5395  if (firstPoint) delete [] firstPoint;
5396  }
5397 }
5398 
5399 static const UInt_t NUMPTSTOBUFFER = 512;
5400 
5401 ////////////////////////////////////////////////////////////////////////////////
5402 /// Fill a polygon (any type convex, non-convex).
5403 
5404 void TASImage::DrawFillArea(UInt_t count, TPoint *ptsIn, const char *col,
5405  const char *stipple, UInt_t w, UInt_t h)
5406 {
5407  if (!InitVisual()) {
5408  Warning("DrawFillArea", "Visual not initiated");
5409  return;
5410  }
5411 
5412  if (!fImage) {
5413  Warning("DrawFillArea", "no image");
5414  return;
5415  }
5416 
5417  if (!fImage->alt.argb32) {
5418  BeginPaint();
5419  }
5420 
5421  if (!fImage->alt.argb32) {
5422  Warning("DrawFillArea", "Failed to get pixel array");
5423  return;
5424  }
5425 
5426  if ((count < 3) || !ptsIn) {
5427  Warning("DrawFillArea", "No points specified npt=%d ppt=0x%lx", count, (Long_t)ptsIn);
5428  return;
5429  }
5430 
5431  if (count < 5) {
5432  FillPolygon(count, ptsIn, col, stipple, w, h);
5433  return;
5434  }
5435 
5436  ARGB32 color = ARGB32_White;
5437  parse_argb_color(col, &color);
5438 
5439  EdgeTableEntry *pAET; // the Active Edge Table
5440  int y; // the current scanline
5441  UInt_t nPts = 0; // number of pts in buffer
5442 
5443  ScanLineList *pSLL; // Current ScanLineList
5444  TPoint *ptsOut; // ptr to output buffers
5445  UInt_t *width;
5446  TPoint firstPoint[NUMPTSTOBUFFER]; // the output buffers
5447  UInt_t firstWidth[NUMPTSTOBUFFER];
5448  EdgeTableEntry *pPrevAET; // previous AET entry
5449  EdgeTable ET; // Edge Table header node
5450  EdgeTableEntry AET; // Active ET header node
5451  EdgeTableEntry *pETEs; // Edge Table Entries buff
5452  ScanLineListBlock SLLBlock; // header for ScanLineList
5453  Bool_t del = kTRUE;
5454 
5455  static const UInt_t gEdgeTableEntryCacheSize = 200;
5456  static EdgeTableEntry gEdgeTableEntryCache[gEdgeTableEntryCacheSize];
5457 
5458  if (count < gEdgeTableEntryCacheSize) {
5459  pETEs = (EdgeTableEntry*)&gEdgeTableEntryCache;
5460  del = kFALSE;
5461  } else {
5462  pETEs = new EdgeTableEntry[count];
5463  del = kTRUE;
5464  }
5465 
5466  ptsOut = firstPoint;
5467  width = firstWidth;
5468  CreateETandAET(count, ptsIn, &ET, &AET, pETEs, &SLLBlock);
5469  pSLL = ET.scanlines.next;
5470 
5471  for (y = ET.ymin; y < ET.ymax; y++) {
5472  if (pSLL && y == pSLL->scanline) {
5473  loadAET(&AET, pSLL->edgelist);
5474  pSLL = pSLL->next;
5475  }
5476  pPrevAET = &AET;
5477  pAET = AET.next;
5478 
5479  while (pAET) {
5480  ptsOut->fX = pAET->bres.minor_axis;
5481  ptsOut->fY = y;
5482  ptsOut++;
5483  nPts++;
5484 
5485  *width++ = pAET->next->bres.minor_axis - pAET->bres.minor_axis;
5486 
5487  if (nPts == NUMPTSTOBUFFER) {
5488  if (!stipple && ((color & 0xff000000)==0xff000000)) { //no stipple, no alpha
5489  FillSpansInternal(nPts, firstPoint, firstWidth, color);
5490  } else {
5491  FillSpans(nPts, firstPoint, firstWidth, col, stipple, w, h);
5492  }
5493  ptsOut = firstPoint;
5494  width = firstWidth;
5495  nPts = 0;
5496  }
5497  EVALUATEEDGEEVENODD(pAET, pPrevAET, y)
5498  EVALUATEEDGEEVENODD(pAET, pPrevAET, y)
5499  }
5500  InsertionSort(&AET);
5501  }
5502 
5503  if (nPts) {
5504  if (!stipple && ((color & 0xff000000)==0xff000000)) { //no stipple, no alpha
5505  FillSpansInternal(nPts, firstPoint, firstWidth, color);
5506  } else {
5507  FillSpans(nPts, firstPoint, firstWidth, col, stipple, w, h);
5508  }
5509  }
5510 
5511  if (del) delete [] pETEs;
5512  FreeStorage(SLLBlock.next);
5513 }
5514 
5515 ////////////////////////////////////////////////////////////////////////////////
5516 /// Fill a polygon (any type convex, non-convex).
5517 
5518 void TASImage::DrawFillArea(UInt_t count, TPoint *ptsIn, TImage *tile)
5519 {
5520  if (!InitVisual()) {
5521  Warning("DrawFillArea", "Visual not initiated");
5522  return;
5523  }
5524 
5525  if (!fImage) {
5526  Warning("DrawFillArea", "no image");
5527  return;
5528  }
5529 
5530  if (!fImage->alt.argb32) {
5531  BeginPaint();
5532  }
5533 
5534  if (!fImage->alt.argb32) {
5535  Warning("DrawFillArea", "Failed to get pixel array");
5536  return;
5537  }
5538 
5539  if ((count < 3) || !ptsIn) {
5540  Warning("DrawFillArea", "No points specified npt=%d ppt=0x%lx", count, (Long_t)ptsIn);
5541  return;
5542  }
5543 
5544  if (count < 5) {
5545  FillPolygon(count, ptsIn, tile);
5546  return;
5547  }
5548 
5549  EdgeTableEntry *pAET; // the Active Edge Table
5550  int y; // the current scanline
5551  UInt_t nPts = 0; // number of pts in buffer
5552 
5553  ScanLineList *pSLL; // Current ScanLineList
5554  TPoint *ptsOut; // ptr to output buffers
5555  UInt_t *width;
5556  TPoint firstPoint[NUMPTSTOBUFFER]; // the output buffers
5557  UInt_t firstWidth[NUMPTSTOBUFFER];
5558  EdgeTableEntry *pPrevAET; // previous AET entry
5559  EdgeTable ET; // Edge Table header node
5560  EdgeTableEntry AET; // Active ET header node
5561  EdgeTableEntry *pETEs; // Edge Table Entries buff
5562  ScanLineListBlock SLLBlock; // header for ScanLineList
5563 
5564  pETEs = new EdgeTableEntry[count];
5565 
5566  ptsOut = firstPoint;
5567  width = firstWidth;
5568  CreateETandAET(count, ptsIn, &ET, &AET, pETEs, &SLLBlock);
5569  pSLL = ET.scanlines.next;
5570 
5571  for (y = ET.ymin; y < ET.ymax; y++) {
5572  if (pSLL && y == pSLL->scanline) {
5573  loadAET(&AET, pSLL->edgelist);
5574  pSLL = pSLL->next;
5575  }
5576  pPrevAET = &AET;
5577  pAET = AET.next;
5578 
5579  while (pAET) {
5580  ptsOut->fX = pAET->bres.minor_axis;
5581  ptsOut->fY = y;
5582  ptsOut++;
5583  nPts++;
5584 
5585  *width++ = pAET->next->bres.minor_axis - pAET->bres.minor_axis;
5586 
5587  if (nPts == NUMPTSTOBUFFER) {
5588  FillSpans(nPts, firstPoint, firstWidth, tile);
5589  ptsOut = firstPoint;
5590  width = firstWidth;
5591  nPts = 0;
5592  }
5593  EVALUATEEDGEEVENODD(pAET, pPrevAET, y)
5594  EVALUATEEDGEEVENODD(pAET, pPrevAET, y)
5595  }
5596  InsertionSort(&AET);
5597  }
5598  FillSpans(nPts, firstPoint, firstWidth, tile);
5599 
5600  delete [] pETEs;
5601  FreeStorage(SLLBlock.next);
5602 }
5603 
5604 ////////////////////////////////////////////////////////////////////////////////
5605 /// Create draw context.
5606 
5607 static ASDrawContext *create_draw_context_argb32(ASImage *im, ASDrawTool *brush)
5608 {
5609  ASDrawContext *ctx = new ASDrawContext;
5610 
5611  ctx->canvas_width = im->width;
5612  ctx->canvas_height = im->height;
5613  ctx->canvas = im->alt.argb32;
5614  ctx->scratch_canvas = 0;
5615 
5616  ctx->flags = ASDrawCTX_CanvasIsARGB;
5617  asim_set_custom_brush_colored( ctx, brush);
5618  return ctx;
5619 }
5620 
5621 ////////////////////////////////////////////////////////////////////////////////
5622 /// Destroy asdraw context32.
5623 
5624 static void destroy_asdraw_context32( ASDrawContext *ctx )
5625 {
5626  if (ctx) {
5627  if (ctx->scratch_canvas) free(ctx->scratch_canvas);
5628  delete ctx;
5629  }
5630 }
5631 
5632 static const UInt_t kBrushCacheSize = 20;
5633 static CARD32 gBrushCache[kBrushCacheSize*kBrushCacheSize];
5634 
5635 ////////////////////////////////////////////////////////////////////////////////
5636 /// Draw wide line.
5637 
5639  UInt_t color, UInt_t thick)
5640 {
5641  Int_t sz = thick*thick;
5642  CARD32 *matrix;
5643  Bool_t use_cache = thick < kBrushCacheSize;
5644 
5645  if (use_cache) {
5646  matrix = gBrushCache;
5647  } else {
5648  matrix = new CARD32[sz];
5649  }
5650 
5651  for (int i = 0; i < sz; i++) {
5652  matrix[i] = (CARD32)color;
5653  };
5654 
5655  ASDrawTool brush;
5656  brush.matrix = matrix;
5657  brush.width = thick;
5658  brush.height = thick;
5659  brush.center_y = brush.center_x = thick/2;
5660 
5661  ASDrawContext *ctx = create_draw_context_argb32(fImage, &brush);
5662  asim_move_to(ctx, x1, y1);
5663  asim_line_to(ctx, x2, y2);
5664 
5665  if (!use_cache) {
5666  delete [] matrix;
5667  }
5669 }
5670 
5671 ////////////////////////////////////////////////////////////////////////////////
5672 /// Draw glyph bitmap.
5673 
5674 void TASImage::DrawGlyph(void *bitmap, UInt_t color, Int_t bx, Int_t by)
5675 {
5676  static UInt_t col[5];
5677  Int_t x, y, yy, y0, xx;
5678 
5679  ULong_t r, g, b;
5680  int idx = 0;
5681  FT_Bitmap *source = (FT_Bitmap*)bitmap;
5682  UChar_t d = 0, *s = source->buffer;
5683 
5684  Int_t dots = Int_t(source->width * source->rows);
5685  r = g = b = 0;
5686  Int_t bxx, byy;
5687 
5688  yy = y0 = by > 0 ? by * fImage->width : 0;
5689  for (y = 0; y < (int) source->rows; y++) {
5690  byy = by + y;
5691  if ((byy >= (int)fImage->height) || (byy <0)) continue;
5692 
5693  for (x = 0; x < (int) source->width; x++) {
5694  bxx = bx + x;
5695  if ((bxx >= (int)fImage->width) || (bxx < 0)) continue;
5696 
5697  idx = bxx + yy;
5698  r += ((fImage->alt.argb32[idx] & 0xff0000) >> 16);
5699  g += ((fImage->alt.argb32[idx] & 0x00ff00) >> 8);
5700  b += (fImage->alt.argb32[idx] & 0x0000ff);
5701  }
5702  yy += fImage->width;
5703  }
5704  if (dots != 0) {
5705  r /= dots;
5706  g /= dots;
5707  b /= dots;
5708  }
5709 
5710  col[0] = (r << 16) + (g << 8) + b;
5711  col[4] = color;
5712  Int_t col4r = (col[4] & 0xff0000) >> 16;
5713  Int_t col4g = (col[4] & 0x00ff00) >> 8;
5714  Int_t col4b = (col[4] & 0x0000ff);
5715 
5716  // interpolate between fore and background colors
5717  for (x = 3; x > 0; x--) {
5718  xx = 4-x;
5719  Int_t colxr = (col4r*x + r*xx) >> 2;
5720  Int_t colxg = (col4g*x + g*xx) >> 2;
5721  Int_t colxb = (col4b*x + b*xx) >> 2;
5722  col[x] = (colxr << 16) + (colxg << 8) + colxb;
5723  }
5724 
5725  yy = y0;
5726  for (y = 0; y < (int) source->rows; y++) {
5727  byy = by + y;
5728  if ((byy >= (int)fImage->height) || (byy <0)) continue;
5729 
5730  for (x = 0; x < (int) source->width; x++) {
5731  bxx = bx + x;
5732  //if ((bxx >= (int)fImage->width) || (bxx < 0)) continue;
5733 
5734  d = *s++ & 0xff;
5735  d = ((d + 10) * 5) >> 8;
5736  if (d > 4) d = 4;
5737 
5738  if (d && (x < (int) source->width) && (bxx < (int)fImage->width) && (bxx >= 0)) {
5739  idx = bxx + yy;
5740  fImage->alt.argb32[idx] = (ARGB32)col[d];
5741  }
5742  }
5743  yy += fImage->width;
5744  }
5745 }
5746 
5747 ////////////////////////////////////////////////////////////////////////////////
5748 /// Draw text at the pixel position (x,y).
5749 
5751 {
5752  if (!text) return;
5753  if (!fImage) return;
5754  if (!gPad) return;
5755 
5756  if (!InitVisual()) {
5757  Warning("DrawText", "Visual not initiated");
5758  return;
5759  }
5760 
5761  if (!fImage->alt.argb32) {
5762  BeginPaint();
5763  }
5764 
5765  if (!TTF::IsInitialized()) TTF::Init();
5766 
5767  // set text font
5768  TTF::SetTextFont(text->GetTextFont());
5769 
5770  Int_t wh = gPad->XtoPixel(gPad->GetX2());
5771  Int_t hh = gPad->YtoPixel(gPad->GetY1());
5772 
5773  // set text size
5774  Float_t ttfsize;
5775  if (wh < hh) {
5776  ttfsize = text->GetTextSize()*wh;
5777  } else {
5778  ttfsize = text->GetTextSize()*hh;
5779  }
5780  TTF::SetTextSize(ttfsize);
5781 
5782  // set text angle
5784 
5785  // set text
5786  const wchar_t *wcsTitle = reinterpret_cast<const wchar_t *>(text->GetWcsTitle());
5787  if (wcsTitle != NULL) {
5788  TTF::PrepareString(wcsTitle);
5789  } else {
5790  TTF::PrepareString(text->GetTitle());
5791  }
5793 
5794  // color
5795  TColor *col = gROOT->GetColor(text->GetTextColor());
5796  if (!col) { // no color, make it black
5797  col = gROOT->GetColor(1);
5798  if (!col) return;
5799  }
5800  ARGB32 color = ARGB32_White;
5801  parse_argb_color(col->AsHexString(), &color);
5802 
5803  // Align()
5804  Int_t align = 0;
5805  Int_t txalh = text->GetTextAlign()/10;
5806  Int_t txalv = text->GetTextAlign()%10;
5807 
5808  switch (txalh) {
5809  case 0 :
5810  case 1 :
5811  switch (txalv) { //left
5812  case 1 :
5813  align = 7; //bottom
5814  break;
5815  case 2 :
5816  align = 4; //center
5817  break;
5818  case 3 :
5819  align = 1; //top
5820  break;
5821  }
5822  break;
5823  case 2 :
5824  switch (txalv) { //center
5825  case 1 :
5826  align = 8; //bottom
5827  break;
5828  case 2 :
5829  align = 5; //center
5830  break;
5831  case 3 :
5832  align = 2; //top
5833  break;
5834  }
5835  break;
5836  case 3 :
5837  switch (txalv) { //right
5838  case 1 :
5839  align = 9; //bottom
5840  break;
5841  case 2 :
5842  align = 6; //center
5843  break;
5844  case 3 :
5845  align = 3; //top
5846  break;
5847  }
5848  break;
5849  }
5850 
5851  FT_Vector ftal;
5852 
5853  // vertical alignment
5854  if (align == 1 || align == 2 || align == 3) {
5855  ftal.y = TTF::GetAscent();
5856  } else if (align == 4 || align == 5 || align == 6) {
5857  ftal.y = TTF::GetAscent()/2;
5858  } else {
5859  ftal.y = 0;
5860  }
5861 
5862  // horizontal alignment
5863  if (align == 3 || align == 6 || align == 9) {
5864  ftal.x = TTF::GetWidth();
5865  } else if (align == 2 || align == 5 || align == 8) {
5866  ftal.x = TTF::GetWidth()/2;
5867  } else {
5868  ftal.x = 0;
5869  }
5870 
5871  FT_Vector_Transform(&ftal, TTF::GetRotMatrix());
5872  ftal.x = (ftal.x >> 6);
5873  ftal.y = (ftal.y >> 6);
5874 
5875  TTF::TTGlyph *glyph = TTF::GetGlyphs();
5876 
5877  for (int n = 0; n < TTF::GetNumGlyphs(); n++, glyph++) {
5878  if (FT_Glyph_To_Bitmap(&glyph->fImage, ft_render_mode_normal, 0, 1 )) continue;
5879 
5880  FT_BitmapGlyph bitmap = (FT_BitmapGlyph)glyph->fImage;
5881  FT_Bitmap *source = &bitmap->bitmap;
5882 
5883  Int_t bx = x - ftal.x + bitmap->left;
5884  Int_t by = y + ftal.y - bitmap->top;
5885 
5886  DrawGlyph(source, color, bx, by);
5887  }
5888 }
5889 
5890 ////////////////////////////////////////////////////////////////////////////////
5891 /// Draw text using TrueType fonts.
5892 
5893 void TASImage::DrawTextTTF(Int_t x, Int_t y, const char *text, Int_t size,
5894  UInt_t color, const char *font_name, Float_t angle)
5895 {
5896  if (!TTF::IsInitialized()) TTF::Init();
5897 
5898  TTF::SetTextFont(font_name);
5899  TTF::SetTextSize(size);
5900  TTF::SetRotationMatrix(angle);
5901  TTF::PrepareString(text);
5903 
5904  TTF::TTGlyph *glyph = TTF::GetGlyphs();
5905 
5906  // compute the size and position that will contain the text
5907  // Int_t Xoff = 0; if (TTF::GetBox().xMin < 0) Xoff = -TTF::GetBox().xMin;
5908  Int_t Yoff = 0; if (TTF::GetBox().yMin < 0) Yoff = -TTF::GetBox().yMin;
5909  Int_t h = TTF::GetBox().yMax + Yoff;
5910 
5911  for (int n = 0; n < TTF::GetNumGlyphs(); n++, glyph++) {
5912  if (FT_Glyph_To_Bitmap(&glyph->fImage, ft_render_mode_normal, 0, 1 )) continue;
5913 
5914  FT_BitmapGlyph bitmap = (FT_BitmapGlyph)glyph->fImage;
5915  FT_Bitmap *source = &bitmap->bitmap;
5916 
5917  Int_t bx = x + bitmap->left;
5918  Int_t by = y + h - bitmap->top;
5919  DrawGlyph(source, color, bx, by);
5920  }
5921 }
5922 
5923 ////////////////////////////////////////////////////////////////////////////////
5924 /// Return in-memory buffer compressed according image type.
5925 /// Buffer must be deallocated after usage.
5926 /// This method can be used for sending images over network.
5927 
5928 void TASImage::GetImageBuffer(char **buffer, int *size, EImageFileTypes type)
5929 {
5930  static ASImageExportParams params;
5931  Bool_t ret = kFALSE;
5932  int isize = 0;
5933  char *ibuff = 0;
5934  ASImage *img = fScaledImage ? fScaledImage->fImage : fImage;
5935 
5936  if (!img) return;
5937 
5938  switch (type) {
5939  case TImage::kXpm:
5940  ret = ASImage2xpmRawBuff(img, (CARD8 **)buffer, size, 0);
5941  break;
5942  default:
5943  ret = ASImage2PNGBuff(img, (CARD8 **)buffer, size, &params);
5944  }
5945 
5946  if (!ret) {
5947  *size = isize;
5948  *buffer = ibuff;
5949  }
5950 }
5951 
5952 ////////////////////////////////////////////////////////////////////////////////
5953 /// Create image from compressed buffer.
5954 /// Supported formats:
5955 ///
5956 /// - PNG - by default
5957 /// - XPM - two options exist:
5958 /// 1. xpm as a single string (raw buffer). Such string
5959 /// is returned by GetImageBuffer method.
5960 /// For example:
5961 /// ~~~ {.cpp}
5962 /// char *buf;
5963 /// int sz;
5964 /// im1->GetImageBuffer(&buf, &int, TImage::kXpm); /*raw buffer*/
5965 /// TImage *im2 = TImage::Create();
5966 /// im2->SetImageBuffer(&buf, TImage::kXpm);
5967 /// ~~~
5968 /// 2. xpm as an array of strings (pre-parsed)
5969 /// ~~~ {.cpp}
5970 /// For example:
5971 /// char *xpm[] = {
5972 /// "64 28 58 1",
5973 /// " c #0A030C",
5974 /// ". c #1C171B"
5975 /// ...
5976 /// TImage *im = TImage::Create();
5977 /// im->SetImageBuffer(xpm, TImage::kXpm);
5978 /// ~~~
5979 
5981 {
5982  DestroyImage();
5983 
5984  static ASImageImportParams params;
5985  params.flags = 0;
5986  params.width = 0;
5987  params.height = 0 ;
5988  params.filter = SCL_DO_ALL;
5989  params.gamma = 0;
5990  params.gamma_table = 0;
5991  params.compression = 0;
5992  params.format = ASA_ASImage;
5993  params.search_path = 0;
5994  params.subimage = 0;
5995 
5996  switch (type) {
5997  case TImage::kXpm:
5998  {
5999  char *ptr = buffer[0];
6000  while (isspace((int)*ptr)) ++ptr;
6001  if (atoi(ptr)) { // pre-parsed and preloaded data
6002  fImage = xpm_data2ASImage((const char**)buffer, &params);
6003  } else {
6004  fImage = xpmRawBuff2ASImage((const char*)*buffer, &params);
6005  }
6006  break;
6007  }
6008  default:
6009  fImage = PNGBuff2ASimage((CARD8 *)*buffer, &params);
6010  break;
6011  }
6012 
6013  if (!fImage) {
6014  return kFALSE;
6015  }
6016 
6017  if (fName.IsNull()) {
6018  fName.Form("img_%dx%d.%d", fImage->width, fImage->height, gRandom->Integer(1000));
6019  }
6020  UnZoom();
6021  return kTRUE;
6022 }
6023 
6024 ////////////////////////////////////////////////////////////////////////////////
6025 /// Create image thumbnail.
6026 
6028 {
6029  int size;
6030  const int sz = 64;
6031 
6032  if (!fImage) {
6033  return;
6034  }
6035 
6036  if (!InitVisual()) {
6037  return;
6038  }
6039 
6040  static char *buf = 0;
6041  int w, h;
6042  ASImage *img = 0;
6043 
6044  if (fImage->width > fImage->height) {
6045  w = sz;
6046  h = (fImage->height*sz)/fImage->width;
6047  } else {
6048  h = sz;
6049  w = (fImage->width*sz)/fImage->height;
6050  }
6051 
6052  w = w < 8 ? 8 : w;
6053  h = h < 8 ? 8 : h;
6054 
6055  img = scale_asimage(fgVisual, fImage, w, h, ASA_ASImage,
6057  if (!img) {
6058  return;
6059  }
6060 
6061  // contrasting
6062  ASImage *rendered_im;
6063  ASImageLayer layers[2];
6064  init_image_layers(&(layers[0]), 2);
6065  layers[0].im = img;
6066  layers[0].dst_x = 0;
6067  layers[0].dst_y = 0;
6068  layers[0].clip_width = img->width;
6069  layers[0].clip_height = img->height;
6070  layers[0].bevel = 0;
6071  layers[1].im = img;
6072  layers[1].dst_x = 0;
6073  layers[1].dst_y = 0;
6074  layers[1].clip_width = img->width;
6075  layers[1].clip_height = img->height;
6076  layers[1].merge_scanlines = blend_scanlines_name2func("tint");
6077  rendered_im = merge_layers(fgVisual, &(layers[0]), 2, img->width, img->height,
6078  ASA_ASImage, GetImageCompression(), GetImageQuality());
6079  destroy_asimage(&img);
6080  img = rendered_im;
6081 
6082  // pad image
6083  ASImage *padimg = 0;
6084  int d = 0;
6085 
6086  if (w == sz) {
6087  d = (sz - h) >> 1;
6088  padimg = pad_asimage(fgVisual, img, 0, d, sz, sz, 0x00ffffff,
6089  ASA_ASImage, GetImageCompression(), GetImageQuality());
6090  } else {
6091  d = (sz - w) >> 1;
6092  padimg = pad_asimage(fgVisual, img, d, 0, sz, sz, 0x00ffffff,
6093  ASA_ASImage, GetImageCompression(), GetImageQuality());
6094  }
6095 
6096  if (!padimg) {
6097  destroy_asimage(&img);
6098  return;
6099  }
6100 
6101  void *ptr = &buf;
6102  ASImage2xpmRawBuff(padimg, (CARD8 **)ptr, &size, 0);
6103  fTitle = buf;
6104 
6105  destroy_asimage(&padimg);
6106 }
6107 
6108 ////////////////////////////////////////////////////////////////////////////////
6109 /// Streamer for ROOT I/O.
6110 
6111 void TASImage::Streamer(TBuffer &b)
6112 {
6113  Bool_t image_type = 0;
6114  char *buffer = 0;
6115  int size = 0;
6116  int w, h;
6117  UInt_t R__s, R__c;
6118 
6119  if (b.IsReading()) {
6120  Version_t version = b.ReadVersion(&R__s, &R__c);
6121  if (version == 0) { //dumb prototype for schema evolution
6122  return;
6123  }
6124 
6125  if ( version == 1 ) {
6126  Int_t fileVersion = b.GetVersionOwner();
6127  if (fileVersion > 0 && fileVersion < 50000 ) {
6128  TImage::Streamer(b);
6129  b >> fMaxValue;
6130  b >> fMinValue;
6131  b >> fZoomOffX;
6132  b >> fZoomOffY;
6133  b >> fZoomWidth;
6134  b >> fZoomHeight;
6135  if ( fileVersion < 40200 ) {
6136  Bool_t zoomUpdate;
6137  b >> zoomUpdate;
6138  fZoomUpdate = zoomUpdate;
6139  } else {
6140  b >> fZoomUpdate;
6141  b >> fEditable;
6142  Bool_t paintMode;
6143  b >> paintMode;
6144  fPaintMode = paintMode;
6145  }
6146  b.CheckByteCount(R__s, R__c, TASImage::IsA());
6147  return;
6148  }
6149  }
6150 
6151  TNamed::Streamer(b);
6152  b >> image_type;
6153 
6154  if (image_type != 0) { // read PNG compressed image
6155  b >> size;
6156  buffer = new char[size];
6157  b.ReadFastArray(buffer, size);
6158  SetImageBuffer(&buffer, TImage::kPng);
6159  delete [] buffer;
6160  } else { // read vector with palette
6161  TAttImage::Streamer(b);
6162  b >> w;
6163  b >> h;
6164  size = w*h;
6165  Double_t *vec = new Double_t[size];
6166  b.ReadFastArray(vec, size);
6167  SetImage(vec, w, h, &fPalette);
6168  delete [] vec;
6169  }
6170  b.CheckByteCount(R__s, R__c, TASImage::IsA());
6171  } else {
6172  if (!fImage) {
6173  return;
6174  }
6175  R__c = b.WriteVersion(TASImage::IsA(), kTRUE);
6176 
6177  if (fName.IsNull()) {
6178  fName.Form("img_%dx%d.%d", fImage->width, fImage->height, gRandom->Integer(1000));
6179  }
6180  TNamed::Streamer(b);
6181 
6182  image_type = fImage->alt.vector ? 0 : 1;
6183  b << image_type;
6184 
6185  if (image_type != 0) { // write PNG compressed image
6186  GetImageBuffer(&buffer, &size, TImage::kPng);
6187  b << size;
6188  b.WriteFastArray(buffer, size);
6189  delete buffer;
6190  } else { // write vector with palette
6191  TAttImage::Streamer(b);
6192  b << fImage->width;
6193  b << fImage->height;
6194  b.WriteFastArray(fImage->alt.vector, fImage->width*fImage->height);
6195  }
6196  b.SetByteCount(R__c, kTRUE);
6197  }
6198 }
6199 
6200 ////////////////////////////////////////////////////////////////////////////////
6201 /// Browse image.
6202 
6204 {
6205  if (fImage->alt.vector) {
6206  Draw("n");
6207  } else {
6208  Draw("nxxx");
6209  }
6210  CreateThumbnail();
6211 }
6212 
6213 ////////////////////////////////////////////////////////////////////////////////
6214 /// Title is used to keep 32x32 xpm image's thumbnail.
6215 
6216 const char *TASImage::GetTitle() const
6217 {
6218  if (!gDirectory || !gDirectory->IsWritable()) {
6219  return 0;
6220  }
6221 
6222  TASImage *mutble = (TASImage *)this;
6223 
6224  if (fTitle.IsNull()) {
6225  mutble->SetTitle(fName.Data());
6226  }
6227 
6228  return fTitle.Data();
6229 }
6230 
6231 ////////////////////////////////////////////////////////////////////////////////
6232 /// Set a title for an image.
6233 
6234 void TASImage::SetTitle(const char *title)
6235 {
6236  if (fTitle.IsNull()) {
6237  CreateThumbnail();
6238  }
6239 
6240  if (fTitle.IsNull()) {
6241  return;
6242  }
6243 
6244  int start = fTitle.Index("/*") + 3;
6245  int stop = fTitle.Index("*/") - 1;
6246 
6247  if ((start > 0) && (stop - start > 0)) {
6248  fTitle.Replace(start, stop - start, title);
6249  }
6250 }
6251 
6252 ////////////////////////////////////////////////////////////////////////////////
6253 /// Draw a cubic bezier line.
6254 
6256  Int_t x3, Int_t y3, const char *col, UInt_t thick)
6257 {
6258  Int_t sz = thick*thick;
6259  CARD32 *matrix;
6260  Bool_t use_cache = thick < kBrushCacheSize;
6261 
6262  ARGB32 color = ARGB32_White;
6263  parse_argb_color(col, &color);
6264 
6265  if (use_cache) {
6266  matrix = gBrushCache;
6267  } else {
6268  matrix = new CARD32[sz];
6269  }
6270 
6271  for (int i = 0; i < sz; i++) {
6272  matrix[i] = (CARD32)color;
6273  };
6274 
6275  ASDrawTool brush;
6276  brush.matrix = matrix;
6277  brush.width = thick;
6278  brush.height = thick;
6279  brush.center_y = brush.center_x = thick/2;
6280 
6281  ASDrawContext *ctx = 0;
6282 
6283  ctx = create_draw_context_argb32(fImage, &brush);
6284  asim_cube_bezier(ctx, x1, y1, x2, y2, x3, y3);
6285 
6286  if (!use_cache) {
6287  delete [] matrix;
6288  }
6290 }
6291 
6292 ////////////////////////////////////////////////////////////////////////////////
6293 /// Draw a straight ellipse.
6294 /// If thick < 0 - draw filled ellipse.
6295 
6297  const char *col, Int_t thick)
6298 {
6299  thick = !thick ? 1 : thick;
6300  Int_t sz = thick*thick;
6301  CARD32 *matrix;
6302  Bool_t use_cache = (thick > 0) && ((UInt_t)thick < kBrushCacheSize);
6303 
6304  ARGB32 color = ARGB32_White;
6305  parse_argb_color(col, &color);
6306 
6307  if (use_cache) {
6308  matrix = gBrushCache;
6309  } else {
6310  matrix = new CARD32[sz];
6311  }
6312 
6313  for (int i = 0; i < sz; i++) {
6314  matrix[i] = (CARD32)color;
6315  };
6316 
6317  ASDrawTool brush;
6318  brush.matrix = matrix;
6319  brush.width = thick > 0 ? thick : 1;
6320  brush.height = thick > 0 ? thick : 1;
6321  brush.center_y = brush.center_x = thick > 0 ? thick/2 : 0;
6322 
6323  ASDrawContext *ctx = create_draw_context_argb32(fImage, &brush);
6324  asim_straight_ellips(ctx, x, y, rx, ry, thick < 0);
6325 
6326  if (!use_cache) {
6327  delete [] matrix;
6328  }
6330 }
6331 
6332 ////////////////////////////////////////////////////////////////////////////////
6333 /// Draw a circle.
6334 /// If thick < 0 - draw filled circle
6335 
6336 void TASImage::DrawCircle(Int_t x, Int_t y, Int_t r, const char *col, Int_t thick)
6337 {
6338  thick = !thick ? 1 : thick;
6339  Int_t sz = thick*thick;
6340  CARD32 *matrix;
6341  Bool_t use_cache = (thick > 0) && ((UInt_t)thick < kBrushCacheSize);
6342 
6343  ARGB32 color = ARGB32_White;
6344  parse_argb_color(col, &color);
6345 
6346 ///matrix = new CARD32[sz];
6347  if (use_cache) {
6348  matrix = gBrushCache;
6349  } else {
6350  matrix = new CARD32[sz];
6351  }
6352 
6353  for (int i = 0; i < sz; i++) {
6354  matrix[i] = (CARD32)color;
6355  }
6356 
6357  ASDrawTool brush;
6358  brush.matrix = matrix;
6359  brush.height = brush.width = thick > 0 ? thick : 1;
6360  brush.center_y = brush.center_x = thick > 0 ? thick/2 : 0;
6361 
6362  ASDrawContext *ctx = create_draw_context_argb32(fImage, &brush);
6363  asim_circle(ctx, x, y, r, thick < 0);
6364 
6365 ///free (matrix);
6366  if (!use_cache) {
6367  delete [] matrix;
6368  }
6370 }
6371 
6372 ////////////////////////////////////////////////////////////////////////////////
6373 /// Draw an ellipse.
6374 /// If thick < 0 - draw filled ellips
6375 
6377  const char *col, Int_t thick)
6378 {
6379  thick = !thick ? 1 : thick;
6380  Int_t sz = thick*thick;
6381  CARD32 *matrix;
6382  Bool_t use_cache = (thick > 0) && ((UInt_t)thick < kBrushCacheSize);
6383 
6384  ARGB32 color = ARGB32_White;
6385  parse_argb_color(col, &color);
6386 
6387  if (use_cache) {
6388  matrix = gBrushCache;
6389  } else {
6390  matrix = new CARD32[sz];
6391  }
6392 
6393  for (int i = 0; i < sz; i++) {
6394  matrix[i] = (CARD32)color;
6395  };
6396 
6397  ASDrawTool brush;
6398  brush.matrix = matrix;
6399  brush.width = thick > 0 ? thick : 1;
6400  brush.height = thick > 0 ? thick : 1;
6401  brush.center_y = brush.center_x = thick > 0 ? thick/2 : 0;
6402 
6403  ASDrawContext *ctx = create_draw_context_argb32(fImage, &brush);
6404  asim_ellips(ctx, x, y, rx, ry, angle, thick < 0);
6405 
6406  if (!use_cache) {
6407  delete [] matrix;
6408  }
6410 }
6411 
6412 ////////////////////////////////////////////////////////////////////////////////
6413 /// Draw an ellipse.
6414 /// If thick < 0 - draw filled ellipse.
6415 
6417  const char *col, Int_t thick)
6418 {
6419  thick = !thick ? 1 : thick;
6420  Int_t sz = thick*thick;
6421  CARD32 *matrix;
6422  Bool_t use_cache = (thick > 0) && ((UInt_t)thick < kBrushCacheSize);
6423 
6424  ARGB32 color = ARGB32_White;
6425  parse_argb_color(col, &color);
6426 
6427  if (use_cache) {
6428  matrix = gBrushCache;
6429  } else {
6430  matrix = new CARD32[sz];
6431  }
6432 
6433  for (int i = 0; i < sz; i++) {
6434  matrix[i] = (CARD32)color;
6435  };
6436 
6437  ASDrawTool brush;
6438  brush.matrix = matrix;
6439  brush.width = thick > 0 ? thick : 1;
6440  brush.height = thick > 0 ? thick : 1;
6441  brush.center_y = brush.center_x = thick > 0 ? thick/2 : 0;
6442 
6443  ASDrawContext *ctx = create_draw_context_argb32(fImage, &brush);
6444  asim_ellips2(ctx, x, y, rx, ry, angle, thick < 0);
6445 
6446  if (!use_cache) {
6447  delete [] matrix;
6448  }
6450 }
6451 
6452 ////////////////////////////////////////////////////////////////////////////////
6453 /// Flood fill.
6454 
6455 void TASImage::FloodFill(Int_t /*x*/, Int_t /*y*/, const char * /*col*/,
6456  const char * /*minc*/, const char * /*maxc*/)
6457 {
6458 }
6459 
6460 ////////////////////////////////////////////////////////////////////////////////
6461 /// Convert RGB image to Gray image and vice versa.
6462 
6464 {
6465  if (fIsGray == on) {
6466  return;
6467  }
6468 
6469  if (!IsValid()) {
6470  Warning("Gray", "Image not initiated");
6471  return;
6472  }
6473 
6474  if (!InitVisual()) {
6475  Warning("Gray", "Visual not initiated");
6476  return;
6477  }
6478 
6479  if (!fGrayImage && !on) {
6480  return;
6481  }
6482  ASImage *sav = 0;
6483  delete fScaledImage;
6484  fScaledImage = 0;
6485 
6486  if (fGrayImage) {
6487  sav = fImage;
6488  fImage = fGrayImage;
6489  fGrayImage = sav;
6490  fIsGray = on;
6491  return;
6492  }
6493 
6494  if (!on) return;
6495 
6496  UInt_t l, r, g, b, idx;
6497  int y = 0;
6498  UInt_t i, j;
6499 
6500  if (fImage->alt.argb32) {
6501  fGrayImage = tile_asimage(fgVisual, fImage, 0, 0, fImage->width, fImage->height,
6502  0, ASA_ARGB32, 0, ASIMAGE_QUALITY_DEFAULT);
6503 
6504  for (i = 0; i < fImage->height; i++) {
6505  for (j = 0; j < fImage->width; j++) {
6506  idx = y + j;
6507 
6508  r = ((fImage->alt.argb32[idx] & 0xff0000) >> 16);
6509  g = ((fImage->alt.argb32[idx] & 0x00ff00) >> 8);
6510  b = (fImage->alt.argb32[idx] & 0x0000ff);
6511  l = (57*r + 181*g + 18*b)/256;
6512  fGrayImage->alt.argb32[idx] = (l << 16) + (l << 8) + l;
6513  }
6514  y += fImage->width;
6515  }
6516  } else {
6517  fGrayImage = create_asimage(fImage->width, fImage->height, 0);
6518 
6519  ASImageDecoder *imdec = start_image_decoding(fgVisual, fImage, SCL_DO_ALL,
6520  0, 0, fImage->width, fImage->height, 0);
6521 
6522  if (!imdec) {
6523  return;
6524  }
6525 #ifdef HAVE_MMX
6526  mmx_init();
6527 #endif
6528  ASImageOutput *imout = start_image_output(fgVisual, fGrayImage, ASA_ASImage,
6530  if (!imout) {
6531  Warning("ToGray", "Failed to start image output");
6532  delete fScaledImage;
6533  fScaledImage = 0;
6534  delete [] imdec;
6535  return;
6536  }
6537 
6538  CARD32 *aa = imdec->buffer.alpha;
6539  CARD32 *rr = imdec->buffer.red;
6540  CARD32 *gg = imdec->buffer.green;
6541  CARD32 *bb = imdec->buffer.blue;
6542 
6543  ASScanline result;
6544  prepare_scanline(fImage->width, 0, &result, fgVisual->BGR_mode);
6545 
6546  for (i = 0; i < fImage->height; i++) {
6547  imdec->decode_image_scanline(imdec);
6548  result.flags = imdec->buffer.flags;
6549  result.back_color = imdec->buffer.back_color;
6550 
6551  for (j = 0; j < fImage->width; j++) {
6552  l = (57*rr[j] + 181*gg[j]+ 18*bb[j])/256;
6553  result.alpha[j] = aa[j];
6554  result.red[j] = l;
6555  result.green[j] = l;
6556  result.blue[j] = l;
6557  }
6558  imout->output_image_scanline(imout, &result, 1);
6559  }
6560 
6561  stop_image_decoding(&imdec);
6562  stop_image_output(&imout);
6563 #ifdef HAVE_MMX
6564  mmx_off();
6565 #endif
6566  }
6567 
6568  sav = fImage;
6569  fImage = fGrayImage;
6570  fGrayImage = sav;
6571  fIsGray = kTRUE;
6572 }
6573 
6574 ////////////////////////////////////////////////////////////////////////////////
6575 /// Create an image (screenshot) from specified window.
6576 
6578 {
6579  Int_t xy;
6580 
6581  x = x < 0 ? 0 : x;
6582  y = y < 0 ? 0 : y;
6583 
6584  // synchronization
6585  gVirtualX->Update(1);
6586  if (!gThreadXAR) {
6588  gSystem->Sleep(10);
6590  }
6591 
6592  if (!w || !h) {
6593  gVirtualX->GetWindowSize(wid, xy, xy, w, h);
6594  }
6595 
6596  if ((x >= (Int_t)w) || (y >= (Int_t)h)) {
6597  return;
6598  }
6599 
6600  if (!InitVisual()) {
6601  Warning("FromWindow", "Visual not initiated");
6602  return;
6603  }
6604 
6605  DestroyImage();
6606  delete fScaledImage;
6607  fScaledImage = 0;
6608 
6609  static int x11 = -1;
6610  if (x11 < 0) x11 = gVirtualX->InheritsFrom("TGX11");
6611 
6612  if (x11) { //use built-in optimized version
6613  fImage = pixmap2asimage(fgVisual, wid, x, y, w, h, kAllPlanes, 0, 0);
6614  } else {
6615  unsigned char *bits = gVirtualX->GetColorBits(wid, 0, 0, w, h);
6616 
6617  if (!bits) { // error
6618  return;
6619  }
6620  fImage = bitmap2asimage(bits, w, h, 0, 0);
6621  delete [] bits;
6622  }
6623 }
6624 
6625 ////////////////////////////////////////////////////////////////////////////////
6626 /// Creates an image (screenshot) from a RGBA buffer.
6627 
6629 {
6630  DestroyImage();
6631  delete fScaledImage;
6632  fScaledImage = 0;
6633 
6634  UChar_t* xx = new UChar_t[4*w];
6635  for (UInt_t i = 0; i < h/2; ++i) {
6636  memcpy(xx, buf + 4*w*i, 4*w);
6637  memcpy(buf + 4*w*i, buf + 4*w*(h-i-1), 4*w);
6638  memcpy(buf + 4*w*(h-i-1), xx, 4*w);
6639  }
6640  delete [] xx;
6641 
6642  fImage = bitmap2asimage(buf, w, h, 0, 0);
6643 }
6644 
6645 ////////////////////////////////////////////////////////////////////////////////
6646 /// Switch on/off the image palette.
6647 /// That also invokes calling vectorization of image.
6648 
6650 {
6651  if (!fImage) {
6652  return;
6653  }
6654 
6655  if (!fImage->alt.vector && on) {
6656  Vectorize();
6657  }
6658  fPaletteEnabled = on;
6659 
6660  if (on) {
6661  Double_t left = gPad->GetLeftMargin();
6662  Double_t right = gPad->GetRightMargin();
6663  Double_t top = gPad->GetTopMargin();
6664  Double_t bottom = gPad->GetBottomMargin();
6665 
6666  gPad->Range(-left / (1.0 - left - right),
6667  -bottom / (1.0 - top - bottom),
6668  1 + right / (1.0 - left - right),
6669  1 + top / ( 1.0 - top - bottom));
6670  gPad->RangeAxis(0, 0, 1, 1);
6671  }
6672 
6673 }
6674 
6675 ////////////////////////////////////////////////////////////////////////////////
6676 /// Save a primitive as a C++ statement(s) on output stream "out".
6677 
6678 void TASImage::SavePrimitive(std::ostream &out, Option_t * /*= ""*/)
6679 {
6680  char *buf = 0;
6681  int sz;
6682 
6683  UInt_t w = GetWidth();
6684  UInt_t h = GetHeight();
6685 
6686  if (w > 500) { // workaround CINT limitations
6687  w = 500;
6688  Double_t scale = 500./GetWidth();
6689  h = TMath::Nint(GetHeight()*scale);
6690  Scale(w, h);
6691  }
6692 
6693  GetImageBuffer(&buf, &sz, TImage::kXpm);
6694 
6695  TString name = GetName();
6696  name.ReplaceAll(".", "_");
6697  TString str = buf;
6698  static int ii = 0;
6699  ii++;
6700 
6701  str.ReplaceAll("static", "const");
6702  TString xpm = "xpm_";
6703  xpm += name;
6704  xpm += ii;
6705  str.ReplaceAll("asxpm", xpm.Data());
6706  out << std::endl << str << std::endl << std::endl;
6707 
6708  out << " TImage *";
6709  out << xpm << "_img = TImage::Create();" << std::endl;
6710  out << " " << xpm << "_img->SetImageBuffer( (char **)" << xpm << ", TImage::kXpm);" << std::endl;
6711  out << " " << xpm << "_img->Draw();" << std::endl;
6712 }
6713 
6714 ////////////////////////////////////////////////////////////////////////////////
6715 /// Set an image printing resolution in Dots Per Inch units.
6716 ///
6717 /// \param[in] name - the name of jpeg file.
6718 /// \param[in] set - dpi resolution.
6719 ///
6720 /// Returns kFALSE in case of error.
6721 
6723 {
6724  static char buf[32];
6725  FILE *fp = fopen(name, "rb+");
6726 
6727  if (!fp) {
6728  printf("file %s : failed to open\n", name);
6729  return kFALSE;
6730  }
6731 
6732  if (!fread(buf, 1, 20, fp)) {
6733  fclose(fp);
6734  return kFALSE;
6735  }
6736 
6737  char dpi1 = (set & 0xffff) >> 8;
6738  char dpi2 = set & 0xff;
6739 
6740  int i = 0;
6741 
6742  int dpi = 0; // start of dpi data
6743  for (i = 0; i < 20; i++) {
6744  if ((buf[i] == 0x4a) && (buf[i+1] == 0x46) && (buf[i+2] == 0x49) &&
6745  (buf[i+3] == 0x46) && (buf[i+4] == 0x00) ) {
6746  dpi = i + 7;
6747  break;
6748  }
6749  }
6750 
6751  if (i == 20 || dpi+4 >= 20) { // jpeg maker was not found
6752  fclose(fp);
6753  printf("file %s : wrong JPEG format\n", name);
6754  return kFALSE;
6755  }
6756 
6757  buf[dpi] = 1; // format specified in dots per inch
6758 
6759  // set x density in dpi units
6760  buf[dpi + 1] = dpi1;
6761  buf[dpi + 2] = dpi2;
6762 
6763  // set y density in dpi units
6764  buf[dpi + 3] = dpi1;
6765  buf[dpi + 4] = dpi2;
6766 
6767  rewind(fp);
6768  fwrite(buf, 1, 20, fp);
6769  fclose(fp);
6770 
6771  return kTRUE;
6772 }
Int_t fClipXOrigin
Definition: GuiTypes.h:246
const int nx
Definition: kalman.C:16
TString fTitle
Definition: TNamed.h:37
void SetTitle(const char *title="")
Set a title for an image.
Definition: TASImage.cxx:6234
Double_t * Vectorize(UInt_t max_colors=256, UInt_t dither=4, Int_t opaque_threshold=1)
Reduce color-depth of an image and fills vector of "scientific data" [0...1].
Definition: TASImage.cxx:2830
virtual const char * BaseName(const char *pathname)
Base name of a file name. Base name of /user/root is root.
Definition: TSystem.cxx:928
Definition: GuiTypes.h:76
virtual const char * GetTitle() const
Returns title of object.
Definition: TNamed.h:52
#define EVALUATEEDGEEVENODD(pAET, pPrevAET, y)
Definition: TASPolyUtils.c:287
static void Init()
Initialise the TrueType fonts interface.
Definition: TTF.cxx:67
Short_t fX1
Definition: GuiTypes.h:353
Double_t * fPoints
Definition: TAttImage.h:87
UInt_t GetScaledHeight() const
Return height of the displayed image not of the original image.
Definition: TASImage.cxx:2177
static void FreeStorage(ScanLineListBlock *pSLLBlock)
Definition: TASPolyUtils.c:524
void GetZoomPosition(UInt_t &x, UInt_t &y, UInt_t &w, UInt_t &h) const
Return the zoom parameters.
Definition: TASImage.cxx:2186
An array of TObjects.
Definition: TObjArray.h:39
virtual Bool_t ProcessEvents()
Process pending events (GUI, timers, sockets).
Definition: TSystem.cxx:420
virtual Float_t GetTextAngle() const
Definition: TAttText.h:47
EImageFileTypes
Definition: TImage.h:52
virtual void CellArrayFill(Int_t r, Int_t g, Int_t b)=0
static Vc_ALWAYS_INLINE int_v min(const int_v &x, const int_v &y)
Definition: vector.h:433
static ASFontManager * gFontManager
Definition: TASImage.cxx:120
static void init_icon_paths()
Set icons paths.
Definition: TASImage.cxx:360
virtual Font_t GetTextFont() const
Definition: TAttText.h:49
void DrawDashZTLine(UInt_t x1, UInt_t y1, UInt_t x2, UInt_t y2, UInt_t nDash, const char *pDash, UInt_t col, UInt_t thick)
Draw a dashed line with thick pixel width.
Definition: TASImage.cxx:4438
Bool_t IsReading() const
Definition: TBuffer.h:81
void PutPixel(Int_t x, Int_t y, const char *col="#000000")
Draw a point at the specified position.
Definition: TASImage.cxx:4665
virtual Bool_t InheritsFrom(const char *classname) const
Returns kTRUE if object inherits from class "classname".
Definition: TObject.cxx:487
static ARGB32 GetAverage(ARGB32 foreground, ARGB32 background)
Get average.
Definition: TASImage.cxx:3217
virtual void Paint(Option_t *option="")=0
This method must be overridden if a class wants to paint itself.
short Version_t
Definition: RtypesCore.h:61
static Bool_t InitVisual()
Static function to initialize the ASVisual.
Definition: TASImage.cxx:2197
Ssiz_t Length() const
Definition: TString.h:390
UInt_t GetWidth() const
Return width of original image not of the displayed image.
Definition: TASImage.cxx:2150
void SetPaletteEnabled(Bool_t on=kTRUE)
Switch on/off the image palette.
Definition: TASImage.cxx:6649
float Float_t
Definition: RtypesCore.h:53
virtual void SetBorderMode(Short_t bordermode)
Definition: TWbox.h:62
Bool_t IsEditable() const
Definition: TASImage.h:96
const char Option_t
Definition: RtypesCore.h:62
void DrawBox(Int_t x1, Int_t y1, Int_t x2, Int_t y2, const char *col="#000000", UInt_t thick=1, Int_t mode=0)
Draw a box.
Definition: TASImage.cxx:4094
Image class.
Definition: TASImage.h:33
float ymin
Definition: THbookFile.cxx:93
Create a Box.
Definition: TBox.h:44
const char * GetTitle() const
Title is used to keep 32x32 xpm image's thumbnail.
Definition: TASImage.cxx:6216
static const ASVisual * GetVisual()
Return visual.
Definition: TASImage.cxx:5140
TString & ReplaceAll(const TString &s1, const TString &s2)
Definition: TString.h:635
EImageFileTypes GetFileType(const char *ext)
Return file type depending on specified extension.
Definition: TASImage.cxx:817
R__EXTERN TStyle * gStyle
Definition: TStyle.h:423
static Bool_t IsInitialized()
Definition: TTF.cxx:618
FT_Glyph fImage
Definition: TTF.h:79
UInt_t GetHeight() const
Return height of original image not of the displayed image.
Definition: TASImage.cxx:2159
unsigned short UShort_t
Definition: RtypesCore.h:36
#define gDirectory
Definition: TDirectory.h:218
virtual void SetName(const char *name)
Change (i.e.
Definition: TNamed.cxx:128
#define BIT(n)
Definition: Rtypes.h:120
TH1 * h
Definition: legend2.C:5
void Draw(Option_t *option="")
Draw image.
Definition: TASImage.cxx:1169
Double_t background(Double_t *x, Double_t *par)
static unsigned long kAllPlanes
Definition: TASImage.cxx:121
void DrawRectangle(UInt_t x, UInt_t y, UInt_t w, UInt_t h, const char *col="#000000", UInt_t thick=1)
Draw a rectangle.
Definition: TASImage.cxx:4054
void CopyArea(TImage *dst, Int_t xsrc, Int_t ysrc, UInt_t w, UInt_t h, Int_t xdst=0, Int_t ydst=0, Int_t gfunc=3, EColorChan chan=kAllChan)
Copy source region to the destination image.
Definition: TASImage.cxx:4986
virtual const char * HomeDirectory(const char *userName=0)
Return the user's home directory.
Definition: TSystem.cxx:881
SCoord_t fX
Definition: TPoint.h:37
Buffer base class used for serializing objects.
Definition: TBuffer.h:40
virtual Float_t GetTextSize() const
Definition: TAttText.h:50
virtual UInt_t * GetArgbArray()
Definition: TImage.h:253
static const char * filename()
virtual Int_t CheckByteCount(UInt_t startpos, UInt_t bcnt, const TClass *clss)=0
#define gROOT
Definition: TROOT.h:340
#define H(x, y, z)
Bool_t fEditable
kZoom - new zooming required, kZoomOps - other ops in action, kNoZoom - no zooming or ops ...
Definition: TASImage.h:67
UInt_t * GetArgbArray()
Return a pointer to internal array[width x height] of ARGB32 values This array is directly accessible...
Definition: TASImage.cxx:3587
Handle_t GContext_t
Definition: GuiTypes.h:39
virtual UInt_t GetWidth() const
Definition: TImage.h:244
Int_t LoadPlugin()
Load the plugin library for this handler.
SCoord_t fY
Definition: TPoint.h:38
Basic string class.
Definition: TString.h:137
TString as(SEXP s)
Definition: RExports.h:85
#define CLRBIT(n, i)
Definition: Rtypes.h:122
Short_t Min(Short_t a, Short_t b)
Definition: TMathBase.h:170
void ToLower()
Change string to lower-case.
Definition: TString.cxx:1088
void StartPaletteEditor()
Start palette editor.
Definition: TASImage.cxx:2251
int Int_t
Definition: RtypesCore.h:41
bool Bool_t
Definition: RtypesCore.h:59
Short_t fY1
Definition: GuiTypes.h:353
TObject * Clone(const char *newname) const
Clone image.
Definition: TASImage.cxx:2784
TArc * a
Definition: textangle.C:12
void ReadImage(const char *file, EImageFileTypes type=TImage::kUnknown)
Read specified image file.
Definition: TASImage.cxx:477
const Bool_t kFALSE
Definition: Rtypes.h:92
virtual void Draw(Option_t *option="")
Default Draw method for all objects.
Definition: TObject.cxx:254
virtual void SetX1(Double_t x1)
Definition: TBox.h:83
virtual void SetFillStyle(Style_t fstyle)
Definition: TAttFill.h:52
void Zoom(UInt_t offX, UInt_t offY, UInt_t width, UInt_t height)
The area of an image displayed in a pad is defined by this function.
Definition: TASImage.cxx:2023
virtual void CellArrayEnd()=0
void FromPad(TVirtualPad *pad, Int_t x=0, Int_t y=0, UInt_t w=0, UInt_t h=0)
Create an image from the given pad, afterwards this image can be saved in any of the supported image ...
Definition: TASImage.cxx:1070
Handle_t Drawable_t
Definition: GuiTypes.h:32
Int_t fClipYOrigin
Definition: GuiTypes.h:247
An abstract interface to image processing library.
Definition: TImage.h:45
virtual void Merge(const TImage *, const char *="alphablend", Int_t=0, Int_t=0)
Definition: TImage.h:188
void Browse(TBrowser *)
Browse image.
Definition: TASImage.cxx:6203
void CreateThumbnail()
Create image thumbnail.
Definition: TASImage.cxx:6027
Pixmap_t fClipMask
Definition: GuiTypes.h:248
virtual UInt_t WriteVersion(const TClass *cl, Bool_t useBcnt=kFALSE)=0
void DrawLine(UInt_t x1, UInt_t y1, UInt_t x2, UInt_t y2, const char *col="#000000", UInt_t thick=1)
Draw a line.
Definition: TASImage.cxx:3885
void DrawCubeBezier(Int_t x1, Int_t y1, Int_t x2, Int_t y2, Int_t x3, Int_t y3, const char *col="#000000", UInt_t thick=1)
Draw a cubic bezier line.
Definition: TASImage.cxx:6255
virtual void SetX2(Double_t x2)
Definition: TBox.h:84
Long_t ExecPlugin(int nargs, const T &...params)
XID Colormap
Definition: TGX11.h:40
Bool_t BeginsWith(const char *s, ECaseCompare cmp=kExact) const
Definition: TString.h:558
Short_t Abs(Short_t d)
Definition: TMathBase.h:110
Bool_t fPaletteEnabled
GUI to edit the color palette.
Definition: TAttImage.h:126
UInt_t * GetScanline(UInt_t y)
Return a pointer to scan-line.
Definition: TASImage.cxx:3661
void DrawTextTTF(Int_t x, Int_t y, const char *text, Int_t size, UInt_t color, const char *font_name, Float_t angle)
Draw text using TrueType fonts.
Definition: TASImage.cxx:5893
void SetBit(UInt_t f, Bool_t set)
Set or unset the user status bits as specified in f.
Definition: TObject.cxx:732
static CARD32 gBrushCache[kBrushCacheSize *kBrushCacheSize]
Definition: TASImage.cxx:5633
static ARGB32 GetShadow(ARGB32 background)
Calculate shadow color.
Definition: TASImage.cxx:3208
UShort_t * fColorRed
Definition: TAttImage.h:88
Double_t * GetVecArray()
Return a pointer to internal array[width x height] of double values [0,1].
Definition: TASImage.cxx:2480
TString & Replace(Ssiz_t pos, Ssiz_t n, const char *s)
Definition: TString.h:625
Bool_t SetImageBuffer(char **buffer, EImageFileTypes type=TImage::kPng)
Create image from compressed buffer.
Definition: TASImage.cxx:5980
static THashTable * fgPlugList
kTRUE if image is gray
Definition: TASImage.h:71
void PolyPoint(UInt_t npt, TPoint *ppt, const char *col="#000000", TImage::ECoordMode mode=kCoordModeOrigin)
Draw a poly point.
Definition: TASImage.cxx:4700
Short_t fX2
Definition: GuiTypes.h:353
const char * Data() const
Definition: TString.h:349
virtual TObject * FindObject(const char *name) const
Find an object in this collection using its name.
Definition: TObjArray.cxx:395
EImageQuality GetImageQuality() const
Definition: TAttImage.h:136
Int_t DistancetoPrimitive(Int_t px, Int_t py)
Is the mouse in the image ?
Definition: TASImage.cxx:1680
void Paint(Option_t *option="")
Paint image.
Definition: TASImage.cxx:1363
const Mask_t kGCClipMask
Definition: GuiTypes.h:306
static const double x2[5]
virtual Short_t GetTextAlign() const
Definition: TAttText.h:46
Double_t dot(const TVector2 &v1, const TVector2 &v2)
Definition: CsgOps.cxx:333
THashTable implements a hash table to store TObject's.
Definition: THashTable.h:39
Double_t x[n]
Definition: legend1.C:17
static void LayoutGlyphs()
Compute the glyphs positions, fgAscent and fgWidth (needed for alignment).
Definition: TTF.cxx:183
EColorChan
Definition: TImage.h:106
Vc_ALWAYS_INLINE void free(T *p)
Frees memory that was allocated with Vc::malloc.
Definition: memory.h:94
void Class()
Definition: Class.C:29
R__EXTERN Int_t(* gThreadXAR)(const char *xact, Int_t nb, void **ar, Int_t *iret)
Definition: TVirtualPad.h:290
virtual void Sleep(UInt_t milliSec)
Sleep milliSec milli seconds.
Definition: TSystem.cxx:441
virtual const char * GetName() const =0
Returns name of object.
void BeginPaint(Bool_t fast=kTRUE)
BeginPaint initializes internal array[width x height] of ARGB32 pixel values.
Definition: TASImage.cxx:3528
static void SetTextFont(Font_t fontnumber)
Set specified font.
Definition: TTF.cxx:496
virtual Int_t GetVersionOwner() const =0
void EndPaint()
EndPaint does internal RLE compression of image data.
Definition: TASImage.cxx:3560
Short_t fY2
Definition: GuiTypes.h:353
#define BRESINCRPGON(d, minval, m, m1, incr1, incr2)
Definition: TASPolyUtils.c:115
const int ny
Definition: kalman.C:17
static void PrepareString(const char *string)
Put the characters in "string" in the "glyphs" array.
Definition: TTF.cxx:249
virtual Color_t GetTextColor() const
Definition: TAttText.h:48
void DrawCellArray(Int_t x1, Int_t y1, Int_t x2, Int_t y2, Int_t nx, Int_t ny, UInt_t *ic)
Draw a cell array.
Definition: TASImage.cxx:5100
void MapFileTypes(EImageFileTypes &type, UInt_t &astype, Bool_t toas=kTRUE)
Map file type to/from AfterImage types.
Definition: TASImage.cxx:861
TArrayD * GetArray(UInt_t w=0, UInt_t h=0, TImagePalette *pal=gWebImagePalette)
In case of vectorized image return an associated array of doubles otherwise this method creates and r...
Definition: TASImage.cxx:2502
UInt_t fZoomOffY
X - offset for zooming in image pixels.
Definition: TASImage.h:63
void Gray(Bool_t on=kTRUE)
Convert RGB image to Gray image and vice versa.
Definition: TASImage.cxx:6463
virtual const char * Getenv(const char *env)
Get environment variable.
Definition: TSystem.cxx:1627
virtual UInt_t Integer(UInt_t imax)
Returns a random integer on [ 0, imax-1 ].
Definition: TRandom.cxx:320
static UInt_t AlphaBlend(UInt_t bot, UInt_t top)
Return alpha-blended value computed from bottom and top pixel values.
Definition: TASImage.cxx:5129
if(pyself &&pyself!=Py_None)
static void loadAET(EdgeTableEntry *AET, EdgeTableEntry *ETEs)
Definition: TASPolyUtils.c:455
void WriteImage(const char *file, EImageFileTypes type=TImage::kUnknown)
Write image to specified file.
Definition: TASImage.cxx:646
Base class for several text objects.
Definition: TText.h:42
UInt_t GetImageCompression() const
Definition: TAttImage.h:135
virtual void Draw(Option_t *option="")
Draw this frame with its current attributes.
Definition: TFrame.cxx:69
Int_t Atoi() const
Return integer value of string.
Definition: TString.cxx:1964
static TTGlyph * GetGlyphs()
Definition: TTF.cxx:660
static ASDrawContext * create_draw_context_argb32(ASImage *im, ASDrawTool *brush)
Create draw context.
Definition: TASImage.cxx:5607
void DrawFillArea(UInt_t npt, TPoint *ppt, const char *col="#000000", const char *stipple=0, UInt_t w=16, UInt_t h=16)
Fill a polygon (any type convex, non-convex).
Definition: TASImage.cxx:5404
static int GetPolyYBounds(TPoint *pts, int n, int *by, int *ty)
Get poly bounds along Y.
Definition: TASImage.cxx:5148
Double_t ATan2(Double_t, Double_t)
Definition: TMath.h:454
virtual void Error(const char *method, const char *msgfmt,...) const
Issue error message.
Definition: TObject.cxx:918
const char *msg switch(type)
TVirtualPad is an abstract base class for the Pad and Canvas classes.
Definition: TVirtualPad.h:59
static ULong_t RGB2Pixel(Int_t r, Int_t g, Int_t b)
Convert r,g,b to graphics system dependent pixel value.
Definition: TColor.cxx:1900
void Scale(UInt_t width, UInt_t height)
Scale the original image.
Definition: TASImage.cxx:1913
SCoord_t GetY() const
Definition: TPoint.h:50
void DrawGlyph(void *bitmap, UInt_t color, Int_t x, Int_t y)
Draw glyph bitmap.
Definition: TASImage.cxx:5674
virtual Int_t GetPixmapID() const =0
char * out
Definition: TBase64.cxx:29
void Pad(const char *color="#00FFFFFF", UInt_t left=0, UInt_t right=0, UInt_t top=0, UInt_t bottom=0)
Enlarge image, padding it with specified color on each side in accordance with requested geometry...
Definition: TASImage.cxx:3361
Int_t fPaintMode
kTRUE image can be resized, moved by resizing/moving gPad
Definition: TASImage.h:68
Definition: TPoint.h:33
virtual UInt_t GetHeight() const
Definition: TImage.h:245
void SavePrimitive(std::ostream &out, Option_t *option="")
Save a primitive as a C++ statement(s) on output stream "out".
Definition: TASImage.cxx:6678
TArrayL * GetPixels(Int_t x=0, Int_t y=0, UInt_t w=0, UInt_t h=0)
Return 2D array of machine dependent pixel values.
Definition: TASImage.cxx:2408
void DrawDashZLine(UInt_t x1, UInt_t y1, UInt_t x2, UInt_t y2, UInt_t nDash, const char *pDash, UInt_t col)
Draw a dashed line with one pixel width.
Definition: TASImage.cxx:4254
Element * GetMatrixArray()
Definition: TVectorT.h:84
virtual const TImagePalette & GetPalette() const
Definition: TAttImage.h:137
void DrawDashHLine(UInt_t y, UInt_t x1, UInt_t x2, UInt_t nDash, const char *pDash, UInt_t col, UInt_t thick)
Draw a dashed horizontal line.
Definition: TASImage.cxx:4143
virtual void SetLineColor(Color_t lcolor)
Definition: TAttLine.h:54
virtual Int_t UtoPixel(Double_t u) const =0
Bool_t SetJpegDpi(const char *name, UInt_t dpi=72)
Set an image printing resolution in Dots Per Inch units.
Definition: TASImage.cxx:6722
void FillSpans(UInt_t npt, TPoint *ppt, UInt_t *widths, const char *col="#000000", const char *stipple=0, UInt_t w=16, UInt_t h=16)
Fill spans with specified color or/and stipple.
Definition: TASImage.cxx:4783
virtual void Delete(Option_t *option="")
Delete this object.
Definition: TObject.cxx:228
Using a TBrowser one can browse all ROOT objects.
Definition: TBrowser.h:41
void DrawCircle(Int_t x, Int_t y, Int_t r, const char *col="#000000", Int_t thick=1)
Draw a circle.
Definition: TASImage.cxx:6336
R__EXTERN const char * gProgName
Definition: TSystem.h:234
void UnZoom()
Un-zoom the image to original size.
Definition: TASImage.cxx:2045
void FillRectangleInternal(UInt_t col, Int_t x, Int_t y, UInt_t width, UInt_t height)
Fill rectangle of size (width, height) at position (x,y) within the existing image with specified col...
Definition: TASImage.cxx:3731
Bool_t fIsGray
gray image
Definition: TASImage.h:70
void SetImage(const Double_t *imageData, UInt_t width, UInt_t height, TImagePalette *palette=0)
Deletes the old image and creates a new image depending on the values of imageData.
Definition: TASImage.cxx:983
float ymax
Definition: THbookFile.cxx:93
virtual void PaintAxis(Double_t xmin, Double_t ymin, Double_t xmax, Double_t ymax, Double_t &wmin, Double_t &wmax, Int_t &ndiv, Option_t *chopt="", Double_t gridlength=0, Bool_t drawGridOnly=kFALSE)
Control function to draw an axis.
Definition: TGaxis.cxx:705
static char * gIconPaths[7]
Definition: TASImage.cxx:125
void Append(const TImage *im, const char *option="+", const char *color="#00000000")
Append image.
Definition: TASImage.cxx:3487
void SetPalette(const TImagePalette *palette)
Set a new palette to an image.
Definition: TASImage.cxx:1857
void DrawWideLine(UInt_t x1, UInt_t y1, UInt_t x2, UInt_t y2, UInt_t col, UInt_t thick)
Draw wide line.
Definition: TASImage.cxx:5638
TPaveText * pt
static Int_t GetWidth()
Definition: TTF.cxx:625
ROOT::R::TRInterface & r
Definition: Object.C:4
Bool_t EndsWith(const char *pat, ECaseCompare cmp=kExact) const
Return true if string ends with the specified string.
Definition: TString.cxx:2220
Double_t fMaxValue
temporary scaled and zoomed image produced from original image
Definition: TASImage.h:60
R__EXTERN TSystem * gSystem
Definition: TSystem.h:549
SVector< double, 2 > v
Definition: Dict.h:5
XPoint xy[kMAXMK]
Definition: TGX11.cxx:122
void Merge(const TImage *im, const char *op="alphablend", Int_t x=0, Int_t y=0)
Merge two images.
Definition: TASImage.cxx:2716
virtual void SetFillColor(Color_t fcolor)
Definition: TAttFill.h:50
#define FillSpansInternal(npt, ppt, widths, color)
Definition: TASImage.cxx:3719
const Mask_t kGCClipXOrigin
Definition: GuiTypes.h:304
void FromWindow(Drawable_t wid, Int_t x=0, Int_t y=0, UInt_t w=0, UInt_t h=0)
Create an image (screenshot) from specified window.
Definition: TASImage.cxx:6577
virtual Int_t GetValue(const char *name, Int_t dflt)
Returns the integer value for a resource.
Definition: TEnv.cxx:494
TImagePalette fPalette
Definition: TAttImage.h:124
void FloodFill(Int_t x, Int_t y, const char *col, const char *min_col, const char *max_col=0)
Flood fill.
Definition: TASImage.cxx:6455
TClass * IsA() const
void CropPolygon(UInt_t npt, TPoint *ppt)
Crop a convex polygon.
Definition: TASImage.cxx:5378
static FT_Matrix * GetRotMatrix()
Definition: TTF.cxx:646
void CropSpans(UInt_t npt, TPoint *ppt, UInt_t *widths)
Crop spans.
Definition: TASImage.cxx:4898
UShort_t * fColorAlpha
Definition: TAttImage.h:91
void Form(const char *fmt,...)
Formats a string using a printf style format descriptor.
Definition: TString.cxx:2321
const char * AsHexString() const
Return color as hexadecimal string.
Definition: TColor.cxx:1134
unsigned int UInt_t
Definition: RtypesCore.h:42
TTF helper class containing glyphs description.
Definition: TTF.h:75
void Slice(UInt_t xStart, UInt_t xEnd, UInt_t yStart, UInt_t yEnd, UInt_t toWidth, UInt_t toHeight)
Another method of enlarging images where corners remain unchanged, but middle part gets tiled...
Definition: TASImage.cxx:1947
char * Form(const char *fmt,...)
const Handle_t kNone
Definition: GuiTypes.h:89
virtual void CellArrayBegin(Int_t W, Int_t H, Double_t x1, Double_t x2, Double_t y1, Double_t y2)=0
Pixmap_t GetMask()
Returns image mask pixmap (alpha channel).
Definition: TASImage.cxx:2302
virtual void SetPalette(const TImagePalette *palette)
Set a new palette for the image.
Definition: TAttImage.cxx:650
Array of longs (32 or 64 bits per element).
Definition: TArrayL.h:29
void AddAt(Long_t c, Int_t i)
Add long c at position i. Check for out of bounds.
Definition: TArrayL.cxx:92
TLine * l
Definition: textangle.C:4
virtual const char * GetName() const
Returns name of object.
Definition: TNamed.h:51
const Mask_t kGCClipYOrigin
Definition: GuiTypes.h:305
The axis painter class.
Definition: TGaxis.h:39
TSubString Strip(EStripType s=kTrailing, char c= ' ') const
Return a substring of self stripped at beginning and/or end.
Definition: TString.cxx:1069
void FillPolygon(UInt_t npt, TPoint *ppt, const char *col="#000000", const char *stipple=0, UInt_t w=16, UInt_t h=16)
Fill a convex polygon with background color or bitmap.
Definition: TASImage.cxx:5322
virtual void SetByteCount(UInt_t cntpos, Bool_t packInVersion=kFALSE)=0
void Blur(Double_t hr=3, Double_t vr=3)
Perform Gaussian blur of the image (useful for drop shadows).
Definition: TASImage.cxx:2755
UInt_t fNumPoints
Definition: TAttImage.h:86
virtual Int_t GetCanvasID() const =0
UInt_t fZoomOffX
min value in image
Definition: TASImage.h:62
void MapQuality(EImageQuality &quality, UInt_t &asquality, Bool_t toas=kTRUE)
Map quality to/from AfterImage quality.
Definition: TASImage.cxx:946
Int_t CountChar(Int_t c) const
Return number of times character c occurs in the string.
Definition: TString.cxx:443
Bool_t IsNull() const
Definition: TString.h:387
static void CreateETandAET(int count, TPoint *pts, EdgeTable *ET, EdgeTableEntry *AET, EdgeTableEntry *pETEs, ScanLineListBlock *pSLLBlock)
Definition: TASPolyUtils.c:365
void Flip(Int_t flip=180)
Flip image in place.
Definition: TASImage.cxx:2073
R__EXTERN TRandom * gRandom
Definition: TRandom.h:62
static int InsertionSort(EdgeTableEntry *AET)
Definition: TASPolyUtils.c:485
UShort_t * fColorBlue
Definition: TAttImage.h:90
TString fName
Definition: TNamed.h:36
virtual void ReadFastArray(Bool_t *b, Int_t n)=0
virtual void WriteFastArray(const Bool_t *b, Int_t n)=0
virtual ~TASImage()
Image destructor, clean up image and visual.
Definition: TASImage.cxx:350
#define gVirtualX
Definition: TVirtualX.h:362
static const UInt_t NUMPTSTOBUFFER
Definition: TASImage.cxx:5399
static TImage * Create()
TASImage * fScaledImage
pointer to image structure of original image
Definition: TASImage.h:59
void FillRectangle(const char *col=0, Int_t x=0, Int_t y=0, UInt_t width=0, UInt_t height=0)
Fill rectangle of size (width, height) at position (x,y) within the existing image with specified col...
Definition: TASImage.cxx:3789
Define a Frame.
Definition: TFrame.h:29
Double_t Cos(Double_t)
Definition: TMath.h:424
const Double_t * GetArray() const
Definition: TArrayD.h:45
char * StrDup(const char *str)
Duplicate the string str.
Definition: TString.cxx:2513
Int_t GetSize() const
Definition: TArray.h:49
void HSV(UInt_t hue=0, UInt_t radius=360, Int_t H=0, Int_t S=0, Int_t V=0, Int_t x=0, Int_t y=0, UInt_t width=0, UInt_t height=0)
This function will tile original image to specified size with offsets requested, and then it will go ...
Definition: TASImage.cxx:2942
virtual void SetY2(Double_t y2)
Definition: TBox.h:86
Bool_t fConstRatio
Definition: TAttImage.h:123
UInt_t * GetRgbaArray()
Return a pointer to an array[width x height] of RGBA32 values.
Definition: TASImage.cxx:3615
long Long_t
Definition: RtypesCore.h:50
Color * colors
Definition: X3DBuffer.c:19
void Tile(UInt_t width, UInt_t height)
Tile the original image.
Definition: TASImage.cxx:1983
Int_t fZoomUpdate
hight of zoomed image in image pixels
Definition: TASImage.h:66
void DrawText(Int_t x=0, Int_t y=0, const char *text="", Int_t size=12, const char *color=0, const char *font="fixed", EText3DType type=TImage::kPlain, const char *fore_file=0, Float_t angle=0)
Draw text of size (in pixels for TrueType fonts) at position (x, y) with color specified by hex strin...
Definition: TASImage.cxx:2580
void Bevel(Int_t x=0, Int_t y=0, UInt_t width=0, UInt_t height=0, const char *hi="#ffdddddd", const char *lo="#ff555555", UShort_t thick=1, Bool_t pressed=kFALSE)
Bevel is used to create 3D effect while drawing buttons, or any other image that needs to be framed...
Definition: TASImage.cxx:3245
Bool_t IsValid() const
Definition: TASImage.h:185
void DrawPolyLine(UInt_t nn, TPoint *xy, const char *col="#000000", UInt_t thick=1, TImage::ECoordMode mode=kCoordModeOrigin)
Draw a polyline.
Definition: TASImage.cxx:4640
static const double x1[5]
void Crop(Int_t x=0, Int_t y=0, UInt_t width=0, UInt_t height=0)
Crop an image.
Definition: TASImage.cxx:3410
struct _EdgeTableEntry EdgeTableEntry
void Mirror(Bool_t vert=kTRUE)
Mirror image in place.
Definition: TASImage.cxx:2120
static Int_t GetAscent()
Definition: TTF.cxx:632
void DrawEllips(Int_t x, Int_t y, Int_t rx, Int_t ry, Int_t angle, const char *col="#000000", Int_t thick=1)
Draw an ellipse.
Definition: TASImage.cxx:6376
double Double_t
Definition: RtypesCore.h:55
void PaintImage(Drawable_t wid, Int_t x, Int_t y, Int_t xsrc=0, Int_t ysrc=0, UInt_t wsrc=0, UInt_t hsrc=0, Option_t *opt="")
Draw image on the drawable wid (pixmap, window) at x,y position.
Definition: TASImage.cxx:1343
TText * text
void fill()
Definition: utils.cpp:314
int type
Definition: TGX11.cxx:120
static const float S
Definition: mandel.cpp:113
R__EXTERN TEnv * gEnv
Definition: TEnv.h:174
ClassImp(TMCParticle) void TMCParticle printf(": p=(%7.3f,%7.3f,%9.3f) ;", fPx, fPy, fPz)
unsigned long ULong_t
Definition: RtypesCore.h:51
UInt_t fZoomHeight
width of zoomed image in image pixels
Definition: TASImage.h:65
ECoordMode
Definition: TImage.h:101
virtual Int_t FindColor(UShort_t r, UShort_t g, UShort_t b)
Returns an index of the closest color.
Definition: TAttImage.cxx:485
Double_t y[n]
Definition: legend1.C:17
static ARGB32 GetHilite(ARGB32 background)
Calculate highlite color.
Definition: TASImage.cxx:3196
static void destroy_asdraw_context32(ASDrawContext *ctx)
Destroy asdraw context32.
Definition: TASImage.cxx:5624
void Add(TObject *obj)
Add object to the hash table.
Definition: THashTable.cxx:75
void DrawDashLine(UInt_t x1, UInt_t y1, UInt_t x2, UInt_t y2, UInt_t nDash, const char *pDash, const char *col="#000000", UInt_t thick=1)
Draw a dashed line.
Definition: TASImage.cxx:4596
#define _MEMSET_(dst, lng, val)
Definition: TASImage.cxx:3714
The color creation and management class.
Definition: TColor.h:23
struct _ScanLineListBlock ScanLineListBlock
Int_t GetEntries() const
Return the number of objects in array (i.e.
Definition: TObjArray.cxx:493
static CARD8 MakeComponentHilite(int cmp)
Make component hilite.
Definition: TASImage.cxx:3182
void GetImageBuffer(char **buffer, int *size, EImageFileTypes type=TImage::kPng)
Return in-memory buffer compressed according image type.
Definition: TASImage.cxx:5928
void FromGLBuffer(UChar_t *buf, UInt_t w, UInt_t h)
Creates an image (screenshot) from a RGBA buffer.
Definition: TASImage.cxx:6628
#define _alphaBlend(bot, top)
Definition: TASImage.cxx:151
TImage & operator=(const TImage &img)
Definition: TImage.h:120
A class to define a conversion from pixel values to pixel color.
Definition: TAttImage.h:83
void DrawLineInternal(UInt_t x1, UInt_t y1, UInt_t x2, UInt_t y2, UInt_t col, UInt_t thick)
Internal line drawing.
Definition: TASImage.cxx:3896
Array of doubles (64 bits per element).
Definition: TArrayD.h:29
static Vc_ALWAYS_INLINE int_v max(const int_v &x, const int_v &y)
Definition: vector.h:440
#define name(a, b)
Definition: linkTestLib0.cpp:5
virtual void Draw(Option_t *option="")
Draw this box with its current attributes.
Definition: TBox.cxx:180
#define SETBIT(n, i)
Definition: Rtypes.h:121
SCoord_t GetX() const
Definition: TPoint.h:49
Mother of all ROOT objects.
Definition: TObject.h:58
Double_t fMinValue
max value in image
Definition: TASImage.h:61
void DrawDashVLine(UInt_t x, UInt_t y1, UInt_t y2, UInt_t nDash, const char *pDash, UInt_t col, UInt_t thick)
Draw a dashed vertical line.
Definition: TASImage.cxx:4197
Bool_t IsDigit() const
Returns true if all characters in string are digits (0-9) or white spaces, i.e.
Definition: TString.cxx:1806
static void SetRotationMatrix(Float_t angle)
Set the rotation matrix used to rotate the font outlines.
Definition: TTF.cxx:341
Int_t GetNoElements() const
Definition: TVectorT.h:82
static ASVisual * fgVisual
hash table containing loaded plugins
Definition: TASImage.h:73
Handle_t Window_t
Definition: GuiTypes.h:30
UShort_t * fColorGreen
Definition: TAttImage.h:89
Mask_t fMask
Definition: GuiTypes.h:252
TASImage()
Default image constructor.
Definition: TASImage.cxx:217
void AddAt(Double_t c, Int_t i)
Add double c at position i. Check for out of bounds.
Definition: TArrayD.cxx:92
static Bool_t fgInit
Definition: TASImage.h:74
void DrawEllips2(Int_t x, Int_t y, Int_t rx, Int_t ry, Int_t angle, const char *col="#000000", Int_t thick=1)
Draw an ellipse.
Definition: TASImage.cxx:6416
virtual Int_t VtoPixel(Double_t v) const =0
const Ssiz_t kNPOS
Definition: Rtypes.h:115
const char * TypeFromMagicNumber(const char *file)
Guess the file type from the first byte of file.
Definition: TASImage.cxx:394
void DrawSegments(UInt_t nseg, Segment_t *seg, const char *col="#000000", UInt_t thick=1)
Draw segments.
Definition: TASImage.cxx:4760
Bool_t GetConstRatio() const
Definition: TAttImage.h:134
void DrawStraightEllips(Int_t x, Int_t y, Int_t rx, Int_t ry, const char *col="#000000", Int_t thick=1)
Draw a straight ellipse.
Definition: TASImage.cxx:6296
Short_t Max(Short_t a, Short_t b)
Definition: TMathBase.h:202
Bool_t Contains(const char *pat, ECaseCompare cmp=kExact) const
Definition: TString.h:567
Handle_t Pixmap_t
Definition: GuiTypes.h:31
struct _ScanLineList ScanLineList
Double_t Sin(Double_t)
Definition: TMath.h:421
TObject * FindObject(const char *name) const
Find object using its name.
Definition: THashTable.cxx:209
virtual void * GetStream() const
Definition: TVirtualPS.h:81
#define NULL
Definition: Rtypes.h:82
R__EXTERN TVirtualPS * gVirtualPS
Definition: TVirtualPS.h:91
#define gPad
Definition: TVirtualPad.h:288
virtual void StartPaletteEditor()
Opens a GUI to edit the color palette.
Definition: TAttImage.cxx:686
TASImage & operator=(const TASImage &img)
Image assignment operator.
Definition: TASImage.cxx:314
#define BRESINITPGON(dy, x1, x2, xStart, d, m, m1, incr1, incr2)
Definition: TASPolyUtils.c:93
static void SetTextSize(Float_t textsize)
Set current text size.
Definition: TTF.cxx:572
float type_of_call hi(const int &, const int &)
double result[121]
unsigned char UChar_t
Definition: RtypesCore.h:34
TVirtualPS is an abstract interface to Postscript, PDF, SVG.
Definition: TVirtualPS.h:40
virtual Bool_t ExpandPathName(TString &path)
Expand a pathname getting rid of special shell characters like ~.
Definition: TSystem.cxx:1243
void flip(struct mesh *m, struct behavior *b, struct otri *flipedge)
Definition: triangle.c:7889
UInt_t fZoomWidth
Y - offset for zooming im image pixels.
Definition: TASImage.h:64
ASImage * fGrayImage
1 - fast mode, 0 - low memory slow mode
Definition: TASImage.h:69
EText3DType
Definition: TImage.h:74
void DestroyImage()
Ssiz_t Index(const char *pat, Ssiz_t i=0, ECaseCompare cmp=kExact) const
Definition: TString.h:582
void DrawHLine(UInt_t y, UInt_t x1, UInt_t x2, UInt_t col, UInt_t thick)
Draw an horizontal line.
Definition: TASImage.cxx:3850
static const UInt_t kBrushCacheSize
Definition: TASImage.cxx:5632
static Int_t GetNumGlyphs()
Definition: TTF.cxx:639
const Bool_t kTRUE
Definition: Rtypes.h:91
float * q
Definition: THbookFile.cxx:87
Float_t GetScreenFactor() const
Definition: TStyle.h:264
Pixmap_t GetPixmap()
Returns image pixmap.
Definition: TASImage.cxx:2270
virtual void SetY1(Double_t y1)
Definition: TBox.h:85
Vc_ALWAYS_INLINE_L T *Vc_ALWAYS_INLINE_R malloc(size_t n)
Allocates memory on the Heap with alignment and padding suitable for vectorized access.
Definition: memory.h:67
Int_t Nint(T x)
Definition: TMath.h:480
ASImage * fImage
Definition: TASImage.h:58
Bool_t GetPolygonSpans(UInt_t npt, TPoint *ppt, UInt_t *nspans, TPoint **firstPoint, UInt_t **firstWidth)
The code is based on Xserver/mi/mipolycon.c "Copyright 1987, 1998 The Open Group".
Definition: TASImage.cxx:5177
void ExecuteEvent(Int_t event, Int_t px, Int_t py)
Execute mouse events.
Definition: TASImage.cxx:1703
const Int_t n
Definition: legend1.C:16
void SetDefaults()
Set default parameters.
Definition: TASImage.cxx:190
EGraphicsFunction
Definition: GuiTypes.h:68
virtual void Open(const char *filename, Int_t type=-111)=0
char * GetObjectInfo(Int_t px, Int_t py) const
Get image pixel coordinates and the pixel value at the mouse pointer.
Definition: TASImage.cxx:1816
To make it possible to use GL for 2D graphic in a TPad/TCanvas.
virtual unsigned char * ReadFile(const char *filename, UInt_t &w, UInt_t &h)=0
static void Image2Drawable(ASImage *im, Drawable_t wid, Int_t x, Int_t y, Int_t xsrc=0, Int_t ysrc=0, UInt_t wsrc=0, UInt_t hsrc=0, Option_t *opt="")
Draw asimage on drawable.
Definition: TASImage.cxx:1221
Ssiz_t First(char c) const
Find first occurrence of a character c.
Definition: TString.cxx:466
void Gradient(UInt_t angle=0, const char *colors="#FFFFFF #000000", const char *offsets=0, Int_t x=0, Int_t y=0, UInt_t width=0, UInt_t height=0)
Render multipoint gradient inside rectangle of size (width, height) at position (x,y) within the existing image.
Definition: TASImage.cxx:3005
ClassImp(TASImage) ClassImp(TASImagePlugin) void TASImage
Destroy image.
Definition: TASImage.cxx:166
virtual Version_t ReadVersion(UInt_t *start=0, UInt_t *bcnt=0, const TClass *cl=0)=0
UInt_t GetScaledWidth() const
Return width of the displayed image not of the original image.
Definition: TASImage.cxx:2168
static const FT_BBox & GetBox()
Definition: TTF.cxx:653
Int_t GetNumber() const
Definition: TColor.h:58
const char Int_t const char * image
Definition: TXSlave.cxx:46
virtual TCanvas * GetCanvas() const =0
const void * GetWcsTitle(void) const
Returns the text as UNICODE.
Definition: TText.cxx:126
static const double x3[11]
void DrawVLine(UInt_t x, UInt_t y1, UInt_t y2, UInt_t col, UInt_t thick)
Draw a vertical line.
Definition: TASImage.cxx:3815
virtual void BeginPaint(Bool_t=kTRUE)
Definition: TImage.h:198
virtual void Warning(const char *method, const char *msgfmt,...) const
Issue warning message.
Definition: TObject.cxx:904