/// This file is part of the X3DToolKit library
/// Copyright (C) 2002-2004  Yannick Le Goc (legoc@imag.fr)

/// http://artis.imag.fr/Members/Yannick.Legoc/X3D/

/// This library is free software; you can redistribute it and/or
/// modify it under the terms of the GNU Lesser General Public
/// License as published by the Free Software Foundation; either
/// version 2.1 of the License, or (at your option) any later version.

/// This library is distributed in the hope that it will be useful,
/// but WITHOUT ANY WARRANTY; without even the implied warranty of
/// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
/// Lesser General Public License for more details.

/// You should have received a copy of the GNU Lesser General Public
/// License along with this library; if not, write to the Free Software
/// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
#ifndef X3DTK_IMAGE_H
#define X3DTK_IMAGE_H

#include "Platform.h"

#include <limits>

#undef max

namespace X3DTK {

class Image;

template<class T>
struct Memory
{
  inline static T *access(Image *I, unsigned short x, unsigned short y);
};

template<class IT, class OT>
struct ImageConverter
{
  static void make(unsigned char *out, unsigned char *in, unsigned int length);
};

/*! \brief Class declared in <b><X3DTK/kernel.h></b> providing an abstract factory 
 *  for the different image formats.
 *
 *  This class is defined to be user friendly for loading texture images in OpenGL.
 *
 *  \ingroup image
 */
 
class Image
{
public:
  /// Constructor.
  Image();
  /// Constructor with parameter.  
  Image(const char *fileName);
  /// Destructor.
  ~Image();
  
  /// Returns TRUE if the image is loaded.
  inline bool isLoaded() const {return (_data != 0);};
  /// Saves the image.
  void saveAs(const char *fileName, float quality = 1.0f);
  /// Resizes the memory array to width*height and GLType.
  void resize(unsigned short width, unsigned short height, GLenum GLType = GL_NONE);
  /// Resizes the memory array to width*height and GLType and returns the array pointer.
  unsigned char *resizeData(unsigned short width, unsigned short height, GLenum GLType = GL_NONE);
  /// Resizes the memory array to a power of two and fills textureTransform, the 
  /// transformation to apply in OpenGL to draw the good texture.
  void resizeGL(float (& textureTransform)[16]);
  /// Allocates a memory block. Used for reading pixels from buffer.
  bool allocate(unsigned short width, unsigned short height, GLenum GLFormat, GLenum GLType);
  /// releases the memory.
  void release();
  
  /// Gets the width.
  inline unsigned short getWidth() const {return _width;};
  /// Gets the height.
  inline unsigned short getHeight() const {return _height;};
  /// Gets the GL type of pixels.
  inline GLenum getGLFormat() const {return _glFormat;};
  /// Gets the data type of each element.
  inline GLenum getGLType() const {return _type;};
  /// Gets the size of pixels in bytes.
  inline int getPixelSize() const;
  /// Gets the data array.
  inline unsigned char* getData() const {return _data;};
  /// Computes the pixel size. 
  static int computePixelSize(GLenum GLFormat, GLenum GLType);  
private:
  unsigned char *_data;
  GLenum _glFormat;    
  GLenum _type;
  unsigned short _width;
  unsigned short _height;
  
  void convert(GLenum oldType, GLenum newType, unsigned char *newData, unsigned char *data, unsigned int length);
};

}

#include "Image.inl"

#endif
