/*------------------------------------------------------------------------------
 src/plugin/djImageIoVlut/save.cxx
 
 Copyright (c) 2004-2006 Darby Johnston.
 All rights reserved.
 Use is subject to license terms.
------------------------------------------------------------------------------*/

//#define DJ_DBG
#include "io.h"

extern "C" {
const dj::List<dj::ImageSave *> djImageSave()
{
  dj::List<dj::ImageSave *> out;
  out += new djImageIoVlut::Save;
  return out;
}
}

namespace djImageIoVlut {

Save::Save() :
  _x(0)
{}

Save::~Save()
{
  if (_x) delete _x;
}

bool Save::open(const Str & fileName, const ImageIoInfo &)
{
  DJ_DBG_FNC("djImageIoVlut::Save::open");
  DJ_DBG_PRN("file name = " << fileName);
  
  _displayName = fileName;
  
  return true;
}

bool Save::imageBegin(const Image & in, int frame)
{
  DJ_DBG_FNC("djImageIoVlut::Save::imageBegin");
  
  if (! imageOpen(_displayName, in)) return false;

  return true;
}

#if defined(DJ_VLUT_XORG)

bool Save::imageOpen(const Str & fileName, const Image &)
{
  DJ_DBG_FNC("djImageIoVlut::Save::imageOpen");
  DJ_DBG_PRN("file name = " << fileName);

  // Open display.
  //
  if (_x) delete _x;
  _x = new XHandle(fileName);
  if (! _x->display) return false;
  
  // Information.
  //
  if (! XF86VidModeGetGammaRampSize(_x->display, _x->screen, &_size))
    return false;
  DJ_DBG_PRN("vlut size = " << _size);
  
  return true;
}

bool Save::imageSet(const PixelData & in)
{
  DJ_DBG_FNC("dj::djImageIoVlut::Save::imageSet");
  DJ_DBG_PRN("in = " << in);
  
  // Convert.
  //
  PixelData scanline(Vec2i(_size, 1), Pixel(PIXEL_RGB, PIXEL_U16));
  unsigned short * const p =
    reinterpret_cast<unsigned short *>(scanline.data());
  for (int c = 0; c < 3; ++c)
    pixelCopy(
      in.data() + c * pixelSize(in.type()), p + _size * c,
      _size, in.pixel(), Pixel(PIXEL_L, PIXEL_U16),
      1, false, -1
    );
  
  // Write.
  //
  if (
    ! XF86VidModeSetGammaRamp(
      _x->display, _x->screen, _size, p, p + _size, p + _size * 2
    )
  )
    return false;

  delete _x;
  _x = 0;
  return true;
}

#elif defined(DJ_VLUT_XSGI)

bool Save::imageOpen(const Str & fileName, const Image & in)
{
  DJ_DBG_FNC("djImageIoVlut::Save::imageOpen");
  DJ_DBG_PRN("file name = " << fileName);

  // Open.
  //
  if (_x) delete _x;
  _x = new XHandle(fileName);
  if (! _x->display) return false;
  
  // Information.
  //
  int maps = 0, precision = 0, attr = 0;
  if (! XSGIvcQueryScreenGammaMaps(_x->display, _x->screen, &maps))
    return false;
  if (maps <= 0) return false;
  if (
    ! XSGIvcQueryGammaMap(
      _x->display, _x->screen, 0, &_size, &precision, &attr
    )
  )
    return false;
  if (attr & XSGIVC_GMWriteLock) return false;
  DJ_DBG_PRN("vlut size = " << size);
  
  return true;
}

bool Save::imageSet(const PixelData & in)
{
  DJ_DBG_FNC("dj::djImageIoVlut::Save::imageSet");
  DJ_DBG_PRN("in = " << in);
  
  // Convert.
  //
  PixelData scanline(Vec2i(_size, 1), Pixel(PIXEL_RGB, PIXEL_U16));
  unsigned short * const p =
    reinterpret_cast<unsigned short *>(scanline.data());
  for (int c = 0; c < 3; ++c)
    pixelCopy(
      in.data() + c * pixelSize(in.type()), p + _size * c,
      _size, in.pixel(), Pixel(PIXEL_L, PIXEL_U16),
      1, false, -1
    );
  
  // Write.
  //
  XSGIvcStoreGammaColors16(
    _x->display, _x->screen, 0, _size, XSGIVC_MComponentRed, p
  );
  XSGIvcStoreGammaColors16(
    _x->display, _x->screen, 0, _size, XSGIVC_MComponentGreen, p + _size
  );
  XSGIvcStoreGammaColors16(
    _x->display, _x->screen, 0, _size, XSGIVC_MComponentBlue, p + _size * 2
  );

  delete _x;
  _x = 0;
  return true;
}

#endif

}
