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

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

namespace dj {

ImageOpRotate90::ImageOpRotate90() :
  _value(ROTATE_90)
{}

const StrList ImageOpRotate90::attrNameList() const
  { return imageOpRotate90AttrStr(); }

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

const StrList ImageOpRotate90::attr(const Str & in) const
{
  StrList out;
  if (compareCase(attrNameList()[ATTR_VALUE], in))
    out += deflateStr(_value, imageOpRotate90Str());
  return out;
}

const PixelDataInfo ImageOpRotate90::info(const InfoList & in) const
{
  return in.size() ? info(*in[0], _value) : PixelDataInfo();
}

const PixelDataInfo ImageOpRotate90::info(
  const PixelDataInfo & in, ROTATE rotate
) {
  Vec2i size;
  switch (rotate) {
    case ROTATE_0:
    case ROTATE_180: size = in.size(); break;
    case ROTATE_90:
    case ROTATE_270: size = swap(in.size()); break;
  }
  return PixelDataInfo(size, in.pixel());
}

const Image ImageOpRotate90::work(const InputList & in) const
{
  return in.size() ? work(*in[0], _value) : Image();
}

const Image ImageOpRotate90::work(const Image & in, ROTATE rotate)
{
  DJ_DBG_FNC("dj::ImageOpRotate90::work");
  DJ_DBG_PRN("in = " << in);
  DJ_DBG_PRN("value = " << imageOpRotate90Str()[rotate]);
  
  // Setup.
  //
  Image out(info(in, rotate));
  out.proxy(in.proxy());
  out.tagList(in.tagList());
  
  // Work.
  //
  const int w = out.width(), h = out.height();
  const int pixelSize = dj::pixelSize(out);
  switch (rotate) {
  
    case ROTATE_0:
      pixelCopy(in, &out);
      break;
    
    case ROTATE_90: {
      for (int y = 0; y < h; ++y) {
        const uint8_t * inP = in.data(in.width() - 1 - y, 0);
        uint8_t * outP = out.data(0, y);
        const int inInc = scanlineSize(in);
        for (int x = 0; x < w; ++x, inP += inInc, outP += pixelSize)
          memCopy(inP, outP, pixelSize);
      }
    } break;
    
    case ROTATE_180: {
      for (int y = 0; y < h; ++y) {
        const uint8_t * inP = in.data(in.width() - 1, in.height() - y - 1);
        uint8_t * outP = out.data(0, y);
        for (int x = 0; x < w; ++x, inP -= pixelSize, outP += pixelSize)
          memCopy(inP, outP, pixelSize);
      }
    } break;
    
    case ROTATE_270: {
      for (int y = 0; y < h; ++y) {
        const uint8_t * inP = in.data(y, in.height() - 1);
        uint8_t * outP = out.data(0, y);
        const int inInc = -scanlineSize(in);
        for (int x = 0; x < w; ++x, inP += inInc, outP += pixelSize)
          memCopy(inP, outP, pixelSize);
      }
    } break;
  }

  return out;
}

}
