/* Copyright (C) 2002 Sony Computer Entertainment America */
/*        All Rights Reserved.  SCEA Confidential         */

#ifndef SCEIMAGE_H
#define SCEIMAGE_H

class sceImage {
public:
  typedef enum  {  // used for run-time type checking
    UNKNOWN,
    PIXEL8,
    PIXEL16, 
    PIXELRGBA, 
    PIXELRGB16, 
    PIXELFLOAT,
  } SceImageType;

  // construct/destruct
  sceImage(int w=0, int h=0, void *data=NULL);
  virtual ~sceImage();

  // accessors
  int width() const { return _width; }
  int height() const { return _height; }
  int size() const { return _size;}
  virtual int pixsize() const { return 0;}
  virtual int bytesize() const { return pixsize()*_size;}
  virtual SceImageType type() const { return UNKNOWN;}

  void* data() const { return _data;}
  virtual u_int pixel(int i) const=0;
  virtual u_int pixel(int x, int y) const=0; // slow!!
  virtual void setPixel(int i, u_int val)=0;

  // methods
  void setData(void *data); // re-assign image data pointer
  void copy(const sceImage&src); // copy image structure and underlying data
  int resize(int w, int h); // resizes and re-allocates image
  
  // drawing routines
  void fill(u_int val=0);
  void drawLine(int x1, int y1, int x2, int y2, u_int val=255); // slow!!
  void drawBox(int xlu, int ylu, int w, int h, u_int val=255); // slow!!
  void drawEllipse(int x, int y, int rx, int ry, u_int val=255); // slow!!

  // in-place filters that I use a lot
  void smooth(int shiftright=8);
  void smooth2(int shiftright=8);
  void lsmooth(int shiftright=4);
  void lsmooth2(int shiftright=4);
  void threshold(int threshold);
  void invthreshold(int threshold);
  void band(int low, int high);
protected:
  int _width;
  int _height;
  int _size;
  int _flags;
  void* _data;
};

class sceImage16;

class sceImage8 : public sceImage {
public:
  sceImage8(int w=0,int h=0, void*data=NULL) : sceImage(w,h,data) {;}
  SceImageType type() const { return PIXEL8;}
  int pixsize() const { return 1;}
  u_char* data() const { return (u_char*) _data;}
  u_int pixel(int i) const { return data()[i];}
  u_int pixel(int x, int y) const { return data()[x+_width*y];}
  u_char& pixel(int i) { return data()[i];}
  u_char& pixel(int x, int y) { return data()[x+_width*y];}
  void setPixel(int i, u_int val) {pixel(i)=val;}

  void truncate(sceImage16& i16);
};

class sceImage16 : public sceImage {
public:
  sceImage16(int w=0,int h=0, void*data=NULL) : sceImage(w,h,data) {;}
  SceImageType type() const { return PIXEL16;}
  u_short* data() const { return (u_short*) _data;}
  int pixsize() const { return 2;}
  u_int pixel(int i) const { return data()[i];}
  u_int pixel(int x, int y) const { return data()[x+_width*y];}
  u_short& pixel(int i) { return data()[i];}
  u_short& pixel(int x, int y) { return data()[x+_width*y];}
  void setPixel(int i, u_int val) {pixel(i)=val;}

  void extend(sceImage8& i8);
};

// primarily texture-related support 
class sceImageRGBA : public sceImage {
public:
  sceImageRGBA(int w=0,int h=0, void*data=NULL) : sceImage(w,h,data) {;}
  SceImageType type() const { return PIXELRGBA;}
  u_int* data() const { return (u_int*) _data;}
  int pixsize() const { return 4;}
  u_int pixel(int i) const { return data()[i];}
  u_int pixel(int x, int y) const { return data()[x+_width*y];}
  u_int& pixel(int i) { return data()[i];}
  u_int& pixel(int x, int y) { return data()[x+_width*y];}
  void setPixel(int i, u_int val) {pixel(i)=val;}

  // texture-specific functions
  void setupTransfer(u_int vramaddress);
  void transferAsTexture();

  // i/o
  void readPPM(const char*file);
  void writePPM(const char*file);
};

// primarily texture-related support 
class sceImageRGB16 : public sceImage {
public:
  sceImageRGB16(int w=0,int h=0, void*data=NULL) : sceImage(w,h,data) {;}
  SceImageType type() const { return PIXELRGB16;}
  u_short* data() const { return (u_short*) _data;}
  int pixsize() const { return 2;}
  u_int pixel(int i) const { return data()[i];}
  u_int pixel(int x, int y) const { return data()[x+_width*y];}
  u_short& pixel(int i) { return data()[i];}
  u_short& pixel(int x, int y) { return data()[x+_width*y];}
  void setPixel(int i, u_int val) {pixel(i)=val;}

  // texture-specific functions
  void setupTransfer(u_int vramaddress);
  void transferAsTexture();
};

// sceImageFloat is not really supported yet.  Its intention is
// for use for prototyping new filters, not real-time use.
class sceImageFloat : public sceImage {
public:
  sceImageFloat(int w=0,int h=0, void*data=NULL) : sceImage(w,h,data) {;}
  SceImageType type() const { return PIXELFLOAT;}
  int pixsize() const { return 4;}
  float *data() const { return (float*)_data;}
  u_int pixel(int i) const { return (u_int)(int)(data()[i]);}
  u_int pixel(int x, int y) const { return (u_int)(int)(data()[x+_width*y]);}
  float& pixel(int i) { return data()[i];}
  float& pixel(int x, int y) { return data()[x+_width*y];}
  void setPixel(int i, u_int val) {pixel(i)=val;}
};



#endif // SCEIMAGE_H












