/* -*- C++ -*- */
#ifndef __utils_header_file__
#define __utils_header_file__

#include "types.h"
#include "Array2D.h"
#include "Image.h"
#include <IL/il.h>


namespace fft
{
   template <typename T>
   Array2D<fft::real> abs(const Array2D<T>& src)
   {
      Array2D<fft::real> ret(src.W(), src.H());

      for (u32 i = 0; i < src.W() * src.H(); i++)
      {
	 ret[i] = std::abs(src[i]);
      }
   
      return ret;
   } 

   inline Array2D<real> imread(const String& fname) throw()
   {
      const real rs = .2126;
      const real gs = .7152;
      const real bs = .0722;

      Image im(fname.c_str());
      Array2D<real> ret(im.getWidth(), im.getHeight(), 0);

      const u8* data = im.getData();
      u32 stride = im.stride();
      for (u32 i = 0; i < im.getWidth() * im.getHeight(); i++)
      {


	 real r = data[i * stride] / 255.0;
	 real g = data[i * stride + 1] / 255.0;
	 real b = data[i * stride + 2] / 255.0;

	 ret[i] = r * rs + g * gs + b * bs;
      }

      ret.flipV();

      return ret;
   }

   inline void imsave(const Array2D<real>& src, const String& fileName)
   {
      // create new OpenIL image
      ILuint imageId;
      ilGenImages(1, &imageId);
      ilBindImage(imageId);


      // create buffer for image data
      u32 w = src.W();
      u32 h = src.H();
      u32 size = w * h;
      u8* data = new u8[size];

      //std::cerr << "min: " << src.min() << " max: " << src.max() << std::endl;

      // convert data from interval <0; 1> to <0; 255>
      for(u32 i = 0; i < size; i++)
      {
	 u32 t = static_cast<u32>(src[i] * 255.0);
	 if (t > 255) t = 255;
	 data[i] = static_cast<u8>(t);
      }

      // store image buffer into OpenIL image
      ilTexImage(w, h, 1, 1, IL_LUMINANCE, IL_UNSIGNED_BYTE, data);

      // save file
      ilEnable(IL_FILE_OVERWRITE);
      ilSaveImage(const_cast<char*>(fileName.c_str()));

      // delete OpenIL image
      ilDeleteImages(1, &imageId);

   }

}

#endif //__utils_header_file__
