// @(#)root/graf:$Name:  $:$Id: TAttImage.cxx,v 1.3 2002/12/02 18:50:02 rdm Exp $
// Author: Reiner Rohlfs   24/03/02

/*************************************************************************
 * Copyright (C) 2001-2001, Rene Brun, Fons Rademakers and Reiner Rohlfs *
 * All rights reserved.                                                  *
 *                                                                       *
 * For the licensing terms see $ROOTSYS/LICENSE.                         *
 * For the list of contributors see $ROOTSYS/README/CREDITS.             *
 *************************************************************************/

//////////////////////////////////////////////////////////////////////////
//                                                                      //
//  TAttImage                                                           //
//                                                                      //
//  Image attributes are:                                               //
//    Image Quality (see EImageQuality for the list of qualities)       //
//    Compression defines the compression rate of the color data in the //
//                internal image structure. Speed and memory depends    //
//                on this rate, but not the image display itself        //
//                0: no compression;  100: max compression              //
//    Radio Flag: kTRUE  the x/y radio of the displayed image is always //
//                       identical to the original image                //
//                kFALSE the x and y size of the displayed image depends//
//                       on the size of the pad                         //
//    Palette:    Defines the conversion from a pixel value to the      //
//                screen color                                          //
//                                                                      //
//  This class is used (in general by secondary inheritance)            //
//  by some other classes (image display).                              //
//                                                                      //
//                                                                      //
//  TImagePalette                                                       //
//                                                                      //
//  A class to define a conversion from pixel values to pixel color.    //
//  A Palette is defined by some anchor points. Each anchor point has   //
//  a value between 0 and 1 and a color. An image has to be normalized  //
//  and the values between the anchor points are interpolated.          //
//  All member variables are public and can be directly manipulated.    //
//  In most cases the default operator will be used to create a         //
//  TImagePalette. In this case the member arrays have to be allocated  //
//  by an application and will be deleted in the destructor of this     //
//  class.                                                              //
//                                                                      //
//                                                                      //
//  TPaletteEditor                                                      //
//                                                                      //
//  This class provides a way to edit the palette via a GUI.            //
//                                                                      //
//////////////////////////////////////////////////////////////////////////

#include "TAttImage.h"
#include "TROOT.h"
#include "TPluginManager.h"
#include "Riostream.h"


// definition of a default palette
const Int_t kNUM_DEFAULT_COLORS = 12;
static UShort_t alphaDefault[kNUM_DEFAULT_COLORS] = {
   0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
   0xffff, 0xffff, 0xffff, 0xffff
};

static UShort_t redDefault[kNUM_DEFAULT_COLORS] = {
   0x0000, 0x0000, 0x7000, 0x0000, 0x0000, 0x0000, 0xffff, 0xffff,
   0x7000, 0x8000, 0xffff, 0xffff
};

static UShort_t greenDefault[kNUM_DEFAULT_COLORS] = {
   0x0000, 0x0000, 0x0000, 0x0000, 0xffff, 0xffff, 0xffff, 0x0000,
   0x0000, 0x8000, 0xffff, 0xffff
};

static UShort_t blueDefault[kNUM_DEFAULT_COLORS] = {
   0x0000, 0x0000, 0x7000, 0xffff, 0xffff, 0x0000, 0x0000, 0x0000,
   0x0000, 0xa000, 0xffff, 0xffff
};


ClassImp(TPaletteEditor)
ClassImp(TAttImage)
ClassImp(TImagePalette)

//______________________________________________________________________________
TPaletteEditor::TPaletteEditor(TAttImage *attImage, UInt_t, UInt_t)
{
   // Constructor.

   fAttImage = attImage;
}

//______________________________________________________________________________
void TPaletteEditor::CloseWindow()
{
   // Closes the window and deletes itself.

   fAttImage->EditorClosed();
}


//______________________________________________________________________________
TImagePalette::TImagePalette()
{
   // Default constructor, sets all pointers to 0.

   fNumPoints     = 0;
   fPoints        = 0;
   fColorRed      = 0;
   fColorGreen    = 0;
   fColorBlue     = 0;
   fColorAlpha    = 0;
}

//______________________________________________________________________________
TImagePalette::TImagePalette(UInt_t numPoints)
{
   // Constructor for a palette with numPoints anchor points.
   // It allocates the memory but does not set any colors.

   fNumPoints  = numPoints;
   fPoints     = new Double_t[fNumPoints];
   fColorRed   = new UShort_t[fNumPoints];
   fColorGreen = new UShort_t[fNumPoints];
   fColorBlue  = new UShort_t[fNumPoints];
   fColorAlpha = new UShort_t[fNumPoints];
}

//______________________________________________________________________________
TImagePalette::TImagePalette(const TImagePalette &palette) : TObject(palette)
{
   // Copy constructor.

   fNumPoints = palette.fNumPoints;

   fPoints = new Double_t[fNumPoints];
   memcpy(fPoints, palette.fPoints, fNumPoints * sizeof(Double_t));

   fColorRed   = new UShort_t[fNumPoints];
   fColorGreen = new UShort_t[fNumPoints];
   fColorBlue  = new UShort_t[fNumPoints];
   fColorAlpha = new UShort_t[fNumPoints];
   memcpy(fColorRed,   palette.fColorRed,   fNumPoints * sizeof(UShort_t));
   memcpy(fColorGreen, palette.fColorGreen, fNumPoints * sizeof(UShort_t));
   memcpy(fColorBlue,  palette.fColorBlue,  fNumPoints * sizeof(UShort_t));
   memcpy(fColorAlpha, palette.fColorAlpha, fNumPoints * sizeof(UShort_t));
}

//______________________________________________________________________________
TImagePalette::~TImagePalette()
{
   // Destructor.

   delete [] fPoints;
   delete [] fColorRed;
   delete [] fColorGreen;
   delete [] fColorBlue;
   delete [] fColorAlpha;
}

//______________________________________________________________________________
TImagePalette &TImagePalette::operator=(const TImagePalette &palette)
{
   // Assignment operator.

   if (this != &palette) {
      fNumPoints = palette.fNumPoints;

      delete [] fPoints;
      fPoints = new Double_t[fNumPoints];
      memcpy(fPoints, palette.fPoints, fNumPoints * sizeof(Double_t));

      delete [] fColorRed;
      fColorRed = new UShort_t[fNumPoints];
      memcpy(fColorRed, palette.fColorRed, fNumPoints * sizeof(UShort_t));

      delete [] fColorGreen;
      fColorGreen = new UShort_t[fNumPoints];
      memcpy(fColorGreen, palette.fColorGreen, fNumPoints * sizeof(UShort_t));

      delete [] fColorBlue;
      fColorBlue = new UShort_t[fNumPoints];
      memcpy(fColorBlue, palette.fColorBlue, fNumPoints * sizeof(UShort_t));

      delete [] fColorAlpha;
      fColorAlpha = new UShort_t[fNumPoints];
      memcpy(fColorAlpha, palette.fColorAlpha, fNumPoints * sizeof(UShort_t));
   }

   return *this;
}



//______________________________________________________________________________
TAttImage::TAttImage()
{
   // TAttImage default constructor.
   // Calls ResetAttImage to set the attributes to a default state.

   ResetAttImage();
   fPaletteEditor = 0;
}

//______________________________________________________________________________
TAttImage::TAttImage(EImageQuality lquality, UInt_t lcompression,
                     Bool_t constRatio)
{
   // TAttImage normal constructor.
   // Image attributes are taken from the argument list
   //    qualtity     : must be one of EImageQuality (kImgDefault is same as
   //                   kImgGood in the current implementation)
   //    lcompression : defines the compression rate of the color data in the
   //                   image. Speed and memory depends on this rate, but not
   //                   the image display itself
   //                   0: no compression;  100: max compression
   //    constRatio   : keeps the aspect ratio of the image constant on the
   //                   screen (in pixel units)

   ResetAttImage();

   fImageQuality = lquality;
   fImageCompression = (lcompression > 100) ? 100 : lcompression;
   fConstRatio = constRatio;
   fPaletteEditor = 0;
}

//______________________________________________________________________________
TAttImage::~TAttImage()
{
   // TAttImage destructor.

   delete fPaletteEditor;
}

//______________________________________________________________________________
void TAttImage::Copy(TAttImage &attimage) const
{
   // Copy this image attributes to a new attimage.

   attimage.fImageQuality     = fImageQuality;
   attimage.fImageCompression = fImageCompression;
   attimage.fConstRatio       = fConstRatio;
   attimage.fPalette          = fPalette;
}

//______________________________________________________________________________
void TAttImage::ResetAttImage(Option_t *)
{
   // Reset this image attributes to default values.
   // Default values are:
   //    quality:     kImgPoor, (no smoothing while the image is zoomed)
   //    compression: 0 (no compression)
   //    constRatio:  kTRUE
   //    palette:     a default rainbow palette

   fImageQuality      = kImgPoor;
   fImageCompression  = 0;
   fConstRatio        = kTRUE;

   // set the default palette
   delete [] fPalette.fPoints;
   delete [] fPalette.fColorRed;
   delete [] fPalette.fColorGreen;
   delete [] fPalette.fColorBlue;
   delete [] fPalette.fColorAlpha;

   fPalette.fNumPoints = kNUM_DEFAULT_COLORS;

   fPalette.fColorRed    = new UShort_t [kNUM_DEFAULT_COLORS];
   fPalette.fColorGreen  = new UShort_t [kNUM_DEFAULT_COLORS];
   fPalette.fColorBlue   = new UShort_t [kNUM_DEFAULT_COLORS];
   fPalette.fColorAlpha  = new UShort_t [kNUM_DEFAULT_COLORS];
   fPalette.fPoints      = new Double_t [kNUM_DEFAULT_COLORS];

   memcpy(fPalette.fColorRed,   redDefault,   kNUM_DEFAULT_COLORS * sizeof(UShort_t));
   memcpy(fPalette.fColorGreen, greenDefault, kNUM_DEFAULT_COLORS * sizeof(UShort_t));
   memcpy(fPalette.fColorBlue,  blueDefault,  kNUM_DEFAULT_COLORS * sizeof(UShort_t));
   memcpy(fPalette.fColorAlpha, alphaDefault, kNUM_DEFAULT_COLORS * sizeof(UShort_t));

   for (Int_t point = 0; point < kNUM_DEFAULT_COLORS - 2; point++)
      fPalette.fPoints[point + 1]  =  (double)point / (kNUM_DEFAULT_COLORS - 3);
   fPalette.fPoints[0] = 0;
   fPalette.fPoints[kNUM_DEFAULT_COLORS - 1] = 1;
}

//______________________________________________________________________________
void TAttImage::SaveImageAttributes(ofstream &out, const char *name,
                                    EImageQuality qualdef,
                                    UInt_t comprdef, Bool_t constRatiodef)
{
   // Save image attributes as C++ statement(s) on output stream, but
   // not the palette.

   if (fImageQuality != qualdef) {
      out<<"   "<<name<<"->SetImageQuality("<<fImageQuality<<");"<<endl;
   }
   if (fImageCompression != comprdef) {
      out<<"   "<<name<<"->SetImageCompression("<<fImageCompression<<");"<<endl;
   }
   if (fConstRatio != constRatiodef) {
      out<<"   "<<name<<"->SetConstRatio("<<fConstRatio<<");"<<endl;
   }
}

//______________________________________________________________________________
void TAttImage::SetConstRatio(Bool_t constRatio)
{
   // Set (constRatio = kTRUE) or unset (constRadio = kFALSE) the ratio flag.
   // The aspect ratio of the image on the screen is constant if the ratio
   // flag is set. That means one image pixel is allways a square on the screen
   // independent of the pad size and of the size of the zoomed area.

   fConstRatio = constRatio;
}

//______________________________________________________________________________
void TAttImage::SetPalette(const TImagePalette *palette)
{
   // Set a new palette for the image. If palette == 0 a default
   // rainbow color palette is used.

   if (palette)
      fPalette = *palette;
   else {
      // set default palette

      delete [] fPalette.fPoints;
      delete [] fPalette.fColorRed;
      delete [] fPalette.fColorGreen;
      delete [] fPalette.fColorBlue;
      delete [] fPalette.fColorAlpha;

      fPalette.fNumPoints = kNUM_DEFAULT_COLORS;

      fPalette.fColorRed    = new UShort_t [kNUM_DEFAULT_COLORS];
      fPalette.fColorGreen  = new UShort_t [kNUM_DEFAULT_COLORS];
      fPalette.fColorBlue   = new UShort_t [kNUM_DEFAULT_COLORS];
      fPalette.fColorAlpha  = new UShort_t [kNUM_DEFAULT_COLORS];
      fPalette.fPoints      = new Double_t [kNUM_DEFAULT_COLORS];

      memcpy(fPalette.fColorRed,   redDefault,   kNUM_DEFAULT_COLORS * sizeof(UShort_t));
      memcpy(fPalette.fColorGreen, greenDefault, kNUM_DEFAULT_COLORS * sizeof(UShort_t));
      memcpy(fPalette.fColorBlue,  blueDefault,  kNUM_DEFAULT_COLORS * sizeof(UShort_t));
      memcpy(fPalette.fColorAlpha, alphaDefault, kNUM_DEFAULT_COLORS * sizeof(UShort_t));

      for (Int_t point = 0; point < kNUM_DEFAULT_COLORS - 2; point++)
         fPalette.fPoints[point + 1]  =  (double)point / (kNUM_DEFAULT_COLORS - 3);
      fPalette.fPoints[0] = 0;
      fPalette.fPoints[kNUM_DEFAULT_COLORS - 1] = 1;
   }
}

//______________________________________________________________________________
void TAttImage::StartPaletteEditor()
{
   // Opens a GUI to edit the color palette.

   if (fPaletteEditor == 0) {
      TPluginHandler *h;

      if ((h = gROOT->GetPluginManager()->FindHandler("TPaletteEditor"))) {
         if (h->LoadPlugin() == -1)
            return;
         fPaletteEditor = (TPaletteEditor *) h->ExecPlugin(3, this, 80, 25);
      }
   }
}
