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

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

namespace dj {

ImageOpNoise::ImageOpNoise()
{
  _size = Vec2i(500, 500);
  _pixel = Pixel(PIXEL_RGB, PIXEL_U8);
  _color = Color(0.0);
  _color2 = Color(1.0);
  _randSeed = 0;
}

const StrList ImageOpNoise::attrNameList() const
  { return imageOpNoiseAttrStr(); }

bool ImageOpNoise::attr(const Str & in, const StrList & data)
{
  StrList tmp = data;
  if (compareCase(attrNameList()[ATTR_SIZE], in)) {
    if (! inflateStr(tmp, &_size)) return false;
  } else if (compareCase(attrNameList()[ATTR_PIXEL], in)) {
    if (! inflateStr(tmp, &_pixel)) return false;
  } else if (compareCase(attrNameList()[ATTR_COLOR], in)) {
    if (! inflateStr(tmp, &_color)) return false;
  } else if (compareCase(attrNameList()[ATTR_COLOR_2], in)) {
    if (! inflateStr(tmp, &_color2)) return false;
  } else if (compareCase(attrNameList()[ATTR_RANDOM_SEED], in)) {
    if (! inflateStr(tmp, &_randSeed)) return false;
  } else
    return false;
  return true;
}

const StrList ImageOpNoise::attr(const Str & in) const
{
  StrList out;
  if (compareCase(attrNameList()[ATTR_SIZE], in))
    out += deflateStr(_size);
  else if (compareCase(attrNameList()[ATTR_PIXEL], in))
    out += deflateStr(_pixel);
  else if (compareCase(attrNameList()[ATTR_COLOR], in))
    out += deflateStr(_color);
  else if (compareCase(attrNameList()[ATTR_COLOR_2], in))
    out += deflateStr(_color2);
  else if (compareCase(attrNameList()[ATTR_RANDOM_SEED], in))
    out += deflateStr(_randSeed);
  return out;
}

const PixelDataInfo ImageOpNoise::info(const InfoList &) const
{
  return PixelDataInfo(_size, _pixel);
}

const Image ImageOpNoise::work(const InputList &) const
{
  return work(_size, _pixel, _color, _color2, _randSeed);
}

const Image ImageOpNoise::work(
  const Vec2i & size, const Pixel & pixel,
  const Color & color, const Color & color2,
  int randSeed
) {
  DJ_DBG_FNC("dj::ImageOpNoise::work");
  DJ_DBG_PRN("size = " << size);
  DJ_DBG_PRN("pixel = " << pixel);
  DJ_DBG_PRN("color = " << color);
  DJ_DBG_PRN("color 2 = " << color2);
  
  // Setup.
  //
  Image out(size, pixel);
  dj::randSeed(randSeed);
  const PIXEL_FORMAT format = max(color.format(), color2.format());
  Color start(format, PIXEL_F32), end(format, PIXEL_F32);
  convert(color, &start);
  convert(color2, &end);
  Color tmp(format, PIXEL_F32);
  DJ_DBG_PRN("start = " << start);
  DJ_DBG_PRN("end = " << end);
  
  // Work.
  //
  PixelF32 * tmpP = reinterpret_cast<PixelF32 *>(tmp.data());
  PixelF32 * startP = reinterpret_cast<PixelF32 *>(start.data());
  PixelF32 * endP = reinterpret_cast<PixelF32 *>(end.data());
  const int w = out.width(), h = out.height();
  const int channels = pixelSize(format);
  for (int y = 0; y < h; ++y)
    for (int x = 0; x < w; ++x) {
      for (int c = 0; c < channels; ++c)
        tmpP[c] = rand(startP[c], endP[c]);
      out.pixel(tmp, x, y);
    }
  
  return out;
}

}
