00001 #include "Util.h"
00002 #include "ViewportGL.h"
00003 #include "Message.h"
00004 #include <math.h>
00005
00006 namespace apig {
00007
00008
00009
00010
00011 template<class Color>
00012 Image2D<Color>::Image2D(int w, int h, Color* inputData) : AbstractImage2D(w, h), data(inputData), wrapMode(CLAMP_TO_EDGE) {
00013 if (w <= 0 || h <= 0) {
00014 w = h = 0;
00015 data = NULL;
00016 }
00017 else if (inputData == NULL) {
00018 data = new Color[w * h];
00019 if (data == NULL) {
00020 Message::error("l'allocation memoire pour l'image a echoué");
00021 w = h = 0;
00022 }
00023 }
00024 }
00025
00026 template<class Color>
00027 Image2D<Color>::Image2D(QImage image) : AbstractImage2D(0,0), data(NULL), wrapMode(CLAMP_TO_EDGE) {
00028 initialize(image);
00029 }
00030
00031 template<class Color>
00032 Image2D<Color>::Image2D(QString fileName) : AbstractImage2D(0,0), data(NULL), wrapMode(CLAMP_TO_EDGE) {
00033 QImage image(fileName);
00034 if (image.isNull())
00035 Message::error(QString("probleme lors du chargement du fichier '%1'").arg(fileName));
00036 else
00037 initialize(image);
00038 }
00039
00040 template<class Color>
00041 void Image2D<Color>::destroy() {
00042 if (data != NULL) delete[] data;
00043 data = NULL;
00044 w = h = 0;
00045 }
00046
00047 template<class Color>
00048 void Image2D<Color>::initialize(QImage image) {
00049 destroy();
00050 if (image.isNull())
00051 Message::error("l'image fournie ne contient pas de données");
00052 else {
00053 w = image.width();
00054 h = image.height();
00055 data = new Color[w * h];
00056 if (data == NULL) {
00057 Message::error("l'allocation memoire pour l'image a echoué");
00058 w = h = 0;
00059 }
00060 else
00061 for (int i=0; i<w; i++)
00062 for (int j=0; j<h; j++)
00063 texel(i,j) = Color(image.pixel(i, h-1-j));
00064 }
00065 }
00066
00067 template<class Color>
00068 QImage Image2D<Color>::toQImage() const {
00069 QImage image(w, h, QImage::Format_ARGB32);
00070 for (int i=0; i<w; i++)
00071 for (int j=0; j<h; j++)
00072 image.setPixel(i, j, texel(i,h-1-j).toQRgb());
00073 return image;
00074 }
00075
00076 template<class Color>
00077 Image2D<Color> Image2D<Color>::clone() const {
00078 if (data == NULL) return Image2D<Color>();
00079 Color *clonedData = new Color[w * h];
00080 if (clonedData == NULL) {
00081 Message::error("l'allocation memoire pour l'image a echoué");
00082 return Image2D<Color>();
00083 }
00084 for (int c=0; c<w*h; c++)
00085 clonedData[c] = data[c];
00086 return Image2D<Color>(w, h, clonedData);
00087 }
00088
00089 template<class Color>
00090 Image2D<Color> Image2D<Color>::subImage(int i0, int j0, int ws, int hs) const {
00091 Image2D<Color> res(ws, hs);
00092 for (int i=0; i<ws; i++)
00093 for (int j=0; j<hs; j++)
00094 res.texel(i,j) = texel(i0+i, j0+j);
00095 return res;
00096 }
00097
00098 template<class Color>
00099 Image2D<Color> Image2D<Color>::supImage(int i0, int j0, int ws, int hs) const {
00100 Image2D<Color> res(ws, hs);
00101 for (int i=0; i<w; i++)
00102 for (int j=0; j<h; j++)
00103 res.texel(i0+i, j0+j) = texel(i, j);
00104 return res;
00105 }
00106
00107 template<class Color>
00108 Image2D<Color> Image2D<Color>::boundingPowerOfTwo() const {
00109 int ws, hs;
00110 for (ws = 1; ws < w; ws *= 2);
00111 for (hs = 1; hs < h; hs *= 2);
00112 return supImage(0,0,ws,hs);
00113 }
00114
00115 template<class Color>
00116 void Image2D<Color>::setBorderColor(Color c) {
00117 borderColor = c;
00118 }
00119
00120 template<class Color>
00121 void Image2D<Color>::setWrapMode(WrapMode mode) {
00122 wrapMode = mode;
00123 }
00124
00125 template<class Color>
00126 void Image2D<Color>::setupBorder(WrapMode mode, Color c) {
00127 wrapMode = mode;
00128 borderColor = c;
00129 }
00130
00131 template<class Color>
00132 Color Image2D<Color>::sample(int i, int j) const {
00133 switch (wrapMode) {
00134 case CLAMP_TO_BORDER : return contains(i, j) ? texel(i,j) : borderColor;
00135 case REPEAT : return texel(util::modulo(i, w), util::modulo(j, h));
00136 case MIRRORED_REPEAT : return texel(util::mirror(i,w), util::mirror(j,h));
00137 case CLAMP_TO_EDGE :
00138 default : return texel(util::clamp(i, 0, w-1), util::clamp(j, 0, h-1));
00139 };
00140 }
00141
00142 template<class Color>
00143 Color Image2D<Color>::interp(float x, float y) const {
00144 int i0 = (int)(floorf(x - 0.5)),
00145 j0 = (int)(floorf(y - 0.5));
00146 float a = x - 0.5 - i0,
00147 b = y - 0.5 - j0;
00148 return (1-a) * (1-b) * sample(i0, j0 ) + a * (1-b) * sample(i0+1, j0 )
00149 + (1-a) * b * sample(i0, j0+1) + a * b * sample(i0+1, j0+1);
00150 }
00151
00152 template<class Color>
00153 void Image2D<Color>::clear(Color c) {
00154 for (int i=0; i<w*h; i++) data[i] = c;
00155 }
00156
00157
00158
00159
00160 template<class Color>
00161 void Image2D<Color>::loadTexture2D(GLenum texFormat, GLenum target) const {
00162 glTexImage2D(target, 0, texFormat, w, h, 0, Color::DATA_FORMAT, Color::DATA_TYPE, data);
00163 }
00164
00165 template<class Color>
00166 Image2D<Color> Image2D<Color>::getTexture(const Texture *tex) {
00167 int w = tex->getWidth(),
00168 h = tex->getHeight();
00169 Image2D<Color> res(w, h, NULL);
00170 if (w < 0 || h < 0)
00171 Message::error("dimensions de la texture non definies");
00172 else {
00173 tex->bind();
00174 glGetTexImage(GL_TEXTURE_2D, 0, Color::DATA_FORMAT, Color::DATA_TYPE, res.data);
00175 }
00176 return res;
00177 }
00178
00179 template<class Color>
00180 void Image2D<Color>::readTexture(const Texture *tex) {
00181 int wTex = tex->getWidth(),
00182 hTex = tex->getHeight();
00183 if (wTex < 0 || hTex < 0)
00184 Message::error("dimensions de la texture non definies");
00185 else if
00186 (wTex != w && hTex != h)
00187 Message::error("dimensions de la texture differentes de celles de l'image");
00188 else {
00189 tex->bind();
00190 glGetTexImage(GL_TEXTURE_2D, 0, Color::DATA_FORMAT, Color::DATA_TYPE, data);
00191 }
00192 }
00193
00194 template<class Color>
00195 Image2D<Color> Image2D<Color>::getColorBuffer() {
00196 ViewportGL view;
00197 Image2D<Color> res(view.w, view.h, NULL);
00198 glReadPixels(0, 0, view.w, view.h, Color::DATA_FORMAT, Color::DATA_TYPE, res.data);
00199 return res;
00200 }
00201
00202 template<class Color>
00203 Image2D<Color> Image2D<Color>::getDepthBuffer() {
00204 ViewportGL view;
00205 Image2D<Color> res(view.w, view.h, NULL);
00206 glReadPixels(0, 0, view.w, view.h, GL_DEPTH_COMPONENT, Color::DATA_TYPE, res.data);
00207 return res;
00208 }
00209
00210 template<class Color>
00211 void Image2D<Color>::readColorBuffer(int i, int j) {
00212 glReadPixels(i, j, w, h, Color::DATA_FORMAT, Color::DATA_TYPE, data);
00213 }
00214
00215 template<class Color>
00216 void Image2D<Color>::readDepthBuffer(int i, int j) {
00217 glReadPixels(i, j, w, h, GL_DEPTH_COMPONENT, Color::DATA_TYPE, data);
00218 }
00219
00220 template<class Color>
00221 Color Image2D<Color>::readPixelColor(int i, int j) {
00222 Color pix;
00223 glReadPixels(i, j, 1, 1, Color::DATA_FORMAT, Color::DATA_TYPE, &pix);
00224 return pix;
00225 }
00226
00227 template<class Color>
00228 void Image2D<Color>::drawColorBuffer(int i, int j) const {
00229 glPushAttrib(GL_ALL_ATTRIB_BITS);
00230 ViewportGL view;
00231 view.pushScreenMatrices();
00232 glRasterPos2i(i, j);
00233 glDisable(GL_DEPTH_TEST);
00234 glDrawPixels(w, h, Color::DATA_FORMAT, Color::DATA_TYPE, data);
00235 view.popScreenMatrices();
00236 glPopAttrib();
00237 }
00238
00239
00240
00241 template<class Color>
00242 Texture Image2D<Color>::createTex2D(QString fileName, GLint internalFormat, GLenum interpMode, GLenum wrapMode) {
00243 Image2D<Color> image(fileName);
00244 Texture tex(&image, interpMode, wrapMode);
00245 tex.load(internalFormat);
00246 image.destroy();
00247 return tex;
00248 }
00249
00250 }
00251