Main Page | Class Hierarchy | Class List | Directories | File List

Image3D_impl.h

00001 #include "Util.h"
00002 #include "Message.h"
00003 #include <QDir>
00004 #include <math.h>
00005 
00006 namespace apig {
00007 
00008 /*********************************************************************************************/
00009 // Image3D :
00010 
00011 template<class Color>
00012 Image3D<Color>::Image3D(int w, int h, int d, Color* inputData) : AbstractImage3D(w, h, d), data(inputData), wrapMode(CLAMP_TO_EDGE) {
00013     if (w <= 0 || h <= 0 || d <= 0) {
00014         w = h = d = 0;
00015         data = NULL;
00016         }
00017     else if (inputData == NULL) {
00018         data = new Color[w * h * d];
00019         if (data == NULL) {
00020             Message::error("l'allocation memoire pour l'image a echoué");
00021             w = h = d = 0;
00022             }
00023         }
00024     }
00025 
00026 template<class Color>
00027 void Image3D<Color>::destroy() {
00028     if (data != NULL) delete[] data;
00029     data = NULL;
00030     w = h = d = 0;
00031     }
00032 
00033 template<class Color>
00034 Image3D<Color> Image3D<Color>::clone() const {
00035     if (data == NULL) return Image3D<Color>();
00036     Color *clonedData = new Color[w * h * d];
00037     if (clonedData == NULL) {
00038         Message::error("l'allocation memoire pour l'image a echoué");
00039         return Image3D<Color>();
00040         }
00041     for (int c=0; c<w*h*d; c++)
00042         clonedData[c] = data[c];
00043     return Image3D<Color>(w, h, d, clonedData);
00044     }
00045 
00046 template<class Color>
00047 void Image3D<Color>::setBorderColor(Color c) {
00048     borderColor = c;
00049     }
00050 
00051 template<class Color>
00052 void Image3D<Color>::setWrapMode(WrapMode mode) {
00053     wrapMode = mode;
00054     }
00055 
00056 template<class Color>
00057 void Image3D<Color>::setupBorder(WrapMode mode, Color c) {
00058     wrapMode = mode;
00059     borderColor = c;
00060     }
00061 
00062 template<class Color>
00063 Color Image3D<Color>::sample(int i, int j, int k) const {
00064     switch (wrapMode) {
00065         case CLAMP_TO_BORDER :  return contains(i, j, k) ? texel(i,j,k) : borderColor;
00066         case REPEAT :           return texel(util::modulo(i, w), util::modulo(j, h), util::modulo(k, d));
00067         case MIRRORED_REPEAT :  return texel(util::mirror(i,w), util::mirror(j,h), util::mirror(k,d));
00068         case CLAMP_TO_EDGE :
00069         default :               return texel(util::clamp(i, 0, w-1), util::clamp(j, 0, h-1), util::clamp(k, 0, d-1));
00070         };
00071     }
00072 
00073 template<class Color>
00074 Color Image3D<Color>::interp(float x, float y, float z) const {
00075     int i0 = (int)(floorf(x - 0.5)),
00076         j0 = (int)(floorf(y - 0.5)),
00077         k0 = (int)(floorf(z - 0.5));
00078     float a = x - 0.5 - i0,
00079           b = y - 0.5 - j0,
00080           c = z - 0.5 - k0;
00081     return (1-a) * (1-b) * (1-c) * sample(i0, j0  , k0  ) + a * (1-b) * (1-c) * sample(i0+1, j0  , k0  )
00082          + (1-a) * (1-b) *    c  * sample(i0, j0  , k0+1) + a * (1-b) *    c  * sample(i0+1, j0  , k0+1)
00083          + (1-a) *    b  * (1-c) * sample(i0, j0+1, k0  ) + a *    b  * (1-c) * sample(i0+1, j0+1, k0  )
00084          + (1-a) *    b  *    c  * sample(i0, j0+1, k0+1) + a *    b  *    c  * sample(i0+1, j0+1, k0+1);
00085     }
00086 
00087 /*********************************************************************************************/
00088 // fonction de chargement de texture :
00089 
00090 template<class Color>
00091 void Image3D<Color>::loadTexture3D(GLint texFormat, GLenum target) const {
00092     glTexImage3D(target, 0, texFormat, w, h, d, 0, Color::DATA_FORMAT, Color::DATA_TYPE, data);
00093     }
00094 
00095 template<class Color>
00096 Image3D<Color> Image3D<Color>::readTexture(Texture *tex) {
00097     int w = tex->getWidth(),
00098         h = tex->getHeight(),
00099         d = tex->getDepth();
00100     Image3D<Color> res(w, h, d, NULL);
00101     if (w < 0 || h < 0 || d < 0)
00102         Message::error("dimensions de la texture non definies");
00103     else {
00104         tex->bind();
00105         glGetTexImage(GL_TEXTURE_3D, 0, Color::DATA_FORMAT, Color::DATA_TYPE, res.data);
00106         }
00107     return res;
00108     }
00109 
00110 /*********************************************************************************************/
00111 // fonctions de chargement/sauvegarde de fichiers :
00112 
00113 template<class Color>
00114 Image3D<Color>::Image3D(QString fileName) : AbstractImage3D(0,0,0), data(NULL), wrapMode(CLAMP_TO_EDGE) {
00115     QDir dir(fileName);
00116     if (!dir.exists()) {
00117         Message::error(QString("le sous-répertoire '%1' n'existe pas").arg(fileName));
00118         return;
00119         }
00120     dir.setNameFilters(QStringList("*.png"));
00121     QStringList fileNamesList = dir.entryList(QDir::Files, QDir::Name);
00122     
00123     d = fileNamesList.size();
00124     if (d == 0) {
00125         Message::error(QString("aucun fichier image dans le répertoire '%1'").arg(fileName));
00126         return;
00127         }
00128     
00129     QImage slice0(dir.filePath(fileNamesList[0]));
00130     w = slice0.width();
00131     h = slice0.height();
00132     data = new Color[w * h * d];
00133     if (data == NULL) {
00134         Message::error("memoire insuffisante pour charger l'image 3D en memoire");
00135         w = h = d = 0;
00136         return;
00137         }
00138 
00139     for (int k=0; k<d; k++) {
00140         QImage slice(dir.filePath(fileNamesList[k]));
00141         // on vérifie que les slices ont bien la même taille :
00142         if (slice.width() != w || slice.height() != h) {
00143             Message::error("les slices d'une image 3D doivent avoir toutes la même taille");
00144             destroy();
00145             return;
00146             }
00147         // on recopie la slice dans l'image 3D :
00148         for (int i=0; i<w; i++) for (int j=0; j<h; j++)
00149             texel(i,j,k) = Color(slice.pixel(i, h-1-j));    // inversion des ordonnées
00150         }
00151     }
00152 
00153 template<class Color>
00154 void Image3D<Color>::save(QString dirName, QString subDirName) const {
00155     if (!loaded()) {
00156         Message::error("l'image ne contient pas de donnees");
00157         return;
00158         }
00159     
00160     QDir dir(dirName);
00161     if (!dir.exists()) {
00162         Message::error(QString("le répertoire '%1' n'existe pas").arg(dirName));
00163         return;
00164         }
00165     
00166     if (dir.exists(subDirName)) {
00167         // les éventuels fichiers que contient le sous-répertoire sont effacés :
00168         QDir subDir = dir;
00169         subDir.cd(subDirName);
00170         QStringList files = subDir.entryList(QDir::Files | QDir::NoSymLinks);
00171         foreach (QString file, files) subDir.remove(file);
00172         }
00173     else if (!dir.mkdir(subDirName)) {
00174         Message::error(QString("impossible de creer le repertoire '%1'").arg(subDirName));
00175         return;
00176         }
00177     
00178     QString absDirName = util::filePath(dirName, subDirName);
00179     
00180     for (int k=0; k<d; k++) {
00181         QImage slice(w, h, QImage::Format_ARGB32);
00182         for (int i=0; i<w; i++) for (int j=0; j<h; j++)
00183             slice.setPixel(i, h-1-j, texel(i,j,k).toQRgb());    // inversion des ordonnées
00184         QString fileName = util::filePath(subDirName, QString("slice%1.png").arg(k, 3, 10, QLatin1Char('0')));
00185         if (!image.save(fileName, "PNG"))
00186             Message::error(QString("probleme lors de la sauvegarde du fichier '%1'").arg(fileName));
00187         }
00188     }
00189 
00190 }
00191 

Generated on Fri Nov 14 20:49:47 2008 for Api Graphics by  doxygen 1.4.4