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

//#define DJ_DBG
#include "djImageOpColor.h"
#include <djMath.h>

namespace dj {

ImageOpPixel::ImageOpPixel(bool lut) :
  _lut(lut)
{}

ImageOpPixel::~ImageOpPixel() {}

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

  DJ_DBG_FNC("dj::ImageOpPixel::work");
  
  // Setup.
  //
  Image out(workInfo(in));
  out.proxy(input.proxy());
  out.tagList(input.tagList());
  DJ_DBG_PRN("input = " << input);
  DJ_DBG_PRN("output = " << out);

  // Work.
  //
  const int w = out.width(), h = out.height();
  const PIXEL_FORMAT format = out.format();
  const PIXEL_TYPE type = out.type();
  if (
    _lut &&
    (
      (PIXEL_U8 == type && area(out.size()) > pixelU8Range) ||
      (PIXEL_U16 == type && area(out.size()) > pixelU16Range)
    )
  ) {
    
    // Initialize LUT.
    //
    int size = 0;
    switch (type) {
      case PIXEL_U8: size = pixelU8Range; break;
      case PIXEL_U16: size = pixelU16Range; break;
      case PIXEL_F32: break;
    }
    Image lut(Vec2i(size, 1), Pixel(format, PIXEL_F32));
    pixelGradient(lut.data(), size, lut.pixel());
    
    // Process LUT.
    //
    workF32(reinterpret_cast<PixelF32 *>(lut.data()), size, format);
    Image lutPlanar(Vec2i(size, 1), Pixel(format, type));
    pixelPlanar(
      lut.data(), lutPlanar.data(),
      Vec2i(size, 1), format, PIXEL_F32, type
    );
    DJ_DBG_PRN("lut = " << lutPlanar);
    
    // Apply LUT.
    //
    pixelLut(
      input.data(), out.data(), w * h,
      lutPlanar.data(), lutPlanar.width(),
      format, type, type
    );
    
  } else {
  
    pixelCopy(input, &out);
  
    if (PIXEL_F32 == out.type()) {
    
      // Process floating point data.
      //
      workF32(
        reinterpret_cast<PixelF32 *>(out.data()),
        w * h, format
      );
        
    } else {
    
      // Convert to floating point data and process.
      //
      Image scanline(Vec2i(w, 1), Pixel(format, PIXEL_F32));
      for (int y = 0; y < h; ++y) {
        pixelCopy(
          out.data(0, y), scanline.data(),
          w, out.pixel(), scanline.pixel()
        );
        workF32(
          reinterpret_cast<PixelF32 *>(scanline.data()),
          w, format
        );
        pixelCopy(
          scanline.data(), out.data(0, y),
          w, scanline.pixel(), out.pixel()
        );
      }
    }
  }
  
  return out;
}

}
