/*------------------------------------------------------------------------------
 src/lib/djImage/imageOpLut.cxx
 
 Copyright (c) 2004-2006 Darby Johnston.
 All rights reserved.
 Use is subject to license terms.
------------------------------------------------------------------------------*/

//#define DJ_DBG
#include "djImageOpColor.h"
#include <djImageOpCore.h>
#include <djImageOpXform.h>
#include <djImageIo.h>

namespace dj {

const StrList ImageOpLut::attrNameList() const { return imageOpLutAttrStr(); }

bool ImageOpLut::attr(const Str & in, const StrList & data)
{
  StrList tmp = data;
  if (compareCase(attrNameList()[ATTR_FILE_NAME], in)) {
    if (! inflateStr(tmp, &_fileName)) return false;
  } else
    return false;
  return true;
}

const StrList ImageOpLut::attr(const Str & in) const
{
  StrList out;
  if (compareCase(attrNameList()[ATTR_FILE_NAME], in))
    out += deflateStr(_fileName);
  return out;
}

const PixelDataInfo ImageOpLut::info(const InfoList & in) const
{
  PixelDataInfo out(
    in.size() ? in[0]->size() : Vec2i(),
    in.size() ? in[0]->pixel() : Pixel()
  );
  
  ImageLoad * load = imageLoad(_fileName);
  if (load) {
    Image lut;
    load->get(&lut);
    out.pixel(Pixel(out.format(), lut.type()));
  }
  
  return out;
}

const Image ImageOpLut::work(const InputList & in) const
{
  if (! in.size()) return Image();
  const Image & input = *in[0];
  
  DJ_DBG_FNC("dj::ImageOpLut::work");

  // Setup.
  //
  Image out(workInfo(in));
  out.proxy(input.proxy());
  out.tagList(input.tagList());
  DJ_DBG_PRN("input = " << input);
  DJ_DBG_PRN("output = " << out);
  if (input.type() == PIXEL_F32) {
    pixelCopy(input, &out);
    return out;
  }
  
  // LUT.
  //
  ImageLoad * load = imageLoad(_fileName);
  if (! load) {
    pixelCopy(input, &out);
    return out;
  }
  Image lut;
  load->get(&lut, 0, input.format());
  int size = 0;
  switch (input.type()) {
    case PIXEL_U8: size = pixelU8Range; break;
    case PIXEL_U16: size = pixelU16Range; break;
    case PIXEL_F32: break;
  }
  DJ_DBG_PRN("size = " << size);
  if (lut.height() != 1)
    lut = ImageOpCrop::work(lut, Vec2i(lut.width(), 1));
  if (lut.width() != size)
    lut = ImageOpScale::work(
      lut,
      Vec2i(size, 1),
      ImageOpScale::AUTO, ImageOpScale::AUTO,
      Image::EDGE_CLIP, Image::EDGE_CLIP
    );
  Image lutPlanar(lut.size(), lut.pixel());
  pixelPlanar(
    lut.data(), lutPlanar.data(),
    lutPlanar.size(), lutPlanar.format(), lut.type(), lutPlanar.type()
  );
  DJ_DBG_PRN("lut = " << lutPlanar);
  
  // Work.
  //
  pixelLut(
    input.data(), out.data(), area(out.size()),
    lutPlanar.data(), lutPlanar.width(),
    out.format(), input.type(), out.type()
  );
  
  return out;
}

}
