diff --git a/app/Algorithms/ClassAnalysis.cpp b/app/Algorithms/ClassAnalysis.cpp new file mode 100644 index 0000000000000000000000000000000000000000..34cf5de303be6806417689255a21698d901fe2f8 --- /dev/null +++ b/app/Algorithms/ClassAnalysis.cpp @@ -0,0 +1,412 @@ +/* + * Copyright 2011-2012 INSA Rennes + * + * This file is part of EIImage. + * + * EIImage is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * EIImage 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with EIImage. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include "ClassAnalysis.h" + +#include <cstring> +#include <cstdio> +#include <cmath> + +#include <GrayscaleImage.h> + +using namespace ClassAnalysis; +using namespace imagein; +using namespace std; + +void ClassAnalysis::analyse(int fen, uint8_t *imorig, double *param1, double *param2, int nbl, int nbc ) { + + // Param 1: Will now hold the means + // Param 2: Will now hold the standard deviations + if(!( fen < (nbl * 2) && fen < (nbc * 2) )) { + char buffer[255]; + sprintf( buffer, "Error in ClassAnalysis::analyse:\nfen = %d, nbl = %d, nbc = %d\n", fen, nbl, nbc ); + throw buffer; + } +// char nom1[40],nom2[40]; + int fen2,i,j,k,l,nbp; + long indexy; + long indexx; + double moy,sigma; + +// printf("taille de la fenetre locale pour le calcul des parametres :"); +// scanf("%d",&fen); + if(fen < 3) fen=3; + if(fen > 15) fen=15; + fen2 = fen/2; +// printf("nom de l'image du parametre 1 :"); +// scanf("%s",nom1); +// printf("nom de l'image du parametre 2 :"); +// scanf("%s",nom2); + + nbp = fen*fen; + for(i=0 ; i<nbl ; i++) + for(j=0 ; j<nbc ; j++) + { + moy = sigma = 0; + + for(k=-fen2 ; k<fen2+1 ; k++) + for(l=-fen2 ; l<fen2+1 ; l++) + { + indexy = abs((i+k)); + if( indexy >= nbl ) { + indexy = 2 * nbl - indexy - 2; + } + indexx = abs((j+l)); + if( indexx >= nbc ) { + indexx = 2 * nbc - indexx - 2; + } + moy = moy + *(imorig+(indexy)*nbc+indexx); + sigma = sigma+(*(imorig+(indexy)*nbc+indexx)*(*(imorig+(indexy)*nbc+indexx))); + } + *(param1+i*nbc+j) = (moy / nbp); + *(param2+i*nbc+j) = sqrt((double)(sigma/nbp-(moy*moy)/(nbp*nbp))); + } + + + /* + *learning_result_1 = new ImageFloat; + (*learning_result_1)->Create( nbc, nbl ); + *learning_result_2 = new ImageFloat; + (*learning_result_2)->Create( nbc, nbl ); + (*learning_result_1)->setFloatMatrix( param1 ); + (*learning_result_2)->setFloatMatrix( param2 ); + */ + //ecrire_image(p1,nom1,nbc,nbl); + //ecrire_image(p2,nom2,nbc,nbl); + +} + +void ClassAnalysis::estimateur(double *param1,double *param2,double moy1[],double var1[],double moy2[],double var2[],int fen,int nbl,int nbc, const vector<Rectangle>& rectangles) { + long nbp; + //long fen2; + double m1,s1,m2,s2; + int current_rectangle; + Rectangle rect; + + +/* estimation des paramtres de chaque classe */ +// Each class is a rectangle in the parameter rectangles + vector<Rectangle>::const_iterator iter; + current_rectangle = 0; + for(iter=rectangles.begin();iter!=rectangles.end();++iter) { + rect = *iter; + NormalizeRectangle( rect ); + nbp = ((rect.bottom() - rect.top()) + 1) * ((rect.right() - rect.left()) + 1); + m1 = m2 = s1 = s2 = 0; + for(unsigned int i=rect.top() ; i<=rect.bottom() ; i++) { + for(unsigned int j=rect.left() ; j<=rect.right() ; j++) { + m1 = m1 + *(param1+i*nbc+j); + s1 = s1+(*(param1+i*nbc+j)*(*(param1+i*nbc+j))); + m2 = m2 + *(param2+i*nbc+j); + s2 = s2+(*(param2+i*nbc+j)*(*(param2+i*nbc+j))); + } + } + moy1[current_rectangle] = (m1 / nbp); + var1[current_rectangle] = ((double)(s1/nbp-(m1*m1)/(nbp*nbp))); + if( var1[current_rectangle] > 0 ) { + var1[current_rectangle] = sqrt( var1[current_rectangle] ); + } + else { + var1[current_rectangle] = 0; + } + moy2[current_rectangle] = (m2 / nbp); + var2[current_rectangle] = ((double)(s2/nbp-(m2*m2)/(nbp*nbp))); + if( var2[current_rectangle] > 0 ) { + var2[current_rectangle] = sqrt( var2[current_rectangle] ); + } + else { + var2[current_rectangle] = 0; + } + current_rectangle++; + } +} + +void ClassAnalysis::classif(double *param1,double *param2,double moy1[],double var1[],double moy2[],double var2[],int fen,int nbl,int nbc, Image **classify_result, int num_classes ) { + //char nom[40]; + int i,j,k,l,numclass; + double distmin,dist,d1,d2; + short *resclass; + double num_class_multiplier = 250.0 / ((double)(num_classes-1)); + + //printf("nom de l'image resultat de classification :"); + //scanf("%s",nom); + + resclass = (short *)calloc(nbl*nbc,sizeof(short)); + +/* classification */ + for(i=0 ; i<nbl ; i++) + { + k=i*nbc; + for(j=0 ; j<nbc ; j++) + { + distmin = 10000; + for(l=0 ; l<num_classes ; l++) + { + d1 = (*(param1+k+j) - moy1[l])/var1[l]; + d2 = (*(param2+k+j) - moy2[l])/var2[l]; + dist = sqrt((double)(d1*d1+d2*d2)); + if(dist < distmin) + { + distmin = dist; + numclass = l; + } + } + *(resclass+k+j) = (short)(numclass * num_class_multiplier); + } + } + +/* sauvegarde image rsultat de classification dans un fichier */ + *classify_result = new GrayscaleImage(nbc, nbl); +// Pixel pixel; + int wcounter, hcounter; + for( hcounter=0; hcounter< nbl; hcounter++ ) { + for( wcounter=0; wcounter< nbc; wcounter++ ) { +// pixel.red = resclass[ hcounter * nbc + wcounter ]; +// pixel.green = pixel.red; +// pixel.blue = pixel.red; + (*classify_result)->setPixelAt( wcounter, hcounter, resclass[hcounter * nbc + wcounter] ); + } + } +// ecrire_image(resclass,nom,nbc,nbl); + +/* libration mmoire alloue */ + free(resclass); +} + +void ClassAnalysis::write_to_file( GrayscaleImage *learning, const vector<Rectangle>& rectangles, FILE *f, int learning_fen, Image_t<double> **returnval_mean, Image_t<double> **returnval_stdev ) { + char buffer[255]; + if(( learning == NULL )) { + sprintf( buffer, "Error in ClassAnalysis::write_to_file:\nlearning = %p", learning); + throw buffer; + } + if( f == NULL ) { + throw "Error in ClassAnalysis::write_to_file:\nf = NULL"; + } + if(!( ( learning_fen & 1 ) == 1 )) { + sprintf( buffer, "Error in ClassAnalysis::write_to_file:\nlearning_fen = %d", learning_fen ); + throw buffer; + } + if( rectangles.empty() ) { + throw "Error in ClassAnalysis::write_to_file:\nrectangles.empty() = TRUE"; + } + + //Image *learning_result_1; + //Image *learning_result_2; + uint8_t *im1; + double *param1,*param2, *moy1, *var1, *moy2, *var2; + long nbl,nbc,size,i; + + // entre des paramtres + nbc = learning->getWidth(); + nbl = learning->getHeight(); + size = nbc * nbl; + + im1 = learning->begin(); + moy1 = new double[ rectangles.size() ]; + var1 = new double[ rectangles.size() ]; + moy2 = new double[ rectangles.size() ]; + var2 = new double[ rectangles.size() ]; + + // allocation memoire pour les images des paramtres caractristiques + param1 = new double[size]; + param2 = new double[size]; + +// Traitement + //printf("\n\n- phase d'apprentissage \n"); + //printf("\n\n- calcul des parametres caracteristiques sur l'image %s\n",nom1); + analyse(learning_fen, im1,param1,param2,nbl,nbc ); + +// printf("\n\n- estimation des parametres caracteristiques \n"); + estimateur(param1,param2,moy1,var1,moy2,var2,learning_fen,nbl,nbc,rectangles); + + fprintf( f, "MEAN_STDEV\n" ); + fprintf( f, "%d\n", learning_fen ); + fprintf( f, "%d\n", rectangles.size() ); + vector<Rectangle>::const_iterator iter; + i = 0; + for(iter=rectangles.begin();iter!=rectangles.end();++iter) { + fprintf( f, "%f %f %f %f\n", moy1[i], var1[i], moy2[i], var2[i] ); + i++; + } + + if( returnval_mean != NULL ) { + (*returnval_mean) = new Image_t<double>(nbc, nbl, 1, param1); + } + if( returnval_stdev != NULL ) { + (*returnval_stdev) = new Image_t<double>(nbc, nbl, 1, param2); + } + /* + return_string = "valeur des parametres estimes :\n\n"; + for(i=0 ; i<4 ; i++) + { + sprintf(buffer, "Classe no %1d \n",i+1); + return_string = return_string + buffer; + sprintf(buffer, "parametre 1 ---> moyenne = %5.1f \n",moy1[i]); + return_string = return_string + buffer; + sprintf(buffer, "parametre 2 ---> ecart-type = %4.1f\n",var2[i]); + return_string = return_string + buffer; + } +*/ + // Erase memory allocated + delete im1; + delete moy1; + delete var1; + delete moy2; + delete var2; + delete param1; + delete param2; +// delete learning_result_1; +// delete learning_result_2; +} + +void ClassAnalysis::NormalizeRectangle( Rectangle &rect ) { + int top, bottom, left, right; + top = min( rect.top(), rect.bottom() ); + bottom = max( rect.top(), rect.bottom() ); + left = min( rect.left(), rect.right() ); + right = max( rect.left(), rect.right() ); + rect.y = top; + rect.h = bottom - top; + rect.x = left; + rect.w = right - left; +} + +Image *ClassAnalysis::classify_from_file( GrayscaleImage *to_classify, FILE *f, int classify_fen, Image_t<double> **returnval_mean, Image_t<double> **returnval_stdev ) { + if(!( to_classify != NULL )) { + throw "Error in ClassAnalysis::classify_from_file:\nto_classify = NULL"; + } + if(!( f != NULL )) { + throw "Error in ClassAnalysis::classify_from_file:\nf = NULL"; + } + if(!( ( classify_fen & 1 ) == 1 )) { + char buffer[255]; + sprintf( buffer, "Error in ClassAnalysis::classify_from_file:\nclassify_fen = %d", classify_fen ); + throw buffer; + } + + Image *returnval = NULL; + char buffer[255]; + int num_classes; + int counter; + double *param1,*param2, *moy1, *var1, *moy2, *var2; + long nbl,nbc; + //long size,i; + nbl = to_classify->getHeight(); + nbc = to_classify->getWidth(); + + fscanf( f, "%s", buffer ); + if( strcmp( buffer, "MEAN_STDEV" ) == 0 ) { + fscanf( f, "%d", &num_classes ); // Old learning window size + fscanf( f, "%d", &num_classes ); + if( num_classes <= 0 ) { + // Invalid number of classes + return NULL; + } + else { + moy1 = new double[ num_classes ]; + var1 = new double[ num_classes ]; + moy2 = new double[ num_classes ]; + var2 = new double[ num_classes ]; + for( counter=0; counter< num_classes; counter++ ) { + fscanf( f, "%lf", &moy1[counter] ); + fscanf( f, "%lf", &var1[counter] ); + fscanf( f, "%lf", &moy2[counter] ); + fscanf( f, "%lf", &var2[counter] ); + } + } + } + else { + // Invalid file type + return NULL; + } + + param1 = new double[nbl * nbc ]; + param2 = new double[nbl * nbc ]; + uint8_t *im1 = to_classify->begin(); + + analyse(classify_fen, im1,param1,param2,nbl,nbc ); + classif(param1,param2,moy1,var1,moy2,var2,classify_fen,nbl,nbc, &returnval, num_classes ); + + if( returnval_mean != NULL ) { + (*returnval_mean) = new Image_t<double>(nbc, nbl, 1, param1); + } + if( returnval_stdev != NULL ) { + (*returnval_stdev) = new Image_t<double>(nbc, nbl, 1, param2); + } + + delete im1; + delete param1; + delete param2; + delete moy1; + delete moy2; + delete var1; + delete var2; + return returnval; +} + +string ClassAnalysis::print_file_info( FILE *f ) { + if(!( f != NULL )) { + throw "Error in ClassAnalysis::print_file_info:\nf = NULL"; + } + string returnval; + + int wsize; + int num_classes; + char buffer[255]; + double moy1, moy2, var1, var2; + int counter; + fscanf( f, "%s", buffer ); + if( strcmp( buffer, "MEAN_STDEV" ) == 0 ) { + fscanf( f, "%d", &wsize ); // Old learning window size + sprintf( buffer, "Learning Window Size: %d\n", wsize ); + returnval = returnval + buffer; + fscanf( f, "%d", &num_classes ); + sprintf( buffer, "Number of Classes: %d\n", num_classes ); + returnval = returnval + buffer; + + if( num_classes <= 0 ) { + // Invalid number of classes + returnval = "\n Invalid number of classes"; + } + else { + for( counter=0; counter< num_classes; counter++ ) { + fscanf( f, "%lf", &moy1 ); + fscanf( f, "%lf", &var1 ); + fscanf( f, "%lf", &moy2 ); + fscanf( f, "%lf", &var2 ); + sprintf( buffer, "---- Class %d:\n", (counter+1) ); + returnval = returnval + buffer; + sprintf( buffer, " Mean of means: %f\n", moy1 ); + returnval = returnval + buffer; + //sprintf( buffer, " Stdev of means: %f\n", var1 ); + //returnval = returnval + buffer; + sprintf( buffer, " Mean of stdevs: %f\n", moy2 ); + returnval = returnval + buffer; + //sprintf( buffer, " Stdev of stdevs: %f\n", var2 ); + //returnval = returnval + buffer; + returnval = returnval + "\n"; + } + } + } + else { + returnval = "Not a valid classification file\n"; + } + + return returnval; +} diff --git a/app/Algorithms/ClassAnalysis.h b/app/Algorithms/ClassAnalysis.h new file mode 100644 index 0000000000000000000000000000000000000000..df327cf8157b6031f41e67392b6ff21c5e48545b --- /dev/null +++ b/app/Algorithms/ClassAnalysis.h @@ -0,0 +1,39 @@ +/* + * Copyright 2011-2012 INSA Rennes + * + * This file is part of EIImage. + * + * EIImage is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * EIImage 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with EIImage. If not, see <http://www.gnu.org/licenses/>. +*/ + +#ifndef CLASSANALYSIS_H +#define CLASSANALYSIS_H + +#include <Image.h> +#include <string> +#include <vector> +#include <GrayscaleImage.h> + +namespace ClassAnalysis +{ + void analyse(int fen, uint8_t *imorig,double *param1,double *param2,int nbl,int nbc ); + void estimateur(double *param1,double *param2,double moy1[],double var1[],double moy2[],double var2[],int fen,int nbl,int nbc, const std::vector<imagein::Rectangle>& rectangles); + void classif(double *param1,double *param2,double moy1[],double var1[],double moy2[],double var2[],int fen,int nbl,int nbc, imagein::Image **classify_result, int num_classes ); + void write_to_file( imagein::GrayscaleImage *learning, const std::vector<imagein::Rectangle>& rectangles, FILE *f, int learning_fen, imagein::Image_t<double> **returnval_mean, imagein::Image_t<double> **returnval_stdev ); + void NormalizeRectangle( imagein::Rectangle &rect ); + imagein::Image *classify_from_file( imagein::GrayscaleImage *to_classify, FILE *f, int classify_fen, imagein::Image_t<double> **returnval_mean, imagein::Image_t<double> **returnval_stdev ); + std::string print_file_info( FILE *f ); +} + +#endif // CLASSANALYSIS_H diff --git a/app/Algorithms/Croissance.cpp b/app/Algorithms/Croissance.cpp index a84d1a6824b70b716778ffe9946b28340d30b944..ff32ac7cdb6982daf106928366bd0a350268c04b 100644 --- a/app/Algorithms/Croissance.cpp +++ b/app/Algorithms/Croissance.cpp @@ -170,7 +170,7 @@ int Croissance::croissance1b( const Image *im, int threshhold, Image **luminance tabout = new Image::depth_t[size]; tablabel = new int[size]; - MoyCell = new int[100000]; + MoyCell = new int[size]; numregion=1 ; nbpregion=0 ; @@ -296,7 +296,7 @@ int Croissance::croissance2a( const Image *im, int threshhold, Image **luminance tabout = new Image::depth_t[size]; tablabel = new int[size]; - MoyCell = new int[100000]; + MoyCell = new int[size]; numregion=1 ; nbpregion=0 ; @@ -389,7 +389,7 @@ int Croissance::croissance2b( const Image *im, int threshhold, Image **luminance tabout = new Image::depth_t[size]; tablabel = new int[size]; - MoyCell = new int[100000]; + MoyCell = new int[size]; numregion=1 ; nbpregion=0 ; diff --git a/app/Algorithms/DCT.cpp b/app/Algorithms/DCT.cpp new file mode 100644 index 0000000000000000000000000000000000000000..498355a3c962898b2e671bd34e5effc6c1351b2c --- /dev/null +++ b/app/Algorithms/DCT.cpp @@ -0,0 +1,641 @@ +/* + * Copyright 2011-2012 INSA Rennes + * + * This file is part of EIImage. + * + * EIImage is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * EIImage 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with EIImage. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include <cstdio> +#include "DCT.h" +#include <Converter.h> + +using namespace std; +using namespace imagein; + + + +void cosi(double* coef); +void inver(double* tab, double* coef); +void trans(double* tab, double* coef); +void idct(Image_t<double>* img, double* coefs); +void dct(Image_t<double>* img, double* coefs); +string reduce(Image_t<double>* img, int nBitInit, double slope); +string tronc(Image_t<double>*img, int limit); + +std::string dct16x16(const imagein::Image *img, imagein::Image_t<double> **resImg, imagein::Image **invImg, bool truncMode, int truncLimit, int nBitInit, double slope) +{ + string returnval; +/*---------------------------------------------------------------------- +* +* OUVERTURE ET LECTURE DU FICHIER IMAGE ORIGINE +* +*----------------------------------------------------------------------*/ +// tab1 = im; + Image_t<double>* tmpImg = Converter<Image_t<double> >::convert(*img); +// tabim= new float[size]; +// choix = v->choice; + //printf("\n\nMode de codage ? :\n"); + //printf(" - par troncature des coefficients (rep=1)\n"); + //printf(" - par matrice d'allocation de bits (rep=2)\n"); + //printf("Votre choix ? :"); + //scanf("%d",&choix); + + //PIXEL *p = tab1->get_image_data(); + +// for(i=0 ; i<nbl ; i++) { +// for(j=0 ; j<nbc ; j++) { +// pixel = tab1->GetPixel( j, i ); +// *(tabim+i*nbc+j) = (float)pixel.red; +// } +// } + +/*---------------------------------------------------------------------- +* +* CALCUL DES COEFFICIENTS DE LA MATRICE DE TRANSFORMATION +* +*----------------------------------------------------------------------*/ + double coef[16]; + cosi(coef); + +/*---------------------------------------------------------------------- +* +* TRANSFORMATION +* +*----------------------------------------------------------------------*/ + dct(tmpImg, coef); + +/*---------------------------------------------------------------------- +* +* CODAGE +* +*----------------------------------------------------------------------*/ +// printf("\ncodage ...\n"); + if(truncMode) { + returnval = tronc(tmpImg, truncLimit); + } + else { + returnval = reduce(tmpImg, nBitInit, slope); + } + +/*---------------------------------------------------------------------- +* +* STOCKAGE DE L'IMAGE TRANSFORMEE DANS UN FICHIER +* +*----------------------------------------------------------------------*/ +// max = 0.; +// for(i=0 ; i<nbl ; i++) +// for(j=0 ; j<nbc ; j++) +// { +// a = (float)log(fabs((double)(*(tabim+i*nbc+j))) + 1.); +// if(a > max) max = a; +// } + +// //q = (*result)->get_image_data(); +// for(i=0 ; i<nbl ; i++) +// for(j=0 ; j<nbc ; j++) +// { +// if( (i%idt)==0 && (j%idt)==0 ) { +// pixel.red = (byte)max; +// pixel.green = (byte)max; +// pixel.blue = (byte)max; +// pixel.alpha = 0; +// (*result)->SetPixel( j, i, pixel ); +// } +// else { +// pixel.red = (byte)(log(fabs((double)(*(tabim+i*nbc+j))) + 1.)*255/max + 0.5); +// pixel.green = pixel.red; +// pixel.blue = pixel.red; +// pixel.alpha = 0; +// (*result)->SetPixel( j, i, pixel ); +// } +// } + *resImg = new Image_t<double>(*tmpImg); + +/*---------------------------------------------------------------------- +* +* TRANSFORMATION INVERSE +* +*----------------------------------------------------------------------*/ + idct(tmpImg, coef); + +/*---------------------------------------------------------------------- +* +* STOCKAGE DE L'IMAGE RESULTAT DANS UN FICHIER +* +*----------------------------------------------------------------------*/ + +// for(i=0 ; i<nbl ; i++) +// for(j=0 ; j<nbc ; j++) +// { +// value = (short)(*(tabim+i*nbc+j) + 0.5); +// if (value > 255) value = 255; +// if (value < 0) value = 0; +// pixel.red = (byte)value; +// pixel.green = (byte)value; +// pixel.blue = (byte)value; +// pixel.alpha = 0; +// (*result_inverse)->SetPixel( j, i, pixel ); +// } + + *invImg = Converter<Image>::convertAndRound(*tmpImg); + + return returnval; +} + +/*-------------------------------------------------------------------- +* +* SOUS-PROGRAMME DE SUPRESSION DES COEFFICIENTS DE HAUTE FREQUENCE +* +*--------------------------------------------------------------------*/ +string tronc(Image_t<double>*img, int limit) +{ + double debit = 0.; + char buffer[255]; + + for(unsigned int c = 0; c < img->getNbChannels(); ++c) { + for(unsigned int i = 0; i < img->getHeight(); i +=16) { + for(unsigned int j = 0; j < img->getWidth(); j +=16) { + + for(int k = 0; k <16; ++k) { + for(int l = 0; l <16; ++l) { + + if(k > limit || l > limit) { + img->setPixelAt(j+l, i+k, c, 0.); + } + } + } + } + } + } + + /* calcul du debit */ + for(int k = 0; k <16; ++k) { + for(int l = 0; l <16; ++l) { + if(k <= limit && l <= limit) ++debit; + } + } + debit = debit * 8. / 256.; + sprintf(buffer, "\nLe debit vaut : %5.2f\n\n", debit); + return buffer; +} + +/*--------------------------------------------------------------------- +* +* SOUS-PROGRAMME DE QUANTIFICATION ET CODAGE DES COEFFICIENTS +* +*---------------------------------------------------------------------*/ +string reduce(Image_t<double>* img, int nBitInit, double slope) +{ + int matrice[16][16]; + + int n0 = nBitInit; + double a = slope; + double debit = 0; + + char buffer[100]; + string cs = "\n---------Matrice d'allocation de bits---------\n\n"; + + for(unsigned int i = 0; i <16; ++i) { + for(unsigned int j = 0; j <16; ++j) { + int m; + if(i==0 && j==0) { + m = 8; + } + else + { + m = n0 - (int)(fabs( a * (i+j) ) + 0.5); + if(m > 8) m = 8; + if(m < 0) m = 0; + } + matrice[i][j] = m; + debit += m; + sprintf( buffer, "%1d ",matrice[i][j]); + cs = cs + buffer; + } + cs = cs + "\n"; + } + debit /= (16 * 16); + sprintf(buffer, "\nLe debit vaut : %5.2f\n\n",debit); + cs = cs + buffer; + + + for(unsigned int c = 0; c < img->getNbChannels(); ++c) { + for(unsigned int i = 0; i < img->getHeight(); i +=16) { + for(unsigned int j = 0; j < img->getWidth(); j +=16) { + + img->setPixelAt(j, i, c, (int)(img->getPixelAt(j, i, c) + 0.5)); + + for(int k = 1; k <= 2*(16 - 1); ++k) { + for(int l = max(0, k -16+1); l <= min(k,16-1); l++) { + int kx, ky; + if( k%2 == 0) + { + kx = l; + ky = k-l; + } + else + { + kx = k-l; + ky = l; + } + + int nb = matrice[ky][kx] - 1; + if(nb >= 0) + { + double cmax = pow(2., nb) - 1.; + double co = img->getPixelAt(j + kx, i + ky, c); + double ca = fabs(co); + double cn = min(ca, cmax); + int cm = cn + 0.5; + img->setPixelAt(j+kx, i+ky, c, (co > 0) ? cm : -cm); + } + else { + img->setPixelAt(j+kx, i+ky, c, 0.); + } + + + } + } + } + } + } + return cs; +} + +/*--------------------------------------------------------------------- +* +* SOUS-PROGRAMME DE TRANSFORMATION DCT SUR TOUTE UNE IMAGE +* +*---------------------------------------------------------------------*/ +void dct(Image_t<double>* img, double* coefs) +{ + double coef = 2. / (16*16); + double coe0 = sqrt(0.5); + + for(unsigned int c = 0; c < img->getNbChannels(); ++c) { + for(unsigned int i = 0; i < img->getHeight(); i += 16) { + for(unsigned int j = 0; j < img->getWidth(); j += 16) { + + for(int k = 0; k < 16; ++k) { + + double tab[16]; + for(int l = 0; l < 16; ++l) { + tab[l] = img->getPixelAt(j+l, i+k, c); + } + + trans(tab, coefs); + tab[0] = tab[0] * coe0; + + for(int l = 0; l <16; ++l) { + img->setPixelAt(j+l, i+k, c, tab[l]); + } + } + + for(int l = 0; l < 16; ++l) + { + double tab[16]; + for(int k = 0; k < 16; ++k) { + tab[k] = img->getPixelAt(j+l, i+k, c); + } + + trans(tab, coefs); + tab[0] = tab[0] * coe0; + + for(int k=0; k < 16; ++k) { + img->setPixelAt(j+l, i+k, c, tab[k]*coef); + } + } + } + } + } +} + +/*--------------------------------------------------------------------- +* +* +* SOUS-PROGRAMME DE TRANSFORMATION DCT INVERSE SUR TOUTE UNE IMAGE +* +*---------------------------------------------------------------------*/ +void idct(Image_t<double>* img, double* coefs) +{ + double coe0 = sqrt(0.5); + double coef = 2.; + + for(unsigned int c = 0; c < img->getNbChannels(); ++c) { + for(unsigned int i = 0 ; i < img->getHeight() ; i += 16) { + for(unsigned int j = 0 ; j < img->getWidth() ; j += 16) { + + for(int k = 0 ; k < 16 ; ++k) { + + double tab[16]; + for(int l = 0; l < 16; ++l) { + tab[l] = img->getPixelAt(j+k, i+l, c) * coef; + } + + tab[0] = tab[0] * coe0; + inver(tab, coefs); + + for(int l = 0; l < 16; ++l) { + img->setPixelAt(j+k, i+l, c, tab[l]); + } + } + + for(int l = 0; l < 16; ++l) { + + double tab[16]; + for(int k = 0; k < 16; ++k) { + tab[k] = img->getPixelAt(j+k, i+l, c); + } + + tab[0] = tab[0] * coe0; + inver(tab, coefs); + + for(int k = 0; k < 16; ++k) { + img->setPixelAt(j+k, i+l, c, tab[k]); + } + } + } + } + } +} + +/*-------------------------------------------------------------------- +* +* SOUS-PROGRAMME DE TRANSFORMATION DCT D'UN VECTEUR A 16 ELEMENTS +* SELON L'ALGORITME RAPIDE DE B.G.LEE. +* +*--------------------------------------------------------------------*/ +void trans(double* tab, double* coef) +{ + double x0,x1,x2,x3,x4,x5,x6,x7,x8,x9,x10,x11,x12,x13,x14,x15; + double y0,y1,y2,y3,y4,y5,y6,y7,y8,y9,y10,y11,y12,y13,y14,y15; + + x0=tab[0]; + x1=tab[1]; + x2=tab[2]; + x3=tab[3]; + x4=tab[4]; + x5=tab[5]; + x6=tab[6]; + x7=tab[7]; + x8=tab[8]; + x9=tab[9]; + x10=tab[10]; + x11=tab[11]; + x12=tab[12]; + x13=tab[13]; + x14=tab[14]; + x15=tab[15]; + y0=x0+x15; + y15=(x0-x15)*coef[1]; + y1=x1+x14; + y14=(x1-x14)*coef[3]; + y2=x2+x13 ; + y13=(x2-x13)*coef[5]; + y3=x3+x12; + y12=(x3-x12)*coef[7]; + y4=x4+x11; + y11=(x4-x11)*coef[9]; + y5=x5+x10; + y10=(x5-x10)*coef[11]; + y6=x6+x9; + y9=(x6-x9)*coef[13]; + y7=x7+x8; + y8=(x7-x8)*coef[15]; + x0=y0+y7; + x7=(y0-y7)*coef[2]; + x1=y1+y6; + x6=(y1-y6)*coef[6]; + x2=y2+y5; + x5=(y2-y5)*coef[10]; + x3=y3+y4; + x4=(y3-y4)*coef[14]; + x15=y15+y8; + x8=(y15-y8)*coef[2]; + x14=y14+y9; + x9=(y14-y9)*coef[6]; + x13=y13+y10 ; + x10=(y13-y10)*coef[10]; + x12=y12+y11; + x11=(y12-y11)*coef[14]; + y0=x0+x3; + y3=(x0-x3)*coef[4]; + y1=x1+x2; + y2=(x1-x2)*coef[12]; + y7=x7+x4; + y4=(x7-x4)*coef[4]; + y6=x6+x5; + y5=(x6-x5)*coef[12]; + y15=x15+x12; + y12=(x15-x12)*coef[4]; + y14=x14+x13; + y13=(x14-x13)*coef[12]; + y8=x8+x11; + y11=(x8-x11)*coef[4]; + y9=x9+x10; + y10=(x9-x10)*coef[12]; + x0=y0+y1; + x1=(y0-y1)*coef[8]; + x3=y3+y2; + x2=(y3-y2)*coef[8]; + x7=y7+y6; + x6=(y7-y6)*coef[8]; + x4=y4+y5; + x5=(y4-y5)*coef[8]; + x15=y15+y14; + x14=(y15-y14)*coef[8]; + x12=y12+y13; + x13=(y12-y13)*coef[8]; + x8=y8+y9; + x9=(y8-y9)*coef[8]; + x11=y11+y10; + x10=(y11-y10)*coef[8]; + x3=x3+x2; + x4=x4+x5; + x12=x12+x13 ; + x11=x11+x10; + x7=x7+x4; + x4=x4+x6; + x6=x6+x5; + x8=x8+x11; + x11=x11+x9; + x9=x9+x10; + x15=x15+x8; + x8=x8+x12; + x12=x12+x11; + x11=x11+x14; + x14=x14+x9; + x9=x9+x13; + x13=x13+x10; + tab[0]=x0; + tab[1]=x15; + tab[2]=x7; + tab[3]=x8; + tab[4]=x3; + tab[5]=x12; + tab[6]=x4; + tab[7]=x11; + tab[8]=x1; + tab[9]=x14; + tab[10]=x6; + tab[11]=x9; + tab[12]=x2; + tab[13]=x13; + tab[14]=x5; + tab[15]=x10; +} + +/*-------------------------------------------------------------------- +* +* SOUS-PROGRAMME DE TRANSFORMATION DCT INVERSE D'UN VECTEUR A 16 ELE- +* MENTS SELON L'ALGORITME RAPIDE DE B.G.LEE. +* +*--------------------------------------------------------------------*/ +void inver(double* tab, double* coef) +{ + double x0,x1,x2,x3,x4,x5,x6,x7,x8,x9,x10,x11,x12,x13,x14,x15; + double y0,y1,y2,y3,y4,y5,y6,y7,y8,y9,y10,y11,y12,y13,y14,y15; + + x0=tab[0]; + x1=tab[1]; + x2=tab[2]; + x3=tab[3]; + x4=tab[4]; + x5=tab[5]; + x6=tab[6]; + x7=tab[7]; + x8=tab[8]; + x9=tab[9]; + x10=tab[10]; + x11=tab[11]; + x12=tab[12]; + x13=tab[13]; + x14=tab[14]; + x15=tab[15]; + x15=x15+x13; + x13=x13+x11; + x11=x11+x9; + x9=x9+x7; + x7=x7+x5; + x5=x5+x3; + x3=x3+x1; + x14=x14+x10; + x10=x10+x6; + x6=x6+x2; + x15=x15+x11; + x11=x11+x7; + x7=x7+x3; + x8=x8*coef[8]; + x10=x10*coef[8]; + x9=x9*coef[8]; + x11=x11*coef[8]; + x12=(x12+x4)*coef[8]; + x14=(x14+x6)*coef[8]; + x13=(x13+x5)*coef[8]; + x15=(x15+x7)*coef[8]; + y0=x0+x8; + y8=(x0-x8); + y4=(x4+x12)*coef[4]; + y12=(x4-x12)*coef[12]; + y2=x2+x10; + y10=x2-x10; + y6=(x6+x14)*coef[4]; + y14=(x6-x14)*coef[12]; + y1=x1+x9; + y9=x1-x9; + y5=(x5+x13)*coef[4]; + y13=(x5-x13)*coef[12]; + y3=x3+x11; + y11=x3-x11; + y7=(x7+x15)*coef[4]; + y15=(x7-x15)*coef[12]; + x0=y0+y4; + x4=y0-y4; + x8=y8+y12; + x12=y8-y12; + x2=(y2+y6)*coef[2]; + x6=(y2-y6)*coef[14]; + x10=(y10+y14)*coef[6]; + x14=(y10-y14)*coef[10]; + x1=y1+y5; + x5=y1-y5; + x9=y9+y13; + x13=y9-y13; + x3=(y3+y7)*coef[2]; + x7=(y3-y7)*coef[14]; + x11=(y11+y15)*coef[6]; + x15=(y11-y15)*coef[10]; + y0=x0+x2; + y2=x0-x2; + y8=x8+x10; + y10=x8-x10; + y4=x4+x6; + y6=x4-x6; + y12=x12+x14; + y14=x12-x14; + y1=(x1+x3)*coef[1]; + y3=(x1-x3)*coef[15]; + y9=(x9+x11)*coef[3]; + y11=(x9-x11)*coef[13]; + y5=(x5+x7)*coef[7]; + y7=(x5-x7)*coef[9]; + y13=(x13+x15)*coef[5]; + y15=(x13-x15)*coef[11]; + x0=y0+y1; + x1=y0-y1; + x2=y2+y3; + x3=y2-y3; + x4=y4+y5; + x5=y4-y5; + x6=y6+y7; + x7=y6-y7; + x8=y8+y9; + x9=y8-y9; + x10=y10+y11; + x11=y10-y11; + x12=y12+y13; + x13=y12-y13; + x14=y14+y15; + x15=y14-y15; + tab[0]=x0; + tab[1]=x8; + tab[2]=x12; + tab[3]=x4; + tab[4]=x6; + tab[5]=x14; + tab[6]=x10; + tab[7]=x2; + tab[8]=x3; + tab[9]=x11; + tab[10]=x15; + tab[11]=x7; + tab[12]=x5; + tab[13]=x13; + tab[14]=x9; + tab[15]=x1; +} + +/*-------------------------------------------------------------------- +* +* CALCUL DES COEFFICIENTS DE LA MATRICE DE TRANSFORMATION DCT. +* +*-------------------------------------------------------------------- */ +void cosi(double* coef) +{ + const double pi = 3.1415926535; + for(int k = 1; k < 16; ++k) { + coef[k] = 1. / ( 2. * cos( k * pi / 32.) ); + } +} diff --git a/core/Output.h b/app/Algorithms/DCT.h similarity index 69% rename from core/Output.h rename to app/Algorithms/DCT.h index 7b5d7aafe98b55310213b8f87986ad2193ab3c21..4166a77f33021d14da2346f6e676081b0d97f4c1 100644 --- a/core/Output.h +++ b/app/Algorithms/DCT.h @@ -1,37 +1,29 @@ /* * Copyright 2011-2012 INSA Rennes - * + * * This file is part of EIImage. - * + * * EIImage is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. - * + * * EIImage 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 General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with EIImage. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef EIIMAGE_OUTPUT_H -#define EIIMAGE_OUTPUT_H +#ifndef DCT_H +#define DCT_H -#include <vector> +#include "DCT.h" +#include <Image.h> #include <string> +std::string dct16x16(const imagein::Image *img, imagein::Image_t<double> **resImg, imagein::Image **invImg, bool truncMode = true, int truncLimit= 16, int nBitInit = 8, double slope = 0.); -class QWidget; -class Output { - public: - Output(std::string name) : _name(name) {} - virtual QWidget* getWidget() = 0; - virtual Output* clone() const = 0; - protected: - std::string _name; -}; - -#endif //!EIIMAGE_OUTPUT_H \ No newline at end of file +#endif // DCT_H diff --git a/app/Algorithms/Pyramid.cpp b/app/Algorithms/Pyramid.cpp new file mode 100644 index 0000000000000000000000000000000000000000..d865a2675cde5cbfddeaf2373e2e31f77c13f8c3 --- /dev/null +++ b/app/Algorithms/Pyramid.cpp @@ -0,0 +1,711 @@ +/* + * Copyright 2011-2012 INSA Rennes + * + * This file is part of EIImage. + * + * EIImage is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * EIImage 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with EIImage. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include "Pyramid.h" +#include <Algorithm/Filtering.h> +#include <cstdio> +#include <cstring> +using namespace std; +using namespace imagein; +using namespace Pyramid; + +const uint8_t tp6_filter_file_data[] = {0x74, 0x72, 0x69, 0x61, 0x6e, 0x67, 0x75, 0x6c, 0x61, 0x69, 0x72, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x80, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x67, 0x61, 0x75, 0x73, 0x73, 0x69, 0x65, 0x6e, 0x00, 0x00, 0xf8, 0x45, 0x26, 0x00, 0xf8, 0x45, 0x26, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xcd, 0xcc, 0xcc, 0x3e, 0x00, 0x00, 0x80, 0x3e, 0xcd, 0xcc, 0x4c, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x74, 0x72, 0x69, 0x6d, 0x6f, 0x64, 0x61, 0x6c, 0x00, 0x00, 0x00, 0x45, 0x26, 0x00, 0xf8, 0x45, 0x26, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9a, 0x99, 0x19, 0x3f, 0x00, 0x00, 0x80, 0x3e, 0xcd, 0xcc, 0x4c, 0xbd, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x72, 0x65, 0x63, 0x74, 0x61, 0x6e, 0x67, 0x75, 0x6c, 0x61, 0x69, 0x72, 0x65, 0x00, 0x00, 0x00, 0xf8, 0x45, 0x26, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xae, 0x47, 0xe1, 0x3d, 0xae, 0x47, 0xe1, 0x3d, 0xae, 0x47, 0xe1, 0x3d, 0xae, 0x47, 0xe1, 0x3d, 0xae, 0x47, 0xe1, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x71, 0x6d, 0x66, 0x00, 0x58, 0xec, 0x00, 0x00, 0xf8, 0x45, 0x26, 0x00, 0x00, 0x00, 0xf8, 0x45, 0x26, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x51, 0x88, 0x10, 0x3f, 0x16, 0xde, 0x95, 0x3e, 0x9c, 0xf9, 0x55, 0xbd, 0xae, 0xf0, 0x2e, 0xbd, 0x2f, 0x6e, 0xa3, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00}; + +Pyramid::Filters::Filters() +{ + num_filters=(int)sizeof(tp6_filter_file_data)/sizeof(filtre); + filters = reinterpret_cast<const filtre*>(tp6_filter_file_data); +} + +Pyramid::Filters::~Filters() +{ + if( filters != NULL ) { +// delete[] filters; + } +} + +bool Pyramid::Filters::getFromPos( int pos, filtre &to_fill ) { + bool found = false; + if( pos >= 0 && pos < num_filters ) { + found = true; + copy_filter( filters[pos], to_fill ); + } + return found; +} + +bool Filters::getFromName( const char *name, filtre &to_fill ) { + bool found = false; + if( strcmp( name, "default - gaussien" ) == 0 ) { + found = true; + getDefault( to_fill ); + } + else { + int counter = 0; + for( counter=0; counter< num_filters && !found; counter++ ) { + if( strcmp( name, filters[counter].nom_f ) == 0 ) { + found = true; + copy_filter( filters[counter], to_fill ); + } + } + } + return found; +} + +int Filters::size() { + return num_filters; +} + +void Filters::copy_filter(const filtre &source, filtre &dest ) { + int counter; + for( counter=0; counter< 30; counter++ ) { + dest.nom_f[counter] = source.nom_f[counter]; + } + for( counter=0; counter< 10; counter++ ) { + dest.coeff_f[counter] = source.coeff_f[counter]; + } + dest.taille_f = source.taille_f; +} + +void Filters::getDefault( filtre &to_fill ) { + strcpy( to_fill.nom_f, "default - gaussien" ); + to_fill.taille_f = (float)2; + to_fill.coeff_f[0] = (float)0.4; + to_fill.coeff_f[1] = (float)0.25; + to_fill.coeff_f[2] = (float)0.05; +} + +/*--------------------------------------------------------------------------- + Cration de l'tage suivant de la pyramide Gaussienne +---------------------------------------------------------------------------*/ +void Pyramid::etage_suiv_g(const uint8_t *srcTab, uint8_t *dstTab, int srcWidth, int srcHeight, filtre &utile) +{ + cout << "etage_suiv_g " << srcWidth << " " << srcHeight << " " << endl; + cout << "src = " << (uintptr_t)srcTab << " dst = " << (uintptr_t)dstTab << endl; + int dstWidth = srcWidth / 2, dstHeight = srcHeight / 2; + uint8_t* intermed = new uint8_t[dstWidth * srcHeight]; + for(int j = 0; j < srcHeight; ++j) + { + for(int i = 0; i < dstWidth; ++i) + { + intermed[i + j * dstWidth] = filt_point_1d_lg(srcTab, srcWidth, 2 * i, j, utile); +// intermed[i + j * dstWidth] = srcTab[2*i + j * srcWidth]; + } + } + for(int i = 0; i < dstWidth; ++i) + { + for(int j = 0; j < dstHeight; ++j) + { + dstTab[i + j * dstWidth] = filt_point_1d_cl(intermed, srcHeight, dstWidth, i, j * 2, utile); +// dstTab[i + j * dstWidth] = intermed[i + 2 * j * dstWidth]; + } + } + delete intermed; +} + +/*--------------------------------------------------------------------------- + Cration d'une pyramide Gaussienne jusqu'au nime tage +---------------------------------------------------------------------------*/ +void Pyramid::pyram_g_n(uint8_t *rep, int nStage, long nbc, long nbl, const uint8_t *itab, filtre &utile) +{ + cout << "pyram_g_n " << nStage << " " << nbc << " " << nbl << endl; + int taille_c=nbc; + int taille_l=nbl; + const int size = nbc * nbl; + for(int i = 0; i < size; ++i) + { + rep[i] = itab[i]; + } + + int j = 0; + for(int fin = nStage; fin > 0 ; --fin) + { + etage_suiv_g((rep+j),(rep+j+taille_c*taille_l),taille_c,taille_l,utile); + j=j+taille_c*taille_l; + taille_l=taille_l/2; + taille_c=taille_c/2; + } +} + +/*--------------------------------------------------------------------------- + Cration d'une pyramide Laplacienne jusqu'au nime tage +---------------------------------------------------------------------------*/ +void Pyramid::pyram_l_n (uint8_t *rep,int n, long nbc, long nbl, const uint8_t *itab, filtre &utile) +{ + int i; + int j=0; + int fin=n; + int taille_c=nbc; + int taille_l=nbl; + uint8_t* pyra1 = new uint8_t[nbc*nbc*2]; + + pyram_g_n(pyra1,fin, nbc, nbl, itab, utile); + do + { + agrandir((pyra1+j+taille_c*taille_l),(rep+j),taille_c/2,taille_l/2,utile); + + for(i=j;i<j+taille_c*taille_l;i++) + { + /* this overflow is important ! */ + int n = 0; + n = n + pyra1[i]; + n = n - rep[i]; + if(n < -127) n = -127; + if(n > 128) n = 128; +// if(n > 255) n = 255; +// if(n < 0) n = 0; + rep[i] = n; + } + + j=j+taille_c*taille_l; + taille_c=taille_c/2; + taille_l=taille_l/2; + fin--; + }while(fin>0); + for(i=j;i<j+taille_c*taille_l;i++) + { + *(rep+i)=*(pyra1+i); + } + delete[] pyra1; +} + + +/*--------------------------------------------------------------------------- + Cration d'une pyramide Gaussienne avec entre en conversationnel + des diffrentes proprits de cette pyramide +---------------------------------------------------------------------------*/ +Image *Pyramid::pyram_g(const GrayscaleImage *im, int etage_f, filtre &utile, string &to_print) +{ + if(!( im != NULL )) { + throw "Error in Pyramid::pyram_g:\nim = NULL"; + } + if(!( im->getWidth() == im->getHeight() )) { + throw "Error in Pyramid::pyram_g:\nim->getWidth() != im->getHeight()"; + } + if( !isPowerOf2(im->getWidth()) ) { + throw "Error in Pyramid::pyram_g:\nimage dimensions not a power of 2"; + } + long nbl = im->getHeight(); + long nbc = im->getWidth(); + const uint8_t* itab = im->begin(); + +// uint8_t* rep = new uint8_t[nbc * nbl * 2]; + GrayscaleImage* resImg = new GrayscaleImage(im->getWidth(), im->getHeight() * 2); + uint8_t* rep = resImg->begin(); + cout << "rep = " << (uintptr_t)rep << endl; + int temp_etage_max = etage_max( im ); + if( etage_f > temp_etage_max ) etage_f = temp_etage_max; + if( etage_f < 1 ) etage_f = 1; + + pyram_g_n(rep,etage_f,nbc,nbl,itab,utile); + to_print = entropie_p(rep,etage_f,nbc,nbl); + reconstruction(rep,etage_f,nbc,nbl); + + return resImg; +} +/*--------------------------------------------------------------------------- + Cration d'un tage de la pyramide Gaussienne +---------------------------------------------------------------------------*/ +Image *Pyramid::n_pyram_g(const Image *im, int etage_f, filtre &utile ) +{ + if(!( im != NULL )) { + throw "Error in Pyramid::pyram_g:\nim = NULL"; + } + if(!( im->getWidth() == im->getHeight() )) { + throw "Error in Pyramid::pyram_g:\nim->getWidth() != im->getHeight()"; + } + if( !isPowerOf2(im->getWidth()) ) { + throw "Error in Pyramid::pyram_g:\nimage dimensions not a power of 2"; + } + + int i; + int k=0; + int taille_c,taille_l; + long nbl = im->getHeight(); + long nbc = im->getWidth(); + const uint8_t* itab = im->begin(); + + taille_c=nbc; + taille_l=nbl; + int temp_etage_max = etage_max(im); + if( etage_f > temp_etage_max ) etage_f = temp_etage_max; + if( etage_f < 1 ) etage_f = 1; + + for(i=0;i<etage_f;i++) + { + k=k+taille_c*taille_l; + taille_c=taille_c/2; + taille_l=taille_l/2; + } + GrayscaleImage* resImg = new GrayscaleImage(taille_c, taille_l); + uint8_t* rep = resImg->begin(); + uint8_t* tab = new uint8_t[(nbc * nbc) / 2 * 3]; + pyram_g_n(tab,etage_f,nbc,nbl,itab,utile); + for(i=0;i<taille_c*taille_l;i++) + { + rep[i] = tab[i+k]; + } + delete[] tab; + return resImg; +} +/*--------------------------------------------------------------------------- + Cration d'une pyramide Laplacienne avec entre en conversationnel + des diffrentes proprits de cette pyramide +---------------------------------------------------------------------------*/ +Image *Pyramid::pyram_l (const Image *im, int etage_f, filtre &utile, string &to_print) +{ + if(!( im != NULL )) { + throw "Error in Pyramid::pyram_g:\nim = NULL"; + } + if(!( im->getWidth() == im->getHeight() )) { + throw "Error in Pyramid::pyram_g:\nim->getWidth() != im->getHeight()"; + } + if( !isPowerOf2(im->getWidth()) ) { + throw "Error in Pyramid::pyram_g:\nimage dimensions not a power of 2"; + } + long nbl = im->getHeight(); + long nbc = im->getWidth(); + const uint8_t* itab = im->begin(); + +// uint8_t* rep = new uint8_t[nbc * nbl * 2]; + GrayscaleImage* resImg = new GrayscaleImage(im->getWidth(), im->getHeight() * 2); + uint8_t* rep = resImg->begin(); + int temp_etage_max = etage_max( im ); + if( etage_f > temp_etage_max ) etage_f = temp_etage_max; + if( etage_f < 1 ) etage_f = 1; + + pyram_l_n(rep,etage_f,nbc,nbl,itab,utile); + to_print = entropie_p(rep,etage_f,nbc,nbl); + reconstruction(rep,etage_f,nbc,nbl); + + return resImg; + +} +/*--------------------------------------------------------------------------- + Cration d'un tage de la pyramide Laplacienne +---------------------------------------------------------------------------*/ +Image *Pyramid::n_pyram_l(const Image *im, int etage_f, filtre &utile) +{ + if(!( im != NULL )) { + throw "Error in Pyramid::pyram_g:\nim = NULL"; + } + if(!( im->getWidth() == im->getHeight() )) { + throw "Error in Pyramid::pyram_g:\nim->getWidth() != im->getHeight()"; + } + if( !isPowerOf2(im->getWidth()) ) { + throw "Error in Pyramid::pyram_g:\nimage dimensions not a power of 2"; + } + + int i; + int k=0; + int taille_c,taille_l; + long nbl = im->getHeight(); + long nbc = im->getWidth(); + const uint8_t* itab = im->begin(); + + taille_c=nbc; + taille_l=nbl; + int temp_etage_max = etage_max(im) - 1; + if( etage_f > temp_etage_max ) etage_f = temp_etage_max; + if( etage_f < 0 ) etage_f = 0; + + for(i=0;i<etage_f;i++) + { + k=k+taille_c*taille_l; + taille_c=taille_c/2; + taille_l=taille_l/2; + } + GrayscaleImage* resImg = new GrayscaleImage(taille_c, taille_l); + uint8_t* rep = resImg->begin(); + uint8_t* tab = new uint8_t[(nbc * nbc) / 2 * 3]; + pyram_g_n(tab,etage_f,nbc,nbl,itab,utile); + pyram_l_n(tab,etage_f+1,nbc,nbl,itab,utile); + for(i=0;i<taille_c*taille_l;i++) + { + rep[i] = tab[i+k]; + } + delete[] tab; + return resImg; +} + + + +/*--------------------------------------------------------------------------- + Filtrage d'un point de l'image suivant une ligne +---------------------------------------------------------------------------*/ +uint8_t Pyramid::filt_point_1d_lg(const uint8_t *tab,int cl, int x, int y, filtre &utile) +{ + float partiel=0.; + int i; + int j; + j=utile.taille_f; + if(x-j<0) + { + for(i=-j;i<=j;i++) + { + if(x+i<0) + partiel += *(tab+y*cl+x-i)*utile.coeff_f[-i]; + else if(i<0) + partiel += *(tab+y*cl+x+i)*utile.coeff_f[-i]; + else + partiel += *(tab+y*cl+x+i)*utile.coeff_f[i]; + } + }else if(x+j<cl) + { + for(i=-j;i<=j;i++) + { + if(i<0) + partiel += *(tab+y*cl+x+i)*utile.coeff_f[-i]; + else + partiel += *(tab+y*cl+x+i)*utile.coeff_f[i]; + } + } + else + { + for(i=-j;i<=j;i++) + { + if(i<0) + partiel += *(tab+y*cl+x+i)*utile.coeff_f[-i]; + else if(i+x<cl) + partiel += *(tab+y*cl+x+i)*utile.coeff_f[i]; + else + partiel += *(tab+y*cl+x-i)*utile.coeff_f[i]; + } + } + return((uint8_t)partiel); +} + +/*--------------------------------------------------------------------------- + Filtrage d'un point de l'image suivant une colonne +---------------------------------------------------------------------------*/ +uint8_t Pyramid::filt_point_1d_cl(const uint8_t *tab,int lg,int cl, int x, int y, filtre &utile) +{ + float partiel=0.; + int i; + int j=utile.taille_f; + if(y-j<0) + { + for(i=-j;i<=j;i++) + { + if(y+i<0) + partiel += *(tab+x+(y-i)*cl)*utile.coeff_f[-i]; + else if(i<0) + partiel += *(tab+x+(y+i)*cl)*utile.coeff_f[-i]; + else + partiel += *(tab+x+(y+i)*cl)*utile.coeff_f[i]; + } + }else if(y+j<lg) + { + for(i=-j;i<=j;i++) + { + if(i<0) + partiel += *(tab+x+(y+i)*cl)*utile.coeff_f[-i]; + else + partiel += *(tab+x+(y+i)*cl)*utile.coeff_f[i]; + } + } + else + { + for(i=-j;i<=j;i++) + { + if(i<0) + partiel += *(tab+x+(y+i)*cl)*utile.coeff_f[-i]; + else if(i+y<cl) + partiel += *(tab+x+(y+i)*cl)*utile.coeff_f[i]; + else + partiel += *(tab+x+(y-i)*cl)*utile.coeff_f[i]; + } + } + return((uint8_t)partiel); +} +/*--------------------------------------------------------------------------- + Filtrage d'une ligne +---------------------------------------------------------------------------*/ +void Pyramid::filt_ligne(uint8_t *ligne,int taille_c, filtre &utile) +{ + int i; + uint8_t *intermed; + intermed=(uint8_t*)calloc(taille_c,sizeof(uint8_t)); + for(i=0;i<taille_c;i++) + { + *(intermed+i)=filt_point_1d_lg(ligne,taille_c,i,0,utile); + } + for(i=0;i<taille_c;i++) + { + *(ligne+i)=*(intermed+i); + } + free(intermed); +} +/*--------------------------------------------------------------------------- + Filtrage d'une image suivant les colonnes +---------------------------------------------------------------------------*/ +void Pyramid::filt_tab_cl(uint8_t *tab,int taille_c,int taille_l, filtre &utile) +{ + int i,j; + uint8_t *intermed; + intermed=(uint8_t*)calloc(taille_c*taille_l,sizeof(uint8_t)); + for(j=0;j<taille_l;j++) + { + for(i=0;i<taille_c;i++) + { + *(intermed+i+j*taille_c)=filt_point_1d_cl(tab,taille_l,taille_c,i,j,utile); + } + } + for(j=0;j<taille_l;j++) + { + for(i=0;i<taille_c;i++) + { + *(tab+i+j*taille_c)= *(intermed+i+j*taille_c) * 4; + } + } + free(intermed); +} + +/*--------------------------------------------------------------------------- + Agrandissement d'une image (avec filtrage) +---------------------------------------------------------------------------*/ +void Pyramid::agrandir(uint8_t *petit,uint8_t *grand,int taille_c,int taille_l, filtre &utile) +{ + int i,j; + uint8_t *intermed; + intermed=(uint8_t*)calloc(taille_c*taille_l*2,sizeof(uint8_t)); + for(j=0;j<taille_l;j++) + { + for(i=0;i<taille_c;i++) + { + *(intermed+i*2+j*taille_c*2)=*(petit+i+j*taille_c); + *(intermed+i*2+j*taille_c*2+1)=0; + } + } + for(j=0;j<taille_l;j++) + { + filt_ligne((intermed+j*taille_c*2),taille_c*2,utile); + } + for(j=0;j<taille_l;j++) + { + for(i=0;i<taille_c*2;i++) + { + *(grand+i+(j*2)*taille_c*2)=*(intermed+i+j*taille_c*2); + *(grand+i+(j*2+1)*taille_c*2)=0; + } + } + filt_tab_cl(grand,taille_c*2,taille_l*2,utile); + free(intermed); +} + +/*--------------------------------------------------------------------------- + Rarangement de la pyramide +---------------------------------------------------------------------------*/ + +void Pyramid::reconstruction(uint8_t *pyra,int n, long nbc, long nbl) +{ + int i,j,k; + int q=0; + int p=0; + int fin=n; + int taille_c=nbc; + int taille_l=nbl; + uint8_t *intermed; + intermed=(uint8_t*)calloc(nbc*nbl,sizeof(uint8_t)); + do + { + q=q+taille_c*taille_l; + taille_c=taille_c/2; + taille_l=taille_l/2; + k=0; + for(j=p;j<p+taille_l;j++) + { + for(i=0;i<taille_c;i++) + { + *(intermed+j*nbc+i)=*(pyra+k+q); + k++; + } + } + p=p+taille_l; + fin--; + }while(fin>0); + for(i=0;i<nbc*nbl;i++) + { + *(pyra+nbc*nbl+i)=*(intermed+i); + } + free(intermed); +} + +int Pyramid::etage_max(const Image *im) +{ + int i; + int taille_c=im->getWidth(); + int taille_l=im->getHeight(); + for(i=0;taille_c||taille_l>1;i++) + { + taille_c=taille_c/2; + taille_l=taille_l/2; + } + i--; + return(i); +} + +/*---------------------------------------------------------------------- + Calcul de l'entropie d'une image donne en paramtre, + la fonction retourne la valeur de l'entropie. +----------------------------------------------------------------------*/ +float Pyramid::entropie2(const uint8_t *tab,int taille_c,int taille_l) +{ + int i,j; + float pi[256],h=0; + int size; + + size=taille_c*taille_l; + +/**********************************************************************/ +/* module de traitement */ +/**********************************************************************/ + +/* initialisation 0 du tableau pi contenant l'histogramme */ + for(i=0 ; i<256 ; i++) + pi[i] = 0; + +/* calcul de l'histogramme de l'image */ + for(i=0 ; i<taille_l ; i++) + for(j=0 ; j<taille_c ; j++) + pi[*(tab+ i*taille_c +j)]++; + +/* calcul de l'entropie de l'image */ + for(i=0 ; i<256 ; i++) + { + if(pi[i] != 0) + { + pi[i] /= size; + h -= (double)pi[i] * log((double)pi[i])/log((double)2.0); + } + } + return(h); +} + +/*---------------------------------------------------------------------- + Calcul et affichage de l'entropie des diffrents tages d'une pyramide +----------------------------------------------------------------------*/ +string Pyramid::entropie_p(const uint8_t *pyra,int etage_f,int nbc,int nbl) +{ + int i; + int j=0; + float h; + int taille_c=nbc; + int taille_l=nbl; + char buffer[255]; + string returnval; + for(i=0;i<=etage_f;i++) + { + h=entropie2((pyra+j),taille_c,taille_l); + j=j+taille_c*taille_l; + taille_c=taille_c/2; + taille_l=taille_l/2; + sprintf(buffer, "L'entropie de l'tage %d est %1f\n",i,h); + returnval = returnval + buffer; + } + return returnval; +} + + +Image *Pyramid::rebuild_interface( const Image *pyramid, int etage_f, int pyramid_to, filtre &utile ) { + // rebuilds from an image that was saved + // etage_f = stage that the original image was built to + char buffer[255]; + if(!pyramid) { + throw "Error in TP6Pyramid::rebuild_interface:\npyramid = NULL"; + } + if(pyramid->getWidth() * 2 != pyramid->getHeight()) { + sprintf( buffer, "Error in TP6Pyramid::rebuild_interface:\npyramid->getWidth = %d, pyramid->getHeight = %d", pyramid->getWidth(), pyramid->getHeight() ); + throw buffer; + } + if(!(isPowerOf2(pyramid->getWidth()))) { + throw "Error in TP6Pyramid::rebuild_interface:\npyramid->getWidth not a power of 2"; + } + if( etage_f <= 0 || (1 << etage_f) > pyramid->getWidth() ) { + throw "Error in TP6Pyramid::rebuild_interface:\nInvalid etage_f specified"; + } + if(pyramid_to < 0 || pyramid_to >= etage_f) { + throw "Error in TP6Pyramid::rebuild_interface:\nInvalid pyramid_to specified"; + } + long nbc = pyramid->getWidth(); + long nbl = pyramid->getWidth(); + int i; + int j=0; + int taille_c=nbc; + int taille_l=nbl; + Image *returnval = NULL; + int taille; + int q=0; + int etage_rec; + const uint8_t *pyra1 = pyramid->begin(); + uint8_t* intermed = new uint8_t[nbc * nbc / 2 * 3]; + uint8_t* rep = new uint8_t[nbc * nbc / 2 * 3]; + + // Copy info into rep in a packed format + long current_offset = 0; + long current_rep_offset = 0; + for(int n = 0; n <= etage_f; ++n) { + for(int j=0; j< taille_l; j++ ) { + for(int i=0; i< taille_c; i++ ) { + rep[current_rep_offset + j * taille_c + i] = pyra1[current_offset + j * pyramid->getWidth() + i]; + } + } + current_offset = current_offset + taille_l * nbc; + current_rep_offset = current_rep_offset + taille_l * taille_c; + taille_l = taille_l / 2; + taille_c = taille_c / 2; + } + +/* reconstruction de l'image partir de sa pyramide laplacienne en s'arretant + un niveau etage_rec choisi par l'utilisateur + La pyramide est contenue dans la zone mmoire pointe par rep */ + etage_rec = pyramid_to; + taille=nbc; + + for(i=0;i<etage_f;i++) + { + q=q+taille*taille; + taille=taille/2; + } + for(i=q;i<q+taille*taille;i++) + { + *(intermed+i)=*(rep+i); + } + for(i=etage_f;i>etage_rec;i--) + { + agrandir((intermed+q),(intermed+q-taille*taille*4),taille,taille,utile); + taille=taille*2; + q=q-taille*taille; + for(j=q;j<q+taille*taille;j++) + { + int value = rep[j]; + if(value > 128) value = value - 256; + value = value + intermed[j]; + if(value < 0) value = 0; + if(value > 255) value = 255; + intermed[j] = value; + } + } + //printf("Entrez le nom du fichier de l'image reconstruite :"); + //scanf("%s",nom); + //ecrire_image((intermed+q),nom,taille,taille); + returnval = new GrayscaleImage(taille, taille, intermed+q); + free(intermed); + free(rep); + return returnval; +} diff --git a/app/Algorithms/Pyramid.h b/app/Algorithms/Pyramid.h new file mode 100644 index 0000000000000000000000000000000000000000..4ff543347cae1d025a8efe1b97777292a2d7beb9 --- /dev/null +++ b/app/Algorithms/Pyramid.h @@ -0,0 +1,73 @@ +/* + * Copyright 2011-2012 INSA Rennes + * + * This file is part of EIImage. + * + * EIImage is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * EIImage 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with EIImage. If not, see <http://www.gnu.org/licenses/>. +*/ + +#ifndef PYRAMID_H +#define PYRAMID_H + +#include <Image.h> +#include <GrayscaleImage.h> +#include <string> + +namespace Pyramid +{ + inline bool isPowerOf2(int n) { + return ( ( n > 0 ) && ( (n & (n - 1) ) == 0) ); + } + + struct filtre { + char nom_f[30]; + float coeff_f[10]; + int taille_f; + }; + + class Filters + { + public: + Filters(); + virtual ~Filters(); + bool getFromPos( int pos, filtre &to_fill ); + bool getFromName( const char *name, filtre &to_fill ); + void getDefault( filtre &to_fill ); + int size(); + private: + const filtre *filters; + int num_filters; + void copy_filter( const filtre &source, filtre &dest ); + }; + + void etage_suiv_g(const uint8_t *srcTab, uint8_t *dstTab, int srcWidth, int srcHeight, filtre &utile); + void pyram_g_n(uint8_t *rep, int nStage, long nbc, long nbl, const uint8_t *itab, filtre &utile); + void pyram_l_n (uint8_t *rep,int n, long nbc, long nbl, const uint8_t *itab, filtre &utile); + imagein::Image *pyram_g(const imagein::GrayscaleImage *im, int etage_f, filtre &utile, std::string &to_print); + imagein::Image *n_pyram_g(const imagein::Image *im, int etage_f, filtre &utile ); + imagein::Image *pyram_l (const imagein::Image *im, int etage_f, filtre &utile, std::string &to_print); + imagein::Image *n_pyram_l(const imagein::Image *im, int etage_f, filtre &utile); + uint8_t filt_point_1d_lg(const uint8_t *tab,int cl, int x, int y, filtre &utile); + uint8_t filt_point_1d_cl(const uint8_t *tab,int lg,int cl, int x, int y, filtre &utile); + void filt_ligne(uint8_t *ligne,int taille_c, filtre &utile); + void filt_tab_cl(uint8_t *tab,int taille_c,int taille_l, filtre &utile); + void agrandir(uint8_t *petit,uint8_t *grand,int taille_c,int taille_l, filtre &utile); + void reconstruction(uint8_t *pyra,int n, long nbc, long nbl); + int etage_max(const imagein::Image *im); + float entropie2(const uint8_t *tab,int taille_c,int taille_l); + std::string entropie_p(const uint8_t *pyra,int etage_f,int nbc,int nbl); + imagein::Image* rebuild_interface(const imagein::Image *to_rebuild, int etage_f, int to_rebuild_to, filtre &utile ); +} + +#endif // PYRAMID_H diff --git a/app/Operations/BFlitOp.cpp b/app/Operations/BFlitOp.cpp index 4b00b9e90e706e05b54d46795f4bef31c06d7cea..ac6b2f215a09b1987d8320ee7f5f67982f22bd1d 100644 --- a/app/Operations/BFlitOp.cpp +++ b/app/Operations/BFlitOp.cpp @@ -34,7 +34,7 @@ using namespace std; using namespace imagein; -BFlitOp::BFlitOp() : Operation(Tools::tr("BFlit").toStdString()) +BFlitOp::BFlitOp() : Operation(qApp->translate("Operations", "BFilt").toStdString()) { } @@ -46,7 +46,7 @@ Image* bflit(const Image* image, unsigned int nPointSide, unsigned int nIteratio void BFlitOp::operator()(const imagein::Image* image, const std::map<const imagein::Image*, std::string>&) { QDialog* dialog = new QDialog(); - dialog->setWindowTitle(dialog->tr("Parameters")); + dialog->setWindowTitle(qApp->translate("Operations", "Parameters")); dialog->setMinimumWidth(180); QFormLayout* layout = new QFormLayout(dialog); @@ -56,10 +56,10 @@ void BFlitOp::operator()(const imagein::Image* image, const std::map<const image nPointBox->setRange(0, nPointImg/2-1); nPointBox->setValue(nPointImg/4); nIterBox->setValue(1); - layout->insertRow(0, "Number of point on each side : ", nPointBox); - layout->insertRow(1, "Number of iteration : ", nIterBox); + layout->insertRow(0, qApp->translate("BFlit", "Number of point on each side : "), nPointBox); + layout->insertRow(1, qApp->translate("BFlit", "Number of iteration : "), nIterBox); - QPushButton *okButton = new QPushButton(dialog->tr("Validate"), dialog); + QPushButton *okButton = new QPushButton(qApp->translate("Operations", "Validate"), dialog); okButton->setDefault(true); layout->addWidget(okButton); QObject::connect(okButton, SIGNAL(clicked()), dialog, SLOT(accept())); diff --git a/app/Operations/CenterOp.cpp b/app/Operations/CenterOp.cpp index 3884c8a3d729714cb81ac7d681591f1b1ff99cbf..9780e78bddf9361373ce3de51cf7496edca6eec2 100644 --- a/app/Operations/CenterOp.cpp +++ b/app/Operations/CenterOp.cpp @@ -22,8 +22,6 @@ #include <Operation.h> #include <Image.h> -#include <ImgWidget.h> - #include "CenterOp.h" @@ -31,7 +29,7 @@ using namespace std; using namespace imagein; -CenterOp::CenterOp() : Operation(tr("Center").toStdString()) +CenterOp::CenterOp() : Operation(qApp->translate("Operations", "Center").toStdString()) { } @@ -71,6 +69,6 @@ void CenterOp::operator()(const imagein::Image* image, const std::map<const imag } } - this->outImage(resImg, " - centered"); + this->outImage(resImg, qApp->translate("CenterOp", "centered").toStdString()); } diff --git a/app/Operations/CenterOp.h b/app/Operations/CenterOp.h index 1ad882a7bdae50ba6df911757374e37d69f6233a..aa7af1e80819e938ce17dcacf924523c54c2c694 100644 --- a/app/Operations/CenterOp.h +++ b/app/Operations/CenterOp.h @@ -33,8 +33,6 @@ public: void operator()(const imagein::Image*, const std::map<const imagein::Image*, std::string>&); - static QString tr(const char* str) { return QApplication::tr(str); } - bool needCurrentImg() const; }; diff --git a/app/Operations/ClassAnalysisDialog.cpp b/app/Operations/ClassAnalysisDialog.cpp new file mode 100644 index 0000000000000000000000000000000000000000..438356e35bf1bca16800e438dd69eb670a278de9 --- /dev/null +++ b/app/Operations/ClassAnalysisDialog.cpp @@ -0,0 +1,99 @@ +/* + * Copyright 2011-2012 INSA Rennes + * + * This file is part of EIImage. + * + * EIImage is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * EIImage 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with EIImage. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include "ClassAnalysisDialog.h" +#include "ui_ClassAnalysisDialog.h" +#include <QFileDialog> + +using namespace std; +using namespace imagein; + +ClassAnalysisDialog::ClassAnalysisDialog(QWidget *parent, const imagein::Image* img) : + QDialog(parent), + ui(new Ui::ClassAnalysisDialog) +{ + + _imgZoneSelector = new ImageZoneSelector(this, new Image(*img)); + ui->setupUi(this); + ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(false); + _label = new QLabel(tr("Please select the image's area to classify :")); + ui->formLayout->addRow(_label); + ui->formLayout->addRow(_imgZoneSelector); + this->adjustSize(); + ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(false); + connect(_imgZoneSelector, SIGNAL(selectionEmptinessChanged()), this, SLOT(checkData())); +} + +ClassAnalysisDialog::~ClassAnalysisDialog() +{ + delete ui; +} + +void ClassAnalysisDialog::on_fileButton_clicked() +{ + QString filename; + if(isLearningStep()) { + filename = QFileDialog::getSaveFileName(this, "Save classification file", "", "Classification files (*.cff)"); + } + else { + filename = QFileDialog::getOpenFileName(this, "Open classification file", "", "Classification files (*.cff)"); + } + ui->fileEdit->setText(filename); +} + +void ClassAnalysisDialog::on_fileEdit_textChanged(QString /*str*/) { +// ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(!str.isEmpty()); + this->checkData(); +} + +bool ClassAnalysisDialog::isLearningStep() const { + return ui->stepBox->currentIndex() == 0; +} + +bool ClassAnalysisDialog::isClassificationStep() const { + return ui->stepBox->currentIndex() == 1; +} +QString ClassAnalysisDialog::getFileName() const { + return ui->fileEdit->text(); +} + +int ClassAnalysisDialog::getWindowSize() const { + return ui->windowBox->value(); +} + +void ClassAnalysisDialog::on_stepBox_currentIndexChanged(int i) { + _imgZoneSelector->setVisible(i == 0); + _label->setVisible(i == 0); + ui->formLayout->invalidate(); + ui->windowBox->setEnabled(i != 2); + ui->windowLabel->setEnabled(i != 2); + this->adjustSize(); +} + +vector<Rectangle> ClassAnalysisDialog::getSelections() const { + return _imgZoneSelector->getSelections(); +} + +void ClassAnalysisDialog::checkData() { + bool ok = !ui->fileEdit->text().isEmpty(); + if(this->isLearningStep()) { + ok &= !_imgZoneSelector->isSelectionEmpty(); + } + ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(ok); +} diff --git a/app/Operations/ClassAnalysisDialog.h b/app/Operations/ClassAnalysisDialog.h new file mode 100644 index 0000000000000000000000000000000000000000..148563fceb0561514686b8edd59e5e50cb1053f5 --- /dev/null +++ b/app/Operations/ClassAnalysisDialog.h @@ -0,0 +1,57 @@ +/* + * Copyright 2011-2012 INSA Rennes + * + * This file is part of EIImage. + * + * EIImage is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * EIImage 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with EIImage. If not, see <http://www.gnu.org/licenses/>. +*/ + +#ifndef CLASSANALYSISDIALOG_H +#define CLASSANALYSISDIALOG_H + +#include <QDialog> +#include "../Widgets/ImageZoneSelector.h" + +namespace Ui { +class ClassAnalysisDialog; +} + +class ClassAnalysisDialog : public QDialog +{ + Q_OBJECT + +public: + explicit ClassAnalysisDialog(QWidget *parent, const Image *img); + ~ClassAnalysisDialog(); + bool isLearningStep() const; + bool isClassificationStep() const; + QString getFileName() const; + int getWindowSize() const; + std::vector<imagein::Rectangle> getSelections() const; + +public slots: + void on_fileEdit_textChanged(QString); + +private slots: + void checkData(); + void on_fileButton_clicked(); + void on_stepBox_currentIndexChanged(int); + +private: + Ui::ClassAnalysisDialog *ui; + ImageZoneSelector* _imgZoneSelector; + QLabel* _label; +}; + +#endif // CLASSANALYSISDIALOG_H diff --git a/app/Operations/ClassAnalysisDialog.ui b/app/Operations/ClassAnalysisDialog.ui new file mode 100644 index 0000000000000000000000000000000000000000..9af2a73f5e3c286e6ed390188b0e84addca49e99 --- /dev/null +++ b/app/Operations/ClassAnalysisDialog.ui @@ -0,0 +1,138 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>ClassAnalysisDialog</class> + <widget class="QDialog" name="ClassAnalysisDialog"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>400</width> + <height>300</height> + </rect> + </property> + <property name="windowTitle"> + <string>Class analysis</string> + </property> + <layout class="QVBoxLayout" name="verticalLayout"> + <item> + <layout class="QFormLayout" name="formLayout"> + <item row="0" column="0"> + <widget class="QLabel" name="stepLabel"> + <property name="text"> + <string>Step : </string> + </property> + </widget> + </item> + <item row="0" column="1"> + <widget class="QComboBox" name="stepBox"> + <item> + <property name="text"> + <string>Learning step</string> + </property> + </item> + <item> + <property name="text"> + <string>Classification step</string> + </property> + </item> + <item> + <property name="text"> + <string>Print file info</string> + </property> + </item> + </widget> + </item> + <item row="1" column="0"> + <widget class="QLabel" name="windowLabel"> + <property name="text"> + <string>Window size : </string> + </property> + </widget> + </item> + <item row="1" column="1"> + <widget class="QSpinBox" name="windowBox"> + <property name="minimum"> + <number>3</number> + </property> + <property name="maximum"> + <number>15</number> + </property> + <property name="singleStep"> + <number>2</number> + </property> + <property name="value"> + <number>7</number> + </property> + </widget> + </item> + <item row="2" column="0"> + <widget class="QLabel" name="fileLabel"> + <property name="text"> + <string>File : </string> + </property> + </widget> + </item> + <item row="2" column="1"> + <layout class="QHBoxLayout" name="horizontalLayout"> + <item> + <widget class="QLineEdit" name="fileEdit"/> + </item> + <item> + <widget class="QPushButton" name="fileButton"> + <property name="text"> + <string>browse</string> + </property> + </widget> + </item> + </layout> + </item> + </layout> + </item> + <item> + <widget class="QDialogButtonBox" name="buttonBox"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="standardButtons"> + <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set> + </property> + </widget> + </item> + </layout> + </widget> + <resources/> + <connections> + <connection> + <sender>buttonBox</sender> + <signal>accepted()</signal> + <receiver>ClassAnalysisDialog</receiver> + <slot>accept()</slot> + <hints> + <hint type="sourcelabel"> + <x>248</x> + <y>254</y> + </hint> + <hint type="destinationlabel"> + <x>157</x> + <y>274</y> + </hint> + </hints> + </connection> + <connection> + <sender>buttonBox</sender> + <signal>rejected()</signal> + <receiver>ClassAnalysisDialog</receiver> + <slot>reject()</slot> + <hints> + <hint type="sourcelabel"> + <x>316</x> + <y>260</y> + </hint> + <hint type="destinationlabel"> + <x>286</x> + <y>274</y> + </hint> + </hints> + </connection> + </connections> +</ui> diff --git a/app/Operations/ClassAnalysisOp.cpp b/app/Operations/ClassAnalysisOp.cpp new file mode 100644 index 0000000000000000000000000000000000000000..f19a6d5f36a63ec667b048f46c9ce2eaeac2a4ae --- /dev/null +++ b/app/Operations/ClassAnalysisOp.cpp @@ -0,0 +1,106 @@ +/* + * Copyright 2011-2012 INSA Rennes + * + * This file is part of EIImage. + * + * EIImage is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * EIImage 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with EIImage. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include "ClassAnalysisOp.h" +#include <QApplication> +#include "ClassAnalysisDialog.h" +#include "../Algorithms/ClassAnalysis.h" + +#include <cstdio> +#include <Converter.h> +#include <GrayscaleImage.h> +#include <QMessageBox> + +using namespace std; +using namespace imagein; + +ClassAnalysisOp::ClassAnalysisOp() : Operation(qApp->translate("Operations", "Supervised classification").toStdString()) +{ +} + +bool ClassAnalysisOp::needCurrentImg() const { + return true; +} + +void ClassAnalysisOp::operator()(const imagein::Image* img, const std::map<const imagein::Image*, std::string>&) { + + ClassAnalysisDialog* dialog = new ClassAnalysisDialog(QApplication::activeWindow(), img); + QDialog::DialogCode code = static_cast<QDialog::DialogCode>(dialog->exec()); + + if(code!=QDialog::Accepted) return; + + GrayscaleImage* image = Converter<GrayscaleImage>::convert(*img); + + + if(dialog->isLearningStep()) { + FILE* f = fopen(dialog->getFileName().toAscii(), "wt" ); + if(f == NULL) { + QMessageBox::critical(NULL, "Error", "Could not open file for write access"); + return; + } + try { + Image_t<double> *meanImg, *devImg; + ClassAnalysis::write_to_file(image, dialog->getSelections(), f, dialog->getWindowSize(), &meanImg, &devImg); + outDoubleImage(meanImg, qApp->translate("ClassAnalysis", "mean").toStdString()); + outDoubleImage(devImg, qApp->translate("ClassAnalysis", "standard deviation").toStdString()); + } + catch(const char*e) { + QMessageBox::critical(NULL, "Error", e); + return; + } + fclose(f); + } + else if(dialog->isClassificationStep()) { + FILE* f = fopen(dialog->getFileName().toAscii(), "rt" ); + if(f == NULL) { + QMessageBox::critical(NULL, "Error", "Could not open file for read access"); + return; + } + try { + Image_t<double> *meanImg, *devImg; + Image *resImg = ClassAnalysis::classify_from_file(image, f, dialog->getWindowSize(), &meanImg, &devImg); + outImage(resImg, qApp->translate("ClassAnalysis", "classified").toStdString()); + outDoubleImage(meanImg, qApp->translate("ClassAnalysis", "mean").toStdString()); + outDoubleImage(devImg, qApp->translate("ClassAnalysis", "standard deviation").toStdString()); + } + catch(const char*e) { + QMessageBox::critical(NULL, "Error", e); + return; + } + fclose(f); + } + else { + FILE* f = fopen(dialog->getFileName().toAscii(), "rt" ); + if(f == NULL) { + QMessageBox::critical(NULL, "Error", "Could not open file for read access"); + return; + } + try { + string s = ClassAnalysis::print_file_info(f); + outText(s); + } + catch(const char*e) { + QMessageBox::critical(NULL, "Error", e); + return; + } + fclose(f); + } + + +} diff --git a/core/ImgOutput.h b/app/Operations/ClassAnalysisOp.h similarity index 61% rename from core/ImgOutput.h rename to app/Operations/ClassAnalysisOp.h index 638beded1e5025380f4a36f41a4625865b90d33a..5ab8841bced4167f13fb39c17dcc292ea6d18169 100644 --- a/core/ImgOutput.h +++ b/app/Operations/ClassAnalysisOp.h @@ -1,41 +1,35 @@ /* * Copyright 2011-2012 INSA Rennes - * + * * This file is part of EIImage. - * + * * EIImage is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. - * + * * EIImage 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 General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with EIImage. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef EIIMAGE_IMGOUTPUT_H -#define EIIMAGE_IMGOUTPUT_H +#ifndef CLASSANALYSISOP_H +#define CLASSANALYSISOP_H -#include <vector> -#include <string> +#include <Operation.h> -#include "Image.h" -#include "Output.h" +class ClassAnalysisOp : public Operation +{ +public: + ClassAnalysisOp(); + void operator()(const imagein::Image*, const std::map<const imagein::Image*, std::string>&); -class QWidget; -class ImgOutput : public Output { - public: - ImgOutput(const imagein::Image& image); - ImgOutput(std::string name, const imagein::Image& image); - virtual QWidget* getWidget(); - ImgOutput* clone() const; - private: - imagein::Image* _img; + bool needCurrentImg() const; }; -#endif //!EIIMAGE_IMGOUTPUT_H \ No newline at end of file +#endif // CLASSANALYSISOP_H diff --git a/app/Operations/ClassResultOp.cpp b/app/Operations/ClassResultOp.cpp new file mode 100644 index 0000000000000000000000000000000000000000..fb95e2c7ec8473aa6d4aedddfd15bb7631705c2b --- /dev/null +++ b/app/Operations/ClassResultOp.cpp @@ -0,0 +1,139 @@ +/* + * Copyright 2011-2012 INSA Rennes + * + * This file is part of EIImage. + * + * EIImage is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * EIImage 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with EIImage. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include "ClassResultOp.h" +#include <QApplication> +#include <string> +#include <cstring> +#include <cstdio> +#include "../Widgets/ImageZoneSelector.h" +#include <QDialog> +#include <QVBoxLayout> +#include <QFormLayout> +#include <QDialogButtonBox> +#include <QSpinBox> +#include <QLabel> +#include <algorithm> + +using namespace std; +using namespace imagein; + +ClassResultOp::ClassResultOp() : Operation(qApp->translate("Operations", "Classification results").toStdString()) +{ +} + +bool ClassResultOp::needCurrentImg() const { + return true; +} + +void ClassResultOp::operator()(const imagein::Image* img, const std::map<const imagein::Image*, std::string>&) { + + QDialog* dialog = new QDialog(QApplication::activeWindow()); + QVBoxLayout* layout = new QVBoxLayout(dialog); + QFormLayout* formLayout = new QFormLayout(); + QSpinBox* innerBox = new QSpinBox(); + QSpinBox* borderBox = new QSpinBox(); + innerBox->setRange(0, img->getWidth()); + borderBox->setRange(0, img->getWidth()); + innerBox->setSuffix(" px"); + borderBox->setSuffix(" px"); + innerBox->setValue(8); + borderBox->setValue(2); + formLayout->insertRow(0, qApp->translate("ClassResult", "Critère de zone intérieure : "), innerBox); + formLayout->insertRow(1, qApp->translate("ClassResult", "Critère de zone frontière : "), borderBox); + layout->addWidget(new QLabel(qApp->translate("ClassResult", "<b>Critère de zones (relatifs aux zones totales) : </b>"))); + layout->addLayout(formLayout); + layout->addWidget(new QLabel(qApp->translate("ClassResult", "<b>Select the image's classes zones : </b>"))); + ImageZoneSelector* zoneSelector = new ImageZoneSelector(dialog, img); + layout->addWidget(zoneSelector); + QDialogButtonBox* buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok|QDialogButtonBox::Cancel, Qt::Horizontal, dialog); + layout->addWidget(buttonBox); + QObject::connect(buttonBox, SIGNAL(accepted()), dialog, SLOT(accept())); + QObject::connect(buttonBox, SIGNAL(rejected()), dialog, SLOT(reject())); + QDialog::DialogCode code = static_cast<QDialog::DialogCode>(dialog->exec()); + + if(code!=QDialog::Accepted) return; + + string returnval; + + int param1 = 2; + int param2 = 8; + vector<Rectangle> selection = zoneSelector->getSelections(); + int K = selection.size(); + int* classes = new int[K]; + outText(qApp->translate("ClassResult", "Voici les résultats du classement : \n").toStdString()); + outText(qApp->translate("ClassResult", "\nNombre de classes = %1 ").arg(K).toStdString()); + for(int i = 0; i < K; ++i) { + Histogram histo = img->getHistogram(0, selection.at(i)); + classes[i] = (uint8_t) (std::max_element(histo.begin(), histo.end()) - histo.begin()); + outText(qApp->translate("ClassResult", "Valeur de la classe %1 = %2").arg(i+1).arg(classes[i]).toStdString()); + } + + + //Zone frontire + double *tauxF = new double[K]; + double *tauxI = new double[K]; + for(int i = 0; i < K; ++i){ + tauxF[i] = 0.; + tauxI[i] = 0.; + } + + for(int n = 0; n < K; ++n) { + Rectangle zone = selection.at(n); + for(unsigned int j = zone.top(); j < zone.bottom(); ++j) { + for(unsigned int i = zone.left(); i < zone.right(); ++i) { + if(img->getPixelAt(i, j) == classes[n]) { + if( i >= zone.left() + param2 && i < zone.right() - param2 && j >= zone.top() + param2 && j < zone.bottom() - param2 ) { + tauxI[n]++; + } + if( i < zone.left() + param1 || i >= zone.right() - param1 || j < zone.top() + param1 || j >= zone.bottom() - param1 ) { + tauxF[n]++; + } + } + } + } + } + + for(int n = 0; n < K; ++n) { + Rectangle zone = selection.at(n); + const double areaI = (zone.h - 2*param2) * (zone.w - 2*param2); + const double areaF = (zone.h * zone.w) - (zone.h - 2*param1) * (zone.w - 2*param1); + tauxI[n] = tauxI[n] * 100. / areaI; + tauxF[n] = tauxF[n] * 100. / areaF; + } + for(int n = 0; n < K; ++n) { + outText(qApp->translate("ClassResult", "Le taux de bon classement en zone intérieure %1 vaut: %2\%").arg(n+1).arg(tauxI[n], 0, 'f', 2).toStdString()); + } + for(int n = 0; n < K; ++n) { + outText(qApp->translate("ClassResult", "Le taux de bon classement en zone frontière %1 vaut: %2\%").arg(n+1).arg(tauxF[n], 0, 'f', 2).toStdString()); + } + + double tauxGI = 0., tauxGF = 0.; + for(int i = 0; i < K; ++i){ + tauxGI += tauxI[i]; + tauxGF += tauxF[i]; + } + tauxGI /= K; + tauxGF /= K; + + outText(qApp->translate("ClassResult", "Le taux de bon classement en zone intérieure globale vaut: %1\%").arg(tauxGI, 0, 'f', 2).toStdString()); + outText(qApp->translate("ClassResult", "Le taux de bon classement en zone frontière globale vaut: %1\%").arg(tauxGF, 0, 'f', 2).toStdString()); + + outText(returnval); +} diff --git a/app/Operations/ClassResultOp.h b/app/Operations/ClassResultOp.h new file mode 100644 index 0000000000000000000000000000000000000000..f090fabb41ea32ee7370c04009020e9ab410dc9d --- /dev/null +++ b/app/Operations/ClassResultOp.h @@ -0,0 +1,35 @@ +/* + * Copyright 2011-2012 INSA Rennes + * + * This file is part of EIImage. + * + * EIImage is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * EIImage 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with EIImage. If not, see <http://www.gnu.org/licenses/>. +*/ + +#ifndef CLASSRESULTOP_H +#define CLASSRESULTOP_H + +#include <Operation.h> + +class ClassResultOp : public Operation +{ +public: + ClassResultOp(); + + void operator()(const imagein::Image*, const std::map<const imagein::Image*, std::string>&); + + bool needCurrentImg() const; +}; + +#endif // CLASSRESULTOP_H diff --git a/app/Operations/ColorDialog.cpp b/app/Operations/ColorDialog.cpp new file mode 100644 index 0000000000000000000000000000000000000000..720b749d9935172ddfe26d5c60d539aea1a42e08 --- /dev/null +++ b/app/Operations/ColorDialog.cpp @@ -0,0 +1,59 @@ +/* + * Copyright 2011-2012 INSA Rennes + * + * This file is part of EIImage. + * + * EIImage is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * EIImage 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with EIImage. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include "ColorDialog.h" +#include "ui_ColorDialog.h" + +ColorDialog::ColorDialog(QWidget *parent) : + QDialog(parent), + ui(new Ui::ColorDialog) +{ + ui->setupUi(this); + ui->hsvWidget->setVisible(false); + this->adjustSize(); +} + +ColorDialog::~ColorDialog() +{ + delete ui; +} + +QColor ColorDialog::getColor() const { + + if(ui->rgbButton->isChecked()) { + int r = ui->redBox->value(); + int g = ui->greenBox->value(); + int b = ui->blueBox->value(); + return QColor::fromRgb(r, g, b); + } + else { + int h = ui->hueBox->value(); + int s = ui->satBox->value(); + int v = ui->valBox->value(); + return QColor::fromHsv(h, s, v); + } +} + +unsigned int ColorDialog::getWidth() const { + return ui->widthBox->value(); +} + +unsigned int ColorDialog::getHeight() const { + return ui->heightBox->value(); +} diff --git a/core/ImgOutput.cpp b/app/Operations/ColorDialog.h similarity index 61% rename from core/ImgOutput.cpp rename to app/Operations/ColorDialog.h index 093ee551262baa5545a52fe1ff3992eb487a9500..e101e03f110c4410f6802430a6e3d5becd63a94f 100644 --- a/core/ImgOutput.cpp +++ b/app/Operations/ColorDialog.h @@ -1,37 +1,44 @@ /* * Copyright 2011-2012 INSA Rennes - * + * * This file is part of EIImage. - * + * * EIImage is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. - * + * * EIImage 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 General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with EIImage. If not, see <http://www.gnu.org/licenses/>. */ -#include "ImgOutput.h" -#include "ImgWidget.h" +#ifndef COLORDIALOG_H +#define COLORDIALOG_H -using namespace std; +#include <QDialog> -ImgOutput::ImgOutput(const imagein::Image& image) : Output(""), _img(new imagein::Image(image)) { -} -ImgOutput::ImgOutput(string name, const imagein::Image& image) : Output(name), _img(new imagein::Image(image)) { +namespace Ui { +class ColorDialog; } + +class ColorDialog : public QDialog +{ + Q_OBJECT -QWidget* ImgOutput::getWidget() { - return new ImgWidget(_img, _name); -} +public: + explicit ColorDialog(QWidget *parent = 0); + ~ColorDialog(); + QColor getColor() const; + unsigned int getWidth() const; + unsigned int getHeight() const; +private: + Ui::ColorDialog *ui; +}; -ImgOutput* ImgOutput::clone() const { - return new ImgOutput(*this); -} \ No newline at end of file +#endif // COLORDIALOG_H diff --git a/app/Operations/ColorDialog.ui b/app/Operations/ColorDialog.ui new file mode 100644 index 0000000000000000000000000000000000000000..27bdb6344149ec007258a396aaf7a39567ac6296 --- /dev/null +++ b/app/Operations/ColorDialog.ui @@ -0,0 +1,266 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>ColorDialog</class> + <widget class="QDialog" name="ColorDialog"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>305</width> + <height>561</height> + </rect> + </property> + <property name="windowTitle"> + <string>RGB image generator</string> + </property> + <layout class="QVBoxLayout" name="verticalLayout"> + <item> + <widget class="QGroupBox" name="groupBox_2"> + <property name="title"> + <string>Image size</string> + </property> + <layout class="QFormLayout" name="formLayout_4"> + <item row="0" column="0"> + <widget class="QLabel" name="label_7"> + <property name="text"> + <string>Width : </string> + </property> + </widget> + </item> + <item row="0" column="1"> + <widget class="QSpinBox" name="widthBox"> + <property name="maximum"> + <number>65536</number> + </property> + </widget> + </item> + <item row="1" column="0"> + <widget class="QLabel" name="label_8"> + <property name="text"> + <string>Height : </string> + </property> + </widget> + </item> + <item row="1" column="1"> + <widget class="QSpinBox" name="heightBox"> + <property name="maximum"> + <number>65536</number> + </property> + </widget> + </item> + </layout> + </widget> + </item> + <item> + <widget class="QGroupBox" name="groupBox"> + <property name="title"> + <string>Mode</string> + </property> + <layout class="QHBoxLayout" name="horizontalLayout"> + <item> + <widget class="QRadioButton" name="rgbButton"> + <property name="text"> + <string>RGB</string> + </property> + <property name="checked"> + <bool>true</bool> + </property> + </widget> + </item> + <item> + <widget class="QRadioButton" name="hsvButton"> + <property name="text"> + <string>HSV</string> + </property> + </widget> + </item> + </layout> + </widget> + </item> + <item> + <widget class="QWidget" name="rgbWidget" native="true"> + <layout class="QFormLayout" name="formLayout"> + <item row="0" column="0"> + <widget class="QLabel" name="label"> + <property name="text"> + <string>Red : </string> + </property> + </widget> + </item> + <item row="0" column="1"> + <widget class="QSpinBox" name="redBox"> + <property name="maximum"> + <number>255</number> + </property> + </widget> + </item> + <item row="1" column="0"> + <widget class="QLabel" name="label_2"> + <property name="text"> + <string>Green : </string> + </property> + </widget> + </item> + <item row="1" column="1"> + <widget class="QSpinBox" name="greenBox"> + <property name="maximum"> + <number>255</number> + </property> + </widget> + </item> + <item row="2" column="0"> + <widget class="QLabel" name="label_3"> + <property name="text"> + <string>Blue : </string> + </property> + </widget> + </item> + <item row="2" column="1"> + <widget class="QSpinBox" name="blueBox"> + <property name="minimum"> + <number>0</number> + </property> + <property name="maximum"> + <number>255</number> + </property> + </widget> + </item> + </layout> + </widget> + </item> + <item> + <widget class="QWidget" name="hsvWidget" native="true"> + <layout class="QFormLayout" name="formLayout_2"> + <property name="fieldGrowthPolicy"> + <enum>QFormLayout::AllNonFixedFieldsGrow</enum> + </property> + <item row="0" column="1"> + <widget class="QSpinBox" name="hueBox"> + <property name="maximum"> + <number>359</number> + </property> + </widget> + </item> + <item row="1" column="0"> + <widget class="QLabel" name="label_5"> + <property name="text"> + <string>Saturation : </string> + </property> + </widget> + </item> + <item row="1" column="1"> + <widget class="QSpinBox" name="satBox"> + <property name="maximum"> + <number>255</number> + </property> + </widget> + </item> + <item row="3" column="0"> + <widget class="QLabel" name="label_6"> + <property name="text"> + <string>Value : </string> + </property> + </widget> + </item> + <item row="3" column="1"> + <widget class="QSpinBox" name="valBox"> + <property name="maximum"> + <number>255</number> + </property> + </widget> + </item> + <item row="0" column="0"> + <widget class="QLabel" name="label_4"> + <property name="text"> + <string>Hue : </string> + </property> + </widget> + </item> + </layout> + </widget> + </item> + <item> + <widget class="QDialogButtonBox" name="buttonBox"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="standardButtons"> + <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set> + </property> + </widget> + </item> + </layout> + <zorder>buttonBox</zorder> + <zorder>groupBox</zorder> + <zorder>rgbWidget</zorder> + <zorder>hsvWidget</zorder> + <zorder>groupBox_2</zorder> + </widget> + <resources/> + <connections> + <connection> + <sender>buttonBox</sender> + <signal>accepted()</signal> + <receiver>ColorDialog</receiver> + <slot>accept()</slot> + <hints> + <hint type="sourcelabel"> + <x>248</x> + <y>254</y> + </hint> + <hint type="destinationlabel"> + <x>157</x> + <y>274</y> + </hint> + </hints> + </connection> + <connection> + <sender>buttonBox</sender> + <signal>rejected()</signal> + <receiver>ColorDialog</receiver> + <slot>reject()</slot> + <hints> + <hint type="sourcelabel"> + <x>316</x> + <y>260</y> + </hint> + <hint type="destinationlabel"> + <x>286</x> + <y>274</y> + </hint> + </hints> + </connection> + <connection> + <sender>rgbButton</sender> + <signal>toggled(bool)</signal> + <receiver>rgbWidget</receiver> + <slot>setVisible(bool)</slot> + <hints> + <hint type="sourcelabel"> + <x>163</x> + <y>44</y> + </hint> + <hint type="destinationlabel"> + <x>300</x> + <y>142</y> + </hint> + </hints> + </connection> + <connection> + <sender>hsvButton</sender> + <signal>toggled(bool)</signal> + <receiver>hsvWidget</receiver> + <slot>setVisible(bool)</slot> + <hints> + <hint type="sourcelabel"> + <x>445</x> + <y>44</y> + </hint> + <hint type="destinationlabel"> + <x>300</x> + <y>288</y> + </hint> + </hints> + </connection> + </connections> +</ui> diff --git a/app/Operations/ColorimetryOp.cpp b/app/Operations/ColorimetryOp.cpp index 89bf5dda99904f8adc59eb1eff585baa17d4c0e7..79965e39abb7667bd5689633f85f0ed510685642 100644 --- a/app/Operations/ColorimetryOp.cpp +++ b/app/Operations/ColorimetryOp.cpp @@ -28,8 +28,10 @@ #include <QSlider> #include <QLabel> #include <QColorDialog> +#include "ColorDialog.h" +using namespace imagein; -ColorimetryOp::ColorimetryOp() : Operation(Tools::tr("Colorimetry").toStdString()) +ColorimetryOp::ColorimetryOp() : Operation(qApp->translate("Operations", "Generate RGB image").toStdString()) { } @@ -39,80 +41,27 @@ bool ColorimetryOp::needCurrentImg() const { void ColorimetryOp::operator()(const imagein::Image*, const std::map<const imagein::Image*, std::string>&) { - QDialog* dialog = new QDialog(QApplication::activeWindow()); - dialog->setModal(false); - dialog->setWindowTitle(QString(dialog->tr("Zero crossing"))); - dialog->setMinimumWidth(180); - QGridLayout* layout = new QGridLayout(); - dialog->setLayout(layout); + ColorDialog* dialog = new ColorDialog(QApplication::activeWindow()); + dialog->setWindowTitle(QString(qApp->translate("Operations", "RGB image generator"))); - QSpinBox* redBox = new QSpinBox(); - QSpinBox* greenBox = new QSpinBox(); - QSpinBox* blueBox = new QSpinBox(); - QSpinBox* hueBox = new QSpinBox(); - QSpinBox* saturationBox = new QSpinBox(); - QSpinBox* valueBox = new QSpinBox(); - QSlider* redSlider = new QSlider(Qt::Horizontal); - QSlider* greenSlider = new QSlider(Qt::Horizontal); - QSlider* blueSlider = new QSlider(Qt::Horizontal); - QSlider* hueSlider = new QSlider(Qt::Horizontal); - QSlider* saturationSlider = new QSlider(Qt::Horizontal); - QSlider* valueSlider = new QSlider(Qt::Horizontal); - - redBox->setRange(0, 255); - greenBox->setRange(0, 255); - blueBox->setRange(0, 255); - hueBox->setRange(0, 360); - saturationBox->setRange(0, 100); - valueBox->setRange(0, 100); - redSlider->setRange(0, 255); - greenSlider->setRange(0, 255); - blueSlider->setRange(0, 255); - hueSlider->setRange(0, 360); - saturationSlider->setRange(0, 100); - valueSlider->setRange(0, 100); - layout->addWidget(new QLabel(dialog->tr("Red : ")), 0, 0); - layout->addWidget(new QLabel(dialog->tr("Green : ")), 1, 0); - layout->addWidget(new QLabel(dialog->tr("Blue : ")), 2, 0); - layout->addWidget(new QLabel(dialog->tr("Hue : ")), 3, 0); - layout->addWidget(new QLabel(dialog->tr("Saturation : ")), 4, 0); - layout->addWidget(new QLabel(dialog->tr("Value : ")), 5, 0); - layout->addWidget(redSlider, 0, 1); - layout->addWidget(greenSlider, 1, 1); - layout->addWidget(blueSlider, 2, 1); - layout->addWidget(hueSlider, 3, 1); - layout->addWidget(saturationSlider, 4, 1); - layout->addWidget(valueSlider, 5, 1); - layout->addWidget(redBox, 0, 2); - layout->addWidget(greenBox, 1, 2); - layout->addWidget(blueBox, 2, 2); - layout->addWidget(hueBox, 3, 2); - layout->addWidget(saturationBox, 4, 2); - layout->addWidget(valueBox, 5, 2); - - QObject::connect(redBox, SIGNAL(valueChanged(int)), redSlider, SLOT(setValue(int))); - QObject::connect(greenBox, SIGNAL(valueChanged(int)), greenSlider, SLOT(setValue(int))); - QObject::connect(blueBox, SIGNAL(valueChanged(int)), blueSlider, SLOT(setValue(int))); - QObject::connect(hueBox, SIGNAL(valueChanged(int)), hueSlider, SLOT(setValue(int))); - QObject::connect(saturationBox, SIGNAL(valueChanged(int)), saturationSlider, SLOT(setValue(int))); - QObject::connect(valueBox, SIGNAL(valueChanged(int)), valueSlider, SLOT(setValue(int))); - QObject::connect(redSlider, SIGNAL(valueChanged(int)), redBox, SLOT(setValue(int))); - QObject::connect(greenSlider, SIGNAL(valueChanged(int)), greenBox, SLOT(setValue(int))); - QObject::connect(blueSlider, SIGNAL(valueChanged(int)), blueBox, SLOT(setValue(int))); - QObject::connect(hueSlider, SIGNAL(valueChanged(int)), hueBox, SLOT(setValue(int))); - QObject::connect(saturationSlider, SIGNAL(valueChanged(int)), saturationBox, SLOT(setValue(int))); - QObject::connect(valueSlider, SIGNAL(valueChanged(int)), valueBox, SLOT(setValue(int))); - - QColorDialog::getColor(); - -// dialog->show(); - -// QDialogButtonBox* buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok|QDialogButtonBox::Cancel, Qt::Horizontal, dialog); -// layout->insertRow(6, buttonBox); -// QObject::connect(buttonBox, SIGNAL(accepted()), dialog, SLOT(accept())); -// QObject::connect(buttonBox, SIGNAL(rejected()), dialog, SLOT(reject())); - -// QDialog::DialogCode code = static_cast<QDialog::DialogCode>(dialog->exec()); - -// if(code!=QDialog::Accepted) return; + QDialog::DialogCode code = static_cast<QDialog::DialogCode>(dialog->exec()); + QColor color = dialog->getColor(); + if(code!=QDialog::Accepted) return; + Image* resImg = new Image(dialog->getWidth(), dialog->getHeight(), 3); + for(unsigned int j = 0; j < resImg->getHeight(); ++j) { + for(unsigned int i = 0; i < resImg->getWidth(); ++i) { + resImg->setPixelAt(i, j, 0, color.red()); + } + } + for(unsigned int j = 0; j < resImg->getHeight(); ++j) { + for(unsigned int i = 0; i < resImg->getWidth(); ++i) { + resImg->setPixelAt(i, j, 1, color.green()); + } + } + for(unsigned int j = 0; j < resImg->getHeight(); ++j) { + for(unsigned int i = 0; i < resImg->getWidth(); ++i) { + resImg->setPixelAt(i, j, 2, color.blue()); + } + } + outImage(resImg, "RGB Image"); } diff --git a/app/Operations/CombineColorOp.cpp b/app/Operations/CombineColorOp.cpp index 875b5cadbfcb7039d511c86ebb294f75cafce575..0bba5373d5c76a2977300ac53cd3f3bc29f179a5 100644 --- a/app/Operations/CombineColorOp.cpp +++ b/app/Operations/CombineColorOp.cpp @@ -27,8 +27,7 @@ #include <GrayscaleImage.h> #include <Converter.h> -#include <ImgWidget.h> -#include "ImageListBox.h" +#include <Widgets/ImageListBox.h> #include "CombineColorOp.h" #include "../Tools.h" @@ -36,7 +35,7 @@ using namespace std; using namespace imagein; -CombineColorOp::CombineColorOp() : Operation(Tools::tr("Combine color planes").toStdString()) +CombineColorOp::CombineColorOp() : Operation(qApp->translate("Operations", "Combine color planes").toStdString()) { } @@ -47,16 +46,16 @@ bool CombineColorOp::needCurrentImg() const { void CombineColorOp::operator()(const imagein::Image*, const std::map<const imagein::Image*, std::string>& imgList) { QDialog* dialog = new QDialog(); - dialog->setWindowTitle(dialog->tr("Parameters")); + dialog->setWindowTitle(qApp->translate("Operations", "Parameters")); dialog->setMinimumWidth(180); QFormLayout* layout = new QFormLayout(); dialog->setLayout(layout); - int nChannel = 3; + unsigned int nChannel = 3; ImageListBox** imageBoxes = new ImageListBox*[nChannel]; - for(int i=0; i < nChannel; ++i) { + for(unsigned int i=0; i < nChannel; ++i) { imageBoxes[i] = new ImageListBox(dialog, NULL, imgList); QLabel* label = new QLabel(Tools::colorName(i, nChannel), dialog); layout->insertRow(i, label, imageBoxes[i]); @@ -77,7 +76,9 @@ void CombineColorOp::operator()(const imagein::Image*, const std::map<const imag unsigned int maxWidth = numeric_limits<unsigned int>::max(); unsigned int maxHeight = numeric_limits<unsigned int>::max(); for(unsigned int c = 0; c < nChannel; ++c) { - channels[c] = Converter<GrayscaleImage>::convert(*imageBoxes[c]->currentImage()); + const Image* img = imageBoxes[c]->currentImage(); + if(img == NULL) return; + channels[c] = Converter<GrayscaleImage>::convert(*img); maxWidth = min(maxWidth, channels[c]->getWidth()); maxHeight = min(maxHeight, channels[c]->getHeight()); } @@ -91,5 +92,5 @@ void CombineColorOp::operator()(const imagein::Image*, const std::map<const imag } } } - this->outImage(resImg, "Reconstructed color image"); + this->outImage(resImg, qApp->translate("CombineColorOp", "Reconstructed color image").toStdString()); } diff --git a/app/Operations/CroissanceOp.cpp b/app/Operations/CroissanceOp.cpp index a0b306b8b4e3af5c806e4584ddcc60c2160f5039..495c6de0f40c7a24b796c21c8b532c053d5b6ff1 100644 --- a/app/Operations/CroissanceOp.cpp +++ b/app/Operations/CroissanceOp.cpp @@ -27,12 +27,14 @@ #include "CroissanceOp.h" #include "../Tools.h" #include "../Algorithms/Croissance.h" +#include <GrayscaleImage.h> +#include <Converter.h> using namespace std; using namespace imagein; -CroissanceOp::CroissanceOp() : Operation(Tools::tr("Croissance").toStdString()) +CroissanceOp::CroissanceOp() : Operation(qApp->translate("Operations", "Croissance").toStdString()) { } @@ -40,10 +42,10 @@ bool CroissanceOp::needCurrentImg() const { return true; } -void CroissanceOp::operator()(const imagein::Image* image, const std::map<const imagein::Image*, std::string>&) { +void CroissanceOp::operator()(const imagein::Image* img, const std::map<const imagein::Image*, std::string>&) { QDialog* dialog = new QDialog(QApplication::activeWindow()); - dialog->setWindowTitle(QString(dialog->tr("Croissance"))); + dialog->setWindowTitle(QString(qApp->translate("Operations", "Croissance"))); dialog->setMinimumWidth(180); QFormLayout* layout = new QFormLayout(); dialog->setLayout(layout); @@ -54,16 +56,16 @@ void CroissanceOp::operator()(const imagein::Image* image, const std::map<const QSpinBox* thresholdBox = new QSpinBox(); thresholdBox->setRange(0, 255); QComboBox* initBox = new QComboBox(); - initBox->addItem(dialog->tr("At origin")); - initBox->addItem(dialog->tr("Point of lowest luminance")); + initBox->addItem(qApp->translate("CroissanceOp", "At origin")); + initBox->addItem(qApp->translate("CroissanceOp", "Point of lowest luminance")); QComboBox* stopBox = new QComboBox(); - stopBox->addItem(dialog->tr("| current - mean | < threshold")); - stopBox->addItem(dialog->tr("| current - initial | < threshold")); + stopBox->addItem(qApp->translate("CroissanceOp", "| current - mean | < threshold")); + stopBox->addItem(qApp->translate("CroissanceOp", "| current - initial | < threshold")); - layout->insertRow(0, dialog->tr("Threshold : "), thresholdBox); - layout->insertRow(1, dialog->tr("Initial germ : "), initBox); - layout->insertRow(2, dialog->tr("Stopping point : "), stopBox); + layout->insertRow(0, qApp->translate("CroissanceOp", "Threshold : "), thresholdBox); + layout->insertRow(1, qApp->translate("CroissanceOp", "Initial germ : "), initBox); + layout->insertRow(2, qApp->translate("CroissanceOp", "Stopping point : "), stopBox); QDialogButtonBox* buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok|QDialogButtonBox::Cancel, Qt::Horizontal, dialog); layout->insertRow(3, buttonBox); @@ -73,6 +75,9 @@ void CroissanceOp::operator()(const imagein::Image* image, const std::map<const QDialog::DialogCode code = static_cast<QDialog::DialogCode>(dialog->exec()); if(code!=QDialog::Accepted) return; + + GrayscaleImage* image = Converter<GrayscaleImage>::convert(*img); + Croissance cr; Image *lum, *color; int nbRegion; @@ -93,9 +98,10 @@ void CroissanceOp::operator()(const imagein::Image* image, const std::map<const nbRegion = cr.croissance2b(image, threshold, &lum, &color); } } - outImage(lum, "Luminance"); - outImage(color, "Color"); - outText(QString("Total number of area : %1").arg(nbRegion).toStdString()); - outText(QString("Mean number of point per area : %1").arg((double)image->getWidth()*image->getHeight()/nbRegion).toStdString()); + outImage(lum, qApp->translate("CroissanceOp", "Luminance").toStdString()); + outImage(color, qApp->translate("CroissanceOp", "Color").toStdString()); + outText(qApp->translate("CroissanceOp", "Total number of area : %1").arg(nbRegion).toStdString()); + outText(qApp->translate("CroissanceOp", "Mean number of point per area : %1").arg((double)image->getWidth()*image->getHeight()/nbRegion).toStdString()); + delete image; } diff --git a/app/Operations/DCTDialog.cpp b/app/Operations/DCTDialog.cpp new file mode 100644 index 0000000000000000000000000000000000000000..af1bed1a8f8ee439a331e38b0c8a8a4f8e2f236f --- /dev/null +++ b/app/Operations/DCTDialog.cpp @@ -0,0 +1,49 @@ +/* + * Copyright 2011-2012 INSA Rennes + * + * This file is part of EIImage. + * + * EIImage is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * EIImage 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with EIImage. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include "DCTDialog.h" +#include "ui_DCTDialog.h" + +DCTDialog::DCTDialog(QWidget *parent) : + QDialog(parent), + ui(new Ui::DCTDialog) +{ + ui->setupUi(this); +} + +DCTDialog::~DCTDialog() +{ + delete ui; +} + +bool DCTDialog::isTruncMode() const { + return ui->truncButton->isChecked(); +} + +int DCTDialog::getTruncLimit() const { + return ui->truncLimitBox->value(); +} + +int DCTDialog::getNbBitInit() const { + return ui->initBitBox->value(); +} + +double DCTDialog::getSlope() const { + return ui->slopeBox->value(); +} diff --git a/app/Operations/DCTDialog.h b/app/Operations/DCTDialog.h new file mode 100644 index 0000000000000000000000000000000000000000..dadc6467ca3bddee5a6457f7b0f884434de1d814 --- /dev/null +++ b/app/Operations/DCTDialog.h @@ -0,0 +1,45 @@ +/* + * Copyright 2011-2012 INSA Rennes + * + * This file is part of EIImage. + * + * EIImage is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * EIImage 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with EIImage. If not, see <http://www.gnu.org/licenses/>. +*/ + +#ifndef DCTDIALOG_H +#define DCTDIALOG_H + +#include <QDialog> + +namespace Ui { +class DCTDialog; +} + +class DCTDialog : public QDialog +{ + Q_OBJECT + +public: + explicit DCTDialog(QWidget *parent = 0); + ~DCTDialog(); + bool isTruncMode() const; + int getTruncLimit() const; + int getNbBitInit() const; + double getSlope() const; + +private: + Ui::DCTDialog *ui; +}; + +#endif // DCTDIALOG_H diff --git a/app/Operations/DCTDialog.ui b/app/Operations/DCTDialog.ui new file mode 100644 index 0000000000000000000000000000000000000000..d5ccc0107dd9cc31a634a69d09d07d4ae5ae4e18 --- /dev/null +++ b/app/Operations/DCTDialog.ui @@ -0,0 +1,306 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>DCTDialog</class> + <widget class="QDialog" name="DCTDialog"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>321</width> + <height>242</height> + </rect> + </property> + <property name="windowTitle"> + <string>DCT encoding</string> + </property> + <layout class="QVBoxLayout" name="verticalLayout_2"> + <item> + <widget class="QGroupBox" name="groupBox"> + <property name="title"> + <string>Encoding mode && associated parameters</string> + </property> + <layout class="QVBoxLayout" name="verticalLayout"> + <item> + <widget class="QRadioButton" name="truncButton"> + <property name="text"> + <string>Coefficients truncation</string> + </property> + <property name="checked"> + <bool>true</bool> + </property> + </widget> + </item> + <item> + <layout class="QHBoxLayout" name="horizontalLayout"> + <item> + <spacer name="horizontalSpacer_3"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item> + <widget class="QLabel" name="truncLimitLabel"> + <property name="enabled"> + <bool>true</bool> + </property> + <property name="sizePolicy"> + <sizepolicy hsizetype="Preferred" vsizetype="Preferred"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text"> + <string>Truncation limit : </string> + </property> + <property name="alignment"> + <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> + </property> + </widget> + </item> + <item> + <widget class="QSpinBox" name="truncLimitBox"> + <property name="maximum"> + <number>16</number> + </property> + </widget> + </item> + </layout> + </item> + <item> + <widget class="QRadioButton" name="bitButton"> + <property name="text"> + <string>Bit allocation matrice</string> + </property> + </widget> + </item> + <item> + <layout class="QHBoxLayout" name="horizontalLayout_2"> + <item> + <spacer name="horizontalSpacer"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item> + <widget class="QLabel" name="initBitLabel"> + <property name="enabled"> + <bool>false</bool> + </property> + <property name="text"> + <string>Initial number of bits : </string> + </property> + </widget> + </item> + <item> + <widget class="QSpinBox" name="initBitBox"> + <property name="enabled"> + <bool>false</bool> + </property> + <property name="maximum"> + <number>128</number> + </property> + </widget> + </item> + </layout> + </item> + <item> + <layout class="QHBoxLayout" name="horizontalLayout_3"> + <item> + <spacer name="horizontalSpacer_2"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item> + <widget class="QLabel" name="slopeLabel"> + <property name="enabled"> + <bool>false</bool> + </property> + <property name="text"> + <string>Slope value : </string> + </property> + </widget> + </item> + <item> + <widget class="QDoubleSpinBox" name="slopeBox"> + <property name="enabled"> + <bool>false</bool> + </property> + <property name="maximum"> + <double>8.000000000000000</double> + </property> + <property name="singleStep"> + <double>0.100000000000000</double> + </property> + </widget> + </item> + </layout> + </item> + </layout> + </widget> + </item> + <item> + <widget class="QDialogButtonBox" name="buttonBox"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="standardButtons"> + <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set> + </property> + </widget> + </item> + </layout> + </widget> + <resources/> + <connections> + <connection> + <sender>buttonBox</sender> + <signal>accepted()</signal> + <receiver>DCTDialog</receiver> + <slot>accept()</slot> + <hints> + <hint type="sourcelabel"> + <x>248</x> + <y>254</y> + </hint> + <hint type="destinationlabel"> + <x>157</x> + <y>274</y> + </hint> + </hints> + </connection> + <connection> + <sender>buttonBox</sender> + <signal>rejected()</signal> + <receiver>DCTDialog</receiver> + <slot>reject()</slot> + <hints> + <hint type="sourcelabel"> + <x>316</x> + <y>260</y> + </hint> + <hint type="destinationlabel"> + <x>286</x> + <y>274</y> + </hint> + </hints> + </connection> + <connection> + <sender>truncButton</sender> + <signal>toggled(bool)</signal> + <receiver>truncLimitLabel</receiver> + <slot>setEnabled(bool)</slot> + <hints> + <hint type="sourcelabel"> + <x>156</x> + <y>44</y> + </hint> + <hint type="destinationlabel"> + <x>156</x> + <y>76</y> + </hint> + </hints> + </connection> + <connection> + <sender>bitButton</sender> + <signal>toggled(bool)</signal> + <receiver>initBitLabel</receiver> + <slot>setEnabled(bool)</slot> + <hints> + <hint type="sourcelabel"> + <x>156</x> + <y>107</y> + </hint> + <hint type="destinationlabel"> + <x>146</x> + <y>139</y> + </hint> + </hints> + </connection> + <connection> + <sender>bitButton</sender> + <signal>toggled(bool)</signal> + <receiver>initBitBox</receiver> + <slot>setEnabled(bool)</slot> + <hints> + <hint type="sourcelabel"> + <x>156</x> + <y>107</y> + </hint> + <hint type="destinationlabel"> + <x>256</x> + <y>139</y> + </hint> + </hints> + </connection> + <connection> + <sender>bitButton</sender> + <signal>toggled(bool)</signal> + <receiver>slopeLabel</receiver> + <slot>setEnabled(bool)</slot> + <hints> + <hint type="sourcelabel"> + <x>156</x> + <y>107</y> + </hint> + <hint type="destinationlabel"> + <x>177</x> + <y>174</y> + </hint> + </hints> + </connection> + <connection> + <sender>truncButton</sender> + <signal>toggled(bool)</signal> + <receiver>truncLimitBox</receiver> + <slot>setEnabled(bool)</slot> + <hints> + <hint type="sourcelabel"> + <x>156</x> + <y>44</y> + </hint> + <hint type="destinationlabel"> + <x>256</x> + <y>76</y> + </hint> + </hints> + </connection> + <connection> + <sender>bitButton</sender> + <signal>toggled(bool)</signal> + <receiver>slopeBox</receiver> + <slot>setEnabled(bool)</slot> + <hints> + <hint type="sourcelabel"> + <x>156</x> + <y>107</y> + </hint> + <hint type="destinationlabel"> + <x>253</x> + <y>174</y> + </hint> + </hints> + </connection> + </connections> +</ui> diff --git a/app/Operations/DCTOp.cpp b/app/Operations/DCTOp.cpp new file mode 100644 index 0000000000000000000000000000000000000000..e59be8257f0c8aa751f38290536a6d6c08813193 --- /dev/null +++ b/app/Operations/DCTOp.cpp @@ -0,0 +1,60 @@ +/* + * Copyright 2011-2012 INSA Rennes + * + * This file is part of EIImage. + * + * EIImage is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * EIImage 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with EIImage. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include "DCTOp.h" +#include <QApplication> +#include "../Algorithms/DCT.h" +#include <GrayscaleImage.h> +#include <Converter.h> +#include "DCTDialog.h" + +using namespace imagein; +using namespace std; + +DCTOp::DCTOp() : Operation(qApp->translate("Operations", "Discrete cosinus transform").toStdString()) +{ +} + +bool DCTOp::needCurrentImg() const { + return true; +} + +void DCTOp::operator()(const imagein::Image* image, const std::map<const imagein::Image*, std::string>&) { +// GrayscaleImage* img = Converter<GrayscaleImage>::convert(*image); + DCTDialog* dialog = new DCTDialog(QApplication::activeWindow()); + QDialog::DialogCode code = static_cast<QDialog::DialogCode>(dialog->exec()); + + + if(code!=QDialog::Accepted) return; + + Image_t<double> *resImg; + Image *invImg; + string s; + if(dialog->isTruncMode()) { + s = dct16x16(image, &resImg, &invImg, true, dialog->getTruncLimit()); + } + else { + s = dct16x16(image, &resImg, &invImg, false, 0, dialog->getNbBitInit(), dialog->getSlope()); + } + + outText(s); + outDoubleImage(resImg, qApp->translate("DCT", "DCT").toStdString(), true, true, 128., true); + outImage(invImg, qApp->translate("DCT", "inverse DCT").toStdString()); +} + diff --git a/app/Operations/ImageListBox.cpp b/app/Operations/DCTOp.h similarity index 73% rename from app/Operations/ImageListBox.cpp rename to app/Operations/DCTOp.h index 50307ca7eb7478a5dfb88b7ef0191d285dba0dba..619aa1bab566ea3e8517025f62decfad4f31969e 100644 --- a/app/Operations/ImageListBox.cpp +++ b/app/Operations/DCTOp.h @@ -17,8 +17,18 @@ * along with EIImage. If not, see <http://www.gnu.org/licenses/>. */ -#include "ImageListBox.h" +#ifndef DCTOP_H +#define DCTOP_H -using namespace std; -using namespace imagein; +#include <Operation.h> +class DCTOp : public Operation +{ +public: + DCTOp(); + void operator()(const imagein::Image*, const std::map<const imagein::Image*, std::string>&); + + bool needCurrentImg() const; +}; + +#endif // DCTOP_H diff --git a/app/Operations/DMMOp.cpp b/app/Operations/DMMOp.cpp index 4077feef67ed27cff2afd6983e4876ce544453a6..c5643e27a3871842f3efef26393111fbcb35c9f4 100644 --- a/app/Operations/DMMOp.cpp +++ b/app/Operations/DMMOp.cpp @@ -30,7 +30,7 @@ bool DMMOp::needCurrentImg() const { return true; } -DMMOp::DMMOp() : Operation(Tools::tr("DMM").toStdString()) { +DMMOp::DMMOp() : Operation(qApp->translate("Operations", "DMM").toStdString()) { } @@ -53,25 +53,25 @@ void DMMOp::operator()(const imagein::Image* image, const std::map<const imagein case DMMDialog::Dilatation: { Image* resImg = dilatation(image, basicElems); - outImage(resImg, "DMM (dilatation)"); + outImage(resImg, qApp->translate("DMMOp", "DMM (dilatation)").toStdString()); break; } case DMMDialog::Erosion: { Image* resImg = erosion(image, basicElems); - outImage(resImg, "DMM (erosion)"); + outImage(resImg, qApp->translate("DMMOp", "DMM (erosion)").toStdString()); break; } case DMMDialog::Opening: { Image* resImg = opening(image, basicElems); - outImage(resImg, "DMM (opening)"); + outImage(resImg, qApp->translate("DMMOp", "DMM (opening)").toStdString()); break; } case DMMDialog::Closing: { Image* resImg = closing(image, basicElems); - outImage(resImg, "DMM (closing)"); + outImage(resImg, qApp->translate("DMMOp", "DMM (closing)").toStdString()); break; } case DMMDialog::Dmm: @@ -157,7 +157,7 @@ Image* DMMOp::erosion(const imagein::Image* image, std::vector<imagein::MorphoMa } Image* DMMOp::opening(const imagein::Image* image, std::vector<imagein::MorphoMat::StructElem::Dir> basicElems) { - outText(QString("Opening with %1 basic elements").arg(basicElems.size()).toStdString()); +// outText(QString("Opening with %1 basic elements").arg(basicElems.size()).toStdString()); Image* tmpImg = erosion(image, basicElems); Image* resImg = dilatation(tmpImg, basicElems); delete tmpImg; @@ -189,7 +189,7 @@ void DMMOp::dmm(const Image* image, vector<StructElem::Dir> basicElems, vector<u } for(unsigned int i = 0; i < components.size(); ++i) { - outImage(components.at(i), QString("DMM component #%1").arg(i).toStdString()); + outImage(components.at(i), qApp->translate("DMMOp", "DMM component #%1").arg(i).toStdString()); } - outImage(resImg, "DMM error"); + outImage(resImg, qApp->translate("DMM", "DMM error").toStdString()); } diff --git a/app/Operations/EntropyOp.cpp b/app/Operations/EntropyOp.cpp index a2f70253e030c578a773c47e00c6a9634a2fa288..1db22079cabf141d0ab652f7b8e44e7ce7419018 100644 --- a/app/Operations/EntropyOp.cpp +++ b/app/Operations/EntropyOp.cpp @@ -25,7 +25,7 @@ using namespace std; using namespace imagein; -EntropyOp::EntropyOp() : Operation(Tools::tr("Calcul d'entropie").toStdString()) +EntropyOp::EntropyOp() : Operation(qApp->translate("Operations", "Calcul d'entropie").toStdString()) { } @@ -42,7 +42,7 @@ void EntropyOp::operator()(const imagein::Image* image, const std::map<const ima } } entropy = - entropy / log(2); - outText(Tools::tr("Entropy of the image = %1").arg(entropy).toStdString()); + outText(qApp->translate("Operations", "Entropy of the image = %1").arg(entropy).toStdString()); } diff --git a/app/Operations/FFTDialog.cpp b/app/Operations/FFTDialog.cpp new file mode 100644 index 0000000000000000000000000000000000000000..725ee4c98969563b2328a9171af7829be87ffaee --- /dev/null +++ b/app/Operations/FFTDialog.cpp @@ -0,0 +1,41 @@ +/* + * Copyright 2011-2012 INSA Rennes + * + * This file is part of EIImage. + * + * EIImage is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * EIImage 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with EIImage. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include "FFTDialog.h" +#include "ui_FFTDialog.h" + +FFTDialog::FFTDialog(QWidget *parent) : + QDialog(parent), + ui(new Ui::FFTDialog) +{ + ui->setupUi(this); +} + +FFTDialog::~FFTDialog() +{ + delete ui; +} + +bool FFTDialog::isCentered() const { + return ui->centerBox->isChecked(); +} + +bool FFTDialog::isMagPhase() const { +return ui->magphaseButton->isChecked(); +} diff --git a/app/Operations/FFTDialog.h b/app/Operations/FFTDialog.h new file mode 100644 index 0000000000000000000000000000000000000000..b7e553ef155dace9ee03b44d1cf1d64ee410e209 --- /dev/null +++ b/app/Operations/FFTDialog.h @@ -0,0 +1,43 @@ +/* + * Copyright 2011-2012 INSA Rennes + * + * This file is part of EIImage. + * + * EIImage is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * EIImage 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with EIImage. If not, see <http://www.gnu.org/licenses/>. +*/ + +#ifndef FFTDIALOG_H +#define FFTDIALOG_H + +#include <QDialog> + +namespace Ui { +class FFTDialog; +} + +class FFTDialog : public QDialog +{ + Q_OBJECT + +public: + explicit FFTDialog(QWidget *parent = 0); + ~FFTDialog(); + bool isCentered() const; + bool isMagPhase() const; + +private: + Ui::FFTDialog *ui; +}; + +#endif // FFTDIALOG_H diff --git a/app/Operations/FFTDialog.ui b/app/Operations/FFTDialog.ui new file mode 100644 index 0000000000000000000000000000000000000000..63b2323fa972f0a5cda17ba0cdfbc2a6137c3ba6 --- /dev/null +++ b/app/Operations/FFTDialog.ui @@ -0,0 +1,104 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>FFTDialog</class> + <widget class="QDialog" name="FFTDialog"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>352</width> + <height>139</height> + </rect> + </property> + <property name="windowTitle"> + <string>Dialog</string> + </property> + <layout class="QVBoxLayout" name="verticalLayout_2"> + <item> + <widget class="QGroupBox" name="groupBox"> + <property name="title"> + <string>Résultat :</string> + </property> + <layout class="QVBoxLayout" name="verticalLayout_3"> + <item> + <layout class="QHBoxLayout" name="horizontalLayout"> + <item> + <widget class="QRadioButton" name="magphaseButton"> + <property name="text"> + <string>Magnitude + Phase</string> + </property> + <property name="checked"> + <bool>true</bool> + </property> + </widget> + </item> + <item> + <widget class="QRadioButton" name="realimButton"> + <property name="text"> + <string>Real + Imaginary</string> + </property> + </widget> + </item> + </layout> + </item> + <item> + <widget class="QCheckBox" name="centerBox"> + <property name="text"> + <string>Centered transform</string> + </property> + <property name="checked"> + <bool>true</bool> + </property> + </widget> + </item> + </layout> + </widget> + </item> + <item> + <widget class="QDialogButtonBox" name="buttonBox"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="standardButtons"> + <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set> + </property> + </widget> + </item> + </layout> + </widget> + <resources/> + <connections> + <connection> + <sender>buttonBox</sender> + <signal>accepted()</signal> + <receiver>FFTDialog</receiver> + <slot>accept()</slot> + <hints> + <hint type="sourcelabel"> + <x>248</x> + <y>254</y> + </hint> + <hint type="destinationlabel"> + <x>157</x> + <y>274</y> + </hint> + </hints> + </connection> + <connection> + <sender>buttonBox</sender> + <signal>rejected()</signal> + <receiver>FFTDialog</receiver> + <slot>reject()</slot> + <hints> + <hint type="sourcelabel"> + <x>316</x> + <y>260</y> + </hint> + <hint type="destinationlabel"> + <x>286</x> + <y>274</y> + </hint> + </hints> + </connection> + </connections> +</ui> diff --git a/app/Operations/FFTOp.cpp b/app/Operations/FFTOp.cpp index 7048542718cc9c1bbec918506b8b1ee22899b4b6..9b3fa168f8590a48f28bef58c80658df1dac9e2b 100644 --- a/app/Operations/FFTOp.cpp +++ b/app/Operations/FFTOp.cpp @@ -16,16 +16,16 @@ * You should have received a copy of the GNU General Public License * along with EIImage. If not, see <http://www.gnu.org/licenses/>. */ -#include "ImgWidget.h" #include "FFTOp.h" #include "../Tools.h" #include "../Algorithms/FFT.h" +#include "FFTDialog.h" #include <cmath> using namespace std; using namespace imagein; -FFTOp::FFTOp() : Operation(Tools::tr("Discrete Fourier transform").toStdString()) +FFTOp::FFTOp() : Operation(qApp->translate("Operations", "Fourier transform").toStdString()) { } @@ -34,57 +34,113 @@ bool FFTOp::needCurrentImg() const { } void FFTOp::operator()(const imagein::Image* image, const map<const imagein::Image*, string>&) { + FFTDialog* dialog = new FFTDialog(QApplication::activeWindow()); + QDialog::DialogCode code = static_cast<QDialog::DialogCode>(dialog->exec()); + + + if(code!=QDialog::Accepted) return; unsigned int width = nearestUpPower2(image->getWidth()); unsigned int height = nearestUpPower2(image->getHeight()); - Image_t<double>* magnitudeImg = new Image_t<double>(width, height, image->getNbChannels()); - Image_t<double>* phaseImg = new Image_t<double>(width, height, image->getNbChannels()); -// Image_t<double>* realImg = new Image_t<double>(width, height, image->getNbChannels()); -// Image_t<double>* imagImg = new Image_t<double>(width, height, image->getNbChannels()); complex<double>** data = new complex<double>*[width]; for(unsigned int i = 0; i < width; ++i) data[i] = new complex<double>[height]; - for(unsigned int c = 0; c < image->getNbChannels(); ++c) { - for(unsigned int j = 0; j < image->getHeight(); ++j) { - for(unsigned int i = 0; i < image->getWidth(); ++i) { - data[i][j] = static_cast<double>(image->getPixel(i, j, c)); + if(dialog->isMagPhase()) { + Image_t<double>* magnitudeImg = new Image_t<double>(width, height, image->getNbChannels()); + Image_t<double>* phaseImg = new Image_t<double>(width, height, image->getNbChannels()); + for(unsigned int c = 0; c < image->getNbChannels(); ++c) { + for(unsigned int j = 0; j < image->getHeight(); ++j) { + for(unsigned int i = 0; i < image->getWidth(); ++i) { + data[i][j] = static_cast<double>(image->getPixel(i, j, c)); + } } - } - for(unsigned int j = image->getHeight(); j < height; ++j) { - for(unsigned int i = image->getWidth(); i < width; ++i) { - data[i][j] = 0; + for(unsigned int j = image->getHeight(); j < height; ++j) { + for(unsigned int i = image->getWidth(); i < width; ++i) { + data[i][j] = 0; + } + } + + FFT2D(data, width, height, 1); + + if(dialog->isCentered()) { + for(unsigned int j = 0; j < height; ++j) { + for(unsigned int i = 0; i < width; ++i) { + const double real = data[i][j].real(); + const double imag = data[i][j].imag(); + const double magnitude = sqrt( real*real + imag*imag ); + const double phase = atan2(imag, real); + const unsigned int cw = width/2; + const unsigned int ch = height/2; + const unsigned int ci = i >= cw ? i - cw : i + cw; + const unsigned int cj = j >= ch ? j - ch : j + ch; + magnitudeImg->setPixel(ci, cj, c, magnitude); + phaseImg->setPixel(ci, cj, c, phase); + } + } + } + else { + for(unsigned int j = 0; j < height; ++j) { + for(unsigned int i = 0; i < width; ++i) { + const double real = data[i][j].real(); + const double imag = data[i][j].imag(); + const double magnitude = sqrt( real*real + imag*imag ); + const double phase = atan2(imag, real); + magnitudeImg->setPixel(i, j, c, magnitude); + phaseImg->setPixel(i, j, c, phase); + } + } } } + this->outDoubleImage(phaseImg, qApp->translate("FFTOp", "DFT (phase)").toStdString(), true, false); + this->outDoubleImage(magnitudeImg, qApp->translate("FFTOp", "DFT (magnitude)").toStdString(), true, true); + } + else { + Image_t<double>* realImg = new Image_t<double>(width, height, image->getNbChannels()); + Image_t<double>* imagImg = new Image_t<double>(width, height, image->getNbChannels()); + for(unsigned int c = 0; c < image->getNbChannels(); ++c) { + for(unsigned int j = 0; j < image->getHeight(); ++j) { + for(unsigned int i = 0; i < image->getWidth(); ++i) { + data[i][j] = static_cast<double>(image->getPixel(i, j, c)); + } + } + for(unsigned int j = image->getHeight(); j < height; ++j) { + for(unsigned int i = image->getWidth(); i < width; ++i) { + data[i][j] = 0; + } + } + + FFT2D(data, width, height, 1); - FFT2D(data, width, height, 1); - - for(unsigned int j = 0; j < height; ++j) { - for(unsigned int i = 0; i < width; ++i) { - const double real = data[i][j].real(); - const double imag = data[i][j].imag(); - const double magnitude = sqrt( real*real + imag*imag ); - const double phase = atan2(imag, real); - const unsigned int cw = width/2; - const unsigned int ch = height/2; - const unsigned int ci = i >= cw ? i - cw : i + cw; - const unsigned int cj = j >= ch ? j - ch : j + ch; - magnitudeImg->setPixel(ci, cj, c, magnitude); - phaseImg->setPixel(ci, cj, c, phase); -// realImg->setPixel(ci, cj, c, real); -// imagImg->setPixel(ci, cj, c, imag); + if(dialog->isCentered()) { + for(unsigned int j = 0; j < height; ++j) { + for(unsigned int i = 0; i < width; ++i) { + const double real = data[i][j].real(); + const double imag = data[i][j].imag(); + const unsigned int cw = width/2; + const unsigned int ch = height/2; + const unsigned int ci = i >= cw ? i - cw : i + cw; + const unsigned int cj = j >= ch ? j - ch : j + ch; + realImg->setPixel(ci, cj, c, real); + imagImg->setPixel(ci, cj, c, imag); + } + } + } + else { + for(unsigned int j = 0; j < height; ++j) { + for(unsigned int i = 0; i < width; ++i) { + const double real = data[i][j].real(); + const double imag = data[i][j].imag(); + realImg->setPixel(i, j, c, real); + imagImg->setPixel(i, j, c, imag); + } + } } } + this->outDoubleImage(realImg, "FFT (real)", true, true); + this->outDoubleImage(imagImg, "FFT (imag)", true, true); } - this->outDoubleImage(phaseImg, "FFT (phase)", true, false); - this->outDoubleImage(magnitudeImg, "FFT (magnitude)", true, true); -// this->outDoubleImage(realImg, "FFT (real)", true, true); -// this->outDoubleImage(imagImg, "FFT (imag)", true, true); -// result.push_back(new DoubleImgWidget(phaseImg, " - FFT : phase", true, false)); -// result.push_back(new DoubleImgWidget(magnitudeImg, " - FFT : magnitude", true, true)); -// result.push_back(new DoubleImgWidget(realImg, " - FFT : real", true, true)); -// result.push_back(new DoubleImgWidget(imagImg, " - FFT : imag", true, true)); } diff --git a/app/Operations/FlipOp.cpp b/app/Operations/FlipOp.cpp index cd99a96184875f7f0167093abd98b87c340b27a9..4c789089901e4ef727dd60cf52a35172db1330ff 100644 --- a/app/Operations/FlipOp.cpp +++ b/app/Operations/FlipOp.cpp @@ -21,14 +21,13 @@ #include <Image.h> -#include "ImgWidget.h" #include "FlipOp.h" using namespace std; using namespace imagein; FlipOp::FlipOp(Direction dir) - : Operation(QString(tr("Flip %1")).arg(dir == Horizontal ? tr("horizontal") : tr("vertical")).toStdString()), _dir(dir) + : Operation(qApp->translate("Operations", "Flip %1").arg(dir == Horizontal ? qApp->translate("FlipOp", "horizontal") : qApp->translate("FlipOp", "vertical")).toStdString()), _dir(dir) { } @@ -60,7 +59,7 @@ void FlipOp::operator()(const imagein::Image* image, const std::map<const imagei } } } - QString name = QString(tr(" - flipped %1")).arg(_dir == Horizontal ? tr("horizontal") : tr("vertical")); + QString name = qApp->translate("FlipOp", "flipped %1").arg(_dir == Horizontal ? qApp->translate("FlipOp", "horizontal") : qApp->translate("FlipOp", "vertical")); this->outImage(resImg, name.toStdString()); } diff --git a/app/Operations/HadamardOp.cpp b/app/Operations/HadamardOp.cpp new file mode 100644 index 0000000000000000000000000000000000000000..56f246f6421f07ff4b48a727c170b9bd6541a83b --- /dev/null +++ b/app/Operations/HadamardOp.cpp @@ -0,0 +1,127 @@ +/* + * Copyright 2011-2012 INSA Rennes + * + * This file is part of EIImage. + * + * EIImage is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * EIImage 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with EIImage. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include "HadamardOp.h" +#include <QApplication> +#include <GrayscaleImage.h> +#include "Transforms.h" +#include <Converter.h> +#include <QDialog> +#include <QGridLayout> +#include <QVBoxLayout> +#include <QHBoxLayout> +#include <QCheckBox> +#include <QDialogButtonBox> +#include <QLabel> +#include <QPushButton> +#include <QComboBox> +#include <QFormLayout> + +using namespace std; +using namespace imagein; + +HadamardOp::HadamardOp() : Operation(qApp->translate("Operations", "8x8 transforms").toStdString()) +{ +} + +bool HadamardOp::needCurrentImg() const { + return true; +} + +void HadamardOp::operator()(const imagein::Image* img, const std::map<const imagein::Image*, std::string>&) { + + + QDialog* dialog = new QDialog(QApplication::activeWindow()); + dialog->setWindowTitle(qApp->translate("Operations", "8x8 transforms")); + QFormLayout* layout = new QFormLayout(dialog); + QComboBox* transformBox = new QComboBox(dialog); + transformBox->addItems(QStringList() << "Hadamard" << "Haar" << "Cosinus (DCT)"); + layout->insertRow(0, qApp->translate("Hadamard", "Transform : "), transformBox); + + QLabel* title = new QLabel(qApp->translate("Transforms", "<b>Select the coefficients to keep : </b>")); + title->setAlignment(Qt::AlignCenter); + layout->insertRow(1, title); + + QHBoxLayout* buttonLayout = new QHBoxLayout(); + QPushButton* selectAllButton = new QPushButton(qApp->translate("Transforms", "Clear selection")); + QPushButton* selectNoneButton = new QPushButton(qApp->translate("Transforms", "Invert selection")); + buttonLayout->addWidget(selectAllButton); + buttonLayout->addWidget(selectNoneButton); + layout->insertRow(2, buttonLayout); + + QWidget* coefWidget = new QWidget(dialog); + QGridLayout* coefLayout = new QGridLayout(coefWidget); + QCheckBox* checkBoxes[8][8]; + for(int i = 0; i < 8; ++i) { + QLabel* labeli = new QLabel(QString("%1").arg(i)); + QLabel* labelj = new QLabel(QString("%1").arg(i)); + labeli->setAlignment(Qt::AlignCenter); + labelj->setAlignment(Qt::AlignCenter); + coefLayout->addWidget(labeli, 0, i + 1); + coefLayout->addWidget(labelj, i + 1, 0); + } + for(int j = 0; j < 8; ++j) { + for(int i = 0; i < 8; ++i) { + checkBoxes[j][i] = new QCheckBox(coefWidget); + coefLayout->addWidget(checkBoxes[j][i], j + 1, i + 1); + checkBoxes[j][i]->setChecked(true); + QObject::connect(selectAllButton, SIGNAL(clicked(bool)), checkBoxes[j][i], SLOT(setChecked(bool))); + QObject::connect(selectNoneButton, SIGNAL(clicked()), checkBoxes[j][i], SLOT(toggle())); + } + } + layout->insertRow(3, coefWidget); + + QDialogButtonBox* buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok|QDialogButtonBox::Cancel, Qt::Horizontal, dialog); + layout->insertRow(4, buttonBox); + QObject::connect(buttonBox, SIGNAL(accepted()), dialog, SLOT(accept())); + QObject::connect(buttonBox, SIGNAL(rejected()), dialog, SLOT(reject())); + + QDialog::DialogCode code = static_cast<QDialog::DialogCode>(dialog->exec()); + + + if(code!=QDialog::Accepted) return; + + GrayscaleImage_t<bool>* selection = new GrayscaleImage_t<bool>(8, 8); + for(int j = 0; j < 8; ++j) { + for(int i = 0; i < 8; ++i) { + selection->setPixelAt(i, j, checkBoxes[j][i]->isChecked()); + } + } +// GrayscaleImage* im = Converter<GrayscaleImage>::convert(*img); + string s; + Image_t<double> *resImg; + Image* invImg; + if(transformBox->currentIndex() == 0) { + s = Transforms::Hadamard(img, &resImg, &invImg, selection); + outDoubleImage(resImg, qApp->translate("Transforms", "Hadamard transform").toStdString(), true, true, 256., true); + outImage(invImg, qApp->translate("Transforms", "Hadamard reconstruction").toStdString()); + } + else if(transformBox->currentIndex() == 1) { + s = Transforms::Haar(img, &resImg, &invImg, selection); + outDoubleImage(resImg, qApp->translate("Transforms", "Haar transform").toStdString(), true, true, 256., true); + outImage(invImg, qApp->translate("Transforms", "Haar reconstruction").toStdString()); + } + else if(transformBox->currentIndex() == 2) { + s = Transforms::cosinus(img, &resImg, &invImg, selection); + outDoubleImage(resImg, qApp->translate("Transforms", "cosinus transform").toStdString(), true, true, 256., true); + outImage(invImg, qApp->translate("Transforms", "cosinus reconstruction").toStdString()); + } + outText(s); +} + diff --git a/app/Operations/HadamardOp.h b/app/Operations/HadamardOp.h new file mode 100644 index 0000000000000000000000000000000000000000..5400d62bf82b10bbd09c8e5cc630aabe22c24c51 --- /dev/null +++ b/app/Operations/HadamardOp.h @@ -0,0 +1,34 @@ +/* + * Copyright 2011-2012 INSA Rennes + * + * This file is part of EIImage. + * + * EIImage is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * EIImage 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with EIImage. If not, see <http://www.gnu.org/licenses/>. +*/ + +#ifndef HADAMARDOP_H +#define HADAMARDOP_H + +#include <Operation.h> + +class HadamardOp : public Operation{ +public: + HadamardOp(); + + void operator()(const imagein::Image*, const std::map<const imagein::Image*, std::string>&); + + bool needCurrentImg() const; +}; + +#endif // HADAMARDOP_H diff --git a/app/Operations/HistogramOp.cpp b/app/Operations/HistogramOp.cpp index 14251d593d84dd483b913736e120797208998d6d..179322b7966c81b6203a37f8ee27af5e4a5d3fc5 100644 --- a/app/Operations/HistogramOp.cpp +++ b/app/Operations/HistogramOp.cpp @@ -29,7 +29,7 @@ using namespace std; using namespace imagein; -HistogramOp::HistogramOp() : Operation(Tools::tr("Histogram operations").toStdString()) +HistogramOp::HistogramOp() : Operation(qApp->translate("Operations", "Histogram operations").toStdString()) { } @@ -39,15 +39,15 @@ bool HistogramOp::needCurrentImg() const { void HistogramOp::operator()(const imagein::Image* img, const std::map<const imagein::Image*, std::string>&) { QDialog* dialog = new QDialog(QApplication::activeWindow()); - dialog->setWindowTitle(QString(dialog->tr("Histogram operations"))); + dialog->setWindowTitle(QString(qApp->translate("HistogramOp", "Histogram operations"))); dialog->setMinimumWidth(180); QFormLayout* layout = new QFormLayout(); dialog->setLayout(layout); QComboBox* opBox = new QComboBox(); - opBox->addItem(dialog->tr("Equalize")); - opBox->addItem(dialog->tr("Normalize")); - layout->insertRow(0, dialog->tr("Operation : "), opBox); + opBox->addItem(qApp->translate("HistogramOp", "Equalize")); + opBox->addItem(qApp->translate("HistogramOp", "Normalize")); + layout->insertRow(0, qApp->translate("HistogramOp", "Operation : "), opBox); QDialogButtonBox* buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok|QDialogButtonBox::Cancel, Qt::Horizontal, dialog); layout->insertRow(3, buttonBox); @@ -60,11 +60,11 @@ void HistogramOp::operator()(const imagein::Image* img, const std::map<const ima if(opBox->currentIndex()==0) { Image* resImg = equalize(img); - outImage(resImg, "equalized"); + outImage(resImg, qApp->translate("HistogramOp", "equalized").toStdString()); } else if(opBox->currentIndex()==1) { Image* resImg = normalize(img); - outImage(resImg, "normalized"); + outImage(resImg, qApp->translate("HistogramOp", "normalized").toStdString()); } } diff --git a/app/Operations/HoughDialog.cpp b/app/Operations/HoughDialog.cpp new file mode 100644 index 0000000000000000000000000000000000000000..8c07e98c374e7e85395b6f5bb1af2a7871c7bb88 --- /dev/null +++ b/app/Operations/HoughDialog.cpp @@ -0,0 +1,45 @@ +/* + * Copyright 2011-2012 INSA Rennes + * + * This file is part of EIImage. + * + * EIImage is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * EIImage 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with EIImage. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include "HoughDialog.h" +#include "ui_HoughDialog.h" + +HoughDialog::HoughDialog(QWidget *parent) : + QDialog(parent), + ui(new Ui::HoughDialog) +{ + ui->setupUi(this); +} + +HoughDialog::~HoughDialog() +{ + delete ui; +} + +bool HoughDialog::isMethod1() const { + return ui->method1Button->isChecked(); +} + +double HoughDialog::getAngleStep() const { + return ui->angleBox->value(); +} + +double HoughDialog::getDistanceStep() const { + return ui->distanceBox->value(); +} diff --git a/app/Operations/HoughDialog.h b/app/Operations/HoughDialog.h new file mode 100644 index 0000000000000000000000000000000000000000..7ec01eeaf0f9bff1d597b053e3b28f16f51818f7 --- /dev/null +++ b/app/Operations/HoughDialog.h @@ -0,0 +1,44 @@ +/* + * Copyright 2011-2012 INSA Rennes + * + * This file is part of EIImage. + * + * EIImage is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * EIImage 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with EIImage. If not, see <http://www.gnu.org/licenses/>. +*/ + +#ifndef HOUGHDIALOG_H +#define HOUGHDIALOG_H + +#include <QDialog> + +namespace Ui { +class HoughDialog; +} + +class HoughDialog : public QDialog +{ + Q_OBJECT + +public: + explicit HoughDialog(QWidget *parent = 0); + ~HoughDialog(); + bool isMethod1() const; + double getAngleStep() const; + double getDistanceStep() const; + +private: + Ui::HoughDialog *ui; +}; + +#endif // HOUGHDIALOG_H diff --git a/app/Operations/HoughDialog.ui b/app/Operations/HoughDialog.ui new file mode 100644 index 0000000000000000000000000000000000000000..2c63e153c1d094731e7fafa54ef6df10243842aa --- /dev/null +++ b/app/Operations/HoughDialog.ui @@ -0,0 +1,232 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>HoughDialog</class> + <widget class="QDialog" name="HoughDialog"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>259</width> + <height>180</height> + </rect> + </property> + <property name="windowTitle"> + <string>Hough transform</string> + </property> + <layout class="QVBoxLayout" name="verticalLayout"> + <item> + <widget class="QGroupBox" name="groupBox"> + <property name="title"> + <string>Method</string> + </property> + <layout class="QHBoxLayout" name="horizontalLayout"> + <item> + <widget class="QRadioButton" name="method1Button"> + <property name="text"> + <string>Method #1</string> + </property> + <property name="checked"> + <bool>true</bool> + </property> + </widget> + </item> + <item> + <widget class="QRadioButton" name="method2Button"> + <property name="text"> + <string>Method #2</string> + </property> + </widget> + </item> + </layout> + </widget> + </item> + <item> + <layout class="QHBoxLayout" name="horizontalLayout_2"> + <item> + <widget class="QLabel" name="angleLabel"> + <property name="enabled"> + <bool>false</bool> + </property> + <property name="sizePolicy"> + <sizepolicy hsizetype="Expanding" vsizetype="Preferred"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text"> + <string>Angle step : </string> + </property> + </widget> + </item> + <item> + <widget class="QDoubleSpinBox" name="angleBox"> + <property name="enabled"> + <bool>false</bool> + </property> + <property name="minimum"> + <double>0.010000000000000</double> + </property> + <property name="maximum"> + <double>90.000000000000000</double> + </property> + <property name="value"> + <double>0.500000000000000</double> + </property> + </widget> + </item> + </layout> + </item> + <item> + <layout class="QHBoxLayout" name="horizontalLayout_3"> + <item> + <widget class="QLabel" name="distanceLabel"> + <property name="enabled"> + <bool>false</bool> + </property> + <property name="sizePolicy"> + <sizepolicy hsizetype="Expanding" vsizetype="Preferred"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text"> + <string>Distance step : </string> + </property> + </widget> + </item> + <item> + <widget class="QDoubleSpinBox" name="distanceBox"> + <property name="enabled"> + <bool>false</bool> + </property> + <property name="minimum"> + <double>0.010000000000000</double> + </property> + <property name="maximum"> + <double>512.000000000000000</double> + </property> + <property name="value"> + <double>1.000000000000000</double> + </property> + </widget> + </item> + </layout> + </item> + <item> + <widget class="QDialogButtonBox" name="buttonBox"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Preferred" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="standardButtons"> + <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set> + </property> + </widget> + </item> + </layout> + </widget> + <resources/> + <connections> + <connection> + <sender>buttonBox</sender> + <signal>accepted()</signal> + <receiver>HoughDialog</receiver> + <slot>accept()</slot> + <hints> + <hint type="sourcelabel"> + <x>248</x> + <y>254</y> + </hint> + <hint type="destinationlabel"> + <x>157</x> + <y>274</y> + </hint> + </hints> + </connection> + <connection> + <sender>buttonBox</sender> + <signal>rejected()</signal> + <receiver>HoughDialog</receiver> + <slot>reject()</slot> + <hints> + <hint type="sourcelabel"> + <x>316</x> + <y>260</y> + </hint> + <hint type="destinationlabel"> + <x>286</x> + <y>274</y> + </hint> + </hints> + </connection> + <connection> + <sender>method2Button</sender> + <signal>toggled(bool)</signal> + <receiver>angleLabel</receiver> + <slot>setEnabled(bool)</slot> + <hints> + <hint type="sourcelabel"> + <x>188</x> + <y>44</y> + </hint> + <hint type="destinationlabel"> + <x>92</x> + <y>87</y> + </hint> + </hints> + </connection> + <connection> + <sender>method2Button</sender> + <signal>toggled(bool)</signal> + <receiver>angleBox</receiver> + <slot>setEnabled(bool)</slot> + <hints> + <hint type="sourcelabel"> + <x>188</x> + <y>44</y> + </hint> + <hint type="destinationlabel"> + <x>215</x> + <y>87</y> + </hint> + </hints> + </connection> + <connection> + <sender>method2Button</sender> + <signal>toggled(bool)</signal> + <receiver>distanceLabel</receiver> + <slot>setEnabled(bool)</slot> + <hints> + <hint type="sourcelabel"> + <x>188</x> + <y>44</y> + </hint> + <hint type="destinationlabel"> + <x>96</x> + <y>123</y> + </hint> + </hints> + </connection> + <connection> + <sender>method2Button</sender> + <signal>toggled(bool)</signal> + <receiver>distanceBox</receiver> + <slot>setEnabled(bool)</slot> + <hints> + <hint type="sourcelabel"> + <x>188</x> + <y>44</y> + </hint> + <hint type="destinationlabel"> + <x>215</x> + <y>123</y> + </hint> + </hints> + </connection> + </connections> +</ui> diff --git a/app/Operations/HoughOp.cpp b/app/Operations/HoughOp.cpp new file mode 100644 index 0000000000000000000000000000000000000000..0c62c7fd2bc83bda179b6b3d64acab8fa23de916 --- /dev/null +++ b/app/Operations/HoughOp.cpp @@ -0,0 +1,58 @@ +/* + * Copyright 2011-2012 INSA Rennes + * + * This file is part of EIImage. + * + * EIImage is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * EIImage 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with EIImage. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include "HoughOp.h" +#include <QApplication> +#include "Transforms.h" +#include <Converter.h> +#include <GrayscaleImage.h> +#include "HoughDialog.h" + +using namespace std; +using namespace imagein; + +HoughOp::HoughOp() : Operation(qApp->translate("Operations", "Hough transform").toStdString()) +{ +} + +bool HoughOp::needCurrentImg() const { + return true; +} + +void HoughOp::operator()(const imagein::Image* img, const std::map<const imagein::Image*, std::string>&) { + HoughDialog* dialog = new HoughDialog(QApplication::activeWindow()); + QDialog::DialogCode code = static_cast<QDialog::DialogCode>(dialog->exec()); + + Image_t<double>* resImg; + + if(code!=QDialog::Accepted) return; + if(dialog->isMethod1()) { + GrayscaleImage* image = Converter<GrayscaleImage>::convert(*img); + resImg = Transforms::hough(image); + delete image; + } + else { + resImg = Transforms::hough2(img, dialog->getAngleStep(), dialog->getDistanceStep()); + } + outDoubleImage(resImg, qApp->translate("Hough", "Hough transform").toStdString(), true, true); +// Image* resImg2; +// Transforms::hough2_inverse(resImg, &resImg2, 512, 0.); +// outImage(resImg2, qApp->translate("Hough", "Hough inverse transform").toStdString()); +} + diff --git a/app/Operations/HoughOp.h b/app/Operations/HoughOp.h new file mode 100644 index 0000000000000000000000000000000000000000..18a36df70d287aee6e78a40c85894fef0fc63897 --- /dev/null +++ b/app/Operations/HoughOp.h @@ -0,0 +1,35 @@ +/* + * Copyright 2011-2012 INSA Rennes + * + * This file is part of EIImage. + * + * EIImage is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * EIImage 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with EIImage. If not, see <http://www.gnu.org/licenses/>. +*/ + +#ifndef HOUGHOP_H +#define HOUGHOP_H + +#include <Operation.h> + +class HoughOp : public Operation +{ +public: + HoughOp(); + + void operator()(const imagein::Image*, const std::map<const imagein::Image*, std::string>&); + + bool needCurrentImg() const; +}; + +#endif // HOUGHOP_H diff --git a/app/Operations/HuffmanOp.cpp b/app/Operations/HuffmanOp.cpp index 5e8b4b3e14fc7f97e4ca67f31c21ca4c6d1d24e5..86a753bf5860137c34158adc2b14444e7850186a 100644 --- a/app/Operations/HuffmanOp.cpp +++ b/app/Operations/HuffmanOp.cpp @@ -26,7 +26,7 @@ using namespace std; using namespace imagein; -HuffmanOp::HuffmanOp() : Operation(Tools::tr("Huffman").toStdString()) +HuffmanOp::HuffmanOp() : Operation(qApp->translate("Operations", "Huffman").toStdString()) { } diff --git a/app/Operations/IFFTOp.cpp b/app/Operations/IFFTOp.cpp index 9386b7543c91f9a9e4769222d09638a2d154a5bd..7ce76aeef620be5729bb57814b9a43fb9a05943a 100644 --- a/app/Operations/IFFTOp.cpp +++ b/app/Operations/IFFTOp.cpp @@ -20,18 +20,22 @@ #include <QDialog> #include <QFormLayout> #include <QDialogButtonBox> -#include "ImageListBox.h" +#include <Widgets/ImageListBox.h> +#include <QHBoxLayout> +#include <QVBoxLayout> +#include <QRadioButton> #include "IFFTOp.h" -#include "ImgWidget.h" #include "../Tools.h" #include "../Algorithms/FFT.h" #include <cmath> +#include <QGroupBox> +#include <QCheckBox> using namespace std; using namespace imagein; -IFFTOp::IFFTOp() : DoubleOperation(Tools::tr("Discrete Fourier reconstruction").toStdString()) +IFFTOp::IFFTOp() : DoubleOperation(qApp->translate("Operations", "Inverse Fourier transform").toStdString()) { } @@ -42,70 +46,155 @@ bool IFFTOp::needCurrentImg() const { void IFFTOp::operator()(const imagein::Image_t<double>*, const map<const imagein::Image_t<double>*, string>& imgList) { QDialog* dialog = new QDialog(); - dialog->setWindowTitle(dialog->tr("Parameters")); + dialog->setWindowTitle(qApp->translate("Operations", "Parameters")); dialog->setMinimumWidth(180); - QFormLayout* layout = new QFormLayout(); - dialog->setLayout(layout); - + QVBoxLayout* layout = new QVBoxLayout(dialog); + + QGroupBox* groupBox = new QGroupBox(dialog); + QHBoxLayout* groupLayout = new QHBoxLayout(groupBox); + QRadioButton* magButton = new QRadioButton("Magnitude/Phase"); + QRadioButton* realButton = new QRadioButton("Real/Imaginary"); + groupLayout->addWidget(magButton); + groupLayout->addWidget(realButton); + layout->addWidget(groupBox); + magButton->setChecked(true); + + QWidget* magWidget = new QWidget(); + QFormLayout* magLayout = new QFormLayout(magWidget); ImageListBox_t<double>* magtdImgBox = new ImageListBox_t<double>(dialog, NULL, imgList); ImageListBox_t<double>* phaseImgBox = new ImageListBox_t<double>(dialog, NULL, imgList); - layout->insertRow(0, "Magnitude : ", magtdImgBox); - layout->insertRow(1, "Phase : ", phaseImgBox); + magLayout->insertRow(0, qApp->translate("IFFTOp", "Magnitude : "), magtdImgBox); + magLayout->insertRow(1, qApp->translate("IFFTOp", "Phase : "), phaseImgBox); + QWidget* realWidget = new QWidget(); + QFormLayout* realLayout = new QFormLayout(realWidget); + ImageListBox_t<double>* realImgBox = new ImageListBox_t<double>(dialog, NULL, imgList); + ImageListBox_t<double>* imagImgBox = new ImageListBox_t<double>(dialog, NULL, imgList); + realLayout->insertRow(0, qApp->translate("IFFTOp", "Real part : "), realImgBox); + realLayout->insertRow(1, qApp->translate("IFFTOp", "Imaginary part : "), imagImgBox); + + layout->addWidget(magWidget); + layout->addWidget(realWidget); + realWidget->setVisible(false); + + QCheckBox* centerBox = new QCheckBox("Source is centered"); + centerBox->setChecked(true); + layout->addWidget(centerBox); QDialogButtonBox* buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok|QDialogButtonBox::Cancel, Qt::Horizontal, dialog); - layout->insertRow(2, buttonBox); + layout->addWidget(buttonBox); QObject::connect(buttonBox, SIGNAL(accepted()), dialog, SLOT(accept())); QObject::connect(buttonBox, SIGNAL(rejected()), dialog, SLOT(reject())); + QObject::connect(realButton, SIGNAL(toggled(bool)), realWidget, SLOT(setVisible(bool))); + QObject::connect(magButton, SIGNAL(toggled(bool)), magWidget, SLOT(setVisible(bool))); + QDialog::DialogCode code = static_cast<QDialog::DialogCode>(dialog->exec()); if(code!=QDialog::Accepted) { return; } - const Image_t<double>* magnitudeImg = magtdImgBox->currentImage(); - const Image_t<double>* phaseImg = phaseImgBox->currentImage(); - unsigned int width = min(nearestUpPower2(magnitudeImg->getWidth()), nearestUpPower2(phaseImg->getWidth())); - unsigned int height = min(nearestUpPower2(magnitudeImg->getHeight()), nearestUpPower2(phaseImg->getHeight())); - unsigned int channels = min(magnitudeImg->getNbChannels(), phaseImg->getNbChannels()); - - Image* resImg = new Image(width, height, channels); -// Image_t<double>* realImg = new Image_t<double>(width, height, channels); -// Image_t<double>* imagImg = new Image_t<double>(width, height, channels); - - complex<double>** data = new complex<double>*[width]; - for(unsigned int i = 0; i < width; ++i) data[i] = new complex<double>[height]; - - const unsigned int cw = width/2; - const unsigned int ch = height/2; - for(unsigned int c = 0; c < channels; ++c) { - for(unsigned int j = 0; j < height; ++j) { - for(unsigned int i = 0; i < width; ++i) { - const unsigned int ci = i >= cw ? i - cw : i + cw; - const unsigned int cj = j >= ch ? j - ch : j + ch; - const double magtd = magnitudeImg->getPixel(ci, cj, c); - const double phase = phaseImg->getPixel(ci, cj, c); - const double real = magtd * cos(phase); - const double imag = magtd * sin(phase); - data[i][j] = complex<double>(real,imag); + Image* resImg; + if(magButton->isChecked()) { + + const Image_t<double>* magnitudeImg = magtdImgBox->currentImage(); + const Image_t<double>* phaseImg = phaseImgBox->currentImage(); + if(magnitudeImg == NULL || phaseImg == NULL) return; + unsigned int width = min(nearestUpPower2(magnitudeImg->getWidth()), nearestUpPower2(phaseImg->getWidth())); + unsigned int height = min(nearestUpPower2(magnitudeImg->getHeight()), nearestUpPower2(phaseImg->getHeight())); + unsigned int channels = min(magnitudeImg->getNbChannels(), phaseImg->getNbChannels()); + + resImg = new Image(width, height, channels); + + complex<double>** data = new complex<double>*[width]; + for(unsigned int i = 0; i < width; ++i) data[i] = new complex<double>[height]; + + const unsigned int cw = width/2; + const unsigned int ch = height/2; + for(unsigned int c = 0; c < channels; ++c) { + if(centerBox->isChecked()) { + for(unsigned int j = 0; j < height; ++j) { + for(unsigned int i = 0; i < width; ++i) { + const unsigned int ci = i >= cw ? i - cw : i + cw; + const unsigned int cj = j >= ch ? j - ch : j + ch; + const double magtd = magnitudeImg->getPixel(ci, cj, c); + const double phase = phaseImg->getPixel(ci, cj, c); + const double real = magtd * cos(phase); + const double imag = magtd * sin(phase); + data[i][j] = complex<double>(real,imag); + } + } + } + else { + for(unsigned int j = 0; j < height; ++j) { + for(unsigned int i = 0; i < width; ++i) { + const double magtd = magnitudeImg->getPixel(i, j, c); + const double phase = phaseImg->getPixel(i, j, c); + const double real = magtd * cos(phase); + const double imag = magtd * sin(phase); + data[i][j] = complex<double>(real,imag); + } + } + } + + FFT2D(data, width, height, -1); + for(unsigned int j = 0; j < height; ++j) { + for(unsigned int i = 0; i < width; ++i) { + double value = floor(data[i][j].real()+0.5); + value = min(255.0, max(0.0, value)); + resImg->setPixel(i, j, c, value); + } } } + } + else { + + const Image_t<double>* realImg = realImgBox->currentImage(); + const Image_t<double>* imagImg = imagImgBox->currentImage(); + if(realImg == NULL || imagImg == NULL) return; + unsigned int width = min(nearestUpPower2(realImg->getWidth()), nearestUpPower2(imagImg->getWidth())); + unsigned int height = min(nearestUpPower2(realImg->getHeight()), nearestUpPower2(imagImg->getHeight())); + unsigned int channels = min(realImg->getNbChannels(), imagImg->getNbChannels()); + + resImg = new Image(width, height, channels); + + complex<double>** data = new complex<double>*[width]; + for(unsigned int i = 0; i < width; ++i) data[i] = new complex<double>[height]; + + const unsigned int cw = width/2; + const unsigned int ch = height/2; + for(unsigned int c = 0; c < channels; ++c) { + if(centerBox->isChecked()) { + for(unsigned int j = 0; j < height; ++j) { + for(unsigned int i = 0; i < width; ++i) { + const unsigned int ci = i >= cw ? i - cw : i + cw; + const unsigned int cj = j >= ch ? j - ch : j + ch; + const double real = realImg->getPixel(ci, cj, c); + const double imag = imagImg->getPixel(ci, cj, c); + data[i][j] = complex<double>(real,imag); + } + } + } + else { + for(unsigned int j = 0; j < height; ++j) { + for(unsigned int i = 0; i < width; ++i) { + const double real = realImg->getPixel(i, j, c); + const double imag = imagImg->getPixel(i, j, c); + data[i][j] = complex<double>(real,imag); + } + } + } - FFT2D(data, width, height, -1); - for(unsigned int j = 0; j < height; ++j) { - for(unsigned int i = 0; i < width; ++i) { - const double real = data[i][j].real(); - const double imag = data[i][j].imag(); - double value = floor(data[i][j].real()+0.5); - value = min(255.0, max(0.0, value)); - resImg->setPixel(i, j, c, value); -// realImg->setPixel(i, j, c, real); -// imagImg->setPixel(i, j, c, imag); + FFT2D(data, width, height, -1); + for(unsigned int j = 0; j < height; ++j) { + for(unsigned int i = 0; i < width; ++i) { + double value = floor(data[i][j].real()+0.5); + value = min(255.0, max(0.0, value)); + resImg->setPixel(i, j, c, value); + } } } } - this->outImage(resImg, "DFT-reconstructed image"); -// this->outDoubleImage(realImg, "DFT-reconstructed image (real)"); -// this->outDoubleImage(imagImg, "DFT-reconstructed image (imag)"); + this->outImage(resImg, qApp->translate("IFFTOp", "DFT-reconstructed image").toStdString()); } diff --git a/app/Operations/ImageListBox.h b/app/Operations/ImageListBox.h deleted file mode 100644 index bab2903a351befc0d4abb70742438dc43fe5a3e5..0000000000000000000000000000000000000000 --- a/app/Operations/ImageListBox.h +++ /dev/null @@ -1,111 +0,0 @@ -/* - * Copyright 2011-2012 INSA Rennes - * - * This file is part of EIImage. - * - * EIImage is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * EIImage 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 General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with EIImage. If not, see <http://www.gnu.org/licenses/>. -*/ - -#ifndef IMAGELISTBOX_H -#define IMAGELISTBOX_H - -#include <QComboBox> -#include <map> -#include <string> - -#include <Image.h> - -template<typename D> -class ImageListBox_t : public QComboBox -{ -public: - explicit ImageListBox_t(QWidget *parent, const imagein::Image_t<D>* img, const std::map<const imagein::Image_t<D>*, std::string>& imgList) - : QComboBox(parent) - { - int i = 0, index = 0; - for(typename std::map<const imagein::Image_t<D>*, std::string>::const_iterator it = imgList.begin(); it != imgList.end(); ++it) { - _images.insert(std::pair<std::string, const imagein::Image_t<D>*>(it->second, it->first)); - this->insertItem(i, QString(it->second.c_str())); - if(it->first == img) index = i; - } - this->setCurrentIndex(index); - } - - const imagein::Image_t<D>* currentImage() { - std::string name = this->currentText().toStdString(); - typename std::map<std::string, const imagein::Image_t<D>*>::iterator it = _images.find(name); - if(it != _images.end()) { - return _images[name]; - } - return NULL; - } -protected: - std::map<std::string, const imagein::Image_t<D>*> _images; -}; - -typedef ImageListBox_t<imagein::Image::depth_t> ImageListBox; - -class MixImageListBox : public QComboBox -{ -public: - enum ImageType {STDIMG, DBLIMG}; - explicit MixImageListBox(QWidget *parent, - std::string currentImg, - std::map<const imagein::Image*,std::string> stdImgs, - std::map<const imagein::Image_t<double>*,std::string> dblImgs) - : QComboBox(parent) - { - int i = 0, index = 0; - for(typename std::map<const imagein::Image*, std::string>::const_iterator it = stdImgs.begin(); it != stdImgs.end(); ++it) { - _images.insert(std::pair<std::string, ImageType>(it->second, STDIMG)); - _stdImgs.insert(std::pair<std::string, const imagein::Image*>(it->second, it->first)); - this->insertItem(i, QString(it->second.c_str())); - if(it->second == currentImg) index = i; - } - for(typename std::map<const imagein::Image_t<double>*, std::string>::const_iterator it = dblImgs.begin(); it != dblImgs.end(); ++it) { - _images.insert(std::pair<std::string, ImageType>(it->second, DBLIMG)); - _dblImgs.insert(std::pair<std::string, const imagein::Image_t<double>*>(it->second, it->first)); - this->insertItem(i, QString(it->second.c_str())); - if(it->second == currentImg) index = i; - } - this->setCurrentIndex(index); - } - - ImageType currentType() { - std::string name = this->currentText().toStdString(); - return _images[name]; - } - - const imagein::Image* getStdImage(std::string name) { - typename std::map<std::string, const imagein::Image*>::iterator it = _stdImgs.find(name); - if(it != _stdImgs.end()) { - return _stdImgs[name]; - } - return NULL; - } - - const imagein::Image_t<double>* getDblImage(std::string name) { - typename std::map<std::string, const imagein::Image_t<double>*>::iterator it = _dblImgs.find(name); - if(it != _dblImgs.end()) { - return _dblImgs[name]; - } - return NULL; - } -protected: - std::map<std::string, ImageType> _images; - std::map<std::string, const imagein::Image*> _stdImgs; - std::map<std::string, const imagein::Image_t<double>*> _dblImgs; - -}; -#endif // IMAGELISTBOX_H diff --git a/app/Operations/InverseHoughDialog.cpp b/app/Operations/InverseHoughDialog.cpp new file mode 100644 index 0000000000000000000000000000000000000000..6b965454b11ffc83fbf401c07a85e273166dc0d4 --- /dev/null +++ b/app/Operations/InverseHoughDialog.cpp @@ -0,0 +1,41 @@ +/* + * Copyright 2011-2012 INSA Rennes + * + * This file is part of EIImage. + * + * EIImage is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * EIImage 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with EIImage. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include "InverseHoughDialog.h" +#include "ui_InverseHoughDialog.h" + +InverseHoughDialog::InverseHoughDialog(QWidget *parent) : + QDialog(parent), + ui(new Ui::InverseHoughDialog) +{ + ui->setupUi(this); +} + +InverseHoughDialog::~InverseHoughDialog() +{ + delete ui; +} + +int InverseHoughDialog::getSize() const { + return ui->sizeBox->value(); +} + +int InverseHoughDialog::getThreshodl() const { + return ui->thresholdBox->value(); +} diff --git a/app/Operations/InverseHoughDialog.h b/app/Operations/InverseHoughDialog.h new file mode 100644 index 0000000000000000000000000000000000000000..adb6fc2937f0afeb95d5074ccf43e5ea9f65a686 --- /dev/null +++ b/app/Operations/InverseHoughDialog.h @@ -0,0 +1,43 @@ +/* + * Copyright 2011-2012 INSA Rennes + * + * This file is part of EIImage. + * + * EIImage is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * EIImage 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with EIImage. If not, see <http://www.gnu.org/licenses/>. +*/ + +#ifndef INVERSEHOUGHDIALOG_H +#define INVERSEHOUGHDIALOG_H + +#include <QDialog> + +namespace Ui { +class InverseHoughDialog; +} + +class InverseHoughDialog : public QDialog +{ + Q_OBJECT + +public: + explicit InverseHoughDialog(QWidget *parent = 0); + ~InverseHoughDialog(); + int getSize() const; + int getThreshodl() const; + +private: + Ui::InverseHoughDialog *ui; +}; + +#endif // INVERSEHOUGHDIALOG_H diff --git a/app/Operations/InverseHoughDialog.ui b/app/Operations/InverseHoughDialog.ui new file mode 100644 index 0000000000000000000000000000000000000000..08a3cce3b4b4fc193dd651f7f0e103ff5583bc04 --- /dev/null +++ b/app/Operations/InverseHoughDialog.ui @@ -0,0 +1,105 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>InverseHoughDialog</class> + <widget class="QDialog" name="InverseHoughDialog"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>279</width> + <height>113</height> + </rect> + </property> + <property name="windowTitle"> + <string>Inverse hough transform</string> + </property> + <layout class="QVBoxLayout" name="verticalLayout"> + <item> + <layout class="QFormLayout" name="formLayout"> + <item row="0" column="0"> + <widget class="QLabel" name="label"> + <property name="text"> + <string>Reconstructed image size : </string> + </property> + </widget> + </item> + <item row="0" column="1"> + <widget class="QSpinBox" name="sizeBox"> + <property name="minimum"> + <number>1</number> + </property> + <property name="maximum"> + <number>65536</number> + </property> + <property name="singleStep"> + <number>128</number> + </property> + <property name="value"> + <number>256</number> + </property> + </widget> + </item> + <item row="1" column="0"> + <widget class="QLabel" name="label_2"> + <property name="text"> + <string>Reconstruction threshold : </string> + </property> + </widget> + </item> + <item row="1" column="1"> + <widget class="QSpinBox" name="thresholdBox"> + <property name="maximum"> + <number>65536</number> + </property> + </widget> + </item> + </layout> + </item> + <item> + <widget class="QDialogButtonBox" name="buttonBox"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="standardButtons"> + <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set> + </property> + </widget> + </item> + </layout> + </widget> + <resources/> + <connections> + <connection> + <sender>buttonBox</sender> + <signal>accepted()</signal> + <receiver>InverseHoughDialog</receiver> + <slot>accept()</slot> + <hints> + <hint type="sourcelabel"> + <x>248</x> + <y>254</y> + </hint> + <hint type="destinationlabel"> + <x>157</x> + <y>274</y> + </hint> + </hints> + </connection> + <connection> + <sender>buttonBox</sender> + <signal>rejected()</signal> + <receiver>InverseHoughDialog</receiver> + <slot>reject()</slot> + <hints> + <hint type="sourcelabel"> + <x>316</x> + <y>260</y> + </hint> + <hint type="destinationlabel"> + <x>286</x> + <y>274</y> + </hint> + </hints> + </connection> + </connections> +</ui> diff --git a/app/Operations/InverseHoughOp.cpp b/app/Operations/InverseHoughOp.cpp new file mode 100644 index 0000000000000000000000000000000000000000..963159472d7c976b8a4b6cdc1945ee6f69314c87 --- /dev/null +++ b/app/Operations/InverseHoughOp.cpp @@ -0,0 +1,45 @@ +/* + * Copyright 2011-2012 INSA Rennes + * + * This file is part of EIImage. + * + * EIImage is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * EIImage 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with EIImage. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include "InverseHoughOp.h" +#include <QApplication> +#include "Transforms.h" +#include "InverseHoughDialog.h" + +using namespace std; +using namespace imagein; + +InverseHoughOp::InverseHoughOp() : DoubleOperation(qApp->translate("Operations", "Houghman inverse transform").toStdString()) +{ +} + +bool InverseHoughOp::needCurrentImg() const { + return true; +} + +void InverseHoughOp::operator()(const imagein::Image_t<double>* img, const std::map<const imagein::Image_t<double>*, std::string>&) { + InverseHoughDialog* dialog = new InverseHoughDialog(QApplication::activeWindow()); + QDialog::DialogCode code = static_cast<QDialog::DialogCode>(dialog->exec()); + + + if(code!=QDialog::Accepted) return; + Image* resImg2; + Transforms::hough2_inverse(img, &resImg2, dialog->getSize(), dialog->getThreshodl()); + outImage(resImg2, qApp->translate("Hough", "Hough inverse transform").toStdString()); +} diff --git a/app/Operations/InverseHoughOp.h b/app/Operations/InverseHoughOp.h new file mode 100644 index 0000000000000000000000000000000000000000..9d0654ab7d78ae596b03c30d873abaf80cdeb5f8 --- /dev/null +++ b/app/Operations/InverseHoughOp.h @@ -0,0 +1,35 @@ +/* + * Copyright 2011-2012 INSA Rennes + * + * This file is part of EIImage. + * + * EIImage is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * EIImage 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with EIImage. If not, see <http://www.gnu.org/licenses/>. +*/ + +#ifndef INVERSEHOUGHOP_H +#define INVERSEHOUGHOP_H + +#include <Operation.h> + +class InverseHoughOp : public DoubleOperation +{ +public: + InverseHoughOp(); + + void operator()(const imagein::Image_t<double>*, const std::map<const imagein::Image_t<double>*, std::string>&); + + bool needCurrentImg() const; +}; + +#endif // INVERSEHOUGHOP_H diff --git a/app/Operations/InversePyramidDialog.cpp b/app/Operations/InversePyramidDialog.cpp new file mode 100644 index 0000000000000000000000000000000000000000..b8f4712d654e02aac0217ac48da5042df05da3b5 --- /dev/null +++ b/app/Operations/InversePyramidDialog.cpp @@ -0,0 +1,54 @@ +/* + * Copyright 2011-2012 INSA Rennes + * + * This file is part of EIImage. + * + * EIImage is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * EIImage 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with EIImage. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include "InversePyramidDialog.h" +#include "ui_InversePyramidDialog.h" + +InversePyramidDialog::InversePyramidDialog(QWidget *parent) : + QDialog(parent), + ui(new Ui::InversePyramidDialog) +{ + ui->setupUi(this); +} + +InversePyramidDialog::~InversePyramidDialog() +{ + delete ui; +} + +Pyramid::filtre InversePyramidDialog::getFilter() const { + Pyramid::Filters filters; + Pyramid::filtre filter; + switch(ui->filterBox->currentIndex()) { + case 1: filters.getFromName("gaussien", filter); break; + case 2: filters.getFromName("trimodal", filter); break; + case 3: filters.getFromName("rectangulaire", filter); break; + case 4: filters.getFromName("qmf", filter); break; + default: filters.getFromName("triangulaire", filter); break; + } + return filter; +} + +int InversePyramidDialog::getNbStep() const { + return ui->nbStepBox->value(); +} + +int InversePyramidDialog::getStep() const { + return ui->stepBox->value(); +} diff --git a/app/Operations/InversePyramidDialog.h b/app/Operations/InversePyramidDialog.h new file mode 100644 index 0000000000000000000000000000000000000000..3a29ec3ffeff69626b4fcd7ecf92e90236e270a8 --- /dev/null +++ b/app/Operations/InversePyramidDialog.h @@ -0,0 +1,46 @@ +/* + * Copyright 2011-2012 INSA Rennes + * + * This file is part of EIImage. + * + * EIImage is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * EIImage 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with EIImage. If not, see <http://www.gnu.org/licenses/>. +*/ + +#ifndef INVERSEPYRAMIDDIALOG_H +#define INVERSEPYRAMIDDIALOG_H + +#include <QDialog> +#include "../Algorithms/Pyramid.h" + +namespace Ui { +class InversePyramidDialog; +} + +class InversePyramidDialog : public QDialog +{ + Q_OBJECT + +public: + explicit InversePyramidDialog(QWidget *parent = 0); + ~InversePyramidDialog(); + Pyramid::filtre getFilter() const; + int getNbStep() const; + int getStep() const; + + +private: + Ui::InversePyramidDialog *ui; +}; + +#endif // INVERSEPYRAMIDDIALOG_H diff --git a/app/Operations/InversePyramidDialog.ui b/app/Operations/InversePyramidDialog.ui new file mode 100644 index 0000000000000000000000000000000000000000..22f4b2938106d0bcb12902621a059f42ad5c344d --- /dev/null +++ b/app/Operations/InversePyramidDialog.ui @@ -0,0 +1,166 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>InversePyramidDialog</class> + <widget class="QDialog" name="InversePyramidDialog"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>245</width> + <height>225</height> + </rect> + </property> + <property name="windowTitle"> + <string>Pyramidal reconstruction</string> + </property> + <layout class="QVBoxLayout" name="verticalLayout"> + <item> + <widget class="QLabel" name="label"> + <property name="text"> + <string>Filter : </string> + </property> + </widget> + </item> + <item> + <widget class="QComboBox" name="filterBox"> + <item> + <property name="text"> + <string>triangular</string> + </property> + </item> + <item> + <property name="text"> + <string>gaussian</string> + </property> + </item> + <item> + <property name="text"> + <string>trimodal</string> + </property> + </item> + <item> + <property name="text"> + <string>rectangular</string> + </property> + </item> + <item> + <property name="text"> + <string>qmf</string> + </property> + </item> + </widget> + </item> + <item> + <spacer name="verticalSpacer"> + <property name="orientation"> + <enum>Qt::Vertical</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>20</width> + <height>40</height> + </size> + </property> + </spacer> + </item> + <item> + <widget class="QLabel" name="nbStepLabel"> + <property name="text"> + <string>Number of steps in the pyramid : </string> + </property> + </widget> + </item> + <item> + <widget class="QSpinBox" name="nbStepBox"> + <property name="minimum"> + <number>1</number> + </property> + <property name="maximum"> + <number>9</number> + </property> + <property name="value"> + <number>9</number> + </property> + </widget> + </item> + <item> + <spacer name="verticalSpacer_2"> + <property name="orientation"> + <enum>Qt::Vertical</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>20</width> + <height>40</height> + </size> + </property> + </spacer> + </item> + <item> + <widget class="QLabel" name="label_2"> + <property name="text"> + <string>Step to reconstruct :</string> + </property> + </widget> + </item> + <item> + <widget class="QSpinBox" name="stepBox"> + <property name="minimum"> + <number>0</number> + </property> + <property name="maximum"> + <number>8</number> + </property> + <property name="value"> + <number>0</number> + </property> + </widget> + </item> + <item> + <widget class="QDialogButtonBox" name="buttonBox_2"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="standardButtons"> + <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set> + </property> + </widget> + </item> + </layout> + </widget> + <resources/> + <connections> + <connection> + <sender>buttonBox_2</sender> + <signal>accepted()</signal> + <receiver>InversePyramidDialog</receiver> + <slot>accept()</slot> + <hints> + <hint type="sourcelabel"> + <x>122</x> + <y>191</y> + </hint> + <hint type="destinationlabel"> + <x>122</x> + <y>106</y> + </hint> + </hints> + </connection> + <connection> + <sender>buttonBox_2</sender> + <signal>rejected()</signal> + <receiver>InversePyramidDialog</receiver> + <slot>reject()</slot> + <hints> + <hint type="sourcelabel"> + <x>122</x> + <y>191</y> + </hint> + <hint type="destinationlabel"> + <x>122</x> + <y>106</y> + </hint> + </hints> + </connection> + </connections> +</ui> diff --git a/app/Operations/InversePyramidOp.cpp b/app/Operations/InversePyramidOp.cpp new file mode 100644 index 0000000000000000000000000000000000000000..cc4e6f19d51949d06e0aa8fc67f237614917dd24 --- /dev/null +++ b/app/Operations/InversePyramidOp.cpp @@ -0,0 +1,70 @@ +/* + * Copyright 2011-2012 INSA Rennes + * + * This file is part of EIImage. + * + * EIImage is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * EIImage 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with EIImage. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include "InversePyramidOp.h" +#include <QApplication> +#include <QMessageBox> +#include "../Algorithms/Pyramid.h" +#include "InversePyramidDialog.h" +#include <GrayscaleImage.h> +#include <Converter.h> + +using namespace std; +using namespace imagein; + +InversePyramidOp::InversePyramidOp() : Operation(qApp->translate("Operations", "Pyramidal reconstruction").toStdString()) +{ +} + +bool InversePyramidOp::needCurrentImg() const { + return true; +} + +void InversePyramidOp::operator()(const imagein::Image* img, const std::map<const imagein::Image*, std::string>&) { + if(2 * img->getWidth() != img->getHeight()) { + QMessageBox::warning(NULL, qApp->translate("Operations", "The operation can't be applied on this image"), + qApp->translate("Operations", "The image width must be twice the image height.")); + return; + } + if(!Pyramid::isPowerOf2(img->getWidth())) { + QMessageBox::warning(NULL, qApp->translate("Operations", "The operation can't be applied on this image"), + qApp->translate("Operations", "The image dimensions must be power of 2.")); + return; + } + + InversePyramidDialog* dialog = new InversePyramidDialog(QApplication::activeWindow()); + QDialog::DialogCode code = static_cast<QDialog::DialogCode>(dialog->exec()); + + if(code!=QDialog::Accepted) return; + + GrayscaleImage* image = Converter<GrayscaleImage>::convert(*img); + Image* resImg = NULL; + string s; + Pyramid::filtre filter = dialog->getFilter(); + try { + resImg = Pyramid::rebuild_interface(image, dialog->getNbStep(), dialog->getStep(), filter); + } + catch(const char*e) { + QMessageBox::critical(NULL, "Error", QString(e)); + return; + } + outImage(resImg, "Pyramid"); + outText(s); + +} diff --git a/app/Operations/InversePyramidOp.h b/app/Operations/InversePyramidOp.h new file mode 100644 index 0000000000000000000000000000000000000000..2c56a1b64f90661fa9301991131533d1fae2205d --- /dev/null +++ b/app/Operations/InversePyramidOp.h @@ -0,0 +1,35 @@ +/* + * Copyright 2011-2012 INSA Rennes + * + * This file is part of EIImage. + * + * EIImage is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * EIImage 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with EIImage. If not, see <http://www.gnu.org/licenses/>. +*/ + +#ifndef INVERSEPYRAMID_H +#define INVERSEPYRAMID_H + +#include <Operation.h> + +class InversePyramidOp : public Operation +{ +public: + InversePyramidOp(); + + void operator()(const imagein::Image*, const std::map<const imagein::Image*, std::string>&); + + bool needCurrentImg() const; +}; + +#endif // INVERSEPYRAMID_H diff --git a/app/Operations/MICD.cpp b/app/Operations/MICD.cpp new file mode 100644 index 0000000000000000000000000000000000000000..03232e87cc1fc77e98b2676e646f972e0646e1c0 --- /dev/null +++ b/app/Operations/MICD.cpp @@ -0,0 +1,262 @@ +/* + * Copyright 2011-2012 INSA Rennes + * + * This file is part of EIImage. + * + * EIImage is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * EIImage 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with EIImage. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include "MICD.h" +#include <cstring> +#include <cstdio> + +using namespace std; +using namespace imagein; + +MICD::MICD() +{ + long counter; + for( counter=0; counter< 128; counter++ ) { + iloiqu[counter] = 0; + } + for( counter=0; counter< 2048*20; counter++ ) { + ((int*)itcod)[counter] = 0; + ((int*)itrco)[counter] = 0; + } + for( counter=0; counter< 40; counter++ ) { + ((int*)ktab)[counter] = 0; + } + quantdef = NULL; +} + +MICD::~MICD() +{ + +} + +string MICD::execute( const GrayscaleImage *im, Prediction prediction_alg, Image **err_image, Image **recons_image, double Q ) { + char buffer[255]; + if( quantdef == NULL ) { + throw "Error in MICD::execute:\nquantdef = NULL"; + } + string returnval; + int nbl,nbc,size,rep,i,j,pred,ier,ireco,icode; + float pi[512],nbpt = 0; + double h = 0.; + rep = prediction_alg; + + nbl = im->getHeight(); + nbc = im->getWidth(); + size = nbc * nbl; + + int po; + int temp_p; + /* initialisation de la loi de quantification */ + set_levels(); + codlq(0); + /* allocation mmoire pour l'image d'erreur de prdiction */ + GrayscaleImage *error_prediction_image = new GrayscaleImage(nbc, nbl); + Image *reconstructed_image = new GrayscaleImage(*im); + // File these images with all values of zero + long wcounter, hcounter; + for( hcounter=0; hcounter< nbl; hcounter++ ) { + for( wcounter=0; wcounter< nbc; wcounter++ ) { + error_prediction_image->setPixelAt(wcounter, hcounter, 0); + } + } + + /* mise 0 du tableau des probas servant pour le calcul de + l'entropie de l'erreur de prdiction */ + for(i=0 ; i<512 ; i++) pi[i]= 0.; + + /* codage de l'image */ + for(i=1; i<nbl ; i++) + { + for(j=1; j<nbc ; j++) + { + if(rep == PX_EQ_A) { + temp_p = reconstructed_image->getPixelAt( j - 1, i ); + pred = temp_p; + } + else if(rep == PX_EQ_B) { + temp_p = reconstructed_image->getPixelAt( j, i - 1); + pred = temp_p; + } + else if(rep == PX_EQ_APC) { + temp_p = reconstructed_image->getPixelAt( j - 1, i ); + pred = (int)temp_p; + temp_p = reconstructed_image->getPixelAt( j, i - 1 ); + pred = ( pred + (int)temp_p ) / 2; + } + else if(rep == PX_EQ_Q) { + /* + Modified Graham's Algorithm: + if |B-C| - Q <= |B-A| <= |B-C| + Q + P(X) = (A+C)/2 + else + if |B-A| > |B-C| + P(X) = A + else + P(X) = C + */ + float A = im->getPixelAt( j - 1, i ); + float B = im->getPixelAt( j - 1, i - 1 ); + float C = im->getPixelAt( j, i - 1 ); + if( ((fabs(B-C) - Q) <= fabs(B-A)) && + (fabs(B-A) <= (fabs(B-C) + Q)) ) { + pred = (uint8_t)((A + C) / 2); + } + else { + if( fabs(B-A) > fabs(B-C) ) { + pred = (uint8_t)A; + } + else { + pred = (uint8_t)C; + } + } + } + + temp_p = reconstructed_image->getPixelAt( j, i ); + ier = (int)temp_p - pred; + codec(0,ier,&icode,&ireco); + pi[ier+255]++; /* proba associe l'erreur de prdiction */ + nbpt++; + + int tempvalue; + tempvalue = ier + 128; + if( tempvalue > 255 ) tempvalue = 255; + if( tempvalue < 0 ) tempvalue = 0; + po = tempvalue; + error_prediction_image->setPixelAt( j, i, po ); + tempvalue = pred + ireco; + if( tempvalue > 255 ) tempvalue = 255; + if( tempvalue < 0 ) tempvalue = 0; + po = tempvalue; + reconstructed_image->setPixelAt( j, i, po ); + } + } + + /* calcul de l'entropie de l'image d'erreur de prdiction */ + for(i=0 ; i<512 ; i++) + { + if(pi[i] != 0) { + pi[i] /= nbpt; + h -= (double)pi[i] * log((double)pi[i])/log((double)2.0); + } + } + + + /* affichage des rsultats */ + sprintf(buffer, "\nL'entropie de l'image d'erreur de prediction vaut : %lf\n",h); + returnval = returnval + buffer; + returnval = returnval + "\n"; + returnval = returnval + print_iloiqu(); + + + /* libration de la mmoire alloue */ + *err_image = error_prediction_image; + *recons_image = reconstructed_image; + return returnval; +} + +void MICD::codlq(int m) { + int n,nar,nk,i,j; + + n=iloiqu[0]; + ktab[0][m]=iloiqu[1]; + nar=ktab[0][m] - 1; + j= -1; + for(i=0;i < n-1 ; i++) + { + nk=1+nar-iloiqu[2*i+1]; + do{j++;itcod[j][m]=i;nk++;} while(nk <= 0); + nar=iloiqu[2*i+1]; + itrco[i][m]=iloiqu[2*i+2]; + } + itcod[j+1][m]=i; + itrco[i][m]=iloiqu[2*i+2]; + ktab[1][m]=iloiqu[2*i+1]; +} + +void MICD::codec(int nlq,int ier,int *icode,int *ireco) { + int m,ip,iep,ierp,n,l; + m=nlq; + ip=ktab[0][m]; + ierp=ier-ip; + if(ierp > 0) + { + ip=ktab[1][m]; + iep=ier-ip; + if(iep < 0) + n=ier - ktab[0][m]; + else + n=ktab[1][m] - ktab[0][m]; + *icode=itcod[n][m]; + l= *icode; + *ireco=itrco[l][m]; + } + else + { + *icode=itcod[0][m]; + *ireco=itrco[0][m]; + } +} + +void MICD::set_levels() { + // Fills in iloiqu with the specified values + if( quantdef->size - 1 > 32 || quantdef->size - 1 < 1 ) { + char buffer[255]; + sprintf( buffer, "Error in MICD::set_levels:\nquantdef->GetNumThresholds() = %d", quantdef->size - 1 ); + throw buffer; + } + int counter; + iloiqu[0] = quantdef->size; + for( counter=0; counter< quantdef->size - 1; counter++ ) { + iloiqu[ counter * 2 + 1 ] = quantdef->threshold[ counter ]; + iloiqu[ counter * 2 + 2 ] = quantdef->values[ counter ]; + } + iloiqu[ (quantdef->size - 1) * 2 + 1 ] = iloiqu[ (quantdef->size - 1) * 2 - 1 ] + 1; + iloiqu[ (quantdef->size - 1) * 2 + 2 ] = quantdef->values[ quantdef->size - 1 ]; +} + +string MICD::print_iloiqu() { + string returnval; + returnval = "seuils de dcision --------------- niveaux de reconstruction\n"; + int counter; + char buffer[100]; + for( counter=1; counter<= iloiqu[0]*2-1; counter++ ) { + if( !(counter & 1 == 1) ) { + sprintf( buffer, " %3d \n", iloiqu[counter] ); + returnval = returnval + buffer; + sprintf( buffer, " %3d ---------------------------------------------\n", iloiqu[counter-1] ); + returnval = returnval + buffer; + } + } + sprintf( buffer, " %3d \n", iloiqu[counter] ); + returnval = returnval + buffer; + + return returnval; +} + +void MICD::setQuantification( Quantification *tquantdef ) { + if( tquantdef == NULL ) { + throw "Error in MICD::setQuantDef:\ntquantdef = NULL"; + } + if( tquantdef->size - 1 > 32 || tquantdef->size - 1 < 1 ) { + char buffer[255]; + sprintf( buffer, "Error in MICD::setQuantDef:\ntquantdef->GetNumThresholds() = %d", tquantdef->size - 1 ); + throw buffer; + } + quantdef = tquantdef; +} diff --git a/core/ImgWidget.h b/app/Operations/MICD.h similarity index 51% rename from core/ImgWidget.h rename to app/Operations/MICD.h index a8b96687b7a57c769ef20393b4ddebbb16be9744..c54b9fa82bfd776033628b185c98b469d80eb0b2 100644 --- a/core/ImgWidget.h +++ b/app/Operations/MICD.h @@ -1,40 +1,45 @@ /* * Copyright 2011-2012 INSA Rennes - * + * * This file is part of EIImage. - * + * * EIImage is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. - * + * * EIImage 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 General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with EIImage. If not, see <http://www.gnu.org/licenses/>. */ -#include "Image.h" -#include <QWidget> +#ifndef MICD_H +#define MICD_H + #include <string> +#include <GrayscaleImage.h> +#include "Quantification.h" -class ImgWidget : public QWidget { - public: - ImgWidget(imagein::Image* img_, std::string name_) : img(img_), name(name_) {} - imagein::Image* img; - std::string name; +class MICD +{ +public: + MICD(); + enum Prediction {PX_EQ_A, PX_EQ_B, PX_EQ_APC, PX_EQ_Q}; + virtual ~MICD(); + std::string execute( const imagein::GrayscaleImage *im, Prediction prediction_alg, imagein::Image **err_image, imagein::Image **recons_image, double Q = 0 ); + void setQuantification( Quantification* tquantdef ); +private: + std::string print_iloiqu(); + Quantification* quantdef; + void codlq(int m); + void codec(int nlq,int ier,int *icode,int *ireco); + void set_levels(); + int iloiqu[128]; + int itcod[2048][20],itrco[2048][20],ktab[2][20]; }; - -class DoubleImgWidget : public QWidget { - public: - DoubleImgWidget(imagein::Image_t<double>* img_, std::string name_, bool normalize_ = false, bool logScale_ = false) - : img(img_), name(name_), normalize(normalize_), logScale(logScale_) {} - imagein::Image_t<double>* img; - std::string name; - bool normalize; - bool logScale; -}; +#endif // MICD_H diff --git a/app/Operations/MICDDialog.cpp b/app/Operations/MICDDialog.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ca87540404c5ec314f653717af6a12e9937c5cd3 --- /dev/null +++ b/app/Operations/MICDDialog.cpp @@ -0,0 +1,71 @@ +/* + * Copyright 2011-2012 INSA Rennes + * + * This file is part of EIImage. + * + * EIImage is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * EIImage 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with EIImage. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include "MICDDialog.h" +#include "ui_MICDDialog.h" +#include <QFileDialog> +#include "QuantificationDialog.h" + +MICDDialog::MICDDialog(QWidget *parent) : + QDialog(parent), + ui(new Ui::MICDDialog) +{ + ui->setupUi(this); +} + +MICDDialog::~MICDDialog() +{ + delete ui; +} + +void MICDDialog::on_quantBrowseButton_clicked() +{ + QString filename = QFileDialog::getOpenFileName(this, tr("Open file"), "", tr("Loi de quantification (*.loi)")); + ui->quantFileEdit->setText(filename); +} + +void MICDDialog::on_quantEditorButton_clicked() +{ + + QuantificationDialog* dialog = new QuantificationDialog(QApplication::activeWindow()); + dialog->exec(); +} + +Quantification* MICDDialog::getQuantification() const { + try { + Quantification* quantif = new Quantification(ui->quantFileEdit->text().toStdString()); + return quantif; + } + catch(std::exception&) { + return NULL; + } + +} + +MICD::Prediction MICDDialog::getPrediction() const { + if(ui->predictRadioA->isChecked()) return MICD::PX_EQ_A; + else if(ui->predictRadioAC->isChecked()) return MICD::PX_EQ_B; + else if(ui->predictRadioC->isChecked()) return MICD::PX_EQ_APC; + else if(ui->predictRadioGraham->isChecked()) return MICD::PX_EQ_Q; + else return MICD::PX_EQ_A; +} + +double MICDDialog::getQ() const { + return ui->qSpinBox->value(); +} diff --git a/app/Operations/MICDDialog.h b/app/Operations/MICDDialog.h new file mode 100644 index 0000000000000000000000000000000000000000..c4d15eaab4ceb4ae350af5e67e6faeb049677329 --- /dev/null +++ b/app/Operations/MICDDialog.h @@ -0,0 +1,51 @@ +/* + * Copyright 2011-2012 INSA Rennes + * + * This file is part of EIImage. + * + * EIImage is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * EIImage 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with EIImage. If not, see <http://www.gnu.org/licenses/>. +*/ + +#ifndef MICDDIALOG_H +#define MICDDIALOG_H + +#include <QDialog> +#include "Quantification.h" +#include "MICD.h" + +namespace Ui { +class MICDDialog; +} + +class MICDDialog : public QDialog +{ + Q_OBJECT + +public: + explicit MICDDialog(QWidget *parent = 0); + ~MICDDialog(); + Quantification* getQuantification() const; + MICD::Prediction getPrediction() const; + double getQ() const; + +private slots: + void on_quantBrowseButton_clicked(); + + void on_quantEditorButton_clicked(); + +private: + Ui::MICDDialog *ui; +}; + +#endif // MICDDIALOG_H diff --git a/app/Operations/MICDDialog.ui b/app/Operations/MICDDialog.ui new file mode 100644 index 0000000000000000000000000000000000000000..285ec2775cdb223db3949e7eaddb84f3ed76d759 --- /dev/null +++ b/app/Operations/MICDDialog.ui @@ -0,0 +1,259 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>MICDDialog</class> + <widget class="QDialog" name="MICDDialog"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>545</width> + <height>340</height> + </rect> + </property> + <property name="windowTitle"> + <string>MICD encoding</string> + </property> + <layout class="QVBoxLayout" name="verticalLayout"> + <item alignment="Qt::AlignHCenter"> + <widget class="QLabel" name="micdImage"> + <property name="text"> + <string/> + </property> + <property name="pixmap"> + <pixmap resource="../eiimage_app_res.qrc">:/img/micd.png</pixmap> + </property> + </widget> + </item> + <item> + <layout class="QHBoxLayout" name="horizontalLayout"> + <item> + <widget class="QWidget" name="widget" native="true"> + <layout class="QVBoxLayout" name="verticalLayout_2"> + <item> + <widget class="QGroupBox" name="predictorBox"> + <property name="title"> + <string>Predictor P(X)</string> + </property> + <layout class="QVBoxLayout" name="verticalLayout_4"> + <item> + <widget class="QRadioButton" name="predictRadioA"> + <property name="text"> + <string>A</string> + </property> + <property name="checked"> + <bool>true</bool> + </property> + </widget> + </item> + <item> + <widget class="QRadioButton" name="predictRadioC"> + <property name="text"> + <string>C</string> + </property> + </widget> + </item> + <item> + <widget class="QRadioButton" name="predictRadioAC"> + <property name="text"> + <string>( A + C ) / 2</string> + </property> + </widget> + </item> + <item> + <widget class="QRadioButton" name="predictRadioGraham"> + <property name="text"> + <string>Modified Graham's</string> + </property> + </widget> + </item> + <item> + <layout class="QHBoxLayout" name="horizontalLayout_2"> + <item alignment="Qt::AlignRight"> + <widget class="QLabel" name="qLabel"> + <property name="text"> + <string>Q = </string> + </property> + </widget> + </item> + <item> + <widget class="QSpinBox" name="qSpinBox"> + <property name="enabled"> + <bool>false</bool> + </property> + <property name="maximum"> + <number>255</number> + </property> + </widget> + </item> + </layout> + </item> + </layout> + </widget> + </item> + <item> + <spacer name="verticalSpacer"> + <property name="orientation"> + <enum>Qt::Vertical</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>20</width> + <height>40</height> + </size> + </property> + </spacer> + </item> + </layout> + </widget> + </item> + <item> + <widget class="QWidget" name="widget_2" native="true"> + <layout class="QVBoxLayout" name="verticalLayout_3"> + <item> + <widget class="QGroupBox" name="quantifierBox"> + <property name="title"> + <string>Quantifier</string> + </property> + <layout class="QVBoxLayout" name="verticalLayout_5"> + <item> + <widget class="QLabel" name="quantFileLabel"> + <property name="text"> + <string>Quantification file :</string> + </property> + </widget> + </item> + <item> + <layout class="QHBoxLayout" name="horizontalLayout_3"> + <item> + <widget class="QLineEdit" name="quantFileEdit"/> + </item> + <item> + <widget class="QPushButton" name="quantBrowseButton"> + <property name="font"> + <font> + <pointsize>10</pointsize> + <weight>75</weight> + <italic>true</italic> + <bold>true</bold> + </font> + </property> + <property name="text"> + <string>Browse</string> + </property> + <property name="iconSize"> + <size> + <width>8</width> + <height>8</height> + </size> + </property> + </widget> + </item> + </layout> + </item> + <item> + <spacer name="verticalSpacer_2"> + <property name="orientation"> + <enum>Qt::Vertical</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>20</width> + <height>22</height> + </size> + </property> + </spacer> + </item> + <item> + <widget class="QPushButton" name="quantEditorButton"> + <property name="text"> + <string>Open quantification editor</string> + </property> + </widget> + </item> + <item> + <spacer name="verticalSpacer_3"> + <property name="orientation"> + <enum>Qt::Vertical</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>20</width> + <height>22</height> + </size> + </property> + </spacer> + </item> + </layout> + </widget> + </item> + </layout> + </widget> + </item> + </layout> + </item> + <item> + <widget class="QDialogButtonBox" name="buttonBox"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="standardButtons"> + <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set> + </property> + </widget> + </item> + </layout> + </widget> + <resources> + <include location="../eiimage_app_res.qrc"/> + </resources> + <connections> + <connection> + <sender>buttonBox</sender> + <signal>accepted()</signal> + <receiver>MICDDialog</receiver> + <slot>accept()</slot> + <hints> + <hint type="sourcelabel"> + <x>248</x> + <y>254</y> + </hint> + <hint type="destinationlabel"> + <x>157</x> + <y>274</y> + </hint> + </hints> + </connection> + <connection> + <sender>buttonBox</sender> + <signal>rejected()</signal> + <receiver>MICDDialog</receiver> + <slot>reject()</slot> + <hints> + <hint type="sourcelabel"> + <x>316</x> + <y>260</y> + </hint> + <hint type="destinationlabel"> + <x>286</x> + <y>274</y> + </hint> + </hints> + </connection> + <connection> + <sender>predictRadioGraham</sender> + <signal>toggled(bool)</signal> + <receiver>qSpinBox</receiver> + <slot>setEnabled(bool)</slot> + <hints> + <hint type="sourcelabel"> + <x>113</x> + <y>224</y> + </hint> + <hint type="destinationlabel"> + <x>153</x> + <y>256</y> + </hint> + </hints> + </connection> + </connections> +</ui> diff --git a/app/Operations/MICDDialog_.ui b/app/Operations/MICDDialog_.ui new file mode 100644 index 0000000000000000000000000000000000000000..9e70d160f1ab19798289f922f735163fa762a02e --- /dev/null +++ b/app/Operations/MICDDialog_.ui @@ -0,0 +1,248 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>Dialog</class> + <widget class="QDialog" name="Dialog"> + <property name="windowModality"> + <enum>Qt::WindowModal</enum> + </property> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>678</width> + <height>528</height> + </rect> + </property> + <property name="windowTitle"> + <string>MICD Encoding</string> + </property> + <property name="modal"> + <bool>true</bool> + </property> + <layout class="QVBoxLayout" name="verticalLayout"> + <item alignment="Qt::AlignHCenter|Qt::AlignVCenter"> + <widget class="QLabel" name="label"> + <property name="text"> + <string/> + </property> + <property name="pixmap"> + <pixmap resource="../eiimage_app_res.qrc">:/img/micd.png</pixmap> + </property> + </widget> + </item> + <item> + <layout class="QHBoxLayout" name="horizontalLayout"> + <item> + <widget class="QWidget" name="widget_2" native="true"> + <layout class="QVBoxLayout" name="verticalLayout_4"> + <item> + <widget class="QGroupBox" name="groupBox_2"> + <property name="title"> + <string>Predictor P(X)</string> + </property> + <layout class="QVBoxLayout" name="verticalLayout_3"> + <item> + <widget class="QRadioButton" name="radioButton_3"> + <property name="text"> + <string>A</string> + </property> + </widget> + </item> + <item> + <widget class="QRadioButton" name="radioButton_4"> + <property name="text"> + <string>C</string> + </property> + </widget> + </item> + <item> + <widget class="QRadioButton" name="radioButton_5"> + <property name="text"> + <string>(A + C) / 2</string> + </property> + </widget> + </item> + <item> + <widget class="QRadioButton" name="radioButton_6"> + <property name="text"> + <string>Modified Graham's</string> + </property> + </widget> + </item> + <item> + <layout class="QHBoxLayout" name="horizontalLayout_2"> + <item alignment="Qt::AlignRight"> + <widget class="QLabel" name="label_2"> + <property name="text"> + <string>Q = </string> + </property> + </widget> + </item> + <item> + <widget class="QSpinBox" name="spinBox"> + <property name="maximum"> + <number>255</number> + </property> + </widget> + </item> + </layout> + </item> + <item> + <spacer name="verticalSpacer_4"> + <property name="orientation"> + <enum>Qt::Vertical</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>20</width> + <height>40</height> + </size> + </property> + </spacer> + </item> + </layout> + <zorder>radioButton_3</zorder> + <zorder>radioButton_4</zorder> + <zorder>radioButton_5</zorder> + <zorder>radioButton_6</zorder> + <zorder>verticalSpacer_4</zorder> + </widget> + </item> + </layout> + </widget> + </item> + <item> + <widget class="QWidget" name="widget" native="true"> + <layout class="QVBoxLayout" name="verticalLayout_2"> + <item> + <widget class="QGroupBox" name="groupBox"> + <property name="title"> + <string>Quantifier</string> + </property> + <layout class="QVBoxLayout" name="verticalLayout_5"> + <item> + <widget class="QLabel" name="label_3"> + <property name="text"> + <string>Quantification file :</string> + </property> + </widget> + </item> + <item> + <layout class="QHBoxLayout" name="horizontalLayout_3"> + <item> + <widget class="QLineEdit" name="lineEdit"/> + </item> + <item> + <widget class="QPushButton" name="pushButton"> + <property name="font"> + <font> + <pointsize>10</pointsize> + <weight>75</weight> + <italic>true</italic> + <bold>true</bold> + </font> + </property> + <property name="text"> + <string>Browse</string> + </property> + <property name="iconSize"> + <size> + <width>8</width> + <height>8</height> + </size> + </property> + </widget> + </item> + </layout> + </item> + <item> + <spacer name="verticalSpacer_2"> + <property name="orientation"> + <enum>Qt::Vertical</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>20</width> + <height>40</height> + </size> + </property> + </spacer> + </item> + <item> + <widget class="QPushButton" name="pushButton_2"> + <property name="text"> + <string>Open quantification editor</string> + </property> + </widget> + </item> + <item> + <spacer name="verticalSpacer_3"> + <property name="orientation"> + <enum>Qt::Vertical</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>20</width> + <height>40</height> + </size> + </property> + </spacer> + </item> + </layout> + </widget> + </item> + </layout> + </widget> + </item> + </layout> + </item> + <item> + <widget class="QDialogButtonBox" name="buttonBox"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="standardButtons"> + <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set> + </property> + </widget> + </item> + </layout> + </widget> + <resources> + <include location="../eiimage_app_res.qrc"/> + </resources> + <connections> + <connection> + <sender>buttonBox</sender> + <signal>rejected()</signal> + <receiver>Dialog</receiver> + <slot>reject()</slot> + <hints> + <hint type="sourcelabel"> + <x>316</x> + <y>260</y> + </hint> + <hint type="destinationlabel"> + <x>286</x> + <y>274</y> + </hint> + </hints> + </connection> + <connection> + <sender>buttonBox</sender> + <signal>accepted()</signal> + <receiver>Dialog</receiver> + <slot>accept()</slot> + <hints> + <hint type="sourcelabel"> + <x>248</x> + <y>254</y> + </hint> + <hint type="destinationlabel"> + <x>157</x> + <y>274</y> + </hint> + </hints> + </connection> + </connections> +</ui> diff --git a/app/Operations/MICDEncodingOp.cpp b/app/Operations/MICDEncodingOp.cpp new file mode 100644 index 0000000000000000000000000000000000000000..19e5e2f9ac7e878c442c1ecb64856dbc84c172ea --- /dev/null +++ b/app/Operations/MICDEncodingOp.cpp @@ -0,0 +1,63 @@ +/* + * Copyright 2011-2012 INSA Rennes + * + * This file is part of EIImage. + * + * EIImage is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * EIImage 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with EIImage. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include "MICDEncodingOp.h" +#include "../Tools.h" +#include <QApplication> +#include "MICDDialog.h" +#include "MICD.h" +#include <QMessageBox> +#include <GrayscaleImage.h> +#include <Converter.h> + +using namespace std; +using namespace imagein; + +MICDEncodingOp::MICDEncodingOp() : Operation(qApp->translate("Operations", "MICD Encoding").toStdString()) +{ +} + +bool MICDEncodingOp::needCurrentImg() const { + return true; +} + +void MICDEncodingOp::operator()(const imagein::Image* img, const std::map<const imagein::Image*, std::string>&) { + + MICDDialog* dialog = new MICDDialog(QApplication::activeWindow()); + QDialog::DialogCode code = static_cast<QDialog::DialogCode>(dialog->exec()); + + + if(code!=QDialog::Accepted) return; + + MICD micd; + try { + micd.setQuantification(dialog->getQuantification()); + } + catch(const char* str) { + QMessageBox::critical(NULL, qApp->translate("MICD", "Error while loading quantification file"), qApp->translate("MICD", "The specified quantification file could not be opened !")); + return; + } + GrayscaleImage* image = Converter<GrayscaleImage>::convert(*img); + Image *errorImage, *reconstructedImage; + string s = micd.execute(image, dialog->getPrediction(), &errorImage, &reconstructedImage, dialog->getQ()); + outText(s); + outImage(errorImage, qApp->translate("MICD", "Error image").toStdString()); + outImage(reconstructedImage, qApp->translate("MICD", "Reconstructed image").toStdString()); +} + diff --git a/app/Operations/MICDEncodingOp.h b/app/Operations/MICDEncodingOp.h new file mode 100644 index 0000000000000000000000000000000000000000..cb0522ad8c7f84e3ef1574deec594bfa6c6de0a1 --- /dev/null +++ b/app/Operations/MICDEncodingOp.h @@ -0,0 +1,35 @@ +/* + * Copyright 2011-2012 INSA Rennes + * + * This file is part of EIImage. + * + * EIImage is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * EIImage 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with EIImage. If not, see <http://www.gnu.org/licenses/>. +*/ + +#ifndef MICDENCODINGOP_H +#define MICDENCODINGOP_H + +#include <Operation.h> + +class MICDEncodingOp : public Operation +{ +public: + MICDEncodingOp(); + + void operator()(const imagein::Image*, const std::map<const imagein::Image*, std::string>&); + + bool needCurrentImg() const; +}; + +#endif // MICDENCODINGOP_H diff --git a/app/Operations/MeanSquaredErrorOp.cpp b/app/Operations/MeanSquaredErrorOp.cpp index 04be9f01bb38c503818ab7c5e9f34044877d2821..ac9409a8b6a26621e3879cce3a1b020f696b30eb 100644 --- a/app/Operations/MeanSquaredErrorOp.cpp +++ b/app/Operations/MeanSquaredErrorOp.cpp @@ -23,7 +23,7 @@ #include <QFormLayout> #include <Image.h> -#include "ImageListBox.h" +#include <Widgets/ImageListBox.h> #include "../Tools.h" #include "MeanSquaredErrorOp.h" @@ -31,7 +31,7 @@ using namespace std; using namespace imagein; -MeanSquaredErrorOp::MeanSquaredErrorOp() : Operation(Tools::tr("Mean squared error").toStdString()) +MeanSquaredErrorOp::MeanSquaredErrorOp() : Operation(qApp->translate("Operations", "Mean squared error").toStdString()) { } @@ -42,7 +42,7 @@ bool MeanSquaredErrorOp::needCurrentImg() const { void MeanSquaredErrorOp::operator()(const imagein::Image* image, const std::map<const imagein::Image*, std::string>& imgList) { QDialog* dialog = new QDialog(); - dialog->setWindowTitle(dialog->tr("Compare to...")); + dialog->setWindowTitle(qApp->translate("Operations", "Compare to...")); dialog->setMinimumWidth(180); QFormLayout* layout = new QFormLayout(); dialog->setLayout(layout); @@ -50,7 +50,7 @@ void MeanSquaredErrorOp::operator()(const imagein::Image* image, const std::map< QString currentImgName = QString(imgList.find(image)->second.c_str()); ImageListBox* imageBox = new ImageListBox(dialog, image, imgList); - layout->insertRow(0, QString("Compare %1 to : ").arg(currentImgName), imageBox); + layout->insertRow(0, qApp->translate("Operations", "Compare %1 to : ").arg(currentImgName), imageBox); QDialogButtonBox* buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok|QDialogButtonBox::Cancel, Qt::Horizontal, dialog); layout->insertRow(1, buttonBox); @@ -81,7 +81,7 @@ void MeanSquaredErrorOp::operator()(const imagein::Image* image, const std::map< mse = mse / static_cast<double>(maxChannel * maxWidth * maxHeight); me = me / static_cast<double>(maxChannel * maxWidth * maxHeight); - QString text = QString("Mean squarred error : %1 (mean error : %2)"); + QString text = qApp->translate("MeanSquareErrorOp", "Mean squarred error : %1 (mean error : %2)"); text = text.arg(mse, 0, 'f', 2); text = text.arg(me, 0, 'f', 2); diff --git a/app/Operations/NoiseOp.cpp b/app/Operations/NoiseOp.cpp index ef18cd0b4625627e31651b2c9b61b2895a0f8885..2e7100156bb133ad9cef10c23e05294ddca66b77 100644 --- a/app/Operations/NoiseOp.cpp +++ b/app/Operations/NoiseOp.cpp @@ -39,20 +39,20 @@ using namespace std; using namespace imagein; using namespace genericinterface; -NoiseOp::NoiseOp() : GenericOperation(Tools::tr("Add noise").toStdString()) +NoiseOp::NoiseOp() : GenericOperation(qApp->translate("Operations", "Add noise").toStdString()) { } -void NoiseOp::operator()(const ImageWindow* currentWnd, vector<ImageWindow*>&) { +void NoiseOp::operator()(const ImageWindow* currentWnd, const vector<const ImageWindow*>&) { QDialog* dialog = new QDialog(); - dialog->setWindowTitle(dialog->tr("Parameters")); + dialog->setWindowTitle(qApp->translate("Operations", "Parameters")); dialog->setMinimumWidth(180); QFormLayout* layout = new QFormLayout(dialog); QGroupBox* radioGroup = new QGroupBox("Type of noise", dialog); - QRadioButton* impulseButton = new QRadioButton(dialog->tr("Impulse noise")); - QRadioButton* gaussianButton = new QRadioButton(dialog->tr("Gaussian noise")); + QRadioButton* impulseButton = new QRadioButton(qApp->translate("NoiseOp", "Impulse noise")); + QRadioButton* gaussianButton = new QRadioButton(qApp->translate("NoiseOp", "Gaussian noise")); QHBoxLayout* radioLayout = new QHBoxLayout(radioGroup); radioLayout->addWidget(impulseButton); radioLayout->addWidget(gaussianButton); @@ -64,8 +64,8 @@ void NoiseOp::operator()(const ImageWindow* currentWnd, vector<ImageWindow*>&) { meanBox->setRange(-255.0, 255.0); meanBox->setValue(0.0); devBox->setValue(1.0); - QLabel* meanLabel = new QLabel("Mean : "); - QLabel* devLabel = new QLabel("Standard deviation : "); + QLabel* meanLabel = new QLabel(qApp->translate("NoiseOp", "Mean : ")); + QLabel* devLabel = new QLabel(qApp->translate("NoiseOp", "Standard deviation : ")); layout->insertRow(1, meanLabel, meanBox); layout->insertRow(2, devLabel, devBox); @@ -73,7 +73,7 @@ void NoiseOp::operator()(const ImageWindow* currentWnd, vector<ImageWindow*>&) { percentBox->setRange(0.0, 100.0); percentBox->setValue(10.0); percentBox->setSuffix("%"); - QLabel* percentLabel = new QLabel("Percent of image : "); + QLabel* percentLabel = new QLabel(qApp->translate("NoiseOp", "Percent of image : ")); layout->insertRow(3, percentLabel, percentBox); percentBox->hide(); percentLabel->hide(); @@ -87,7 +87,7 @@ void NoiseOp::operator()(const ImageWindow* currentWnd, vector<ImageWindow*>&) { QObject::connect(gaussianButton, SIGNAL(toggled(bool)), devLabel, SLOT(setVisible(bool))); QObject::connect(gaussianButton, SIGNAL(toggled(bool)), devBox, SLOT(setVisible(bool))); - QPushButton *okButton = new QPushButton(dialog->tr("Validate"), dialog); + QPushButton *okButton = new QPushButton(qApp->translate("Operations", "Validate"), dialog); okButton->setDefault(true); layout->addWidget(okButton); QObject::connect(okButton, SIGNAL(clicked()), dialog, SLOT(accept())); @@ -115,7 +115,7 @@ void NoiseOp::operator()(const ImageWindow* currentWnd, vector<ImageWindow*>&) { Image::depth_t value = random.Boolean() ? min : max; image->setPixel(x, y, c, value); } - this->outImage(image, Tools::tr("impulse noise").toStdString()); + this->outImage(image, qApp->translate("NoiseOp", "impulse noise").toStdString()); } else if(currentWnd->isDouble()) { @@ -131,7 +131,7 @@ void NoiseOp::operator()(const ImageWindow* currentWnd, vector<ImageWindow*>&) { double value = random.Boolean() ? min : max; image->setPixel(x, y, c, value); } - this->outDoubleImage(image, Tools::tr("gaussian noise").toStdString(), wnd->isNormalized(), wnd->isLogScaled()); + this->outDoubleImage(image, qApp->translate("NoiseOp", "impulse noise").toStdString(), wnd->isNormalized(), wnd->isLogScaled()); } } @@ -149,7 +149,7 @@ void NoiseOp::operator()(const ImageWindow* currentWnd, vector<ImageWindow*>&) { value = min(255.0, max( 0.0, value ) ); *it = static_cast<Image::depth_t>(value); } - this->outImage(image, Tools::tr("impulse noise").toStdString()); + this->outImage(image, qApp->translate("NoiseOp", "gaussian noise").toStdString()); } else if(currentWnd->isDouble()) { @@ -158,7 +158,7 @@ void NoiseOp::operator()(const ImageWindow* currentWnd, vector<ImageWindow*>&) { for(Image_t<double>::iterator it = image->begin(); it < image->end(); ++it) { *it += normdist.operator()(random, mean, deviation); } - this->outDoubleImage(image, Tools::tr("gaussian noise").toStdString(), wnd->isNormalized(), wnd->isLogScaled()); + this->outDoubleImage(image, qApp->translate("NoiseOp", "gaussian noise").toStdString(), wnd->isNormalized(), wnd->isLogScaled()); } } diff --git a/app/Operations/NoiseOp.h b/app/Operations/NoiseOp.h index 62aedf535b9e601c88379ed8f0543a3d7876d16f..1c32471dd50ccef5d8a54eaf61afed74a80e4529 100644 --- a/app/Operations/NoiseOp.h +++ b/app/Operations/NoiseOp.h @@ -28,7 +28,7 @@ class NoiseOp : public GenericOperation public: NoiseOp(); - virtual void operator()(const genericinterface::ImageWindow* currentWnd, std::vector<genericinterface::ImageWindow*>&); + virtual void operator()(const genericinterface::ImageWindow* currentWnd, const std::vector<const genericinterface::ImageWindow*>&); virtual bool isValidImgWnd(const genericinterface::ImageWindow* imgWnd) const; diff --git a/app/Operations/PointOp.cpp b/app/Operations/PointOp.cpp index 7d502d59278f87272b021bb97ffc19209f30ed43..535c4b5fddfe9b96027c01c42c2158101645e1dc 100644 --- a/app/Operations/PointOp.cpp +++ b/app/Operations/PointOp.cpp @@ -30,10 +30,9 @@ #include <QGroupBox> #include "PointOp.h" -#include "ImgWidget.h" -#include "ImageListBox.h" -#include "Widgets/ImageWidgets/StandardImageWindow.h" -#include "Widgets/ImageWidgets/DoubleImageWindow.h" +#include <Widgets/ImageListBox.h> +#include <Widgets/ImageWidgets/StandardImageWindow.h> +#include <Widgets/ImageWidgets/DoubleImageWindow.h> #include <Converter.h> #include "../Tools.h" @@ -42,7 +41,7 @@ using namespace std; using namespace imagein; using namespace genericinterface; -PointOp::PointOp() : GenericOperation(Tools::tr("Pixel operations").toStdString()) { +PointOp::PointOp() : GenericOperation(qApp->translate("Operations", "Pixel operations").toStdString()) { } @@ -90,7 +89,7 @@ PointOp::DoubleImageOp* PointOp::DoubleImageOp::fromString(QString op) { return new DoubleImgIdent(); } -void PointOp::operator()(const ImageWindow* currentWnd, vector<ImageWindow*>& wndList) { +void PointOp::operator()(const ImageWindow* currentWnd, const vector<const ImageWindow*>& wndList) { QStringList pixOperators, imgOperators; @@ -99,7 +98,7 @@ void PointOp::operator()(const ImageWindow* currentWnd, vector<ImageWindow*>& wn QString currentImgName = currentWnd->windowTitle(); map<const Image*,string> stdImgList; map<const Image_t<double>*,string> dblImgList; - for(vector<ImageWindow*>::iterator it = wndList.begin(); it != wndList.end(); ++it) { + for(vector<const ImageWindow*>::const_iterator it = wndList.begin(); it != wndList.end(); ++it) { if((*it)->isStandard()) { const StandardImageWindow* stdImgWnd = dynamic_cast<const StandardImageWindow*>(*it); stdImgList.insert(pair<const Image*, string>(stdImgWnd->getImage(), stdImgWnd->windowTitle().toStdString())); @@ -112,21 +111,21 @@ void PointOp::operator()(const ImageWindow* currentWnd, vector<ImageWindow*>& wn QDialog* dialog = new QDialog(); - dialog->setWindowTitle(dialog->tr("Parameter")); + dialog->setWindowTitle(qApp->translate("Operations", "Parameters")); dialog->setMinimumWidth(180); QVBoxLayout* layout = new QVBoxLayout(); dialog->setLayout(layout); - QGroupBox* radioGroup = new QGroupBox("Second operand", dialog); - QRadioButton* valueButton = new QRadioButton(dialog->tr("Value")); - QRadioButton* imageButton = new QRadioButton(dialog->tr("Image")); + QGroupBox* radioGroup = new QGroupBox(qApp->translate("PointOp", "Second operand"), dialog); + QRadioButton* valueButton = new QRadioButton(qApp->translate("PointOp", "Value")); + QRadioButton* imageButton = new QRadioButton(qApp->translate("PointOp", "Image")); QHBoxLayout* radioLayout = new QHBoxLayout(radioGroup); radioLayout->addWidget(valueButton); radioLayout->addWidget(imageButton); layout->addWidget(radioGroup); valueButton->setChecked(true); - QCheckBox* colorBox = new QCheckBox("Explode colors", dialog); + QCheckBox* colorBox = new QCheckBox(qApp->translate("PointOp", "Explode colors"), dialog); layout->addWidget(colorBox); int nChannel = currentWnd->getDisplayImage()->getNbChannels(); @@ -190,7 +189,7 @@ void PointOp::operator()(const ImageWindow* currentWnd, vector<ImageWindow*>& wn layout->setSizeConstraint(QLayout::SetFixedSize); - QPushButton *okButton = new QPushButton(dialog->tr("Validate"), dialog); + QPushButton *okButton = new QPushButton(qApp->translate("Operations", "Validate"), dialog); okButton->setDefault(true); layout->addWidget(okButton); QObject::connect(okButton, SIGNAL(clicked()), dialog, SLOT(accept())); diff --git a/app/Operations/PointOp.h b/app/Operations/PointOp.h index ffe4a8fb3b3a06c5299e63275ed93a3ded44f399..8ba7acd3ff81e6b52c16147854f26be3c57b9aec 100644 --- a/app/Operations/PointOp.h +++ b/app/Operations/PointOp.h @@ -36,7 +36,7 @@ class PointOp : public GenericOperation { PointOp(); - virtual void operator()(const genericinterface::ImageWindow* currentWnd, std::vector<genericinterface::ImageWindow*>&); + virtual void operator()(const genericinterface::ImageWindow* currentWnd, const std::vector<const genericinterface::ImageWindow*>&); bool needCurrentImg() const; virtual bool isValidImgWnd(const genericinterface::ImageWindow* imgWnd) const; @@ -84,7 +84,7 @@ class PointOp : public GenericOperation { }; struct PixAdd : PixOp_t<int> { - PixAdd(int value_) : PixOp_t(value_) {} + PixAdd(int value_) : PixOp_t<int>(value_) {} intmax_t op(depth_t pixel) { return pixel + value; } }; struct DoublePixAdd : DoublePixelOp { @@ -93,7 +93,7 @@ class PointOp : public GenericOperation { }; struct PixMul : PixOp_t<double> { - PixMul(double value_) : PixOp_t(value_) {} + PixMul(double value_) : PixOp_t<double>(value_) {} intmax_t op(depth_t pixel) { return pixel * value + 0.5; } }; struct DoublePixMul : DoublePixelOp { @@ -102,27 +102,27 @@ class PointOp : public GenericOperation { }; struct PixAnd : PixOp_t<depth_t> { - PixAnd(depth_t value_) : PixOp_t(value_) {} + PixAnd(depth_t value_) : PixOp_t<depth_t>(value_) {} intmax_t op(depth_t pixel) { return pixel & value; } }; struct PixOr : PixOp_t<depth_t> { - PixOr(depth_t value_) : PixOp_t(value_) {} + PixOr(depth_t value_) : PixOp_t<depth_t>(value_) {} intmax_t op(depth_t pixel) { return pixel | value; } }; struct PixXor : PixOp_t<depth_t> { - PixXor(depth_t value_) : PixOp_t(value_) {} + PixXor(depth_t value_) : PixOp_t<depth_t>(value_) {} intmax_t op(depth_t pixel) { return pixel ^ value; } }; struct PixLshift : PixOp_t<unsigned int> { - PixLshift(unsigned int value_) : PixOp_t(value_) {} + PixLshift(unsigned int value_) : PixOp_t<unsigned int>(value_) {} intmax_t op(depth_t pixel) { return pixel << value; } }; struct PixRshift : PixOp_t<unsigned int> { - PixRshift(unsigned int value_) : PixOp_t(value_) {} + PixRshift(unsigned int value_) : PixOp_t<unsigned int>(value_) {} intmax_t op(depth_t pixel) { return pixel >> value; } }; diff --git a/app/Operations/PseudoColorOp.cpp b/app/Operations/PseudoColorOp.cpp index 1e7437e52ca02b723b5fbc0d409a01d435b8915b..347218acb9d45f66095df3afe137cfd95b61d324 100644 --- a/app/Operations/PseudoColorOp.cpp +++ b/app/Operations/PseudoColorOp.cpp @@ -25,7 +25,7 @@ using namespace std; using namespace imagein; -PseudoColorOp::PseudoColorOp() : Operation(Tools::tr("Pseudo color").toStdString()) +PseudoColorOp::PseudoColorOp() : Operation(qApp->translate("Operations", "Pseudo color").toStdString()) { } @@ -50,7 +50,7 @@ void PseudoColorOp::operator()(const imagein::Image* image, const std::map<const } } delete tmpImg; - outImage(resImg, "Pseudo color"); + outImage(resImg, qApp->translate("PseudoColorOp", "Pseudo color").toStdString()); } diff --git a/app/Operations/PyramidDialog.cpp b/app/Operations/PyramidDialog.cpp new file mode 100644 index 0000000000000000000000000000000000000000..185f65d883350ae199a3ba1b257288aa379ddfc6 --- /dev/null +++ b/app/Operations/PyramidDialog.cpp @@ -0,0 +1,62 @@ +/* + * Copyright 2011-2012 INSA Rennes + * + * This file is part of EIImage. + * + * EIImage is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * EIImage 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with EIImage. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include "PyramidDialog.h" +#include "ui_PyramidDialog.h" + +PyramidDialog::PyramidDialog(QWidget *parent) : + QDialog(parent), + ui(new Ui::PyramidDialog) +{ + ui->setupUi(this); +} + +PyramidDialog::~PyramidDialog() +{ + delete ui; +} + +Pyramid::filtre PyramidDialog::getFilter() const { + Pyramid::Filters filters; + Pyramid::filtre filter; + switch(ui->filterBox->currentIndex()) { + case 1: filters.getFromName("gaussien", filter); break; + case 2: filters.getFromName("trimodal", filter); break; + case 3: filters.getFromName("rectangulaire", filter); break; + case 4: filters.getFromName("qmf", filter); break; + default: filters.getFromName("triangulaire", filter); break; + } + return filter; +} + +int PyramidDialog::getNbStep() { + return ui->stepBox->value(); +} + +bool PyramidDialog::isGaussian() const { + return ui->gaussianButton->isChecked(); +} + +bool PyramidDialog::onlyOneStep() const { + return ui->oneStepBox->isChecked(); +} + +int PyramidDialog::onlyStep() const { + return ui->onlyStepBox->value(); +} diff --git a/app/Operations/PyramidDialog.h b/app/Operations/PyramidDialog.h new file mode 100644 index 0000000000000000000000000000000000000000..9065a0ff1babd4424a140e28b978f4d5b365ebb9 --- /dev/null +++ b/app/Operations/PyramidDialog.h @@ -0,0 +1,47 @@ +/* + * Copyright 2011-2012 INSA Rennes + * + * This file is part of EIImage. + * + * EIImage is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * EIImage 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with EIImage. If not, see <http://www.gnu.org/licenses/>. +*/ + +#ifndef PYRAMIDDIALOG_H +#define PYRAMIDDIALOG_H + +#include <QDialog> +#include "../Algorithms/Pyramid.h" + +namespace Ui { +class PyramidDialog; +} + +class PyramidDialog : public QDialog +{ + Q_OBJECT + +public: + explicit PyramidDialog(QWidget *parent = 0); + ~PyramidDialog(); + Pyramid::filtre getFilter() const; + int getNbStep(); + bool isGaussian() const; + bool onlyOneStep() const; + int onlyStep() const; + +private: + Ui::PyramidDialog *ui; +}; + +#endif // PYRAMIDDIALOG_H diff --git a/app/Operations/PyramidDialog.ui b/app/Operations/PyramidDialog.ui new file mode 100644 index 0000000000000000000000000000000000000000..2a1cccbb085ea381a7b606be6daba018d4db7823 --- /dev/null +++ b/app/Operations/PyramidDialog.ui @@ -0,0 +1,219 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>PyramidDialog</class> + <widget class="QDialog" name="PyramidDialog"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>261</width> + <height>231</height> + </rect> + </property> + <property name="windowTitle"> + <string>Pyramidal decomposition</string> + </property> + <layout class="QVBoxLayout" name="verticalLayout"> + <item> + <widget class="QGroupBox" name="groupBox"> + <property name="title"> + <string>Type of pyramid</string> + </property> + <layout class="QHBoxLayout" name="horizontalLayout"> + <item> + <widget class="QRadioButton" name="gaussianButton"> + <property name="text"> + <string>gaussian</string> + </property> + <property name="checked"> + <bool>true</bool> + </property> + </widget> + </item> + <item> + <widget class="QRadioButton" name="laplacianButton"> + <property name="text"> + <string>laplacian</string> + </property> + </widget> + </item> + </layout> + </widget> + </item> + <item> + <layout class="QFormLayout" name="formLayout"> + <item row="0" column="0"> + <widget class="QLabel" name="label"> + <property name="text"> + <string>Filter : </string> + </property> + </widget> + </item> + <item row="0" column="1"> + <widget class="QComboBox" name="filterBox"> + <item> + <property name="text"> + <string>triangular</string> + </property> + </item> + <item> + <property name="text"> + <string>gaussian</string> + </property> + </item> + <item> + <property name="text"> + <string>trimodal</string> + </property> + </item> + <item> + <property name="text"> + <string>rectangular</string> + </property> + </item> + <item> + <property name="text"> + <string>qmf</string> + </property> + </item> + </widget> + </item> + <item row="1" column="0"> + <widget class="QLabel" name="nbStepLabel"> + <property name="text"> + <string>Number of steps : </string> + </property> + </widget> + </item> + <item row="1" column="1"> + <widget class="QSpinBox" name="stepBox"> + <property name="minimum"> + <number>1</number> + </property> + <property name="maximum"> + <number>9</number> + </property> + </widget> + </item> + </layout> + </item> + <item> + <layout class="QHBoxLayout" name="horizontalLayout_2"> + <item> + <widget class="QCheckBox" name="oneStepBox"> + <property name="text"> + <string>Create only one step :</string> + </property> + </widget> + </item> + <item> + <widget class="QSpinBox" name="onlyStepBox"> + <property name="enabled"> + <bool>false</bool> + </property> + <property name="minimum"> + <number>1</number> + </property> + <property name="maximum"> + <number>9</number> + </property> + </widget> + </item> + </layout> + </item> + <item> + <widget class="QDialogButtonBox" name="buttonBox"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="standardButtons"> + <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set> + </property> + </widget> + </item> + </layout> + </widget> + <resources/> + <connections> + <connection> + <sender>buttonBox</sender> + <signal>accepted()</signal> + <receiver>PyramidDialog</receiver> + <slot>accept()</slot> + <hints> + <hint type="sourcelabel"> + <x>248</x> + <y>254</y> + </hint> + <hint type="destinationlabel"> + <x>157</x> + <y>274</y> + </hint> + </hints> + </connection> + <connection> + <sender>buttonBox</sender> + <signal>rejected()</signal> + <receiver>PyramidDialog</receiver> + <slot>reject()</slot> + <hints> + <hint type="sourcelabel"> + <x>316</x> + <y>260</y> + </hint> + <hint type="destinationlabel"> + <x>286</x> + <y>274</y> + </hint> + </hints> + </connection> + <connection> + <sender>oneStepBox</sender> + <signal>toggled(bool)</signal> + <receiver>onlyStepBox</receiver> + <slot>setEnabled(bool)</slot> + <hints> + <hint type="sourcelabel"> + <x>96</x> + <y>164</y> + </hint> + <hint type="destinationlabel"> + <x>218</x> + <y>164</y> + </hint> + </hints> + </connection> + <connection> + <sender>oneStepBox</sender> + <signal>toggled(bool)</signal> + <receiver>nbStepLabel</receiver> + <slot>setDisabled(bool)</slot> + <hints> + <hint type="sourcelabel"> + <x>96</x> + <y>164</y> + </hint> + <hint type="destinationlabel"> + <x>70</x> + <y>120</y> + </hint> + </hints> + </connection> + <connection> + <sender>oneStepBox</sender> + <signal>toggled(bool)</signal> + <receiver>stepBox</receiver> + <slot>setDisabled(bool)</slot> + <hints> + <hint type="sourcelabel"> + <x>96</x> + <y>164</y> + </hint> + <hint type="destinationlabel"> + <x>193</x> + <y>120</y> + </hint> + </hints> + </connection> + </connections> +</ui> diff --git a/app/Operations/PyramidOp.cpp b/app/Operations/PyramidOp.cpp new file mode 100644 index 0000000000000000000000000000000000000000..129fd4c48d847dfcc09e20ac3d27786b8966dcb2 --- /dev/null +++ b/app/Operations/PyramidOp.cpp @@ -0,0 +1,86 @@ +/* + * Copyright 2011-2012 INSA Rennes + * + * This file is part of EIImage. + * + * EIImage is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * EIImage 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with EIImage. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include "PyramidOp.h" + +#include <QApplication> +#include "../Algorithms/Pyramid.h" +#include "PyramidDialog.h" +#include <Converter.h> +#include <GrayscaleImage.h> +#include <QMessageBox> + +using namespace std; +using namespace imagein; + +PyramidOp::PyramidOp() : Operation(qApp->translate("Operations", "Pyramidal decomposition").toStdString()) +{ +} + +bool PyramidOp::needCurrentImg() const { + return true; +} + +void PyramidOp::operator()(const imagein::Image* img, const std::map<const imagein::Image*, std::string>&) { + + if(img->getWidth() != img->getHeight()) { + QMessageBox::warning(NULL, qApp->translate("Operations", "The operation can't be applied on this image"), + qApp->translate("Operations", "The image width must equal the image height.")); + return; + } + if(!Pyramid::isPowerOf2(img->getWidth())) { + QMessageBox::warning(NULL, qApp->translate("Operations", "The operation can't be applied on this image"), + qApp->translate("Operations", "The image dimensions must be power of 2.")); + return; + } + + PyramidDialog* dialog = new PyramidDialog(QApplication::activeWindow()); + QDialog::DialogCode code = static_cast<QDialog::DialogCode>(dialog->exec()); + + if(code!=QDialog::Accepted) return; + + GrayscaleImage* image = Converter<GrayscaleImage>::convert(*img); + Image* resImg = NULL; + string s; + Pyramid::filtre filtre = dialog->getFilter(); + try { + if(dialog->onlyOneStep()) { + if(dialog->isGaussian()) { + resImg = Pyramid::n_pyram_g(image, dialog->onlyStep(), filtre); + } + else { + resImg = Pyramid::n_pyram_l(image, dialog->onlyStep(), filtre); + } + } + else { + if(dialog->isGaussian()) { + resImg = Pyramid::pyram_g(image, dialog->getNbStep(), filtre, s); + } + else { + resImg = Pyramid::pyram_l(image, dialog->getNbStep(), filtre, s); + } + } + } + catch(const char*e) { + QMessageBox::critical(NULL, "Error", QString(e)); + return; + } + outImage(resImg, "Pyramid"); + outText(s); +} diff --git a/app/Operations/PyramidOp.h b/app/Operations/PyramidOp.h new file mode 100644 index 0000000000000000000000000000000000000000..88dbe6a06bba0d64a02265a46a0a6551989f8a7a --- /dev/null +++ b/app/Operations/PyramidOp.h @@ -0,0 +1,35 @@ +/* + * Copyright 2011-2012 INSA Rennes + * + * This file is part of EIImage. + * + * EIImage is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * EIImage 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with EIImage. If not, see <http://www.gnu.org/licenses/>. +*/ + +#ifndef PYRAMIDOP_H +#define PYRAMIDOP_H + +#include <Operation.h> + +class PyramidOp : public Operation +{ +public: + PyramidOp(); + + void operator()(const imagein::Image*, const std::map<const imagein::Image*, std::string>&); + + bool needCurrentImg() const; +}; + +#endif // PYRAMIDOP_H diff --git a/app/Operations/Quantification.cpp b/app/Operations/Quantification.cpp index 995b4cb9055a1b6f409786e3cf8d606f7cbd5573..249d941e64deb7af8e4bccf4ab6af863849e7c26 100644 --- a/app/Operations/Quantification.cpp +++ b/app/Operations/Quantification.cpp @@ -36,7 +36,7 @@ Quantification::Quantification(std::string filename) { file >> s; if(s.compare("Quant_Level_File") != 0) throw exception(); file >> this->size; -// this->size++; + this->size++; if(this->size < 2) throw exception(); threshold = new int[this->size - 1]; values = new imagein::Image::depth_t[this->size]; @@ -57,7 +57,7 @@ Quantification::Quantification(std::string filename) { void Quantification::saveAs(std::string filename) { ofstream file(filename.c_str(), fstream::out); file << "Quant_Level_File" << endl; - file << this->size << endl; + file << (this->size - 1) << endl; for(int i = 0; i < size - 1; ++i) { double n = threshold[i]; file << n << endl; diff --git a/app/Operations/QuantificationDialog.cpp b/app/Operations/QuantificationDialog.cpp index 2529d7a23f43fccaa5474a56ecb9e7e18de748c0..3c35519c9c4a0227f0fb13f35572a1dbaad4c443 100644 --- a/app/Operations/QuantificationDialog.cpp +++ b/app/Operations/QuantificationDialog.cpp @@ -33,10 +33,15 @@ #include <QFileDialog> using namespace imagein; -QuantificationDialog::QuantificationDialog(QWidget *parent) : - QDialog(parent) +QuantificationDialog::QuantificationDialog(QWidget *parent, QString imgName) : + QDialog(parent), _editorOnly(imgName.isEmpty()) { - setWindowTitle(QString(tr("Quantification"))); + if(_editorOnly) { + this->setWindowTitle(tr("Quantification file editor")); + } + else { + this->setWindowTitle(tr("Quantification of %1").arg(imgName)); + } setMinimumWidth(180); QFormLayout* layout = new QFormLayout(this); setLayout(layout); @@ -47,8 +52,10 @@ QuantificationDialog::QuantificationDialog(QWidget *parent) : _quantBox = new QComboBox(); _quantBox->addItem(tr("Linear with centered value")); - _quantBox->addItem(tr("Non linear with centered value")); - _quantBox->addItem(tr("Non linear with mean value")); + if(!_editorOnly) { + _quantBox->addItem(tr("Non linear with centered value")); + _quantBox->addItem(tr("Non linear with mean value")); + } _quantBox->addItem(tr("Custom")); layout->insertRow(0, tr("Quantification : "), _quantBox); layout->insertRow(1, tr("Number of values : "), _sizeBox); @@ -75,17 +82,25 @@ QuantificationDialog::QuantificationDialog(QWidget *parent) : QObject::connect(_sizeBox, SIGNAL(valueChanged(int)), _quantWidget, SLOT(setNbThreshold(int))); QObject::connect(_quantBox, SIGNAL(currentIndexChanged(int)), this, SLOT(methodChanged(int))); + if(_editorOnly) { + buttonBox->button(QDialogButtonBox::Cancel)->setVisible(false); + buttonBox->button(QDialogButtonBox::Ok)->setText(tr("Exit")); + } + else { + buttonBox->button(QDialogButtonBox::Ok)->setText(tr("Apply")); + } } void QuantificationDialog::methodChanged(int method) { - _editorWidget->setVisible(method == 3); - _saveButton->setEnabled(method==3 || method == 0); + _editorWidget->setVisible((_editorOnly && method == 1) || (!_editorOnly && method == 3)); + _saveButton->setEnabled(_editorOnly || method==3 || method == 0); this->adjustSize(); } Quantification QuantificationDialog::getQuantif(const Image* image, unsigned int c) { int size = _sizeBox->value(); + if(_editorOnly) return Quantification::linearQuant(size); switch(_quantBox->currentIndex()) { case 1: return Quantification::nonLinearQuant(size, image, c); break; case 2: return Quantification::nonLinearQuantOptimized(size, image, c); break; @@ -94,21 +109,33 @@ Quantification QuantificationDialog::getQuantif(const Image* image, unsigned int } } +Quantification QuantificationDialog::getQuantif() { + int size = _sizeBox->value(); + if(!_editorOnly) return Quantification::linearQuant(size); + switch(_quantBox->currentIndex()) { + case 2: return _quantWidget->getQuantif(); break; + default: return Quantification::linearQuant(size); break; + } +} + void QuantificationDialog::open() { QString filename = QFileDialog::getOpenFileName(this, tr("Open a file"), "", tr("Loi de quantification (*.loi)")); + if(filename.isEmpty()) return; Quantification q(filename.toStdString()); _quantWidget->setQuantif(q); _sizeBox->setValue(q.size); - _quantBox->setCurrentIndex(3); + _quantBox->setCurrentIndex(_editorOnly ? 1 : 3); } void QuantificationDialog::save() { QString filename = QFileDialog::getSaveFileName(this, tr("Save to file"), "", tr("Loi de quantification (*.loi)")); - switch(_quantBox->currentIndex()) { - case 0: Quantification::linearQuant(this->_sizeBox->value()).saveAs(filename.toStdString()); break; - case 3: _quantWidget->getQuantif().saveAs(filename.toStdString()); break; - default: return; + if(filename.isEmpty()) return; + if(_quantBox->currentIndex() == 0) { + Quantification::linearQuant(this->_sizeBox->value()).saveAs(filename.toStdString()); + } + else if((_editorOnly && _quantBox->currentIndex()) == 1 || (!_editorWidget && _quantBox->currentIndex() == 3)) { + _quantWidget->getQuantif().saveAs(filename.toStdString()); } } diff --git a/app/Operations/QuantificationDialog.h b/app/Operations/QuantificationDialog.h index be92c58dc9f2f7684fb2ff005f23c10ac4d6983d..72e1c375583eb1233c25a8bb3d8012b0bc0705a2 100644 --- a/app/Operations/QuantificationDialog.h +++ b/app/Operations/QuantificationDialog.h @@ -31,8 +31,9 @@ class QuantificationDialog : public QDialog Q_OBJECT public: enum QuantMethod {LinearQuant, NonLinearQuant, NonLinearQuantOptimized}; - explicit QuantificationDialog(QWidget *parent = 0); + explicit QuantificationDialog(QWidget *parent = 0, QString imgName = QString()); Quantification getQuantif(const imagein::Image *image, unsigned int c); + Quantification getQuantif(); signals: public slots: @@ -45,6 +46,7 @@ protected: QuantificationWidget* _quantWidget; QWidget* _editorWidget; QPushButton* _saveButton; + bool _editorOnly; }; #endif // QUANTIFICATIONDIALOG_H diff --git a/app/Operations/QuantificationOp.cpp b/app/Operations/QuantificationOp.cpp index c0f6859462e2aaceaa51a2e6a57d07ac1cee60bd..e73dba99938991a8f168ca0607c26f4bac242b0f 100644 --- a/app/Operations/QuantificationOp.cpp +++ b/app/Operations/QuantificationOp.cpp @@ -28,43 +28,52 @@ using namespace std; using namespace imagein; using namespace genericinterface; -QuantificationOp::QuantificationOp() : Operation(Tools::tr("Quantification").toStdString()) +QuantificationOp::QuantificationOp() : Operation(qApp->translate("Operations", "Quantification").toStdString()) { } bool QuantificationOp::needCurrentImg() const { - return true; + return false; } -void QuantificationOp::operator()(const imagein::Image* image, const std::map<const imagein::Image*, std::string>&) { +void QuantificationOp::operator()(const imagein::Image* image, const std::map<const imagein::Image*, std::string>& imgList) { + QuantificationDialog* dialog; + if(image != NULL) { + QString imgName = QString::fromStdString(imgList.find(image)->second); + dialog = new QuantificationDialog(QApplication::activeWindow(), imgName); + } + else { + dialog = new QuantificationDialog(QApplication::activeWindow()); + } - QuantificationDialog* dialog = new QuantificationDialog(QApplication::activeWindow()); QDialog::DialogCode code = static_cast<QDialog::DialogCode>(dialog->exec()); if(code!=QDialog::Accepted) return; - Image* resImg = new Image(image->getWidth(), image->getHeight(), image->getNbChannels()); - for(unsigned int c = 0; c < image->getNbChannels(); ++c) { - Quantification quantification = dialog->getQuantif(image, c); - for(int i = 0; i < quantification.size; ++i) { - cout << (int)quantification.values[i] << "."; - } - cout << endl; - for(int i = 0; i < quantification.size-1; ++i) { - cout << quantification.threshold[i] << "."; - } - cout << endl; - Quantifier quantifier = Quantifier(quantification); - for(unsigned int j = 0; j < image->getHeight(); ++j) { - for(unsigned int i = 0; i < image->getWidth(); ++i) { - const Image::depth_t value = image->getPixelAt(i, j, c); - resImg->setPixelAt(i, j, c, quantifier.valueOf(value)); + if(image != NULL) { + Image* resImg = new Image(image->getWidth(), image->getHeight(), image->getNbChannels()); + for(unsigned int c = 0; c < image->getNbChannels(); ++c) { + Quantification quantification = dialog->getQuantif(image, c); + for(int i = 0; i < quantification.size; ++i) { + cout << (int)quantification.values[i] << "."; + } + cout << endl; + for(int i = 0; i < quantification.size-1; ++i) { + cout << quantification.threshold[i] << "."; + } + cout << endl; + Quantifier quantifier = Quantifier(quantification); + for(unsigned int j = 0; j < image->getHeight(); ++j) { + for(unsigned int i = 0; i < image->getWidth(); ++i) { + const Image::depth_t value = image->getPixelAt(i, j, c); + resImg->setPixelAt(i, j, c, quantifier.valueOf(value)); + } } } + outImage(resImg, qApp->translate("QuantificationOp", "quantified").toStdString()); } - outImage(resImg, "quantified"); } diff --git a/app/Operations/QuantificationWidget.cpp b/app/Operations/QuantificationWidget.cpp index 99196daf14a66b3993197a01709a4f1c936abe02..aa6a6f4f986554c9a7446c839bc790e68351c740 100644 --- a/app/Operations/QuantificationWidget.cpp +++ b/app/Operations/QuantificationWidget.cpp @@ -120,7 +120,7 @@ void QuantificationWidget::setQuantif(Quantification q) { } void QuantificationWidget::CentralWidget::setQuantif(Quantification q) { - this->_nThreshold = q.size; + this->_nThreshold = q.size - 1; for(int i = 0; i < q.size - 1; ++i) { _thresholdBoxes[i]->setValue(q.threshold[i]); } diff --git a/app/Operations/RandomImgOp.cpp b/app/Operations/RandomImgOp.cpp index 9d311ba70abf9440acf65904b42e77cb4bfd5921..517b2dd9c7c99be519a6c30bf95004980e56e46e 100644 --- a/app/Operations/RandomImgOp.cpp +++ b/app/Operations/RandomImgOp.cpp @@ -29,23 +29,24 @@ #include "RandomImgOp.h" #include "../Tools.h" #include <RandomLib/Random.hpp> +#include <QApplication> using namespace std; using namespace imagein; -RandomImgOp::RandomImgOp() : Operation(Tools::tr("Generate random image").toStdString()) +RandomImgOp::RandomImgOp() : Operation(qApp->translate("Operations", "Generate random image").toStdString()) { } void RandomImgOp::operator()(const imagein::Image*, const std::map<const imagein::Image*, std::string>&) { - QDialog* dialog = new QDialog(); - dialog->setWindowTitle(dialog->tr("Parameters")); + QDialog* dialog = new QDialog(qApp->activeWindow()); + dialog->setWindowTitle(qApp->translate("RandomImgOp", "Parameters")); dialog->setMinimumWidth(180); QFormLayout* layout = new QFormLayout(dialog); - QGroupBox* radioGroup = new QGroupBox("Image type", dialog); - QRadioButton* intButton = new QRadioButton(dialog->tr("8-bit integer")); - QRadioButton* floatButton = new QRadioButton(dialog->tr("Floating point")); + QGroupBox* radioGroup = new QGroupBox(qApp->translate("RandomImgOp", "Image type"), dialog); + QRadioButton* intButton = new QRadioButton(qApp->translate("RandomImgOp", "8-bit integer")); + QRadioButton* floatButton = new QRadioButton(qApp->translate("RandomImgOp", "Floating point")); QHBoxLayout* radioLayout = new QHBoxLayout(radioGroup); radioLayout->addWidget(intButton); radioLayout->addWidget(floatButton); @@ -55,17 +56,17 @@ void RandomImgOp::operator()(const imagein::Image*, const std::map<const imagein QSpinBox* widthBox = new QSpinBox(dialog); widthBox->setRange(0, 65536); widthBox->setValue(512); - layout->insertRow(1, "Width : ", widthBox); + layout->insertRow(1, qApp->translate("RandomImgOp", "Width : "), widthBox); QSpinBox* heightBox = new QSpinBox(dialog); heightBox->setRange(0, 65536); heightBox->setValue(512); - layout->insertRow(2, "Height : ", heightBox); + layout->insertRow(2, qApp->translate("RandomImgOp", "Height : "), heightBox); QSpinBox* channelBox = new QSpinBox(dialog); channelBox->setRange(1, 4); channelBox->setValue(3); - layout->insertRow(3, "Number of channels : ", channelBox); + layout->insertRow(3, qApp->translate("RandomImgOp", "Number of channels : "), channelBox); QWidget* intRangeWidget = new QWidget(dialog); QHBoxLayout* intRangeLayout = new QHBoxLayout(intRangeWidget); @@ -75,9 +76,9 @@ void RandomImgOp::operator()(const imagein::Image*, const std::map<const imagein intMaxBox->setRange(0, 255); intMinBox->setValue(0); intMaxBox->setValue(255); - intRangeLayout->addWidget(new QLabel("Range : ")); + intRangeLayout->addWidget(new QLabel(qApp->translate("RandomImgOp", "Range : "))); intRangeLayout->addWidget(intMinBox); - intRangeLayout->addWidget(new QLabel(" to ")); + intRangeLayout->addWidget(new QLabel(qApp->translate("RandomImgOp", " to "))); intRangeLayout->addWidget(intMaxBox); layout->insertRow(4, intRangeWidget); @@ -89,9 +90,9 @@ void RandomImgOp::operator()(const imagein::Image*, const std::map<const imagein floatMaxBox->setValue(1.0); floatMinBox->setRange(-65536, 65536); floatMaxBox->setRange(-65536, 65536); - floatRangeLayout->addWidget(new QLabel("Range : ")); + floatRangeLayout->addWidget(new QLabel(qApp->translate("RandomImgOp", "Range : "))); floatRangeLayout->addWidget(floatMinBox); - floatRangeLayout->addWidget(new QLabel(" to ")); + floatRangeLayout->addWidget(new QLabel(qApp->translate("RandomImgOp", " to "))); floatRangeLayout->addWidget(floatMaxBox); layout->insertRow(5, floatRangeWidget); floatRangeWidget->hide(); @@ -101,7 +102,7 @@ void RandomImgOp::operator()(const imagein::Image*, const std::map<const imagein QObject::connect(intButton, SIGNAL(toggled(bool)), intRangeWidget, SLOT(setVisible(bool))); QObject::connect(floatButton, SIGNAL(toggled(bool)), floatRangeWidget, SLOT(setVisible(bool))); - QPushButton *okButton = new QPushButton(dialog->tr("Validate"), dialog); + QPushButton *okButton = new QPushButton(qApp->translate("Operations", "Validate"), dialog); okButton->setDefault(true); layout->addWidget(okButton); QObject::connect(okButton, SIGNAL(clicked()), dialog, SLOT(accept())); @@ -120,11 +121,12 @@ void RandomImgOp::operator()(const imagein::Image*, const std::map<const imagein for(unsigned int j = 0; j < resImg->getHeight(); ++j) { for(unsigned int i = 0; i < resImg->getWidth(); ++i) { Image::depth_t value = random.IntegerC<Image::depth_t>(intMinBox->value(), intMaxBox->value()); +// Image::depth_t value = 256. * (rand() / (RAND_MAX + 1.));; resImg->setPixel(i, j, c, value); } } } - this->outImage(resImg, Tools::tr("Random image").toStdString()); + this->outImage(resImg, qApp->translate("Operations", "Random image").toStdString()); } else if(floatButton->isChecked()) { @@ -136,13 +138,15 @@ void RandomImgOp::operator()(const imagein::Image*, const std::map<const imagein for(unsigned int i = 0; i < resImg->getWidth(); ++i) { double min = floatMinBox->value(); double max = floatMaxBox->value(); +// double width = max - min; +// double value = min + (double)rand() * width / RAND_MAX; double value = random.FixedN<double>(); value = value*(max-min) + min; resImg->setPixel(i, j, c, value); } } } - this->outDoubleImage(resImg, Tools::tr("Random image").toStdString(), true); + this->outDoubleImage(resImg, qApp->translate("Operations", "Random image").toStdString(), true); } } diff --git a/app/Operations/RejectionRingOp.cpp b/app/Operations/RejectionRingOp.cpp index 51266415c09e6a909ada03054d4f7406572328b9..66f6eea88f2bc78d5b8484cf8896af221ad77b8e 100644 --- a/app/Operations/RejectionRingOp.cpp +++ b/app/Operations/RejectionRingOp.cpp @@ -33,28 +33,28 @@ using namespace imagein; using namespace std; -RejectionRingOp::RejectionRingOp() : Operation(Tools::tr("Rejection ring").toStdString()) +RejectionRingOp::RejectionRingOp() : Operation(qApp->translate("Operations", "Rejection ring").toStdString()) { } void RejectionRingOp::operator()(const imagein::Image*, const std::map<const imagein::Image*, std::string>&) { QDialog* dialog = new QDialog(); - dialog->setWindowTitle(dialog->tr("Rejection ring")); + dialog->setWindowTitle(qApp->translate("Operations", "Rejection ring")); dialog->setMinimumWidth(180); QFormLayout* layout = new QFormLayout(dialog); QSpinBox* widthBox = new QSpinBox(dialog); widthBox->setRange(0, 65536); widthBox->setValue(512); - layout->insertRow(0, "Width=Height : ", widthBox); + layout->insertRow(0, qApp->translate("RejectionRingOp", "Width=Height : "), widthBox); QSpinBox* radiusBox = new QSpinBox(dialog); radiusBox->setRange(0, 65536); - layout->insertRow(1, "Radius : ", radiusBox); + layout->insertRow(1, qApp->translate("RejectionRingOp", "Radius : "), radiusBox); QSpinBox* thickBox = new QSpinBox(dialog); thickBox->setRange(0, 65536); - layout->insertRow(2, "Thickness (beyond radius) : ", thickBox); + layout->insertRow(2, qApp->translate("RejectionRingOp", "Thickness (beyond radius) : "), thickBox); QDialogButtonBox* buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok|QDialogButtonBox::Cancel, Qt::Horizontal, dialog); layout->insertRow(3, buttonBox); @@ -96,7 +96,7 @@ void RejectionRingOp::operator()(const imagein::Image*, const std::map<const ima - QString name(Tools::tr("Rejection ring (%1 %2 %3)")); + QString name(qApp->translate("RejectionRingOp", "Rejection ring (%1 %2 %3)")); name = name.arg(nb_ligne).arg(rayon).arg(epaisseur); outDoubleImage(result, name.toStdString(), true, false); } diff --git a/app/Operations/RotateOp.cpp b/app/Operations/RotateOp.cpp index daffe6bd875edaba5cbe4703c6f93f5861d17d95..659ebcfc9fb80c606f5c15faa1ebf08a8f572ae1 100644 --- a/app/Operations/RotateOp.cpp +++ b/app/Operations/RotateOp.cpp @@ -23,15 +23,13 @@ #include <QSpinBox> #include <QCheckBox> -#include "ImgWidget.h" - #include "RotateOp.h" #include "../Tools.h" using namespace std; using namespace imagein; -RotateOp::RotateOp() : Operation(Tools::tr("Rotation").toStdString()) +RotateOp::RotateOp() : Operation(qApp->translate("Operations", "Rotation").toStdString()) { } @@ -57,7 +55,7 @@ void RotateOp::operator()(const Image* img, const map<const Image*, string>& img QString imgName(imgList.find(img)->second.c_str()); QDialog* dialog = new QDialog(); - dialog->setWindowTitle(QString(dialog->tr("Rotating %1")).arg(imgName)); + dialog->setWindowTitle(qApp->translate("Rotation", "Rotating %1").arg(imgName)); dialog->setMinimumWidth(180); QFormLayout* layout = new QFormLayout(); dialog->setLayout(layout); @@ -66,7 +64,7 @@ void RotateOp::operator()(const Image* img, const map<const Image*, string>& img layout->setSizeConstraint(QLayout::SetFixedSize); QDoubleSpinBox* angleSpinBox = new QDoubleSpinBox(dialog); - QCheckBox* expandBox = new QCheckBox("Expand image", dialog); + QCheckBox* expandBox = new QCheckBox(qApp->translate("Rotation", "Expand image"), dialog); QSpinBox* valueSpinBox = new QSpinBox(dialog); angleSpinBox->setRange(-180, 180); @@ -75,9 +73,9 @@ void RotateOp::operator()(const Image* img, const map<const Image*, string>& img valueSpinBox->setRange(0, 255); valueSpinBox->setValue(0); - layout->insertRow(0, "Rotation angle : ", angleSpinBox); + layout->insertRow(0, qApp->translate("Rotation", "Rotation angle : "), angleSpinBox); layout->insertRow(1, expandBox); - layout->insertRow(2, "Fill value : ", valueSpinBox); + layout->insertRow(2, qApp->translate("Rotation", "Fill value : "), valueSpinBox); QDialogButtonBox* buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok|QDialogButtonBox::Cancel, Qt::Horizontal, dialog); layout->insertRow(3, buttonBox); @@ -149,6 +147,6 @@ void RotateOp::operator()(const Image* img, const map<const Image*, string>& img } } - QString name = QString("rotated %1").arg(angleSpinBox->value()); + QString name = qApp->translate("Rotation", "rotated %1").arg(angleSpinBox->value()); this->outImage(resImg, name.toStdString()); } diff --git a/app/Operations/ScalingOp.cpp b/app/Operations/ScalingOp.cpp index 724bc7d95293b2c3dd5b601844546fdf68fd67d7..43807e16ddc119bb3f9f4ea826fe9a1063d1656f 100644 --- a/app/Operations/ScalingOp.cpp +++ b/app/Operations/ScalingOp.cpp @@ -33,12 +33,13 @@ #include <QRadioButton> #include <QHBoxLayout> #include <QLabel> +#include <QtScript/QScriptEngine> using namespace std; using namespace imagein; using namespace genericinterface; -ScalingOp::ScalingOp() : GenericOperation(Tools::tr("Scaling").toStdString()) +ScalingOp::ScalingOp() : GenericOperation(qApp->translate("Operations", "Scaling").toStdString()) { } @@ -50,29 +51,29 @@ bool ScalingOp::isValidImgWnd(const genericinterface::ImageWindow* imgWnd) const return imgWnd != NULL; } -void ScalingOp::operator()(const genericinterface::ImageWindow* currentWnd, vector<ImageWindow*>&) { +void ScalingOp::operator()(const genericinterface::ImageWindow* currentWnd, const vector<const ImageWindow*>&) { QDialog* dialog = new QDialog(QApplication::activeWindow()); - dialog->setWindowTitle(QString(dialog->tr("Scaling"))); + dialog->setWindowTitle(QString(qApp->translate("Operations", "Scaling"))); dialog->setMinimumWidth(180); QFormLayout* layout = new QFormLayout(); dialog->setLayout(layout); - QDoubleSpinBox* xScaleBox = new QDoubleSpinBox(); - QDoubleSpinBox* yScaleBox = new QDoubleSpinBox(); - xScaleBox->setRange(0, 100); - yScaleBox->setRange(0, 100); - xScaleBox->setValue(1.); - yScaleBox->setValue(1.); + QLineEdit* xScaleBox = new QLineEdit(); + QLineEdit* yScaleBox = new QLineEdit(); +// xScaleBox->setRange(0, 100); +// yScaleBox->setRange(0, 100); + xScaleBox->setText("1"); + yScaleBox->setText("1"); QComboBox* algoBox = new QComboBox(); - algoBox->addItem(dialog->tr("Nearest neighboor (standard)")); - algoBox->addItem(dialog->tr("Bi-linear")); - algoBox->addItem(dialog->tr("Parabolic")); - algoBox->addItem(dialog->tr("Spline")); - layout->insertRow(0, dialog->tr("Interpolation : "), algoBox); - layout->insertRow(1, dialog->tr("X scale factor : "), xScaleBox); - layout->insertRow(2, dialog->tr("Y scale factor : "), yScaleBox); + algoBox->addItem(qApp->translate("ScalingOp", "Nearest neighboor (standard)")); + algoBox->addItem(qApp->translate("ScalingOp", "Bi-linear")); + algoBox->addItem(qApp->translate("ScalingOp", "Parabolic")); + algoBox->addItem(qApp->translate("ScalingOp", "Spline")); + layout->insertRow(0, qApp->translate("ScalingOp", "Interpolation : "), algoBox); + layout->insertRow(1, qApp->translate("ScalingOp", "X scale factor : "), xScaleBox); + layout->insertRow(2, qApp->translate("ScalingOp", "Y scale factor : "), yScaleBox); QDialogButtonBox* buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok|QDialogButtonBox::Cancel, Qt::Horizontal, dialog); layout->insertRow(3, buttonBox); @@ -91,29 +92,36 @@ void ScalingOp::operator()(const genericinterface::ImageWindow* currentWnd, vect default: inter = NearestInterpolation; break; } + QScriptEngine scriptEngine; + QScriptValue xScriptValue = scriptEngine.evaluate(xScaleBox->text()); + QScriptValue yScriptValue = scriptEngine.evaluate(yScaleBox->text()); + double xValue = xScriptValue.toNumber(); + double yValue = yScriptValue.toNumber(); if(currentWnd->isStandard()) { const Image* image = static_cast<const StandardImageWindow*>(currentWnd)->getImage(); - Image* resImg; + Image* resImg = NULL; switch(inter) { case NearestInterpolation: - resImg = scale<Image::depth_t, Nearest>(image, xScaleBox->value(), yScaleBox->value()); + resImg = scale<Image::depth_t, Nearest>(image, xValue, yValue); break; case BilinearInterpolation: - resImg = scale<Image::depth_t, Bilinear>(image, xScaleBox->value(), yScaleBox->value()); + resImg = scale<Image::depth_t, Bilinear>(image, xValue, yValue); break; case ParabolicInterpolation: - resImg = scale<Image::depth_t, Parabolic>(image, xScaleBox->value(), yScaleBox->value()); + resImg = scale<Image::depth_t, Parabolic>(image, xValue, yValue); break; case SplineInterpolation: - resImg = scale<Image::depth_t, Spline>(image, xScaleBox->value(), yScaleBox->value()); + resImg = scale<Image::depth_t, Spline>(image, xValue, yValue); break; } - outImage(resImg, "scaled"); + if(resImg != NULL) { + outImage(resImg, qApp->translate("ScalingOp", "scaled").toStdString()); + } } else if(currentWnd->isDouble()) { const Image_t<double>* image = static_cast<const DoubleImageWindow*>(currentWnd)->getImage(); - Image_t<double>* resImg = scale<double, Nearest>(image, xScaleBox->value(), yScaleBox->value()); - outDoubleImage(resImg, "scaled"); + Image_t<double>* resImg = scale<double, Nearest>(image, xValue, yValue); + outDoubleImage(resImg, qApp->translate("ScalingOp", "scaled").toStdString()); } } diff --git a/app/Operations/ScalingOp.h b/app/Operations/ScalingOp.h index 551ba94fe0db8dd2d7e65747c4cbc84790ba7e4b..dc8199ee7708edfa997af58c36b9399cfedafff1 100644 --- a/app/Operations/ScalingOp.h +++ b/app/Operations/ScalingOp.h @@ -44,7 +44,7 @@ public: static void interpolate(typename imagein::Image_t<D>::ConstLine src, typename imagein::Image_t<double>::Line dst); }; - virtual void operator()(const genericinterface::ImageWindow* currentWnd, std::vector<genericinterface::ImageWindow*>&); + virtual void operator()(const genericinterface::ImageWindow* currentWnd, const std::vector<const genericinterface::ImageWindow*>&); bool needCurrentImg() const; virtual bool isValidImgWnd(const genericinterface::ImageWindow* imgWnd) const; diff --git a/app/Operations/SeparatorOp.cpp b/app/Operations/SeparatorOp.cpp new file mode 100644 index 0000000000000000000000000000000000000000..4a348cd7ab8156934fb0f4a3f7696d3678844a3f --- /dev/null +++ b/app/Operations/SeparatorOp.cpp @@ -0,0 +1,37 @@ +/* + * Copyright 2011-2012 INSA Rennes + * + * This file is part of EIImage. + * + * EIImage is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * EIImage 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with EIImage. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include "SeparatorOp.h" + +SeparatorOp::SeparatorOp() : GenericOperation("") +{ +} + +bool SeparatorOp::needCurrentImg() const { + return true; +} + +bool SeparatorOp::isValidImgWnd(const genericinterface::ImageWindow*) const { + return false; +} + +void SeparatorOp::operator()(const genericinterface::ImageWindow*, const std::vector<const genericinterface::ImageWindow*>&) { + return; +} + diff --git a/app/Operations/SeparatorOp.h b/app/Operations/SeparatorOp.h new file mode 100644 index 0000000000000000000000000000000000000000..04d1709f120fbf9da428b5133e0cf9c3a5f41d2e --- /dev/null +++ b/app/Operations/SeparatorOp.h @@ -0,0 +1,35 @@ +/* + * Copyright 2011-2012 INSA Rennes + * + * This file is part of EIImage. + * + * EIImage is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * EIImage 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with EIImage. If not, see <http://www.gnu.org/licenses/>. +*/ + +#ifndef SEPARATOROP_H +#define SEPARATOROP_H + +#include <Operation.h> + +class SeparatorOp : public GenericOperation +{ +public: + SeparatorOp(); + virtual void operator()(const genericinterface::ImageWindow* currentWnd, const std::vector<const genericinterface::ImageWindow*>&); + + bool needCurrentImg() const; + virtual bool isValidImgWnd(const genericinterface::ImageWindow* imgWnd) const; +}; + +#endif // SEPARATOROP_H diff --git a/app/Operations/SignalToNoiseOp.cpp b/app/Operations/SignalToNoiseOp.cpp index 6f43d5b48312798d339f1b053cdb381ff1b7f44f..c2ae8e97c784ac8b749674a2ea7ce87c8933a621 100644 --- a/app/Operations/SignalToNoiseOp.cpp +++ b/app/Operations/SignalToNoiseOp.cpp @@ -22,7 +22,7 @@ #include <QFormLayout> #include <Image.h> -#include "ImageListBox.h" +#include <Widgets/ImageListBox.h> #include "../Tools.h" #include "SignalToNoiseOp.h" @@ -30,7 +30,7 @@ using namespace std; using namespace imagein; -SignalToNoiseOp::SignalToNoiseOp() : Operation(Tools::tr("Signal-to-noise ratio").toStdString()) +SignalToNoiseOp::SignalToNoiseOp() : Operation(qApp->translate("Operations", "Signal-to-noise ratio").toStdString()) { } @@ -42,7 +42,7 @@ bool SignalToNoiseOp::needCurrentImg() const { void SignalToNoiseOp::operator()(const imagein::Image* image, const std::map<const imagein::Image*, std::string>& imgList) { QDialog* dialog = new QDialog(); - dialog->setWindowTitle(dialog->tr("Compare to...")); + dialog->setWindowTitle(qApp->translate("Operations", "Compare to...")); dialog->setMinimumWidth(180); QFormLayout* layout = new QFormLayout(); dialog->setLayout(layout); @@ -50,7 +50,7 @@ void SignalToNoiseOp::operator()(const imagein::Image* image, const std::map<con QString currentImgName = QString(imgList.find(image)->second.c_str()); ImageListBox* imageBox = new ImageListBox(dialog, image, imgList); - layout->insertRow(0, QString("Compare %1 to : ").arg(currentImgName), imageBox); + layout->insertRow(0, qApp->translate("Operations", "Compare %1 to : ").arg(currentImgName), imageBox); QDialogButtonBox* buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok|QDialogButtonBox::Cancel, Qt::Horizontal, dialog); layout->insertRow(1, buttonBox); @@ -80,13 +80,13 @@ void SignalToNoiseOp::operator()(const imagein::Image* image, const std::map<con } var = var / static_cast<double>(maxChannel * maxWidth * maxHeight); - QString text = QString("Signal-to-noise ratio : %1"); + QString text = qApp->translate("SignalToNoiseOp", "Signal-to-noise ratio : %1"); if(var != 0) { double snd = 10.0 * log10(255.0*255.0 / var); text = text.arg(snd, 0, 'f', 2) + "dB"; } else { - text = text.arg(Tools::tr("+inf")); + text = text.arg("+inf"); } this->outText(text.toStdString()); diff --git a/app/Operations/SinusSynthesisOp.cpp b/app/Operations/SinusSynthesisOp.cpp index 8524ebe5049d583e163efe1f0cb3996109ff7d49..79c8dbfdca50c9a01a4459d2a3b1d1c5c9f47bf7 100644 --- a/app/Operations/SinusSynthesisOp.cpp +++ b/app/Operations/SinusSynthesisOp.cpp @@ -35,7 +35,7 @@ using namespace std; using namespace imagein; -SinusSynthesisOp::SinusSynthesisOp() : Operation(Tools::tr("Sinus synthesis").toStdString()) +SinusSynthesisOp::SinusSynthesisOp() : Operation(qApp->translate("Operations", "Sinus synthesis").toStdString()) { } @@ -46,14 +46,14 @@ bool SinusSynthesisOp::needCurrentImg() const { void SinusSynthesisOp::operator()(const imagein::Image*, const std::map<const imagein::Image*, std::string>&) { QDialog* dialog = new QDialog(QApplication::activeWindow()); - dialog->setWindowTitle(QString(dialog->tr("Sinus synthesis"))); + dialog->setWindowTitle(QString(qApp->translate("SinusSynthesisOp", "Sinus synthesis"))); dialog->setMinimumWidth(180); QFormLayout* layout = new QFormLayout(); dialog->setLayout(layout); QGroupBox* radioGroup = new QGroupBox("Direction", dialog); - QRadioButton* linearButton = new QRadioButton(dialog->tr("Linear")); - QRadioButton* circularButton = new QRadioButton(dialog->tr("Circular")); + QRadioButton* linearButton = new QRadioButton(qApp->translate("SinusSynthesisOp", "Linear")); + QRadioButton* circularButton = new QRadioButton(qApp->translate("SinusSynthesisOp", "Circular")); QHBoxLayout* radioLayout = new QHBoxLayout(radioGroup); radioLayout->addWidget(linearButton); radioLayout->addWidget(circularButton); @@ -67,14 +67,14 @@ void SinusSynthesisOp::operator()(const imagein::Image*, const std::map<const im angleBox->setRange(0, 359); QComboBox* colorBox = new QComboBox(); - colorBox->addItem(dialog->tr("256")); - colorBox->addItem(dialog->tr("2 (Black and white)")); + colorBox->addItem(qApp->translate("SinusSynthesisOp", "256")); + colorBox->addItem(qApp->translate("SinusSynthesisOp", "2 (Black and white)")); layout->insertRow(0, radioGroup); - layout->insertRow(1, dialog->tr("Image size (width=height) : "), sizeBox); - layout->insertRow(2, dialog->tr("Signal period (pixel) : "), periodBox); - QLabel* orientationLabel = new QLabel(dialog->tr("Orientation (°): ")); + layout->insertRow(1, qApp->translate("SinusSynthesisOp", "Image size (width=height) : "), sizeBox); + layout->insertRow(2, qApp->translate("SinusSynthesisOp", "Signal period (pixel) : "), periodBox); + QLabel* orientationLabel = new QLabel(qApp->translate("SinusSynthesisOp", "Orientation (°): ")); layout->insertRow(3, orientationLabel, angleBox); - layout->insertRow(4, dialog->tr("Niveaux de gris : "), colorBox); + layout->insertRow(4, qApp->translate("SinusSynthesisOp", "Niveaux de gris : "), colorBox); QDialogButtonBox* buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok|QDialogButtonBox::Cancel, Qt::Horizontal, dialog); layout->insertRow(5, buttonBox); @@ -141,7 +141,7 @@ void SinusSynthesisOp::operator()(const imagein::Image*, const std::map<const im } } } - outImage(resImg, "Sinus synthesis"); + outImage(resImg, qApp->translate("Operations", "Sinus synthesis").toStdString()); } diff --git a/app/Operations/SplitColorOp.cpp b/app/Operations/SplitColorOp.cpp index 0babfbbdf7f06dbdee1080e22eb2937068e2722f..2ae27c83a91559c57733824b50ef4692cecc31b9 100644 --- a/app/Operations/SplitColorOp.cpp +++ b/app/Operations/SplitColorOp.cpp @@ -18,8 +18,6 @@ */ #include <GrayscaleImage.h> -#include "ImgWidget.h" - #include "SplitColorOp.h" #include "../Tools.h" @@ -30,7 +28,7 @@ bool SplitColorOp::needCurrentImg() const { return true; } -SplitColorOp::SplitColorOp() : Operation(tr("Split color planes").toStdString()) +SplitColorOp::SplitColorOp() : Operation(qApp->translate("Operations", "Split color planes").toStdString()) { } @@ -43,7 +41,7 @@ void SplitColorOp:: operator()(const imagein::Image* image, const std::map<const resImg->setPixel(i, j, image->getPixel(i, j, c)); } } - QString name(" - "); + QString name(""); name += Tools::colorName(c, image->getNbChannels()); this->outImage(resImg, name.toStdString()); } diff --git a/app/Operations/SplitColorOp.h b/app/Operations/SplitColorOp.h index ed6aed0daa3e3fd5223f84022d7b05d8f2b6d79b..a55bebbb0e28f4838b8fbd92aaaa8a2da47e3c57 100644 --- a/app/Operations/SplitColorOp.h +++ b/app/Operations/SplitColorOp.h @@ -33,8 +33,6 @@ public: void operator()(const imagein::Image*, const std::map<const imagein::Image*, std::string>&); - static QString tr(const char* str) { return QApplication::tr(str); } - bool needCurrentImg() const; }; diff --git a/app/Operations/ThresholdDialog.cpp b/app/Operations/ThresholdDialog.cpp index e5d1136a10dcaa2a1c13ea52834367504a094bf5..3c8909bcd9eda54c456bbe48aed57428faf2f7e1 100644 --- a/app/Operations/ThresholdDialog.cpp +++ b/app/Operations/ThresholdDialog.cpp @@ -41,11 +41,11 @@ void ThresholdDialog::spinbox2Changed(int i) { void ThresholdDialog::doubleThreshold(bool activate) { if(activate) { _marker2->show(); - _spin1label->setText("Threshold #1 : "); + _spin1label->setText(tr("Threshold #1 : ")); } else { _marker2->hide(); - _spin1label->setText("Threshold : "); + _spin1label->setText(tr("Threshold : ")); } } @@ -62,28 +62,28 @@ ThresholdDialog::ThresholdDialog(const GrayscaleImage* image, bool converted) : this->setLayout(layout); if(converted) { - layout->addWidget(new QLabel("<font color=red><i>Information : The input image has been converted to grayscale.</i></font>")); + layout->addWidget(new QLabel(tr("<font color=red><i>Information : The input image has been converted to grayscale.</i></font>"))); } - QGroupBox* threshGroup = new QGroupBox("Threshold", this); + QGroupBox* threshGroup = new QGroupBox(tr("Threshold"), this); QHBoxLayout* threshLayout = new QHBoxLayout(threshGroup); - _doubleBox = new QCheckBox("Double threshold"); + _doubleBox = new QCheckBox(tr("Double threshold")); threshLayout->addWidget(_doubleBox); layout->addWidget(threshGroup); QHBoxLayout* box1layout = new QHBoxLayout(); - _spin1label = new QLabel("Threshold : "); + _spin1label = new QLabel(tr("Threshold : ")); _spinbox1 = new QSpinBox(); _spinbox1->setRange(0, 255); _spinbox1->setValue(127); - QPushButton* otsuButton = new QPushButton("Otsu"); + QPushButton* otsuButton = new QPushButton(tr("Otsu")); box1layout->addWidget(_spin1label); box1layout->addWidget(_spinbox1); box1layout->addWidget(otsuButton); layout->addLayout(box1layout); QHBoxLayout* box2layout = new QHBoxLayout(); - QLabel* spin2label = new QLabel("Threshold #2 : "); + QLabel* spin2label = new QLabel(tr("Threshold #2 : ")); spin2label->setVisible(false); _spinbox2 = new QSpinBox(); _spinbox2->setRange(0, 255); @@ -94,7 +94,7 @@ ThresholdDialog::ThresholdDialog(const GrayscaleImage* image, bool converted) : layout->addLayout(box2layout); QHBoxLayout* radiolayout = new QHBoxLayout(); - QLabel* radioLabel = new QLabel("Color between thresholds :"); + QLabel* radioLabel = new QLabel(tr("Color between thresholds :")); QRadioButton* whiteButton = new QRadioButton(tr("White")); _blackButton = new QRadioButton(tr("Black")); radiolayout->addWidget(radioLabel); diff --git a/app/Operations/ThresholdDialog.h b/app/Operations/ThresholdDialog.h index 4abadb8e5b80b06baacdfc71d4226f820bcdf4ba..a8f074e2c49b4fbb77a47969a8a11b454e901145 100644 --- a/app/Operations/ThresholdDialog.h +++ b/app/Operations/ThresholdDialog.h @@ -41,7 +41,7 @@ class ThresholdDialog : public QDialog { ThresholdDialog(const imagein::GrayscaleImage*, bool converted); inline int threshold1() { return _spinbox1->value(); } inline int threshold2() { return _spinbox2->value(); } - inline bool blackBand() { return _blackButton->isChecked(); } + inline bool blackBand() { return !_blackButton->isChecked(); } inline bool doubleThreshold() { return _doubleBox->isChecked(); } public slots: diff --git a/app/Operations/ThresholdOp.cpp b/app/Operations/ThresholdOp.cpp index 91f4bd3340a78d7ee4df5e7d0a0f53d9f2971161..fd08985a1c40a2fc0b94a711099850b5a42ee04f 100644 --- a/app/Operations/ThresholdOp.cpp +++ b/app/Operations/ThresholdOp.cpp @@ -1,5 +1,3 @@ -#include "ImgWidget.h" - #include "Algorithm/Binarization.h" #include "Converter.h" @@ -10,7 +8,7 @@ using namespace std ; using namespace imagein; using namespace imagein::algorithm; -ThresholdOp::ThresholdOp() : Operation(Tools::tr("Thresholding").toStdString()) { +ThresholdOp::ThresholdOp() : Operation(qApp->translate("Operations", "Thresholding").toStdString()) { } bool ThresholdOp::needCurrentImg() const { diff --git a/app/Operations/Transforms.cpp b/app/Operations/Transforms.cpp new file mode 100644 index 0000000000000000000000000000000000000000..a8ebb89a77a237e34754b684e2b1b0583674902b --- /dev/null +++ b/app/Operations/Transforms.cpp @@ -0,0 +1,709 @@ +/* + * Copyright 2011-2012 INSA Rennes + * + * This file is part of EIImage. + * + * EIImage is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * EIImage 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with EIImage. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include "Transforms.h" +#include <GrayscaleImage.h> +#include <cstring> +#include <cstdlib> +#include <cstdio> +#include <Converter.h> + +using namespace std; +using namespace imagein; +const double pi = 3.1415926535897932384626433832795; +const double pid2 = 1.57079632679489661923132169163975144209858469968755291; +const double sqrt2 = 1.414213562373095048801688724209698078569671875376948; + +Image_t<double>* Transforms::hough(const GrayscaleImage *image ) { +// int height = image->getHeight(); +// int width = image->getWidth(); +// const uint8_t* tabim = image->begin(); +// double* itab = new double[ image->size() ]; +// for(unsigned int i = 0; i < image->size(); ++i) itab[i] = 0; + double diag = sqrt(image->getWidth()*image->getWidth() + image->getHeight()*image->getHeight()); + Image_t<double>* resImg = new Image_t<double>(diag+0.5, 180, 1, 0.); + + for(unsigned int j = 0; j < image->getHeight(); j++) { + for(unsigned int i = 0; i < image->getWidth(); i++) { + + if(image->getPixelAt(i, j) == 255) { + + int j1 = j; + + for(unsigned int i1 = i+1; i1 < image->getWidth(); i1++) { + if(image->getPixelAt(i1, j1) == 255) { + const double x0 = i; + const double y0 = j; + const double x1 = i1; + const double y1 = j1; + const double l0 = sqrt((double)((y0-y1)*(y0-y1) + (x0-x1)*(x0-x1))); + const double l1 = fabs((double)(x0*y1 - x1*y0)); + const double x2 = l1/l0; + double y2; + const int i2 = x2 + 0.5; + int j2; +// if(x1-x0 != 0) { +// y2 = atan((y1-y0)/(x1-x0)); +// j2 = 125 + (int)(y2*124./pid2 + 0.5); + y2 = (x1 != x0) ? atan((y1-y0) / (x1-x0)) : y1 > y0 ? pid2 : -pid2; + j2 = (y2 / pi) * 180. + 90. + 0.5; +// j2 = (x1 != x0) ? 125.5 + atan((y1-y0)/(x1-x0))*124./pid2 : 250; +// } +// else { +// j2 = 250; +// } + +// itab[j2*width+i2]++; + resImg->setPixelAt(i2, j2, resImg->getPixelAt(i2, j2) + 1.); + } + } + + for(unsigned int j1 = j+1; j1 < image->getHeight(); j1++) { + for(unsigned int i1 = 0; i1 < image->getWidth(); i1++) { + if(image->getPixelAt(i1, j1) == 255) { + const double x0 = i; + const double y0 = j; + const double x1 = i1; + const double y1 = j1; + const double l0 = sqrt((double)((y0-y1)*(y0-y1) + (x0-x1)*(x0-x1))); + const double l1 = fabs((double)(x0*y1 - x1*y0)); + const double x2 = l1/l0; + double y2; + const int i2 = x2 + 0.5; + int j2; +// if(x1-x0 != 0) { +// y2 = atan((double)(y1-y0)/(x1-x0)); +// j2 = 125 + (int)(y2*124./pid2 + 0.5); +// } +// else { +// j2 = 250; +// } + y2 = x1 != x0 ? atan((y1-y0) / (x1-x0)) : y1 > y0 ? pid2 : -pid2; +// j2 = (y2 / pi + 0.5) * image->getHeight() + 0.5; +// j2 = (y2 * 2. + pi)*100. + 0.5; + j2 = (y2 / pi) * 180. + 90. + 0.5; +// j2 = (x1 != x0) ? 125.5 + atan((y1-y0)/(x1-x0))*124./pid2 : 250; + +// itab[j2*width+i2]++; + resImg->setPixelAt(i2, j2, resImg->getPixelAt(i2, j2) + 1.); + } + } + } + } + } + } +// Image_t<double> *returnval = new Image_t<double>(width, height, 1, itab); +// delete itab; +// return returnval; + return resImg; + +} + + +Image_t<double>* Transforms::hough2(const Image *image, double angleStep, double rhoStep) { + +// double angleStep = .5; +// double rhoStep = 1.; + + +// double imageDiag = image->getWidth() * sqrt(2.); + double imageDiag = sqrt(image->getWidth()*image->getWidth() + image->getHeight()*image->getHeight()); + Image_t<double>* resImg = new Image_t<double>(1. + imageDiag / rhoStep, 180. / angleStep + 0.5, image->getNbChannels(), 0.); + + + for(unsigned int c = 0; c < image->getNbChannels(); ++c) { + + for(unsigned int j = 0; j < image->getHeight(); ++j) // on parcourt l'image + { + for(unsigned int i = 0; i < image->getWidth(); ++i) + { + if(image->getPixelAt(i, j, c) == 255) + { + + for(double te=0; te < 180; te += angleStep) // on parcourt la matrice + { + const double coste = cos(te * pi / 180.); + double sinte = sin(te * pi / 180.); + + // for(double ro = 0; ro < imageDiag; ro += rhoStep) + // { + // // on incrmente la matrice pour l'intervalle de ro correspondant au teta + // if( (ro <= (i*coste+j*sinte) ) && ( (i*coste+j*sinte) < (ro+rhoStep) ) ) + // { + // resImg->pixelAt(ro / rhoStep, te / angleStep)++; + // } + // } + const double rho = i * coste + j * sinte; +// const double start = max(0., delta); +// const double end = min(imageDiag, delta + rhoStep); + +// for(double ro = start; ro < end; ro += rhoStep) + if(rho >= 0. && rho < imageDiag) + { + resImg->pixelAt(rho / rhoStep + 0.5, te / angleStep + 0.5, c)++; + } + } + } + } + } + } + + + +// //Exemple d'affichage de texte dans la fentre "texte" +// char buffer[455]; +// sprintf( buffer, "Lecture du rsultat :\nLigne du haut : angle=0\nLigne du bas : angle=+180\nColonne de gauche : distance=0\nColonne de droite : distance max (diagonale de l'image)\nPoint de rfrence pour les distances : coin en haut gauche\nDroite de rfrence pour les angles : axe VERTICAL\nAngles positifs dans le sens trigonomtrique indirect"); +// oh->AddString( buffer ); + + + + return resImg; +} +string Transforms::hough2_inverse(const Image_t<double> *image, Image** resImgptr, unsigned int size, unsigned int threshold) { + + Image_t<uint32_t>* resImg = new Image_t<uint32_t>(size, size, image->getNbChannels(), uint32_t(0)); + +// int param = 5000 + 20 * image->getWidth() * image->getHeight(); + +// char *buffer; +// buffer=(char *)calloc(param,sizeof(char)); + + +// char tampon[50]; +// sprintf( buffer, "Valeur Max de la matrice d'entre=%d",(int)(max+0.1)); + + + double angleStep = 180. / image->getHeight(); + double imageDiag = resImg->getWidth() * sqrt(2.); + double rhoStep = imageDiag / image->getWidth(); + + //Algorithme de traitement + + int cmpt = 0; + for(unsigned int c = 0; c < image->getNbChannels(); ++c) { + for(unsigned int j = 0; j < image->getHeight(); ++j) { + for(unsigned int i = 0; i < image->getWidth(); ++i) { + + int n = image->getPixelAt(i, j, c); + if(n >= threshold) + { + cmpt++; + double angle = angleStep * j / 180. * pi; + double rho = rhoStep * i; + double sinte = sin(angle); + double coste = cos(angle); + + // sprintf( tampon,"\nniveau=%d\tangle=%1.0f\tdistance=%1.0f",(int)(0.1+tab_image[i+nl*j]),angle/pi*180.,rho); + // strcat( buffer, tampon); + + //Construction de la droite d'quation + for(unsigned int jj = 0; jj < size; ++jj) { + + // int kk = rho * (cos(angle) + tan(angle) * sin(angle)) - tan(angle)*jj; + int kk = (rho - sinte * jj) / coste; + if( kk > 0 && kk < size) { + resImg->pixelAt(kk, jj, c) += n; + } + } + for(unsigned int ii = 0; ii < size; ++ii) { + // int kk = ( rho * (cos(angle) + tan(angle) * sin(angle)) -ii ) / tan(angle); + int kk = (rho - coste * ii) / sinte; + if( kk>0 && kk < size) { + resImg->pixelAt(ii, kk, c) += n; + } + } + + } + } + } + } + +// sprintf( tampon,"\nNombre de droites traces=%d",cmpt); +// strcat( buffer, tampon); + std::cout << resImg->max() << std::endl; + Image* resStdImg = new Image(resImg->getWidth(), resImg->getHeight(), resImg->getNbChannels()); + Image_t<uint32_t>::iterator it = resImg->begin(); + Image::iterator jt = resStdImg->begin(); + double max = resImg->max(); + while(it != resImg->end()) { + *jt = *it * 256. / max + 0.5; + ++it; + ++jt; + } + + *resImgptr = resStdImg; + return ""; +} + +/***************************************************************************************************/ +string hadamard_haar_88( const Image *im, Image_t<double> **result, Image **result_inverse, double *rmat, GrayscaleImage_t<bool> *selection ); + +string Transforms::Hadamard( const Image *im, Image_t<double> **result, Image **result_inverse, GrayscaleImage_t<bool> *selection ) { + if(!( im != NULL && result != NULL && result_inverse != NULL )) { + char buffer[255]; + sprintf( buffer, "Error in Transforms::Hadamard:\nim = %p, result = %p, result_inverse = %p", im, result, result_inverse ); + throw buffer; + } + double rmat[8][8] = { + { 1.000, 1.000, 1.000, 1.000, 1.000, 1.000, 1.000, 1.000}, + { 1.000, 1.000, 1.000, 1.000,-1.000,-1.000,-1.000,-1.000}, + { 1.000, 1.000,-1.000,-1.000,-1.000,-1.000, 1.000, 1.000}, + { 1.000, 1.000,-1.000,-1.000, 1.000, 1.000,-1.000,-1.000}, + { 1.000,-1.000,-1.000, 1.000, 1.000,-1.000,-1.000, 1.000}, + { 1.000,-1.000,-1.000, 1.000,-1.000, 1.000, 1.000,-1.000}, + { 1.000,-1.000, 1.000,-1.000,-1.000, 1.000,-1.000, 1.000}, + { 1.000,-1.000, 1.000,-1.000, 1.000,-1.000, 1.000,-1.000} + }; + for(int i=0 ; i<8 ; i++) + { + for(int j=0 ; j<8 ; j++) + { + rmat[i][j] /= (double)sqrt(8.); + } + } + string returnval = hadamard_haar_88( im, result, result_inverse, (double*)rmat, selection ); + return returnval; +} + +string Transforms::Haar( const Image *im, Image_t<double> **result, Image **result_inverse, GrayscaleImage_t<bool> *selection ) { + if(!( im != NULL && result != NULL && result_inverse != NULL )) { + char buffer[255]; + sprintf( buffer, "Error in Transforms::Haar:\nim = %p, result = %p, result_inverse = %p", im, result, result_inverse ); + throw buffer; + } + // Returns result as the resulting image + // Returns result_inverse as the inverse of the resulting image + // Assume that this image is a black-and-white image, again + double sqrt2 = sqrt(2.); + double rmat[8][8] = { + { 1.000, 1.000, 1.000, 1.000, 1.000, 1.000, 1.000, 1.000}, + { 1.000, 1.000, 1.000, 1.000,-1.000,-1.000,-1.000,-1.000}, + { sqrt2, sqrt2,-sqrt2,-sqrt2, 0.000, 0.000, 0.000, 0.000}, + { 0.000, 0.000, 00000, 0.000, sqrt2, sqrt2,-sqrt2,-sqrt2}, + { 2.000,-2.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000}, + { 0.000, 0.000, 2.000,-2.000, 0.000, 0.000, 0.000, 0.000}, + { 0.000, 0.000, 0.000, 0.000, 2.000,-2.000, 0.000, 0.000}, + { 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 2.000,-2.000} + }; + for(int i=0 ; i<8 ; i++) + { + for(int j=0 ; j<8 ; j++) + { + rmat[i][j] /= (double)sqrt(8.); + } + } + string returnval = hadamard_haar_88( im, result, result_inverse, (double*)rmat, selection ); + return returnval; +} + +string Transforms::cosinus( const Image *im, Image_t<double> **result, Image **result_inverse, GrayscaleImage_t<bool> *selection ) { + if(!( im != NULL && result != NULL && result_inverse != NULL )) { + char buffer[255]; + sprintf( buffer, "Error in Transforms::Haar:\nim = %p, result = %p, result_inverse = %p", im, result, result_inverse ); + throw buffer; + } + // Returns result as the resulting image + // Returns result_inverse as the inverse of the resulting image + // Assume that this image is a black-and-white image, again + double rmat[8][8]; + const double pi = 3.1415926535; + for(int i=0 ; i<8 ; i++) + { + for(int j=0 ; j<8 ; j++) + { + rmat[i][j] = (double)((cos((2*j+1)*i*pi/16.))/2.); + } + } + for(int i=0 ; i<8 ; i++) + rmat[0][i] = (double)(1/sqrt(8.)); + string returnval = hadamard_haar_88( im, result, result_inverse, (double*)rmat, selection ); + return returnval; +} + +string hadamard_haar_88( const Image *im, Image_t<double> **resImg, Image **invImg, double *rmat, GrayscaleImage_t<bool> *selection ) { + if(!( im != NULL && resImg != NULL && invImg != NULL )) { + char buffer[255]; + sprintf( buffer, "Error in Transforms::hadamard_haar_88:\nim = %p, result = %p, result_inverse = %p", im, resImg, invImg ); + throw buffer; + } + // Returns result as the resulting image + // Returns result_inverse as the inverse of the resulting image + int idt = 8; + double res[8]; + string returnval; + +/*---------------------------------------------------------------------- +* +* OUVERTURE ET LECTURE DU FICHIER IMAGE ORIGINE +* ALLOCATION MEMOIRE POUR LES TABLEAUX IMAGES +* +*----------------------------------------------------------------------*/ + Image_t<double>* tmpImg = Converter<Image_t<double> >::convert(*im); + +/*--------------------------------------------------------------------- +* +* CALCUL DES COEFFICIENTS DE LA MATRICE DE TRANSFORMATION +* +*---------------------------------------------------------------------*/ + + char buffer[100]; + returnval = "\n\nmatrice de transformation utilisee : \n"; + + for(int i=0 ; i<idt ; i++) + { + for(int j=0 ; j<idt ; j++) + { + sprintf( buffer,"%5.2f ",rmat[i * idt + j]); + returnval = returnval + buffer; + } + returnval = returnval + "\n"; + } + +/*---------------------------------------------------------------------- +* +* TRANSFORMATION +* +*----------------------------------------------------------------------*/ + + for(unsigned int c = 0; c < tmpImg->getNbChannels(); ++c) { + for(unsigned int i=0 ; i < tmpImg->getWidth() ; i += idt) { + for(unsigned int j=0 ; j < tmpImg->getHeight() ; j += idt) { + + double res[8]; + for(int k = 0 ; k < idt ; ++k) res[k] = 0.; + + + for(int k = 0; k < idt; ++k) { + + for(int l = 0; l < idt; ++l) { + for(int m=0 ; m<idt ; m++) { + res[l] += rmat[l * idt + m] * tmpImg->getPixelAt(i+k, j+m, c); + } + } + + for(int l=0 ; l<idt ; l++) { + tmpImg->setPixelAt(i+k, j+l, c, res[l]); + res[l] = 0.; + } + } + + for(int k = 0; k < idt; ++k) { + + for(int l=0 ; l<idt ; l++) { + for(int m=0 ; m<idt ; m++) { + res[l] += rmat[l * idt + m] * tmpImg->getPixelAt(i+m, j+k, c); + } + } + + for(int l=0 ; l<idt ; l++) { + tmpImg->setPixelAt(i+l, j+k, c, +res[l]); + res[l] = 0.; + } + } + } + } + } + +/*---------------------------------------------------------------------- +* +* CODAGE +* +*----------------------------------------------------------------------*/ + + if(selection != NULL) { + for(unsigned int c = 0; c < tmpImg->getNbChannels(); ++c) { + for(unsigned int j = 0; j < tmpImg->getHeight(); ++j) { + for(unsigned int i = 0; i < tmpImg->getWidth(); ++i) { + if(!selection->getPixelAt(i % 8, j % 8)) { + tmpImg->setPixelAt(i, j, c, 0.); + } + } + } + } + } + +/*---------------------------------------------------------------------- +* +* STOCKAGE DE L'IMAGE TRANSFORMEE DANS UN FICHIER +* +*----------------------------------------------------------------------*/ + *resImg = new Image_t<double>(*tmpImg); + +/*---------------------------------------------------------------------- +* +* TRANSFORMATION INVERSE +* +*----------------------------------------------------------------------*/ + +for(unsigned int c = 0; c < tmpImg->getNbChannels(); ++c) { + for(unsigned int i=0 ; i< tmpImg->getHeight() ; i+=idt) { + for(unsigned int j=0 ; j<tmpImg->getWidth(); j+=idt) + { + for(int k=0 ; k<idt ; k++) + res[k] = 0.; + + for(int k=0 ; k<idt ; k++) + { + for(int l=0 ; l<idt ; l++) + for(int m=0 ; m<idt ; m++) + res[l] += rmat[m * idt + l] * tmpImg->getPixelAt(i+m, j+k, c); + + for(int l=0 ; l<idt ; l++) + { + tmpImg->setPixelAt(i+l, j+k, c, res[l]); + res[l] = 0.; + } + } + + for(int k=0 ; k<idt ; k++) + { + for(int l=0 ; l<idt ; l++) + for(int m=0 ; m<idt ; m++) + res[l] += rmat[m * idt + l] * tmpImg->getPixelAt(i+k, j+m, c); + + for(int l=0 ; l<idt ; l++) + { + tmpImg->setPixelAt(i+k, j+l, c, res[l]); + res[l] = 0.; + } + } + } + } +} + +/*---------------------------------------------------------------------- +* +* STOCKAGE DE L'IMAGE RESULTAT DANS UN FICHIER +* +*----------------------------------------------------------------------*/ +// Image *tabout = new Image(im->getWidth(), im->getHeight(), tmpImg->getNbChannels()); +// for(unsigned int i=0 ; i<tmpImg->getHeight() ; i++) +// for(unsigned int j=0 ; j<tmpImg->getWidth() ; j++) +// { +// double ftemp = tmpImg->getPixelAt(j, i); +// if(ftemp < 0) +// ftemp = 0; +// if(ftemp > 255) +// ftemp = 255; +// tabout->setPixel( j, i, (uint8_t)(ftemp + 0.5) ); +// } + +// *invImg = new Image(tmpImg->getWidth(), tmpImg->getHeight(), tmpImg->getNbChannels()); +// for(unsigned int c = 0; c < tmpImg->getNbChannels(); ++c) { +// for(unsigned int j = 0; j < tmpImg->getHeight(); ++j) { +// for(unsigned int i = 0; i < tmpImg->getWidth(); ++i) { +// double value = tmpImg->getPixelAt(i, j, c); +// (*invImg)->setPixelAt(i, j, c, value + 0.5); +// } +// } +// } + *invImg = Converter<Image>::convertAndRound(*tmpImg); + + +// delete tabin; + return returnval; +} + +//void Transforms::cosinus( const Image *image, Image_t<double> **resImg, Image **invImg ) { +// if(!( im != NULL && result != NULL && result_inverse != NULL )) { +// char buffer[255]; +// sprintf( buffer, "Error in Transforms::cosinus:\nim = %p, result = %p, result_inverse = %p", im, result, result_inverse ); +// throw buffer; +// } +// int idt = 8; +// double res[8]; +// double rmat[8][8]; +// double pi = 3.141592; +// double *tabin; +// int i,j,k,l,m; +// long nbl,nbc,size; +// double a,max; + +///*---------------------------------------------------------------------- +//* +//* RECUPERATION DES PARAMETRES DE LANCEMENT +//* +//*----------------------------------------------------------------------*/ + +///*---------------------------------------------------------------------- +//* +//* OUVERTURE ET LECTURE DU FICHIER IMAGE ORIGINE +//* ALLOCATION MEMOIRE POUR LES TABLEAUX IMAGES +//* +//*----------------------------------------------------------------------*/ +// nbc = im->getWidth(); +// nbl = im->getHeight(); +// size = nbc * nbl; +// GrayscaleImage* tabout = new GrayscaleImage(im->getWidth(), im->getHeight()); +// Image_t<double>* tmpImg = Converter<Image_t<double> >::convert(*image); +//// tabin = new double[ size ]; +//// for(i=0 ; i<nbl ; i++) +//// for(j=0 ; j<nbc ; j++) +//// tabin[i*nbc+j] = (double)im->getPixel( j, i ); + +///*--------------------------------------------------------------------- +//* +//* CALCUL DES COEFFICIENTS DE LA MATRICE DE TRANSFORMATION +//* +//*---------------------------------------------------------------------*/ +// for(int i=0 ; i<idt ; i++) +// { +// for(int j=0 ; j<idt ; j++) +// { +// rmat[i][j] = (double)((cos((2*j+1)*i*pi/16.))/2.); +// } +// } +// for(int i=0 ; i<idt ; i++) +// rmat[0][i] = (double)(1/sqrt((double)idt)); + +///*---------------------------------------------------------------------- +//* +//* TRANSFORMATION +//* +//*----------------------------------------------------------------------*/ +// for(unsigned int i=0 ; i<tmpImg->getHeight() ; i+=idt) +// for(unsigned int j=0 ; j<tmpImg->getWidth() ; j+=idt) +// { +// for(int k=0 ; k<idt ; k++) +// res[k] = 0.; + +// for(int k=0 ; k<idt ; k++) +// { +// for(int l=0 ; l<idt ; l++) +// for(int m=0 ; m<idt ; m++) +// res[l] += rmat[l][m]*(*(tabin+(i+k)*nbc+(j+m))); + +// for(l=0 ; l<idt ; l++) +// { +// *(tabin+(i+k)*nbc+(j+l)) = res[l]; +// res[l] = 0.; +// } +// } + +// for(k=0 ; k<idt ; k++) +// { +// for(l=0 ; l<idt ; l++) +// for(m=0 ; m<idt ; m++) +// res[l] += rmat[l][m]*(*(tabin+(i+m)*nbc+(j+k))); + +// for(l=0 ; l<idt ; l++) +// { +// *(tabin+(i+l)*nbc+(j+k)) = res[l]; +// res[l] = 0.; +// } +// } +// } + +///*---------------------------------------------------------------------- +//* +//* CODAGE +//* +//*----------------------------------------------------------------------*/ + +///*---------------------------------------------------------------------- +//* +//* STOCKAGE DE L'IMAGE TRANSFORMEE DANS UN FICHIER +//* +//*----------------------------------------------------------------------*/ +// max = 0.; +// for(i=0 ; i<nbl ; i++) +// for(j=0 ; j<nbc ; j++) +// { +// a = (double)log(fabs((double)(*(tabin+i*nbc+j))) + 1.); +// if(a > max) max = a; +// } + +// for(i=0 ; i<nbl ; i++) +// for(j=0 ; j<nbc ; j++) +// { +// if( (i%idt)==0 && (j%idt)==0 ) { +// tabout->setPixel( j, i, 0 ); +// } +// else { +// uint8_t p = (uint8_t)(log(fabs((double)(*(tabin+i*nbc+j))) + 1.)*255/max + 0.5); +// tabout->setPixel( j, i, p ); +// } +// } +// *result = tabout; + +///*---------------------------------------------------------------------- +//* +//* TRANSFORMATION INVERSE +//* +//*----------------------------------------------------------------------*/ +// tabout = new GrayscaleImage(im->getWidth(), im->getHeight()); +// for(unsigned int hcounter=0; hcounter< tabout->getHeight(); hcounter++ ) { +// for(unsigned int wcounter=0; wcounter< tabout->getWidth(); wcounter++ ) { +// tabout->setPixel( wcounter, hcounter, (*result)->getPixel( wcounter, hcounter ) ); +// } +// } + +// for(i=0 ; i<nbl ; i+=idt) +// for(j=0 ; j<nbc ; j+=idt) +// { +// for(k=0 ; k<idt ; k++) +// res[k] = 0.; + +// for(k=0 ; k<idt ; k++) +// { +// for(l=0 ; l<idt ; l++) +// for(m=0 ; m<idt ; m++) +// res[l] += rmat[m][l]*(*(tabin+(i+m)*nbc+(j+k))); + +// for(l=0 ; l<idt ; l++) +// { +// *(tabin+(i+l)*nbc+(j+k)) = res[l]; +// res[l] = 0.; +// } +// } + +// for(k=0 ; k<idt ; k++) +// { +// for(l=0 ; l<idt ; l++) +// for(m=0 ; m<idt ; m++) +// res[l] += rmat[m][l]*(*(tabin+(i+k)*nbc+(j+m))); + +// for(l=0 ; l<idt ; l++) +// { +// *(tabin+(i+k)*nbc+(j+l)) = res[l]; +// res[l] = 0.; +// } +// } +// } + +///*---------------------------------------------------------------------- +//* +//* STOCKAGE DE L'IMAGE RESULTAT DANS UN FICHIER +//* +//*----------------------------------------------------------------------*/ +// for(i=0 ; i<nbl ; i++) +// for(j=0 ; j<nbc ; j++) +// { +// double ftemp = (*(tabin+i*nbc+j)); +// if(ftemp < 0) +// ftemp = 0; +// if(ftemp > 255) +// ftemp = 255; +// tabout->setPixel( j, i, (uint8_t)ftemp ); +// } + +// *result_inverse = tabout; + +// delete tabin; +//} diff --git a/app/Operations/Transforms.h b/app/Operations/Transforms.h new file mode 100644 index 0000000000000000000000000000000000000000..3973499c0241fde3815635ffa7997579860f6095 --- /dev/null +++ b/app/Operations/Transforms.h @@ -0,0 +1,37 @@ +/* + * Copyright 2011-2012 INSA Rennes + * + * This file is part of EIImage. + * + * EIImage is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * EIImage 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with EIImage. If not, see <http://www.gnu.org/licenses/>. +*/ + +#ifndef TRANSFORMS_H +#define TRANSFORMS_H + +#include <Image.h> +#include <GrayscaleImage.h> +#include <string> + +namespace Transforms +{ + imagein::Image_t<double> *hough( const imagein::GrayscaleImage *im ); // This function works + imagein::Image_t<double> *hough2( const imagein::Image *im , double angleStep, double rhoStep); // This function works + std::string hough2_inverse(const imagein::Image_t<double> *image, imagein::Image **resImg, unsigned int size, unsigned int threshold); + std::string Hadamard( const imagein::Image *im, imagein::Image_t<double> **result, imagein::Image **result_inverse, imagein::GrayscaleImage_t<bool> *selection = NULL); + std::string Haar( const imagein::Image *im, imagein::Image_t<double> **result, imagein::Image **result_inverse, imagein::GrayscaleImage_t<bool> *selection = NULL ); + std::string cosinus( const imagein::Image *image, imagein::Image_t<double> **resImg, imagein::Image **invImg, imagein::GrayscaleImage_t<bool> *selection = NULL ); +}; + +#endif // TRANSFORMS_H diff --git a/app/Operations/TranslateOp.cpp b/app/Operations/TranslateOp.cpp index d47384ce6e64e6d59044bd36541951dbc7e0fa8e..b05f5d680edd14a0e403b29a3d995aa88d6bae70 100644 --- a/app/Operations/TranslateOp.cpp +++ b/app/Operations/TranslateOp.cpp @@ -4,14 +4,12 @@ #include <QSpinBox> #include <QCheckBox> -#include "ImgWidget.h" - #include "TranslateOp.h" #include "../Tools.h" using namespace std; using namespace imagein; -TranslateOp::TranslateOp() : Operation(Tools::tr("Translation").toStdString()) { +TranslateOp::TranslateOp() : Operation(qApp->translate("Operations", "Translation").toStdString()) { } bool TranslateOp::needCurrentImg() const { @@ -23,7 +21,7 @@ void TranslateOp::operator()(const Image* img, const map<const Image*, string>& vector<QWidget*> result; QString imgName(imgList.find(img)->second.c_str()); QDialog* dialog = new QDialog(); - dialog->setWindowTitle(QString(dialog->tr("Translating %1")).arg(imgName)); + dialog->setWindowTitle(qApp->translate("Translation", "Translating %1").arg(imgName)); dialog->setMinimumWidth(180); QFormLayout* layout = new QFormLayout(); dialog->setLayout(layout); @@ -33,7 +31,7 @@ void TranslateOp::operator()(const Image* img, const map<const Image*, string>& QSpinBox* xSpinBox = new QSpinBox(dialog); QSpinBox* ySpinBox = new QSpinBox(dialog); - QCheckBox* expandBox = new QCheckBox("Expand image", dialog); + QCheckBox* expandBox = new QCheckBox(qApp->translate("TranslateOp", "Expand image"), dialog); QSpinBox* valueSpinBox = new QSpinBox(dialog); xSpinBox->setRange(-65536, 65535); @@ -41,10 +39,10 @@ void TranslateOp::operator()(const Image* img, const map<const Image*, string>& valueSpinBox->setRange(0, 255); valueSpinBox->setValue(0); - layout->insertRow(0, "X offset : ", xSpinBox); - layout->insertRow(1, "Y offset : ", ySpinBox); + layout->insertRow(0, qApp->translate("TranslateOp", "X offset : "), xSpinBox); + layout->insertRow(1, qApp->translate("TranslateOp", "Y offset : "), ySpinBox); layout->insertRow(2, expandBox); - layout->insertRow(3, "Fill value : ", valueSpinBox); + layout->insertRow(3, qApp->translate("TranslateOp", "Fill value : "), valueSpinBox); QDialogButtonBox* buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok|QDialogButtonBox::Cancel, Qt::Horizontal, dialog); layout->insertRow(4, buttonBox); @@ -84,7 +82,7 @@ void TranslateOp::operator()(const Image* img, const map<const Image*, string>& } } - QString name = QString("Translated %1:%2").arg(dx).arg(dy); + QString name = qApp->translate("TranslateOp", "Translated %1:%2").arg(dx).arg(dy); this->outImage(resImg, name.toStdString()); return; } diff --git a/app/Operations/ZeroCrossingOp.cpp b/app/Operations/ZeroCrossingOp.cpp index 6180d9ae5a64c3329ebabb6a119c46fffaaf90ed..0273f092b7138693fcae0dc85c218392a60e616b 100644 --- a/app/Operations/ZeroCrossingOp.cpp +++ b/app/Operations/ZeroCrossingOp.cpp @@ -30,7 +30,7 @@ using namespace std; using namespace imagein; -ZeroCrossingOp::ZeroCrossingOp() : DoubleOperation(Tools::tr("Zero crossing").toStdString()) +ZeroCrossingOp::ZeroCrossingOp() : DoubleOperation(qApp->translate("Operations", "Zero crossing").toStdString()) { } @@ -41,7 +41,7 @@ bool ZeroCrossingOp::needCurrentImg() const { void ZeroCrossingOp::operator()(const imagein::Image_t<double>* img, const std::map<const imagein::Image_t<double>*, std::string>&) { QDialog* dialog = new QDialog(QApplication::activeWindow()); - dialog->setWindowTitle(QString(dialog->tr("Zero crossing"))); + dialog->setWindowTitle(QString(qApp->translate("ZeroCrossingOp", "Zero crossing"))); dialog->setMinimumWidth(180); QFormLayout* layout = new QFormLayout(); dialog->setLayout(layout); @@ -49,7 +49,7 @@ void ZeroCrossingOp::operator()(const imagein::Image_t<double>* img, const std:: QDoubleSpinBox* thresholdBox = new QDoubleSpinBox(); thresholdBox->setRange(0., 65536.); - layout->insertRow(0, dialog->tr("Threshold : "), thresholdBox); + layout->insertRow(0, qApp->translate("ZeroCrossingOp", "Threshold : "), thresholdBox); QDialogButtonBox* buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok|QDialogButtonBox::Cancel, Qt::Horizontal, dialog); layout->insertRow(3, buttonBox); @@ -107,6 +107,6 @@ void ZeroCrossingOp::operator()(const imagein::Image_t<double>* img, const std:: } } - outDoubleImage(result, "contours bruts"); - outDoubleImage(result2, "contours nettoyes"); + outDoubleImage(result, qApp->translate("ZeroCrossingOp", "contours bruts").toStdString()); + outDoubleImage(result2, qApp->translate("ZeroCrossingOp", "contours nettoyes").toStdString()); } diff --git a/app/RandomLib/CMakeFiles/CMakeDirectoryInformation.cmake b/app/RandomLib/CMakeFiles/CMakeDirectoryInformation.cmake deleted file mode 100644 index ec8a7742f4a5cbb693160bf8921a367b48cc4458..0000000000000000000000000000000000000000 --- a/app/RandomLib/CMakeFiles/CMakeDirectoryInformation.cmake +++ /dev/null @@ -1,23 +0,0 @@ -# CMAKE generated file: DO NOT EDIT! -# Generated by "Unix Makefiles" Generator, CMake Version 2.8 - -# Relative path conversion top directories. -SET(CMAKE_RELATIVE_PATH_TOP_SOURCE "/home/sacha/Downloads/RandomLib-1.5") -SET(CMAKE_RELATIVE_PATH_TOP_BINARY "/home/sacha/Downloads/RandomLib-1.5") - -# Force unix paths in dependencies. -SET(CMAKE_FORCE_UNIX_PATHS 1) - -# The C and CXX include file search paths: -SET(CMAKE_C_INCLUDE_PATH - "include" - ) -SET(CMAKE_CXX_INCLUDE_PATH ${CMAKE_C_INCLUDE_PATH}) -SET(CMAKE_Fortran_INCLUDE_PATH ${CMAKE_C_INCLUDE_PATH}) -SET(CMAKE_ASM_INCLUDE_PATH ${CMAKE_C_INCLUDE_PATH}) - -# The C and CXX include file regular expressions for this directory. -SET(CMAKE_C_INCLUDE_REGEX_SCAN "^.*$") -SET(CMAKE_C_INCLUDE_REGEX_COMPLAIN "^$") -SET(CMAKE_CXX_INCLUDE_REGEX_SCAN ${CMAKE_C_INCLUDE_REGEX_SCAN}) -SET(CMAKE_CXX_INCLUDE_REGEX_COMPLAIN ${CMAKE_C_INCLUDE_REGEX_COMPLAIN}) diff --git a/app/RandomLib/CMakeFiles/progress.marks b/app/RandomLib/CMakeFiles/progress.marks deleted file mode 100644 index 573541ac9702dd3969c9bc859d2b91ec1f7e6e56..0000000000000000000000000000000000000000 --- a/app/RandomLib/CMakeFiles/progress.marks +++ /dev/null @@ -1 +0,0 @@ -0 diff --git a/app/RandomLib/CMakeLists.txt b/app/RandomLib/CMakeLists.txt deleted file mode 100644 index 92979ae322611dd6ed384a955848eb6b3408d27e..0000000000000000000000000000000000000000 --- a/app/RandomLib/CMakeLists.txt +++ /dev/null @@ -1,8 +0,0 @@ -# $Id: 0ff45cb4371024d7d85cc9884c6372c568921c65 $ - -# Install the header files including the generated Config.h (which is in -# the build tree). -file (GLOB HEADERS *.hpp) -install (FILES ${HEADERS} DESTINATION include/RandomLib) -install (FILES ${CMAKE_CURRENT_BINARY_DIR}/Config.h - DESTINATION include/RandomLib) diff --git a/app/RandomLib/Config.h b/app/RandomLib/Config.h deleted file mode 100644 index e75b434c77b4e738dc057a34c673ccb1fd9c0e61..0000000000000000000000000000000000000000 --- a/app/RandomLib/Config.h +++ /dev/null @@ -1,9 +0,0 @@ -// $Id: e8cf4f146baf9674fb19041fe3f42231958e0200 $ - -#define RANDOMLIB_VERSION_STRING "1.5" - -// These are macros which affect the building of the library -#define RANDOM_SHARED_LIB 1 -/* #undef HAVE_SSE2 */ -/* #undef HAVE_ALTIVEC */ -#define HAVE_LONG_DOUBLE 1 diff --git a/app/RandomLib/Config.h.in b/app/RandomLib/Config.h.in deleted file mode 100644 index 815ab165b2532db094703891aecf8827230d3f91..0000000000000000000000000000000000000000 --- a/app/RandomLib/Config.h.in +++ /dev/null @@ -1,9 +0,0 @@ -// $Id: e8cf4f146baf9674fb19041fe3f42231958e0200 $ - -#define RANDOMLIB_VERSION_STRING "@RandomLib_VERSION@" - -// These are macros which affect the building of the library -#cmakedefine RANDOM_SHARED_LIB 1 -#cmakedefine HAVE_SSE2 1 -#cmakedefine HAVE_ALTIVEC 1 -#cmakedefine HAVE_LONG_DOUBLE 1 diff --git a/app/RandomLib/Config.h.template b/app/RandomLib/Config.h.template deleted file mode 100644 index 651064d7861a0af768232ab5488d745374bf7a8c..0000000000000000000000000000000000000000 --- a/app/RandomLib/Config.h.template +++ /dev/null @@ -1,12 +0,0 @@ -// $Id: 3a37988377ea144f891b1142150247bed67ac476 $ - -#define RANDOMLIB_VERSION_STRING "Unconfigured" - -// Define HAVE_SSE2 to be 1 if Intel/AMD CPU with SSE2 support -/* #undef HAVE_SSE2 */ - -// Define HAVE_ALTIVEC to be 1 if Power PC CPU with AltiVec support -/* #undef HAVE_ALTIVEC */ - -// Undefine HAVE_LONG_DOUBLE if this type is unknown to the compiler -#define HAVE_LONG_DOUBLE 1 diff --git a/app/RandomLib/ExactExponential.hpp b/app/RandomLib/ExactExponential.hpp deleted file mode 100644 index 10948112f1ca31d0ac0a33ab6b656df46eccbe0d..0000000000000000000000000000000000000000 --- a/app/RandomLib/ExactExponential.hpp +++ /dev/null @@ -1,230 +0,0 @@ -/** - * \file ExactExponential.hpp - * \brief Header for ExactExponential - * - * Sample exactly from an exponential distribution. - * - * Copyright (c) Charles Karney (2006-2012) <charles@karney.com> and licensed - * under the MIT/X11 License. For more information, see - * http://randomlib.sourceforge.net/ - **********************************************************************/ - -#if !defined(RANDOMLIB_EXACTEXPONENTIAL_HPP) -#define RANDOMLIB_EXACTEXPONENTIAL_HPP \ - "$Id: 25ebc0248e6e5cf18b5616767d4c5bb632fa15c3 $" - -#include <RandomLib/RandomNumber.hpp> - -namespace RandomLib { - /** - * \brief Sample exactly from an exponential distribution. - * - * Sample \e x >= 0 from exp(-\e x). See: - * - J. von Neumann, Various Techniques used in Connection with Random - * Digits, J. Res. Nat. Bur. Stand., Appl. Math. Ser. 12, 36-38 (1951), - * reprinted in Collected Works, Vol. 5, 768-770 (Pergammon, 1963). - * - M. Abramowitz and I. A. Stegun, Handbook of Mathematical Functions - * (National Bureau of Standards, 1964), Sec. 26.8.6.c.2. - * - G. E. Forsythe, Von Neumann's Comparison Method for Random Sampling from - * Normal and Other Distributions, Math. Comp. 26, 817-826 (1972). - * - D. E. Knuth, TAOCP, Vol 2, Sec 3.4.1.C.3. - * - D. E. Knuth and A. C. Yao, The Complexity of Nonuniform Random Number - * Generation, in "Algorithms and Complexity" (Academic Press, 1976), - * pp. 357-428. - * - P. Flajolet and N. Saheb, The Complexity of Generating an - * Exponentially Distributed Variate, J. Algorithms 7, 463-488 (1986). - * - * The following code illustrates the basic method given by von Neumann: - * \code -// Return a random number x >= 0 distributed with probability exp(-x). -double ExpDist(RandomLib::Random& r) { - for (unsigned k = 0; ; ++k) { - double x = r.Fixed(), // executed 1/(1-exp(-1)) times on average - p = x, q; - do { - q = r.Fixed(); // executed exp(x)*cosh(x) times on average - if (!(q < p)) return k + x; - p = r.Fixed(); // executed exp(x)*sinh(x) times on average - } while (p < q); - } -} -\endcode - * This returns a result consuming exp(1)/(1 - exp(-1)) = 4.30 random - * numbers on average. (Von Neumann incorrectly states that the method takes - * (1 + exp(1))/(1 - exp(-1)) = 5.88 random numbers on average.) Because of - * the finite precision of Random::Fixed(), the code snippet above only - * approximates exp(-\e x). Instead, it returns \e x with probability \e - * h(1 - \e h)<sup><i>x</i>/<i>h</i></sup> for \e x = \e ih, \e h = - * 2<sup>-53</sup>, and integer \e i >= 0. - * - * The above is precisely von Neumann's method. Abramowitz and Stegun - * consider a variant: sample uniform variants until the first is less - * than the sum of the rest. Forsythe converts the < ranking for the runs to - * <= which makes the analysis of the discrete case more difficult. He also - * drops the "trick" by which the integer part of the deviate is given by the - * number of rejections when finding the fractional part. - * - * Von Neumann says of his method: "The machine has in effect computed a - * logarithm by performing only discriminations on the relative magnitude of - * numbers in (0,1). It is a sad fact of life, however, that under the - * particular conditions of the Eniac it was slightly quicker to use a - * truncated power series for log(1-\e T) than to carry out all the - * discriminations." - * - * Here the code is modified to make it more efficient: - * \code -// Return a random number x >= 0 distributed with probability exp(-x). -double ExpDist(RandomLib::Random& r) { - for (unsigned k = 0; ; ++k) { - double x = r.Fixed(); // executed 1/(1-exp(-1/2)) times on average - if (x >= 0.5) continue; - double p = x, q; - do { - q = r.Fixed(); // executed exp(x)*cosh(x) times on average - if (!(q < p)) return 0.5 * k + x; - p = r.Fixed(); // executed exp(x)*sinh(x) times on average - } while (p < q); - } -} -\endcode - * In addition, the method is extended to use infinite precision uniform - * deviates implemented by RandomNumber and returning \e exact results for - * the exponential distribution. This is possible because only comparisons - * are done in the method. The template parameter \e bits specifies the - * number of bits in the base used for RandomNumber (i.e., base = - * 2<sup><i>bits</i></sup>). - * - * For example the following samples from an exponential distribution and - * prints various representations of the result. - * \code -#include <RandomLib/RandomNumber.hpp> -#include <RandomLib/ExactExponential.hpp> - - RandomLib::Random r; - const int bits = 1; - RandomLib::ExactExponential<bits> edist; - for (size_t i = 0; i < 10; ++i) { - RandomLib::RandomNumber<bits> x = edist(r); // Sample - std::pair<double, double> z = x.Range(); - std::cout << x << " = " // Print in binary with ellipsis - << "(" << z.first << "," << z.second << ")"; // Print range - double v = x.Value<double>(r); // Round exactly to nearest double - std::cout << " = " << v << "\n"; - } -\endcode - * Here's a possible result: -\verbatim - 0.0111... = (0.4375,0.5) = 0.474126 - 10.000... = (2,2.125) = 2.05196 - 1.00... = (1,1.25) = 1.05766 - 0.010... = (0.25,0.375) = 0.318289 - 10.1... = (2.5,3) = 2.8732 - 0.0... = (0,0.5) = 0.30753 - 0.101... = (0.625,0.75) = 0.697654 - 0.00... = (0,0.25) = 0.0969214 - 0.0... = (0,0.5) = 0.194053 - 0.11... = (0.75,1) = 0.867946 -\endverbatim - * First number is in binary with ... indicating an infinite sequence of - * random bits. Second number gives the corresponding interval. Third - * number is the result of filling in the missing bits and rounding exactly - * to the nearest representable double. - * - * This class uses some mutable RandomNumber objects. So a single - * ExactExponential object cannot safely be used by multiple threads. In a - * multi-processing environment, each thread should use a thread-specific - * ExactExponential object. In addition, these should be invoked with - * thread-specific random generator objects. - * - * @tparam bits the number of bits in each digit. - **********************************************************************/ - template<int bits = 1> class ExactExponential { - public: - /** - * Return a random deviate with an exponential distribution, exp(-\e x) for - * \e x >= 0. Requires 7.232 bits per invocation for \e bits = 1. The - * average number of bits in the fraction = 1.743. The relative frequency - * of the results for the fractional part with \e bits = 1 is shown by the - * histogram\n - * <img src="exphist.png" width=580 height=750 - * alt="exact binary sampling of exponential distribution">\n - * The base of each rectangle gives the range represented by the - * corresponding binary number and the area is proportional to its - * frequency. A PDF version of this figure is given - * <a href="exphist.pdf">here</a>. This allows the figure to be magnified - * to show the rectangles for all binary numbers up to 9 bits. Note that - * this histogram was generated using an earlier version of - * ExactExponential (thru version 1.3) that implements von Neumann's - * original method. The histogram generated with the current version of - * ExactExponential is the same as this figure for \e u in [0, 1/2]. The - * histogram for \e u in [1/2, 1] is obtained by shifting and scaling the - * part for \e u in [0, 1/2] to fit under the exponential curve. - * - * Another way of assessing the efficiency of the algorithm is thru the - * mean value of the balance = (number of random bits consumed) - (number - * of bits in the result). If we code the result in mixed Knuth and Yao's - * unary-binary notation (integer is given in unary, followed by "0" as a - * separator, followed by the fraction in binary), then the mean balance is - * 3.906. (Flajolet and Saheb analyzed the algorithm based on the original - * von Neumann method and showed that the balance is 5.680 in that case.) - * - * For \e bits large, the mean number of random digits is exp(1/2)/(1 - - * exp(-1/2)) = 4.19 (versus 4.30 digits for the original method). - * - * @tparam Random the type of the random generator. - * @param[in,out] r a random generator. - * @return the random sample. - **********************************************************************/ - template<class Random> RandomNumber<bits> operator()(Random& r) const; - private: - /** - * Return true with probability exp(-\e p) for \e p in (0,1/2). - **********************************************************************/ - template<class Random> bool - ExpFraction(Random& r, RandomNumber<bits>& p) const; - mutable RandomNumber<bits> _x; - mutable RandomNumber<bits> _v; - mutable RandomNumber<bits> _w; - }; - - template<int bits> template<class Random> RandomNumber<bits> - ExactExponential<bits>::operator()(Random& r) const { - // A simple rejection method gives the 1/2 fractional part. The number of - // rejections gives the multiples of 1/2. - // - // bits: used fract un-bin balance double - // original stats: 9.31615 2.05429 3.63628 5.67987 61.59456 - // new stats: 7.23226 1.74305 3.32500 3.90725 59.82198 - _x.Init(); - int k = 0; - while (!ExpFraction(r, _x)) { // Executed 1/(1 - exp(-1/2)) on average - ++k; - _x.Init(); - } - if (k & 1) _x.RawDigit(0) += 1 << (bits - 1); - _x.AddInteger(k >> 1); - return _x; - } - - template<int bits> template<class Random> bool - ExactExponential<bits>::ExpFraction(Random& r, RandomNumber<bits>& p) - const { - // The early bale out - if (p.Digit(r, 0) >> (bits - 1)) return false; - // Implement the von Neumann algorithm - _w.Init(); - if (!_w.LessThan(r, p)) // if (w < p) - return true; - while (true) { // Unroll loop to avoid copying RandomNumber - _v.Init(); // v = r.Fixed(); - if (!_v.LessThan(r, _w)) // if (v < w) - return false; - _w.Init(); // w = r.Fixed(); - if (!_w.LessThan(r, _v)) // if (w < v) - return true; - } - } - -} // namespace RandomLib - -#endif // RANDOMLIB_EXACTEXPONENTIAL_HPP diff --git a/app/RandomLib/ExactNormal.hpp b/app/RandomLib/ExactNormal.hpp deleted file mode 100644 index 2f0af8d2600f69da7adfe62576e2f47d9c7c7963..0000000000000000000000000000000000000000 --- a/app/RandomLib/ExactNormal.hpp +++ /dev/null @@ -1,400 +0,0 @@ -/** - * \file ExactNormal.hpp - * \brief Header for ExactNormal - * - * Sample exactly from a normal distribution. - * - * Copyright (c) Charles Karney (2011, 2012) <charles@karney.com> and licensed - * under the MIT/X11 License. For more information, see - * http://randomlib.sourceforge.net/ - **********************************************************************/ - -#if !defined(RANDOMLIB_EXACTNORMAL_HPP) -#define RANDOMLIB_EXACTNORMAL_HPP \ - "$Id: 9ee73b561ec195199553237ae749b7e937408f59 $" - -#include <RandomLib/RandomNumber.hpp> -#include <algorithm> // for max/min - -namespace RandomLib { - /** - * \brief Sample exactly from a normal distribution. - * - * Sample \e x from exp(-<i>x</i><sup>2</sup>/2) / sqrt(2 pi). For - * background, see: - * - J. von Neumann, Various Techniques used in Connection with Random - * Digits, J. Res. Nat. Bur. Stand., Appl. Math. Ser. 12, 36-38 (1951), - * reprinted in Collected Works, Vol. 5, 768-770 (Pergammon, 1963). - * - D. E. Knuth and A. C. Yao, The Complexity of Nonuniform Random Number - * Generation, in "Algorithms and Complexity" (Academic Press, 1976), - * pp. 357-428. - * - P. Flajolet and N. Saheb, The Complexity of Generating an - * Exponentially Distributed Variate, J. Algorithms 7, 463-488 (1986). - * - * The algorithm is as follows: - * -# Select an integer \e k >= 0 with probability - * exp(-<i>k</i>/2) (1-exp(-1/2)). - * -# Accept with probability - * exp(- \e k (\e k - 1) / 2); otherwise, reject and start over at step 1. - * -# Sample a random number \e x uniformly from [0,1). - * -# Accept with probability exp(- \e x (\e x + 2\e k) / 2); - * otherwise, reject and start over at step 1. - * -# Set \e x = \e k + \e x. - * -# With probability 1/2, negate \e x. - * -# Return \e x. - * . - * It is easy to show that this algorithm returns samples from the normal - * distribution with zero mean and unit variance. Futhermore, all these - * steps can be carried out exactly as follows: - * - Step 1: - * - \e k = 0; - * - while (ExpProb(-1/2)) increment \e k by 1. - * - Step 2: - * - \e n = \e k (\e k - 1) / 2; - * - while (\e n > 0) - * { if (!ExpProb(-1/2)) go to step 1; decrement \e n by 1; } - * - Step 4: - * - repeat \e k + 1 times: - * if (!ExpProb(- \e x (\e x + 2\e k) / (2\e k + 2))) go to step 1. - * . - * Here, ExpProb(-\e p) returns true with probability exp(-\e p). With \e p - * = 1/2 (steps 1 and 2), this is implemented with von Neumann's rejection - * technique: - * - Generate a sequence of random numbers <i>U</i><sub><i>i</i></sub> and - * find the greatest \e n such that 1/2 > <i>U</i><sub>1</sub> > - * <i>U</i><sub>2</sub> > . . . > <i>U</i><sub><i>n</i></sub>. (The - * resulting value of \e n may be 0.) - * - If \e n is even, accept and return true; otherwise (\e n odd), reject - * and return false. - * . - * For \e p = \e x (\e x + 2\e k) / (2\e k + 2) (step 4), we generalize von - * Neumann's procedure as follows: - * - Generate two sequences of random numbers <i>U</i><sub><i>i</i></sub> - * and <i>V</i><sub><i>i</i></sub> and find the greatest \e n such that - * both the following conditions hold - * - \e x > <i>U</i><sub>1</sub> > <i>U</i><sub>2</sub> > . . . > - * <i>U</i><sub><i>n</i></sub>; - * - <i>V</i><sub><i>i</i></sub> < (\e x + 2 \e k) / (2 \e k + 2) for - * all \e i in [1, \e n]. - * . - * (The resulting value of \e n may be 0.) - * - If \e n is even, accept (return true); otherwise (\e n odd), reject - * (return false). - * . - * Here, instead of testing <i>V</i><sub><i>i</i></sub> < (\e x + 2 \e k) - * / (2 \e k + 2), we carry out the following tests: - * - return true, with probability 2 \e k / (2 \e k + 2); - * - return false, with probability 1 / (2 \e k + 2); - * - otherwise (also with probability 1 / (2 \e k + 2)), - * return \e x > <i>V</i><sub><i>i</i></sub>. - * . - * The resulting method now entails evaluation of simple fractional - * probabilities (e.g., 1 / (2 \e k + 2)), or comparing random numbers (e.g., - * <i>U</i><sub>1</sub> > <i>U</i><sub>2</sub>). These may be carried out - * exactly with a finite mean running time. - * - * With \e bits = 1, this consumes 30.1 digits on average and the result has - * 1.19 digits in the fraction. It takes about 676 ns to generate a result - * (1460 ns, including the time to round it to a double). With bits = 32, it - * takes 437 ns to generate a result (621 ns, including the time to round it - * to a double). In contrast, NormalDistribution takes about 44 ns to - * generate a double result. - * - * Another way of assessing the efficiency of the algorithm is thru the mean - * value of the balance = (number of random bits consumed) - (number of bits - * in the result). If we code the result in Knuth & Yao's unary-binary - * notation, then the mean balance is 26.6. - * - * For example the following samples from a normal exponential distribution - * and prints various representations of the result. - * \code -#include <RandomLib/RandomNumber.hpp> -#include <RandomLib/ExactNormal.hpp> - - RandomLib::Random r; - const int bits = 1; - RandomLib::ExactNormal<bits> ndist; - for (size_t i = 0; i < 10; ++i) { - RandomLib::RandomNumber<bits> x = ndist(r); // Sample - std::pair<double, double> z = x.Range(); - std::cout << x << " = " // Print in binary with ellipsis - << "(" << z.first << "," << z.second << ")"; // Print range - double v = x.Value<double>(r); // Round exactly to nearest double - std::cout << " = " << v << "\n"; - } -\endcode - * Here's a possible result: -\verbatim --1.00... = (-1.25,-1) = -1.02142 --0.... = (-1,0) = -0.319708 -0.... = (0,1) = 0.618735 --0.0... = (-0.5,0) = -0.396591 -0.0... = (0,0.5) = 0.20362 -0.0... = (0,0.5) = 0.375662 --1.111... = (-2,-1.875) = -1.88295 --1.10... = (-1.75,-1.5) = -1.68088 --0.... = (-1,0) = -0.577547 --0.... = (-1,0) = -0.890553 -\endverbatim - * First number is in binary with ... indicating an infinite sequence of - * random bits. Second number gives the corresponding interval. Third - * number is the result of filling in the missing bits and rounding exactly - * to the nearest representable double. - * - * This class uses some mutable RandomNumber objects. So a single - * ExactNormal object cannot safely be used by multiple threads. In a - * multi-processing environment, each thread should use a thread-specific - * ExactNormal object. In addition, these should be invoked with - * thread-specific random generator objects. - * - * @tparam bits the number of bits in each digit. - **********************************************************************/ - template<int bits = 1> class ExactNormal { - public: - /** - * Return a random deviate with a normal distribution of mean 0 and - * variance 1. - * - * @tparam Random the type of the random generator. - * @param[in,out] r a random generator. - * @return the random sample. - **********************************************************************/ - template<class Random> RandomNumber<bits> operator()(Random& r) const; - private: - /** - * Return true with probability exp(-1/2). For \e bits = 1, this consumes, - * on average, \e t = 2.846 random digits. We have \e t = \e a - * (1-exp(-1/2)) + \e b exp(-1/2), where \e a is the mean bit count for - * false result = 3.786 and \e b is the mean bit count for true result = - * 2.236. - **********************************************************************/ - template<class Random> bool ExpProbH(Random& r) const; - - /** - * Return true with probability exp(-<i>n</i>/2). For \e bits = 1, this - * consumes, on average, \e t (1-exp(-<i>n</i>/2))/(1-exp(-1/2)) random - * digits. A true result uses \e n \e b random digits. A false result - * uses \e a + \e b [exp(-1/2)/(1-exp(-1/2)) - - * <i>n</i> exp(-<i>n</i>/2)/(1-exp(-<i>n</i>/2))] random digits. - **********************************************************************/ - template<class Random> bool ExpProb(Random& r, unsigned n) const; - - /** - * Return \e n with probability exp(-<i>n</i>/2) (1-exp(-1/2)). For \e - * bits = 1, this consumes \e n \e a + \e b random digits if the result is - * \e n. Averaging over \e n this becomes (\e b - (\e b - \e a) - * exp(-1/2))/(1 - exp(-1/2)) digits. - **********************************************************************/ - template<class Random> unsigned ExpProbN(Random& r) const; - - /** - * Return true with probability 1/2. This is similar to r.Boolean() but - * forces all the random results to come thru RandomNumber::RandomDigit. - **********************************************************************/ - template<class Random> static bool Boolean(Random& r) { - // A more general implementation which deals with the case where the base - // might be negative is: - // - // const unsigned base = 1u << bits; - // unsigned b; - // do - // b = RandomNumber<bits>::RandomDigit(r); - // while (b == (base / 2) * 2); - // return b & 1u; - return RandomNumber<bits>::RandomDigit(r) & 1u; - } - - /** - * Implement outcomes for choosing with prob (\e x + 2\e k) / (2\e k + 2); - * return: - * - 1 (succeed unconditionally) with prob (2\e k) / (2\e k + 2), - * - 0 (succeed with probability x) with prob 1 / (2\e k + 2), - * - -1 (fail unconditionally) with prob 1 / (2\e k + 2). - * . - * This simulates \code - double x = r.Fixed(); // Uniform in [0,1) - x *= (2 * k + 2); - return x < 2 * k ? 1 : (x < 2 * k + 1 ? 0 : -1); -\endcode - **********************************************************************/ - template<class Random> static int Choose(Random& r, int k) { - // Limit base to 2^15 to avoid integer overflow - const int b = bits > 15 ? 15 : bits; - const unsigned mask = (1u << b) - 1; - const int m = 2 * k + 2; - int n1 = m - 2, n2 = m - 1; - // Evaluate u < n/m where u is a random real number in [0,1). Write u = - // (d + u') / 2^b where d is a random integer in [0,2^b) and u' is in - // [0,1). Then u < n/m becomes u' < n'/m where n' = 2^b * n - d * m and - // exit if n' <= 0 (false) or n >= m (true). - while (true) { - int d = (mask & RandomNumber<bits>::RandomDigit(r)) * m; - n1 = std::max((n1 << b) - d, 0); - if (n1 >= m) return 1; - n2 = std::min((n2 << b) - d, m); - if (n2 <= 0) return -1; - if (n1 == 0 && n2 == m) return 0; - } - } - - mutable RandomNumber<bits> _x; - mutable RandomNumber<bits> _p; - mutable RandomNumber<bits> _q; - }; - - template<int bits> template<class Random> - bool ExactNormal<bits>::ExpProbH(Random& r) const { - // Bit counts - // ExpProbH: 2.846 = 3.786 * (1-exp(-1/2)) + 2.236 * exp(-1/2) - // t = a * (1-exp(-1/2)) + b * exp(-1/2) - // t = mean bit count for result = 2.846 - // a = mean bit count for false result = 3.786 - // b = mean bit count for true result = 2.236 - // - // for bits large - // t = exp(1/2) = 1.6487 - // a = exp(1/2)/(2*(1-exp(-1/2))) = 2.0951 - // b = exp(1/2)/(2*exp(-1/2)) = 1.3591 - // - // Results for Prob(exp(-1)), omitting first test - // total = 5.889, false = 5.347, true = 6.826 - // - // Results for Prob(exp(-1)) using ExpProbH(r) && ExpProbH(r), - // total = 4.572 = (1 - exp(-1)) * a + (1 + exp(-1/2)) * exp(-1/2) * b - // false = 4.630 = a + b * exp(-1/2)/(1 + exp(-1/2)), - // true = 4.472 = 2 * b - _p.Init(); - if (_p.Digit(r, 0) >> (bits - 1)) return true; - while (true) { - _q.Init(); if (!_q.LessThan(r, _p)) return false; - _p.Init(); if (!_p.LessThan(r, _q)) return true; - } - } - - template<int bits> template<class Random> - bool ExactNormal<bits>::ExpProb(Random& r, unsigned n) const { - // Bit counts - // ExpProb(n): t * (1-exp(-n/2))/(1-exp(-1/2)) - // ExpProb(n) = true: n * b - // ExpProb(n) = false: a + - // b * (exp(-1/2)/(1-exp(-1/2)) - n*exp(-n/2)/(1-exp(-n/2))) - while (n--) { if (!ExpProbH(r)) return false; } - return true; - } - - template<int bits> template<class Random> - unsigned ExactNormal<bits>::ExpProbN(Random& r) const { - // Bit counts - // ExpProbN() = n: n * a + b - unsigned n = 0; - while (ExpProbH(r)) ++n; - return n; - } - - template<int bits> template<class Random> RandomNumber<bits> - ExactNormal<bits>::operator()(Random& r) const { - // With bits = 1, - // - mean number of bits used = 30.10434 - // - mean number of bits in fraction = 1.18700 - // - mean number of bits in result = 3.55257 (unary-binary) - // - mean balance = 30.10434 - 3.55257 = 26.55177 - // - mean number of bits to generate a double = 83.33398 - // . - // Note - // - unary-binary notation (Knuth + Yao, 1976): write x = n + y, with n = - // integer and y in [0,1). If n >=0, then write (n+1) 1's followed by a - // 0; otherwise (n < 0), write (-n) 0's followed by a 1. Write y as a - // binary fraction. - // - (bits in result) - (bits in fraction) = 2 (for encoding overhead for - // the integer part) + 0.36557, where 0.36557 = (bits used for integer - // part) = sum(k*int(sqrt(2/pi)*exp(-x^2/2), x=k..k+1), k=0..inf) - // - (bits for double) approx (bits used) - (bits in fraction) + 1 (for - // guard bit) + 53.41664 where 53.41664 = (bits in fraction of double) = - // sum((52-l)*int(sqrt(2/pi)*exp(-x^2/2), x=2^l,2^(l+1)), l=-inf..inf) - // This is approximate because it doesn't account for the minimum - // exponent, denormalized numbers, and rounding changing the exponent. - // - while (true) { - // Executed sqrt(2/pi)/(1-exp(-1/2)) = 2.027818889827955 times on - // average. - unsigned k = ExpProbN(r); // the integer part of the result. - if (ExpProb(r, (k - 1) * k)) { - // Probability that this test succeeds is - // (1 - exp(-1/2)) * sum(exp(-k/2) * exp(-(k-1)*k/2), k=0..inf)) - // = (1 - exp(-1/2)) * G = 0.7391491050895928 - // where G = sum(exp(-k^2/2, k=0..inf) = 1.753314144021453 - // For k == 0, sample from exp(-x^2/2) for x in [0,1]. This succeeds - // with probability int(exp(-x^2/2),x=0..1). - // - // For general k, substitute x' = x + k in exp(-x'^2/2), and obtain - // exp(-k^2/2) * exp(-x*(x+2*k)/2). So sample from exp(-x*(x+2*k)/2). - // This succeeds with probability int(exp(-x*(x+2*k)/2),x=0..1) = - // int(exp(-x^2/2),x=k..k+1)*exp(k^2/2) = - // - // 0.8556243918921 for k = 0 - // 0.5616593588061 for k = 1 - // 0.3963669350376 for k = 2 - // 0.2974440159655 for k = 3 - // 0.2345104783458 for k = 4 - // 0.1921445042826 for k = 5 - // - // Returns a result with prob sqrt(pi/2) / G = 0.714825772431666; - // otherwise another trip through the outer loop is taken. - _x.Init(); - unsigned s = 1; - for (unsigned j = 0; j <= k; ++j) { // execute k + 1 times - bool first; - for (s = 1, first = true; ; s ^= 1, first = false) { - // A simpler algorithm is indicated by ALT, results in - // - mean number of bits used = 29.99968 - // - mean number of bits in fraction = 1.55580 - // - mean number of bits in result = 3.92137 (unary-binary) - // - mean balance = 29.99968 - 3.92137 = 26.07831 - // - mean number of bits to generate a double = 82.86049 - // . - // This has a smaller balance (by 0.47 bits). However the number - // of bits in the fraction is larger by 0.37 - if (first) { // ALT: if (false) { - // This implements the success prob (x + 2*k) / (2*k + 2). - int y = Choose(r, k); - if (y < 0) break; // the y test fails - _q.Init(); - if (y > 0) { // the y test succeeds just test q < x - if (!_q.LessThan(r, _x)) break; - } else { // the y test is ambiguous - // Test max(q, p) < x. List _q before _p since it ends up with - // slight more digits generated (and these will be used - // subsequently). (_p's digits are immediately thrown away.) - _p.Init(); if (!_x.GreaterPair(r, _q, _p)) break; - } - } else { - // Split off the failure test for k == 0, i.e., factor the prob - // x/2 test into the product: 1/2 (here) times x (in assignment - // of y). - if (k == 0 && Boolean(r)) break; - // ALT: _q.Init(); if (!_q.LessThan(r, first ? _x : _p)) break; - _q.Init(); if (!_q.LessThan(r, _p)) break; - // succeed with prob k == 0 ? x : (x + 2*k) / (2*k + 2) - int y = k == 0 ? 0 : Choose(r, k); - if (y < 0) - break; - else if (y == 0) { - _p.Init(); if (!_p.LessThan(r, _x)) break; - } - } - _p.swap(_q); // a fast way of doing p = q - } - if (s == 0) break; - } - if (s != 0) { - _x.AddInteger(k); - if (Boolean(r)) _x.Negate(); // half of the numbers are negative - return _x; - } - } - } - } - -} // namespace RandomLib - -#endif // RANDOMLIB_EXACTNORMAL_HPP diff --git a/app/RandomLib/ExactPower.hpp b/app/RandomLib/ExactPower.hpp deleted file mode 100644 index 95dedaade189c4ce38c69f234bbe4d681b2e547f..0000000000000000000000000000000000000000 --- a/app/RandomLib/ExactPower.hpp +++ /dev/null @@ -1,103 +0,0 @@ -/** - * \file ExactPower.hpp - * \brief Header for ExactPower - * - * Sample exactly from a power distribution. - * - * Copyright (c) Charles Karney (2006-2011) <charles@karney.com> and licensed - * under the MIT/X11 License. For more information, see - * http://randomlib.sourceforge.net/ - **********************************************************************/ - -#if !defined(RANDOMLIB_EXACTPOWER_HPP) -#define RANDOMLIB_EXACTPOWER_HPP \ - "$Id: 788de166a8e87f38aa42bc6b3e2386b4523d0f7e $" - -#include <RandomLib/RandomNumber.hpp> - -namespace RandomLib { - /** - * \brief Sample exactly from a power distribution. - * - * Sample exactly from power distribution (<i>n</i> + 1) - * <i>x</i><sup><i>n</i></sup> for \e x in (0,1) and integer \e n >= 0 using - * infinite precision. The template parameter \e bits specifies the number - * of bits in the base used for RandomNumber (i.e., base = - * 2<sup><i>bits</i></sup>). - * - * This class uses some mutable RandomNumber objects. So a single ExactPower - * object cannot safely be used by multiple threads. In a multi-processing - * environment, each thread should use a thread-specific ExactPower object. - * In addition, these should be invoked with thread-specific random generator - * objects. - * - * @tparam bits the number of bits in each digit. - **********************************************************************/ - template<int bits = 1> class ExactPower { - public: - /** - * Return the random deviate with a power distribution, (<i>n</i> + 1) - * <i>x</i><sup><i>n</i></sup> for \e x in (0,1) and integer \e n >= 0. - * Returned result is a RandomNumber with base 2<sup><i>bits</i></sup>. - * For \e bits = 1, the number of random bits in the result and consumed - * are as follows:\n -\verbatim - n random bits - result consumed - 0 0 0 - 1 2 4 - 2 2.33 6.67 - 3 2.67 9.24 - 4 2.96 11.71 - 5 3.20 14.11 - 6 3.41 16.45 - 7 3.59 18.75 - 8 3.75 21.01 - 9 3.89 23.25 - 10 4.02 25.47 -\endverbatim - * The relative frequency of the results with \e bits = 1 and \e n = 2 can - * be is shown by the histogram\n - * <img src="powerhist.png" width=580 height=750 - * alt="exact binary sampling of power distribution">\n - * The base of each rectangle gives the range represented by the - * corresponding binary number and the area is proportional to its - * frequency. A PDF version of this figure - * <a href="powerhist.pdf">here</a>. This allows the figure to be - * magnified to show the rectangles for all binary numbers up to 9 bits. - * - * @tparam Random the type of the random generator. - * @param[in,out] r a random generator. - * @param[in] n the power. - * @return the random sample. - **********************************************************************/ - template<class Random> - RandomNumber<bits> operator()(Random& r, unsigned n) const; - private: - mutable RandomNumber<bits> _x; - mutable RandomNumber<bits> _y; - }; - - template<int bits> template<class Random> RandomNumber<bits> - ExactPower<bits>::operator()(Random& r, unsigned n) const { - // Return max(u_0, u_1, u_2, ..., u_n). Equivalent to taking the - // (n+1)th root of u_0. - _x.Init(); - for (; n--;) { - _y.Init(); - // For bits = 1, we can save 1 bit on the first iteration by using a - // technique suggested by Knuth and Yao (1976). When comparing the - // digits of x and y, use 1 bit to determine if the digits are the same. - // If they are, then use another bit for the value of the digit. If they - // are not, then the next bit of the maximum must be 1 (avoiding using a - // second bit). Applying this optimization to subsequent iterations - // (when x already is filled with some bits) gets trickier. - if (_x.LessThan(r, _y)) - _x.swap(_y); // x = y; - } - return _x; - } - -} // namespace RandomLib - -#endif // RANDOMLIB_EXACTPOWER_HPP diff --git a/app/RandomLib/ExponentialDistribution.hpp b/app/RandomLib/ExponentialDistribution.hpp deleted file mode 100644 index d91aaef1c32bbacfd249fe6e14d316ca3fc94f2b..0000000000000000000000000000000000000000 --- a/app/RandomLib/ExponentialDistribution.hpp +++ /dev/null @@ -1,70 +0,0 @@ -/** - * \file ExponentialDistribution.hpp - * \brief Header for ExponentialDistribution - * - * Sample from an exponential distribution. - * - * Copyright (c) Charles Karney (2006-2011) <charles@karney.com> and licensed - * under the MIT/X11 License. For more information, see - * http://randomlib.sourceforge.net/ - **********************************************************************/ - -#if !defined(RANDOMLIB_EXPONENTIALDISTRIBUTION_HPP) -#define RANDOMLIB_EXPONENTIALDISTRIBUTION_HPP \ - "$Id: 67685642890facf15ee34325264cb64ef6fdd114 $" - -#include <cmath> - -namespace RandomLib { - /** - * \brief The exponential distribution. - * - * Sample from the distribution exp(-\e x) for \e x >= 0. This uses the - * logarithm method, see Knuth, TAOCP, Vol 2, Sec 3.4.1.D. Example - * \code - * #include <RandomLib/ExponentialDistribution.hpp> - * - * RandomLib::Random r; - * std::cout << "Seed set to " << r.SeedString() << "\n"; - * RandomLib::ExponentialDistribution<double> expdist; - * std::cout << "Select from exponential distribution:"; - * for (size_t i = 0; i < 10; ++i) - * std::cout << " " << expdist(r); - * std::cout << "\n"; - * \endcode - * - * @tparam RealType the real type of the results (default double). - **********************************************************************/ - template<typename RealType = double> class ExponentialDistribution { - public: - /** - * The type returned by ExponentialDistribution::operator()(Random&) - **********************************************************************/ - typedef RealType result_type; - /** - * Return a sample of type RealType from the exponential distribution and - * mean \e mu. This uses Random::FloatU() which avoids taking log(0) and - * allows rare large values to be returned. If \e mu = 1, minimum returned - * value = 0 with prob 1/2<sup><i>p</i></sup>; maximum returned value = - * log(2)(\e p + \e e) with prob 1/2<sup><i>p</i> + <i>e</i></sup>. Here - * \e p is the precision of real type RealType and \e e is the exponent - * range. - * - * @tparam Random the type of RandomCanonical generator. - * @param[in,out] r the RandomCanonical generator. - * @param[in] mu the mean value of the exponential distribution (default 1). - * @return the random sample. - **********************************************************************/ - template<class Random> - RealType operator()(Random& r, RealType mu = RealType(1)) const throw(); - }; - - template<typename RealType> template<class Random> inline RealType - ExponentialDistribution<RealType>::operator()(Random& r, RealType mu) const - throw() { - return -mu * std::log(r.template FloatU<RealType>()); - } - -} // namespace RandomLib - -#endif // RANDOMLIB_EXPONENTIALDISTRIBUTION_HPP diff --git a/app/RandomLib/ExponentialProb.hpp b/app/RandomLib/ExponentialProb.hpp deleted file mode 100644 index 4c8d25a6dcca57d63f4ac99e19f3741b64e31fb4..0000000000000000000000000000000000000000 --- a/app/RandomLib/ExponentialProb.hpp +++ /dev/null @@ -1,156 +0,0 @@ -/** - * \file ExponentialProb.hpp - * \brief Header for ExponentialProb - * - * Return true with probabililty exp(-\e p). - * - * Copyright (c) Charles Karney (2006-2012) <charles@karney.com> and licensed - * under the MIT/X11 License. For more information, see - * http://randomlib.sourceforge.net/ - **********************************************************************/ - -#if !defined(RANDOMLIB_EXPONENTIALPROB_HPP) -#define RANDOMLIB_EXPONENTIALPROB_HPP \ - "$Id: 094003166859dea78502e9f51653b4070a36f237 $" - -#include <vector> -#include <limits> - -namespace RandomLib { - /** - * \brief The exponential probability. - * - * Return true with probability exp(-\e p). Basic method taken from:\n - * J. von Neumann,\n Various Techniques used in Connection with Random - * Digits,\n J. Res. Nat. Bur. Stand., Appl. Math. Ser. 12, 36-38 (1951),\n - * reprinted in Collected Works, Vol. 5, 768-770 (Pergammon, 1963).\n See - * also the references given for the ExactExponential class. - * - * Here the method is extended to be exact by generating sufficient bits in - * the random numbers in the algorithm to allow the unambiguous comparisons - * to be made. - * - * Here's one way of sampling from a normal distribution with zero mean and - * unit variance in the interval [-1,1] with reasonable accuracy: - * \code - * #include <RandomLib/Random.hpp> - * #include <RandomLib/ExponentialProb.hpp> - * - * double Normal(RandomLib::Random& r) { - * double x; - * RandomLib::ExponentialProb e; - * do - * x = r.FloatW(); - * while ( !e(r, - 0.5 * x * x) ); - * return x; - * } - * \endcode - * (Note that the ExactNormal class samples from the normal distribution - * exactly.) - * - * This class uses a mutable private vector. So a single ExponentialProb - * object cannot safely be used by multiple threads. In a multi-processing - * environment, each thread should use a thread-specific ExponentialProb - * object. - **********************************************************************/ - class ExponentialProb { - private: - typedef unsigned word; - public: - - ExponentialProb() : _v(std::vector<word>(alloc_incr)) {} - /** - * Return true with probability exp(-\e p). Returns false if \e p <= 0. - * For in \e p (0,1], it requires about exp(\e p) random deviates. For \e - * p large, it requires about exp(1)/(1 - exp(-1)) random deviates. - * - * @tparam RealType the real type of the argument. - * @tparam Random the type of the random generator. - * @param[in,out] r a random generator. - * @param[in] p the probability. - * @return true with probability \e p. - **********************************************************************/ - template<typename RealType, class Random> - bool operator()(Random& r, RealType p) const; - - private: - /** - * Return true with probability exp(-\e p) for \e p in [0,1]. - **********************************************************************/ - template<typename RealType, class Random> - bool ExpFraction(Random& r, RealType p) const; - /** - * Holds as much of intermediate uniform deviates as needed. - **********************************************************************/ - mutable std::vector<word> _v; - /** - * Increment on size of _v. - **********************************************************************/ - static const unsigned alloc_incr = 16; - }; - - template<typename RealType, class Random> - bool ExponentialProb::operator()(Random& r, RealType p) const { - STATIC_ASSERT(!std::numeric_limits<RealType>::is_integer, - "ExponentialProb(): invalid real type RealType"); - return p <= 0 || // True if p <=0 - // Ensure p - 1 < p. Also deal with IsNaN(p) - ( p < RealType(1)/std::numeric_limits<RealType>::epsilon() && - // exp(a+b) = exp(a) * exp(b) - ExpFraction(r, p < RealType(1) ? p : RealType(1)) && - ( p <= RealType(1) || operator()(r, p - RealType(1)) ) ); - } - - template<typename RealType, class Random> - bool ExponentialProb::ExpFraction(Random& r, RealType p) const { - // Base of _v is 2^c. Adjust so that word(p) doesn't lose precision. - static const int c = // The Intel compiler needs this to be static?? - std::numeric_limits<word>::digits < - std::numeric_limits<RealType>::digits ? - std::numeric_limits<word>::digits : - std::numeric_limits<RealType>::digits; - // m gives number of valid words in _v - unsigned m = 0, l = unsigned(_v.size()); - if (p < RealType(1)) - while (true) { - if (p <= RealType(0)) - return true; - // p in (0, 1) - if (l == m) - _v.resize(l += alloc_incr); - _v[m++] = r.template Integer<word, c>(); - p *= std::pow(RealType(2), c); // p in (0, 2^c) - word w = word(p); // w in [0, 2^c) - if (_v[m - 1] > w) - return true; - else if (_v[m - 1] < w) - break; - else // _v[m - 1] == w - p -= RealType(w); // p in [0, 1) - } - // Here _v < p. Now loop finding decreasing V. Exit when first increasing - // one is found. - for (unsigned s = 0; ; s ^= 1) { // Parity of loop count - for (unsigned j = 0; ; ++j) { - if (j == m) { - // Need more bits in the old V - if (l == m) - _v.resize(l += alloc_incr); - _v[m++] = r.template Integer<word, c>(); - } - word w = r.template Integer<word, c>(); - if (w > _v[j]) - return s != 0u; // New V is bigger, so exit - else if (w < _v[j]) { - _v[j] = w; // New V is smaller, update _v - m = j + 1; // adjusting its size - break; // and generate the next V - } - // Else w == _v[j] and we need to check the next c bits - } - } - } - -} // namespace RandomLib - -#endif // RANDOMLIB_EXPONENTIALPROB_HPP diff --git a/app/RandomLib/InverseEProb.hpp b/app/RandomLib/InverseEProb.hpp deleted file mode 100644 index b5590b9174515256c3075e4076e16510b7c3e85e..0000000000000000000000000000000000000000 --- a/app/RandomLib/InverseEProb.hpp +++ /dev/null @@ -1,68 +0,0 @@ -/** - * \file InverseEProb.hpp - * \brief Header for InverseEProb - * - * Return true with probabililty 1/\e e. - * - * Copyright (c) Charles Karney (2012) <charles@karney.com> and licensed under - * the MIT/X11 License. For more information, see - * http://randomlib.sourceforge.net/ - **********************************************************************/ - -#if !defined(RANDOMLIB_INVERSEEPROB_HPP) -#define RANDOMLIB_INVERSEEPROB_HPP \ - "$Id: f46f0c00ad4ac76dc2a4c276468debab0bc76a84 $" - -#include <vector> -#include <RandomLib/Random.hpp> - -namespace RandomLib { - - /** - * \brief Return true with probability 1/\e e. - * - * InverseEProb p; p(Random& r) returns true with prob 1/e using von - * Neumann's rejection method. It consumes 4.572 bits per call on average. - * - * This class illustrates how to return an exact result using coin tosses - * only. A more efficient way of returning an exact result would be to use - * ExponentialProb p; p(r, 1.0f); - **********************************************************************/ - class InverseEProb { - private: - mutable std::vector<bool> _p; - template<class Random> bool exph(Random& r) { - // Return true with prob 1/sqrt(e). - if (r.Boolean()) return true; - _p.clear(); // vector of bits in p - _p.push_back(false); - for (bool s = false; ; s = !s) { // s is a parity - for (size_t i = 0; ; ++i) { // Compare bits of p and q - if (i == _p.size()) - _p.push_back(r.Boolean()); // Generate next bit of p if necessary - if (r.Boolean()) { // Half the time the bits differ - if (_p[i]) { // p's bit is 1, so q is smaller, update p - _p[i] = false; // Last bit of q 0 - if (++i < _p.size()) _p.resize(i); // p = q - break; - } else - return s; // p's bit is 0, so q is bigger, return parity - } // The other half of the time the bits match, so go to next bit - } - } - } - public: - /** - * Return true with probability 1/\e e. - * - * @tparam Random the type of the random generator. - * @param[in,out] r a random generator. - * @return true with probability 1/\e e. - **********************************************************************/ - template<class Random> bool operator()(Random& r) - { return exph(r) && exph(r); } - }; - -} // namespace RandomLib - -#endif // RANDOMLIB_INVERSEEPROB_HPP diff --git a/app/RandomLib/InversePiProb.hpp b/app/RandomLib/InversePiProb.hpp deleted file mode 100644 index 06ba71b33dfdf117bd45f547378fb09769cbfda6..0000000000000000000000000000000000000000 --- a/app/RandomLib/InversePiProb.hpp +++ /dev/null @@ -1,125 +0,0 @@ -/** - * \file InversePiProb.hpp - * \brief Header for InversePiProb - * - * Return true with probabililty 1/\e pi. - * - * Copyright (c) Charles Karney (2012) <charles@karney.com> and licensed - * under the MIT/X11 License. For more information, see - * http://randomlib.sourceforge.net/ - **********************************************************************/ - -#if !defined(RANDOMLIB_INVERSEPIPROB_HPP) -#define RANDOMLIB_INVERSEPIPROB_HPP \ - "$Id: 5394753ce030151afe8f8524f0ca5a80d560e98d $" - -#include <cstdlib> // for abs(int) -#include <RandomLib/Random.hpp> - -namespace RandomLib { - - /** - * \brief Return true with probability 1/\e pi. - * - * InverseEProb p; p(Random& r) returns true with prob 1/\e pi using the - * method of Flajolet et al. It consumes 9.6365 bits per call on average. - * - * The method is given in<br> - - * - P. Flajolet, M. Pelletier, and M. Soria,<br> - * On Buffon Machines and Numbers,<br> Proc. 22nd ACM-SIAM Symposium on - * Discrete Algorithms (SODA), Jan. 2011.<br> - * http://www.siam.org/proceedings/soda/2011/SODA11_015_flajoletp.pdf <br> - * . - * using the identity \verbatim - 1/pi = sum( binomial(2n,n)^3 (6n+1)/(2^(8n+2)), n = 0..infty) -\endverbatim - * - * It is based on an expression for 1/pi given by Eq. (28) of<br> - * - S. Ramanujan,<br> - * Modular Equations and Approximations to pi,<br> - * Quart. J. Math. 45, 350-372 (1914);<br> - * In Collected Papers, edited by G. H. Hardy, P. V. Sechu Aiyar, - * B. M. Wilson (Cambridge Univ. Press, 1927; preprinted AMS, 2000).<br> - * http://books.google.com/books?id=oSioAM4wORMC&pg=PA36 <br> - * . - * \verbatim - 4/pi = 1 + 7/4 *(1 /(2) )^3 - + 13/4^2*(1*3 /(2*4) )^3 + - + 19/4^3*(1*3*5/(2*4*6))^3 + ... -\endverbatim - * Flajolet et al. write this as \verbatim - 1/pi = sum( binomial(2*n,n)^3 * (6*n+1)/(2^(8*n+2)), n = 0..infty) -\endverbatim - * (however, their paper misprints the final exponent of 2 as 8*n+4). - * - * Proof of the algorithm: \verbatim - 1/pi = sum( (binomial(2*n,n)/2^(2*n))^3 * (6*n+1)/2^(2*n+2), n, 0..infty) -\endverbatim - * But \verbatim - sum( (6*n+1)/2^(2*n+2), n, 0..infty) = 1 -\endverbatim - * so algorithm becomes: - * -# pick n >= 0 with prob (6*n+1)/2^(2*n+2) (mean n = 11/9); - * -# return true with prob (binomial(2*n,n)/2^(2*n))^3. - * - * Implement (1) as - * - geom4(r) + geom4(r) returns n with prob 9*(n+1)/2^(2*n+4); - * - geom4(r) + geom4(r) + 1 returns n with prob 36*n/2^(2*n+4); - * - Combine these with probs [4/9, 5/9] to yield (6*n+1)/2^(2*n+2), as - * required. - * . - * Implement (2) as the outcome of 3 coin tossing experiments of 2*n tosses - * with success defined as equal numbers heads and tails. - * - * This class illustrates how to return an exact result using coin tosses - * only. A more efficient implementation (which is still exact) would - * replace prob59 by r.Prob(5,9) and geom4 by LeadingZeros z; z(r)/2. - **********************************************************************/ - class InversePiProb { - private: - template<class Random> bool prob59(Random& r) { - // true with prob 5/9 = 0.1 000 111 000 111 000 111 ... (binary expansion) - if (r.Boolean()) return true; - for (bool res = false; ; res = !res) - for (int i = 3; i--; ) if (r.Boolean()) return res; - } - - template<class Random> int geom4(Random& r) { // Geom(1/4) - int sum = 0; - while (r.Boolean() && r.Boolean()) ++sum; - return sum; - } - - template<class Random> bool binom(Random& r, int n) { - // Probability of equal heads and tails on 2*n tosses - // = binomial(2*n, n) / 2^(2*n) - int d = 0; - for (int k = n; k--; ) d += r.Boolean() ? 1 : -1; - for (int k = n; k--; ) { - d += r.Boolean() ? 1 : -1; - // This optimization saves 0.1686 bit per call to operator() on average. - if (std::abs(d) > k) return false; - } - return true; - } - - public: - /** - * Return true with probability 1/\e pi. - * - * @tparam Random the type of the random generator. - * @param[in,out] r a random generator. - * @return true with probability 1/\e pi. - **********************************************************************/ - template<class Random> bool operator()(Random& r) { - // Return true with prob 1/pi. - int n = geom4(r) + geom4(r) + (prob59(r) ? 1 : 0); - for (int j = 3; j--; ) if (!binom(r, n)) return false; - return true; - } - }; - -} // namespace RandomLib - -#endif // RANDOMLIB_INVERSEPIPROB_HPP diff --git a/app/RandomLib/LeadingZeros.hpp b/app/RandomLib/LeadingZeros.hpp deleted file mode 100644 index 052f9821456d90e30577b123e37e0844a92449a5..0000000000000000000000000000000000000000 --- a/app/RandomLib/LeadingZeros.hpp +++ /dev/null @@ -1,85 +0,0 @@ -/** - * \file LeadingZeros.hpp - * \brief Header for LeadingZeros - * - * Count the leading zeros in a real number. - * - * Copyright (c) Charles Karney (2006-2011) <charles@karney.com> and licensed - * under the MIT/X11 License. For more information, see - * http://randomlib.sourceforge.net/ - **********************************************************************/ - -#if !defined(RANDOMLIB_LEADINGZEROS_HPP) -#define RANDOMLIB_LEADINGZEROS_HPP \ - "$Id: b81d02bd2b7bf0959a2d8fdaab9d03073e4298cb $" - -namespace RandomLib { - /** - * \brief Count of leading zeros. - * - * Count of leading zero bits after the binary point in a real number - * uniformly distributed in (0,1). (This is equivalent to the geometric - * distribution with probability 1/2.) For example - * \code - * #include <RandomLib/LeadingZeros.hpp> - * - * RandomLib::Random r; // A RandomGenerator works here too - * std::cout << "Seed set to " << r.SeedString() << "\n"; - * LeadingZeros zeros; - * std::cout << "Count of leading zeros:"; - * for (size_t i = 0; i < 20; ++i) - * std::cout << " " << zeros(r); - * std::cout << "\n"; - * \endcode - **********************************************************************/ - class LeadingZeros { - public: - /** - * Return the number of zero bits after the binary point in a real number - * uniformly distributed in (0,1). Thus \e k is returned with probability - * 1/2<sup><i>k</i>+1</sup>. Because MT19937 is \e not a perfect random - * number generator, this always returns a result in [0, 19937). - * - * @tparam Random the type of the random generator. - * @param[in,out] r a random generator. - * @return the random sample. - **********************************************************************/ - template<class Random> unsigned operator()(Random& r) const throw(); - }; - - template<class Random> - unsigned LeadingZeros::operator()(Random& r) const throw() { - // It's simpler to count the number of trailing ones in each w-bit block - // stopping when we get to a zero bit. - // - // Process a word in chunks of size m. The algorithm here can deal with - // any m assuming that z is modified accordingly. m = 4 is an approximate - // optimum. - // - // Can also adapt this routine to use RandomNumber::highest_bit_idx - // instead. However the result is considerably slower. - const int m = 4; - STATIC_ASSERT(m <= Random::width, "LeadingZeros: m too large"); - // mask with m low bits set - const typename Random::result_type mask = ~(Random::max << m); - // Number of trailing 1 bits in [0, 1<<m). However, correct results are - // also obtained with any permutation of this array. This particular - // permutation is useful since the initial 1/2, 1/4, etc. can be used for - // m-1, m-2, etc. To generate the array for the next higher m, append a - // duplicate of the array and increment the last entry by one. - const unsigned z[1 << m] = - { 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4, }; - typename Random::result_type x = r(); - for (unsigned b = m, n = 0; b < Random::width; b += m) { - n += z[x & mask]; // count trailing 1s in chunk - if (n < b) // chunk contains a 0 - return n; - x >>= m; // shift out the chunk we've processed - } - // x is all ones (prob 1/2^w); process the next word. - return Random::width + operator()(r); - } - -} // namespace RandomLib - -#endif // RANDOMLIB_LEADINGZEROS_HPP diff --git a/app/RandomLib/MPFRExponential.hpp b/app/RandomLib/MPFRExponential.hpp deleted file mode 100644 index 035bd0a60341d1cd550fdc8df77cf5f8419c5359..0000000000000000000000000000000000000000 --- a/app/RandomLib/MPFRExponential.hpp +++ /dev/null @@ -1,90 +0,0 @@ -/** - * \file MPFRExponential.hpp - * \brief Header for MPFRExponential - * - * Sampling exactly from the normal distribution for MPFR. - * - * Copyright (c) Charles Karney (2012) <charles@karney.com> and licensed under - * the MIT/X11 License. For more information, see - * http://randomlib.sourceforge.net/ - **********************************************************************/ - -#if !defined(RANDOMLIB_MPFREXPONENTIAL_HPP) -#define RANDOMLIB_MPFREXPONENTIAL_HPP \ - "$Id: cdb75307df601b5beba371dea0714a151c765a35 $" - -#include <RandomLib/MPFRRandom.hpp> - -namespace RandomLib { - - /** - * \brief The exponential distribution for MPFR. - * - * This is a transcription of ExactExponential (version 1.4) for use with - * MPFR. - * - * This class uses mutable private objects. So a single MPFRExponential - * object cannot safely be used by multiple threads. In a multi-processing - * environment, each thread should use a thread-specific MPFRExponential - * object. - * - * @tparam bits the number of bits in each digit. - **********************************************************************/ - template<int bits = 32> class MPFRExponential { - public: - - /** - * Initialize the MPFRExponential object. - **********************************************************************/ - MPFRExponential() {}; - /** - * Sample from the exponential distribution with mean 1 returning a - * MPFRRandom. - * - * @param[out] t the MPFRRandom result. - * @param[in,out] r a GMP random generator. - **********************************************************************/ - void operator()(MPFRRandom<bits>& t, gmp_randstate_t r) const - { Compute(r); _x.swap(t); } - /** - * Sample from the exponential distribution with mean 1. - * - * @param[out] val the sample from the exponential distribution - * @param[in,out] r a GMP random generator. - * @param[in] round the rounding direction. - * @return the MPFR ternary result (+1/-1 if val is larger/smaller than the - * exact sample). - **********************************************************************/ - int operator()(mpfr_t val, gmp_randstate_t r, mpfr_rnd_t round) const - { Compute(r); return _x(val, r, round); } - private: - // Disable copy constructor and assignment operator - MPFRExponential(const MPFRExponential&); - MPFRExponential& operator=(const MPFRExponential&); - int ExpFraction(gmp_randstate_t r, MPFRRandom<bits>& p) const { - // The early bale out - if (p.TestHighBit(r)) return 0; - // Implement the von Neumann algorithm - _w.Init(); - if (!_w.LessThan(r, p)) return 1; - while (true) { - _v.Init(); if (!_v.LessThan(r, _w)) return 0; - _w.Init(); if (!_w.LessThan(r, _v)) return 1; - } - } - void Compute(gmp_randstate_t r) const { - _x.Init(); - unsigned k = 0; - while (!ExpFraction(r, _x)) { ++k; _x.Init(); } - if (k & 1) _x.SetHighBit(r); - _x.AddInteger(k >> 1); - return; - } - mutable MPFRRandom<bits> _x; - mutable MPFRRandom<bits> _v; - mutable MPFRRandom<bits> _w; - }; - -} // namespace RandomLib - -#endif // RANDOMLIB_MPFREXPONENTIAL_HPP diff --git a/app/RandomLib/MPFRExponentialL.hpp b/app/RandomLib/MPFRExponentialL.hpp deleted file mode 100644 index 02fd736eceaee26a33f13b53de256c77e816578e..0000000000000000000000000000000000000000 --- a/app/RandomLib/MPFRExponentialL.hpp +++ /dev/null @@ -1,119 +0,0 @@ -/** - * \file MPFRExponentialL.hpp - * \brief Header for MPFRExponentialL - * - * Sampling exactly from the exponential distribution for MPFR using the - * traditional method. - * - * Copyright (c) Charles Karney (2012) <charles@karney.com> and licensed under - * the MIT/X11 License. For more information, see - * http://randomlib.sourceforge.net/ - **********************************************************************/ - -#if !defined(RANDOMLIB_MPFREXPONENTIALL_HPP) -#define RANDOMLIB_MPFREXPONENTIALL_HPP \ - "$Id: a6ca899faa2b27b3f6b69b61fd9874e3fc428fd7 $" - -#include <cmath> // for log -#include <mpfr.h> - -namespace RandomLib { - - /** - * \brief The exponential distribution for MPFR (the log method). - * - * This class is <b>DEPRECATED</b>. It is included for illustrative purposes - * only. The MPFRExponential class provides a much more efficient method for - * sampling from the exponential distribution. - * - * This is an adaption of ExponentialDistribution to MPFR. The changes are - * - Use MPFR's random number generator - * - Use sufficient precision internally to ensure that a correctly rounded - * result is returned. - * - * This class uses mutable private objects. So a single MPFRExponentialL - * object cannot safely be used by multiple threads. In a multi-processing - * environment, each thread should use a thread-specific MPFRExponentialL - * object. - **********************************************************************/ - class MPFRExponentialL { - private: - // The number of bits of randomness to add at a time. - static const long chunk_ = 32; - - public: - /** - * Initialize the MPFRExponentialL object. - **********************************************************************/ - MPFRExponentialL() { - mpz_init(_vi); - mpfr_init2(_eps, chunk_); - mpfr_init2(_v1, chunk_); - mpfr_init2(_v2, chunk_); - } - /** - * Destroy the MPFRExponentialL object. - **********************************************************************/ - ~MPFRExponentialL() { - mpfr_clear(_v2); - mpfr_clear(_v1); - mpfr_clear(_eps); - mpz_clear(_vi); - } - /** - * Sample from the exponential distribution with mean 1. - * - * @param[out] val the sample from the exponential distribution - * @param[in,out] r a GMP random generator. - * @param[in] round the rounding direction. - * @return the MPFR ternary result (+1/-1 if val is larger/smaller than the - * exact sample). - **********************************************************************/ - int operator()(mpfr_t val, gmp_randstate_t r, mpfr_rnd_t round) const { - - mpfr_prec_t prec0 = mpfr_get_prec (val); - mpfr_prec_t prec = prec0 + 10; // A rough optimum - mpz_urandomb(_vi, r, prec); - mpfr_set_ui_2exp(_eps, 1u, -prec, MPFR_RNDN); - mpfr_set_prec(_v1, prec); - mpfr_set_z_2exp(_v1, _vi, -prec, MPFR_RNDN); - mpfr_set_prec(_v2, prec); - mpfr_add(_v2, _v1, _eps, MPFR_RNDN); - while (true) { - int f2 = mpfr_log(val, _v2, round); // val = log(upper bound) - mpfr_set_prec(_v2, prec0); - int f1 = mpfr_log(_v2, _v1, round); // v2 = log(lower bound) - if (f1 == f2 && mpfr_equal_p(val, _v2)) { - mpfr_neg(val, val, MPFR_RNDN); - return -f1; - } - prec = Refine(r, prec); - } - } - private: - // disable copy constructor and assignment operator - MPFRExponentialL(const MPFRExponentialL&); - MPFRExponentialL& operator=(const MPFRExponentialL&); - // Refine the random interval - mpfr_prec_t Refine(gmp_randstate_t r, mpfr_prec_t prec) - const { - prec += chunk_; - mpfr_div_2ui(_eps, _eps, chunk_, MPFR_RNDN); - mpz_urandomb(_vi, r, chunk_); - mpfr_set_prec(_v2, prec); - mpfr_set_z_2exp(_v2, _vi, -prec, MPFR_RNDN); - mpfr_add(_v2, _v1, _v2, MPFR_RNDN); - mpfr_swap(_v1, _v2); // v1 = v2; - mpfr_set_prec(_v2, prec); - mpfr_add(_v2, _v1, _eps, MPFR_RNDN); - return prec; - } - mutable mpz_t _vi; - mutable mpfr_t _eps; - mutable mpfr_t _v1; - mutable mpfr_t _v2; - }; - -} // namespace RandomLib - -#endif // RANDOMLIB_MPFREXPONENTIALL_HPP diff --git a/app/RandomLib/MPFRNormal.hpp b/app/RandomLib/MPFRNormal.hpp deleted file mode 100644 index beaefba2279a867b5a4537add5eddfc5cdc82b14..0000000000000000000000000000000000000000 --- a/app/RandomLib/MPFRNormal.hpp +++ /dev/null @@ -1,142 +0,0 @@ -/** - * \file MPFRNormal.hpp - * \brief Header for MPFRNormal - * - * Sampling exactly from the normal distribution for MPFR. - * - * Copyright (c) Charles Karney (2012) <charles@karney.com> and licensed under - * the MIT/X11 License. For more information, see - * http://randomlib.sourceforge.net/ - **********************************************************************/ - -#if !defined(RANDOMLIB_MPFRNORMAL_HPP) -#define RANDOMLIB_MPFRNORMAL_HPP \ - "$Id: 058b4357936d14651b87f0876d3973f49be2a779 $" - -#include <algorithm> // for max/min -#include <RandomLib/MPFRRandom.hpp> - -namespace RandomLib { - - /** - * \brief The normal distribution for MPFR. - * - * This is a transcription of ExactNormal (version 1.3) for use with MPFR. - * - * This class uses mutable private objects. So a single MPFRNormal object - * cannot safely be used by multiple threads. In a multi-processing - * environment, each thread should use a thread-specific MPFRNormal object. - * - * @tparam bits the number of bits in each digit. - **********************************************************************/ - template<int bits = 32> class MPFRNormal { - public: - - /** - * Initialize the MPFRNormal object. - **********************************************************************/ - MPFRNormal() { mpz_init(_tt); } - /** - * Destroy the MPFRNormal object. - **********************************************************************/ - ~MPFRNormal() { mpz_clear(_tt); } - /** - * Sample from the normal distribution with mean 0 and variance 1 returning - * a MPFRRandom. - * - * @param[out] t the MPFRRandom result. - * @param[in,out] r a GMP random generator. - **********************************************************************/ - void operator()(MPFRRandom<bits>& t,gmp_randstate_t r) const - { Compute(r); return _x.swap(t); } - /** - * Sample from the normal distribution with mean 0 and variance 1. - * - * @param[out] val the sample from the normal distribution - * @param[in,out] r a GMP random generator. - * @param[in] round the rounding direction. - * @return the MPFR ternary result (+1/-1 if val is larger/smaller than the - * exact sample). - **********************************************************************/ - int operator()(mpfr_t val, gmp_randstate_t r, mpfr_rnd_t round) const - { Compute(r); return _x(val, r, round); } - private: - // Disable copy constructor and assignment operator - MPFRNormal(const MPFRNormal&); - MPFRNormal& operator=(const MPFRNormal&); - // True with prob exp(-1/2) - int ExpProbH(gmp_randstate_t r) const { - _p.Init(); if (_p.TestHighBit(r)) return 1; - // von Neumann rejection - while (true) { - _q.Init(); if (!_q.LessThan(r, _p)) return 0; - _p.Init(); if (!_p.LessThan(r, _q)) return 1; - } - } - // True with prob exp(-n/2) - int ExpProb(gmp_randstate_t r, unsigned n) const { - while (n--) { if (!ExpProbH(r)) return 0; } - return 1; - } - // n with prob (1-exp(-1/2)) * exp(-n/2) - unsigned ExpProbN(gmp_randstate_t r) const { - unsigned n = 0; - while (ExpProbH(r)) ++n; - return n; - } - // Return: - // 1 with prob 2k/(2k + 2) - // 0 with prob 1/(2k + 2) - // -1 with prob 1/(2k + 2) - int Choose(gmp_randstate_t r, int k) const { - const int b = 15; // To avoid integer overflow on multiplication - const int m = 2 * k + 2; - int n1 = m - 2, n2 = m - 1; - while (true) { - mpz_urandomb(_tt, r, b); - int d = int( mpz_get_ui(_tt) ) * m; - n1 = std::max((n1 << b) - d, 0); - if (n1 >= m) return 1; - n2 = std::min((n2 << b) - d, m); - if (n2 <= 0) return -1; - if (n1 == 0 && n2 == m) return 0; - } - } - void Compute(gmp_randstate_t r) const { - while (true) { - unsigned k = ExpProbN(r); // the integer part of the result. - if (ExpProb(r, (k - 1) * k)) { - _x.Init(); - unsigned s = 1; - for (unsigned j = 0; j <= k; ++j) { // execute k + 1 times - bool first; - for (s = 1, first = true; ; s ^= 1, first = false) { - if (k == 0 && _x.Boolean(r)) break; - _q.Init(); if (!_q.LessThan(r, first ? _x : _p)) break; - int y = k == 0 ? 0 : Choose(r, k); - if (y < 0) - break; - else if (y == 0) { - _p.Init(); if (!_p.LessThan(r, _x)) break; - } - _p.swap(_q); // a fast way of doing p = q - } - if (s == 0) break; - } - if (s != 0) { - _x.AddInteger(k); - if (_x.Boolean(r)) _x.Negate(); - return; - } - } - } - } - mutable mpz_t _tt; // A temporary - mutable MPFRRandom<bits> _x; - mutable MPFRRandom<bits> _p; - mutable MPFRRandom<bits> _q; - }; - -} // namespace RandomLib - -#endif // RANDOMLIB_MPFRNORMAL_HPP diff --git a/app/RandomLib/MPFRNormalK.hpp b/app/RandomLib/MPFRNormalK.hpp deleted file mode 100644 index 514972ae2cc9f0051b85688195c46df050ecc184..0000000000000000000000000000000000000000 --- a/app/RandomLib/MPFRNormalK.hpp +++ /dev/null @@ -1,136 +0,0 @@ -/** - * \file MPFRNormalK.hpp - * \brief Header for MPFRNormalK - * - * Sampling exactly from the normal distribution for MPFR. - * - * Copyright (c) Charles Karney (2012) <charles@karney.com> and licensed under - * the MIT/X11 License. For more information, see - * http://randomlib.sourceforge.net/ - **********************************************************************/ - -#if !defined(RANDOMLIB_MPFRNORMALK_HPP) -#define RANDOMLIB_MPFRNORMALK_HPP \ - "$Id: a512196382fe6e7a2765ae0b88ff414df2940619 $" - -#include <algorithm> // for max -#include <RandomLib/MPFRRandom.hpp> -#include <RandomLib/MPFRExponential.hpp> - -namespace RandomLib { - - /** - * \brief The normal distribution for MPFR (Kahn algorithm). - * - * This class is <b>DEPRECATED</b>. It is included for illustrative purposes - * only. The MPFRNormal class provides a somewhat more efficient method for - * sampling from the normal distribution. - * - * Refs: - * - H. Kahn, Rand Report RM-1237-AEC, p. 41 (1954). - * - M. Abramowitz and I. A. Stegun, p. 953, Sec. 26.8.6.a(4) (1964). - * . - * N.B. Damien Stehle' drew my attention to this algorithm as a useful way to - * compute normal deviates exactly. - * - * This class uses mutable private objects. So a single MPFRNormalK object - * cannot safely be used by multiple threads. In a multi-processing - * environment, each thread should use a thread-specific MPFRNormalK object. - * - * @tparam bits the number of bits in each digit. - **********************************************************************/ - template<int bits = 32> class MPFRNormalK { - public: - - /** - * Initialize the MPFRNormalK object. - **********************************************************************/ - MPFRNormalK() - { mpfr_init2(_xf, MPFR_PREC_MIN); mpfr_init2(_zf, MPFR_PREC_MIN); } - /** - * Destroy the MPFRNormalK object. - **********************************************************************/ - ~MPFRNormalK() - { mpfr_clear(_zf); mpfr_clear(_xf); } - /** - * Sample from the normal distribution with mean 0 and variance 1 returning - * a MPFRRandom. - * - * @param[out] t the MPFRRandom result. - * @param[in,out] r a GMP random generator. - **********************************************************************/ - void operator()(MPFRRandom<bits>& t, gmp_randstate_t r) const - { Compute(r); _x.swap(t); } - /** - * Sample from the normal distribution with mean 0 and variance 1. - * - * @param[out] val the sample from the normal distribution - * @param[in,out] r a GMP random generator. - * @param[in] round the rounding direction. - * @return the MPFR ternary result (+1/-1 if val is larger/smaller than the - * exact sample). - **********************************************************************/ - int operator()(mpfr_t val, gmp_randstate_t r, mpfr_rnd_t round) const - { Compute(r); return _x(val, r, round); } - private: - // disable copy constructor and assignment operator - MPFRNormalK(const MPFRNormalK&); - MPFRNormalK& operator=(const MPFRNormalK&); - void Compute(gmp_randstate_t r) const { - // The algorithm is sample x and z from the exponential distribution; if - // (x-1)^2 < 2*z, return (random sign)*x; otherwise repeat. Probability - // of acceptance is sqrt(pi/2) * exp(-1/2) = 0.7602. - while (true) { - _edist(_x, r); - _edist(_z, r); - for (mp_size_t k = 1; ; ++k) { - _x.ExpandTo(r, k - 1); - _z.ExpandTo(r, k - 1); - mpfr_prec_t prec = std::max(mpfr_prec_t(MPFR_PREC_MIN), k * bits); - mpfr_set_prec(_xf, prec); - mpfr_set_prec(_zf, prec); - // Try for acceptance first; so compute upper limit on (y-1)^2 and - // lower limit on 2*z. - if (_x.UInteger() == 0) { - _x(_xf, MPFR_RNDD); - mpfr_ui_sub(_xf, 1u, _xf, MPFR_RNDU); - } else { - _x(_xf, MPFR_RNDU); - mpfr_sub_ui(_xf, _xf, 1u, MPFR_RNDU); - } - mpfr_sqr(_xf, _xf, MPFR_RNDU); - _z(_zf, MPFR_RNDD); - mpfr_mul_2ui(_zf, _zf, 1u, MPFR_RNDD); - if (mpfr_cmp(_xf, _zf) < 0) { // (y-1)^2 < 2*z, so accept - if (_x.Boolean(r)) _x.Negate(); // include a random sign - return; - } - // Try for rejection; so compute lower limit on (y-1)^2 and upper - // limit on 2*z. - if (_x.UInteger() == 0) { - _x(_xf, MPFR_RNDU); - mpfr_ui_sub(_xf, 1u, _xf, MPFR_RNDD); - } else { - _x(_xf, MPFR_RNDD); - mpfr_sub_ui(_xf, _xf, 1u, MPFR_RNDD); - } - mpfr_sqr(_xf, _xf, MPFR_RNDD); - _z(_zf, MPFR_RNDU); - mpfr_mul_2ui(_zf, _zf, 1u, MPFR_RNDU); - if (mpfr_cmp(_xf, _zf) > 0) // (y-1)^2 > 2*z, so reject - break; - // Otherwise repeat with more precision - } - // Reject and start over with a new y and z - } - } - mutable MPFRRandom<bits> _x; - mutable MPFRRandom<bits> _z; - mutable mpfr_t _xf; - mutable mpfr_t _zf; - const MPFRExponential<bits> _edist; - }; - -} // namespace RandomLib - -#endif // RANDOMLIB_MPFRNORMALK_HPP diff --git a/app/RandomLib/MPFRNormalR.hpp b/app/RandomLib/MPFRNormalR.hpp deleted file mode 100644 index 6d1007783e527212ac865870b0aac2a85dccc0d0..0000000000000000000000000000000000000000 --- a/app/RandomLib/MPFRNormalR.hpp +++ /dev/null @@ -1,251 +0,0 @@ -/** - * \file MPFRNormalR.hpp - * \brief Header for MPFRNormalR - * - * Sampling exactly from the normal distribution for MPFR using the ratio - * method. - * - * Copyright (c) Charles Karney (2012) <charles@karney.com> and licensed under - * the MIT/X11 License. For more information, see - * http://randomlib.sourceforge.net/ - **********************************************************************/ - -#if !defined(RANDOMLIB_MPFRNORMALR_HPP) -#define RANDOMLIB_MPFRNORMALR_HPP \ - "$Id: 6c5c70f2503d4b24c4ae0ebc609b62ba99977ad2 $" - -#include <algorithm> // for max/min -#include <cmath> // for pow -#include <mpfr.h> - -namespace RandomLib { - - /** - * \brief The normal distribution for MPFR (ratio method). - * - * This class is <b>DEPRECATED</b>. It is included for illustrative purposes - * only. The MPFRNormal class provides a much more efficient method for - * sampling from the normal distribution. - * - * This is an adaption of NormalDistribution to MPFR. The changes are - * - Use MPFR's random number generator - * - Use sufficient precision internally to ensure that a correctly rounded - * result is returned. - * - * This class uses a mutable private object. So a single MPFRNormalR - * object cannot safely be used by multiple threads. In a multi-processing - * environment, each thread should use a thread-specific MPFRNormalR - * object. - **********************************************************************/ - class MPFRNormalR { - private: - // The number of bits of randomness to add at a time. Require that Leva's - // bounds "work" at a precision of 2^-chunk and that an unsigned long can - // hold this many bits. - static const long chunk_ = 32; - static const unsigned long m = 3684067834; // ceil(2^chunk*sqrt(2/e)) - - public: - /** - * Initialize the MPFRNormalR object. - **********************************************************************/ - MPFRNormalR() { - mpz_init(_ui); - mpz_init(_vi); - mpfr_init2(_eps, chunk_); - mpfr_init2(_u, chunk_); - mpfr_init2(_v, chunk_); - mpfr_init2(_up, chunk_); - mpfr_init2(_vp, chunk_); - mpfr_init2(_vx, chunk_); - mpfr_init2(_x1, chunk_); - mpfr_init2(_x2, chunk_); - } - /** - * Destroy the MPFRNormalR object. - **********************************************************************/ - ~MPFRNormalR() { - mpfr_clear(_x2); - mpfr_clear(_x1); - mpfr_clear(_vx); - mpfr_clear(_vp); - mpfr_clear(_up); - mpfr_clear(_v); - mpfr_clear(_u); - mpfr_clear(_eps); - mpz_clear(_vi); - mpz_clear(_ui); - } - /** - * Sample from the normal distribution with mean 0 and variance 1. - * - * @param[out] val the sample from the normal distribution - * @param[in,out] r a GMP random generator. - * @param[in] round the rounding direction. - * @return the MPFR ternary result (+1/-1 if val is larger/smaller than the - * exact sample). - **********************************************************************/ - int operator()(mpfr_t val, gmp_randstate_t r, mpfr_rnd_t round) const { - const double - s = 0.449871, // Constants from Leva - t = -0.386595, - a = 0.19600 , - b = 0.25472 , - r1 = 0.27597 , - r2 = 0.27846 , - u1 = 0.606530, // sqrt(1/e) rounded down and up - u2 = 0.606531, - scale = std::pow(2.0, -chunk_); // for turning randoms into doubles - - while (true) { - mpz_urandomb(_vi, r, chunk_); - if (mpz_cmp_ui(_vi, m) >= 0) continue; // Very early reject - double vf = (mpz_get_ui(_vi) + 0.5) * scale; - mpz_urandomb(_ui, r, chunk_); - double uf = (mpz_get_ui(_ui) + 0.5) * scale; - double - x = uf - s, - y = vf - t, - Q = x*x + y * (a*y - b*x); - if (Q >= r2) continue; // Early reject - mpfr_set_ui_2exp(_eps, 1u, -chunk_, MPFR_RNDN); - mpfr_prec_t prec = chunk_; - mpfr_set_prec(_u, prec); - mpfr_set_prec(_v, prec); - // (u,v) = sw corner of range - mpfr_set_z_2exp(_u, _ui, -prec, MPFR_RNDN); - mpfr_set_z_2exp(_v, _vi, -prec, MPFR_RNDN); - mpfr_set_prec(_up, prec); - mpfr_set_prec(_vp, prec); - // (up,vp) = ne corner of range - mpfr_add(_up, _u, _eps, MPFR_RNDN); - mpfr_add(_vp, _v, _eps, MPFR_RNDN); - // Estimate how many extra bits will be needed to achieve the desired - // precision. - mpfr_prec_t prec_guard = 3 + chunk_ - std::max(mpz_sizeinbase(_ui, 2), - mpz_sizeinbase(_vi, 2)); - if (Q > r1) { - int reject; - while (true) { - // Rejection curve v^2 + 4 * u^2 * log(u) < 0 has a peak at u = - // exp(-1/2) = 0.60653066. So treat uf in (0.606530, 0.606531) = - // (u1, u2) specially - - // Try for rejection first - if (uf <= u1) - reject = Reject(_u, _vp, prec, MPFR_RNDU); - else if (uf >= u2) - reject = Reject(_up, _vp, prec, MPFR_RNDU); - else { // u in (u1, u2) - mpfr_set_prec(_vx, prec); - mpfr_add(_vx, _vp, _eps, MPFR_RNDN); - reject = Reject(_u, _vx, prec, MPFR_RNDU); // Could use _up too - } - if (reject < 0) break; // tried to reject but failed, so accept - - // Try for acceptance - if (uf <= u1) - reject = Reject(_up, _v, prec, MPFR_RNDD); - else if (uf >= u2) - reject = Reject(_u, _v, prec, MPFR_RNDD); - else { // u in (u2, u2) - mpfr_sub(_vx, _v, _eps, MPFR_RNDN); - reject = Reject(_u, _vx, prec, MPFR_RNDD); // Could use _up too - } - if (reject > 0) break; // tried to accept but failed, so reject - - prec = Refine(r, prec); // still can't decide, to refine - } - if (reject > 0) continue; // reject, back to outer loop - } - // Now evaluate v/u to the necessary precision - mpfr_prec_t prec0 = mpfr_get_prec (val); - // while (prec < prec0 + prec_guard) prec = Refine(r, prec); - if (prec < prec0 + prec_guard) - prec = Refine(r, prec, - (prec0 + prec_guard - prec + chunk_ - 1) / chunk_); - mpfr_set_prec(_x1, prec0); - mpfr_set_prec(_x2, prec0); - int flag; - while (true) { - int - f1 = mpfr_div(_x1, _v, _up, round), // min slope - f2 = mpfr_div(_x2, _vp, _u, round); // max slope - if (f1 == f2 && mpfr_equal_p(_x1, _x2)) { - flag = f1; - break; - } - prec = Refine(r, prec); - } - mpz_urandomb(_ui, r, 1); - if (mpz_tstbit(_ui, 0)) { - flag = -flag; - mpfr_neg(val, _x1, MPFR_RNDN); - } else - mpfr_set(val, _x1, MPFR_RNDN); - // std::cerr << uf << " " << vf << " " << Q << "\n"; - return flag; - } - } - private: - // disable copy constructor and assignment operator - MPFRNormalR(const MPFRNormalR&); - MPFRNormalR& operator=(const MPFRNormalR&); - // Refine the random square - mpfr_prec_t Refine(gmp_randstate_t r, mpfr_prec_t prec, long num = 1) - const { - if (num <= 0) return prec; - // Use _vx as scratch - prec += num * chunk_; - mpfr_div_2ui(_eps, _eps, num * chunk_, MPFR_RNDN); - - mpz_urandomb(_ui, r, num * chunk_); - mpfr_set_prec(_up, prec); - mpfr_set_z_2exp(_up, _ui, -prec, MPFR_RNDN); - mpfr_set_prec(_vx, prec); - mpfr_add(_vx, _u, _up, MPFR_RNDN); - mpfr_swap(_u, _vx); // u = vx - mpfr_add(_up, _u, _eps, MPFR_RNDN); - - mpz_urandomb(_vi, r, num * chunk_); - mpfr_set_prec(_vp, prec); - mpfr_set_z_2exp(_vp, _vi, -prec, MPFR_RNDN); - mpfr_set_prec(_vx, prec); - mpfr_add(_vx, _v, _vp, MPFR_RNDN); - mpfr_swap(_v, _vx); // v = vx - mpfr_add(_vp, _v, _eps, MPFR_RNDN); - - return prec; - } - // Evaluate the sign of the rejection condition v^2 + 4*u^2*log(u) - int Reject(mpfr_t u, mpfr_t v, mpfr_prec_t prec, mpfr_rnd_t round) const { - // Use x1, x2 as scratch - mpfr_set_prec(_x1, prec); - - mpfr_log(_x1, u, round); - mpfr_mul(_x1, _x1, u, round); // Important to do the multiplications in - mpfr_mul(_x1, _x1, u, round); // this order so that rounding works right. - mpfr_mul_2ui(_x1, _x1, 2u, round); // 4*u^2*log(u) - - mpfr_set_prec(_x2, prec); - mpfr_mul(_x2, v, v, round); // v^2 - - mpfr_add(_x1, _x1, _x2, round); // v^2 + 4*u^2*log(u) - - return mpfr_sgn(_x1); - } - mutable mpz_t _ui; - mutable mpz_t _vi; - mutable mpfr_t _eps; - mutable mpfr_t _u; - mutable mpfr_t _v; - mutable mpfr_t _up; - mutable mpfr_t _vp; - mutable mpfr_t _vx; - mutable mpfr_t _x1; - mutable mpfr_t _x2; - }; - -} // namespace RandomLib - -#endif // RANDOMLIB_MPFRNORMALR_HPP diff --git a/app/RandomLib/MPFRRandom.hpp b/app/RandomLib/MPFRRandom.hpp deleted file mode 100644 index 60db3f160193ae9b65f71659e96ce4837eff9795..0000000000000000000000000000000000000000 --- a/app/RandomLib/MPFRRandom.hpp +++ /dev/null @@ -1,378 +0,0 @@ -/** - * \file MPFRRandom.hpp - * \brief Header for MPFRRandom - * - * Utility class for MPFRUniform, MPFRExponential, and MPFRNormal. - * - * Copyright (c) Charles Karney (2012) <charles@karney.com> and licensed under - * the MIT/X11 License. For more information, see - * http://randomlib.sourceforge.net/ - **********************************************************************/ - -#if !defined(RANDOMLIB_MPFRRANDOM_HPP) -#define RANDOMLIB_MPFRRANDOM_HPP \ - "$Id: f45db9d188823c74ad97ac4b31b3c2bfe4a5ee2a $" - -#include <algorithm> // for swap -#include <mpfr.h> - -/** - * A compile-time assert. Use C++11 static_assert, if available. - **********************************************************************/ -#if !defined(STATIC_ASSERT) -# if defined(__GXX_EXPERIMENTAL_CXX0X__) -# define STATIC_ASSERT static_assert -# elif defined(_MSC_VER) && _MSC_VER >= 1600 -# define STATIC_ASSERT static_assert -# else -# define STATIC_ASSERT(cond,reason) \ - { enum{ STATIC_ASSERT_ENUM = 1/int(cond) }; } -# endif -#endif - -namespace RandomLib { - - /** - * \brief Handling random numbers in MPFR. - * - * This class provides roughly the same capabilities as RandomNumber. The - * fraction is represented by a mpz integer f and an exponent e. We have e - * >= 0 and 0 <= f < b^e, and b = 2^bits. This represents the number x = f * - * b^-e, with x in [0, 1). - * - * @tparam bits the number of bits in each digit. - * - * \e bits must divide GMP_LIMB_BITS. The default value \e bits = 32 yields - * portable results on all MPFR platforms. - **********************************************************************/ - template<int bits = 32> class MPFRRandom { - private: - static const int limb_ = GMP_LIMB_BITS; // How many bits in a limb - static const int loglimb_ = (limb_ == 32 ? 5 : - (limb_ == 64 ? 6 : - (limb_ == 128 ? 7 : -1))); - static const int logbits_ = (bits == 1 ? 0 : - (bits == 2 ? 1 : - (bits == 4 ? 2 : - (bits == 8 ? 3 : - (bits == 16 ? 4 : - (bits == 32 ? 5 : - (bits == 64 ? 6 : - (bits == 128 ? 7 : -1)))))))); - static const mp_limb_t mask_ = (bits == limb_ ? ~0UL : // Digit mask - ~(~0UL << (bits < limb_ ? bits : 0))); - static const int logw_ = loglimb_ - logbits_; // 2^logw digits per limb - static const unsigned wmask_ = ~(~0U << logw_); - - mutable mpz_t _tt; // A temporary - mpz_t _f; // The fraction - mp_size_t _e; // Count of digits - unsigned long _n; // Integer part - int _s; // Sign - void AddDigits(gmp_randstate_t r, long num = 1) { // Add num more digits - if (num <= 0) return; - mpz_mul_2exp(_f, _f, num << logbits_); - mpz_urandomb(_tt, r, num << logbits_); - mpz_add(_f, _f, _tt); - _e += num; - } - // return k'th digit counting k = 0 as most significant - mp_limb_t Digit(gmp_randstate_t r, mp_size_t k) { - ExpandTo(r, k); // Now e > k - k = _e - 1 - k; // Reverse k so k = 0 is least significant - // (k >> logw) is the limb index - // (k & wmask) is the digit position within the limb - return mask_ & - (mpz_getlimbn(_f, k >> logw_) >> ((k & wmask_) << logbits_)); - } - // Return index [0..32] of highest bit set. Return 0 if x = 0, 32 is if x - // = ~0. (From Algorithms for programmers by Joerg Arndt.) - static int highest_bit_idx(unsigned long x) throw() { - if (x == 0) return 0; - int r = 1; - // STILL TO DO: handle 64-bit unsigned longs.q - if (x & 0xffff0000UL) { x >>= 16; r += 16; } - if (x & 0x0000ff00UL) { x >>= 8; r += 8; } - if (x & 0x000000f0UL) { x >>= 4; r += 4; } - if (x & 0x0000000cUL) { x >>= 2; r += 2; } - if (x & 0x00000002UL) { r += 1; } - return r; - } - public: - /** - * Initialize the MPFRRandom object. - **********************************************************************/ - MPFRRandom() : _e(0u), _n(0u), _s(1) { - STATIC_ASSERT(logbits_ >= 0 && loglimb_ >= 0 && logbits_ <= loglimb_, - "MPRFRandom: unsupported value for bits"); - mpz_init(_f); mpz_init(_tt); - } - /** - * Initialize the MPFRRandom object from another one. - * - * @param[in] t the MPFRRandom to copy. - **********************************************************************/ - MPFRRandom(const MPFRRandom& t) : _e(t._e), _n(t._n), _s(t._s) - { mpz_init(_f); mpz_set(_f, t._f); mpz_init(_tt); } - /** - * Destroy the MPFRRandom object. - **********************************************************************/ - ~MPFRRandom() { mpz_clear(_f); mpz_clear(_tt); } - /** - * Assignment operator. (But swapping is typically faster.) - * - * @param[in] t the MPFRRandom to copy. - **********************************************************************/ - MPFRRandom& operator=(const MPFRRandom& t) { - _e = t._e; - _n = t._n; - _s = t._s; - mpz_set(_f, t._f); // Don't copy _tt - return *this; - } - /** - * Swap with another MPFRRandom. This is a fast way of doing an - * assignment. - * - * @param[in,out] t the MPFRRandom to swap with. - **********************************************************************/ - void swap(MPFRRandom& t) throw() { - if (this != &t) { - std::swap(_e, t._e); - std::swap(_n, t._n); - std::swap(_s, t._s); - mpz_swap(_f, t._f); // Don't swap _tt - } - } - /** - * Reinitialize the MPFRRandom object, setting its value to [0,1]. - **********************************************************************/ - void Init() { mpz_set_ui(_f, 0u); _e = 0; _n = 0; _s = 1; } - /** - * @return the sign of the MPFRRandom (+/- 1). - **********************************************************************/ - int Sign() const throw() { return _s; } - /** - * Change the sign of the MPFRRandom. - **********************************************************************/ - void Negate() throw() { _s *= -1; } - /** - * @return the floor of the MPFRRandom - **********************************************************************/ - long Floor() const throw() { return _s > 0 ? long(_n) : -1 - long(_n); } - /** - * @return the ceiling of the MPFRRandom - **********************************************************************/ - long Ceiling() const throw() { return _s > 0 ? 1 + long(_n) : -long(_n); } - /** - * @return the unsigned integer component of the MPFRRandom. - **********************************************************************/ - unsigned long UInteger() const throw() { return _n; } - /** - * @return the number of digits in fraction - **********************************************************************/ - unsigned long Size() const throw() { return unsigned(_e); } - /** - * Add integer \e k to the MPRFRandom. - * - * @param[in] k the integer to add. - **********************************************************************/ - void AddInteger(long k) { - k += Floor(); // The new floor - int ns = k < 0 ? -1 : 1; // The new sign - if (ns != _s) { // If sign changes, set f = 1 - f - mpz_set_ui(_tt, 1u); - mpz_mul_2exp(_tt, _tt, _e << logbits_); - mpz_sub_ui(_tt, _tt, 1u); - mpz_sub(_f, _tt, _f); - _s = ns; - } - _n = ns > 0 ? k : -(k + 1); - } - /** - * Compare with another MPFRRandom, *this < \e t. - * - * @param[in,out] r a random generator. - * @param[in,out] t a MPFRRandom to compare. - * @return true if *this < \e t. - **********************************************************************/ - int LessThan(gmp_randstate_t r, MPFRRandom& t) { - if (this == &t) return false; // same object - if (_s != t._s) return _s < t._s; - if (_n != t._n) return (_s < 0) ^ (_n < t._n); - for (mp_size_t k = 0; ; ++k) { - mp_limb_t x = Digit(r, k); - mp_limb_t y = t.Digit(r, k); - if (x != y) return (_s < 0) ^ (x < y); - } - } - /** - * Set high bit of fraction to 1. - * - * @param[in,out] r a random generator. - **********************************************************************/ - void SetHighBit(gmp_randstate_t r) { // Set the msb to 1 - ExpandTo(r, 0); // Generate msb if necessary - mpz_setbit(_f, (_e << logbits_) - 1); - } - /** - * Test high bit of fraction. - * - * @param[in,out] r a random generator. - **********************************************************************/ - int TestHighBit(gmp_randstate_t r) { // test the msb of f - ExpandTo(r, 0); // Generate msb if necessary - return mpz_tstbit(_f, (_e << logbits_) - 1); - } - /** - * Return the position of the most significant bit in the MPFRRandom. - * - * @param[in,out] r a random generator. - * - * The bit position is numbered such the 1/2 bit is 0, the 1/4 bit is -1, - * etc. - **********************************************************************/ - mp_size_t LeadingBit(gmp_randstate_t r) { - if (_n) return highest_bit_idx(_n); - while (true) { - int sgn = mpz_sgn(_f); - if (sgn != 0) - return mp_size_t(mpz_sizeinbase(_f, 2)) - mp_size_t(_e << logbits_); - AddDigits(r); - } - } - /** - * Ensure that the k'th digit of the fraction is computed. - * - * @param[in,out] r a random generator. - * @param[in] k the digit number (0 is the most significant, 1 is the next - * most significant, etc. - **********************************************************************/ - void ExpandTo(gmp_randstate_t r, mp_size_t k) - { if (_e <= k) AddDigits(r, k - _e + 1); } - /** - * Convert to a MPFR number \e without adding more bits. - * - * @param[out] val the value of s * (n + *this). - * @param[in] round the rounding direction. - * @return the MPFR ternary result (+1/-1 if val is larger/smaller than the - * exact sample). - * - * If round is MPFR_RNDN, then the rounded midpoint of the interval - * represented by the MPFRRandom is returned. Otherwise it is the rounded - * lower or upper bound of the interval (whichever is appropriate). - **********************************************************************/ - int operator()(mpfr_t val, mpfr_rnd_t round) - { return operator()(val, NULL, round); } - /** - * Convert to a MPFR number. - * - * @param[out] val the value of s * (n + *this). - * @param[in,out] r a GMP random generator. - * @param[in] round the rounding direction. - * @return the MPFR ternary result (+1/-1 if val is larger/smaller than the - * exact sample). - * - * If \e r is NULL, then no additional random bits are generated and the - * lower bound, midpoint, or upper bound of the MPFRRandom interval is - * returned, depending on the value of \e round. - **********************************************************************/ - int operator()(mpfr_t val, gmp_randstate_t r, mpfr_rnd_t round) { - // The value is constructed as a positive quantity, so adjust rounding - // mode to account for this. - switch (round) { - case MPFR_RNDD: - case MPFR_RNDU: - case MPFR_RNDN: - break; - case MPFR_RNDZ: - round = _s < 0 ? MPFR_RNDU : MPFR_RNDD; - break; - case MPFR_RNDA: - round = _s < 0 ? MPFR_RNDD : MPFR_RNDU; - break; - default: - round = MPFR_RNDN; // New rounding modes are variants of N - break; - } // Now round is one of MPFR_RND{D,N,U} - - mp_size_t excess; - mpfr_exp_t expt; - if (r == NULL) { - // If r is NULL then all the bits currently generated are considered - // significant. Thus no excess bits need to be squeezed out. - excess = 0; - // And the exponent shift in mpfr_set_z_2exp is just... - expt = -(_e << logbits_); - // However, if rounding to nearest, we need to make room for the - // midpoint bit. - if (round == MPFR_RNDN) { - excess = -1; - --expt; - } - } else { // r is non-NULL - // Generate enough digits, i.e., enough to generate prec significant - // figures for RNDD and RNDU; for RNDN we need to generate an - // additional guard bit. - mp_size_t lead = LeadingBit(r); - mpfr_prec_t prec = mpfr_get_prec (val); - mp_size_t trail = lead - prec; // position one past trailing bit - mp_size_t guard = trail + (round == MPFR_RNDN ? 0 : 1); // guard bit pos - // Generate the bits needed. - if (guard <= 0) ExpandTo(r, (-guard) >> logbits_); - // Unless bits = 1, the generation process will typically have - // generated too many bits. We figure out how many, but leaving room - // for one additional "inexact" bit. The inexact bit is set to 1 in - // order to force MPFR to treat the result as inexact, to break RNDN - // ties, and to get the ternary value set correctly. - // - // expt is the exponent used when forming the number using - // mpfr_set_z_2exp. Without the inexact bit, it's (guard - 1). - // Subtract 1 to account for the inexact bit. - expt = guard - 2; - // The number of excess bits is now the difference between the number - // of bits in the fraction (e << logbits) and -expt. Note that this - // may be -1 (meaning we'll need to shift the number left to - // accommodate the inexact bit). - excess = (_e << logbits_) + expt; - } - mpz_set_ui(_tt, _n); // The integer part - mpz_mul_2exp(_tt, _tt, _e << logbits_); // Shift to allow for fraction - mpz_add(_tt, _tt, _f); // Add fraction - if (excess > 0) - mpz_tdiv_q_2exp(_tt, _tt, excess); - else if (excess < 0) - mpz_mul_2exp(_tt, _tt, -excess); - if (r || round == MPFR_RNDN) - // Set the inexact bit (or compute the midpoint if r is NULL). - mpz_setbit(_tt, 0); - else if (round == MPFR_RNDU) - // If r is NULL, compute the upper bound. - mpz_add_ui(_tt, _tt, 1u); - - // Convert to a mpfr number. If r is specified, then there are - // sufficient bits in tt that the result is inexact and that (in the case - // of RNDN) there are no ties. - int flag = mpfr_set_z_2exp(val, _tt, expt, round); - if (_s < 0) { - mpfr_neg (val, val, MPFR_RNDN); - flag = -flag; - } - return flag; - } - /** - * A coin toss. (This should really be a static function. But it uses the - * MPFRRandom temporary variable.) - * - * @param[in,out] r a GMP random generator. - * @return true or false. - **********************************************************************/ - int Boolean(gmp_randstate_t r) const { - mpz_urandomb(_tt, r, 1); - return mpz_tstbit(_tt, 0); - } - }; - -} // namespace RandomLib - -#endif // RANDOMLIB_MPFRRANDOM_HPP diff --git a/app/RandomLib/MPFRUniform.hpp b/app/RandomLib/MPFRUniform.hpp deleted file mode 100644 index 91a40328c92c7d06d3bb3decc1f98f4a79c944a5..0000000000000000000000000000000000000000 --- a/app/RandomLib/MPFRUniform.hpp +++ /dev/null @@ -1,70 +0,0 @@ -/** - * \file MPFRUniform.hpp - * \brief Header for MPFRUniform - * - * Sampling exactly from a uniform distribution for MPFR. - * - * Copyright (c) Charles Karney (2012) <charles@karney.com> and licensed under - * the MIT/X11 License. For more information, see - * http://randomlib.sourceforge.net/ - **********************************************************************/ - -#if !defined(RANDOMLIB_MPFRUNIFORM_HPP) -#define RANDOMLIB_MPFRUNIFORM_HPP \ - "$Id: 519dae274a9320e0683e217b0e0e27b3257deac7 $" - -#include <RandomLib/MPFRRandom.hpp> - -namespace RandomLib { - - /** - * \brief The uniform distribution for MPFR. - * - * This is just a thin layer on top of MPFRRandom to provide random numbers - * uniformly distributed in [0,1]. - * - * This class uses a mutable private object. So a single MPFRUniform object - * cannot safely be used by multiple threads. In a multi-processing - * environment, each thread should use a thread-specific MPFRUniform object. - * - * @tparam bits the number of bits in each digit. - **********************************************************************/ - template<int bits = 32> class MPFRUniform { - public: - - /** - * Initialize the MPFRUniform object. - **********************************************************************/ - MPFRUniform() {}; - /** - * Sample from the uniform distribution in [0,1] returning a MPFRRandom. - * This function takes an unused GMP random generator as a parameter, in - * order to parallel the usage of MPFRExponential and MPFRNormal. - * - * @param[out] t the MPFRRandom result. - * @param[in,out] r a GMP random generator (unused). - **********************************************************************/ - void operator()(MPFRRandom<bits>& t, gmp_randstate_t r) const - { Compute(r); _x.swap(t); } - /** - * Sample from the uniform distribution in [0,1]. - * - * @param[out] val the sample from the uniform distribution - * @param[in,out] r a GMP random generator. - * @param[in] round the rounding direction. - * @return the MPFR ternary result (+1/-1 if val is larger/smaller than the - * exact sample). - **********************************************************************/ - int operator()(mpfr_t val, gmp_randstate_t r, mpfr_rnd_t round) const - { Compute(r); return _x(val, r, round); } - private: - // disable copy constructor and assignment operator - MPFRUniform(const MPFRUniform&); - MPFRUniform& operator=(const MPFRUniform&); - void Compute(gmp_randstate_t /* r */) const { _x. Init(); } - mutable MPFRRandom<bits> _x; - }; - -} // namespace RandomLib - -#endif // RANDOMLIB_MPFRUNIFORM_HPP diff --git a/app/RandomLib/NormalDistribution.hpp b/app/RandomLib/NormalDistribution.hpp deleted file mode 100644 index 2efb21e742180b2255f6b5ee73024b194667093c..0000000000000000000000000000000000000000 --- a/app/RandomLib/NormalDistribution.hpp +++ /dev/null @@ -1,114 +0,0 @@ -/** - * \file NormalDistribution.hpp - * \brief Header for NormalDistribution - * - * Compute normal deviates. - * - * Copyright (c) Charles Karney (2006-2011) <charles@karney.com> and licensed - * under the MIT/X11 License. For more information, see - * http://randomlib.sourceforge.net/ - **********************************************************************/ - -#if !defined(RANDOMLIB_NORMALDISTRIBUTION_HPP) -#define RANDOMLIB_NORMALDISTRIBUTION_HPP \ - "$Id: 5cf62acdd75c228523bdae4348447f0a594dfbff $" - -#include <cmath> // for std::log - -namespace RandomLib { - /** - * \brief Normal deviates - * - * Sample from the normal distribution. - * - * This uses the ratio method; see Knuth, TAOCP, Vol 2, Sec. 3.4.1.C, - * Algorithm R. Unlike the Box-Muller method which generates two normal - * deviates at a time, this method generates just one. This means that this - * class has no state that needs to be saved when checkpointing a - * calculation. Original citation is\n A. J. Kinderman, J. F. Monahan,\n - * Computer Generation of Random Variables Using the Ratio of Uniform - * Deviates,\n ACM TOMS 3, 257-260 (1977). - * - * Improved "quadratic" bounds are given by\n J. L. Leva,\n A Fast Normal - * Random Number Generator,\n ACM TOMS 18, 449-453 and 454-455 (1992). - * - * The log is evaluated 1.369 times per normal deviate with no bounds, 0.232 - * times with Knuth's bounds, and 0.012 times with the quadratic bounds. - * Time is approx 0.3 us per deviate (1GHz machine, optimized, RealType = - * float). - * - * Example - * \code - * #include <RandomLib/NormalDistribution.hpp> - * - * RandomLib::Random r; - * std::cout << "Seed set to " << r.SeedString() << "\n"; - * RandomLib::NormalDistribution<double> normdist; - * std::cout << "Select from normal distribution:"; - * for (size_t i = 0; i < 10; ++i) - * std::cout << " " << normdist(r); - * std::cout << "\n"; - * \endcode - * - * @tparam RealType the real type of the results (default double). - **********************************************************************/ - template<typename RealType = double> class NormalDistribution { - public: - /** - * The type returned by NormalDistribution::operator()(Random&) - **********************************************************************/ - typedef RealType result_type; - /** - * Return a sample of type RealType from the normal distribution with mean - * \e mu and standard deviation <i>sigma</i>. - * - * For \e mu = 0 and \e sigma = 1 (the defaults), the distribution is - * symmetric about zero and is nonzero. The maximum result is less than 2 - * sqrt(log(2) \e p) where \e p is the precision of real type RealType. - * The minimum positive value is approximately 1/2<sup><i>p</i>+1</sup>. - * Here \e p is the precision of real type RealType. - * - * @tparam Random the type of RandomCanonical generator. - * @param[in,out] r the RandomCanonical generator. - * @param[in] mu the mean value of the normal distribution (default 0). - * @param[in] sigma the standard deviation of the normal distribution - * (default 1). - * @return the random sample. - **********************************************************************/ - template<class Random> - RealType operator()(Random& r, RealType mu = RealType(0), - RealType sigma = RealType(1)) const throw(); - }; - - template<typename RealType> template<class Random> inline RealType - NormalDistribution<RealType>::operator()(Random& r, RealType mu, - RealType sigma) const throw() { - // N.B. These constants can be regarded as "exact", so that the same number - // of significant figures are used in all versions. (They serve to - // "bracket" the real boundary specified by the log expression.) - const RealType - m = RealType( 1.7156 ), // sqrt(8/e) (rounded up) - s = RealType( 0.449871), // Constants from Leva - t = RealType(-0.386595), - a = RealType( 0.19600 ), - b = RealType( 0.25472 ), - r1 = RealType( 0.27597 ), - r2 = RealType( 0.27846 ); - RealType u, v, Q; - do { // This loop is executed 1.369 times on average - // Pick point P = (u, v) - u = r.template FixedU<RealType>(); // Sample u in (0,1] - v = m * r.template FixedS<RealType>(); // Sample v in (-m/2, m/2); avoid 0 - // Compute quadratic form Q - const RealType x = u - s; - const RealType y = (v < 0 ? -v : v) - t; // Sun has no long double abs! - Q = x*x + y * (a*y - b*x); - } while ( Q >= r1 && // accept P if Q < r1 - ( Q > r2 || // reject P if Q > r2 - v*v > - 4 * u*u * std::log(u) ) ); // accept P if v^2 <= ... - return mu + sigma * (v / u); // return the slope of P (note u != 0) - } - -} // namespace RandomLib - -#endif // RANDOMLIB_NORMALDISTRIBUTION_HPP diff --git a/app/RandomLib/Random.hpp b/app/RandomLib/Random.hpp deleted file mode 100644 index 920c7aa8d21ca642a51048f0d682d3e4980b39b8..0000000000000000000000000000000000000000 --- a/app/RandomLib/Random.hpp +++ /dev/null @@ -1,149 +0,0 @@ -/** - * \file Random.hpp - * \brief Header for Random, RandomGenerator. - * - * This loads up the header for RandomCanonical, RandomEngine, etc., to - * provide access to random integers of various sizes, random reals with - * various precisions, a random probability, etc. - * - * Copyright (c) Charles Karney (2006-2011) <charles@karney.com> and licensed - * under the MIT/X11 License. For more information, see - * http://randomlib.sourceforge.net/ - **********************************************************************/ - -#if !defined(RANDOMLIB_RANDOM_HPP) -#define RANDOMLIB_RANDOM_HPP \ - "$Id: cc11caea585fca1d2373b952cf37b7678dabd8b9 $" - -#include <RandomLib/Config.h> - -#if defined(_MSC_VER) -typedef unsigned uint32_t; -typedef unsigned long long uint64_t; -#else -#include <stdint.h> -#endif - -#if defined(__GNUC__) -// Suppress "defined but not used" warnings -#define RCSID_DECL(x) namespace \ -{ char VAR_ ## x [] __attribute__((unused)) = x; } -#else -/** - * Insertion of RCS Id strings into the object file. - **********************************************************************/ -#define RCSID_DECL(x) namespace { char VAR_ ## x [] = x; } -#endif - -/** - * Use table, Power2::power2, for pow2? This isn't necessary with g++ 4.0 - * because calls to std::pow are optimized. g++ 4.1 seems to have lost this - * capability though! And it's back in g++ 4.4. So, for simplicity, assume - * that all "current" versions of g++ perform the optimization. - **********************************************************************/ -#if !defined(RANDOMLIB_POWERTABLE) -#if defined(__GNUC__) -#define RANDOMLIB_POWERTABLE 0 -#else -// otherwise use a lookup table -#define RANDOMLIB_POWERTABLE 1 -#endif -#endif - -#if !HAVE_LONG_DOUBLE || defined(_MSC_VER) -#define RANDOMLIB_LONGDOUBLEPREC 53 -#elif defined(__sparc) -#define RANDOMLIB_LONGDOUBLEPREC 113 -#else -/** - * The precision of long doubles, used for sizing Power2::power2. 64 on - * Linux/Intel, 106 on MaxOS/PowerPC - **********************************************************************/ -#define RANDOMLIB_LONGDOUBLEPREC __LDBL_MANT_DIG__ -#endif - -/** - * A compile-time assert. Use C++11 static_assert, if available. - **********************************************************************/ -#if !defined(STATIC_ASSERT) -# if defined(__GXX_EXPERIMENTAL_CXX0X__) -# define STATIC_ASSERT static_assert -# elif defined(_MSC_VER) && _MSC_VER >= 1600 -# define STATIC_ASSERT static_assert -# else -# define STATIC_ASSERT(cond,reason) \ - { enum{ STATIC_ASSERT_ENUM = 1/int(cond) }; } -# endif -#endif - -/** - * Are denormalized reals of type RealType supported? - **********************************************************************/ -#define RANDOMLIB_HASDENORM(RealType) 1 - -#if defined(_WIN32) && defined(RANDOM_SHARED_LIB) -# if defined(Random_EXPORTS) -# define RANDOM_EXPORT __declspec(dllexport) -# else -# define RANDOM_EXPORT __declspec(dllimport) -# endif -#else -# define RANDOM_EXPORT -#endif - -#include <stdexcept> - -/** - * \brief Namespace for %RandomLib - * - * All of %RandomLib is defined within the RandomLib namespace. In addtiion - * all the header files are included via %RandomLib/filename. This minimizes - * the likelihood of conflicts with other packages. - **********************************************************************/ -namespace RandomLib { - - /** - * \brief Exception handling for %RandomLib - * - * A class to handle exceptions. It's derived from std::runtime_error so it - * can be caught by the usual catch clauses. - **********************************************************************/ - class RandomErr : public std::runtime_error { - public: - - /** - * Constructor - * - * @param[in] msg a string message, which is accessible in the catch - * clause, via what(). - **********************************************************************/ - RandomErr(const std::string& msg) : std::runtime_error(msg) {} - }; - -} // namespace RandomLib - -#include <RandomLib/RandomCanonical.hpp> - -#if !defined(RANDOMLIB_BUILDING_LIBRARY) - -namespace RandomLib { - -#if !defined(RANDOMLIB_DEFAULT_GENERATOR) -#define RANDOMLIB_DEFAULT_GENERATOR SRandomGenerator32 -#endif - - /** - * Point Random to one of a specific MT19937 generators. - **********************************************************************/ - typedef RANDOMLIB_DEFAULT_GENERATOR RandomGenerator; - - /** - * Hook Random to RandomGenerator - **********************************************************************/ - typedef RandomCanonical<RandomGenerator> Random; - -} // namespace RandomLib - -#endif // !defined(RANDOMLIB_BUILDING_LIBRARY) - -#endif // RANDOMLIB_RANDOM_HPP diff --git a/app/RandomLib/RandomAlgorithm.hpp b/app/RandomLib/RandomAlgorithm.hpp deleted file mode 100644 index 015da62ce8bb2e64b38df633cc5b13bfa9fc77ce..0000000000000000000000000000000000000000 --- a/app/RandomLib/RandomAlgorithm.hpp +++ /dev/null @@ -1,376 +0,0 @@ -/** - * \file RandomAlgorithm.hpp - * \brief Header for MT19937 and SFMT19937. - * - * This provides an interface to the Mersenne Twister - * <a href="http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/emt.html"> - * MT19937</a> and SIMD oriented Fast Mersenne Twister - * <a href="http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/SFMT/index.html"> - * SFMT19937</a> random number engines. - * - * Interface routines written by Charles Karney <charles@karney.com> and - * licensed under the MIT/X11 License. For more information, see - * http://randomlib.sourceforge.net/ - **********************************************************************/ - -#if !defined(RANDOMLIB_RANDOMALGORITHM_HPP) -#define RANDOMLIB_RANDOMALGORITHM_HPP \ - "$Id: 9b552f2d80c03c7729eff07431a92a6c51211767 $" - -#include <RandomLib/RandomType.hpp> -#include <stdexcept> -#include <string> -#if defined(HAVE_SSE2) && HAVE_SSE2 -#include <emmintrin.h> -#endif - -#if (defined(HAVE_SSE2) && HAVE_SSE2) && (defined(HAVE_ALTIVEC) && HAVE_ALTIVEC) -#error "HAVE_SSE2 and HAVE_ALTIVEC should not both be defined" -#endif - -namespace RandomLib { - - /** - * \brief The %MT19937 random number engine. - * - * This provides an interface to Mersenne Twister random number engine, - * <a href="http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/emt.html"> - * MT19937</a>. See\n Makoto Matsumoto and Takuji Nishimura,\n Mersenne - * Twister: A 623-Dimensionally Equidistributed Uniform Pseudo-Random Number - * Generator,\n ACM TOMACS 8, 3-30 (1998) - * - * This is adapted from the 32-bit and 64-bit C versions available at - * http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/MT2002/emt19937ar.html and - * http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/emt64.html - * - * The template argument give the type \e RandomType of the "natural" result. - * This incorporates the bit width and the C++ type of the result. Although - * the two versions of MT19937 produce different sequences, the - * implementations here are portable across 32-bit and 64-bit architectures. - * - * The class chiefly supplies the method for advancing the state by - * Transition. - * - * @tparam RandomType the type of the results, either Random_u32 or - * Random_u64. - * - * Interface routines written by Charles Karney <charles@karney.com> and - * licensed under the MIT/X11 License. For more information, see - * http://randomlib.sourceforge.net/ - **********************************************************************/ - template<class RandomType> class RANDOM_EXPORT MT19937 { - public: - /** - * The result RandomType - **********************************************************************/ - typedef RandomType engine_t; - /** - * The internal numeric type for MT19337::Transition - **********************************************************************/ - typedef typename engine_t::type internal_type; - private: - /** - * The unsigned type of engine_t - **********************************************************************/ - typedef typename engine_t::type engine_type; - /** - * The width of the engine_t - **********************************************************************/ - static const unsigned width = engine_t::width; - enum { - /** - * The Mersenne prime is 2<sup><i>P</i></sup> - 1 - **********************************************************************/ - P = 19937, - /** - * The short lag for MT19937 - **********************************************************************/ - M = width == 32 ? 397 : 156, - /** - * The number of ignored bits in the first word of the state - **********************************************************************/ - R = ((P + width - 1)/width) * width - P - }; - static const engine_type mask = engine_t::mask; - /** - * Magic matrix for MT19937 - **********************************************************************/ - static const engine_type magic = - width == 32 ? 0x9908b0dfULL : 0xb5026f5aa96619e9ULL; - /** - * Mask for top \e width - \e R bits of a word - **********************************************************************/ - static const engine_type upper = mask << R & mask; - /** - * Mask for low \e R bits of a <i>width</i>-bit word - **********************************************************************/ - static const engine_type lower = ~upper & mask; - - public: - /** - * A version number "EnMT" or "EnMU" to ensure safety of Save/Load. This - * needs to be unique across RandomAlgorithms. - **********************************************************************/ - static const unsigned version = 0x456e4d54UL + (engine_t::width/32 - 1); - enum { - /** - * The size of the state. This is the long lag for MT19937. - **********************************************************************/ - N = (P + width - 1)/width - }; - /** - * Advance state by \e count batches. For speed all \e N words of state - * are advanced together. If \e count is negative, the state is stepped - * backwards. This is the meat of the MT19937 engine. - * - * @param[in] count how many batches to advance. - * @param[in,out] statev the internal state of the random number generator. - **********************************************************************/ - static void Transition(long long count, internal_type statev[]) - throw(); - - /** - * Manipulate a word of the state prior to output. - * - * @param[in] y a word of the state. - * @return the result. - **********************************************************************/ - static engine_type Generate(engine_type y) throw(); - - /** - * Convert an arbitrary state into a legal one. This consists of (a) - * turning on one bit if the state is all zero and (b) making 31 bits of - * the state consistent with the other 19937 bits. - * - * @param[in,out] state the state of the generator. - **********************************************************************/ - static void NormalizeState(engine_type state[]) throw(); - - /** - * Check that the state is legal, throwing an exception if it is not. At - * the same time, accumulate a checksum of the state. - * - * @param[in] state the state of the generator. - * @param[in,out] check an accumulated checksum. - **********************************************************************/ - static void CheckState(const engine_type state[], Random_u32::type& check); - - /** - * Return the name of the engine - * - * @return the name. - **********************************************************************/ - static std::string Name() throw() { - return "MT19937<Random_u" + std::string(width == 32 ? "32" : "64") + ">"; - } - }; - - /// \cond SKIP - template<> - inline Random_u32::type MT19937<Random_u32>::Generate(engine_type y) throw() { - y ^= y >> 11; - y ^= y << 7 & engine_type(0x9d2c5680UL); - y ^= y << 15 & engine_type(0xefc60000UL); - y ^= y >> 18; - - return y; - } - - template<> - inline Random_u64::type MT19937<Random_u64>::Generate(engine_type y) throw() { - // Specific tempering instantiation for width = 64 given in - // http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/emt64.html - y ^= y >> 29 & engine_type(0x5555555555555555ULL); - y ^= y << 17 & engine_type(0x71d67fffeda60000ULL); - y ^= y << 37 & engine_type(0xfff7eee000000000ULL); - y ^= y >> 43; - - return y; - } - /// \endcond - - /** - * \brief The SFMT random number engine. - * - * This provides an implementation of the SIMD-oriented Fast Mersenne Twister - * random number engine, - * <a href="http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/SFMT/index.html"> - * SFMT</a>. See\n Mutsuo Saito,\n An Application of Finite Field: Design - * and Implementation of 128-bit Instruction-Based Fast Pseudorandom Number - * Generator,\n Master's Thesis, Dept. of Math., Hiroshima University - * (Feb. 2007).\n - * http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/SFMT/M062821.pdf - * Mutsuo Saito and Makoto Matsumoto,\n - * SIMD-oriented Fast Mersenne Twister: a 128-bit Pseudorandom Number - * Generator,\n accepted in the proceedings of MCQMC2006\n - * http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/ARTICLES/sfmt.pdf - * - * The template argument gives the type \e RandomType of the "natural" - * result. This incorporates the bit width and the C++ type of the result. - * The 32-bit and 64-bit versions of SFMT19937 produce the same sequences and - * the differing only in whether how the state is represented. The - * implementation includes a version using 128-bit SSE2 instructions. On - * machines without these instructions, portable implementations using - * traditional operations are provided. With the same starting seed, - * SRandom32::Ran64() and SRandom64::Ran64() produces the same sequences. - * Similarly SRandom64::Ran32() produces every other member of the sequence - * produced by SRandom32::Ran32(). - * - * The class chiefly supplies the method for advancing the state by - * Transition. - * - * @tparam RandomType the type of the results, either Random_u32 or - * Random_u64. - * - * Written by Charles Karney <charles@karney.com> and licensed under the - * MIT/X11 License. For more information, see - * http://randomlib.sourceforge.net/ - **********************************************************************/ - template<class RandomType> class RANDOM_EXPORT SFMT19937 { - public: - /** - * The result RandomType - **********************************************************************/ - typedef RandomType engine_t; -#if defined(HAVE_SSE2) && HAVE_SSE2 - typedef __m128i internal_type; -#elif defined(HAVE_ALTIVEC) && HAVE_ALTIVEC - typedef vector unsigned internal_type; -#else - /** - * The internal numeric type for SFMT19337::Transition - **********************************************************************/ - typedef typename engine_t::type internal_type; -#endif - private: - /** - * The unsigned type of engine_t - **********************************************************************/ - typedef typename engine_t::type engine_type; - /** - * The width of the engine_t - **********************************************************************/ - static const unsigned width = engine_t::width; - enum { - /** - * The Mersenne prime is 2<sup><i>P</i></sup> - 1 - **********************************************************************/ - P = 19937, - /** - * The long lag for SFMT19937 in units of 128-bit words - **********************************************************************/ - N128 = (P + 128 - 1)/128, - /** - * How many width words per 128-bit word. - **********************************************************************/ - R = 128 / width, - /** - * The short lag for SFMT19937 in units of 128-bit words - **********************************************************************/ - M128 = 122, - /** - * The short lag for SFMT19937 - **********************************************************************/ - M = M128 * R - }; -#if (defined(HAVE_SSE2) && HAVE_SSE2) || (defined(HAVE_ALTIVEC) && HAVE_ALTIVEC) - static const Random_u32::type magic0 = 0x1fffefUL; - static const Random_u32::type magic1 = 0x1ecb7fUL; - static const Random_u32::type magic2 = 0x1affffUL; - static const Random_u32::type magic3 = 0x1ffff6UL; -#else - /** - * Magic matrix for SFMT19937. Only the low 21 (= 32 - 11) bits need to be - * set. (11 is the right shift applied to the words before masking. - **********************************************************************/ - static const engine_type - magic0 = width == 32 ? 0x1fffefULL : 0x1ecb7f001fffefULL; - static const engine_type - magic1 = width == 32 ? 0x1ecb7fULL : 0x1ffff6001affffULL; - static const engine_type - magic2 = width == 32 ? 0x1affffULL : 0ULL; - static const engine_type - magic3 = width == 32 ? 0x1ffff6ULL : 0ULL; -#endif - /** - * Mask for simulating u32 << 18 with 64-bit words - **********************************************************************/ - static const engine_type mask18 = engine_type(0xfffc0000fffc0000ULL); - /** - * Magic constants needed by "period certification" - **********************************************************************/ - static const engine_type PARITY0 = 1U; - static const engine_type PARITY1 = width == 32 ? 0U : 0x13c9e68400000000ULL; - static const engine_type PARITY2 = 0U; - static const engine_type PARITY3 = width == 32 ? 0x13c9e684UL : 0U; - /** - * Least significant bit of PARITY - **********************************************************************/ - static const unsigned PARITY_LSB = 0; - static const engine_type mask = engine_t::mask; - - public: - /** - * A version number "EnSM" or "EnSN" to ensure safety of Save/Load. This - * needs to be unique across RandomAlgorithms. - **********************************************************************/ - static const unsigned version = 0x456e534dUL + (engine_t::width/32 - 1); - enum { - /** - * The size of the state. The long lag for SFMT19937 - **********************************************************************/ - N = N128 * R - }; - /** - * Advance state by \e count batches. For speed all \e N words of state - * are advanced together. If \e count is negative, the state is stepped - * backwards. This is the meat of the SFMT19937 engine. - * - * @param[in] count how many batches to advance. - * @param[in,out] statev the internal state of the random number generator. - **********************************************************************/ - static void Transition(long long count, internal_type statev[]) - throw(); - - /** - * Manipulate a word of the state prior to output. This is a no-op for - * SFMT19937. - * - * @param[in] y a word of the state. - * @return the result. - **********************************************************************/ - static engine_type Generate(engine_type y) throw() { return y; } - - /** - * Convert an arbitrary state into a legal one. This consists a "period - * certification to ensure that the period of the generator is at least - * 2<sup><i>P</i></sup> - 1. - * - * @param[in,out] state the state of the generator. - **********************************************************************/ - static void NormalizeState(engine_type state[]) throw(); - - /** - * Check that the state is legal, throwing an exception if it is not. This - * merely verifies that the state is not all zero. At the same time, - * accumulate a checksum of the state. - * - * @param[in] state the state of the generator. - * @param[in,out] check an accumulated checksum. - **********************************************************************/ - static void CheckState(const engine_type state[], Random_u32::type& check); - - /** - * Return the name of the engine - * - * @return the name. - **********************************************************************/ - static std::string Name() throw() { - return "SFMT19937<Random_u" + - std::string(width == 32 ? "32" : "64") + ">"; - } - }; - -} // namespace RandomLib - -#endif // RANDOMLIB_RANDOMALGORITHM_HPP diff --git a/app/RandomLib/RandomCanonical.hpp b/app/RandomLib/RandomCanonical.hpp deleted file mode 100644 index 560f4275cac5bf8307c6519632164f2fdc5c46a6..0000000000000000000000000000000000000000 --- a/app/RandomLib/RandomCanonical.hpp +++ /dev/null @@ -1,1290 +0,0 @@ -/** - * \file RandomCanonical.hpp - * \brief Header for RandomCanonical. - * - * Use the random bits from Generator to produce random integers of various - * sizes, random reals with various precisions, a random probability, etc. - * - * Copyright (c) Charles Karney (2006-2011) <charles@karney.com> and licensed - * under the MIT/X11 License. For more information, see - * http://randomlib.sourceforge.net/ - **********************************************************************/ - -#if !defined(RANDOMLIB_RANDOMCANONICAL_HPP) -#define RANDOMLIB_RANDOMCANONICAL_HPP \ - "$Id: aceea2ccd92a1d91717d7edc0331bcb38f6eb2ef $" - -#include <bitset> -#include <RandomLib/RandomPower2.hpp> -#include <RandomLib/RandomEngine.hpp> - -namespace RandomLib { - /** - * \brief Generate random integers, reals, and booleans. - * - * Use the random bits from Generator to produce random integers of various - * sizes, random reals with various precisions, a random probability, etc. - * RandomCanonical assumes that Generator produces random results as 32-bit - * quantities (of type uint32_t) via Generator::Ran32(), 64-bit quantities - * (of type uint64_t) via Generator::Ran64(), and in "natural" units of - * Generator::width bits (of type Generator::result_type) via - * Generator::Ran(). - * - * For the most part this class uses Ran() when needing \e width or fewer - * bits, otherwise it uses Ran64(). However, when \e width = 64, the - * resulting code is RandomCanonical::Unsigned(\e n) is inefficient because - * of the 64-bit arithmetic. For this reason RandomCanonical::Unsigned(\e n) - * uses Ran32() if less than 32 bits are required (even though this results - * in more numbers being produced by the Generator). - * - * This class has been tested with the 32-bit and 64-bit versions of MT19937 - * and SFMT19937. Other random number generators could be used provided that - * they provide a whole number of random bits so that Ran() is uniformly - * distributed in [0,2<sup><i>w</i></sup>). Probably some modifications - * would be needed if \e w is not 32 or 64. - * - * @tparam Generator the type of the underlying generator. - **********************************************************************/ - template<class Generator> - class RandomCanonical : public Generator { - public: - /** - * The type of operator()(). - **********************************************************************/ - typedef typename Generator::result_type result_type; - /** - * The type of elements of Seed(). - **********************************************************************/ - typedef typename RandomSeed::seed_type seed_type; - enum { - /** - * The number of random bits in result_type. - **********************************************************************/ - width = Generator::width - }; - - /** - * \name Constructors which set the seed - **********************************************************************/ - ///@{ - /** - * Initialize from a vector. - * - * @tparam IntType the integral type of the elements of the vector. - * @param[in] v the vector of elements. - **********************************************************************/ - template<typename IntType> - explicit RandomCanonical(const std::vector<IntType>& v) : Generator(v) {} - /** - * Initialize from a pair of iterator setting seed to [\e a, \e b) - * - * @tparam InputIterator the type of the iterator. - * @param[in] a the beginning iterator. - * @param[in] b the ending iterator. - **********************************************************************/ - template<typename InputIterator> - RandomCanonical(InputIterator a, InputIterator b) : Generator(a, b) {} - /** - * Initialize with seed [\e n] - * - * @param[in] n the new seed to use. - **********************************************************************/ - explicit RandomCanonical(seed_type n); - /** - * Initialize with seed []. This can be followed by a call to Reseed() to - * select a unique seed. - **********************************************************************/ - RandomCanonical() : Generator() {} - /** - * Initialize from a string. See RandomCanonical::StringToVector - * - * @param[in] s the string to be decoded into a seed. - **********************************************************************/ - explicit RandomCanonical(const std::string& s) : Generator(s) {} - ///@} - - /** - * \name Member functions returning integers - **********************************************************************/ - ///@{ - /** - * Return a raw result in [0, 2<sup><i>w</i></sup>) from the - * underlying Generator. - * - * @return a <i>w</i>-bit random number. - **********************************************************************/ - result_type operator()() throw() { return Generator::Ran(); } - - /** - * A random integer in [0, \e n). This allows a RandomCanonical object to - * be passed to those standard template library routines that require - * random numbers. E.g., - * \code - * RandomCanonical r; - * int a[] = {0, 1, 2, 3, 4}; - * std::random_shuffle(a, a+5, r); - * \endcode - * - * @param[in] n the upper end of the interval. The upper end of the - * interval is open, so \e n is never returned. - * @return the random integer in [0, \e n). - **********************************************************************/ - result_type operator()(result_type n) throw() - { return Integer<result_type>(n); } - - // Integer results (binary range) - - /** - * A random integer of type IntType in [0, 2<sup><i>b</i></sup>). - * - * @tparam IntType the integer type of the returned random numbers. - * @tparam bits how many random bits to return. - * @return the random result. - **********************************************************************/ - template<typename IntType, int bits> IntType Integer() throw() { - // A random integer of type IntType in [0, 2^bits) - STATIC_ASSERT(std::numeric_limits<IntType>::is_integer && - std::numeric_limits<IntType>::radix == 2, - "Integer<T,b>(): bad integer type IntType"); - // Check that we have enough digits in Ran64 - STATIC_ASSERT(bits > 0 && bits <= std::numeric_limits<IntType>::digits && - bits <= 64, "Integer<T,b>(): invalid value for bits"); - // Prefer masking to shifting so that we don't have to worry about sign - // extension (a non-issue, because Ran/64 are unsigned?). - return bits <= width ? - IntType(Generator::Ran() & Generator::mask - >> (bits <= width ? width - bits : 0)) : - IntType(Generator::Ran64() & u64::mask >> (64 - bits)); - } - - /** - * A random integer in [0, 2<sup><i>b</i></sup>). - * - * @tparam bits how many random bits to return. - * @return the random result. - **********************************************************************/ - template<int bits> - result_type Integer() throw() { return Integer<result_type, bits>(); } - - /** - * A random integer of type IntType in - * [std::numeric_limits<IntType>::min(), std::numeric_limits::max()]. - * - * @tparam IntType the integer type of the returned random numbers. - * @return the random result. - **********************************************************************/ - template<typename IntType> IntType Integer() throw(); - - /** - * A random result_type in [0, std::numeric_limits<result_type>::max()]. - * - * @return the random result. - **********************************************************************/ - result_type Integer() throw() - { return Integer<result_type>(); } - - // Integer results (finite range) - - /** - * A random integer of type IntType in [0, \e n). \e Excludes \e n. If \e - * n == 0, treat as std::numeric_limits::max() + 1. If \e n < 0, return 0. - * Compare RandomCanonical::Integer<int>(0) which returns a result in - * [0,2<sup>31</sup>) with RandomCanonical::Integer<int>() which returns a - * result in [-2<sup>31</sup>,2<sup>31</sup>). - * - * @tparam IntType the integer type of the returned random numbers. - * @param[in] n the upper end of the semi-open interval. - * @return the random result in [0, \e n). - **********************************************************************/ - template<typename IntType> IntType Integer(IntType n) throw(); - /** - * A random integer of type IntType in Closed interval [0, \e n]. \e - * Includes \e n. If \e n < 0, return 0. - * - * @tparam IntType the integer type of the returned random numbers. - * @param[in] n the upper end of the closed interval. - * @return the random result in [0, \e n]. - **********************************************************************/ - template<typename IntType> IntType IntegerC(IntType n) throw(); - /** - * A random integer of type IntType in Closed interval [\e m, \e n]. \e - * Includes both endpoints. If \e n < \e m, return \e m. - * - * @tparam IntType the integer type of the returned random numbers. - * @param[in] m the lower end of the closed interval. - * @param[in] n the upper end of the closed interval. - * @return the random result in [\e m, \e n]. - **********************************************************************/ - template<typename IntType> IntType IntegerC(IntType m, IntType n) throw(); - ///@} - - /** - * \name Member functions returning real fixed-point numbers - **********************************************************************/ - ///@{ - /** - * In the description of the functions FixedX returning \ref fixed - * "fixed-point" numbers, \e u is a random real number uniformly - * distributed in (0, 1), \e p is the precision, and \e h = - * 1/2<sup><i>p</i></sup>. Each of the functions come in three variants, - * e.g., - * - RandomCanonical::Fixed<RealType,p>() --- return \ref fixed - * "fixed-point" real of type RealType, precision \e p; - * - RandomCanonical::Fixed<RealType>() --- as above with \e p = - * std::numeric_limits<RealType>::digits; - * - RandomCanonical::Fixed() --- as above with RealType = double. - * - * See the \ref reals "summary" for a comparison of the functions. - * - * Return \e i \e h with \e i in [0,2<sup><i>p</i></sup>) by rounding \e u - * down to the previous \ref fixed "fixed" real. Result is in default - * interval [0,1). - * - * @tparam RealType the real type of the returned random numbers. - * @tparam prec the precision of the returned random numbers. - * @return the random result. - **********************************************************************/ - template<typename RealType, int prec> RealType Fixed() throw() { - // RandomCanonical reals in [0, 1). Results are of the form i/2^prec for - // integer i in [0,2^prec). - STATIC_ASSERT(!std::numeric_limits<RealType>::is_integer && - std::numeric_limits<RealType>::radix == 2, - "Fixed(): bad real type RealType"); - STATIC_ASSERT(prec > 0 && prec <= std::numeric_limits<RealType>::digits, - "Fixed(): invalid precision"); - RealType x = 0; // Accumulator - int s = 0; // How many bits so far - // Let n be the loop count. Typically prec = 24, n = 1 for float; prec = - // 53, n = 2 for double; prec = 64, n = 2 for long double. For Sun - // Sparc's, we have prec = 113, n = 4 for long double. For Windows, long - // double is the same as double (prec = 53). - do { - s += width; - x += RandomPower2::shiftf<RealType> - (RealType(Generator::Ran() >> (s > prec ? s - prec : 0)), - -(s > prec ? prec : s)); - } while (s < prec); - return x; - } - /** - * See documentation for RandomCanonical::Fixed<RealType,prec>(). - * - * @tparam RealType the real type of the returned random numbers. - * @return the random result with the full precision of RealType. - **********************************************************************/ - template<typename RealType> RealType Fixed() throw() - { return Fixed<RealType, std::numeric_limits<RealType>::digits>(); } - /** - * See documentation for RandomCanonical::Fixed<RealType,prec>(). - * - * @return the random double. - **********************************************************************/ - double Fixed() throw() { return Fixed<double>(); } - - /** - * An alias for RandomCanonical::Fixed<RealType>(). Returns a random - * number of type RealType in [0,1). - * - * @tparam RealType the real type of the returned random numbers. - * @return the random result with the full precision of RealType. - **********************************************************************/ - template<typename RealType> RealType Real() throw() - { return Fixed<RealType>(); } - /** - * An alias for RandomCanonical::Fixed(). Returns a random double in - * [0,1). - * - * @return the random double. - **********************************************************************/ - double Real() throw() { return Fixed(); } - - /** - * Return \e i \e h with \e i in (0,2<sup><i>p</i></sup>] by rounding \e u - * up to the next \ref fixed "fixed" real. Result is in upper interval - * (0,1]. - * - * @tparam RealType the real type of the returned random numbers. - * @tparam prec the precision of the returned random numbers. - * @return the random result. - **********************************************************************/ - template<typename RealType, int prec> RealType FixedU() throw() - { return RealType(1) - Fixed<RealType, prec>(); } - /** - * See documentation for RandomCanonical::FixedU<RealType,prec>(). - * - * @tparam RealType the real type of the returned random numbers. - * @return the random result with the full precision of RealType. - **********************************************************************/ - template<typename RealType> RealType FixedU() throw() - { return FixedU<RealType, std::numeric_limits<RealType>::digits>(); } - /** - * See documentation for RandomCanonical::FixedU<RealType,prec>(). - * - * @return the random double. - **********************************************************************/ - double FixedU() throw() { return FixedU<double>(); } - - /** - * Return \e i \e h with \e i in [0,2<sup><i>p</i></sup>] by rounding \e u - * to the nearest \ref fixed "fixed" real. Result is in nearest interval - * [0,1]. The probability of returning interior values is <i>h</i> while - * the probability of returning the endpoints is <i>h</i>/2. - * - * @tparam RealType the real type of the returned random numbers. - * @tparam prec the precision of the returned random numbers. - * @return the random result. - **********************************************************************/ - template<typename RealType, int prec> RealType FixedN() throw() { - const RealType x = Fixed<RealType, prec>(); - return x || Boolean() ? x : RealType(1); - } - /** - * See documentation for RandomCanonical::FixedN<RealType,prec>(). - * - * @tparam RealType the real type of the returned random numbers. - * @return the random result with the full precision of RealType. - **********************************************************************/ - template<typename RealType> RealType FixedN() throw() - { return FixedN<RealType, std::numeric_limits<RealType>::digits>(); } - /** - * See documentation for RandomCanonical::FixedN<RealType,prec>(). - * - * @return the random double. - **********************************************************************/ - double FixedN() throw() { return FixedN<double>(); } - - /** - * Return \e i \e h with \e i in [-2<sup><i>p</i></sup>, - * 2<sup><i>p</i></sup>] by rounding 2\e u - 1 to the nearest \ref fixed - * "fixed" real. Result is in wide interval [-1,1]. The probability of - * returning interior values is <i>h</i>/2 while the probability of - * returning the endpoints is <i>h</i>/4. - * - * @tparam RealType the real type of the returned random numbers. - * @tparam prec the precision of the returned random numbers. - * @return the random result. - **********************************************************************/ - template<typename RealType, int prec> RealType FixedW() throw() { - // Random reals in [-1, 1]. Round random in [-1, 1] to nearest multiple - // of 1/2^prec. Results are of the form i/2^prec for integer i in - // [-2^prec,2^prec]. - STATIC_ASSERT(!std::numeric_limits<RealType>::is_integer && - std::numeric_limits<RealType>::radix == 2, - "FixedW(): bad real type RealType"); - STATIC_ASSERT(prec > 0 && prec <= std::numeric_limits<RealType>::digits, - "FixedW(): invalid precision"); - RealType x = -RealType(1); // Accumulator - int s = -1; // How many bits so far - do { - s += width; - x += RandomPower2::shiftf<RealType> - (RealType(Generator::Ran() >> (s > prec ? s - prec : 0)), - -(s > prec ? prec : s)); - } while (s < prec); - return (x + RealType(1) != RealType(0)) || Boolean() ? x : RealType(1); - } - /** - * See documentation for RandomCanonical::FixedW<RealType,prec>(). - * - * @tparam RealType the real type of the returned random numbers. - * @return the random result with the full precision of RealType. - **********************************************************************/ - template<typename RealType> RealType FixedW() throw() - { return FixedW<RealType, std::numeric_limits<RealType>::digits>(); } - /** - * See documentation for RandomCanonical::FixedW<RealType,prec>(). - * - * @return the random double. - **********************************************************************/ - double FixedW() throw() { return FixedW<double>(); } - - /** - * Return (<i>i</i>+1/2)\e h with \e i in [2<sup><i>p</i>-1</sup>, - * 2<sup><i>p</i>-1</sup>) by rounding \e u - 1/2 to nearest offset \ref - * fixed "fixed" real. Result is in symmetric interval (-1/2,1/2). - * - * @tparam RealType the real type of the returned random numbers. - * @tparam prec the precision of the returned random numbers. - * @return the random result. - **********************************************************************/ - template<typename RealType, int prec> RealType FixedS() throw() - { return Fixed<RealType, prec>() - - ( RealType(1) - RandomPower2::pow2<RealType>(-prec) ) / 2; } - /** - * See documentation for RandomCanonical::FixedS<RealType,prec>(). - * - * @tparam RealType the real type of the returned random numbers. - * @return the random result with the full precision of RealType. - **********************************************************************/ - template<typename RealType> RealType FixedS() throw() - { return FixedS<RealType, std::numeric_limits<RealType>::digits>(); } - /** - * See documentation for RandomCanonical::FixedS<RealType,prec>(). - * - * @return the random double. - **********************************************************************/ - double FixedS() throw() { return FixedS<double>(); } - - /** - * Return \e i \e h with \e i in (0,2<sup><i>p</i></sup>) by rounding (1 - - * \e h)\e u up to next \ref fixed "fixed" real. Result is in open - * interval (0,1). - * - * @tparam RealType the real type of the returned random numbers. - * @tparam prec the precision of the returned random numbers. - * @return the random result. - **********************************************************************/ - template<typename RealType, int prec> RealType FixedO() throw() { - // A real of type RealType in (0, 1) with precision prec - STATIC_ASSERT(!std::numeric_limits<RealType>::is_integer && - std::numeric_limits<RealType>::radix == 2, - "FixedO(): bad real type RealType"); - STATIC_ASSERT(prec > 0 && prec <= std::numeric_limits<RealType>::digits, - "FixedO(): invalid precision"); - RealType x; - // Loop executed 2^prec/(2^prec-1) times on average. - do - x = Fixed<RealType, prec>(); - while (x == 0); - return x; - } - /** - * See documentation for RandomCanonical::FixedO<RealType,prec>(). - * - * @tparam RealType the real type of the returned random numbers. - * @return the random result with the full precision of RealType. - **********************************************************************/ - template<typename RealType> RealType FixedO() throw() - { return FixedO<RealType, std::numeric_limits<RealType>::digits>(); } - /** - * See documentation for RandomCanonical::FixedO<RealType,prec>(). - * - * @return the random double. - **********************************************************************/ - double FixedO() throw() { return FixedO<double>(); } - - /** - * Return \e i \e h with \e i in [0,2<sup><i>p</i></sup>] by rounding (1 + - * \e h)\e u down to previous \ref fixed "fixed" real. Result is in closed - * interval [0,1]. - * - * @tparam RealType the real type of the returned random numbers. - * @tparam prec the precision of the returned random numbers. - * @return the random result. - **********************************************************************/ - template<typename RealType, int prec> RealType FixedC() throw() { - // A real of type RealType in [0, 1] with precision prec - STATIC_ASSERT(!std::numeric_limits<RealType>::is_integer && - std::numeric_limits<RealType>::radix == 2, - "FixedC(): bad real type RealType"); - STATIC_ASSERT(prec > 0 && prec <= std::numeric_limits<RealType>::digits, - "FixedC(): invalid precision"); - if (prec < width) { - // Sample an integer in [0, n) where n = 2^prec + 1. This uses the - // same logic as Unsigned(n - 1). However, unlike Unsigned, there - // doesn't seem to be much of a penalty for the 64-bit arithmetic here - // when result_type = unsigned long long. Presumably this is because - // the compiler can do some of the arithmetic. - const result_type - n = (result_type(1) << (prec < width ? prec : 0)) + 1, - // Computing this instead of 2^width/n suffices, because of the form - // of n. - r = Generator::mask / n, - m = r * n; - result_type u; - do - u = Generator::Ran(); - while (u >= m); - // u is rv in [0, r * n) - return RandomPower2::shiftf<RealType>(RealType(u / r), -prec); - // Could also special case prec < 64, using Ran64(). However the - // general code below is faster. - } else { // prec >= width - // Synthesize a prec+1 bit random, Y, width bits at a time. If number - // is odd, return Fixed<RealType, prec>() (w prob 1/2); else if number - // is zero, return 1 (w prob 1/2^(prec+1)); else repeat. Normalizing - // probabilities on returned results we find that Fixed<RealType, - // prec>() is returned with prob 2^prec/(2^prec+1), and 1 is return - // with prob 1/(2^prec+1), as required. Loop executed twice on average - // and so consumes 2rvs more than rvs for Fixed<RealType, prec>(). As - // in FloatZ, do NOT try to save on calls to Ran() by using the - // leftover bits from Fixed. - while (true) { - // If prec + 1 < width then mask x with (1 << prec + 1) - 1 - const result_type x = Generator::Ran(); // Low width bits of Y - if (x & 1u) // Y odd? - return Fixed<RealType, prec>(); // Prob 1/2 on each loop iteration - if (x) - continue; // Y nonzero - int s = prec + 1 - width; // Bits left to check (s >= 0) - while (true) { - if (s <= 0) // We're done. Y = 0 - // Prob 1/2^(prec+1) on each loop iteration - return RealType(1); // We get here once every 60000 yrs (p = 64)! - // Check the next min(s, width) bits. - if (Generator::Ran() >> (s > width ? 0 : width - s)) - break; - s -= width; // Decrement s - } - } - } - } - /** - * See documentation for RandomCanonical::FixedC<RealType,prec>(). - * - * @tparam RealType the real type of the returned random numbers. - * @return the random result with the full precision of RealType. - **********************************************************************/ - template<typename RealType> RealType FixedC() throw() - { return FixedC<RealType, std::numeric_limits<RealType>::digits>(); } - /** - * See documentation for RandomCanonical::FixedC<RealType,prec>(). - * - * @return the random double. - **********************************************************************/ - double FixedC() throw() { return FixedC<double>(); } - ///@} - - /** - * \name Member functions returning real floating-point numbers - **********************************************************************/ - ///@{ - - // The floating results produces results on a floating scale. Here the - // separation between possible results is smaller for smaller numbers. - - /** - * In the description of the functions FloatX returning \ref floating - * "floating-point" numbers, \e u is a random real number uniformly - * distributed in (0, 1), \e p is the precision, and \e e is the exponent - * range. Each of the functions come in three variants, e.g., - * - RandomCanonical::Float<RealType,p,e>() --- return \ref floating - * "floating-point" real of type RealType, precision \e p, and exponent - * range \e e; - * - RandomCanonical::Float<RealType>() --- as above with \e p = - * std::numeric_limits<RealType>::digits and \e e = - * - std::numeric_limits<RealType>::min_exponent; - * - RandomCanonical::Float() --- as above with RealType = double. - * - * See the \ref reals "summary" for a comparison of the functions. - * - * Return result is in default interval [0,1) by rounding \e u down - * to the previous \ref floating "floating" real. - * - * @tparam RealType the real type of the returned random numbers. - * @tparam prec the precision of the returned random numbers. - * @tparam erange the exponent range of the returned random numbers. - * @return the random result. - **********************************************************************/ - template<typename RealType, int prec, int erange> RealType Float() throw() - { return FloatZ<RealType, prec, erange, false>(0, 0); } - /** - * See documentation for RandomCanonical::Float<RealType,prec,erange>(). - * - * @tparam RealType the real type of the returned random numbers. - * @return the random result with the full precision of RealType. - **********************************************************************/ - template<typename RealType> RealType Float() throw() { - return Float<RealType, std::numeric_limits<RealType>::digits, - -std::numeric_limits<RealType>::min_exponent>(); - } - /** - * See documentation for RandomCanonical::Float<RealType,prec,erange>(). - * - * @return the random double. - **********************************************************************/ - double Float() throw() { return Float<double>(); } - - /** - * Return result is in upper interval (0,1] by round \e u up to the - * next \ref floating "floating" real. - * - * @tparam RealType the real type of the returned random numbers. - * @tparam prec the precision of the returned random numbers. - * @tparam erange the exponent range of the returned random numbers. - * @return the random result. - **********************************************************************/ - template<typename RealType, int prec, int erange> RealType FloatU() throw() - { return FloatZ<RealType, prec, erange, true>(0, 0); } - /** - * See documentation for RandomCanonical::FloatU<RealType,prec,erange>(). - * - * @tparam RealType the real type of the returned random numbers. - * @return the random result with the full precision of RealType. - **********************************************************************/ - template<typename RealType> RealType FloatU() throw() { - return FloatU<RealType, std::numeric_limits<RealType>::digits, - -std::numeric_limits<RealType>::min_exponent>(); - } - /** - * See documentation for RandomCanonical::FloatU<RealType,prec,erange>(). - * - * @return the random double. - **********************************************************************/ - double FloatU() throw() { return FloatU<double>(); } - - /** - * Return result is in nearest interval [0,1] by rounding \e u to - * the nearest \ref floating "floating" real. - * - * @tparam RealType the real type of the returned random numbers. - * @tparam prec the precision of the returned random numbers. - * @tparam erange the exponent range of the returned random numbers. - * @return the random result. - **********************************************************************/ - template<typename RealType, int prec, int erange> RealType FloatN() - throw() { - // Use Float or FloatU each with prob 1/2, i.e., return Boolean() ? - // Float() : FloatU(). However, rather than use Boolean(), we pick the - // high bit off a Ran() and pass the rest of the number to FloatZ to use. - // This saves 1/2 a call to Ran(). - const result_type x = Generator::Ran(); - return x >> (width - 1) ? // equivalent to Boolean() - // Float<RealType, prec, erange>() - FloatZ<RealType, prec, erange, false>(width - 1, x) : - // FloatU<RealType, prec, erange>() - FloatZ<RealType, prec, erange, true>(width - 1, x); - } - /** - * See documentation for RandomCanonical::FloatN<RealType,prec,erange>(). - * - * @tparam RealType the real type of the returned random numbers. - * @return the random result with the full precision of RealType. - **********************************************************************/ - template<typename RealType> RealType FloatN() throw() { - return FloatN<RealType, std::numeric_limits<RealType>::digits, - -std::numeric_limits<RealType>::min_exponent>(); - } - /** - * See documentation for RandomCanonical::FloatN<RealType,prec,erange>(). - * - * @return the random double. - **********************************************************************/ - double FloatN() throw() { return FloatN<double>(); } - - /** - * Return result is in wide interval [-1,1], by rounding 2\e u - 1 to the - * nearest \ref floating "floating" real. - * - * @tparam RealType the real type of the returned random numbers. - * @tparam prec the precision of the returned random numbers. - * @tparam erange the exponent range of the returned random numbers. - * @return the random result. - **********************************************************************/ - template<typename RealType, int prec, int erange> - RealType FloatW() throw() { - const result_type x = Generator::Ran(); - const int y = int(x >> (width - 2)); - return (1 - (y & 2)) * // Equiv to (Boolean() ? -1 : 1) * - ( y & 1 ? // equivalent to Boolean() - // Float<RealType, prec, erange>() - FloatZ<RealType, prec, erange, false>(width - 2, x) : - // FloatU<RealType, prec, erange>() - FloatZ<RealType, prec, erange, true>(width - 2, x) ); - } - /** - * See documentation for RandomCanonical::FloatW<RealType,prec,erange>(). - * - * @tparam RealType the real type of the returned random numbers. - * @return the random result with the full precision of RealType. - **********************************************************************/ - template<typename RealType> RealType FloatW() throw() { - return FloatW<RealType, std::numeric_limits<RealType>::digits, - -std::numeric_limits<RealType>::min_exponent>(); - } - /** - * See documentation for RandomCanonical::FloatW<RealType,prec,erange>(). - * - * @return the random double. - **********************************************************************/ - double FloatW() throw() { return FloatW<double>(); } - ///@} - - /** - * \name Member functions returning booleans - **********************************************************************/ - ///@{ - /** - * A coin toss. Equivalent to RandomCanonical::Integer<bool>(). - * - * @return true with probability 1/2. - **********************************************************************/ - bool Boolean() throw() { return Generator::Ran() & 1u; } - - /** - * The Bernoulli distribution, true with probability \e p. False if \e p - * <= 0; true if \e p >= 1. Equivalent to RandomCanonical::Float() < \e p, - * but typically faster. - * - * @tparam NumericType the type (integer or real) of the argument. - * @param[in] p the probability. - * @return true with probability \e p. - **********************************************************************/ - template<typename NumericType> bool Prob(NumericType p) throw(); - - /** - * True with probability <i>m</i>/<i>n</i>. False if \e m <= 0 or \e n < - * 0; true if \e m >= \e n. With real types, Prob(\e x, \e y) is exact but - * slower than Prob(<i>x</i>/<i>y</i>). - * - * @tparam NumericType the type (integer or real) of the argument. - * @param[in] m the numerator of the probability. - * @param[in] n the denominator of the probability. - * @return true with probability <i>m</i>/<i>n</i>. - **********************************************************************/ - template<typename NumericType> - bool Prob(NumericType m, NumericType n) throw(); - ///@} - - // Bits - - /** - * \name Functions returning bitsets - * These return random bits in a std::bitset. - **********************************************************************/ - ///@{ - - /** - * Return \e nbits random bits - * - * @tparam nbits the number of bits in the bitset. - * @return the random bitset. - **********************************************************************/ - template<int nbits> std::bitset<nbits> Bits() throw(); - - ///@} - - /** - * A "global" random number generator (not thread-safe!), initialized with - * a fixed seed []. - **********************************************************************/ - static RANDOM_EXPORT RandomCanonical Global; - - private: - typedef RandomSeed::u32 u32; - typedef RandomSeed::u64 u64; - /** - * A helper for Integer(\e n). A random unsigned integer in [0, \e n]. If - * \e n >= 2<sup>32</sup>, this \e must be invoked with \e onep = false. - * Otherwise, it \e should be invoked with \e onep = true. - **********************************************************************/ - template<typename UIntT> - typename UIntT::type Unsigned(typename UIntT::type n) throw(); - - /** - * A helper for Float and FloatU. Produces \e up ? FloatU() : Float(). On - * entry the low \e b bits of \e m are usable random bits. - **********************************************************************/ - template<typename RealType, int prec, int erange, bool up> - RealType FloatZ(int b, result_type m) throw(); - - /** - * The one-argument version of Prob for real types - **********************************************************************/ - template<typename RealType> bool ProbF(RealType z) throw(); - /** - * The two-argument version of Prob for real types - **********************************************************************/ - template<typename RealType> bool ProbF(RealType x, RealType y) throw(); - }; - - template<class Generator> - RandomCanonical<Generator>::RandomCanonical(seed_type n) - : Generator(n) { - // Compile-time checks on real types -#if HAVE_LONG_DOUBLE - STATIC_ASSERT(std::numeric_limits<float>::radix == 2 && - std::numeric_limits<double>::radix == 2 && - std::numeric_limits<long double>::radix == 2, - "RandomCanonical: illegal floating type"); - STATIC_ASSERT(0 <= std::numeric_limits<float>::digits && - std::numeric_limits<float>::digits <= - std::numeric_limits<double>::digits && - std::numeric_limits<double>::digits <= - std::numeric_limits<long double>::digits, - "RandomCanonical: inconsistent floating precision"); -#else - STATIC_ASSERT(std::numeric_limits<float>::radix == 2 && - std::numeric_limits<double>::radix == 2, - "RandomCanonical: illegal floating type"); - STATIC_ASSERT(0 <= std::numeric_limits<float>::digits && - std::numeric_limits<float>::digits <= - std::numeric_limits<double>::digits, - "RandomCanonical: inconsistent floating precision"); -#endif -#if HAVE_LONG_DOUBLE -#endif -#if RANDOMLIB_POWERTABLE - // checks on power2 -#if HAVE_LONG_DOUBLE - STATIC_ASSERT(std::numeric_limits<long double>::digits == - RANDOMLIB_LONGDOUBLEPREC, - "RandomPower2: RANDOMLIB_LONGDOUBLEPREC incorrect"); -#else - STATIC_ASSERT(std::numeric_limits<double>::digits == - RANDOMLIB_LONGDOUBLEPREC, - "RandomPower2: RANDOMLIB_LONGDOUBLEPREC incorrect"); -#endif - // Make sure table hasn't underflowed - STATIC_ASSERT(RandomPower2::minpow >= - std::numeric_limits<float>::min_exponent - - (RANDOMLIB_HASDENORM(float) ? - std::numeric_limits<float>::digits : 1), - "RandomPower2 table underflow"); - STATIC_ASSERT(RandomPower2::maxpow >= RandomPower2::minpow + 1, - "RandomPower2 table empty"); - // Needed by RandomCanonical::Fixed<long double>() -#if HAVE_LONG_DOUBLE - STATIC_ASSERT(RandomPower2::minpow <= - -std::numeric_limits<long double>::digits, - "RandomPower2 minpow not small enough for long double"); -#else - STATIC_ASSERT(RandomPower2::minpow <= - -std::numeric_limits<double>::digits, - "RandomPower2 minpow not small enough for double"); -#endif - // Needed by ProbF - STATIC_ASSERT(RandomPower2::maxpow - width >= 0, - "RandomPower2 maxpow not large enough for ProbF"); -#endif - // Needed for RandomCanonical::Bits() - STATIC_ASSERT(2 * std::numeric_limits<unsigned long>::digits - width >= 0, - "Bits<n>(): unsigned long too small"); - } - - template<class Generator> template<typename IntType> - inline IntType RandomCanonical<Generator>::Integer() throw() { - // A random integer of type IntType in [min(IntType), max(IntType)]. - STATIC_ASSERT(std::numeric_limits<IntType>::is_integer && - std::numeric_limits<IntType>::radix == 2, - "Integer: bad integer type IntType"); - const int d = std::numeric_limits<IntType>::digits + - std::numeric_limits<IntType>::is_signed; // Include the sign bit - // Check that we have enough digits in Ran64 - STATIC_ASSERT(d > 0 && d <= 64, "Integer: bad bit-size"); - if (d <= width) - return IntType(Generator::Ran()); - else // d <= 64 - return IntType(Generator::Ran64()); - } - - template<class Generator> template<typename UIntT> - inline typename UIntT::type - RandomCanonical<Generator>::Unsigned(typename UIntT::type n) throw() { - // A random unsigned in [0, n]. In n fits in 32-bits, call with UIntType = - // u32 and onep = true else call with UIntType = u64 and onep = false. - // There are a few cases (e.g., n = 0x80000000) where on a 64-bit machine - // with a 64-bit Generator it would be quicker to call this with UIntType = - // result_type and invoke Ran(). However this speed advantage disappears - // if the argument isn't a compile time constant. - // - // Special case n == 0 is handled by the callers of Unsigned. The - // following is to guard against a division by 0 in the return statement - // (but it shouldn't happen). - n = n ? n : 1U; // n >= 1 - // n1 = n + 1, but replace overflowed value by 1. Overflow occurs, e.g., - // when n = u32::mask and then we have r1 = 0, m = u32::mask. - const typename UIntT::type n1 = ~n ? n + 1U : 1U; - // "Ratio method". Find m = r * n1 - 1, s.t., 0 < (q - n1 ) < m <= q, - // where q = max(UIntType), and sample in u in [0, m] and return u / r. If - // onep then we use Ran32() else Rand64(). - const typename UIntT::type - // r = floor((q + 1)/n1), r1 = r - 1, avoiding overflow. Actually - // overflow can occur if std::numeric_limits<u32>::digits == 64, because - // then we can have onep && n > U32_MASK. This is however ruled out by - // the callers to Unsigned. (If Unsigned is called in this way, the - // results are bogus, but there is no error condition.) - r1 = ((UIntT::width == 32 ? typename UIntT::type(u32::mask) : - typename UIntT::type(u64::mask)) - n) / n1, - m = r1 * n1 + n; // m = r * n1 - 1, avoiding overflow - // Here r1 in [0, (q-1)/2], m in [(q+1)/2, q] - typename UIntT::type u; // Find a random number in [0, m] - do - // For small n1, this is executed once (since m is nearly q). In the - // worst case the loop is executed slightly less than twice on average. - u = UIntT::width == 32 ? typename UIntT::type(Generator::Ran32()) : - typename UIntT::type(Generator::Ran64()); - while (u > m); - // Now u is in [0, m] = [0, r * n1), so u / r is in [0, n1) = [0, n]. An - // alternative unbiased method would be u % n1; but / appears to be faster. - return u / (r1 + 1U); - } - - template<class Generator> template<typename IntType> - inline IntType RandomCanonical<Generator>::Integer(IntType n) throw() { - // A random integer of type IntType in [0, n). If n == 0, treat as - // max(IntType) + 1. If n < 0, treat as 1 and return 0. - // N.B. Integer<IntType>(0) is equivalent to Integer<IntType>() for - // unsigned types. For signed types, the former returns a non-negative - // result and the latter returns a result in the full range. - STATIC_ASSERT(std::numeric_limits<IntType>::is_integer && - std::numeric_limits<IntType>::radix == 2, - "Integer(n): bad integer type IntType"); - const int d = std::numeric_limits<IntType>::digits; - // Check that we have enough digits in Ran64 - STATIC_ASSERT(d > 0 && d <= 64, "Integer(n): bad bit-size"); - return n > IntType(1) ? - (d <= 32 || n - 1 <= IntType(u32::mask) ? - IntType(Unsigned<u32>(u32::type(n - 1))) : - IntType(Unsigned<u64>(u64::type(n - 1)))) : - ( n ? IntType(0) : // n == 1 || n < 0 - Integer<IntType, d>()); // n == 0 - } - - template<class Generator> template<typename IntType> - inline IntType RandomCanonical<Generator>::IntegerC(IntType n) throw() { - // A random integer of type IntType in [0, n] - STATIC_ASSERT(std::numeric_limits<IntType>::is_integer && - std::numeric_limits<IntType>::radix == 2, - "IntegerC(n): bad integer type IntType"); - const int d = std::numeric_limits<IntType>::digits; - // Check that we have enough digits in Ran64 - STATIC_ASSERT(d > 0 && d <= 64, "IntegerC(n): bad bit-size"); - return n > IntType(0) ? - (d <= 32 || n <= IntType(u32::mask) ? - IntType(Unsigned<u32>(u32::type(n))) : - IntType(Unsigned<u64>(u64::type(n)))) - : IntType(0); // n <= 0 - } - - template<class Generator> template<typename IntType> - inline IntType RandomCanonical<Generator>::IntegerC(IntType m, IntType n) - throw() { - // A random integer of type IntType in [m, n] - STATIC_ASSERT(std::numeric_limits<IntType>::is_integer && - std::numeric_limits<IntType>::radix == 2, - "IntegerC(m,n): bad integer type IntType"); - const int d = std::numeric_limits<IntType>::digits + - std::numeric_limits<IntType>::is_signed; // Include sign bit - // Check that we have enough digits in Ran64 - STATIC_ASSERT(d > 0 && d <= 64, "IntegerC(m,n): bad bit-size"); - // The unsigned subtraction, n - m, avoids the underflow that is possible - // in the signed operation. - return m + (n <= m ? 0 : - d <= 32 ? - IntType(IntegerC<u32::type>(u32::type(n) - u32::type(m))) : - IntType(IntegerC<u64::type>(u64::type(n) - u64::type(m)))); - } - - template<class Generator> - template<typename RealType, int prec, int erange, bool up> inline - RealType RandomCanonical<Generator>::FloatZ(int b, result_type m) throw() { - // Produce up ? FloatU() : Float(). On entry the low b bits of m are - // usable random bits. - STATIC_ASSERT(!std::numeric_limits<RealType>::is_integer && - std::numeric_limits<RealType>::radix == 2, - "FloatZ: bad real type RealType"); - STATIC_ASSERT(prec > 0 && prec <= std::numeric_limits<RealType>::digits, - "FloatZ: invalid precision"); - STATIC_ASSERT(erange >= 0, "FloatZ: invalid exponent range"); - // With subnormals: condition that smallest number is representable - STATIC_ASSERT(!RANDOMLIB_HASDENORM(RealType) || - // Need 1/2^(erange+prec) > 0 - prec + erange <= std::numeric_limits<RealType>::digits - - std::numeric_limits<RealType>::min_exponent, - "FloatZ: smallest number cannot be represented"); - // Without subnormals :condition for no underflow in while loop - STATIC_ASSERT(RANDOMLIB_HASDENORM(RealType) || - // Need 1/2^(erange+1) > 0 - erange <= - std::numeric_limits<RealType>::min_exponent, - "FloatZ: underflow possible"); - - // Simpler (but slower) version of FloatZ. However this method cannot - // handle the full range of exponents and, in addition, is slower on - // average. - // template<typename RealType, int prec, int erange, bool up> - // RealType FloatZ() { - // RealType x = Fixed<RealType, erange + 1>(); - // int s; // Determine exponent (-erange <= s <= 0) - // frexp(x, &s); // Prob(s) = 2^(s-1) - // // Scale number in [1,2) by 2^(s-1). If x == 0 scale number in [0,1). - // return ((up ? FixedU<RealType, prec - 1>() : - // Fixed<RealType, prec - 1>()) + (x ? 1 : 0)) * - // RandomPower2::pow2<RealType>(s - 1); - // } - // - // Use {a, b} to denote the inteval: up ? (a, b] : [a, b) - // - // The code produces the number as - // - // Interval count prob = spacing - // {1,2} / 2 2^(prec-1) 1/2^prec - // {1,2} / 2^s 2^(prec-1) 1/2^(prec+s-1) for s = 2..erange+1 - // {0,1} / 2^(erange+1) 2^(prec-1) 1/2^(prec+erange) - - // Generate prec bits in {0, 1} - RealType x = up ? FixedU<RealType, prec>() : Fixed<RealType, prec>(); - // Use whole interval if erange == 0 and handle the interval {1/2, 1} - if (erange == 0 || (up ? x > RealType(0.5) : x >= RealType(0.5))) - return x; - x += RealType(0.5); // Shift remaining portion to {1/2, 1} - if (b == 0) { - m = Generator::Ran(); // Random bits - b = width; // Bits available in m - } - int sm = erange; // sm = erange - s + 2 - // Here x in {1, 2} / 2, prob 1/2 - do { // s = 2 thru erange+1, sm = erange thru 1 - x /= 2; - if (m & 1u) - return x; // x in {1, 2} / 2^s, prob 1/2^s - if (--b) - m >>= 1; - else { - m = Generator::Ran(); - b = width; - } - } while (--sm); - // x in {1, 2} / 2^(erange+1), prob 1/2^(erange+1). Don't worry about the - // possible overhead of the calls to pow here. We rarely get here. - if (RANDOMLIB_HASDENORM(RealType) || // subnormals allowed - // No subnormals but smallest number still representable - prec + erange <= -std::numeric_limits<RealType>::min_exponent + 1 || - // Possibility of underflow, so have to test on x. Here, we have -prec - // + 1 < erange + min_exp <= 0 so pow2 can be used - x >= (RealType(1) + - RandomPower2::pow2<RealType> - (erange + std::numeric_limits<RealType>::min_exponent)) * - (erange + 1 > -RandomPower2::minpow ? - std::pow(RealType(2), - erange - 1) : - RandomPower2::pow2<RealType>(- erange - 1))) - // shift x to {0, 1} / 2^(erange+1) - // Use product of pow's since max(erange + 1) = - // std::numeric_limits<RealType>::digits - - // std::numeric_limits<RealType>::min_exponent and pow may underflow - return x - - (erange + 1 > -RandomPower2::minpow ? - std::pow(RealType(2), -(erange + 1)/2) * - std::pow(RealType(2), -(erange + 1) + (erange + 1)/2) : - RandomPower2::pow2<RealType>(- erange - 1)); - else - return up ? // Underflow to up ? min() : 0 - // pow is OK here. - std::pow(RealType(2), std::numeric_limits<RealType>::min_exponent - 1) - : RealType(0); - } - - /// \cond SKIP - // True with probability n. Since n is an integer this is equivalent to n > - // 0. - template<class Generator> template<typename IntType> - inline bool RandomCanonical<Generator>::Prob(IntType n) throw() { - STATIC_ASSERT(std::numeric_limits<IntType>::is_integer, - "Prob(n): invalid integer type IntType"); - return n > 0; - } - /// \endcond - - // True with probability p. true if p >= 1, false if p <= 0 or isnan(p). - template<class Generator> template<typename RealType> - inline bool RandomCanonical<Generator>::ProbF(RealType p) throw() { - // Simulate Float<RealType>() < p. The definition involves < (instead of - // <=) because Float<RealType>() is in [0,1) so it is "biased downwards". - // Instead of calling Float<RealType>(), we generate only as many bits as - // necessary to determine the result. This makes the routine considerably - // faster than Float<RealType>() < x even for type float. Compared with - // the inexact Fixed<RealType>() < p, this is about 20% slower with floats - // and 20% faster with doubles and long doubles. - STATIC_ASSERT(!std::numeric_limits<RealType>::is_integer && - std::numeric_limits<RealType>::radix == 2, - "ProbF(p): invalid real type RealType"); - // Generate Real() c bits at a time where c is chosen so that cast doesn't - // loose any bits and so that it uses up just one rv. - const int c = std::numeric_limits<RealType>::digits > width ? - width : std::numeric_limits<RealType>::digits; - STATIC_ASSERT(c > 0, "ProbF(p): Illegal chunk size"); - const RealType mult = RandomPower2::pow2<RealType>(c); - // A recursive definition: - // - // return p > RealType(0) && - // (p >= RealType(1) || - // ProbF(mult * p - RealType(Integer<result_type, c>()))); - // - // Pre-loop tests needed to avoid overflow - if (!(p > RealType(0))) // Ensure false if isnan(p) - return false; - else if (p >= RealType(1)) - return true; - do { // Loop executed slightly more than once. - // Here p is in (0,1). Write Fixed() = (X + y)/mult where X is an - // integer in [0, mult) and y is a real in [0,1). Then Fixed() < p - // becomes p' > y where p' = p * mult - X. - p *= mult; // Form p'. Multiplication is exact - p -= RealType(Integer<result_type, c>()); // Also exact - if (p <= RealType(0)) - return false; // If p' <= 0 the result is definitely false. - // Exit if p' >= 1; the result is definitely true. Otherwise p' is in - // (0,1) and the result is true with probability p'. - } while (p < RealType(1)); - return true; - } - - /// \cond SKIP - // True with probability m/n (ratio of integers) - template<class Generator> template<typename IntType> - inline bool RandomCanonical<Generator>::Prob(IntType m, IntType n) throw() { - STATIC_ASSERT(std::numeric_limits<IntType>::is_integer, - "Prob(m,n): invalid integer type IntType"); - // Test n >= 0 without triggering compiler warning when n = unsigned - return m > 0 && (n > 0 || n == 0) && (m >= n || Integer<IntType>(n) < m); - } - /// \endcond - - // True with probability x/y (ratio of reals) - template<class Generator> template<typename RealType> - inline bool RandomCanonical<Generator>::ProbF(RealType x, RealType y) - throw() { - STATIC_ASSERT(!std::numeric_limits<RealType>::is_integer && - std::numeric_limits<RealType>::radix == 2, - "ProbF(x,y): invalid real type RealType"); - if (!(x > RealType(0) && y >= RealType(0))) // Do the trivial cases - return false; // Also if either x or y is a nan - else if (x >= y) - return true; - // Now 0 < x < y - int ex, ey; // Extract exponents - x = std::frexp(x, &ex); - y = std::frexp(y, &ey); - // Now 0.5 <= x,y < 1 - if (x > y) { - x *= RealType(0.5); - ++ex; - } - int s = ey - ex; - // Now 0.25 < x < y < 1, s >= 0, 0.5 < x/y <= 1 - // Return true with prob 2^-s * x/y - while (s > 0) { // With prob 1 - 2^-s return false - // Check the next min(s, width) bits. - if (Generator::Ran() >> (s > width ? 0 : width - s)) - return false; - s -= width; - } - // Here with prob 2^-s - const int c = std::numeric_limits<RealType>::digits > width ? - width : std::numeric_limits<RealType>::digits; - STATIC_ASSERT(c > 0, "ProbF(x,y): invalid chunk size"); - const RealType mult = RandomPower2::pow2<RealType>(c); - // Generate infinite precision z = Real(). - // As soon as we know z > y, start again - // As soon as we know z < x, return true - // As soon as we know x < z < y, return false - while (true) { // Loop executed 1/x on average - double xa = x, ya = y; - while (true) { // Loop executed slightly more than once - // xa <= ya, ya > 0, xa < 1. - // Here (xa,ya) are in (0,1). Write Fixed() = (X + y)/mult where X is - // an integer in [0, mult) and y is a real in [0,1). Then Fixed() < z - // becomes z' > y where z' = z * mult - X. - const RealType d = RealType(Integer<result_type, c>()); - if (ya < RealType(1)) { - ya *= mult; // Form ya' - ya -= d; - if (ya <= RealType(0)) - break; // z > y, start again - } - if (xa > RealType(0)) { - xa *= mult; // From xa' - xa -= d; - if (xa >= RealType(1)) - return true; // z < x - } - if (xa <= RealType(0) && ya >= RealType(1)) - return false; // x < z < y - } - } - } - - template<class Generator> template<int nbits> - inline std::bitset<nbits> RandomCanonical<Generator>::Bits() throw() { - // Return nbits random bits - STATIC_ASSERT(nbits >= 0, "Bits<n>(): invalid nbits"); - const int ulbits = std::numeric_limits<bitset_uint_t>::digits; - STATIC_ASSERT(2 * ulbits >= width, - "Bits<n>(): integer constructor type too narrow"); - std::bitset<nbits> b; - int m = nbits; - - while (m > 0) { - result_type x = Generator::Ran(); - if (m < nbits) - b <<= (width > ulbits ? width - ulbits : width); - if (width > ulbits && // x doesn't fit into a bitset_uint_t - // But on the first time through the loop the most significant bits - // may not be needed. - (nbits > ((nbits-1)/width) * width + ulbits || m < nbits)) { - // Handle most significant width - ulbits bits. - b |= (bitset_uint_t)(x >> (width > ulbits ? ulbits : 0)); - b <<= ulbits; - } - // Bitsets can be constructed from a bitset_uint_t. - b |= (bitset_uint_t)(x); - m -= width; - } - return b; - } - /// \cond SKIP - - // The specialization of Integer<bool> is required because bool(int) in the - // template definition will test for non-zeroness instead of returning the - // low bit. -#if HAVE_LONG_DOUBLE -#define RANDOMCANONICAL_SPECIALIZE(RandomType) \ - template<> template<> \ - inline bool RandomType::Integer<bool>() \ - throw() { return Boolean(); } \ - RANDOMCANONICAL_SPECIALIZE_PROB(RandomType, float) \ - RANDOMCANONICAL_SPECIALIZE_PROB(RandomType, double) \ - RANDOMCANONICAL_SPECIALIZE_PROB(RandomType, long double) -#else -#define RANDOMCANONICAL_SPECIALIZE(RandomType) \ - template<> template<> \ - inline bool RandomType::Integer<bool>() \ - throw() { return Boolean(); } \ - RANDOMCANONICAL_SPECIALIZE_PROB(RandomType, float) \ - RANDOMCANONICAL_SPECIALIZE_PROB(RandomType, double) -#endif - - // Connect Prob(p) with ProbF(p) for all real types - // Connect Prob(x, y) with ProbF(x, y) for all real types -#define RANDOMCANONICAL_SPECIALIZE_PROB(RandomType, RealType) \ - template<> template<> \ - inline bool RandomType::Prob<RealType>(RealType p) \ - throw() { return ProbF<RealType>(p); } \ - template<> template<> \ - inline bool RandomType::Prob<RealType>(RealType x, RealType y) \ - throw() { return ProbF<RealType>(x, y); } - - RANDOMCANONICAL_SPECIALIZE(RandomCanonical<MRandomGenerator32>) - RANDOMCANONICAL_SPECIALIZE(RandomCanonical<MRandomGenerator64>) - RANDOMCANONICAL_SPECIALIZE(RandomCanonical<SRandomGenerator32>) - RANDOMCANONICAL_SPECIALIZE(RandomCanonical<SRandomGenerator64>) - -#undef RANDOMCANONICAL_SPECIALIZE -#undef RANDOMCANONICAL_SPECIALIZE_PROB - - /// \endcond - - /** - * Hook XRandomNN to XRandomGeneratorNN - **********************************************************************/ - typedef RandomCanonical<MRandomGenerator32> MRandom32; - typedef RandomCanonical<MRandomGenerator64> MRandom64; - typedef RandomCanonical<SRandomGenerator32> SRandom32; - typedef RandomCanonical<SRandomGenerator64> SRandom64; - -} // namespace RandomLib - -namespace std { - - /** - * Swap two RandomCanonicals. This is about 3x faster than the default swap. - **********************************************************************/ - template<class Generator> - void swap(RandomLib::RandomCanonical<Generator>& r, - RandomLib::RandomCanonical<Generator>& s) throw() { - r.swap(s); - } - -} // namespace srd - -#endif // RANDOMLIB_RANDOMCANONICAL_HPP diff --git a/app/RandomLib/RandomEngine.hpp b/app/RandomLib/RandomEngine.hpp deleted file mode 100644 index 87aea6e1828a7158caed32e04655b3e782d5799c..0000000000000000000000000000000000000000 --- a/app/RandomLib/RandomEngine.hpp +++ /dev/null @@ -1,637 +0,0 @@ -/** - * \file RandomEngine.hpp - * \brief Header for RandomEngine. - * - * Copyright (c) Charles Karney (2006-2012) <charles@karney.com> and licensed - * under the MIT/X11 License. For more information, see - * http://randomlib.sourceforge.net/ - **********************************************************************/ - -#if !defined(RANDOMLIB_RANDOMENGINE_HPP) -#define RANDOMLIB_RANDOMENGINE_HPP \ - "$Id: d67488cb6e929362e46dc35e59fbbeaa70467ae9 $" - -#include <RandomLib/RandomSeed.hpp> -#include <RandomLib/RandomAlgorithm.hpp> -#include <RandomLib/RandomMixer.hpp> -#include <limits> -#include <string> -#include <algorithm> -#if defined(HAVE_SSE2) && HAVE_SSE2 && defined(_MSC_VER) && !defined(_WIN64) -#include <new> -#endif - -#if !defined(RANDOMLIB_BUILDING_LIBRARY) && \ - defined(HAVE_BOOST_SERIALIZATION) && HAVE_BOOST_SERIALIZATION -#include <boost/serialization/nvp.hpp> -#include <boost/serialization/split_member.hpp> -#include <boost/serialization/vector.hpp> -#endif - -namespace RandomLib { - /** - * \brief Uniform random number generator. - * - * This implements a generic random number generator. Such a generator - * requires two data holders RandomSeed, to hold the seed, and RandomEngine, - * to hold the state. In addition we need two piece of machinery, a "Mixer" - * to convert the seed into an initial state and an "Algorithm" to advance the - * state. - * - * @tparam Algorithm the random number algorithm. - * @tparam Mixer the way seeds are turned into state. - * - * RandomSeed is responsible for setting and reporting the seed. - * - * Mixer has no state and implements only static methods. It needs to have - * the following public interface - * - typedef mixer_t: a RandomType giving the output type - * - unsigned version: an identifying version number - * - static std::string Name(): an identifying name for the mixer - * - static method SeedToState: converts a seed into n words of state. - * - * Algorithm has no state and implements only static methods. It needs to - * have the following public interface - * - typedef engine_t: a RandomType giving the output type - * - typedef internal_type: a integer type used by Transition. This is - * usually the same as engine_t::type. However it allows the use of - * vector instructions on some platforms. We require that engine_t::type - * and internal_type line up properly in a union so that there is no need - * to convert the data explicitly between internal_type and - * engine_t::type. - * - unsigned version: an identifying version number - * - static std::string Name(): an identifying name for the mixer - * - enum N: the size of the state in units of engine_t. - * - static method Transition: steps the generator forwards or backwards. - * - static method Generate: tempers the state immediately prior to output - * - static method NormalizeState: force the initial state (the result of - * the Mixer) into a legal state. - * - static method CheckState accumulates the checksum for the state into - * check. In addition it throws an exception if the state is bad. - * - * RandomEngine is the glue that holds everything together. It repacks - * the mixer_t data from Mixer into engine_t if necessary. It deals with - * delivering individual random results, stepping the state forwards and - * backwards, leapfrogging the generator, I/O of the generator, etc. - * - * Written by Charles Karney <charles@karney.com> and licensed under the - * MIT/X11 License. For more information, see - * http://randomlib.sourceforge.net/ - **********************************************************************/ - template<class Algorithm, class Mixer> - class RANDOM_EXPORT RandomEngine : public RandomSeed { - private: - /** - * The result RandomType (carried over from the \e Algorithm). - **********************************************************************/ - typedef typename Algorithm::engine_t result_t; - /** - * The RandomType used by the \e Mixer. - **********************************************************************/ - typedef typename Mixer::mixer_t mixer_t; - /** - * The internal_type used by the Algorithm::Transition(). - **********************************************************************/ - typedef typename Algorithm::internal_type engine_type; - public: - /** - * The number of random bits produced by Ran(). - **********************************************************************/ - enum { - width = result_t::width - }; - - /** - * A type large enough to hold \e width bits. This is used for the - * internal state of the generator and the result returned by Ran(). - **********************************************************************/ - typedef typename result_t::type result_type; - - /** - * The minimum result returned by Ran() = 0. - **********************************************************************/ - static const result_type min = result_t::min; - - /** - * The maximum result returned by Ran() = 2<sup><i>w</i></sup> - 1. - **********************************************************************/ - static const result_type max = result_t::max; - - protected: - - /** - * The mask for the result_t. - **********************************************************************/ - static const result_type mask = result_t::mask; - - private: - /** - * A version number "RandLib0" to ensure safety of Save/Load. The first 7 - * bytes can be regarded as a "signature" and the 8th byte a version - * number. - **********************************************************************/ - static const u64::type version = 0x52616e644c696230ULL; // 'RandLib0' - /** - * Marker for uninitialized object - **********************************************************************/ - static const unsigned UNINIT = 0xffffffffU; - enum { - /** - * The size of the state in units of result_type - **********************************************************************/ - N = Algorithm::N, - /** - * The size of the state in units of mixer_t::type - **********************************************************************/ - NU = (N * width + mixer_t::width - 1) / mixer_t::width, - /** - * The size of the state in units of engine_type. - **********************************************************************/ - NV = N * sizeof(result_type) / sizeof(engine_type) - }; - - /** - * \brief Union for the state. - * - * A union to hold the state in the result_type, mixer_t::type, and - * engine_type representations. - **********************************************************************/ - union { - /** - * the result_type representation returned by Ran() - **********************************************************************/ - result_type _state[N]; - /** - * the mixer_t::type representation returned by Mixer::SeedToState. - **********************************************************************/ - typename mixer_t::type _stateu[NU]; - /** - * the engine_type representation returned by Algorithm::Transition. - **********************************************************************/ - engine_type _statev[NV]; - }; - - /** - * The index for the next random value - **********************************************************************/ - unsigned _ptr; - /** - * How many times has Transition() been called - **********************************************************************/ - long long _rounds; - /** - * Stride for leapfrogging - **********************************************************************/ - unsigned _stride; - - public: - - /** - * \name Constructors - **********************************************************************/ - ///@{ - /** - * Initialize from a vector. Only the low \e 32 bits of each element are - * used. - * - * @tparam IntType the integral type of the elements of the vector. - * @param[in] v the vector of elements. - **********************************************************************/ - template<typename IntType> - explicit RandomEngine(const std::vector<IntType>& v) { Reseed(v); } - /** - * Initialize from a pair of iterators setting seed to [\e a, \e b). The - * iterator must produce results which can be converted into seed_type. - * Only the low \e 32 bits of each element are used. - * - * @tparam InputIterator the type of the iterator. - * @param[in] a the beginning iterator. - * @param[in] b the ending iterator. - **********************************************************************/ - template<typename InputIterator> - RandomEngine(InputIterator a, InputIterator b) { Reseed(a, b); } - /** - * Initialize with seed [\e n]. Only the low \e width bits of \e n are - * used. - * - * @param[in] n the new seed to use. - **********************************************************************/ - explicit RandomEngine(seed_type n) { Reseed(n); } - /** - * Initialize with seed []. This can be followed by a call to Reseed() to - * select a unique seed. - **********************************************************************/ - RandomEngine() { unsigned long s[1]; Reseed(s, s); } - /** - * Initialize from a string. See Reseed(const std::string& s) - * - * @param[in] s the string to be decoded into a seed. - **********************************************************************/ - explicit RandomEngine(const std::string& s) { Reseed(s); } - - ///@} - - /** - * \name Functions for returning random data - **********************************************************************/ - ///@{ - /** - * Return \e width bits of randomness. This is the natural unit of random - * data produced random number generator. - * - * @return the next random number of width \e width. - **********************************************************************/ - result_type Ran() throw() { - if (_ptr >= N) - Next(); - result_type y = _state[_ptr]; - _ptr += _stride; - - return Algorithm::Generate(y); - } - - /** - * Return 32 bits of randomness. - * - * @return a 32-bit random number. - **********************************************************************/ - u32::type Ran32() throw() { - // return width > 32 ? u32::cast(Ran()) : Ran(); - return u32::cast(Ran()); - } - - /** - * Return 64 bits of randomness. - * - * @return a 64-bit random number. - **********************************************************************/ - u64::type Ran64() throw() { - const u64::type x = Ran(); - return width > 32 ? x : u64::cast(Ran()) << (64 - width) | x; - } - - /** - * Return \e width bits of randomness. Result is in [0, - * 2<sup><i>w</i></sup>). (This just calls Ran().) - * - * @return the next random number of width \e width. - **********************************************************************/ - result_type operator()() throw() { return Ran(); } - ///@} - -#if defined(HAVE_SSE2) && HAVE_SSE2 && defined(_MSC_VER) && !defined(_WIN64) - /** - * new operator with alignment (needed for Visual Studio) - **********************************************************************/ - void* operator new(size_t n) { - void* p = _aligned_malloc(n, __alignof(RandomEngine)); - if (p == 0) throw std::bad_alloc(); - return p; - } - - /** - * delete operator with alignment (needed for Visual Studio) - **********************************************************************/ - void operator delete(void* p) { _aligned_free(p); } - - /** - * new[] operator with alignment (needed for Visual Studio) - **********************************************************************/ - void* operator new[](size_t n) { - void* p = _aligned_malloc(n, __alignof(RandomEngine)); - if (p == 0) throw std::bad_alloc(); - return p; - } - - /** - * delete[] operator with alignment (needed for Visual Studio) - **********************************************************************/ - void operator delete[](void* p) { _aligned_free(p); } -#endif - - /** - * \name Comparing Random objects - **********************************************************************/ - ///@{ - /** - * Test equality of two Random objects. This test that the seeds match and - * that they have produced the same number of random numbers. - * - * @param[in] r the RandomEngine object to compare. - * @return true if the RandomEngine objects produce the same results. - **********************************************************************/ - bool operator==(const RandomEngine& r) const throw() - // Ensure that the two Random objects behave the same way. Note however - // that the internal states may still be different, e.g., the following all - // result in Random objects which are == (with Count() == 0) but which all - // have different internal states: - // - // Random r(0); _ptr == UNINIT - // r.StepCount( 1); r.StepCount(-1); _ptr == 0, _rounds == 0 - // r.StepCount(-1); r.StepCount( 1); _ptr == N, _rounds == -1 - { return Count() == r.Count() && _seed == r._seed && - _stride == r._stride; } - /** - * Test inequality of two Random objects. See Random::operator== - * - * @param[in] r the RandomEngine object to compare. - * @return true if the RandomEngine objects produce different results. - **********************************************************************/ - bool operator!=(const RandomEngine& r) const throw() - { return !operator==(r); } - ///@} - - /** - * \name Interchanging Random objects - **********************************************************************/ - ///@{ - /** - * Swap with another Random object. - * - * @param[in,out] t the RandomEngine object to swap with. - **********************************************************************/ - void swap(RandomEngine& t) throw() { - _seed.swap(t._seed); - std::swap(_ptr, t._ptr); - std::swap(_stride, t._stride); - std::swap(_rounds, t._rounds); - std::swap_ranges(_state, _state + N, t._state); - } - ///@} - - /** - * \name Writing to and reading from a stream - **********************************************************************/ - ///@{ - /** - * Save the state of the Random object to an output stream. Format is a - * sequence of unsigned 32-bit integers written either in decimal (\e bin - * false, text format) or in network order with most significant byte first - * (\e bin true, binary format). Data consists of: - * - * - RandomLib magic string + version (2 words) - * - Algorithm version (1 word) - * - Mixer version (1 word) - * - _seed.size() (1 word) - * - _seed data (_seed.size() words) - * - _ptr (1 word) - * - _stride (1 word) - * - if _ptr != UNINIT, _rounds (2 words) - * - if _ptr != UNINIT, _state (N words or 2 N words) - * - checksum - * - * Shortest possible saved result consists of 8 words. This corresponds to - * RandomSeed() = [] and Count() = 0. - * - * @param[in,out] os the output stream. - * @param[in] bin if true (the default) save in binary mode. - **********************************************************************/ - void Save(std::ostream& os, bool bin = true) const; - /** - * Restore the state of the Random object from an input stream. If \e bin, - * read in binary, else use text format. See documentation of - * RandomEngine::Save for the format. Include error checking on data to - * make sure the input has not been corrupted. If an error occurs while - * reading, the Random object is unchanged. - * - * @param[in,out] is the input stream. - * @param[in] bin if true (the default) load in binary mode. - **********************************************************************/ - void Load(std::istream& is, bool bin = true) { - // Read state into temporary so as not to change object on error. - RandomEngine t(is, bin); - _seed.reserve(t._seed.size()); - *this = t; - } - ///@} - - /** - * \name Basic I/O - **********************************************************************/ - ///@{ - /** - * Write the state of a generator to stream \e os as text - * - * @param[in,out] os the output stream. - * @param[in] r the RandomEngine object to be saved. - **********************************************************************/ - friend std::ostream& operator<<(std::ostream& os, const RandomEngine& r) { - r.Save(os, false); - return os; - } - - /** - * Read the state of a generator from stream \e is as text - * - * @param[in,out] is the output stream. - * @param[in] r the RandomEngine object to be loaded. - **********************************************************************/ - friend std::istream& operator>>(std::istream& is, RandomEngine& r) { - r.Load(is, false); - return is; - } - ///@} - - /** - * \name Examining and advancing the Random generator - **********************************************************************/ - ///@{ - /** - * Return the number of random numbers used. This needs to return a long - * long result since it can reasonably exceed 2<sup>31</sup>. (On a 1GHz - * machine, it takes about a minute to produce 2<sup>32</sup> random - * numbers.) More precisely this is the (zero-based) index of the next - * random number to be produced. (This distinction is important when - * leapfrogging is in effect.) - * - * @return the count of random numbers used. - **********************************************************************/ - long long Count() const throw() - { return _ptr == UNINIT ? 0 : _rounds * N + _ptr; } - /** - * Step the generator forwards or backwards so that the value returned - * by Count() is \e n - * - * @param[in] n the new count. - **********************************************************************/ - void SetCount(long long n) throw() { StepCount(n - Count()); } - /** - * Step the generator forward \e n steps. \e n can be negative. - * - * @param[in] n how much to step the generator forward. - **********************************************************************/ - void StepCount(long long n) throw(); - /** - * Resets the sequence. Equivalent to SetCount(0), but works by - * reinitializing the Random object from its seed, rather than by stepping - * the sequence backwards. In addition, this undoes leapfrogging. - **********************************************************************/ - void Reset() throw() { _ptr = UNINIT; _stride = 1; } - ///@} - - /** - * \name Leapfrogging - **********************************************************************/ - ///@{ - /** - * Set leapfrogging stride to a positive number \e n and increment Count() - * by \e k < \e n. If the current Count() is \e i, then normally the next - * 3 random numbers would have (zero-based) indices \e i, \e i + 1, \e i + - * 2, and the new Count() is \e i + 2. However, after SetStride(\e n, \e - * k) the next 3 random numbers have indices \e i + \e k, \e i + \e k + \e - * n, \e i + \e k + 2\e n, and the new Count() is \e i + \e k + 3\e n. - * With leapfrogging in effect, the time to produce raw random numbers is - * roughly proportional to 1 + (\e n - 1)/3. Reseed(...) and Reset() both - * reset the stride back to 1. See \ref parallel for a description of how - * to use this facility. - * - * @param[in] n the stride (default 1). - * @param[in] k the initial increment (default 0). - **********************************************************************/ - void SetStride(unsigned n = 1, unsigned k = 0) { - // Limit stride to UNINIT/2. This catches negative numbers that have - // been cast into unsigned. In reality the stride should be no more than - // 10-100. - if (n == 0 || n > UNINIT/2) - throw RandomErr("RandomEngine: Invalid stride"); - if (k >= n) - throw RandomErr("RandomEngine: Invalid offset"); - _stride = n; - StepCount(k); - } - /** - * Return leapfrogging stride. - * - * *return the string. - **********************************************************************/ - unsigned GetStride() const throw() { return _stride; } - ///@} - - /** - * Tests basic engine. Throws out_of_range errors on bad results. - **********************************************************************/ - static void SelfTest(); - - /** - * Return the name of the generator. This incorporates the names of the \e - * Algorithm and \e Mixer. - * - * @return the nae of the generator. - **********************************************************************/ - static std::string Name() { - return "RandomEngine<" + Algorithm::Name() + "," + Mixer::Name() + ">"; - } - - private: - /** - * Compute initial state from seed - **********************************************************************/ - void Init() throw(); - /** - * The interface to Transition used by Ran(). - **********************************************************************/ - void Next() throw() { - if (_ptr == UNINIT) - Init(); - _rounds += _ptr/N; - Algorithm::Transition(_ptr/N, _statev); - _ptr %= N; - } - - u32::type Check(u64::type v, u32::type e, u32::type m) const; - - static result_type SelfTestResult(unsigned k) throw() { - return 0; - } - - /** - * Read from an input stream. Potentially corrupts object. This private - * constructor is used by RandomEngine::Load so that it can avoid - * corrupting its state on bad input. - **********************************************************************/ - explicit RandomEngine(std::istream& is, bool bin); - -#if !defined(RANDOMLIB_BUILDING_LIBRARY) && \ - defined(HAVE_BOOST_SERIALIZATION) && HAVE_BOOST_SERIALIZATION - friend class boost::serialization::access; - /** - * Save to a boost archive. Boost versioning isn't very robust. (It - * allows a RandomGenerator32 to be read back in as a RandomGenerator64. - * It doesn't interact well with templates.) So we do our own versioning - * and supplement this with a checksum. - **********************************************************************/ - template<class Archive> void save(Archive& ar, const unsigned int) const { - u64::type _version = version; - u32::type _eversion = Algorithm::version, - _mversion = Mixer::version, - _checksum = Check(_version, _eversion, _mversion); - ar & boost::serialization::make_nvp("version" , _version ) - & boost::serialization::make_nvp("eversion", _eversion) - & boost::serialization::make_nvp("mversion", _mversion) - & boost::serialization::make_nvp("seed" , _seed ) - & boost::serialization::make_nvp("ptr" , _ptr ) - & boost::serialization::make_nvp("stride" , _stride ); - if (_ptr != UNINIT) - ar & boost::serialization::make_nvp("rounds", _rounds ) - & boost::serialization::make_nvp("state" , _state ); - ar & boost::serialization::make_nvp("checksum", _checksum); - } - /** - * Load from a boost archive. Do this safely so that the current object is - * not corrupted if the archive is bogus. - **********************************************************************/ - template<class Archive> void load(Archive& ar, const unsigned int) { - u64::type _version; - u32::type _eversion, _mversion, _checksum; - ar & boost::serialization::make_nvp("version" , _version ) - & boost::serialization::make_nvp("eversion", _eversion ) - & boost::serialization::make_nvp("mversion", _mversion ); - RandomEngine<Algorithm, Mixer> t(std::vector<seed_type>(0)); - ar & boost::serialization::make_nvp("seed" , t._seed ) - & boost::serialization::make_nvp("ptr" , t._ptr ) - & boost::serialization::make_nvp("stride" , t._stride ); - if (t._ptr != UNINIT) - ar & boost::serialization::make_nvp("rounds", t._rounds ) - & boost::serialization::make_nvp("state" , t._state ); - ar & boost::serialization::make_nvp("checksum", _checksum ); - if (t.Check(_version, _eversion, _mversion) != _checksum) - throw RandomErr("RandomEngine: Checksum failure"); - _seed.reserve(t._seed.size()); - *this = t; - } - /** - * Glue the boost save and load functionality together -- a bit of boost - * magic. - **********************************************************************/ - template<class Archive> - void serialize(Archive &ar, const unsigned int file_version) - { boost::serialization::split_member(ar, *this, file_version); } -#endif // HAVE_BOOST_SERIALIZATION - - }; - - typedef RandomEngine<MT19937 <Random_u32>, MixerSFMT> MRandomGenerator32; - typedef RandomEngine<MT19937 <Random_u64>, MixerSFMT> MRandomGenerator64; - typedef RandomEngine<SFMT19937<Random_u32>, MixerSFMT> SRandomGenerator32; - typedef RandomEngine<SFMT19937<Random_u64>, MixerSFMT> SRandomGenerator64; - -} // namespace RandomLib - -namespace std { - /** - * Swap two RandomEngines. This is about 3x faster than the default swap. - * - * @tparam Algorithm the algorithm for the RandomEngine. - * @tparam Mixer the mixer for the RandomEngine. - * @param[in,out] r the first RandomEngine to swap. - * @param[in,out] s the second RandomEngine to swap. - **********************************************************************/ - template<class Algorithm, class Mixer> - void swap(RandomLib::RandomEngine<Algorithm, Mixer>& r, - RandomLib::RandomEngine<Algorithm, Mixer>& s) throw() { - r.swap(s); - } - -} // namespace std - -#endif // RANDOMLIB_RANDOMENGINE_HPP diff --git a/app/RandomLib/RandomMixer.hpp b/app/RandomLib/RandomMixer.hpp deleted file mode 100644 index 7a6f395f8c641b86726112c90eccb95cdeaac11d..0000000000000000000000000000000000000000 --- a/app/RandomLib/RandomMixer.hpp +++ /dev/null @@ -1,259 +0,0 @@ -/** - * \file RandomMixer.hpp - * \brief Header for Mixer classes. - * - * Mixer classes convert a seed vector into a random generator state. An - * important property of this method is that "close" seeds should produce - * "widely separated" states. This allows the seeds to be set is some - * systematic fashion to produce a set of uncorrelated random number - * sequences. - * - * Copyright (c) Charles Karney (2006-2011) <charles@karney.com> and licensed - * under the MIT/X11 License. For more information, see - * http://randomlib.sourceforge.net/ - **********************************************************************/ - -#if !defined(RANDOMLIB_RANDOMMIXER_HPP) -#define RANDOMLIB_RANDOMMIXER_HPP \ - "$Id: f0e908cf956c1b0558f8be3fbbc167cc7bbfce0b $" - -#include <vector> -#include <string> -#include <RandomLib/RandomSeed.hpp> - -namespace RandomLib { - - /** - * \brief The original %MT19937 mixing functionality - * - * This implements the functionality of init_by_array in MT19937 - * http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/MT2002/CODES/mt19937ar.c - * and init_by_array64 in MT19937_64 - * http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/VERSIONS/C-LANG/mt19937-64.c - * with the following changes: - * - in the case of an zero-length seed array, behave in the same way if - * MT19937 and MT19937_64 are called without initialization in which case, - * e.g., init_genrand(5489UL) is called. (init_by_array does not allow - * calling with a zero-length seed.) - * - init_by_array64 accepts a seed array of 64-bit unsigned ints. Here with - * seed is an array of 32-bit unsigned ints and these are repacked into - * 64-bit quantities internally using a LSB convention. Thus, to mimic the - * MT19937_64 sample invocation with a seed array {0x12345ULL, 0x23456ULL, - * 0x34567ULL, 0x45678ULL}, MixerMT0<Random_u64>::SeedToState needs to - * be invoked with a seed vector [0x12345UL, 0, 0x23456UL, 0, 0x34567UL, 0, - * 0x45678UL, 0]. (Actually the last 0 is unnecessary.) - * - * The template parameter \e RandomType switches between the 32-bit and - * 64-bit versions. - * - * MixerMT0 is specific to the MT19937 generators and should not be used - * for other generators (e.g., SFMT19937). In addition, MixerMT0 has - * known defects and should only be used to check the operation of the - * MT19937 engines against the original implementation. These defects are - * described in the MixerMT1 which is a modification of MixerMT0 - * which corrects these defects. For production use MixerMT1 or, - * preferably, MixerSFMT should be used. - * - * @tparam RandomType the type of the results, either Random_u32 or - * Random_u64. - **********************************************************************/ - template<class RandomType> class RANDOM_EXPORT MixerMT0 { - public: - /** - * The RandomType controlling the output of MixerMT0::SeedToState - **********************************************************************/ - typedef RandomType mixer_t; - /** - * A version number which should be unique to this RandomMixer. This - * prevents RandomEngine::Load from loading a saved generator with a - * different RandomMixer. Here the version is "MxMT" or "MxMU". - **********************************************************************/ - static const unsigned version = 0x4d784d54UL + (mixer_t::width == 64); - private: - /** - * The unsigned type corresponding to mixer_t. - **********************************************************************/ - typedef typename mixer_t::type mixer_type; - /** - * The mask for mixer_t. - **********************************************************************/ - static const mixer_type mask = mixer_t::mask; - public: - /** - * Mix the seed vector, \e seed, into the state array, \e state, of size \e - * n. - * - * @param[in] seed the input seed vector. - * @param[out] state the generator state. - * @param[in] n the size of the state. - **********************************************************************/ - static void SeedToState(const std::vector<RandomSeed::seed_type>& seed, - mixer_type state[], unsigned n) throw(); - /** - * Return the name of this class. - * - * @return the name. - **********************************************************************/ - static std::string Name() { - return "MixerMT0<Random_u" + - std::string(mixer_t::width == 32 ? "32" : "64") + ">"; - } - private: - static const mixer_type a0 = 5489ULL; - static const mixer_type a1 = 19650218ULL; - static const mixer_type - b = mixer_t::width == 32 ? 1812433253ULL : 6364136223846793005ULL; - static const mixer_type - c = mixer_t::width == 32 ? 1664525ULL : 3935559000370003845ULL; - static const mixer_type - d = mixer_t::width == 32 ? 1566083941ULL : 2862933555777941757ULL; - }; - - /** - * \brief The modified %MT19937 mixing functionality - * - * MixerMT0 has two defects - * - The zeroth word of the state is set to a constant (independent of the - * seed). This is a relatively minor defect which halves the accessible - * state space for MT19937 (but the resulting state space is still huge). - * (Actually, for the 64-bit version, it reduces the accessible states by - * 2<sup>33</sup>. On the other hand the 64-bit has better mixing - * properties.) - * - Close seeds, for example, [1] and [1,0], result in the same state. This - * is a potentially serious flaw which might result is identical random - * number sequences being generated instead of independent sequences. - * - * MixerMT1 fixes these defects in a straightforward manner. The - * resulting algorithm was included in one of the proposals for Random Number - * Generation for C++0X, see Brown, et al., - * http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2006/n2079.pdf - * - * The template parameter \e RandomType switches between the 32-bit and - * 64-bit versions. - * - * MixerMT1 still has a weakness in that it doesn't thoroughly mix the - * state. This is illustrated by an example given to me by Makoto Matsumoto: - * Consider a seed of length \e N and suppose we consider all \e - * W<sup><i>N</i>/2</sup> values for the first half of the seed (here \e W = - * 2<sup><i>width</i></sup>). MixerMT1 has a bottleneck in the way that - * the state is initialized which results in the second half of the state - * only taking on \e W<sup>2</sup> possible values. MixerSFMT mixes the - * seed into the state much more thoroughly. - * - * @tparam RandomType the type of the results, either Random_u32 or - * Random_u64. - **********************************************************************/ - template<class RandomType> class RANDOM_EXPORT MixerMT1 { - public: - /** - * The RandomType controlling the output of MixerMT1::SeedToState - **********************************************************************/ - typedef RandomType mixer_t; - /** - * A version number which should be unique to this RandomMixer. This - * prevents RandomEngine::Load from loading a saved generator with a - * different RandomMixer. Here the version is "MxMV" or "MxMW". - **********************************************************************/ - static const unsigned version = 0x4d784d56UL + (mixer_t::width == 64); - private: - /** - * The unsigned type corresponding to mixer_t. - **********************************************************************/ - typedef typename mixer_t::type mixer_type; - /** - * The mask for mixer_t. - **********************************************************************/ - static const mixer_type mask = mixer_t::mask; - public: - /** - * Mix the seed vector, \e seed, into the state array, \e state, of size \e - * n. - * - * @param[in] seed the input seed vector. - * @param[out] state the generator state. - * @param[in] n the size of the state. - **********************************************************************/ - static void SeedToState(const std::vector<RandomSeed::seed_type>& seed, - mixer_type state[], unsigned n) throw(); - /** - * Return the name of this class. - * - * @return the name. - **********************************************************************/ - static std::string Name() { - return "MixerMT1<Random_u" + - std::string(mixer_t::width == 32 ? "32" : "64") + ">"; - } - private: - static const mixer_type a = 5489ULL; - static const mixer_type - b = mixer_t::width == 32 ? 1812433253ULL : 6364136223846793005ULL; - static const mixer_type - c = mixer_t::width == 32 ? 1664525ULL : 3935559000370003845ULL; - static const mixer_type - d = mixer_t::width == 32 ? 1566083941ULL : 2862933555777941757ULL; - }; - - /** - * \brief The SFMT mixing functionality - * - * MixerSFMT is adapted from SFMT's init_by_array Mutsuo Saito given in - * http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/SFMT/SFMT-src-1.2.tar.gz - * and is part of the C++11 standard; see P. Becker, Working Draft, Standard - * for Programming Language C++, Oct. 2007, Sec. 26.4.7.1, - * http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2461.pdf - * - * MixerSFMT contains a single change is to allow it to function properly - * when the size of the state is small. - * - * MixerSFMT mixes the seed much more thoroughly than MixerMT1 and, in - * particular, it removes the mixing bottleneck present in MixerMT1. - * Thus it is the recommended mixing scheme for all production work. - **********************************************************************/ - class RANDOM_EXPORT MixerSFMT { - public: - /** - * The RandomType controlling the output of MixerSFMT::SeedToState - **********************************************************************/ - typedef Random_u32 mixer_t; - /** - * A version number which should be unique to this RandomMixer. This - * prevents RandomEngine::Load from loading a saved generator with a - * different RandomMixer. Here the version is "MxSM". - **********************************************************************/ - static const unsigned version = 0x4d78534dUL; - private: - /** - * The unsigned type corresponding to mixer_t. - **********************************************************************/ - typedef mixer_t::type mixer_type; - /** - * The mask for mixer_t. - **********************************************************************/ - static const mixer_type mask = mixer_t::mask; - public: - /** - * Mix the seed vector, \e seed, into the state array, \e state, of size \e - * n. - * - * @param[in] seed the input seed vector. - * @param[out] state the generator state. - * @param[in] n the size of the state. - **********************************************************************/ - static void SeedToState(const std::vector<RandomSeed::seed_type>& seed, - mixer_type state[], unsigned n) throw(); - /** - * Return the name of this class. - * - * @return the name. - **********************************************************************/ - static std::string Name() { return "MixerSFMT"; } - private: - static const mixer_type a = 0x8b8b8b8bUL; - static const mixer_type b = 1664525UL; - static const mixer_type c = 1566083941UL; - }; - -} // namespace RandomLib - -#endif // RANDOMLIB_RANDOMMIXER_HPP diff --git a/app/RandomLib/RandomNumber.hpp b/app/RandomLib/RandomNumber.hpp deleted file mode 100644 index 378b43df8c8ee5d74cdc7011bd6f2f474e1b13ff..0000000000000000000000000000000000000000 --- a/app/RandomLib/RandomNumber.hpp +++ /dev/null @@ -1,434 +0,0 @@ -/** - * \file RandomNumber.hpp - * \brief Header for RandomNumber - * - * Infinite precision random numbers. - * - * Copyright (c) Charles Karney (2006-2012) <charles@karney.com> and licensed - * under the MIT/X11 License. For more information, see - * http://randomlib.sourceforge.net/ - **********************************************************************/ - -#if !defined(RANDOMLIB_RANDOMNUMBER_HPP) -#define RANDOMLIB_RANDOMNUMBER_HPP \ - "$Id: e40bc1451b8493a049c12fae697352606b9b79da $" - -#include <vector> -#include <iomanip> -#include <limits> -#include <cmath> // for std::pow - -namespace RandomLib { - /** - * \brief Infinite precision random numbers. - * - * Implement infinite precision random numbers. Integer part is non-random. - * Fraction part consists of any some number of digits in base - * 2<sup><i>b</i></sup>. If \e m digits have been generated then the - * fraction is uniformly distributed in the open interval - * sum<sub><i>k</i>=1</sub><sup><i>m</i></sup> - * <i>f</i><sub><i>k</i>-1</sub>/2<sup><i>kb</i></sup> + - * (0,1)/2<sup><i>mb</i></sup>. When a RandomNumber is first constructed the - * integer part is zero and \e m = 0, and the number represents (0,1). A - * RandomNumber is able to represent all numbers in the symmetric open - * interval (-2<sup>31</sup>, 2<sup>31</sup>). In this implementation, \e b - * must one of 1, 2, 3, 4, 8, 12, 16, 20, 24, 28, or 32. (This restriction - * allows printing in hexadecimal and can easily be relaxed. There's also no - * essential reason why the base should be a power of 2.) - * - * @tparam bits the number of bits in each digit. - **********************************************************************/ - template<int bits = 1> class RandomNumber { - public: - /** - * Constructor sets number to a random number uniformly distributed in - * (0,1). - **********************************************************************/ - RandomNumber() throw() : _n(0), _s(1) {} - /** - * Swap with another RandomNumber. This is a fast way of doing an - * assignment. - * - * @param[in,out] t the RandomNumber to swap with. - **********************************************************************/ - void swap(RandomNumber& t) throw() { - if (this != &t) { - std::swap(_n, t._n); - std::swap(_s, t._s); - _f.swap(t._f); - } - } - /** - * Return to initial state, uniformly distributed in (0,1). - **********************************************************************/ - void Init() throw() { - STATIC_ASSERT(bits > 0 && bits <= w && (bits < 4 || bits % 4 == 0), - "RandomNumber: unsupported value for bits"); - _n = 0; - _s = 1; - _f.clear(); - } - /** - * @return the sign of the RandomNumber (+/- 1). - **********************************************************************/ - int Sign() const throw() { return _s; } - /** - * Change the sign of the RandomNumber. - **********************************************************************/ - void Negate() throw() { _s *= -1; } - /** - * @return the floor of the RandomNumber. - **********************************************************************/ - int Floor() const throw() { return _s > 0 ? int(_n) : -1 - int(_n); } - /** - * @return the ceiling of the RandomNumber. - **********************************************************************/ - int Ceiling() const throw() { return _s > 0 ? 1 + int(_n) : - int(_n); } - /** - * @return the unsigned integer component of the RandomNumber. - **********************************************************************/ - unsigned UInteger() const throw() { return _n; } - /** - * Add integer \e k to the RandomNumber. - * - * @param[in] k the integer to add. - **********************************************************************/ - void AddInteger(int k) throw() { - k += Floor(); // The new floor - int ns = k < 0 ? -1 : 1; // The new sign - if (ns != _s) // If sign changes, set f = 1 - f - for (size_t k = 0; k < Size(); ++k) - _f[k] = ~_f[k] & mask; - _n = ns > 0 ? k : -(k + 1); - } - /** - * Compare with another RandomNumber, *this < \e t - * - * @tparam Random the type of the random generator. - * @param[in,out] r a random generator. - * @param[in,out] t a RandomNumber to compare. - * @return true if *this < \e t. - **********************************************************************/ - template<class Random> bool LessThan(Random& r, RandomNumber& t) { - if (this == &t) return false; // same object - if (_s != t._s) return _s < t._s; - if (_n != t._n) return (_s < 0) ^ (_n < t._n); - for (unsigned k = 0; ; ++k) { - // Impose an order on the evaluation of the digits. - const unsigned x = Digit(r,k); - const unsigned y = t.Digit(r,k); - if (x != y) return (_s < 0) ^ (x < y); - // Two distinct numbers are never equal - } - } - /** - * Compare RandomNumber with two others, *this > max(\e u, \e v) - * - * @tparam Random the type of the random generator. - * @param[in,out] r a random generator. - * @param[in,out] u first RandomNumber to compare. - * @param[in,out] v second RandomNumber to compare. - * @return true if *this > max(\e u, \e v). - **********************************************************************/ - template<class Random> bool GreaterPair(Random& r, - RandomNumber& u, RandomNumber& v) { - // cmps is set to false as soon as u <= *this, and likewise for cmpt. - bool cmpu = this != &u, cmpv = this != &v && &u != &v; - if (!(cmpu || cmpv)) return true; - // Check signs first - if (cmpu) { - if (u._s > _s) return false; // u > *this - if (u._s < _s) cmpu = false; - } - if (cmpv) { - if (v._s > _s) return false; // v > *this - if (v._s < _s) cmpv = false; - } - if (!(cmpu || cmpv)) return true; // u <= *this && v <= *this - // Check integer parts - if (cmpu) { - if ((_s < 0) ^ (u._n > _n)) return false; // u > *this - if ((_s < 0) ^ (u._n < _n)) cmpu = false; - } - if (cmpv) { - if ((_s < 0) ^ (v._n > _n)) return false; // v > *this - if ((_s < 0) ^ (v._n < _n)) cmpv = false; - } - if (!(cmpu || cmpv)) return true; // u <= *this && v <= *this - // Check fractions - for (unsigned k = 0; ; ++k) { - // Impose an order on the evaluation of the digits. Note that this is - // asymmetric on interchange of u and v; since u is tested first, more - // digits of u are generated than v (on average). - const unsigned x = Digit(r,k); - if (cmpu) { - const unsigned y = u.Digit(r,k); - if ((_s < 0) ^ (y > x)) return false; // u > *this - if ((_s < 0) ^ (y < x)) cmpu = false; - } - if (cmpv) { - const unsigned y = v.Digit(r,k); - if ((_s < 0) ^ (y > x)) return false; // v > *this - if ((_s < 0) ^ (y < x)) cmpv = false; - } - if (!(cmpu || cmpv)) return true; // u <= *this && v <= *this - } - } - /** - * @tparam Random the type of the random generator. - * @param[in,out] r a random generator. - * @param[in] k the index of a digit of the fraction - * @return digit number \e k, generating it if necessary. - **********************************************************************/ - template<class Random> unsigned Digit(Random& r, unsigned k) { - ExpandTo(r, k + 1); - return _f[k]; - } - /** - * Add one digit to the fraction. - * - * @tparam Random the type of the random generator. - * @param[in,out] r a random generator. - **********************************************************************/ - template<class Random> void AddDigit(Random& r) - { _f.push_back(RandomDigit(r)); } - /** - * @param[in] k the index of a digit of the fraction - * @return a const reference to digit number \e k, without generating new - * digits. - * - * This will throw an exception if the digit hasn't been generated. - **********************************************************************/ - const unsigned& RawDigit(unsigned k) const throw() - { return (const unsigned&)(_f.at(k)); } - /** - * @param[in] k the index of a digit of the fraction - * @return a non-const reference to digit number \e k, without generating - * new digits. - * - * This will throw an exception if the digit hasn't been generated. - **********************************************************************/ - unsigned& RawDigit(unsigned k) throw() - { return (unsigned&)(_f.at(k)); } - /** - * Return to initial state, uniformly distributed in \e n + (0,1). This is - * similar to Init but also returns the memory used by the object to the - * system. Normally Init should be used. - **********************************************************************/ - void Clear() { - std::vector<unsigned> z(0); - _n = 0; - _s = 1; - _f.swap(z); - } - /** - * @return the number of digits in fraction - **********************************************************************/ - unsigned Size() const throw() { return unsigned(_f.size()); } - /** - * Return the fraction part of the RandomNumber as a floating point number - * of type RealType rounded to the nearest multiple of - * 1/2<sup><i>p</i></sup>, where \e p = - * std::numeric_limits<RealType>::digits, and, if necessary, creating - * additional digits of the number. - * - * @tparam RealType the floating point type to convert to. - * @tparam Random the type of the random generator. - * @param[in,out] r a random generator for generating the necessary digits. - * @return the fraction of the RandomNumber rounded to a RealType. - **********************************************************************/ - template<typename RealType, typename Random> RealType Fraction(Random& r) { - STATIC_ASSERT(!std::numeric_limits<RealType>::is_integer, - "RandomNumber::Fraction: invalid real type RealType"); - const int d = std::numeric_limits<RealType>::digits; - const int k = (d + bits - 1)/bits; - const int kg = (d + bits)/bits; // For guard bit - RealType y = 0; - if (Digit(r, kg - 1) & (1U << (kg * bits - d - 1))) - // if guard bit is set, round up. - y += std::pow(RealType(2), -d); - const RealType fact = std::pow(RealType(2), -bits); - RealType mult = RealType(1); - for (int i = 0; i < k; ++i) { - mult *= fact; - y += mult * RealType(i < k - 1 ? RawDigit(i) : - RawDigit(i) & (~0U << (k * bits - d))); - } - return y; - } - /** - * Return the value of the RandomNumber rounded to nearest floating point - * number of type RealType and, if necessary, creating additional digits of - * the number. - * - * @tparam RealType the floating point type to convert to. - * @tparam Random the type of the random generator. - * @param[in,out] r a random generator for generating the necessary digits. - * @return the value of the RandomNumber rounded to a RealType. - **********************************************************************/ - template<typename RealType, class Random> RealType Value(Random& r) { - // Ignore the possibility of overflow here (OK because int doesn't - // currently overflow any real type). Assume the real type supports - // denormalized numbers. Need to treat rounding explicitly since the - // missing digits always imply rounding up. - STATIC_ASSERT(!std::numeric_limits<RealType>::is_integer, - "RandomNumber::Value: invalid real type RealType"); - const int digits = std::numeric_limits<RealType>::digits, - min_exp = std::numeric_limits<RealType>::min_exponent; - RealType y; - int lead; // Position of leading bit (0.5 = position 0) - if (_n) lead = highest_bit_idx(_n); - else { - int i = 0; - while ( Digit(r, i) == 0 && i < (-min_exp)/bits ) ++i; - lead = highest_bit_idx(RawDigit(i)) - (i + 1) * bits; - // To handle denormalized numbers set lead = max(lead, min_exp) - lead = lead > min_exp ? lead : min_exp; - } - int trail = lead - digits; // Position of guard bit (0.5 = position 0) - if (trail > 0) { - y = RealType(_n & (~0U << trail)); - if (_n & (1U << (trail - 1))) - y += std::pow(RealType(2), trail); - } else { - y = RealType(_n); - int k = (-trail)/bits; // Byte with guard bit - if (Digit(r, k) & (1U << ((k + 1) * bits + trail - 1))) - // If guard bit is set, round bit (some subsequent bit will be 1). - y += std::pow(RealType(2), trail); - // Byte with trailing bit (can be negative) - k = (-trail - 1 + bits)/bits - 1; - const RealType fact = std::pow(RealType(2), -bits); - RealType mult = RealType(1); - for (int i = 0; i <= k; ++i) { - mult *= fact; - y += mult * - RealType(i < k ? RawDigit(i) : - RawDigit(i) & (~0U << ((k + 1) * bits + trail))); - } - } - if (_s < 0) y *= -1; - return y; - } - /** - * Return the range of possible values for the RandomNumber as pair of - * doubles. This doesn't create any additional digits of the result and - * doesn't try to control roundoff. - * - * @return a pair denoting the range with first being the lower limit and - * second being the upper limit. - **********************************************************************/ - std::pair<double, double> Range() const throw() { - double y = _n; - const double fact = std::pow(double(2), -bits); - double mult = double(1); - for (unsigned i = 0; i < Size(); ++i) { - mult *= fact; - y += mult * RawDigit(i); - } - return std::pair<double, double>(_s > 0 ? y : -(y + mult), - _s > 0 ? (y + mult) : -y); - } - /** - * @tparam Random the type of the random generator. - * @param[in,out] r a random generator. - * @return a random digit in [0, 2<sup><i>bits</i></sup>). - **********************************************************************/ - template<class Random> static unsigned RandomDigit(Random& r) throw() { - return unsigned(r.template Integer<bits>()); - } - - private: - /** - * The integer part - **********************************************************************/ - unsigned _n; - /** - * The sign - **********************************************************************/ - int _s; - /** - * The fraction part - **********************************************************************/ - std::vector<unsigned> _f; - /** - * Fill RandomNumber to \e k digits. - **********************************************************************/ - template<class Random> void ExpandTo(Random& r, size_t k) { - size_t l = _f.size(); - if (k <= l) - return; - _f.resize(k); - for (size_t i = l; i < k; ++i) - _f[i] = RandomDigit(r); - } - /** - * Return index [0..32] of highest bit set. Return 0 if x = 0, 32 is if x - * = ~0. (From Algorithms for programmers by Joerg Arndt.) - **********************************************************************/ - static int highest_bit_idx(unsigned x) throw() { - if (x == 0) return 0; - int r = 1; - if (x & 0xffff0000U) { x >>= 16; r += 16; } - if (x & 0x0000ff00U) { x >>= 8; r += 8; } - if (x & 0x000000f0U) { x >>= 4; r += 4; } - if (x & 0x0000000cU) { x >>= 2; r += 2; } - if (x & 0x00000002U) { r += 1; } - return r; - } - /** - * The number of bits in unsigned. - **********************************************************************/ - static const int w = std::numeric_limits<unsigned>::digits; - public: - /** - * A mask for the digits. - **********************************************************************/ - static const unsigned mask = - bits == w ? ~0U : ~(~0U << (bits < w ? bits : 0)); - }; - - /** - * \relates RandomNumber - * Print a RandomNumber. Format is n.dddd... where the base for printing is - * 2<sup>max(4,<i>b</i>)</sup>. The ... represents an infinite sequence of - * ungenerated random digits (uniformly distributed). Thus with \e b = 1, - * 0.0... = (0,1/2), 0.00... = (0,1/4), 0.11... = (3/4,1), etc. - **********************************************************************/ - template<int bits> - std::ostream& operator<<(std::ostream& os, const RandomNumber<bits>& n) { - const std::ios::fmtflags oldflags = os.flags(); - RandomNumber<bits> t = n; - os << (t.Sign() > 0 ? "+" : "-"); - unsigned i = t.UInteger(); - os << std::hex << std::setfill('0'); - if (i == 0) - os << "0"; - else { - bool first = true; - const int w = std::numeric_limits<unsigned>::digits; - const unsigned mask = RandomNumber<bits>::mask; - for (int s = ((w + bits - 1)/bits) * bits - bits; s >= 0; s -= bits) { - unsigned d = mask & (i >> s); - if (d || !first) { - if (first) { - os << d; - first = false; - } - else - os << std::setw((bits+3)/4) << d; - } - } - } - os << "."; - unsigned s = t.Size(); - for (unsigned i = 0; i < s; ++i) - os << std::setw((bits+3)/4) << t.RawDigit(i); - os << "..." << std::setfill(' '); - os.flags(oldflags); - return os; - } - -} // namespace RandomLib - -#endif // RANDOMLIB_RANDOMNUMBER_HPP diff --git a/app/RandomLib/RandomPower2.hpp b/app/RandomLib/RandomPower2.hpp deleted file mode 100644 index 1357832e56d012db3d67f806c106e8893dc368a7..0000000000000000000000000000000000000000 --- a/app/RandomLib/RandomPower2.hpp +++ /dev/null @@ -1,78 +0,0 @@ -/** - * \file RandomPower2.hpp - * \brief Header for RandomPower2. - * - * Return and multiply by powers of two. - * - * Copyright (c) Charles Karney (2006-2011) <charles@karney.com> and licensed - * under the MIT/X11 License. For more information, see - * http://randomlib.sourceforge.net/ - **********************************************************************/ - -#if !defined(RANDOMLIB_RANDOMPOWER2_HPP) -#define RANDOMLIB_RANDOMPOWER2_HPP \ - "$Id: 7e91d02ba364b811c79a9932e1a6986985bc9601 $" - -#include <cmath> // For std::pow - -namespace RandomLib { - - /** - * \brief Return or multiply by powers of 2 - * - * With some compilers it's fastest to do a table lookup of powers of - * 2. If RANDOMLIB_POWERTABLE is 1, a lookup table is used. If - * RANDOMLIB_POWERTABLE is 0, then std::pow is used. - **********************************************************************/ - class RANDOM_EXPORT RandomPower2 { - public: - /** - * Return powers of 2 (either using a lookup table or std::pow) - * - * @param[in] n the integer power. - * @return 2<sup><i>n</i></sup>. - **********************************************************************/ - template<typename RealType> static inline RealType pow2(int n) throw() { -#if RANDOMLIB_POWERTABLE - return RealType(power2[n - minpow]); -#else - return std::pow(RealType(2), n); -#endif - } - /** - * Multiply a real by a power of 2 - * - * @tparam RealType the type of \e x. - * @param[in] x the real number. - * @param[in] n the power (positive or negative). - * @return \e x 2<sup><i>n</i></sup>. - **********************************************************************/ - template<typename RealType> - static inline RealType shiftf(RealType x, int n) throw() - // std::ldexp(x, n); is equivalent, but slower - { return x * pow2<RealType>(n); } - - // Constants - enum { - /** - * Minimum power in RandomPower2::power2 - **********************************************************************/ -#if RANDOMLIB_LONGDOUBLEPREC > 64 - minpow = -120, -#else - minpow = -64, -#endif - maxpow = 64 /**< Maximum power in RandomPower2::power2. */ - }; - private: -#if RANDOMLIB_POWERTABLE - /** - * Table of powers of two - **********************************************************************/ - static const float power2[maxpow - minpow + 1]; // Powers of two -#endif - }; - -} // namespace RandomLib - -#endif // RANDOMLIB_RANDOMPOWER2_HPP diff --git a/app/RandomLib/RandomSeed.hpp b/app/RandomLib/RandomSeed.hpp deleted file mode 100644 index 78c9dcfd74cffa38cab2a75bbcddcd6f67ad0a18..0000000000000000000000000000000000000000 --- a/app/RandomLib/RandomSeed.hpp +++ /dev/null @@ -1,252 +0,0 @@ -/** - * \file RandomSeed.hpp - * \brief Header for RandomSeed - * - * This provides a base class for random generators. - * - * Copyright (c) Charles Karney (2006-2011) <charles@karney.com> and licensed - * under the MIT/X11 License. For more information, see - * http://randomlib.sourceforge.net/ - **********************************************************************/ - -#if !defined(RANDOMLIB_RANDOMSEED_HPP) -#define RANDOMLIB_RANDOMSEED_HPP \ - "$Id: ff109bb5ed8074c9a998a8560a7b2fadf8745dec $" - -#include <iostream> -#include <stdexcept> -#include <vector> -#include <iterator> -#include <algorithm> // For std::transform -#include <sstream> // For VectorToString -#include <RandomLib/RandomType.hpp> - -#if defined(_MSC_VER) -// Squelch warnings about dll vs vector -#pragma warning (push) -#pragma warning (disable: 4251) -#endif - -namespace RandomLib { - /** - * \brief A base class for random generators - * - * This provides facilities for managing the seed and for converting the seed - * into random generator state. - * - * The seed is taken to be a vector of unsigned longs of arbitrary length. - * (Only the low 32 bit of each element of the vector are used.) The class - * provides several methods for setting the seed, static functions for - * producing "random" and "unique" seeds, and facilities for converting the - * seed to a string so that it can be printed easily. - * - * The seeding algorithms are those used by - * <a href="http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/emt.html"> - * MT19937</a> with some modifications to make all states accessible and to - * minimize the likelihood of different seeds giving the same state. - * - * Finally some low-level routines are provided to facilitate the creation of - * I/O methods for the random generator. - * - * A random generator class can be written based on this class. The - * generator class would use the base class methods for setting the seed and - * for converting the seed into state. It would provide the machinery for - * advancing the state and for producing random data. It is also responsible - * for the routine to save and restore the generator state (including the - * seed). - * - * Written by Charles Karney <charles@karney.com> and licensed under the - * MIT/X11 License. The seeding algorithms are adapted from those of - * <a href="http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/emt.html"> - * MT19937</a>. For more information, see http://randomlib.sourceforge.net/ - **********************************************************************/ - class RANDOM_EXPORT RandomSeed { - public: - typedef Random_u32 u32; - typedef Random_u64 u64; - - virtual ~RandomSeed() throw() = 0; - /** - * A type large enough to hold the seed words. This is needs to hold 32 - * bits and is an unsigned long for portability. - **********************************************************************/ - typedef RandomType<32, unsigned long> seed_t; - typedef seed_t::type seed_type; - - /** - * \name Resetting the seed - **********************************************************************/ - ///@{ - /** - * Set the seed to a vector \e v. Only the low \e 32 bits of each element - * are used. - * - * @tparam IntType the integral type of the elements of the vector. - * @param[in] v the vector of elements. - **********************************************************************/ - template<typename IntType> void Reseed(const std::vector<IntType>& v) { - Reseed(v.begin(), v.end()); - } - /** - * Set the seed to [\e a, \e b) from a pair of iterators. The iterator - * must produce results which can be converted into seed_type. Only the - * low 32 bits of each element are used. - * - * @tparam InputIterator the type of the iterator. - * @param[in] a the beginning iterator. - * @param[in] b the ending iterator. - **********************************************************************/ - template<typename InputIterator> - void Reseed(InputIterator a, InputIterator b) { - // Read new seed into temporary so as not to change object on error. - std::vector<seed_type> t; - std::transform(a, b, back_inserter(t), - seed_t::cast<typename std::iterator_traits<InputIterator> - ::value_type>); - _seed.swap(t); - Reset(); - } - /** - * Set the seed to [\e n]. Only the low 32 bits of \e n are used. - * - * @param[in] n the new seed to use. - **********************************************************************/ - void Reseed(seed_type n) { - // Reserve space for new seed so as not to change object on error. - _seed.reserve(1); - _seed.resize(1); - _seed[0] = seed_t::cast(n); - Reset(); - } - /** - * Set the seed to [SeedVector()]. This is the standard way to reseed with - * a "unique" seed. - **********************************************************************/ - void Reseed() { Reseed(SeedVector()); } - /** - * Set the seed from the string \e s using Random::StringToVector. - * - * @param[in] s the string to be decoded into a seed. - **********************************************************************/ - void Reseed(const std::string& s) { - // Read new seed into temporary so as not to change object on error. - std::vector<seed_type> t = StringToVector(s); - _seed.swap(t); - Reset(); - } - ///@} - - /** - * \name Examining the seed - **********************************************************************/ - ///@{ - /** - * Return reference to the seed vector (read-only). - * - * @return the seed vector. - **********************************************************************/ - const std::vector<seed_type>& Seed() const throw() { return _seed; } - /** - * Format the current seed suitable for printing. - * - * @return the seedd as a string. - **********************************************************************/ - std::string SeedString() const { return VectorToString(_seed); } - ///@} - - /** - * \name Resetting the random seed - **********************************************************************/ - ///@{ - /** - * Resets the sequence to its just-seeded state. This needs to be declared - * virtual here so that the Reseed functions can call it after saving the - * seed. - **********************************************************************/ - virtual void Reset() throw() = 0; - ///@} - - /** - * \name Static functions for seed management - **********************************************************************/ - ///@{ - /** - * Return a 32 bits of data suitable for seeding the random generator. The - * result is obtained by combining data from /dev/urandom, gettimeofday, - * time, and getpid to provide a reasonably "random" word of data. - * Usually, it is safer to seed the random generator with SeedVector() - * instead of SeedWord(). - * - * @return a single "more-or-less random" seed_type to be used as a seed. - **********************************************************************/ - static seed_type SeedWord(); - /** - * Return a vector of unsigned longs suitable for seeding the random - * generator. The vector is almost certainly unique; however, the results - * of successive calls to Random::SeedVector() will be correlated. If - * several Random objects are required within a single program execution, - * call Random::SeedVector once, print it out (!), push_back additional - * data to identify the instance (e.g., loop index, thread ID, etc.), and - * use the result to seed the Random object. The number of elements - * included in the vector may depend on the operating system. Additional - * elements may be added in future versions of this library. - * - * @return a "unique" vector of seed_type to be uses as a seed. - **********************************************************************/ - static std::vector<seed_type> SeedVector(); - /** - * Convert a vector into a string suitable for printing or as an argument - * for Random::Reseed(const std::string& s). - * - * @tparam IntType the integral type of the elements of the vector. - * @param[in] v the vector to be converted. - * @return the resulting string. - **********************************************************************/ - template<typename IntType> - static std::string VectorToString(const std::vector<IntType>& v) { - std::ostringstream os; - os << "["; - for (typename std::vector<IntType>::const_iterator n = v.begin(); - n != v.end(); ++n) { - if (n != v.begin()) - os << ","; - // Normalize in case this is called by user. - os << seed_t::cast(*n); - } - os << "]"; - return os.str(); - } - /** - * Convert a string into a vector of seed_type suitable for printing or as - * an argument for Random::Reseed(const std::vector<seed_type>& v). Reads - * consecutive digits in string. Thus "[1,2,3]" => [1,2,3]; "-0.123e-4" => - * [0,123,4], etc. strtoul understands C's notation for octal and - * hexadecimal, for example "012 10 0xa" => [10,10,10]. Reading of a - * number stops at the first illegal character for the base. Thus - * "2006-04-08" => [2006,4,0,8] (i.e., 08 becomes two numbers). Note that - * input numbers greater than ULONG_MAX overflow to ULONG_MAX, which - * probably will result in the number being interpreted as LONG_MASK. - * - * @param[in] s the string to be converted. - * @return the resulting vector of seed_type. - **********************************************************************/ - static std::vector<seed_type> StringToVector(const std::string& s); - ///@} - - protected: - /** - * The seed vector - **********************************************************************/ - std::vector<seed_type> _seed; - - }; - - inline RandomSeed::~RandomSeed() throw() {} - -} // namespace RandomLib - -#if defined(_MSC_VER) -#pragma warning (pop) -#endif - -#endif // RANDOMLIB_RANDOMSEED_HPP diff --git a/app/RandomLib/RandomSelect.hpp b/app/RandomLib/RandomSelect.hpp deleted file mode 100644 index 38e7023c4405cddb99dc1e128fe21861facbdf71..0000000000000000000000000000000000000000 --- a/app/RandomLib/RandomSelect.hpp +++ /dev/null @@ -1,323 +0,0 @@ -/** - * \file RandomSelect.hpp - * \brief Header for RandomSelect. - * - * An implementation of the Walker algorithm for selecting from a finite set. - * - * Copyright (c) Charles Karney (2006-2011) <charles@karney.com> and licensed - * under the MIT/X11 License. For more information, see - * http://randomlib.sourceforge.net/ - **********************************************************************/ - -#if !defined(RANDOMLIB_RANDOMSELECT_HPP) -#define RANDOMLIB_RANDOMSELECT_HPP \ - "$Id: 6dcd473eb6e01c541d20091600f604b45303dee9 $" - -#include <vector> -#include <limits> -#include <stdexcept> - -namespace RandomLib { - /** - * \brief Random selection from a discrete set. - * - * An implementation of Walker algorithm for selecting from a finite set - * (following Knuth, TAOCP, Vol 2, Sec 3.4.1.A). This provides a rapid way - * of selecting one of several choices depending on a discrete set weights. - * Original citation is\n A. J. Walker,\n An Efficient Method for Generating - * Discrete Random Variables and General Distributions,\n ACM TOMS 3, 253-256 - * (1977). - * - * There are two changes here in the setup algorithm as given by Knuth: - * - * - The probabilities aren't sorted at the beginning of the setup; nor are - * they maintained in a sorted order. Instead they are just partitioned on - * the mean. This improves the setup time from O(\e k<sup>2</sup>) to O(\e - * k). - * - * - The internal calculations are carried out with type \e NumericType. If - * the input weights are of integer type, then choosing an integer type for - * \e NumericType yields an exact solution for the returned distribution - * (assuming that the underlying random generator is exact.) - * - * Example: - * \code - * #include <RandomLib/RandomSelect.hpp> - * - * // Weights for throwing a pair of dice - * unsigned w[] = { 0, 0, 1, 2, 3, 4, 5, 6, 5, 4, 3, 2, 1 }; - * - * // Initialize selection - * RandomLib::RandomSelect<unsigned> sel(w, w + 13); - * - * RandomLib::Random r; // Initialize random numbers - * std::cout << "Seed set to " << r.SeedString() << "\n"; - * - * std::cout << "Throw a pair of dice 100 times:"; - * for (unsigned i = 0; i < 100; ++i) - * std::cout << " " << sel(r); - * std::cout << "\n"; - * \endcode - * - * @tparam NumericType the numeric type to use (default double). - **********************************************************************/ - template<typename NumericType = double> class RandomSelect { - public: - /** - * Initialize in a cleared state (equivalent to having a single - * choice). - **********************************************************************/ - RandomSelect() : _k(0), _wsum(0), _wmax(0) {} - - /** - * Initialize with a weight vector \e w of elements of type \e WeightType. - * Internal calculations are carried out with type \e NumericType. \e - * NumericType needs to allow Choices() * MaxWeight() to be represented. - * Sensible combinations are: - * - \e WeightType integer, \e NumericType integer with - * digits(\e NumericType) >= digits(\e WeightType) - * - \e WeightType integer, \e NumericType real - * - \e WeightType real, \e NumericType real with digits(\e NumericType) >= - * digits(\e WeightType) - * - * @tparam WeightType the type of the weights. - * @param[in] w the vector of weights. - **********************************************************************/ - template<typename WeightType> - RandomSelect(const std::vector<WeightType>& w) { Init(w.begin(), w.end()); } - - /** - * Initialize with a weight given by a pair of iterators [\e a, \e b). - * - * @tparam InputIterator the type of the iterator. - * @param[in] a the beginning iterator. - * @param[in] b the ending iterator. - **********************************************************************/ - template<typename InputIterator> - RandomSelect(InputIterator a, InputIterator b); - - - /** - * Clear the state (equivalent to having a single choice). - **********************************************************************/ - void Init() throw() - { _k = 0; _wsum = 0; _wmax = 0; _Q.clear(); _Y.clear(); } - - /** - * Re-initialize with a weight vector \e w. Leave state unaltered in the - * case of an error. - * - * @tparam WeightType the type of the weights. - * @param[in] w the vector of weights. - **********************************************************************/ - template<typename WeightType> - void Init(const std::vector<WeightType>& w) { Init(w.begin(), w.end()); } - - /** - * Re-initialize with a weight given as a pair of iterators [\e a, \e b). - * Leave state unaltered in the case of an error. - * - * @tparam InputIterator the type of the iterator. - * @param[in] a the beginning iterator. - * @param[in] b the ending iterator. - **********************************************************************/ - template<typename InputIterator> - void Init(InputIterator a, InputIterator b) { - RandomSelect<NumericType> t(a, b); - _Q.reserve(t._k); - _Y.reserve(t._k); - *this = t; - } - - /** - * Return an index into the weight vector with probability proportional to - * the weight. - * - * @tparam Random the type of RandomCanonical generator. - * @param[in,out] r the RandomCanonical generator. - * @return the random index into the weight vector. - **********************************************************************/ - template<class Random> - unsigned operator()(Random& r) const throw() { - if (_k <= 1) - return 0; // Special cases - const unsigned K = r.template Integer<unsigned>(_k); - // redundant casts to type NumericType to prevent warning from MS Project - return (std::numeric_limits<NumericType>::is_integer ? - r.template Prob<NumericType>(NumericType(_Q[K]), - NumericType(_wsum)) : - r.template Prob<NumericType>(NumericType(_Q[K]))) ? - K : _Y[K]; - } - - /** - * @return the sum of the weights. - **********************************************************************/ - NumericType TotalWeight() const throw() { return _wsum; } - - /** - * @return the maximum weight. - **********************************************************************/ - NumericType MaxWeight() const throw() { return _wmax; } - - /** - * @param[in] i the index in to the weight vector. - * @return the weight for sample \e i. Weight(i) / TotalWeight() gives the - * probability of sample \e i. - **********************************************************************/ - NumericType Weight(unsigned i) const throw() { - if (i >= _k) - return NumericType(0); - else if (_k == 1) - return _wsum; - const NumericType n = std::numeric_limits<NumericType>::is_integer ? - _wsum : NumericType(1); - NumericType p = _Q[i]; - for (unsigned j = _k; j;) - if (_Y[--j] == i) - p += n - _Q[j]; - // If NumericType is integral, then p % _k == 0. - // assert(!std::numeric_limits<NumericType>::is_integer || p % _k == 0); - return (p / NumericType(_k)) * (_wsum / n); - } - - /** - * @return the number of choices, i.e., the length of the weight vector. - **********************************************************************/ - unsigned Choices() const throw() { return _k; } - - private: - - /** - * Size of weight vector - **********************************************************************/ - unsigned _k; - /** - * Vector of cutoffs - **********************************************************************/ - std::vector<NumericType> _Q; - /** - * Vector of aliases - **********************************************************************/ - std::vector<unsigned> _Y; - /** - * The sum of the weights - **********************************************************************/ - NumericType _wsum; - /** - * The maximum weight - **********************************************************************/ - NumericType _wmax; - - }; - - template<typename NumericType> template<typename InputIterator> - RandomSelect<NumericType>::RandomSelect(InputIterator a, InputIterator b) { - - typedef typename std::iterator_traits<InputIterator>::value_type - WeightType; - // Disallow WeightType = real, NumericType = integer - STATIC_ASSERT(std::numeric_limits<WeightType>::is_integer || - !std::numeric_limits<NumericType>::is_integer, - "RandomSelect: inconsistent WeightType and NumericType"); - - // If WeightType and NumericType are the same type, NumericType as precise - // as WeightType - STATIC_ASSERT(std::numeric_limits<WeightType>::is_integer != - std::numeric_limits<NumericType>::is_integer || - std::numeric_limits<NumericType>::digits >= - std::numeric_limits<WeightType>::digits, - "RandomSelect: NumericType insufficiently precise"); - - _wsum = 0; - _wmax = 0; - std::vector<NumericType> p; - - for (InputIterator wptr = a; wptr != b; ++wptr) { - // Test *wptr < 0 without triggering compiler warning when *wptr = - // unsigned - if (!(*wptr > 0 || *wptr == 0)) - // This also catches NaNs - throw RandomErr("RandomSelect: Illegal weight"); - NumericType w = NumericType(*wptr); - if (w > (std::numeric_limits<NumericType>::max)() - _wsum) - throw RandomErr("RandomSelect: Overflow"); - _wsum += w; - _wmax = w > _wmax ? w : _wmax; - p.push_back(w); - } - - _k = unsigned(p.size()); - if (_wsum <= 0) - throw RandomErr("RandomSelect: Zero total weight"); - - if (_k <= 1) { - // We treat k <= 1 as a special case in operator() - _Q.clear(); - _Y.clear(); - return; - } - - if ((std::numeric_limits<NumericType>::max)()/NumericType(_k) < - NumericType(_wmax)) - throw RandomErr("RandomSelect: Overflow"); - - std::vector<unsigned> j(_k); - _Q.resize(_k); - _Y.resize(_k); - - // Pointers to the next empty low and high slots - unsigned u = 0; - unsigned v = _k - 1; - - // Scale input and store in p and setup index array j. Note _wsum = - // mean(p). We could scale out _wsum here, but the following is exact when - // w[i] are low integers. - for (unsigned i = 0; i < _k; ++i) { - p[i] *= NumericType(_k); - j[p[i] > _wsum ? v-- : u++] = i; - } - - // Pointers to the next low and high slots to use. Work towards the - // middle. This simplifies the loop exit test to u == v. - u = 0; - v = _k - 1; - - // For integer NumericType, store the unnormalized probability in _Q and - // select using the exact Prob(_Q[k], _wsum). For real NumericType, store - // the normalized probability and select using Prob(_Q[k]). There will be - // a round off error in performing the division; but there is also the - // potential for round off errors in performing the arithmetic on p. There - // is therefore no point in simulating the division exactly using the - // slower Prob(real, real). - const NumericType n = std::numeric_limits<NumericType>::is_integer ? - NumericType(1) : _wsum; - - while (true) { - // A loop invariant here is mean(p[j[u..v]]) == _wsum - _Q[j[u]] = p[j[u]] / n; - - // If all arithmetic were exact this assignment could be: - // if (p[j[u]] < _wsum) _Y[j[u]] = j[v]; - // But the following is safer: - _Y[j[u]] = j[p[j[u]] < _wsum ? v : u]; - - if (u == v) { - // The following assertion may fail because of roundoff errors - // assert( p[j[u]] == _wsum ); - break; - } - - // Update p, u, and v maintaining the loop invariant - p[j[v]] = p[j[v]] - (_wsum - p[j[u]]); - if (p[j[v]] > _wsum) - ++u; - else - j[u] = j[v--]; - } - return; - } - -} // namespace RandomLib - -#endif // RANDOMLIB_RANDOMSELECT_HPP diff --git a/app/RandomLib/RandomType.hpp b/app/RandomLib/RandomType.hpp deleted file mode 100644 index cd6aaa3490684327029cddfb11882cecb9259dd6..0000000000000000000000000000000000000000 --- a/app/RandomLib/RandomType.hpp +++ /dev/null @@ -1,138 +0,0 @@ -/** - * \file RandomType.hpp - * \brief Class to hold bit-width and unsigned type - * - * This provides a simple class to couple a bit-width and an unsigned type - * capable of holding all the bits. In addition is offers static methods for - * I/O and checksumming. - * - * Copyright (c) Charles Karney (2006-2011) <charles@karney.com> and licensed - * under the MIT/X11 License. For more information, see - * http://randomlib.sourceforge.net/ - **********************************************************************/ -#if !defined(RANDOMLIB_RANDOMTYPE_HPP) -#define RANDOMLIB_RANDOMTYPE_HPP \ - "$Id: 16319dad1a8c9f3ecbb7bfa0c82e220e332705a4 $" - -#include <limits> -#include <string> -#include <iostream> - -namespace RandomLib { - /** - * \brief Class to hold bit-width and unsigned type - * - * This provides a simple class to couple a bit-width and an unsigned type - * capable of holding all the bits. In addition is offers static methods for - * I/O and checksumming. - * - * @tparam bits the number of significant bits. - * @tparam UIntType the C++ unsigned integer type capable of holding the bits. - **********************************************************************/ - template<int bits, typename UIntType> - class RANDOM_EXPORT RandomType { - public: - /** - * The unsigned C++ type - **********************************************************************/ - typedef UIntType type; - /** - * The number of significant bits - **********************************************************************/ - static const unsigned width = bits; - /** - * A mask for the significant bits. - **********************************************************************/ - static const type mask = - ~type(0) >> (std::numeric_limits<type>::digits - width); - /** - * The minimum representable value - **********************************************************************/ - static const type min = type(0); - /** - * The maximum representable value - **********************************************************************/ - static const type max = mask; - /** - * A combined masking and casting operation - * - * @tparam IntType the integer type of the \e x. - * @param[in] x the input integer. - * @return the masked and casted result. - **********************************************************************/ - template<typename IntType> static type cast(IntType x) throw() - { return type(x) & mask; } - /** - * Read a data value from a stream of 32-bit quantities (binary or text) - * - * @param[in,out] is the input stream. - * @param[in] bin true if the stream is binary. - * @param[out] x the data value read from the stream. - **********************************************************************/ - static void Read32(std::istream& is, bool bin, type& x); - /** - * Write the data value to a stream of 32-bit quantities (binary or text) - * - * @param[in,out] os the output stream. - * @param[in] bin true if the stream is binary. - * @param[in,out] cnt controls the use of spaces and newlines for text - * output. - * @param[in] x the data value to be written to the stream. - * - * \e cnt should be zero on the first invocation of a series of writes. - * This function increments it by one on each call. - **********************************************************************/ - static void Write32(std::ostream& os, bool bin, int& cnt, type x); - /** - * Accumulate a checksum of a integer into a 32-bit check. This implements - * a very simple checksum and is intended to avoid accidental corruption - * only. - * - * @param[in] n the number to be included in the checksum. - * @param[in,out] check the running checksum. - **********************************************************************/ - static void CheckSum(type n, uint32_t& check) throw(); - }; - - /** - * The standard unit for 32-bit quantities - **********************************************************************/ - typedef RandomType<32, uint32_t> Random_u32; - /** - * The standard unit for 64-bit quantities - **********************************************************************/ - typedef RandomType<64, uint64_t> Random_u64; - - /** - * The integer type of constructing bitsets. This used to be unsigned long. - * C++11 has made this unsigned long long. - **********************************************************************/ -#if defined(_MSC_VER) && _MSC_VER >= 1600 - typedef unsigned long long bitset_uint_t; -#else - typedef unsigned long bitset_uint_t; -#endif - - /// \cond SKIP - - // Accumulate a checksum of a 32-bit quantity into check - template<> - inline void Random_u32::CheckSum(Random_u32::type n, Random_u32::type& check) - throw() { - // Circular shift left by one bit and add new word. - check = (check << 1 | (check >> 31 & Random_u32::type(1))) + n; - check &= Random_u32::mask; - } - - // Accumulate a checksum of a 64-bit quantity into check - template<> - inline void Random_u64::CheckSum(Random_u64::type n, Random_u32::type& check) - throw() { - Random_u32::CheckSum(Random_u32::cast(n >> 32), check); - Random_u32::CheckSum(Random_u32::cast(n ), check); - } - /// \endcond - -} // namespace RandomLib - -#endif // RANDOMLIB_RANDOMTYPE_HPP diff --git a/app/RandomLib/cmake_install.cmake b/app/RandomLib/cmake_install.cmake deleted file mode 100644 index 7d6aa651b01155981f50f629220ea80a44e7d1fa..0000000000000000000000000000000000000000 --- a/app/RandomLib/cmake_install.cmake +++ /dev/null @@ -1,69 +0,0 @@ -# Install script for directory: /home/sacha/Downloads/RandomLib-1.5/include/RandomLib - -# Set the install prefix -IF(NOT DEFINED CMAKE_INSTALL_PREFIX) - SET(CMAKE_INSTALL_PREFIX "/usr/local") -ENDIF(NOT DEFINED CMAKE_INSTALL_PREFIX) -STRING(REGEX REPLACE "/$" "" CMAKE_INSTALL_PREFIX "${CMAKE_INSTALL_PREFIX}") - -# Set the install configuration name. -IF(NOT DEFINED CMAKE_INSTALL_CONFIG_NAME) - IF(BUILD_TYPE) - STRING(REGEX REPLACE "^[^A-Za-z0-9_]+" "" - CMAKE_INSTALL_CONFIG_NAME "${BUILD_TYPE}") - ELSE(BUILD_TYPE) - SET(CMAKE_INSTALL_CONFIG_NAME "Release") - ENDIF(BUILD_TYPE) - MESSAGE(STATUS "Install configuration: \"${CMAKE_INSTALL_CONFIG_NAME}\"") -ENDIF(NOT DEFINED CMAKE_INSTALL_CONFIG_NAME) - -# Set the component getting installed. -IF(NOT CMAKE_INSTALL_COMPONENT) - IF(COMPONENT) - MESSAGE(STATUS "Install component: \"${COMPONENT}\"") - SET(CMAKE_INSTALL_COMPONENT "${COMPONENT}") - ELSE(COMPONENT) - SET(CMAKE_INSTALL_COMPONENT) - ENDIF(COMPONENT) -ENDIF(NOT CMAKE_INSTALL_COMPONENT) - -# Install shared libraries without execute permission? -IF(NOT DEFINED CMAKE_INSTALL_SO_NO_EXE) - SET(CMAKE_INSTALL_SO_NO_EXE "1") -ENDIF(NOT DEFINED CMAKE_INSTALL_SO_NO_EXE) - -IF(NOT CMAKE_INSTALL_COMPONENT OR "${CMAKE_INSTALL_COMPONENT}" STREQUAL "Unspecified") - FILE(INSTALL DESTINATION "${CMAKE_INSTALL_PREFIX}/include/RandomLib" TYPE FILE FILES - "/home/sacha/Downloads/RandomLib-1.5/include/RandomLib/MPFRNormalK.hpp" - "/home/sacha/Downloads/RandomLib-1.5/include/RandomLib/ExponentialDistribution.hpp" - "/home/sacha/Downloads/RandomLib-1.5/include/RandomLib/RandomType.hpp" - "/home/sacha/Downloads/RandomLib-1.5/include/RandomLib/RandomPower2.hpp" - "/home/sacha/Downloads/RandomLib-1.5/include/RandomLib/Random.hpp" - "/home/sacha/Downloads/RandomLib-1.5/include/RandomLib/LeadingZeros.hpp" - "/home/sacha/Downloads/RandomLib-1.5/include/RandomLib/InversePiProb.hpp" - "/home/sacha/Downloads/RandomLib-1.5/include/RandomLib/InverseEProb.hpp" - "/home/sacha/Downloads/RandomLib-1.5/include/RandomLib/MPFRNormal.hpp" - "/home/sacha/Downloads/RandomLib-1.5/include/RandomLib/RandomCanonical.hpp" - "/home/sacha/Downloads/RandomLib-1.5/include/RandomLib/RandomMixer.hpp" - "/home/sacha/Downloads/RandomLib-1.5/include/RandomLib/MPFRNormalR.hpp" - "/home/sacha/Downloads/RandomLib-1.5/include/RandomLib/MPFRExponential.hpp" - "/home/sacha/Downloads/RandomLib-1.5/include/RandomLib/ExactPower.hpp" - "/home/sacha/Downloads/RandomLib-1.5/include/RandomLib/MPFRUniform.hpp" - "/home/sacha/Downloads/RandomLib-1.5/include/RandomLib/MPFRExponentialL.hpp" - "/home/sacha/Downloads/RandomLib-1.5/include/RandomLib/NormalDistribution.hpp" - "/home/sacha/Downloads/RandomLib-1.5/include/RandomLib/RandomSelect.hpp" - "/home/sacha/Downloads/RandomLib-1.5/include/RandomLib/RandomNumber.hpp" - "/home/sacha/Downloads/RandomLib-1.5/include/RandomLib/ExactExponential.hpp" - "/home/sacha/Downloads/RandomLib-1.5/include/RandomLib/RandomSeed.hpp" - "/home/sacha/Downloads/RandomLib-1.5/include/RandomLib/RandomAlgorithm.hpp" - "/home/sacha/Downloads/RandomLib-1.5/include/RandomLib/ExponentialProb.hpp" - "/home/sacha/Downloads/RandomLib-1.5/include/RandomLib/RandomEngine.hpp" - "/home/sacha/Downloads/RandomLib-1.5/include/RandomLib/MPFRRandom.hpp" - "/home/sacha/Downloads/RandomLib-1.5/include/RandomLib/ExactNormal.hpp" - ) -ENDIF(NOT CMAKE_INSTALL_COMPONENT OR "${CMAKE_INSTALL_COMPONENT}" STREQUAL "Unspecified") - -IF(NOT CMAKE_INSTALL_COMPONENT OR "${CMAKE_INSTALL_COMPONENT}" STREQUAL "Unspecified") - FILE(INSTALL DESTINATION "${CMAKE_INSTALL_PREFIX}/include/RandomLib" TYPE FILE FILES "/home/sacha/Downloads/RandomLib-1.5/include/RandomLib/Config.h") -ENDIF(NOT CMAKE_INSTALL_COMPONENT OR "${CMAKE_INSTALL_COMPONENT}" STREQUAL "Unspecified") - diff --git a/app/Services/EIImageService.cpp b/app/Services/EIImageService.cpp index 9cf6d1a8442b117ba1e9e616b4baac252ec9e1e2..20c430b8c16c255c0d78489ccd0ee12d0609d987 100644 --- a/app/Services/EIImageService.cpp +++ b/app/Services/EIImageService.cpp @@ -39,10 +39,10 @@ void EIImageService::display(GenericInterface* gi) _statusEdit = new QTextEdit(); _statusEdit->setReadOnly(true); _statusEdit->setMinimumHeight(1); - _statusEdit->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Maximum); + _statusEdit->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Preferred); _statusEdit->setReadOnly(true); QDockWidget* statusDock = new QDockWidget(tr("Informations"), gi); - statusDock->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Maximum); + statusDock->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Preferred); statusDock->setMinimumWidth(128); statusDock->setWidget(_statusEdit); gi->addDockWidget(Qt::BottomDockWidgetArea, statusDock); @@ -69,9 +69,8 @@ void EIImageService::addOpSet(OpSet* opSet) { void EIImageService::removeOpSet(OpSet* opSet) { for(vector<OpSetService*>::iterator it = _opSetServices.begin(); it != _opSetServices.end(); ++it) { if((*it)->getOpSet() == opSet) { - _opSetServices.erase(it); _gi->removeService(*it); - delete *it; + _opSetServices.erase(it); return; } } @@ -83,3 +82,9 @@ void EIImageService::outputText(QString text) { if(_statusEdit->minimumHeight() < 92) _statusEdit->setMinimumHeight(_statusEdit->minimumHeight()+24); // _statusEdit->setMinimumHeight(32); } + +void EIImageService::addText(std::string s) { + _statusEdit->append(QString::fromStdString(s)); + _statusEdit->show(); + if(_statusEdit->minimumHeight() < 92) _statusEdit->setMinimumHeight(_statusEdit->minimumHeight()+24); +} diff --git a/app/Services/EIImageService.h b/app/Services/EIImageService.h index dfc0fcefbf182162fd8542444b8590e5b04a9353..18de689f2b703323682cdc8e205deffaea521335 100644 --- a/app/Services/EIImageService.h +++ b/app/Services/EIImageService.h @@ -42,6 +42,7 @@ class EIImageService : public genericinterface::WindowService void addOpSet(OpSet* opSet); void removeOpSet(OpSet* opSet); void outputText(QString text); + virtual void addText(std::string); private: genericinterface::GenericInterface* _gi; diff --git a/app/Services/FilteringService.cpp b/app/Services/FilteringService.cpp index 5d82815c7916fc9be5d1efeda9d6a4aa448fcd81..73b1fd5a1bd5b14f1fe385e3c731e7a23acae58a 100644 --- a/app/Services/FilteringService.cpp +++ b/app/Services/FilteringService.cpp @@ -24,6 +24,7 @@ #include <GenericInterface.h> #include <Converter.h> #include <Widgets/ImageWidgets/DoubleImageWindow.h> +#include <QApplication> using namespace filtrme; using namespace genericinterface; @@ -35,10 +36,10 @@ void FilteringService::display(GenericInterface* gi) // _filtering = _toolBar->addAction("&Filtering"); // _filterEdition = _toolBar->addAction("&FilterEditor"); - QMenu* menu = gi->menu(gi->tr("Filtering")); - _filtering = menu->addAction("&Apply filter"); + QMenu* menu = gi->menu(qApp->translate("", "Filtering")); + _filtering = menu->addAction(tr("&Apply filter")); _filtering->setEnabled(false); - _filterEdition = menu->addAction("&Edit filters"); + _filterEdition = menu->addAction(tr("&Edit filters")); } void FilteringService::checkActionsValid(const QWidget* activeWidget) { @@ -63,6 +64,7 @@ void FilteringService::applyFiltering() _siw = siw; _filterChoice = new FilterChoice(_gi); + _filterChoice->setDoubleResult(siw->isDouble()); // QMdiArea* area = (QMdiArea*)_gi->centralWidget(); // area->addSubWindow(_filterChoice); QDialog::DialogCode code = static_cast<QDialog::DialogCode>(_filterChoice->exec()); @@ -70,6 +72,7 @@ void FilteringService::applyFiltering() if(code!=QDialog::Accepted) { return; } + _dblResult = _filterChoice->doubleResult(); Filtering* filtering = _filterChoice->getFiltering(); this->applyAlgorithm(filtering); @@ -109,16 +112,23 @@ void FilteringService::applyAlgorithm(Filtering* algo) ImageWindow* riw; if(_siw->isStandard()) { delete image; + } + if(_dblResult) { + DoubleImageWindow* diw = dynamic_cast<DoubleImageWindow*>(_siw); + if(diw != NULL) { + riw = new DoubleImageWindow(dblResImg, _siw->getPath(), diw->isNormalized(), diw->isLogScaled()); + } + else { + riw = new DoubleImageWindow(dblResImg, _siw->getPath()); + } + } + else { Image_t<int>* intResImg = Converter<Image_t<int> >::convert(*dblResImg); delete dblResImg; Image* resImg = Converter<Image>::makeDisplayable(*intResImg); delete intResImg; riw = new StandardImageWindow(resImg, _siw->getPath()); } - else { - DoubleImageWindow* diw = dynamic_cast<DoubleImageWindow*>(_siw); - riw = new DoubleImageWindow(dblResImg, _siw->getPath(), diw->isNormalized(), diw->isLogScaled()); - } riw->setWindowTitle(_siw->windowTitle()); emit newImageWindowCreated(_ws->getNodeId(_siw), riw); } diff --git a/app/Services/FilteringService.h b/app/Services/FilteringService.h index cc5e5cbb0cb359ace1470ad249ebe86f0cf8f13f..c6c9a55dad83b1e799e983f7280fa577a308303f 100644 --- a/app/Services/FilteringService.h +++ b/app/Services/FilteringService.h @@ -63,6 +63,7 @@ namespace filtrme QStringList _texts; genericinterface::ImageWindow* _siw; + bool _dblResult; }; } diff --git a/app/Services/MorphoMatService.cpp b/app/Services/MorphoMatService.cpp index b3942f0ebbfe146187b2a1cce6ca1f07764789b0..e40bbe99304617e5fac35b08148f2a9e4bbcce06 100644 --- a/app/Services/MorphoMatService.cpp +++ b/app/Services/MorphoMatService.cpp @@ -53,7 +53,7 @@ void MorphoMatService::display(GenericInterface* gi) // _erosion = _toolBar->addAction("&Erosion"); // _dilatation = _toolBar->addAction("&Dilatation"); - QMenu* menu = gi->menu(tr("&Mathematical morphology")); + QMenu* menu = gi->menu("&Morpho. math."); _erosion2 = menu->addAction(tr("&Erosion")); _dilatation2 = menu->addAction(tr("&Dilatation")); diff --git a/app/Services/OperationService.cpp b/app/Services/OperationService.cpp index 57c36192140c24eda4a641863695df0407d27675..f641356a0831144de466841b8f21f284897254c9 100644 --- a/app/Services/OperationService.cpp +++ b/app/Services/OperationService.cpp @@ -21,7 +21,6 @@ #include <GenericInterface.h> #include <Widgets/ImageWidgets/DoubleImageWindow.h> #include <Widgets/ImageWidgets/StandardImageWindow.h> -#include <ImgWidget.h> #include "EIImageService.h" #include <QMessageBox> @@ -40,8 +39,13 @@ OperationService::OperationService(GenericOperation* operation, QMenu* menu) : _ void OperationService::display(GenericInterface* gi) { _gi = gi; - - _action = _menu->addAction(_operation->getName().c_str()); + + if(_operation->getName().length() > 0) { + _action = _menu->addAction(_operation->getName().c_str()); + } + else { + _action = _menu->addSeparator(); + } } void OperationService::connect(GenericInterface* gi) @@ -51,11 +55,11 @@ void OperationService::connect(GenericInterface* gi) void OperationService::operation() { - cout << _operation->getName() << endl; +// cout << _operation->getName() << endl; WindowService* ws = _gi->windowService(); ImageWindow* curImgWnd = ws->getCurrentImageWindow(); - + // StandardImageWindow* curStdImgWnd = NULL; // if (curImgWnd != NULL) // { @@ -69,8 +73,8 @@ void OperationService::operation() { if(_operation->needCurrentImg() && !_operation->isValidImgWnd(curImgWnd)) return; map<const ImageWindow*, string> wndList; - vector<ImageWindow*> windows = ws->getImageWindows(); - for(vector<ImageWindow*>::iterator it = windows.begin(); it < windows.end(); ++it) { + vector<const ImageWindow*> windows = ws->getImageWindows(); + for(vector<const ImageWindow*>::const_iterator it = windows.begin(); it < windows.end(); ++it) { wndList.insert(pair<const ImageWindow*, string>(*it, (*it)->windowTitle().toStdString())); } diff --git a/app/Services/PluginManager.cpp b/app/Services/PluginManager.cpp index c48fc15dc9dc9ea60b6971506dba9b5a3b00bacf..bda6322a74cbde598589dba1d2cdf0413bd7b406 100644 --- a/app/Services/PluginManager.cpp +++ b/app/Services/PluginManager.cpp @@ -33,7 +33,7 @@ using namespace std; PluginManager::PluginManager(GenericInterface* gi) { _gi = gi; - QDir directory("Plugins"); + QDir directory(tr("Plugins")); QStringList files = directory.entryList(); std::cout << files.size() << " files in plugins' directory" << std::endl; for(QStringList::iterator it = files.begin(); it != files.end(); ++it) { @@ -49,10 +49,10 @@ PluginManager::PluginManager(GenericInterface* gi) { void PluginManager::display(GenericInterface* gi) { - QMenu* menu = gi->menu("&Plugin"); + QMenu* menu = gi->menu(tr("&Plugin")); - _loadPluginAction = menu->addAction("&Load plugin"); - _unloadPluginsAction = menu->addAction("&Unload all plugins"); + _loadPluginAction = menu->addAction(tr("&Load plugin")); + _unloadPluginsAction = menu->addAction(tr("&Unload all plugins")); checkActionsValid(); } @@ -75,7 +75,7 @@ void PluginManager::connect(GenericInterface* gi) }*/ void PluginManager::choosePlugin() { - QString file = QFileDialog::getOpenFileName(_gi, "Open a file", QString(), "Images (*.dll *.so *.dylib)"); + QString file = QFileDialog::getOpenFileName(_gi, tr("Load plugin"), QString(), tr("Plugin (*.dll *.so *.dylib)")); if(file.size()==0) return; std::map<std::string, Plugin*>::iterator it = _plugins.find(file.toStdString()); if(it != _plugins.end()) { @@ -128,7 +128,14 @@ void PluginManager::choosePlugin() { } void PluginManager::unloadAllPlugins() { for(std::map<string, Plugin*>::iterator it = _plugins.begin(); it != _plugins.end(); ++it) { - emit removePlugin(it->second); + Plugin* plugin = it->second; + map<Plugin*,QLibrary*>::iterator lit = _libraries.find(plugin); + if(lit != _libraries.end()) { + bool res = lit->second->unload(); + std::cout << "Unloading " << lit->second->fileName().toStdString() << "..." << res << std::endl; + _libraries.erase(lit); + } + emit removePlugin(plugin); } _plugins.clear(); checkActionsValid(); @@ -140,8 +147,14 @@ void PluginManager::unloadPlugin(Plugin* plugin) { //delete it->second; //_pluginServices.erase(it); ////it = _pluginServices.begin(); - _plugins.erase(it->first); + map<Plugin*,QLibrary*>::iterator lit = _libraries.find(plugin); + if(lit != _libraries.end()) { + bool res = lit->second->unload(); + std::cout << "Unloading " << lit->second->fileName().toStdString() << "..." << res << std::endl; + _libraries.erase(lit); + } emit removePlugin(plugin); + _plugins.erase(it); checkActionsValid(); return; } @@ -157,7 +170,7 @@ bool PluginManager::loadPlugin(QString file, bool silent) { QLibrary* library = new QLibrary(file); if(!library->load()) { if(!silent) { - QMessageBox::critical (_gi, "Error loading plugin", library->errorString()); + QMessageBox::critical (_gi, tr("Error loading plugin"), library->errorString()); } return false; } @@ -168,7 +181,7 @@ bool PluginManager::loadPlugin(QString file, bool silent) { if(ptr==0) { if(!silent) { - QMessageBox::critical (_gi, "Error loading plugin", "Could not find the plugin's entry point \"loadPlugin\""); + QMessageBox::critical (_gi, tr("Error loading plugin"), tr("Could not find the plugin's entry point \"loadPlugin\"")); } return false; } @@ -180,7 +193,7 @@ bool PluginManager::loadPlugin(QString file, bool silent) { Plugin* plugin = getPlugin(); if(plugin==NULL) { if(!silent) { - QMessageBox::critical (_gi, "Error loading plugin", "The getPlugin entry point does not return a valid Plugin"); + QMessageBox::critical (_gi, tr("Error loading plugin"), tr("The getPlugin entry point does not return a valid Plugin")); } return false; } @@ -191,6 +204,7 @@ bool PluginManager::loadPlugin(QString file, bool silent) { //PluginService* pluginService = new PluginService(plugin); _plugins.insert(pair<string,Plugin*>(file.toStdString(), plugin)); + _libraries.insert(pair<Plugin*,QLibrary*>(plugin, library)); //_gi->addService(pluginService); emit addPlugin(plugin); checkActionsValid(); diff --git a/app/Services/PluginManager.h b/app/Services/PluginManager.h index b88b7ea0eaba798341cb5b5d140c5a360eb6c00f..6837c45261e83c1a379b4cf813b2fa9b95b4648b 100644 --- a/app/Services/PluginManager.h +++ b/app/Services/PluginManager.h @@ -26,6 +26,7 @@ #include <Services/AlgorithmService.h> #include <QToolBar> +class QLibrary; #include "OpSetService.h" @@ -52,6 +53,7 @@ class PluginManager : public QObject, public genericinterface::Service QAction* _loadPluginAction; QAction* _unloadPluginsAction; std::map<std::string, Plugin*> _plugins; + std::map<Plugin*, QLibrary*> _libraries; void checkActionsValid(); }; diff --git a/app/Tools.h b/app/Tools.h index 4bd1ca014f4b8fa6f008b15e4f52a853b7b663fa..c7d070c3f3791b5d2df49191f5f1fb828e91f85c 100644 --- a/app/Tools.h +++ b/app/Tools.h @@ -21,15 +21,21 @@ #define TOOLS_H #include <QCoreApplication> - +#include <QApplication> +#include <iostream> namespace Tools { - inline QString tr(const char* str) { return QCoreApplication::tr(str); } +// inline QString tr(const char* str) { + +// QString res = qApp->translate("Operations", str); +// std::cout << "Translating " << str << " to " << res.toStdString() << std::endl; +// return res; +// } inline QString colorName(int i, int n) { - if((n==1 || n==2) && i==0) return tr("Black"); - if((n==2 && i==1) || (n==4 && i==3)) return tr("Alpha"); - switch(i) { case 0: return tr("Red"); case 1: return tr("Green"); case 2: return tr("Blue"); default: return tr("Color"); } + if((n==1 || n==2) && i==0) return qApp->translate("Color", "Black"); + if((n==2 && i==1) || (n==4 && i==3)) return qApp->translate("Color", "Alpha"); + switch(i) { case 0: return qApp->translate("Color", "Red"); case 1: return qApp->translate("Color", "Green"); case 2: return qApp->translate("Color", "Blue"); default: return qApp->translate("Color", "Color"); } } } diff --git a/app/Widgets/FilterChoice.cpp b/app/Widgets/FilterChoice.cpp index 18324869556dd831164ab7172a10d593e37584ce..cde0dfbe4579270f4c47dfaa9478b4eea60daad6 100644 --- a/app/Widgets/FilterChoice.cpp +++ b/app/Widgets/FilterChoice.cpp @@ -46,6 +46,10 @@ #include <QtXml/QDomElement> #include <QTextStream> +#include <QGroupBox> +#include <QRadioButton> +#include <QHBoxLayout> + #include <QFormLayout> #include <QSpacerItem> #include <GenericInterface.h> @@ -60,44 +64,72 @@ FilterChoice::FilterChoice(QWidget* parent) : QDialog(parent) initUI(); } +/** + * @brief + * + */ void FilterChoice::initUI() { - this->setWindowTitle("FilterChoice"); + this->setWindowTitle(tr("FilterChoice")); QLayout* layout = new QVBoxLayout(this); QWidget* mainWidget = new QWidget(); layout->addWidget(mainWidget); QHBoxLayout* mainLayout = new QHBoxLayout(mainWidget); QWidget* leftWidget = new QWidget(); - QFormLayout* leftLayout = new QFormLayout(leftWidget); + QLayout* leftLayout = new QVBoxLayout(leftWidget); + QGroupBox* confBox = new QGroupBox(tr("Filter configuration")); + QFormLayout* confLayout = new QFormLayout(confBox); /* FILTER CHOICE */ QLabel* label = new QLabel(this); - label->setText("Filter:"); + label->setText(tr("Filter:")); _blurChoices = new QComboBox(this); QStringList blurs = initFilters(); _blurChoices->addItems(blurs); QObject::connect(_blurChoices, SIGNAL(currentIndexChanged(int)), this, SLOT(currentBlurChanged(int))); - leftLayout->addRow(label, _blurChoices); + confLayout->addRow(label, _blurChoices); /* POLICIES CHOICE */ QLabel* label_2 = new QLabel(this); - label_2->setText("Edge policy: "); + label_2->setText(tr("Edge policy: ")); _policyChoices = new QComboBox(this); QStringList policies = QStringList() << tr("Black") << tr("Mirror") << tr("Nearest") << tr("Spherical"); _policyChoices->addItems(policies); - leftLayout->addRow(label_2, _policyChoices); + _policyChoices->setCurrentIndex(2); + confLayout->addRow(label_2, _policyChoices); _labelNumber = new QLabel(this); - _labelNumber->setText("Number of pixels:"); + _labelNumber->setText(tr("Filter size:")); _number = new QSpinBox(this); _number->setValue(3); _number->setMinimum(1); - leftLayout->addRow(_labelNumber, _number); + confLayout->addRow(_labelNumber, _number); + + _stdDevLabel = new QLabel(tr("Standard deviation : ")); + _stdDevBox = new QDoubleSpinBox(this); + _stdDevBox->setValue(1.); + _stdDevBox->setRange(0., 256.); + _stdDevBox->setSingleStep(0.1); + confLayout->addRow(_stdDevLabel, _stdDevBox); + _stdDevLabel->setVisible(false); + _stdDevBox->setVisible(false); + + QGroupBox* radioBox = new QGroupBox(tr("Resulting image type")); + _stdResButton = new QRadioButton(tr("Standard")); + _dblResButton = new QRadioButton(tr("Floating point")); + radioBox->setLayout(new QHBoxLayout()); + radioBox->layout()->addWidget(_stdResButton); + radioBox->layout()->addWidget(_dblResButton); + + leftLayout->addWidget(confBox); + leftLayout->addWidget(radioBox); + mainLayout->addWidget(leftWidget); QObject::connect(_number, SIGNAL(valueChanged(const QString&)), this, SLOT(dataChanged(const QString&))); + QObject::connect(_stdDevBox, SIGNAL(valueChanged(const QString&)), this, SLOT(dataChanged(const QString&))); QWidget* rightWidget = new QWidget(); @@ -119,7 +151,7 @@ void FilterChoice::initUI() QTableWidgetItem* item = new QTableWidgetItem("1"); item->setTextAlignment(Qt::AlignHCenter); item->setFlags(Qt::ItemIsSelectable|Qt::ItemIsEnabled); - _filterView->setItem(i, j, item); + _filterView->setItem(j, i, item); } } @@ -128,8 +160,8 @@ void FilterChoice::initUI() QDialogButtonBox *buttonBox = new QDialogButtonBox(this); buttonBox->setOrientation(Qt::Horizontal); buttonBox->setStandardButtons(QDialogButtonBox::Cancel); - QPushButton* applyButton = buttonBox->addButton(QString::fromStdString("Apply filter"), QDialogButtonBox::ApplyRole); - _deleteButton = buttonBox->addButton(QString::fromStdString("Delete filter"), QDialogButtonBox::ActionRole); + QPushButton* applyButton = buttonBox->addButton(tr("Apply filter"), QDialogButtonBox::ApplyRole); + _deleteButton = buttonBox->addButton(tr("Delete filter"), QDialogButtonBox::ActionRole); _deleteButton->setEnabled(false); QObject::connect(applyButton, SIGNAL(clicked()), this, SLOT(validate())); @@ -151,13 +183,18 @@ void FilterChoice::initUI() } +/** + * @brief + * + * @return QStringList + */ QStringList FilterChoice::initFilters() { QStringList blurs = QStringList(); blurs << tr("Uniform") << tr("Gaussian") << tr("Prewitt") << tr("Roberts") << tr("Sobel") << tr("SquareLaplacien"); _filters.push_back(Filter::uniform(3)); - _filters.push_back(Filter::gaussian(1)); + _filters.push_back(Filter::gaussian(3, 1.)); _filters.push_back(Filter::prewitt(3)); _filters.push_back(Filter::roberts()); _filters.push_back(Filter::sobel()); @@ -202,13 +239,13 @@ QStringList FilterChoice::initFilters() { // (*f)[w][h] = QString::fromStdString(word).toInt(); f->setPixelAt(w, h, QString::fromStdString(word).toDouble()); - if(h == f->getHeight() - 1) + if(w == f->getWidth() - 1) { - h = 0; - w++; + w = 0; + h++; } else - h++; + w++; } } temp.push_back(f); @@ -223,16 +260,30 @@ QStringList FilterChoice::initFilters() { return blurs; } +/** + * @brief + * + * @param int + */ void FilterChoice::currentBlurChanged(int) { updateDisplay(); } +/** + * @brief + * + * @param + */ void FilterChoice::dataChanged(const QString&) { updateDisplay(); } +/** + * @brief + * + */ void FilterChoice::validate() { int num = _number->value(); @@ -243,7 +294,8 @@ void FilterChoice::validate() _filtering = new Filtering(Filtering::uniformBlur(num)); break; case 1: - _filtering = new Filtering(Filtering::gaussianBlur(num)); + _filtering = new Filtering(Filtering::gaussianBlur(num, _stdDevBox->value())); +// _filtering = new Filtering(_filters[_blurChoices->currentIndex()]); break; case 2: _filtering = new Filtering(Filtering::prewitt(num)); @@ -254,33 +306,38 @@ void FilterChoice::validate() switch(_policyChoices->currentIndex()) { - case 0: - _filtering->setPolicy(Filtering::blackPolicy); - break; case 1: - _filtering->setPolicy(Filtering::mirrorPolicy); + _filtering->setPolicy(Filtering::POLICY_MIRROR); break; case 2: - _filtering->setPolicy(Filtering::nearestPolicy); + _filtering->setPolicy(Filtering::POLICY_NEAREST); break; case 3: - _filtering->setPolicy(Filtering::sphericalPolicy); + _filtering->setPolicy(Filtering::POLICY_TOR); break; default: - _filtering->setPolicy(Filtering::blackPolicy); + _filtering->setPolicy(Filtering::POLICY_BLACK); } this->accept(); } +/** + * @brief + * + */ void FilterChoice::cancel() { // emit(cancelAction()); } +/** + * @brief + * + */ void FilterChoice::deleteFilter() { - QMessageBox msgBox(QMessageBox::Warning, "Warning!", "This filter will be permanently deleted ?"); - msgBox.setInformativeText("Do you want to continue?"); + QMessageBox msgBox(QMessageBox::Warning, tr("Warning!"), tr("This filter will be permanently deleted ?")); + msgBox.setInformativeText(tr("Do you want to continue?")); msgBox.setStandardButtons(QMessageBox::No | QMessageBox::Yes); msgBox.setDefaultButton(QMessageBox::No); @@ -321,6 +378,10 @@ void FilterChoice::deleteFilter() } } +/** + * @brief + * + */ void FilterChoice::updateDisplay() { std::vector<Filter*> filters; @@ -331,24 +392,29 @@ void FilterChoice::updateDisplay() filters = Filter::uniform(num); _number->show(); _labelNumber->show(); - _labelNumber->setText("Number of Pixels:"); + _stdDevBox->hide(); + _stdDevLabel->hide(); break; case 1: - filters = Filter::gaussian(num); + filters = Filter::gaussian(num, _stdDevBox->value()); _number->show(); _labelNumber->show(); - _labelNumber->setText("Coefficient:"); + _stdDevBox->show(); + _stdDevLabel->show(); break; case 2: filters = Filter::prewitt(num); _number->show(); _labelNumber->show(); - _labelNumber->setText("Number of Pixels:"); + _stdDevBox->hide(); + _stdDevLabel->hide(); break; default: filters = _filters[_blurChoices->currentIndex()]; _number->hide(); _labelNumber->hide(); + _stdDevBox->hide(); + _stdDevLabel->hide(); } if(_blurChoices->currentIndex() > 5) @@ -368,35 +434,35 @@ void FilterChoice::updateDisplay() } _filterView->setRowCount(height); _filterView->setColumnCount(width); - for(unsigned int i = 0; i < height; i++) + for(unsigned int j = 0; j < height; j++) { - for(unsigned int j = 0; j < width; j++) + for(unsigned int i = 0; i < width; i++) { QTableWidgetItem* item = new QTableWidgetItem(""); item->setFlags(Qt::ItemIsSelectable|Qt::ItemIsEnabled); - _filterView->setItem(i, j, item); + _filterView->setItem(j, i, item); } } height = 0; for(unsigned int i = 0; i < filters.size(); i++) { - for(unsigned int j = height; j < filters[i]->getWidth() + height; j++) + for(unsigned int j = 0; j < filters[i]->getHeight(); j++) { - for(unsigned int k = 0; k < filters[i]->getHeight(); k++) + for(unsigned int k = 0; k < filters[i]->getWidth(); k++) { // int value = (*filters[i])[j - height][k]; - double value = filters[i]->getPixelAt(j - height, k); + double value = filters[i]->getPixelAt(k, j); QTableWidgetItem* item = new QTableWidgetItem(QString::number(value)); item->setTextAlignment(Qt::AlignHCenter); item->setFlags(Qt::ItemIsSelectable|Qt::ItemIsEnabled); - _filterView->setItem(j, k, item); + _filterView->setItem(height + j, k, item); _filterView->setColumnWidth(k, _filterView->rowHeight(0)); } } - height += filters[i]->getWidth(); - for(unsigned int k = 0; k < filters[i]->getHeight(); k++) + height += filters[i]->getHeight(); + for(unsigned int k = 0; k < filters[i]->getWidth(); k++) { QTableWidgetItem* item = new QTableWidgetItem(""); item->setFlags(Qt::ItemIsSelectable|Qt::ItemIsEnabled); diff --git a/app/Widgets/FilterChoice.h b/app/Widgets/FilterChoice.h index 78a9d7e0fdcb1d4cfb6f0505bb57b17c5354deef..ad2e74cf2b2df7a2c9619641059bec6b98c8ec74 100644 --- a/app/Widgets/FilterChoice.h +++ b/app/Widgets/FilterChoice.h @@ -35,6 +35,7 @@ #include <QPushButton> #include <QStringList> #include <Algorithm/Filtering.h> +#include <QRadioButton> namespace filtrme { @@ -50,7 +51,9 @@ namespace filtrme public: FilterChoice(QWidget *parent); inline imagein::algorithm::Filtering* getFiltering() { return _filtering; } - + inline bool doubleResult() { return _dblResButton->isChecked(); } + inline void setDoubleResult(bool c) { _dblResButton->setChecked(c); _stdResButton->setChecked(!c);} + signals: void choiceValidate(imagein::algorithm::Filtering* filtering); @@ -73,10 +76,14 @@ namespace filtrme QLabel* _labelNumber; QSpinBox* _number; + QDoubleSpinBox* _stdDevBox; + QLabel* _stdDevLabel; QTableWidget* _filterView; QPushButton* _deleteButton; imagein::algorithm::Filtering* _filtering; + QRadioButton* _dblResButton; + QRadioButton* _stdResButton; }; } diff --git a/app/Widgets/FilterEditor.cpp b/app/Widgets/FilterEditor.cpp index 07492527b5e68f6b635bea7dcec29298c7b70686..8be74a49290e236a269be515849145b1242a493f 100644 --- a/app/Widgets/FilterEditor.cpp +++ b/app/Widgets/FilterEditor.cpp @@ -66,10 +66,10 @@ void FilterEditor::initUI() QLabel *label_3; QLabel *label_4; label_3 = new QLabel(); - label_3->setText("Name:"); + label_3->setText(tr("Name:")); _name = new QLineEdit(); label_4 = new QLabel(); - label_4->setText("Number of filters:"); + label_4->setText(tr("Number of filters:")); spinBoxNbFilters = new QSpinBox(); spinBoxNbFilters->setValue(_nbFilters); spinBoxNbFilters->setMinimum(1); @@ -102,7 +102,7 @@ void FilterEditor::initUI() layout->addWidget(scroll); this->setLayout(layout); this->setMinimumSize(670, 470); - this->setWindowTitle("FilterEditor"); + this->setWindowTitle(tr("FilterEditor")); } void FilterEditor::nameChanged(QString name) { @@ -114,7 +114,7 @@ void FilterEditor::save() vector<Filter*> filters; if(_name->text() == "") { - QMessageBox msgBox(QMessageBox::Critical, "Error!", "Your filter has to have a name to be saved."); + QMessageBox msgBox(QMessageBox::Critical, tr("Error!"), tr("Your filter has to have a name to be saved.")); msgBox.setStandardButtons(QMessageBox::Ok); msgBox.setDefaultButton(QMessageBox::Ok); msgBox.exec(); @@ -163,8 +163,8 @@ void FilterEditor::saveXML(vector<Filter*> filtersToSave) // We know how to treat appearance and geometry if (e.attribute("name") == _name->text()) { - QMessageBox msgBox(QMessageBox::Warning, "Warning!", "This filter name is already use."); - msgBox.setInformativeText("Do you want to replace it?"); + QMessageBox msgBox(QMessageBox::Warning, tr("Warning!"), tr("This filter name is already use.")); + msgBox.setInformativeText(tr("Do you want to replace it?")); msgBox.setStandardButtons(QMessageBox::No|QMessageBox::Yes); msgBox.setDefaultButton(QMessageBox::No); int ret = msgBox.exec(); @@ -197,9 +197,9 @@ void FilterEditor::saveXML(vector<Filter*> filtersToSave) valuesNode.setAttribute("height", QString::number(height)); QString s = ""; - for(int w = 0; w < width; w++) + for(int h = 0; h < height; h++) { - for(int h = 0; h < height; h++) + for(int w = 0; w < width; w++) { s += QString::number(filterToSave->getPixelAt(w, h)); if(w != width - 1 || h != height - 1) @@ -237,11 +237,8 @@ vector<Filter*> FilterEditor::validFilters(bool* ok) else { *ok = false; - QMessageBox msgBox(QMessageBox::Critical, "Error!", "Every square have to be completed by int value."); - std::ostringstream oss; - oss << i; - std::string is = oss.str(); - msgBox.setInformativeText(QString::fromStdString("Filter " + is + " isn't ok.")); + QMessageBox msgBox(QMessageBox::Critical, tr("Error!"), tr("Every square have to be completed by int value.")); + msgBox.setInformativeText(tr("Filter %1 isn't ok.").arg(i)); msgBox.setStandardButtons(QMessageBox::Ok); msgBox.setDefaultButton(QMessageBox::Ok); msgBox.exec(); @@ -254,8 +251,8 @@ vector<Filter*> FilterEditor::validFilters(bool* ok) void FilterEditor::cancel() { - QMessageBox msgBox(QMessageBox::Warning, "Warning!", "Unsaved changes will be lost."); - msgBox.setInformativeText("Do you want to continue?"); + QMessageBox msgBox(QMessageBox::Warning, tr("Warning!"), tr("Unsaved changes will be lost.")); + msgBox.setInformativeText(tr("Do you want to continue?")); msgBox.setStandardButtons(QMessageBox::No | QMessageBox::Yes); msgBox.setDefaultButton(QMessageBox::No); int ret = msgBox.exec(); diff --git a/app/Widgets/FilterEditorItem.cpp b/app/Widgets/FilterEditorItem.cpp index 9e4a2b3deb265aeca60b9ac73a309cb4753341cc..6dfcba7c316b78f22755bdf81272c451281acd2b 100644 --- a/app/Widgets/FilterEditorItem.cpp +++ b/app/Widgets/FilterEditorItem.cpp @@ -35,6 +35,8 @@ #include <QtXml/QDomElement> #include <QTextStream> +#include <iostream> +using namespace std; using namespace filtrme; using namespace imagein::algorithm; @@ -69,16 +71,16 @@ void FilterEditorItem::initUI() spinBoxWidth = new QSpinBox(this); spinBoxWidth->setGeometry(QRect(100, 167, 60, 27)); spinBoxWidth->setValue(_width); - spinBoxWidth->setMinimum(2); + spinBoxWidth->setMinimum(1); spinBoxHeight = new QSpinBox(this); spinBoxHeight->setGeometry(QRect(100, 207, 60, 27)); spinBoxHeight->setValue(_height); - spinBoxHeight->setMinimum(2); + spinBoxHeight->setMinimum(1); label = new QLabel(this); - label->setText("Width:"); + label->setText(tr("Width:")); label->setGeometry(QRect(30, 170, 66, 17)); label_2 = new QLabel(this); - label_2->setText("Height:"); + label_2->setText(tr("Height:")); label_2->setGeometry(QRect(30, 210, 66, 17)); this->setMinimumSize(600, 330); @@ -123,9 +125,11 @@ imagein::algorithm::Filter* FilterEditorItem::validFilter() for(int h = 0; h < _height; h++) { double i; - QTableWidgetItem* item = _filter->item(w, h); - if(!item) + QTableWidgetItem* item = _filter->item(h, w); + if(!item) { + cout << "item " << w << ":" << h << " not set !" << endl; ok = false; + } else i = item->text().toDouble(&ok); diff --git a/app/Widgets/ImageZoneSelector.cpp b/app/Widgets/ImageZoneSelector.cpp new file mode 100644 index 0000000000000000000000000000000000000000..45e982d26abb83a387e949c0250373c9fae4110e --- /dev/null +++ b/app/Widgets/ImageZoneSelector.cpp @@ -0,0 +1,84 @@ +/* + * Copyright 2011-2012 INSA Rennes + * + * This file is part of EIImage. + * + * EIImage is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * EIImage 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with EIImage. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include "ImageZoneSelector.h" + +using namespace std; +using namespace imagein; +using namespace genericinterface; + +ImageZoneSelector::ImageZoneSelector(QWidget *parent, const Image *img) : + ImageView(parent, img) +{ + _tracing = false; + _currentRubberBand = NULL; +} + +void ImageZoneSelector::mousePressEvent(QMouseEvent * event) { + _currentRubberBand = new QRubberBand(QRubberBand::Rectangle, _imgWidget); + _start = mapToWidget(event->pos()); + if(_start.x() < 0) _start.setX(0); + if(_start.y() < 0) _start.setY(0); + if(_start.x() >= _imgWidget->width()) _start.setX(_imgWidget->width() - 1); + if(_start.y() >= _imgWidget->height()) _start.setY(_imgWidget->height() - 1); + _currentRubberBand->setGeometry(QRect(_start, _start)); + _currentRubberBand->setVisible(true); + _tracing = true; +} + +bool ImageZoneSelector::isSelectionEmpty() const { + return _rubberBands.empty(); +} + +void ImageZoneSelector::mouseReleaseEvent(QMouseEvent * event) { + _tracing = false; + _rubberBands.push_back(_currentRubberBand); + emit selectionEmptinessChanged(); + _currentRubberBand = NULL; + _start = QPoint(); +} + +void ImageZoneSelector::mouseMoveEvent(QMouseEvent * event) { + if(_tracing && _currentRubberBand != NULL) { + QPoint pos = mapToWidget(event->pos()); + if(pos.x() < 0) pos.setX(0); + if(pos.y() < 0) pos.setY(0); + if(pos.x() >= _imgWidget->width()) pos.setX(_imgWidget->width() - 1); + if(pos.y() >= _imgWidget->height()) pos.setY(_imgWidget->height() - 1); + QRect rect = QRect(_start, pos); + _currentRubberBand->setGeometry(rect.normalized()); + } +} + +void ImageZoneSelector::mouseDoubleClickEvent(QMouseEvent * event) { + event->ignore(); +} + +void ImageZoneSelector::wheelEvent(QWheelEvent* event) { + event->ignore(); +} + +vector<Rectangle> ImageZoneSelector::getSelections() const { + vector<Rectangle> selections; + for(vector<QRubberBand*>::const_iterator it = _rubberBands.begin(); it < _rubberBands.end(); ++it) { + QRect rect = _imgWidget->mapToPixmap((*it)->geometry()); + selections.push_back(Rectangle(rect.x(), rect.y(), rect.width(), rect.height())); + } + return selections; +} diff --git a/app/Widgets/ImageZoneSelector.h b/app/Widgets/ImageZoneSelector.h new file mode 100644 index 0000000000000000000000000000000000000000..26dee4101583b14b8c41d3e437868a2d1566a9f0 --- /dev/null +++ b/app/Widgets/ImageZoneSelector.h @@ -0,0 +1,54 @@ +/* + * Copyright 2011-2012 INSA Rennes + * + * This file is part of EIImage. + * + * EIImage is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * EIImage 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with EIImage. If not, see <http://www.gnu.org/licenses/>. +*/ + +#ifndef IMAGEZONESELECTOR_H +#define IMAGEZONESELECTOR_H + +#include <Widgets/ImageWidgets/ImageView.h> +#include <QRubberBand> +#include <vector> + +class ImageZoneSelector : public genericinterface::ImageView +{ + Q_OBJECT +public: + explicit ImageZoneSelector(QWidget *parent = 0, const imagein::Image* img = NULL); + std::vector<imagein::Rectangle> getSelections() const; + bool isSelectionEmpty() const; + +signals: + void selectionEmptinessChanged(); + +public slots: + +protected: + + void mousePressEvent(QMouseEvent * event); + void mouseReleaseEvent(QMouseEvent * event); + void mouseMoveEvent(QMouseEvent * event); + void mouseDoubleClickEvent(QMouseEvent * event); + void wheelEvent(QWheelEvent* event); + + std::vector<QRubberBand*> _rubberBands; + bool _tracing; + QPoint _start; + QRubberBand* _currentRubberBand; +}; + +#endif // IMAGEZONESELECTOR_H diff --git a/app/Widgets/StructElemWindow.cpp b/app/Widgets/StructElemWindow.cpp index 241ef330b1632a057bd874151fa37a898d52f22b..84961555d1428c87d1f5fc3af779f85fbf33540c 100644 --- a/app/Widgets/StructElemWindow.cpp +++ b/app/Widgets/StructElemWindow.cpp @@ -38,8 +38,8 @@ StructElemWindow::StructElemWindow(StructElem*& elem, QAction* tbButton) : _stru QVBoxLayout* layout = new QVBoxLayout(); _toolBar = new QToolBar; - _openFile = _toolBar->addAction("&Open file"); - _saveFile = _toolBar->addAction("&Save as..."); + _openFile = _toolBar->addAction(tr("&Open file")); + _saveFile = _toolBar->addAction(tr("&Save as...")); layout->addWidget(_toolBar); this->setLayout(layout); @@ -50,19 +50,19 @@ StructElemWindow::StructElemWindow(StructElem*& elem, QAction* tbButton) : _stru QHBoxLayout* layout2 = new QHBoxLayout(); layout->addLayout(layout2); - layout2->addWidget(new QLabel("Basic shapes :")); + layout2->addWidget(new QLabel(tr("Basic shapes :"))); _shapeToGen = new QComboBox; _shapeToGen->setEditable(false); - _shapeToGen->insertItem(0, "Diamond"); - _shapeToGen->insertItem(1, "Disc"); - _shapeToGen->insertItem(2, "Empty"); + _shapeToGen->insertItem(0, tr("Diamond")); + _shapeToGen->insertItem(1, tr("Disc")); + _shapeToGen->insertItem(2, tr("Empty")); layout2->addWidget(_shapeToGen); _shapeSize = new QSpinBox(); _shapeSize->setRange(1,64); _shapeSize->setSingleStep(1); _shapeSize->setValue(3); layout2->addWidget(_shapeSize); - _genButton = new QPushButton("Generate"); + _genButton = new QPushButton(tr("Generate")); layout2->addWidget(_genButton); _viewer = new StructElemViewer(_structElem); @@ -73,7 +73,7 @@ StructElemWindow::StructElemWindow(StructElem*& elem, QAction* tbButton) : _stru QHBoxLayout* layout3 = new QHBoxLayout(); layout->addLayout(layout3); - layout3->addWidget(new QLabel("Scale :")); + layout3->addWidget(new QLabel(tr("Scale :"))); QSpinBox* spinBox = new QSpinBox(); spinBox->setRange(1,32); spinBox->setSingleStep(1); @@ -172,7 +172,7 @@ void StructElemWindow::generate() { } } - if(_shapeToGen->currentText()=="Disc") { + if(_shapeToGen->currentText()==tr("Disc")) { const float radius = (size)/2.0f; const float center = radius; for(unsigned int j = 0; j < elem.getHeight(); ++j) { @@ -192,7 +192,7 @@ void StructElemWindow::generate() { } //rasterCircle(elem, size/2, size/2, size/2); } - else if(_shapeToGen->currentText()=="Diamond") { + else if(_shapeToGen->currentText()==tr("Diamond")) { const float radius = (size)/2.0f; const float center = radius; for(unsigned int j = 0; j < elem.getHeight(); ++j) { @@ -244,7 +244,7 @@ void StructElemWindow::changeStructElem(imagein::MorphoMat::StructElem* elem) { } void StructElemWindow::openFile() { - QString file = QFileDialog::getOpenFileName(this, "Open a file", QString(), "Images (*.png *.bmp *.jpg *.jpeg)"); + QString file = QFileDialog::getOpenFileName(this, tr("Open a file"), QString(), tr("Images (*.png *.bmp *.jpg *.jpeg)")); if(file.size()==0) return; //Image image(file.toStdString()); //Otsu algo; @@ -265,7 +265,7 @@ void StructElemWindow::openFile() { } void StructElemWindow::saveFile() { - QString file = QFileDialog::getSaveFileName(this, "Save file", QString(), "Images (*.png *.bmp *.jpg *.jpeg)"); + QString file = QFileDialog::getSaveFileName(this, tr("Save file"), QString(), tr("Images (*.png *.bmp *.jpg *.jpeg)")); if(file.size()==0) return; //GrayscaleImage img(_structElem->getWidth(), _structElem->getHeight()); diff --git a/app/eiimage_app_res.qrc b/app/eiimage_app_res.qrc index 4d7bce60407f2d1d60044af722d96a9f49cd7827..92c6781935acdccc29f3655483ceb741076e6e35 100644 --- a/app/eiimage_app_res.qrc +++ b/app/eiimage_app_res.qrc @@ -1,12 +1,13 @@ <RCC> - <qresource prefix="/"> - <file>img/arrow-bottom.png</file> - <file>img/arrow-bottom-left.png</file> - <file>img/arrow-bottom-right.png</file> - <file>img/arrow-left.png</file> - <file>img/arrow-right.png</file> - <file>img/arrow-top.png</file> - <file>img/arrow-top-left.png</file> - <file>img/arrow-top-right.png</file> - </qresource> + <qresource prefix="/"> + <file>img/micd.png</file> + <file>img/arrow-bottom.png</file> + <file>img/arrow-bottom-left.png</file> + <file>img/arrow-bottom-right.png</file> + <file>img/arrow-left.png</file> + <file>img/arrow-right.png</file> + <file>img/arrow-top.png</file> + <file>img/arrow-top-left.png</file> + <file>img/arrow-top-right.png</file> + </qresource> </RCC> diff --git a/app/eiimage_en.ts b/app/eiimage_en.ts new file mode 100644 index 0000000000000000000000000000000000000000..b3bd2d02885234c5b4bd8ce36b6935266292e3ac --- /dev/null +++ b/app/eiimage_en.ts @@ -0,0 +1,2852 @@ +<?xml version="1.0" encoding="utf-8"?> +<!DOCTYPE TS> +<TS version="2.0" language="en_US"> +<context> + <name></name> + <message> + <location filename="main.cpp" line="124"/> + <source>&Image</source> + <oldsource>Image</oldsource> + <translation>&Image</translation> + </message> + <message> + <location filename="main.cpp" line="139"/> + <source>&Tools</source> + <oldsource>Tools</oldsource> + <translation>&Tools</translation> + </message> + <message> + <location filename="main.cpp" line="151"/> + <source>&Encoding</source> + <oldsource>Encoding</oldsource> + <translation>&Encoding</translation> + </message> + <message> + <location filename="main.cpp" line="159"/> + <source>Transforms</source> + <translation>Transforms</translation> + </message> + <message> + <location filename="main.cpp" line="167"/> + <source>Analysis</source> + <translation>Analysis</translation> + </message> + <message> + <location filename="Services/FilteringService.cpp" line="39"/> + <location filename="main.cpp" line="176"/> + <source>Filtering</source> + <translation>Filtering</translation> + </message> +</context> +<context> + <name>BFlit</name> + <message> + <location filename="Operations/BFlitOp.cpp" line="59"/> + <source>Number of point on each side : </source> + <translation>Number of points on each side : </translation> + </message> + <message> + <location filename="Operations/BFlitOp.cpp" line="60"/> + <source>Number of iteration : </source> + <translation>Number of iteration : </translation> + </message> +</context> +<context> + <name>BFlitOp</name> + <message> + <source>BFlit</source> + <translation type="obsolete">BFlit</translation> + </message> + <message> + <source>Parameters</source> + <translation type="obsolete">Parameters</translation> + </message> + <message> + <source>Validate</source> + <translation type="obsolete">Validate</translation> + </message> +</context> +<context> + <name>CenterOp</name> + <message> + <source>Center</source> + <translation type="obsolete">Center</translation> + </message> + <message> + <location filename="Operations/CenterOp.cpp" line="72"/> + <source>centered</source> + <oldsource> - centered</oldsource> + <translation>centered</translation> + </message> +</context> +<context> + <name>ClassAnalysis</name> + <message> + <location filename="Operations/ClassAnalysisOp.cpp" line="60"/> + <location filename="Operations/ClassAnalysisOp.cpp" line="79"/> + <source>mean</source> + <translation>mean</translation> + </message> + <message> + <location filename="Operations/ClassAnalysisOp.cpp" line="61"/> + <location filename="Operations/ClassAnalysisOp.cpp" line="80"/> + <source>standard deviation</source> + <translation>standard deviation</translation> + </message> + <message> + <location filename="Operations/ClassAnalysisOp.cpp" line="78"/> + <source>classified</source> + <translation>classified</translation> + </message> +</context> +<context> + <name>ClassAnalysisDialog</name> + <message> + <source>Dialog</source> + <translation type="obsolete">Dialog</translation> + </message> + <message> + <location filename="Operations/ClassAnalysisDialog.ui" line="14"/> + <source>Class analysis</source> + <translation>Class analysis</translation> + </message> + <message> + <location filename="Operations/ClassAnalysisDialog.ui" line="22"/> + <source>Step : </source> + <translation>Step : </translation> + </message> + <message> + <location filename="Operations/ClassAnalysisDialog.ui" line="35"/> + <source>Classification step</source> + <translation>Classification step</translation> + </message> + <message> + <location filename="Operations/ClassAnalysisDialog.ui" line="30"/> + <source>Learning step</source> + <translation>Learning step</translation> + </message> + <message> + <location filename="Operations/ClassAnalysisDialog.ui" line="40"/> + <source>Print file info</source> + <translation>Print file info</translation> + </message> + <message> + <location filename="Operations/ClassAnalysisDialog.ui" line="48"/> + <source>Window size : </source> + <translation>Window size : </translation> + </message> + <message> + <location filename="Operations/ClassAnalysisDialog.ui" line="71"/> + <source>File : </source> + <translation>File : </translation> + </message> + <message> + <location filename="Operations/ClassAnalysisDialog.ui" line="83"/> + <source>browse</source> + <translation>browse</translation> + </message> + <message> + <location filename="Operations/ClassAnalysisDialog.cpp" line="35"/> + <source>Please select the image's area to classify :</source> + <translation>Please select the image's area to classify :</translation> + </message> +</context> +<context> + <name>ClassResult</name> + <message> + <location filename="Operations/ClassResultOp.cpp" line="81"/> + <source> +Nombre de classes = %1 </source> + <oldsource> +Nombre de classes = %1 +</oldsource> + <translation> +Number of classes = %1 </translation> + </message> + <message> + <location filename="Operations/ClassResultOp.cpp" line="85"/> + <source>Valeur de la classe %1 = %2</source> + <oldsource>Valeur de la classe %1 = %2 +</oldsource> + <translation>Value of class %1 = %2</translation> + </message> + <message> + <location filename="Operations/ClassResultOp.cpp" line="80"/> + <source>Voici les résultats du classement : +</source> + <translation>Here are the classification results : +</translation> + </message> + <message> + <location filename="Operations/ClassResultOp.cpp" line="58"/> + <source>Critère de zone intérieure : </source> + <translation>Inner zone criterion : </translation> + </message> + <message> + <location filename="Operations/ClassResultOp.cpp" line="59"/> + <source>Critère de zone frontière : </source> + <translation>Border zone criterion : </translation> + </message> + <message> + <location filename="Operations/ClassResultOp.cpp" line="60"/> + <source><b>Critère de zones (relatifs aux zones totales) : </b></source> + <translation><b>Areas' criteria (relative to the whole zones) : </b></translation> + </message> + <message> + <location filename="Operations/ClassResultOp.cpp" line="62"/> + <source><b>Select the image's classes zones : </b></source> + <translation><b>Select the image's classes zones : </b></translation> + </message> + <message> + <location filename="Operations/ClassResultOp.cpp" line="121"/> + <source>Le taux de bon classement en zone intérieure %1 vaut: %2%</source> + <oldsource>Le taux de bon classement en zone intérieure %1 vaut: %2% +</oldsource> + <translation>The correct classification rate in inner area %1 is %2%</translation> + </message> + <message> + <location filename="Operations/ClassResultOp.cpp" line="124"/> + <source>Le taux de bon classement en zone frontière %1 vaut: %2%</source> + <oldsource>Le taux de bon classement en zone frontière %1 vaut: %2% +</oldsource> + <translation>The correct classification rate in border area %1 is %2%</translation> + </message> + <message> + <location filename="Operations/ClassResultOp.cpp" line="135"/> + <source>Le taux de bon classement en zone intérieure globale vaut: %1%</source> + <oldsource>Le taux de bon classement en zone intérieure globale vaut: %1% +</oldsource> + <translation>The global correct classification rate in inner area is %1%</translation> + </message> + <message> + <location filename="Operations/ClassResultOp.cpp" line="136"/> + <source>Le taux de bon classement en zone frontière globale vaut: %1%</source> + <oldsource>Le taux de bon classement en zone frontière globale vaut: %1% +</oldsource> + <translation>The global correct classification rate in border area is %1%</translation> + </message> +</context> +<context> + <name>Color</name> + <message> + <location filename="Tools.h" line="36"/> + <source>Black</source> + <translation>Black</translation> + </message> + <message> + <location filename="Tools.h" line="37"/> + <source>Alpha</source> + <translation>Alpha</translation> + </message> + <message> + <location filename="Tools.h" line="38"/> + <source>Red</source> + <translation>Red</translation> + </message> + <message> + <location filename="Tools.h" line="38"/> + <source>Green</source> + <translation>Green</translation> + </message> + <message> + <location filename="Tools.h" line="38"/> + <source>Blue</source> + <translation>Blue</translation> + </message> + <message> + <location filename="Tools.h" line="38"/> + <source>Color</source> + <translation>Color</translation> + </message> +</context> +<context> + <name>ColorDialog</name> + <message> + <source>Dialog</source> + <translation type="obsolete">Dialog</translation> + </message> + <message> + <location filename="Operations/ColorDialog.ui" line="14"/> + <source>RGB image generator</source> + <translation>RGB image generator</translation> + </message> + <message> + <location filename="Operations/ColorDialog.ui" line="20"/> + <source>Image size</source> + <translation>Image size</translation> + </message> + <message> + <location filename="Operations/ColorDialog.ui" line="26"/> + <source>Width : </source> + <translation>Width : </translation> + </message> + <message> + <location filename="Operations/ColorDialog.ui" line="40"/> + <source>Height : </source> + <translation>Height : </translation> + </message> + <message> + <location filename="Operations/ColorDialog.ui" line="57"/> + <source>Mode</source> + <translation>Mode</translation> + </message> + <message> + <location filename="Operations/ColorDialog.ui" line="63"/> + <source>RGB</source> + <translation>RGB</translation> + </message> + <message> + <location filename="Operations/ColorDialog.ui" line="73"/> + <source>HSV</source> + <translation>HSV</translation> + </message> + <message> + <location filename="Operations/ColorDialog.ui" line="86"/> + <source>Red : </source> + <translation>Red : </translation> + </message> + <message> + <location filename="Operations/ColorDialog.ui" line="100"/> + <source>Green : </source> + <translation>Green : </translation> + </message> + <message> + <location filename="Operations/ColorDialog.ui" line="114"/> + <source>Blue : </source> + <translation>Blue : </translation> + </message> + <message> + <location filename="Operations/ColorDialog.ui" line="147"/> + <source>Saturation : </source> + <translation>Saturation : </translation> + </message> + <message> + <location filename="Operations/ColorDialog.ui" line="161"/> + <source>Value : </source> + <translation>Value : </translation> + </message> + <message> + <location filename="Operations/ColorDialog.ui" line="175"/> + <source>Hue : </source> + <translation>Hue : </translation> + </message> +</context> +<context> + <name>ColorimetryOp</name> + <message> + <source>Colorimetry</source> + <translation type="obsolete">Colorimetry</translation> + </message> + <message> + <source>Zero crossing</source> + <translation type="obsolete">Zero crossing</translation> + </message> + <message> + <source>Red : </source> + <translation type="obsolete">Red : </translation> + </message> + <message> + <source>Green : </source> + <translation type="obsolete">Green : </translation> + </message> + <message> + <source>Blue : </source> + <translation type="obsolete">Blue : </translation> + </message> + <message> + <source>Hue : </source> + <translation type="obsolete">Hue : </translation> + </message> + <message> + <source>Saturation : </source> + <translation type="obsolete">Saturation : </translation> + </message> + <message> + <source>Value : </source> + <translation type="obsolete">Value : </translation> + </message> + <message> + <source>Red: </source> + <translation type="obsolete">Red: </translation> + </message> + <message> + <source>Green: </source> + <translation type="obsolete">Green: </translation> + </message> + <message> + <source>Blue: </source> + <translation type="obsolete">Blue: </translation> + </message> + <message> + <source>Hue: </source> + <translation type="obsolete">Hue: </translation> + </message> + <message> + <source>Saturation: </source> + <translation type="obsolete">Saturation: </translation> + </message> + <message> + <source>Value: </source> + <translation type="obsolete">Value: </translation> + </message> +</context> +<context> + <name>CombineColorOp</name> + <message> + <source>Combine color planes</source> + <translation type="obsolete">Combine color planes</translation> + </message> + <message> + <source>Parameters</source> + <translation type="obsolete">Parameters</translation> + </message> + <message> + <location filename="Operations/CombineColorOp.cpp" line="95"/> + <source>Reconstructed color image</source> + <translation>Reconstructed color image</translation> + </message> +</context> +<context> + <name>CroissanceOp</name> + <message> + <source>Croissance</source> + <translation type="obsolete">Croissance</translation> + </message> + <message> + <location filename="Operations/CroissanceOp.cpp" line="59"/> + <source>At origin</source> + <translation>At origin</translation> + </message> + <message> + <location filename="Operations/CroissanceOp.cpp" line="60"/> + <source>Point of lowest luminance</source> + <translation>Point of lowest luminance</translation> + </message> + <message> + <location filename="Operations/CroissanceOp.cpp" line="62"/> + <source>| current - mean | < threshold</source> + <translation>| current - mean | < threshold</translation> + </message> + <message> + <location filename="Operations/CroissanceOp.cpp" line="63"/> + <source>| current - initial | < threshold</source> + <translation>| current - initial | < threshold</translation> + </message> + <message> + <location filename="Operations/CroissanceOp.cpp" line="66"/> + <source>Threshold : </source> + <translation>Threshold : </translation> + </message> + <message> + <location filename="Operations/CroissanceOp.cpp" line="67"/> + <source>Initial germ : </source> + <translation>Initial germ : </translation> + </message> + <message> + <location filename="Operations/CroissanceOp.cpp" line="68"/> + <source>Stopping point : </source> + <translation>Stopping point : </translation> + </message> + <message> + <location filename="Operations/CroissanceOp.cpp" line="101"/> + <source>Luminance</source> + <translation>Luminance</translation> + </message> + <message> + <location filename="Operations/CroissanceOp.cpp" line="102"/> + <source>Color</source> + <translation>Color</translation> + </message> + <message> + <location filename="Operations/CroissanceOp.cpp" line="103"/> + <source>Total number of area : %1</source> + <translation>Total number of area : %1</translation> + </message> + <message> + <location filename="Operations/CroissanceOp.cpp" line="104"/> + <source>Mean number of point per area : %1</source> + <translation>Mean number of point per area : %1</translation> + </message> +</context> +<context> + <name>DCT</name> + <message> + <location filename="Operations/DCTOp.cpp" line="57"/> + <source>DCT</source> + <translation>DCT</translation> + </message> + <message> + <location filename="Operations/DCTOp.cpp" line="58"/> + <source>inverse DCT</source> + <translation>inverse DCT</translation> + </message> +</context> +<context> + <name>DCTDialog</name> + <message> + <source>Dialog</source> + <translation type="obsolete">Dialog</translation> + </message> + <message> + <location filename="Operations/DCTDialog.ui" line="14"/> + <source>DCT encoding</source> + <translation>DCT with encoding</translation> + </message> + <message> + <location filename="Operations/DCTDialog.ui" line="20"/> + <source>Encoding mode && associated parameters</source> + <translation>Encoding mode && associated parameters</translation> + </message> + <message> + <location filename="Operations/DCTDialog.ui" line="26"/> + <source>Coefficients truncation</source> + <translation>Coefficients truncation</translation> + </message> + <message> + <location filename="Operations/DCTDialog.ui" line="60"/> + <source>Truncation limit : </source> + <translation>Truncation limit : </translation> + </message> + <message> + <location filename="Operations/DCTDialog.ui" line="79"/> + <source>Bit allocation matrice</source> + <translation>Bit allocation matrice</translation> + </message> + <message> + <location filename="Operations/DCTDialog.ui" line="104"/> + <source>Initial number of bits : </source> + <translation>Initial number of bits : </translation> + </message> + <message> + <location filename="Operations/DCTDialog.ui" line="141"/> + <source>Slope value : </source> + <translation>Slope value : </translation> + </message> +</context> +<context> + <name>DMM</name> + <message> + <location filename="Operations/DMMOp.cpp" line="194"/> + <source>DMM error</source> + <translation>DMM (error)</translation> + </message> +</context> +<context> + <name>DMMDialog</name> + <message> + <location filename="Operations/DMMDialog.cpp" line="44"/> + <location filename="Operations/DMMDialog.cpp" line="279"/> + <source>Erosion</source> + <translation>Erosion</translation> + </message> + <message> + <location filename="Operations/DMMDialog.cpp" line="44"/> + <location filename="Operations/DMMDialog.cpp" line="276"/> + <source>Dilatation</source> + <translation>Dilatation</translation> + </message> + <message> + <location filename="Operations/DMMDialog.cpp" line="44"/> + <location filename="Operations/DMMDialog.cpp" line="282"/> + <source>Opening</source> + <translation>Opening</translation> + </message> + <message> + <location filename="Operations/DMMDialog.cpp" line="44"/> + <location filename="Operations/DMMDialog.cpp" line="285"/> + <source>Closing</source> + <translation>Closing</translation> + </message> + <message> + <location filename="Operations/DMMDialog.cpp" line="44"/> + <location filename="Operations/DMMDialog.cpp" line="46"/> + <source>DMM</source> + <translation>DMM</translation> + </message> + <message> + <location filename="Operations/DMMDialog.cpp" line="62"/> + <source>Structuring element</source> + <translation>Structuring element</translation> + </message> + <message> + <location filename="Operations/DMMDialog.cpp" line="128"/> + <source>Validate</source> + <translation>Validate</translation> + </message> +</context> +<context> + <name>DMMOp</name> + <message> + <source>DMM</source> + <translation type="obsolete">DMM</translation> + </message> + <message> + <location filename="Operations/DMMOp.cpp" line="56"/> + <source>DMM (dilatation)</source> + <translation>DMM (dilatation)</translation> + </message> + <message> + <location filename="Operations/DMMOp.cpp" line="62"/> + <source>DMM (erosion)</source> + <translation>DMM (erosion)</translation> + </message> + <message> + <location filename="Operations/DMMOp.cpp" line="68"/> + <source>DMM (opening)</source> + <translation>DMM (opening)</translation> + </message> + <message> + <location filename="Operations/DMMOp.cpp" line="74"/> + <source>DMM (closing)</source> + <translation>DMM (closing)</translation> + </message> + <message> + <location filename="Operations/DMMOp.cpp" line="192"/> + <source>DMM component #%1</source> + <translation>DMM (component #%1)</translation> + </message> +</context> +<context> + <name>Dialog</name> + <message> + <location filename="Operations/MICDDialog_.ui" line="17"/> + <source>MICD Encoding</source> + <translation>MICD Encoding</translation> + </message> + <message> + <location filename="Operations/MICDDialog_.ui" line="41"/> + <source>Predictor P(X)</source> + <translation>Predictor P(X)</translation> + </message> + <message> + <location filename="Operations/MICDDialog_.ui" line="47"/> + <source>A</source> + <translation>A</translation> + </message> + <message> + <location filename="Operations/MICDDialog_.ui" line="54"/> + <source>C</source> + <translation>C</translation> + </message> + <message> + <location filename="Operations/MICDDialog_.ui" line="61"/> + <source>(A + C) / 2</source> + <translation>(A + C) / 2</translation> + </message> + <message> + <location filename="Operations/MICDDialog_.ui" line="68"/> + <source>Modified Graham's</source> + <translation>Modified Graham's</translation> + </message> + <message> + <location filename="Operations/MICDDialog_.ui" line="77"/> + <source>Q = </source> + <translation>Q = </translation> + </message> + <message> + <location filename="Operations/MICDDialog_.ui" line="120"/> + <source>Quantifier</source> + <translation>Quantifier</translation> + </message> + <message> + <location filename="Operations/MICDDialog_.ui" line="126"/> + <source>Quantification file :</source> + <translation>Quantification file :</translation> + </message> + <message> + <location filename="Operations/MICDDialog_.ui" line="146"/> + <source>Browse</source> + <translation>Browse</translation> + </message> + <message> + <location filename="Operations/MICDDialog_.ui" line="174"/> + <source>Open quantification editor</source> + <translation>Open quantification editor</translation> + </message> +</context> +<context> + <name>EIImageService</name> + <message> + <location filename="Services/EIImageService.cpp" line="44"/> + <source>Informations</source> + <translation>Informations</translation> + </message> +</context> +<context> + <name>EntropyOp</name> + <message> + <source>Calcul d'entropie</source> + <translation type="obsolete">Entropy calculation</translation> + </message> + <message> + <source>Entropy of the image = %1</source> + <translation type="obsolete">Entropy of the image = %1</translation> + </message> +</context> +<context> + <name>FFTDialog</name> + <message> + <location filename="Operations/FFTDialog.ui" line="14"/> + <source>Dialog</source> + <translation>Dialog</translation> + </message> + <message utf8="true"> + <location filename="Operations/FFTDialog.ui" line="20"/> + <source>Résultat :</source> + <translation>Result :</translation> + </message> + <message> + <location filename="Operations/FFTDialog.ui" line="28"/> + <source>Magnitude + Phase</source> + <translation>Magnitude + Phase</translation> + </message> + <message> + <location filename="Operations/FFTDialog.ui" line="38"/> + <source>Real + Imaginary</source> + <translation>Real + Imaginary</translation> + </message> + <message> + <location filename="Operations/FFTDialog.ui" line="47"/> + <source>Centered transform</source> + <translation>Centered transform</translation> + </message> +</context> +<context> + <name>FFTOp</name> + <message> + <source>Discrete Fourier transform</source> + <translation type="obsolete">Discrete Fourier transform</translation> + </message> + <message> + <location filename="Operations/FFTOp.cpp" line="96"/> + <source>DFT (phase)</source> + <translation>DFT (phase)</translation> + </message> + <message> + <location filename="Operations/FFTOp.cpp" line="97"/> + <source>DFT (magnitude)</source> + <translation>DFT (magnitude)</translation> + </message> +</context> +<context> + <name>FlipOp</name> + <message> + <source>Flip %1</source> + <translation type="obsolete">Flip %1</translation> + </message> + <message> + <location filename="Operations/FlipOp.cpp" line="30"/> + <location filename="Operations/FlipOp.cpp" line="62"/> + <source>horizontal</source> + <translation>horizontal</translation> + </message> + <message> + <location filename="Operations/FlipOp.cpp" line="30"/> + <location filename="Operations/FlipOp.cpp" line="62"/> + <source>vertical</source> + <translation>vertical</translation> + </message> + <message> + <location filename="Operations/FlipOp.cpp" line="62"/> + <source>flipped %1</source> + <translation>flipped %1</translation> + </message> + <message> + <source> - flipped %1</source> + <translation type="obsolete"> - flipped %1</translation> + </message> +</context> +<context> + <name>HistogramOp</name> + <message> + <location filename="Operations/HistogramOp.cpp" line="42"/> + <source>Histogram operations</source> + <translation>Histogram operations</translation> + </message> + <message> + <location filename="Operations/HistogramOp.cpp" line="48"/> + <source>Equalize</source> + <translation>Equalize</translation> + </message> + <message> + <location filename="Operations/HistogramOp.cpp" line="49"/> + <source>Normalize</source> + <translation>Normalize</translation> + </message> + <message> + <location filename="Operations/HistogramOp.cpp" line="50"/> + <source>Operation : </source> + <translation>Operation : </translation> + </message> + <message> + <location filename="Operations/HistogramOp.cpp" line="63"/> + <source>equalized</source> + <translation>equalized</translation> + </message> + <message> + <location filename="Operations/HistogramOp.cpp" line="67"/> + <source>normalized</source> + <translation>normalized</translation> + </message> +</context> +<context> + <name>Hough</name> + <message> + <location filename="Operations/HoughOp.cpp" line="53"/> + <source>Hough transform</source> + <translation>Hough transform</translation> + </message> + <message> + <location filename="Operations/InverseHoughOp.cpp" line="44"/> + <source>Hough inverse transform</source> + <translation>Hough inverse transform</translation> + </message> +</context> +<context> + <name>HoughDialog</name> + <message> + <source>Dialog</source> + <translation type="obsolete">Dialog</translation> + </message> + <message> + <location filename="Operations/HoughDialog.ui" line="14"/> + <source>Hough transform</source> + <translation>Hough transform</translation> + </message> + <message> + <location filename="Operations/HoughDialog.ui" line="20"/> + <source>Method</source> + <translation>Method</translation> + </message> + <message> + <location filename="Operations/HoughDialog.ui" line="26"/> + <source>Method #1</source> + <translation>Method #1</translation> + </message> + <message> + <location filename="Operations/HoughDialog.ui" line="36"/> + <source>Method #2</source> + <translation>Method #2</translation> + </message> + <message> + <location filename="Operations/HoughDialog.ui" line="57"/> + <source>Angle step : </source> + <translation>Angle step : </translation> + </message> + <message> + <location filename="Operations/HoughDialog.ui" line="93"/> + <source>Distance step : </source> + <translation>Distance step : </translation> + </message> +</context> +<context> + <name>HuffmanOp</name> + <message> + <source>Huffman</source> + <translation type="obsolete">Huffman</translation> + </message> +</context> +<context> + <name>IFFTOp</name> + <message> + <source>Discrete Fourier reconstruction</source> + <translation type="obsolete">Discrete Fourier reconstruction</translation> + </message> + <message> + <source>Parameters</source> + <translation type="obsolete">Parameters</translation> + </message> + <message> + <location filename="Operations/IFFTOp.cpp" line="66"/> + <source>Magnitude : </source> + <translation>Magnitude : </translation> + </message> + <message> + <location filename="Operations/IFFTOp.cpp" line="67"/> + <source>Phase : </source> + <translation>Phase : </translation> + </message> + <message> + <location filename="Operations/IFFTOp.cpp" line="72"/> + <source>Real part : </source> + <translation>Real part : </translation> + </message> + <message> + <location filename="Operations/IFFTOp.cpp" line="73"/> + <source>Imaginary part : </source> + <translation>Imaginary part : </translation> + </message> + <message> + <location filename="Operations/IFFTOp.cpp" line="199"/> + <source>DFT-reconstructed image</source> + <translation>DFT-reconstructed image</translation> + </message> +</context> +<context> + <name>InverseHoughDialog</name> + <message> + <source>Dialog</source> + <translation type="obsolete">Dialog</translation> + </message> + <message> + <location filename="Operations/InverseHoughDialog.ui" line="14"/> + <source>Inverse hough transform</source> + <oldsource>Hough reconstruction</oldsource> + <translation>Inverse Hough transform</translation> + </message> + <message> + <location filename="Operations/InverseHoughDialog.ui" line="22"/> + <source>Reconstructed image size : </source> + <translation>Reconstructed image size : </translation> + </message> + <message> + <location filename="Operations/InverseHoughDialog.ui" line="45"/> + <source>Reconstruction threshold : </source> + <translation>Reconstruction threshold : </translation> + </message> +</context> +<context> + <name>InversePyramidDialog</name> + <message> + <source>Dialog</source> + <translation type="obsolete">Dialog</translation> + </message> + <message> + <location filename="Operations/InversePyramidDialog.ui" line="14"/> + <source>Pyramidal reconstruction</source> + <oldsource>Pyramid reconstruction</oldsource> + <translation>Pyramidal reconstruction</translation> + </message> + <message> + <location filename="Operations/InversePyramidDialog.ui" line="20"/> + <source>Filter : </source> + <translation>Filter : </translation> + </message> + <message> + <location filename="Operations/InversePyramidDialog.ui" line="28"/> + <source>triangular</source> + <translation>triangular</translation> + </message> + <message> + <location filename="Operations/InversePyramidDialog.ui" line="33"/> + <source>gaussian</source> + <translation>gaussian</translation> + </message> + <message> + <location filename="Operations/InversePyramidDialog.ui" line="38"/> + <source>trimodal</source> + <translation>trimodal</translation> + </message> + <message> + <location filename="Operations/InversePyramidDialog.ui" line="43"/> + <source>rectangular</source> + <translation>rectangular</translation> + </message> + <message> + <location filename="Operations/InversePyramidDialog.ui" line="48"/> + <source>qmf</source> + <translation>qmf</translation> + </message> + <message> + <location filename="Operations/InversePyramidDialog.ui" line="69"/> + <source>Number of steps in the pyramid : </source> + <translation>Number of steps in the pyramid : </translation> + </message> + <message> + <location filename="Operations/InversePyramidDialog.ui" line="102"/> + <source>Step to reconstruct :</source> + <translation>Step to reconstruct :</translation> + </message> +</context> +<context> + <name>MICD</name> + <message> + <source>MICD Encoding</source> + <translation type="obsolete">MICD Encoding</translation> + </message> + <message> + <location filename="Operations/MICDEncodingOp.cpp" line="53"/> + <source>Error while loading quantification file</source> + <translation>Error while loading quantification file</translation> + </message> + <message> + <location filename="Operations/MICDEncodingOp.cpp" line="53"/> + <source>The specified quantification file could not be opened !</source> + <translation>The specified quantification file could not be opened !</translation> + </message> + <message> + <location filename="Operations/MICDEncodingOp.cpp" line="60"/> + <source>Error image</source> + <translation>Error image</translation> + </message> + <message> + <location filename="Operations/MICDEncodingOp.cpp" line="61"/> + <source>Reconstructed image</source> + <translation>Reconstructed image</translation> + </message> +</context> +<context> + <name>MICDDialog</name> + <message> + <source>Dialog</source> + <translation type="obsolete">Dialog</translation> + </message> + <message> + <location filename="Operations/MICDDialog.ui" line="14"/> + <source>MICD encoding</source> + <translation>MICD encoding</translation> + </message> + <message> + <location filename="Operations/MICDDialog.ui" line="35"/> + <source>Predictor P(X)</source> + <translation>Predictor P(X)</translation> + </message> + <message> + <location filename="Operations/MICDDialog.ui" line="41"/> + <source>A</source> + <translation>A</translation> + </message> + <message> + <location filename="Operations/MICDDialog.ui" line="51"/> + <source>C</source> + <translation>C</translation> + </message> + <message> + <location filename="Operations/MICDDialog.ui" line="58"/> + <source>( A + C ) / 2</source> + <translation>( A + C ) / 2</translation> + </message> + <message> + <location filename="Operations/MICDDialog.ui" line="65"/> + <source>Modified Graham's</source> + <translation>Modified Graham's</translation> + </message> + <message> + <location filename="Operations/MICDDialog.ui" line="74"/> + <source>Q = </source> + <translation></translation> + </message> + <message> + <location filename="Operations/MICDDialog.ui" line="115"/> + <source>Quantifier</source> + <translation></translation> + </message> + <message> + <location filename="Operations/MICDDialog.ui" line="121"/> + <source>Quantification file :</source> + <translation>Quantification file :</translation> + </message> + <message> + <location filename="Operations/MICDDialog.ui" line="141"/> + <source>Browse</source> + <translation>Browse</translation> + </message> + <message> + <location filename="Operations/MICDDialog.ui" line="169"/> + <source>Open quantification editor</source> + <translation></translation> + </message> + <message> + <location filename="Operations/MICDDialog.cpp" line="39"/> + <source>Open file</source> + <translation>Open file</translation> + </message> + <message> + <location filename="Operations/MICDDialog.cpp" line="39"/> + <source>Loi de quantification (*.loi)</source> + <translation>Quantification file (*.loi)</translation> + </message> +</context> +<context> + <name>MICDEncodingOp</name> + <message> + <source>MICD Encoding</source> + <translation type="obsolete">MICD Encoding</translation> + </message> +</context> +<context> + <name>MeanSquareErrorOp</name> + <message> + <location filename="Operations/MeanSquaredErrorOp.cpp" line="84"/> + <source>Mean squarred error : %1 (mean error : %2)</source> + <translation>Mean squarred error : %1 (mean error : %2)</translation> + </message> +</context> +<context> + <name>MeanSquaredErrorOp</name> + <message> + <source>Mean squared error</source> + <translation type="obsolete">Mean squared error</translation> + </message> + <message> + <source>Compare to...</source> + <translation type="obsolete">Compare to...</translation> + </message> +</context> +<context> + <name>NoiseOp</name> + <message> + <source>Add noise</source> + <translation type="obsolete">Add noise</translation> + </message> + <message> + <source>Parameters</source> + <translation type="obsolete">Parameters</translation> + </message> + <message> + <location filename="Operations/NoiseOp.cpp" line="54"/> + <source>Impulse noise</source> + <translation>Impulse noise</translation> + </message> + <message> + <location filename="Operations/NoiseOp.cpp" line="55"/> + <source>Gaussian noise</source> + <translation>Gaussian noise</translation> + </message> + <message> + <location filename="Operations/NoiseOp.cpp" line="67"/> + <source>Mean : </source> + <translation>Mean : </translation> + </message> + <message> + <location filename="Operations/NoiseOp.cpp" line="68"/> + <source>Standard deviation : </source> + <translation>Standard deviation : </translation> + </message> + <message> + <location filename="Operations/NoiseOp.cpp" line="76"/> + <source>Percent of image : </source> + <translation>Percent of image : </translation> + </message> + <message> + <source>Validate</source> + <translation type="obsolete">Validate</translation> + </message> + <message> + <location filename="Operations/NoiseOp.cpp" line="118"/> + <location filename="Operations/NoiseOp.cpp" line="134"/> + <source>impulse noise</source> + <translation>impulse noise</translation> + </message> + <message> + <location filename="Operations/NoiseOp.cpp" line="152"/> + <location filename="Operations/NoiseOp.cpp" line="161"/> + <source>gaussian noise</source> + <translation>gaussian noise</translation> + </message> +</context> +<context> + <name>Operations</name> + <message> + <location filename="Operations/BFlitOp.cpp" line="37"/> + <source>BFilt</source> + <oldsource>BFlit</oldsource> + <translation>BFilt</translation> + </message> + <message> + <location filename="Operations/BFlitOp.cpp" line="49"/> + <location filename="Operations/CombineColorOp.cpp" line="49"/> + <location filename="Operations/IFFTOp.cpp" line="49"/> + <location filename="Operations/NoiseOp.cpp" line="49"/> + <location filename="Operations/PointOp.cpp" line="114"/> + <source>Parameters</source> + <translation>Parameters</translation> + </message> + <message> + <location filename="Operations/BFlitOp.cpp" line="62"/> + <location filename="Operations/NoiseOp.cpp" line="90"/> + <location filename="Operations/PointOp.cpp" line="192"/> + <location filename="Operations/RandomImgOp.cpp" line="105"/> + <source>Validate</source> + <translation>Validate</translation> + </message> + <message> + <source>Colorimetry</source> + <translation type="obsolete">Colorimetry</translation> + </message> + <message> + <location filename="Operations/CombineColorOp.cpp" line="38"/> + <source>Combine color planes</source> + <translation>Combine color planes</translation> + </message> + <message> + <location filename="Operations/CroissanceOp.cpp" line="37"/> + <location filename="Operations/CroissanceOp.cpp" line="48"/> + <source>Croissance</source> + <translation>Croissance</translation> + </message> + <message> + <location filename="Operations/DMMOp.cpp" line="33"/> + <source>DMM</source> + <translation>DMM</translation> + </message> + <message> + <location filename="Operations/EntropyOp.cpp" line="28"/> + <source>Calcul d'entropie</source> + <translation>Entropy calculation</translation> + </message> + <message> + <location filename="Operations/EntropyOp.cpp" line="45"/> + <source>Entropy of the image = %1</source> + <translation>Entropy of the image = %1</translation> + </message> + <message> + <location filename="Operations/FFTOp.cpp" line="28"/> + <source>Fourier transform</source> + <oldsource>Discrete Fourier transform</oldsource> + <translation>Fourier transform</translation> + </message> + <message> + <location filename="Operations/HistogramOp.cpp" line="32"/> + <source>Histogram operations</source> + <translation>Histogram operations</translation> + </message> + <message> + <location filename="Operations/HuffmanOp.cpp" line="29"/> + <source>Huffman</source> + <translation>Huffman</translation> + </message> + <message> + <source>Discrete Fourier reconstruction</source> + <translation type="obsolete">Discrete Fourier reconstruction</translation> + </message> + <message> + <location filename="Operations/MICDEncodingOp.cpp" line="32"/> + <source>MICD Encoding</source> + <translation>MICD Encoding</translation> + </message> + <message> + <location filename="Operations/MeanSquaredErrorOp.cpp" line="34"/> + <source>Mean squared error</source> + <translation>Mean squared error</translation> + </message> + <message> + <location filename="Operations/MeanSquaredErrorOp.cpp" line="45"/> + <location filename="Operations/SignalToNoiseOp.cpp" line="45"/> + <source>Compare to...</source> + <translation>Compare to...</translation> + </message> + <message> + <location filename="Operations/MeanSquaredErrorOp.cpp" line="53"/> + <location filename="Operations/SignalToNoiseOp.cpp" line="53"/> + <source>Compare %1 to : </source> + <translation>Compare %1 to : </translation> + </message> + <message> + <location filename="Operations/NoiseOp.cpp" line="42"/> + <source>Add noise</source> + <translation>Add noise</translation> + </message> + <message> + <source>impulse noise</source> + <translation type="obsolete">impulse noise</translation> + </message> + <message> + <source>gaussian noise</source> + <translation type="obsolete">gaussian noise</translation> + </message> + <message> + <location filename="Operations/PointOp.cpp" line="44"/> + <source>Pixel operations</source> + <translation>Pixel operations</translation> + </message> + <message> + <location filename="Operations/PseudoColorOp.cpp" line="28"/> + <source>Pseudo color</source> + <translation>Pseudo color</translation> + </message> + <message> + <location filename="Operations/QuantificationOp.cpp" line="31"/> + <source>Quantification</source> + <translation>Quantification</translation> + </message> + <message> + <location filename="Operations/RandomImgOp.cpp" line="37"/> + <source>Generate random image</source> + <translation>Generate random image</translation> + </message> + <message> + <location filename="Operations/RandomImgOp.cpp" line="129"/> + <location filename="Operations/RandomImgOp.cpp" line="149"/> + <source>Random image</source> + <translation>Random image</translation> + </message> + <message> + <location filename="Operations/RejectionRingOp.cpp" line="36"/> + <location filename="Operations/RejectionRingOp.cpp" line="42"/> + <source>Rejection ring</source> + <translation>Rejection ring</translation> + </message> + <message> + <source>Rejection ring (%1 %2 %3)</source> + <translation type="obsolete">Rejection ring (%1 %2 %3)</translation> + </message> + <message> + <location filename="Operations/RotateOp.cpp" line="32"/> + <source>Rotation</source> + <translation>Rotation</translation> + </message> + <message> + <location filename="Operations/ScalingOp.cpp" line="42"/> + <location filename="Operations/ScalingOp.cpp" line="57"/> + <source>Scaling</source> + <translation>Scaling</translation> + </message> + <message> + <location filename="Operations/SignalToNoiseOp.cpp" line="33"/> + <source>Signal-to-noise ratio</source> + <translation>Signal-to-noise ratio</translation> + </message> + <message> + <source>+inf</source> + <translation type="obsolete">infinite</translation> + </message> + <message> + <location filename="Operations/SinusSynthesisOp.cpp" line="38"/> + <location filename="Operations/SinusSynthesisOp.cpp" line="144"/> + <source>Sinus synthesis</source> + <translation>Sinus synthesis</translation> + </message> + <message> + <source>Test</source> + <translation type="obsolete">Test</translation> + </message> + <message> + <location filename="Operations/ThresholdOp.cpp" line="11"/> + <source>Thresholding</source> + <translation>Thresholding</translation> + </message> + <message> + <location filename="Operations/TranslateOp.cpp" line="12"/> + <source>Translation</source> + <translation>Translation</translation> + </message> + <message> + <location filename="Operations/ZeroCrossingOp.cpp" line="33"/> + <source>Zero crossing</source> + <translation>Zero crossing</translation> + </message> + <message> + <location filename="Operations/CenterOp.cpp" line="32"/> + <source>Center</source> + <translation>Center</translation> + </message> + <message> + <location filename="Operations/SplitColorOp.cpp" line="31"/> + <source>Split color planes</source> + <translation>Split color planes</translation> + </message> + <message> + <location filename="Operations/FlipOp.cpp" line="30"/> + <source>Flip %1</source> + <translation>Flip %1</translation> + </message> + <message> + <source>Class analysis</source> + <translation type="obsolete">Class analysis</translation> + </message> + <message> + <location filename="Operations/DCTOp.cpp" line="30"/> + <source>Discrete cosinus transform</source> + <translation>DCT 16x16 with coef. reduction</translation> + </message> + <message> + <location filename="Operations/HadamardOp.cpp" line="39"/> + <location filename="Operations/HadamardOp.cpp" line="51"/> + <source>8x8 transforms</source> + <translation>8x8 transforms (Haar, Hadamard, DCT)</translation> + </message> + <message> + <location filename="Operations/HoughOp.cpp" line="30"/> + <source>Hough transform</source> + <translation>Hough transform</translation> + </message> + <message> + <location filename="Operations/InverseHoughOp.cpp" line="28"/> + <source>Houghman inverse transform</source> + <translation>Houghman inverse transform</translation> + </message> + <message> + <location filename="Operations/InversePyramidOp.cpp" line="31"/> + <source>Pyramidal reconstruction</source> + <oldsource>Reconstruct pyramid</oldsource> + <translation>Pyramidal reconstruction</translation> + </message> + <message> + <location filename="Operations/InversePyramidOp.cpp" line="41"/> + <location filename="Operations/InversePyramidOp.cpp" line="46"/> + <location filename="Operations/PyramidOp.cpp" line="43"/> + <location filename="Operations/PyramidOp.cpp" line="48"/> + <source>The operation can't be applied on this image</source> + <translation>The operation can't be applied on this image</translation> + </message> + <message> + <location filename="Operations/InversePyramidOp.cpp" line="42"/> + <source>The image width must be twice the image height.</source> + <translation>The image width must be twice the image height.</translation> + </message> + <message> + <location filename="Operations/InversePyramidOp.cpp" line="47"/> + <location filename="Operations/PyramidOp.cpp" line="49"/> + <source>The image dimensions must be power of 2.</source> + <translation>The image dimensions must be power of 2.</translation> + </message> + <message> + <source>Create pyramid</source> + <translation type="obsolete">Create pyramid</translation> + </message> + <message> + <location filename="Operations/PyramidOp.cpp" line="32"/> + <source>Pyramidal decomposition</source> + <translation>Pyramidal decomposition</translation> + </message> + <message> + <location filename="Operations/PyramidOp.cpp" line="44"/> + <source>The image width must equal the image height.</source> + <translation>The image width must equal the image height.</translation> + </message> + <message> + <location filename="Operations/ClassResultOp.cpp" line="37"/> + <source>Classification results</source> + <translation>Classification results</translation> + </message> + <message> + <location filename="Operations/ColorimetryOp.cpp" line="34"/> + <source>Generate RGB image</source> + <translation>Generate RGB image</translation> + </message> + <message> + <location filename="Operations/ColorimetryOp.cpp" line="45"/> + <source>RGB image generator</source> + <translation>RGB image generator</translation> + </message> + <message> + <location filename="Operations/IFFTOp.cpp" line="38"/> + <source>Inverse Fourier transform</source> + <translation>Inverse Fourier transform</translation> + </message> + <message> + <location filename="Operations/ClassAnalysisOp.cpp" line="33"/> + <source>Supervised classification</source> + <translation>Supervised classification</translation> + </message> +</context> +<context> + <name>PluginManager</name> + <message> + <location filename="Services/PluginManager.cpp" line="36"/> + <source>Plugins</source> + <translation>Plugins</translation> + </message> + <message> + <location filename="Services/PluginManager.cpp" line="52"/> + <source>&Plugin</source> + <translation>&Plugin</translation> + </message> + <message> + <location filename="Services/PluginManager.cpp" line="54"/> + <source>&Load plugin</source> + <translation>&Load plugin</translation> + </message> + <message> + <location filename="Services/PluginManager.cpp" line="55"/> + <source>&Unload all plugins</source> + <translation>&Unload all plugins</translation> + </message> + <message> + <location filename="Services/PluginManager.cpp" line="78"/> + <source>Load plugin</source> + <translation>Load plugin</translation> + </message> + <message> + <location filename="Services/PluginManager.cpp" line="78"/> + <source>Plugin (*.dll *.so *.dylib)</source> + <translation>Plugin (*.dll *.so *.dylib)</translation> + </message> + <message> + <location filename="Services/PluginManager.cpp" line="173"/> + <location filename="Services/PluginManager.cpp" line="184"/> + <location filename="Services/PluginManager.cpp" line="196"/> + <source>Error loading plugin</source> + <translation>Error loading plugin</translation> + </message> + <message> + <location filename="Services/PluginManager.cpp" line="184"/> + <source>Could not find the plugin's entry point "loadPlugin"</source> + <translation>Could not find the plugin's entry point "loadPlugin"</translation> + </message> + <message> + <location filename="Services/PluginManager.cpp" line="196"/> + <source>The getPlugin entry point does not return a valid Plugin</source> + <translation>The getPlugin entry point does not return a valid Plugin</translation> + </message> +</context> +<context> + <name>PointOp</name> + <message> + <source>Pixel operations</source> + <translation type="obsolete">Pixel operations</translation> + </message> + <message> + <source>Parameter</source> + <translation type="obsolete">Parameter</translation> + </message> + <message> + <location filename="Operations/PointOp.cpp" line="119"/> + <source>Second operand</source> + <translation>Second operand</translation> + </message> + <message> + <location filename="Operations/PointOp.cpp" line="120"/> + <source>Value</source> + <translation>Value</translation> + </message> + <message> + <location filename="Operations/PointOp.cpp" line="121"/> + <source>Image</source> + <translation>Image</translation> + </message> + <message> + <location filename="Operations/PointOp.cpp" line="128"/> + <source>Explode colors</source> + <translation>Explode colors</translation> + </message> + <message> + <source>Validate</source> + <translation type="obsolete">Validate</translation> + </message> +</context> +<context> + <name>PseudoColorOp</name> + <message> + <location filename="Operations/PseudoColorOp.cpp" line="53"/> + <source>Pseudo color</source> + <translation>Pseudo color</translation> + </message> +</context> +<context> + <name>PyramidDialog</name> + <message> + <source>Dialog</source> + <translation type="obsolete">Dialog</translation> + </message> + <message> + <source>Pyramid generator</source> + <translation type="obsolete">Pyramid generator</translation> + </message> + <message> + <location filename="Operations/PyramidDialog.ui" line="14"/> + <source>Pyramidal decomposition</source> + <translation>Pyramidal decomposition</translation> + </message> + <message> + <location filename="Operations/PyramidDialog.ui" line="20"/> + <source>Type of pyramid</source> + <translation>Type of pyramid</translation> + </message> + <message> + <location filename="Operations/PyramidDialog.ui" line="26"/> + <location filename="Operations/PyramidDialog.ui" line="61"/> + <source>gaussian</source> + <translation>gaussian</translation> + </message> + <message> + <location filename="Operations/PyramidDialog.ui" line="36"/> + <source>laplacian</source> + <translation>laplacian</translation> + </message> + <message> + <location filename="Operations/PyramidDialog.ui" line="48"/> + <source>Filter : </source> + <translation>Filter : </translation> + </message> + <message> + <location filename="Operations/PyramidDialog.ui" line="56"/> + <source>triangular</source> + <translation>triangular</translation> + </message> + <message> + <location filename="Operations/PyramidDialog.ui" line="66"/> + <source>trimodal</source> + <translation>trimodal</translation> + </message> + <message> + <location filename="Operations/PyramidDialog.ui" line="71"/> + <source>rectangular</source> + <translation>rectangular</translation> + </message> + <message> + <location filename="Operations/PyramidDialog.ui" line="76"/> + <source>qmf</source> + <translation>qmf</translation> + </message> + <message> + <location filename="Operations/PyramidDialog.ui" line="84"/> + <source>Number of steps : </source> + <translation>Number of steps : </translation> + </message> + <message> + <location filename="Operations/PyramidDialog.ui" line="105"/> + <source>Create only one step :</source> + <translation>Create only one step :</translation> + </message> +</context> +<context> + <name>QuantificationDialog</name> + <message> + <source>Quantification</source> + <translation type="obsolete">Quantification</translation> + </message> + <message> + <location filename="Operations/QuantificationDialog.cpp" line="40"/> + <source>Quantification file editor</source> + <translation>Quantification file editor</translation> + </message> + <message> + <location filename="Operations/QuantificationDialog.cpp" line="43"/> + <source>Quantification of %1</source> + <translation>Quantification of %1</translation> + </message> + <message> + <location filename="Operations/QuantificationDialog.cpp" line="54"/> + <source>Linear with centered value</source> + <translation>Linear with centered value</translation> + </message> + <message> + <location filename="Operations/QuantificationDialog.cpp" line="56"/> + <source>Non linear with centered value</source> + <translation>Non linear with centered value</translation> + </message> + <message> + <location filename="Operations/QuantificationDialog.cpp" line="57"/> + <source>Non linear with mean value</source> + <translation>Non linear with mean value</translation> + </message> + <message> + <location filename="Operations/QuantificationDialog.cpp" line="59"/> + <source>Custom</source> + <translation>Custom</translation> + </message> + <message> + <location filename="Operations/QuantificationDialog.cpp" line="60"/> + <source>Quantification : </source> + <translation>Quantification : </translation> + </message> + <message> + <location filename="Operations/QuantificationDialog.cpp" line="61"/> + <source>Number of values : </source> + <translation>Number of values : </translation> + </message> + <message> + <location filename="Operations/QuantificationDialog.cpp" line="87"/> + <source>Exit</source> + <translation>Exit</translation> + </message> + <message> + <location filename="Operations/QuantificationDialog.cpp" line="90"/> + <source>Apply</source> + <translation>Apply</translation> + </message> + <message> + <location filename="Operations/QuantificationDialog.cpp" line="123"/> + <source>Open a file</source> + <translation>Open a file</translation> + </message> + <message> + <location filename="Operations/QuantificationDialog.cpp" line="123"/> + <location filename="Operations/QuantificationDialog.cpp" line="132"/> + <source>Loi de quantification (*.loi)</source> + <translation>Quantification file (*.loi)</translation> + </message> + <message> + <location filename="Operations/QuantificationDialog.cpp" line="132"/> + <source>Save to file</source> + <translation>Save to file</translation> + </message> +</context> +<context> + <name>QuantificationOp</name> + <message> + <source>Quantification</source> + <translation type="obsolete">Quantification</translation> + </message> + <message> + <location filename="Operations/QuantificationOp.cpp" line="75"/> + <source>quantified</source> + <translation>quantified</translation> + </message> +</context> +<context> + <name>QuantificationWidget</name> + <message> + <location filename="Operations/QuantificationWidget.cpp" line="43"/> + <source>Thresholds +(low to high)</source> + <translation>Thresholds +(low to high)</translation> + </message> + <message> + <location filename="Operations/QuantificationWidget.cpp" line="45"/> + <source>Values</source> + <translation>Values</translation> + </message> +</context> +<context> + <name>RandomImgOp</name> + <message> + <source>Generate random image</source> + <translation type="obsolete">Generate random image</translation> + </message> + <message> + <location filename="Operations/RandomImgOp.cpp" line="43"/> + <source>Parameters</source> + <translation>Parameters</translation> + </message> + <message> + <location filename="Operations/RandomImgOp.cpp" line="47"/> + <source>Image type</source> + <translation>Image type</translation> + </message> + <message> + <location filename="Operations/RandomImgOp.cpp" line="48"/> + <source>8-bit integer</source> + <translation>8-bit integer</translation> + </message> + <message> + <location filename="Operations/RandomImgOp.cpp" line="49"/> + <source>Floating point</source> + <translation>Floating point</translation> + </message> + <message> + <location filename="Operations/RandomImgOp.cpp" line="59"/> + <source>Width : </source> + <translation>Width : </translation> + </message> + <message> + <location filename="Operations/RandomImgOp.cpp" line="64"/> + <source>Height : </source> + <translation>Height : </translation> + </message> + <message> + <location filename="Operations/RandomImgOp.cpp" line="69"/> + <source>Number of channels : </source> + <translation>Number of channels : </translation> + </message> + <message> + <location filename="Operations/RandomImgOp.cpp" line="79"/> + <location filename="Operations/RandomImgOp.cpp" line="93"/> + <source>Range : </source> + <translation>Range of values: </translation> + </message> + <message> + <location filename="Operations/RandomImgOp.cpp" line="81"/> + <location filename="Operations/RandomImgOp.cpp" line="95"/> + <source> to </source> + <translation> to </translation> + </message> + <message> + <source>Validate</source> + <translation type="obsolete">Validate</translation> + </message> + <message> + <source>Random image</source> + <translation type="obsolete">Random image</translation> + </message> +</context> +<context> + <name>RejectionRingOp</name> + <message> + <source>Rejection ring</source> + <translation type="obsolete">Rejection ring</translation> + </message> + <message> + <location filename="Operations/RejectionRingOp.cpp" line="49"/> + <source>Width=Height : </source> + <translation>Width=Height : </translation> + </message> + <message> + <location filename="Operations/RejectionRingOp.cpp" line="53"/> + <source>Radius : </source> + <translation>Radius : </translation> + </message> + <message> + <location filename="Operations/RejectionRingOp.cpp" line="57"/> + <source>Thickness (beyond radius) : </source> + <translation>Thickness (beyond radius) : </translation> + </message> + <message> + <location filename="Operations/RejectionRingOp.cpp" line="99"/> + <source>Rejection ring (%1 %2 %3)</source> + <translation>Rejection ring (%1 %2 %3)</translation> + </message> +</context> +<context> + <name>RotateOp</name> + <message> + <source>Rotation</source> + <translation type="obsolete">Rotation</translation> + </message> + <message> + <source>Rotating %1</source> + <translation type="obsolete">Rotating %1</translation> + </message> +</context> +<context> + <name>Rotation</name> + <message> + <location filename="Operations/RotateOp.cpp" line="58"/> + <source>Rotating %1</source> + <translation>Rotating %1</translation> + </message> + <message> + <location filename="Operations/RotateOp.cpp" line="67"/> + <source>Expand image</source> + <translation>Expand image</translation> + </message> + <message> + <location filename="Operations/RotateOp.cpp" line="76"/> + <source>Rotation angle : </source> + <translation>Rotation angle : </translation> + </message> + <message> + <location filename="Operations/RotateOp.cpp" line="78"/> + <source>Fill value : </source> + <translation>Fill value : </translation> + </message> + <message> + <location filename="Operations/RotateOp.cpp" line="150"/> + <source>rotated %1</source> + <translation>rotated %1</translation> + </message> +</context> +<context> + <name>ScalingOp</name> + <message> + <source>Scaling</source> + <translation type="obsolete">Scaling</translation> + </message> + <message> + <location filename="Operations/ScalingOp.cpp" line="70"/> + <source>Nearest neighboor (standard)</source> + <translation>Nearest neighboor (standard)</translation> + </message> + <message> + <location filename="Operations/ScalingOp.cpp" line="71"/> + <source>Bi-linear</source> + <translation>Bi-linear</translation> + </message> + <message> + <location filename="Operations/ScalingOp.cpp" line="72"/> + <source>Parabolic</source> + <translation>Parabolic</translation> + </message> + <message> + <location filename="Operations/ScalingOp.cpp" line="73"/> + <source>Spline</source> + <translation>Spline</translation> + </message> + <message> + <location filename="Operations/ScalingOp.cpp" line="74"/> + <source>Interpolation : </source> + <translation>Interpolation : </translation> + </message> + <message> + <location filename="Operations/ScalingOp.cpp" line="75"/> + <source>X scale factor : </source> + <translation>X scale factor : </translation> + </message> + <message> + <location filename="Operations/ScalingOp.cpp" line="76"/> + <source>Y scale factor : </source> + <translation>Y scale factor : </translation> + </message> + <message> + <location filename="Operations/ScalingOp.cpp" line="118"/> + <location filename="Operations/ScalingOp.cpp" line="124"/> + <source>scaled</source> + <translation>scaled</translation> + </message> +</context> +<context> + <name>SignalToNoiseOp</name> + <message> + <source>Signal-to-noise ratio</source> + <translation type="obsolete">Signal-to-noise ratio</translation> + </message> + <message> + <source>Compare to...</source> + <translation type="obsolete">Compare to...</translation> + </message> + <message> + <source>+inf</source> + <translation type="obsolete">infinite</translation> + </message> + <message> + <location filename="Operations/SignalToNoiseOp.cpp" line="83"/> + <source>Signal-to-noise ratio : %1</source> + <translation>Signal-to-noise ratio : %1</translation> + </message> +</context> +<context> + <name>SinusSynthesisOp</name> + <message> + <location filename="Operations/SinusSynthesisOp.cpp" line="49"/> + <source>Sinus synthesis</source> + <translation>Sinus synthesis</translation> + </message> + <message> + <location filename="Operations/SinusSynthesisOp.cpp" line="55"/> + <source>Linear</source> + <translation>Linear</translation> + </message> + <message> + <location filename="Operations/SinusSynthesisOp.cpp" line="56"/> + <source>Circular</source> + <translation>Circular</translation> + </message> + <message> + <location filename="Operations/SinusSynthesisOp.cpp" line="70"/> + <source>256</source> + <translation>256</translation> + </message> + <message> + <location filename="Operations/SinusSynthesisOp.cpp" line="71"/> + <source>2 (Black and white)</source> + <translation>2 (Black and white)</translation> + </message> + <message> + <location filename="Operations/SinusSynthesisOp.cpp" line="73"/> + <source>Image size (width=height) : </source> + <translation>Image size (width=height) : </translation> + </message> + <message> + <location filename="Operations/SinusSynthesisOp.cpp" line="74"/> + <source>Signal period (pixel) : </source> + <translation>Signal period (pixel) : </translation> + </message> + <message> + <location filename="Operations/SinusSynthesisOp.cpp" line="75"/> + <source>Orientation (°): </source> + <translation>Orientation (°): </translation> + </message> + <message> + <location filename="Operations/SinusSynthesisOp.cpp" line="77"/> + <source>Niveaux de gris : </source> + <translation>Grayscale levels : </translation> + </message> +</context> +<context> + <name>SplitColorOp</name> + <message> + <source>Split color planes</source> + <translation type="obsolete">Split color planes</translation> + </message> +</context> +<context> + <name>StructElemWindow</name> + <message> + <location filename="Widgets/StructElemWindow.cpp" line="41"/> + <source>&Open file</source> + <translation>&Open file</translation> + </message> + <message> + <location filename="Widgets/StructElemWindow.cpp" line="42"/> + <source>&Save as...</source> + <translation>&Save as...</translation> + </message> + <message> + <location filename="Widgets/StructElemWindow.cpp" line="53"/> + <source>Basic shapes :</source> + <translation>Basic shapes :</translation> + </message> + <message> + <location filename="Widgets/StructElemWindow.cpp" line="56"/> + <location filename="Widgets/StructElemWindow.cpp" line="195"/> + <source>Diamond</source> + <translation>Diamond</translation> + </message> + <message> + <location filename="Widgets/StructElemWindow.cpp" line="57"/> + <location filename="Widgets/StructElemWindow.cpp" line="175"/> + <source>Disc</source> + <translation>Disc</translation> + </message> + <message> + <location filename="Widgets/StructElemWindow.cpp" line="58"/> + <source>Empty</source> + <translation>Empty</translation> + </message> + <message> + <location filename="Widgets/StructElemWindow.cpp" line="65"/> + <source>Generate</source> + <translation>Generate</translation> + </message> + <message> + <location filename="Widgets/StructElemWindow.cpp" line="76"/> + <source>Scale :</source> + <translation>Scale :</translation> + </message> + <message> + <location filename="Widgets/StructElemWindow.cpp" line="247"/> + <source>Open a file</source> + <translation>Open a file</translation> + </message> + <message> + <location filename="Widgets/StructElemWindow.cpp" line="247"/> + <location filename="Widgets/StructElemWindow.cpp" line="268"/> + <source>Images (*.png *.bmp *.jpg *.jpeg)</source> + <translation>Images (*.png *.bmp *.jpg *.jpeg)</translation> + </message> + <message> + <location filename="Widgets/StructElemWindow.cpp" line="268"/> + <source>Save file</source> + <translation>Save file</translation> + </message> +</context> +<context> + <name>TestOp</name> + <message> + <source>Test</source> + <translation type="obsolete">Test</translation> + </message> +</context> +<context> + <name>ThresholdDialog</name> + <message> + <location filename="Operations/ThresholdDialog.cpp" line="44"/> + <source>Threshold #1 : </source> + <translation>Threshold #1 : </translation> + </message> + <message> + <location filename="Operations/ThresholdDialog.cpp" line="48"/> + <location filename="Operations/ThresholdDialog.cpp" line="75"/> + <source>Threshold : </source> + <translation>Threshold : </translation> + </message> + <message> + <location filename="Operations/ThresholdDialog.cpp" line="59"/> + <source>ThresholdOp</source> + <translation>Thresholding</translation> + </message> + <message> + <location filename="Operations/ThresholdDialog.cpp" line="65"/> + <source><font color=red><i>Information : The input image has been converted to grayscale.</i></font></source> + <translation><font color=red><i>Information : The input image has been converted to grayscale.</i></font></translation> + </message> + <message> + <location filename="Operations/ThresholdDialog.cpp" line="68"/> + <source>Threshold</source> + <translation>Threshold</translation> + </message> + <message> + <location filename="Operations/ThresholdDialog.cpp" line="70"/> + <source>Double threshold</source> + <translation>Double threshold</translation> + </message> + <message> + <location filename="Operations/ThresholdDialog.cpp" line="79"/> + <source>Otsu</source> + <translation>Otsu</translation> + </message> + <message> + <location filename="Operations/ThresholdDialog.cpp" line="86"/> + <source>Threshold #2 : </source> + <translation>Threshold #2 : </translation> + </message> + <message> + <location filename="Operations/ThresholdDialog.cpp" line="97"/> + <source>Color between thresholds :</source> + <translation>Color between thresholds :</translation> + </message> + <message> + <location filename="Operations/ThresholdDialog.cpp" line="98"/> + <source>White</source> + <translation>White</translation> + </message> + <message> + <location filename="Operations/ThresholdDialog.cpp" line="99"/> + <source>Black</source> + <translation>Black</translation> + </message> + <message> + <location filename="Operations/ThresholdDialog.cpp" line="130"/> + <source>Validate</source> + <translation>Validate</translation> + </message> +</context> +<context> + <name>ThresholdOp</name> + <message> + <source>Thresholding</source> + <translation type="obsolete">Thresholding</translation> + </message> +</context> +<context> + <name>Tools</name> + <message> + <source>Combine color planes</source> + <translation type="obsolete">Combine color planes</translation> + </message> + <message> + <source>Discrete Fourier transform</source> + <translation type="obsolete">Discrete Fourier transform</translation> + </message> + <message> + <source>Discrete Fourier reconstruction</source> + <translation type="obsolete">Discrete Fourier reconstruction</translation> + </message> + <message> + <source>Mean squared error</source> + <translation type="obsolete">Mean squared error</translation> + </message> + <message> + <source>Signal-to-noise ratio</source> + <translation type="obsolete">Signal-to-noise ratio</translation> + </message> + <message> + <source>+inf</source> + <translation type="obsolete">infinite</translation> + </message> + <message> + <source>Black</source> + <translation type="obsolete">Black</translation> + </message> + <message> + <source>Alpha</source> + <translation type="obsolete">Alpha</translation> + </message> + <message> + <source>Red</source> + <translation type="obsolete">Red</translation> + </message> + <message> + <source>Green</source> + <translation type="obsolete">Green</translation> + </message> + <message> + <source>Blue</source> + <translation type="obsolete">Blue</translation> + </message> + <message> + <source>Color</source> + <translation type="obsolete">Color</translation> + </message> + <message> + <source>BFlit</source> + <translation type="obsolete">BFlit</translation> + </message> + <message> + <source>Colorimetry</source> + <translation type="obsolete">Colorimetry</translation> + </message> + <message> + <source>Croissance</source> + <translation type="obsolete">Croissance</translation> + </message> + <message> + <source>DMM</source> + <translation type="obsolete">DMM</translation> + </message> + <message> + <source>Calcul d'entropie</source> + <translation type="obsolete">Entropy calculation</translation> + </message> + <message> + <source>Entropy of the image = %1</source> + <translation type="obsolete">Entropy of the image = %1</translation> + </message> + <message> + <source>Histogram operations</source> + <translation type="obsolete">Histogram operations</translation> + </message> + <message> + <source>Huffman</source> + <translation type="obsolete">Huffman</translation> + </message> + <message> + <source>MICD Encoding</source> + <translation type="obsolete">MICD Encoding</translation> + </message> + <message> + <source>Add noise</source> + <translation type="obsolete">Add noise</translation> + </message> + <message> + <source>impulse noise</source> + <translation type="obsolete">impulse noise</translation> + </message> + <message> + <source>gaussian noise</source> + <translation type="obsolete">gaussian noise</translation> + </message> + <message> + <source>Pixel operations</source> + <translation type="obsolete">Pixel operations</translation> + </message> + <message> + <source>Pseudo color</source> + <translation type="obsolete">Pseudo color</translation> + </message> + <message> + <source>Quantification</source> + <translation type="obsolete">Quantification</translation> + </message> + <message> + <source>Generate random image</source> + <translation type="obsolete">Generate random image</translation> + </message> + <message> + <source>Random image</source> + <translation type="obsolete">Random image</translation> + </message> + <message> + <source>Rejection ring</source> + <translation type="obsolete">Rejection ring</translation> + </message> + <message> + <source>Rejection ring (%1 %2 %3)</source> + <translation type="obsolete">Rejection ring (%1 %2 %3)</translation> + </message> + <message> + <source>Rotation</source> + <translation type="obsolete">Rotation</translation> + </message> + <message> + <source>Scaling</source> + <translation type="obsolete">Scaling</translation> + </message> + <message> + <source>Sinus synthesis</source> + <translation type="obsolete">Sinus synthesis</translation> + </message> + <message> + <source>Test</source> + <translation type="obsolete">Test</translation> + </message> + <message> + <source>Thresholding</source> + <translation type="obsolete">Thresholding</translation> + </message> + <message> + <source>Translation</source> + <translation type="obsolete">Translation</translation> + </message> + <message> + <source>Zero crossing</source> + <translation type="obsolete">Zero crossing</translation> + </message> +</context> +<context> + <name>Transforms</name> + <message> + <location filename="Operations/HadamardOp.cpp" line="57"/> + <source><b>Select the coefficients to keep : </b></source> + <translation><b>Select the coefficients to keep : </b></translation> + </message> + <message> + <location filename="Operations/HadamardOp.cpp" line="62"/> + <source>Clear selection</source> + <translation>Clear selection</translation> + </message> + <message> + <location filename="Operations/HadamardOp.cpp" line="63"/> + <source>Invert selection</source> + <translation>Invert selection</translation> + </message> + <message> + <location filename="Operations/HadamardOp.cpp" line="112"/> + <source>Hadamard transform</source> + <translation>Hadamard transform</translation> + </message> + <message> + <location filename="Operations/HadamardOp.cpp" line="113"/> + <source>Hadamard reconstruction</source> + <translation>Hadamard reconstruction</translation> + </message> + <message> + <location filename="Operations/HadamardOp.cpp" line="117"/> + <source>Haar transform</source> + <translation>Haar transform</translation> + </message> + <message> + <location filename="Operations/HadamardOp.cpp" line="118"/> + <source>Haar reconstruction</source> + <translation>Haar reconstruction</translation> + </message> + <message> + <location filename="Operations/HadamardOp.cpp" line="122"/> + <source>cosinus transform</source> + <translation>cosinus transform</translation> + </message> + <message> + <location filename="Operations/HadamardOp.cpp" line="123"/> + <source>cosinus reconstruction</source> + <translation>cosinus reconstruction</translation> + </message> +</context> +<context> + <name>TranslateOp</name> + <message> + <source>Translation</source> + <translation type="obsolete">Translation</translation> + </message> + <message> + <source>Translating %1</source> + <translation type="obsolete">Translating %1</translation> + </message> + <message> + <location filename="Operations/TranslateOp.cpp" line="34"/> + <source>Expand image</source> + <translation>Expand image</translation> + </message> + <message> + <location filename="Operations/TranslateOp.cpp" line="42"/> + <source>X offset : </source> + <translation>X offset : </translation> + </message> + <message> + <location filename="Operations/TranslateOp.cpp" line="43"/> + <source>Y offset : </source> + <translation>Y offset : </translation> + </message> + <message> + <location filename="Operations/TranslateOp.cpp" line="45"/> + <source>Fill value : </source> + <translation>Fill value : </translation> + </message> + <message> + <location filename="Operations/TranslateOp.cpp" line="85"/> + <source>Translated %1:%2</source> + <translation>Translated %1:%2</translation> + </message> +</context> +<context> + <name>Translation</name> + <message> + <location filename="Operations/TranslateOp.cpp" line="24"/> + <source>Translating %1</source> + <translation>Translating %1</translation> + </message> +</context> +<context> + <name>ZeroCrossingOp</name> + <message> + <location filename="Operations/ZeroCrossingOp.cpp" line="44"/> + <source>Zero crossing</source> + <translation>Zero crossing</translation> + </message> + <message> + <location filename="Operations/ZeroCrossingOp.cpp" line="52"/> + <source>Threshold : </source> + <translation>Threshold : </translation> + </message> + <message> + <location filename="Operations/ZeroCrossingOp.cpp" line="110"/> + <source>contours bruts</source> + <translation>Raw edges</translation> + </message> + <message> + <location filename="Operations/ZeroCrossingOp.cpp" line="111"/> + <source>contours nettoyes</source> + <translation>Cleaned edges</translation> + </message> +</context> +<context> + <name>dialog</name> + <message> + <source>Parameters</source> + <translation type="obsolete">Parameters</translation> + </message> + <message> + <source>Validate</source> + <translation type="obsolete">Validate</translation> + </message> + <message> + <source>Zero crossing</source> + <translation type="obsolete">Zero crossing</translation> + </message> + <message> + <source>Red : </source> + <translation type="obsolete">Red : </translation> + </message> + <message> + <source>Green : </source> + <translation type="obsolete">Green : </translation> + </message> + <message> + <source>Blue : </source> + <translation type="obsolete">Blue : </translation> + </message> + <message> + <source>Hue : </source> + <translation type="obsolete">Hue : </translation> + </message> + <message> + <source>Saturation : </source> + <translation type="obsolete">Saturation : </translation> + </message> + <message> + <source>Value : </source> + <translation type="obsolete">Value : </translation> + </message> + <message> + <source>Croissance</source> + <translation type="obsolete">Croissance</translation> + </message> + <message> + <source>At origin</source> + <translation type="obsolete">At origin</translation> + </message> + <message> + <source>Point of lowest luminance</source> + <translation type="obsolete">Point of lowest luminance</translation> + </message> + <message> + <source>| current - mean | < threshold</source> + <translation type="obsolete">| current - mean | < threshold</translation> + </message> + <message> + <source>| current - initial | < threshold</source> + <translation type="obsolete">| current - initial | < threshold</translation> + </message> + <message> + <source>Threshold : </source> + <translation type="obsolete">Threshold : </translation> + </message> + <message> + <source>Initial germ : </source> + <translation type="obsolete">Initial germ : </translation> + </message> + <message> + <source>Stopping point : </source> + <translation type="obsolete">Stopping point : </translation> + </message> + <message> + <source>Histogram operations</source> + <translation type="obsolete">Histogram operations</translation> + </message> + <message> + <source>Equalize</source> + <translation type="obsolete">Equalize</translation> + </message> + <message> + <source>Normalize</source> + <translation type="obsolete">Normalize</translation> + </message> + <message> + <source>Operation : </source> + <translation type="obsolete">Operation : </translation> + </message> + <message> + <source>Compare to...</source> + <translation type="obsolete">Compare to...</translation> + </message> + <message> + <source>Impulse noise</source> + <translation type="obsolete">Impulse noise</translation> + </message> + <message> + <source>Gaussian noise</source> + <translation type="obsolete">Gaussian noise</translation> + </message> + <message> + <source>Parameter</source> + <translation type="obsolete">Parameter</translation> + </message> + <message> + <source>Second operand</source> + <translation type="obsolete">Second operand</translation> + </message> + <message> + <source>Value</source> + <translation type="obsolete">Value</translation> + </message> + <message> + <source>Image</source> + <translation type="obsolete">Image</translation> + </message> + <message> + <source>Explode colors</source> + <translation type="obsolete">Explode colors</translation> + </message> + <message> + <source>8-bit integer</source> + <translation type="obsolete">8-bit integer</translation> + </message> + <message> + <source>Floating point</source> + <translation type="obsolete">Floating point</translation> + </message> + <message> + <source>Rejection ring</source> + <translation type="obsolete">Rejection ring</translation> + </message> + <message> + <source>Rotating %1</source> + <translation type="obsolete">Rotating %1</translation> + </message> + <message> + <source>Scaling</source> + <translation type="obsolete">Scaling</translation> + </message> + <message> + <source>Nearest neighboor (standard)</source> + <translation type="obsolete">Nearest neighboor (standard)</translation> + </message> + <message> + <source>Bi-linear</source> + <translation type="obsolete">Bi-linear</translation> + </message> + <message> + <source>Parabolic</source> + <translation type="obsolete">Parabolic</translation> + </message> + <message> + <source>Spline</source> + <translation type="obsolete">Spline</translation> + </message> + <message> + <source>Interpolation : </source> + <translation type="obsolete">Interpolation : </translation> + </message> + <message> + <source>X scale factor : </source> + <translation type="obsolete">X scale factor : </translation> + </message> + <message> + <source>Y scale factor : </source> + <translation type="obsolete">Y scale factor : </translation> + </message> + <message> + <source>Sinus synthesis</source> + <translation type="obsolete">Sinus synthesis</translation> + </message> + <message> + <source>Linear</source> + <translation type="obsolete">Linear</translation> + </message> + <message> + <source>Circular</source> + <translation type="obsolete">Circular</translation> + </message> + <message> + <source>256</source> + <translation type="obsolete">256</translation> + </message> + <message> + <source>2 (Black and white)</source> + <translation type="obsolete">2 (Black and white)</translation> + </message> + <message> + <source>Image size (width=height) : </source> + <translation type="obsolete">Image size (width=height) : </translation> + </message> + <message> + <source>Signal period (pixel) : </source> + <translation type="obsolete">Signal period (pixel) : </translation> + </message> + <message> + <source>Orientation (°): </source> + <translation type="obsolete">Orientation (°): </translation> + </message> + <message> + <source>Niveaux de gris : </source> + <translation type="obsolete">Grayscale levels : </translation> + </message> + <message> + <source>Translating %1</source> + <translation type="obsolete">Translating %1</translation> + </message> +</context> +<context> + <name>filtrme::FilterChoice</name> + <message> + <location filename="Widgets/FilterChoice.cpp" line="74"/> + <source>FilterChoice</source> + <translation>Filter choice</translation> + </message> + <message> + <location filename="Widgets/FilterChoice.cpp" line="82"/> + <source>Filter configuration</source> + <translation>Filter configuration</translation> + </message> + <message> + <location filename="Widgets/FilterChoice.cpp" line="86"/> + <source>Filter:</source> + <translation>Filter:</translation> + </message> + <message> + <location filename="Widgets/FilterChoice.cpp" line="95"/> + <source>Edge policy: </source> + <translation>Edge policy: </translation> + </message> + <message> + <location filename="Widgets/FilterChoice.cpp" line="97"/> + <source>Black</source> + <translation>Black</translation> + </message> + <message> + <location filename="Widgets/FilterChoice.cpp" line="97"/> + <source>Mirror</source> + <translation>Mirror</translation> + </message> + <message> + <location filename="Widgets/FilterChoice.cpp" line="97"/> + <source>Nearest</source> + <translation>Nearest</translation> + </message> + <message> + <location filename="Widgets/FilterChoice.cpp" line="97"/> + <source>Spherical</source> + <translation>Spherical</translation> + </message> + <message> + <source>Number of pixels:</source> + <translation type="obsolete">Number of pixels:</translation> + </message> + <message> + <location filename="Widgets/FilterChoice.cpp" line="103"/> + <source>Filter size:</source> + <translation>Filter size:</translation> + </message> + <message> + <location filename="Widgets/FilterChoice.cpp" line="109"/> + <source>Standard deviation : </source> + <translation>Standard deviation : </translation> + </message> + <message> + <location filename="Widgets/FilterChoice.cpp" line="118"/> + <source>Resulting image type</source> + <translation>Resulting image type</translation> + </message> + <message> + <location filename="Widgets/FilterChoice.cpp" line="119"/> + <source>Standard</source> + <translation>Standard</translation> + </message> + <message> + <location filename="Widgets/FilterChoice.cpp" line="120"/> + <source>Floating point</source> + <translation>Floating point</translation> + </message> + <message> + <location filename="Widgets/FilterChoice.cpp" line="163"/> + <source>Apply filter</source> + <translation>Apply filter</translation> + </message> + <message> + <location filename="Widgets/FilterChoice.cpp" line="164"/> + <source>Delete filter</source> + <translation>Delete filter</translation> + </message> + <message> + <location filename="Widgets/FilterChoice.cpp" line="194"/> + <source>Uniform</source> + <translation>Uniform</translation> + </message> + <message> + <location filename="Widgets/FilterChoice.cpp" line="194"/> + <source>Gaussian</source> + <translation>Gaussian</translation> + </message> + <message> + <location filename="Widgets/FilterChoice.cpp" line="194"/> + <source>Prewitt</source> + <translation>Prewitt</translation> + </message> + <message> + <location filename="Widgets/FilterChoice.cpp" line="194"/> + <source>Roberts</source> + <translation>Roberts</translation> + </message> + <message> + <location filename="Widgets/FilterChoice.cpp" line="194"/> + <source>Sobel</source> + <translation>Sobel</translation> + </message> + <message> + <location filename="Widgets/FilterChoice.cpp" line="194"/> + <source>SquareLaplacien</source> + <translation>SquareLaplacien</translation> + </message> + <message> + <location filename="Widgets/FilterChoice.cpp" line="339"/> + <source>Warning!</source> + <translation>Warning!</translation> + </message> + <message> + <location filename="Widgets/FilterChoice.cpp" line="339"/> + <source>This filter will be permanently deleted ?</source> + <translation>This filter will be permanently deleted !</translation> + </message> + <message> + <location filename="Widgets/FilterChoice.cpp" line="340"/> + <source>Do you want to continue?</source> + <translation>Do you want to continue?</translation> + </message> + <message> + <source>Number of Pixels:</source> + <translation type="obsolete">Number of Pixels:</translation> + </message> + <message> + <source>Coefficient:</source> + <translation type="obsolete">Coefficient:</translation> + </message> +</context> +<context> + <name>filtrme::FilterEditor</name> + <message> + <location filename="Widgets/FilterEditor.cpp" line="69"/> + <source>Name:</source> + <translation>Name:</translation> + </message> + <message> + <location filename="Widgets/FilterEditor.cpp" line="72"/> + <source>Number of filters:</source> + <translation>Number of filters:</translation> + </message> + <message> + <location filename="Widgets/FilterEditor.cpp" line="105"/> + <source>FilterEditor</source> + <translation>Filter editor</translation> + </message> + <message> + <location filename="Widgets/FilterEditor.cpp" line="117"/> + <location filename="Widgets/FilterEditor.cpp" line="240"/> + <source>Error!</source> + <translation>Error!</translation> + </message> + <message> + <location filename="Widgets/FilterEditor.cpp" line="117"/> + <source>Your filter has to have a name to be saved.</source> + <translation>Your filter has to have a name to be saved.</translation> + </message> + <message> + <location filename="Widgets/FilterEditor.cpp" line="166"/> + <location filename="Widgets/FilterEditor.cpp" line="254"/> + <source>Warning!</source> + <translation>Warning!</translation> + </message> + <message> + <location filename="Widgets/FilterEditor.cpp" line="166"/> + <source>This filter name is already use.</source> + <translation>This filter name is already use.</translation> + </message> + <message> + <location filename="Widgets/FilterEditor.cpp" line="167"/> + <source>Do you want to replace it?</source> + <translation>Do you want to replace it?</translation> + </message> + <message> + <location filename="Widgets/FilterEditor.cpp" line="240"/> + <source>Every square have to be completed by int value.</source> + <translation>Every square have to be completed by int value.</translation> + </message> + <message> + <location filename="Widgets/FilterEditor.cpp" line="241"/> + <source>Filter %1 isn't ok.</source> + <translation>Filter %1 isn't ok.</translation> + </message> + <message> + <location filename="Widgets/FilterEditor.cpp" line="254"/> + <source>Unsaved changes will be lost.</source> + <translation>Unsaved changes will be lost.</translation> + </message> + <message> + <location filename="Widgets/FilterEditor.cpp" line="255"/> + <source>Do you want to continue?</source> + <translation>Do you want to continue?</translation> + </message> +</context> +<context> + <name>filtrme::FilterEditorItem</name> + <message> + <location filename="Widgets/FilterEditorItem.cpp" line="80"/> + <source>Width:</source> + <translation>Width:</translation> + </message> + <message> + <location filename="Widgets/FilterEditorItem.cpp" line="83"/> + <source>Height:</source> + <translation>Height:</translation> + </message> +</context> +<context> + <name>filtrme::FilteringService</name> + <message> + <source>Filtering</source> + <translation type="obsolete">Filtering</translation> + </message> + <message> + <location filename="Services/FilteringService.cpp" line="40"/> + <source>&Apply filter</source> + <translation>&Apply filter</translation> + </message> + <message> + <location filename="Services/FilteringService.cpp" line="42"/> + <source>&Edit filters</source> + <translation>&Edit filters</translation> + </message> +</context> +<context> + <name>genericinterface::GenericInterface</name> + <message> + <source>Filtering</source> + <translation type="obsolete">Filtering</translation> + </message> +</context> +<context> + <name>genericinterface::MorphoMatService</name> + <message> + <source>&Mathematical morphology</source> + <translation type="obsolete">&Mathematical morphology</translation> + </message> + <message> + <location filename="Services/MorphoMatService.cpp" line="58"/> + <source>&Erosion</source> + <translation>&Erosion</translation> + </message> + <message> + <location filename="Services/MorphoMatService.cpp" line="59"/> + <source>&Dilatation</source> + <translation>&Dilatation</translation> + </message> + <message> + <location filename="Services/MorphoMatService.cpp" line="60"/> + <source>&Opening</source> + <translation>&Opening</translation> + </message> + <message> + <location filename="Services/MorphoMatService.cpp" line="61"/> + <source>&Closing</source> + <translation>&Closing</translation> + </message> + <message> + <location filename="Services/MorphoMatService.cpp" line="62"/> + <source>&Gradient</source> + <translation>&Gradient</translation> + </message> + <message> + <location filename="Services/MorphoMatService.cpp" line="63"/> + <source>&White top hat</source> + <translation>&White top hat</translation> + </message> + <message> + <location filename="Services/MorphoMatService.cpp" line="64"/> + <source>&Black top hat</source> + <translation>&Black top hat</translation> + </message> + <message> + <location filename="Services/MorphoMatService.cpp" line="66"/> + <source>&Structuring element</source> + <translation>&Structuring element</translation> + </message> +</context> +<context> + <name>gi</name> + <message> + <source>Filtering</source> + <translation type="obsolete">Filtering</translation> + </message> +</context> +</TS> diff --git a/app/eiimage_fr.ts b/app/eiimage_fr.ts new file mode 100644 index 0000000000000000000000000000000000000000..18aca6dace2b11ad8057ec830b1474fce29555d2 --- /dev/null +++ b/app/eiimage_fr.ts @@ -0,0 +1,2840 @@ +<?xml version="1.0" encoding="utf-8"?> +<!DOCTYPE TS> +<TS version="2.0" language="fr_FR"> +<context> + <name></name> + <message> + <location filename="main.cpp" line="124"/> + <source>&Image</source> + <oldsource>Image</oldsource> + <translation>&Image</translation> + </message> + <message> + <location filename="main.cpp" line="139"/> + <source>&Tools</source> + <oldsource>Tools</oldsource> + <translation>Ou&tils</translation> + </message> + <message> + <location filename="main.cpp" line="151"/> + <source>&Encoding</source> + <oldsource>Encoding</oldsource> + <translation>&Encodage</translation> + </message> + <message> + <location filename="main.cpp" line="159"/> + <source>Transforms</source> + <translation>Transformées</translation> + </message> + <message> + <location filename="main.cpp" line="167"/> + <source>Analysis</source> + <translation>Analyse</translation> + </message> + <message> + <location filename="Services/FilteringService.cpp" line="39"/> + <location filename="main.cpp" line="176"/> + <source>Filtering</source> + <translation>Filtrage</translation> + </message> +</context> +<context> + <name>BFlit</name> + <message> + <location filename="Operations/BFlitOp.cpp" line="59"/> + <source>Number of point on each side : </source> + <translation>Nombre de points de chaque côté : </translation> + </message> + <message> + <location filename="Operations/BFlitOp.cpp" line="60"/> + <source>Number of iteration : </source> + <translation>Nombre d'itérations : </translation> + </message> +</context> +<context> + <name>BFlitOp</name> + <message> + <source>BFlit</source> + <translation type="obsolete">BFlit</translation> + </message> + <message> + <source>Parameters</source> + <translation type="obsolete">Paramètres</translation> + </message> + <message> + <source>Validate</source> + <translation type="obsolete">Valider</translation> + </message> +</context> +<context> + <name>CenterOp</name> + <message> + <source>Center</source> + <translation type="obsolete">Centrer</translation> + </message> + <message> + <location filename="Operations/CenterOp.cpp" line="72"/> + <source>centered</source> + <oldsource> - centered</oldsource> + <translation>centrée</translation> + </message> +</context> +<context> + <name>ClassAnalysis</name> + <message> + <location filename="Operations/ClassAnalysisOp.cpp" line="60"/> + <location filename="Operations/ClassAnalysisOp.cpp" line="79"/> + <source>mean</source> + <translation>moyenne</translation> + </message> + <message> + <location filename="Operations/ClassAnalysisOp.cpp" line="61"/> + <location filename="Operations/ClassAnalysisOp.cpp" line="80"/> + <source>standard deviation</source> + <translation>écart-type</translation> + </message> + <message> + <location filename="Operations/ClassAnalysisOp.cpp" line="78"/> + <source>classified</source> + <translation>classifiée</translation> + </message> +</context> +<context> + <name>ClassAnalysisDialog</name> + <message> + <source>Dialog</source> + <translation type="obsolete">Dialog</translation> + </message> + <message> + <location filename="Operations/ClassAnalysisDialog.ui" line="14"/> + <source>Class analysis</source> + <translation>Classification</translation> + </message> + <message> + <location filename="Operations/ClassAnalysisDialog.ui" line="22"/> + <source>Step : </source> + <translation>Étape : </translation> + </message> + <message> + <location filename="Operations/ClassAnalysisDialog.ui" line="35"/> + <source>Classification step</source> + <translation>Étape de classification</translation> + </message> + <message> + <location filename="Operations/ClassAnalysisDialog.ui" line="30"/> + <source>Learning step</source> + <translation>Étape d'apprentissage</translation> + </message> + <message> + <location filename="Operations/ClassAnalysisDialog.ui" line="40"/> + <source>Print file info</source> + <translation>Afficher les info. du fichier</translation> + </message> + <message> + <location filename="Operations/ClassAnalysisDialog.ui" line="48"/> + <source>Window size : </source> + <translation>Taille de la fenêtre : </translation> + </message> + <message> + <location filename="Operations/ClassAnalysisDialog.ui" line="71"/> + <source>File : </source> + <translation>Fichier : </translation> + </message> + <message> + <location filename="Operations/ClassAnalysisDialog.ui" line="83"/> + <source>browse</source> + <translation>parcourir</translation> + </message> + <message> + <location filename="Operations/ClassAnalysisDialog.cpp" line="35"/> + <source>Please select the image's area to classify :</source> + <translation>Veuillez sélectionner les zones de l'image à classifier : </translation> + </message> +</context> +<context> + <name>ClassResult</name> + <message> + <location filename="Operations/ClassResultOp.cpp" line="81"/> + <source> +Nombre de classes = %1 </source> + <oldsource> +Nombre de classes = %1 +</oldsource> + <translation> +Nombre de classes = %1 </translation> + </message> + <message> + <location filename="Operations/ClassResultOp.cpp" line="85"/> + <source>Valeur de la classe %1 = %2</source> + <oldsource>Valeur de la classe %1 = %2 +</oldsource> + <translation>Valeur de la classe %1 = %2</translation> + </message> + <message> + <location filename="Operations/ClassResultOp.cpp" line="80"/> + <source>Voici les résultats du classement : +</source> + <translation>Voici les résultats du classement : +</translation> + </message> + <message> + <location filename="Operations/ClassResultOp.cpp" line="58"/> + <source>Critère de zone intérieure : </source> + <translation>Critère de zone intérieure : </translation> + </message> + <message> + <location filename="Operations/ClassResultOp.cpp" line="59"/> + <source>Critère de zone frontière : </source> + <translation>Critère de zone frontière : </translation> + </message> + <message> + <location filename="Operations/ClassResultOp.cpp" line="60"/> + <source><b>Critère de zones (relatifs aux zones totales) : </b></source> + <translation><b>Critère de zones (relatifs aux zones totales) : </b></translation> + </message> + <message> + <location filename="Operations/ClassResultOp.cpp" line="62"/> + <source><b>Select the image's classes zones : </b></source> + <translation><b>Sélectionner les zones des classes de l'image : </b></translation> + </message> + <message> + <location filename="Operations/ClassResultOp.cpp" line="121"/> + <source>Le taux de bon classement en zone intérieure %1 vaut: %2%</source> + <oldsource>Le taux de bon classement en zone intérieure %1 vaut: %2% +</oldsource> + <translation>Le taux de bon classement en zone intérieure %1 vaut: %2%</translation> + </message> + <message> + <location filename="Operations/ClassResultOp.cpp" line="124"/> + <source>Le taux de bon classement en zone frontière %1 vaut: %2%</source> + <oldsource>Le taux de bon classement en zone frontière %1 vaut: %2% +</oldsource> + <translation>Le taux de bon classement en zone frontière %1 vaut: %2%</translation> + </message> + <message> + <location filename="Operations/ClassResultOp.cpp" line="135"/> + <source>Le taux de bon classement en zone intérieure globale vaut: %1%</source> + <oldsource>Le taux de bon classement en zone intérieure globale vaut: %1% +</oldsource> + <translation>Le taux de bon classement en zone intérieure globale vaut: %1%</translation> + </message> + <message> + <location filename="Operations/ClassResultOp.cpp" line="136"/> + <source>Le taux de bon classement en zone frontière globale vaut: %1%</source> + <oldsource>Le taux de bon classement en zone frontière globale vaut: %1% +</oldsource> + <translation>Le taux de bon classement en zone frontière globale vaut: %1%</translation> + </message> +</context> +<context> + <name>Color</name> + <message> + <location filename="Tools.h" line="36"/> + <source>Black</source> + <translation>Noir</translation> + </message> + <message> + <location filename="Tools.h" line="37"/> + <source>Alpha</source> + <translation>Alpha</translation> + </message> + <message> + <location filename="Tools.h" line="38"/> + <source>Red</source> + <translation>Rouge</translation> + </message> + <message> + <location filename="Tools.h" line="38"/> + <source>Green</source> + <translation>Vert</translation> + </message> + <message> + <location filename="Tools.h" line="38"/> + <source>Blue</source> + <translation>Bleu</translation> + </message> + <message> + <location filename="Tools.h" line="38"/> + <source>Color</source> + <translation>Couleur</translation> + </message> +</context> +<context> + <name>ColorDialog</name> + <message> + <source>Dialog</source> + <translation type="obsolete">Dialog</translation> + </message> + <message> + <location filename="Operations/ColorDialog.ui" line="14"/> + <source>RGB image generator</source> + <translation>Générateur d'image RVB</translation> + </message> + <message> + <location filename="Operations/ColorDialog.ui" line="20"/> + <source>Image size</source> + <translation>Taille de l'image</translation> + </message> + <message> + <location filename="Operations/ColorDialog.ui" line="26"/> + <source>Width : </source> + <translation>Largeur : </translation> + </message> + <message> + <location filename="Operations/ColorDialog.ui" line="40"/> + <source>Height : </source> + <translation>Hauteur : </translation> + </message> + <message> + <location filename="Operations/ColorDialog.ui" line="57"/> + <source>Mode</source> + <translation>Mode</translation> + </message> + <message> + <location filename="Operations/ColorDialog.ui" line="63"/> + <source>RGB</source> + <translation>RVB</translation> + </message> + <message> + <location filename="Operations/ColorDialog.ui" line="73"/> + <source>HSV</source> + <translation>TSV</translation> + </message> + <message> + <location filename="Operations/ColorDialog.ui" line="86"/> + <source>Red : </source> + <translation>Rouge : </translation> + </message> + <message> + <location filename="Operations/ColorDialog.ui" line="100"/> + <source>Green : </source> + <translation>Vert : </translation> + </message> + <message> + <location filename="Operations/ColorDialog.ui" line="114"/> + <source>Blue : </source> + <translation>Bleu : </translation> + </message> + <message> + <location filename="Operations/ColorDialog.ui" line="147"/> + <source>Saturation : </source> + <translation>Saturation : </translation> + </message> + <message> + <location filename="Operations/ColorDialog.ui" line="161"/> + <source>Value : </source> + <translation>Valeur : </translation> + </message> + <message> + <location filename="Operations/ColorDialog.ui" line="175"/> + <source>Hue : </source> + <translation>Teinte : </translation> + </message> +</context> +<context> + <name>ColorimetryOp</name> + <message> + <source>Colorimetry</source> + <translation type="obsolete">Colorimétrie</translation> + </message> + <message> + <source>Zero crossing</source> + <translation type="obsolete">Passage par zero</translation> + </message> + <message> + <source>Red : </source> + <translation type="obsolete">Rouge : </translation> + </message> + <message> + <source>Green : </source> + <translation type="obsolete">Vert : </translation> + </message> + <message> + <source>Blue : </source> + <translation type="obsolete">Bleu : </translation> + </message> + <message> + <source>Hue : </source> + <translation type="obsolete">Teinte : </translation> + </message> + <message> + <source>Saturation : </source> + <translation type="obsolete">Saturation : </translation> + </message> + <message> + <source>Value : </source> + <translation type="obsolete">Valeur : </translation> + </message> + <message> + <source>Red: </source> + <translation type="obsolete">Rouge : </translation> + </message> + <message> + <source>Green: </source> + <translation type="obsolete">Vert : </translation> + </message> + <message> + <source>Blue: </source> + <translation type="obsolete">Bleu : </translation> + </message> + <message> + <source>Hue: </source> + <translation type="obsolete">Teinte : </translation> + </message> + <message> + <source>Saturation: </source> + <translation type="obsolete">Saturation : </translation> + </message> + <message> + <source>Value: </source> + <translation type="obsolete">Valeur : </translation> + </message> +</context> +<context> + <name>CombineColorOp</name> + <message> + <source>Combine color planes</source> + <translation type="obsolete">Combiner les plans de couleurs</translation> + </message> + <message> + <source>Parameters</source> + <translation type="obsolete">Paramètres</translation> + </message> + <message> + <location filename="Operations/CombineColorOp.cpp" line="95"/> + <source>Reconstructed color image</source> + <translation>Image couleur reconstituée</translation> + </message> +</context> +<context> + <name>CroissanceOp</name> + <message> + <source>Croissance</source> + <translation type="obsolete">Croissance</translation> + </message> + <message> + <location filename="Operations/CroissanceOp.cpp" line="59"/> + <source>At origin</source> + <translation>A l'origine</translation> + </message> + <message> + <location filename="Operations/CroissanceOp.cpp" line="60"/> + <source>Point of lowest luminance</source> + <translation>Point de luminance minimale</translation> + </message> + <message> + <location filename="Operations/CroissanceOp.cpp" line="62"/> + <source>| current - mean | < threshold</source> + <translation>| actuel - moyenne | < seuil</translation> + </message> + <message> + <location filename="Operations/CroissanceOp.cpp" line="63"/> + <source>| current - initial | < threshold</source> + <translation>| actuel - initial | < seuil</translation> + </message> + <message> + <location filename="Operations/CroissanceOp.cpp" line="66"/> + <source>Threshold : </source> + <translation>Seuil : </translation> + </message> + <message> + <location filename="Operations/CroissanceOp.cpp" line="67"/> + <source>Initial germ : </source> + <translation>Germe initial : </translation> + </message> + <message> + <location filename="Operations/CroissanceOp.cpp" line="68"/> + <source>Stopping point : </source> + <translation>Point d'arrêt : </translation> + </message> + <message> + <location filename="Operations/CroissanceOp.cpp" line="101"/> + <source>Luminance</source> + <translation>Luminance</translation> + </message> + <message> + <location filename="Operations/CroissanceOp.cpp" line="102"/> + <source>Color</source> + <translation>Couleur</translation> + </message> + <message> + <location filename="Operations/CroissanceOp.cpp" line="103"/> + <source>Total number of area : %1</source> + <translation>Nombre total de zone : %1</translation> + </message> + <message> + <location filename="Operations/CroissanceOp.cpp" line="104"/> + <source>Mean number of point per area : %1</source> + <translation>Nombre moyen de points par zone : %1</translation> + </message> +</context> +<context> + <name>DCT</name> + <message> + <location filename="Operations/DCTOp.cpp" line="57"/> + <source>DCT</source> + <translation>DCT</translation> + </message> + <message> + <location filename="Operations/DCTOp.cpp" line="58"/> + <source>inverse DCT</source> + <translation>DCT inverse</translation> + </message> +</context> +<context> + <name>DCTDialog</name> + <message> + <source>Dialog</source> + <translation type="obsolete">Dialog</translation> + </message> + <message> + <location filename="Operations/DCTDialog.ui" line="14"/> + <source>DCT encoding</source> + <translation>DCT avec encodage</translation> + </message> + <message> + <location filename="Operations/DCTDialog.ui" line="20"/> + <source>Encoding mode && associated parameters</source> + <translation>Mode d'encodage && paramètres associés</translation> + </message> + <message> + <location filename="Operations/DCTDialog.ui" line="26"/> + <source>Coefficients truncation</source> + <translation>Troncature des coefficients</translation> + </message> + <message> + <location filename="Operations/DCTDialog.ui" line="60"/> + <source>Truncation limit : </source> + <translation>Limite de troncature : </translation> + </message> + <message> + <location filename="Operations/DCTDialog.ui" line="79"/> + <source>Bit allocation matrice</source> + <translation>Matrice d'allocation de bits</translation> + </message> + <message> + <location filename="Operations/DCTDialog.ui" line="104"/> + <source>Initial number of bits : </source> + <translation>Nombre de bits initial : </translation> + </message> + <message> + <location filename="Operations/DCTDialog.ui" line="141"/> + <source>Slope value : </source> + <translation>Valeur de la pente : </translation> + </message> +</context> +<context> + <name>DMM</name> + <message> + <location filename="Operations/DMMOp.cpp" line="194"/> + <source>DMM error</source> + <translation>DMM (erreur)</translation> + </message> +</context> +<context> + <name>DMMDialog</name> + <message> + <location filename="Operations/DMMDialog.cpp" line="44"/> + <location filename="Operations/DMMDialog.cpp" line="279"/> + <source>Erosion</source> + <translation>Erosion</translation> + </message> + <message> + <location filename="Operations/DMMDialog.cpp" line="44"/> + <location filename="Operations/DMMDialog.cpp" line="276"/> + <source>Dilatation</source> + <translation>Dilatation</translation> + </message> + <message> + <location filename="Operations/DMMDialog.cpp" line="44"/> + <location filename="Operations/DMMDialog.cpp" line="282"/> + <source>Opening</source> + <translation>Ouverture</translation> + </message> + <message> + <location filename="Operations/DMMDialog.cpp" line="44"/> + <location filename="Operations/DMMDialog.cpp" line="285"/> + <source>Closing</source> + <translation>Fermeture</translation> + </message> + <message> + <location filename="Operations/DMMDialog.cpp" line="44"/> + <location filename="Operations/DMMDialog.cpp" line="46"/> + <source>DMM</source> + <translation>DMM</translation> + </message> + <message> + <location filename="Operations/DMMDialog.cpp" line="62"/> + <source>Structuring element</source> + <translation>Elément structurant</translation> + </message> + <message> + <location filename="Operations/DMMDialog.cpp" line="128"/> + <source>Validate</source> + <translation>Valider</translation> + </message> +</context> +<context> + <name>DMMOp</name> + <message> + <source>DMM</source> + <translation type="obsolete">DMM</translation> + </message> + <message> + <location filename="Operations/DMMOp.cpp" line="56"/> + <source>DMM (dilatation)</source> + <translation>DMM (dilatation)</translation> + </message> + <message> + <location filename="Operations/DMMOp.cpp" line="62"/> + <source>DMM (erosion)</source> + <translation>DMM (erosion)</translation> + </message> + <message> + <location filename="Operations/DMMOp.cpp" line="68"/> + <source>DMM (opening)</source> + <translation>DMM (opening)</translation> + </message> + <message> + <location filename="Operations/DMMOp.cpp" line="74"/> + <source>DMM (closing)</source> + <translation>DMM (closing)</translation> + </message> + <message> + <location filename="Operations/DMMOp.cpp" line="192"/> + <source>DMM component #%1</source> + <translation>DMM (composante %1)</translation> + </message> +</context> +<context> + <name>Dialog</name> + <message> + <location filename="Operations/MICDDialog_.ui" line="17"/> + <source>MICD Encoding</source> + <translation>Encodage MICD</translation> + </message> + <message> + <location filename="Operations/MICDDialog_.ui" line="41"/> + <source>Predictor P(X)</source> + <translation>Prédicteur P(X)</translation> + </message> + <message> + <location filename="Operations/MICDDialog_.ui" line="47"/> + <source>A</source> + <translation>A</translation> + </message> + <message> + <location filename="Operations/MICDDialog_.ui" line="54"/> + <source>C</source> + <translation>C</translation> + </message> + <message> + <location filename="Operations/MICDDialog_.ui" line="61"/> + <source>(A + C) / 2</source> + <translation>(A + C) / 2</translation> + </message> + <message> + <location filename="Operations/MICDDialog_.ui" line="68"/> + <source>Modified Graham's</source> + <translation>Graham modifié</translation> + </message> + <message> + <location filename="Operations/MICDDialog_.ui" line="77"/> + <source>Q = </source> + <translation>Q = </translation> + </message> + <message> + <location filename="Operations/MICDDialog_.ui" line="120"/> + <source>Quantifier</source> + <translation>Quantifieur</translation> + </message> + <message> + <location filename="Operations/MICDDialog_.ui" line="126"/> + <source>Quantification file :</source> + <translation>Fichier de quantification : </translation> + </message> + <message> + <location filename="Operations/MICDDialog_.ui" line="146"/> + <source>Browse</source> + <translation>Parcourir</translation> + </message> + <message> + <location filename="Operations/MICDDialog_.ui" line="174"/> + <source>Open quantification editor</source> + <translation>Ouvrir l'éditeur de quantification</translation> + </message> +</context> +<context> + <name>EIImageService</name> + <message> + <location filename="Services/EIImageService.cpp" line="44"/> + <source>Informations</source> + <translation>Informations</translation> + </message> +</context> +<context> + <name>EntropyOp</name> + <message> + <source>Calcul d'entropie</source> + <translation type="obsolete">Calcul d'entropie</translation> + </message> + <message> + <source>Entropy of the image = %1</source> + <translation type="obsolete">Entropie de l'image = %1</translation> + </message> +</context> +<context> + <name>FFTDialog</name> + <message> + <location filename="Operations/FFTDialog.ui" line="14"/> + <source>Dialog</source> + <translation>Dialog</translation> + </message> + <message utf8="true"> + <location filename="Operations/FFTDialog.ui" line="20"/> + <source>Résultat :</source> + <translation>Résultat :</translation> + </message> + <message> + <location filename="Operations/FFTDialog.ui" line="28"/> + <source>Magnitude + Phase</source> + <translation>Amplitude + Phase</translation> + </message> + <message> + <location filename="Operations/FFTDialog.ui" line="38"/> + <source>Real + Imaginary</source> + <translation>Réel + Imaginaire</translation> + </message> + <message> + <location filename="Operations/FFTDialog.ui" line="47"/> + <source>Centered transform</source> + <translation>Transformée centrée</translation> + </message> +</context> +<context> + <name>FFTOp</name> + <message> + <source>Discrete Fourier transform</source> + <translation type="obsolete">Transformée de Fourrier discrète</translation> + </message> + <message> + <location filename="Operations/FFTOp.cpp" line="96"/> + <source>DFT (phase)</source> + <translation>DFT (phase)</translation> + </message> + <message> + <location filename="Operations/FFTOp.cpp" line="97"/> + <source>DFT (magnitude)</source> + <translation>DFT (magnitude)</translation> + </message> +</context> +<context> + <name>FlipOp</name> + <message> + <source>Flip %1</source> + <translation type="obsolete">Symétrie %1</translation> + </message> + <message> + <location filename="Operations/FlipOp.cpp" line="30"/> + <location filename="Operations/FlipOp.cpp" line="62"/> + <source>horizontal</source> + <translation>horizontale</translation> + </message> + <message> + <location filename="Operations/FlipOp.cpp" line="30"/> + <location filename="Operations/FlipOp.cpp" line="62"/> + <source>vertical</source> + <translation>verticale</translation> + </message> + <message> + <location filename="Operations/FlipOp.cpp" line="62"/> + <source>flipped %1</source> + <translation>symétrie %1</translation> + </message> + <message> + <source> - flipped %1</source> + <translation type="obsolete"> - symétrie %1</translation> + </message> +</context> +<context> + <name>HistogramOp</name> + <message> + <location filename="Operations/HistogramOp.cpp" line="42"/> + <source>Histogram operations</source> + <translation>Opérations sur histogramme</translation> + </message> + <message> + <location filename="Operations/HistogramOp.cpp" line="48"/> + <source>Equalize</source> + <translation>Egaliser</translation> + </message> + <message> + <location filename="Operations/HistogramOp.cpp" line="49"/> + <source>Normalize</source> + <translation>Normaliser</translation> + </message> + <message> + <location filename="Operations/HistogramOp.cpp" line="50"/> + <source>Operation : </source> + <translation>Opération : </translation> + </message> + <message> + <location filename="Operations/HistogramOp.cpp" line="63"/> + <source>equalized</source> + <translation>égalisée</translation> + </message> + <message> + <location filename="Operations/HistogramOp.cpp" line="67"/> + <source>normalized</source> + <translation>normalisée</translation> + </message> +</context> +<context> + <name>Hough</name> + <message> + <location filename="Operations/HoughOp.cpp" line="53"/> + <source>Hough transform</source> + <translation>Transformé de Hough</translation> + </message> + <message> + <location filename="Operations/InverseHoughOp.cpp" line="44"/> + <source>Hough inverse transform</source> + <translation>Transformée de Hough inverse</translation> + </message> +</context> +<context> + <name>HoughDialog</name> + <message> + <source>Dialog</source> + <translation type="obsolete">Dialog</translation> + </message> + <message> + <location filename="Operations/HoughDialog.ui" line="14"/> + <source>Hough transform</source> + <translation>Transformé de Hough</translation> + </message> + <message> + <location filename="Operations/HoughDialog.ui" line="20"/> + <source>Method</source> + <translation>Méthode</translation> + </message> + <message> + <location filename="Operations/HoughDialog.ui" line="26"/> + <source>Method #1</source> + <translation>Méthode n°1</translation> + </message> + <message> + <location filename="Operations/HoughDialog.ui" line="36"/> + <source>Method #2</source> + <translation>Méthode n°2</translation> + </message> + <message> + <location filename="Operations/HoughDialog.ui" line="57"/> + <source>Angle step : </source> + <translation>Pas pour les angles : </translation> + </message> + <message> + <location filename="Operations/HoughDialog.ui" line="93"/> + <source>Distance step : </source> + <translation>Pas pour les distances : </translation> + </message> +</context> +<context> + <name>HuffmanOp</name> + <message> + <source>Huffman</source> + <translation type="obsolete">Huffman</translation> + </message> +</context> +<context> + <name>IFFTOp</name> + <message> + <source>Discrete Fourier reconstruction</source> + <translation type="obsolete">Reconstruction de Fourrier discrète</translation> + </message> + <message> + <source>Parameters</source> + <translation type="obsolete">Paramètres</translation> + </message> + <message> + <location filename="Operations/IFFTOp.cpp" line="66"/> + <source>Magnitude : </source> + <translation>Magnitude : </translation> + </message> + <message> + <location filename="Operations/IFFTOp.cpp" line="67"/> + <source>Phase : </source> + <translation>Phase : </translation> + </message> + <message> + <location filename="Operations/IFFTOp.cpp" line="72"/> + <source>Real part : </source> + <translation>Partie réelle : </translation> + </message> + <message> + <location filename="Operations/IFFTOp.cpp" line="73"/> + <source>Imaginary part : </source> + <translation>Partie imaginaire : </translation> + </message> + <message> + <location filename="Operations/IFFTOp.cpp" line="199"/> + <source>DFT-reconstructed image</source> + <translation>Image DFT reconstruite</translation> + </message> +</context> +<context> + <name>InverseHoughDialog</name> + <message> + <source>Dialog</source> + <translation type="obsolete">Dialog</translation> + </message> + <message> + <location filename="Operations/InverseHoughDialog.ui" line="14"/> + <source>Inverse hough transform</source> + <oldsource>Hough reconstruction</oldsource> + <translation>Transformée de Hough inverse</translation> + </message> + <message> + <location filename="Operations/InverseHoughDialog.ui" line="22"/> + <source>Reconstructed image size : </source> + <translation>Taille de l'image reconstruite : </translation> + </message> + <message> + <location filename="Operations/InverseHoughDialog.ui" line="45"/> + <source>Reconstruction threshold : </source> + <translation>Seuil de reconstruction : </translation> + </message> +</context> +<context> + <name>InversePyramidDialog</name> + <message> + <source>Dialog</source> + <translation type="obsolete">Dialog</translation> + </message> + <message> + <location filename="Operations/InversePyramidDialog.ui" line="14"/> + <source>Pyramidal reconstruction</source> + <oldsource>Pyramid reconstruction</oldsource> + <translation>Reconstruction pyramidale</translation> + </message> + <message> + <location filename="Operations/InversePyramidDialog.ui" line="20"/> + <source>Filter : </source> + <translation>Filtre : </translation> + </message> + <message> + <location filename="Operations/InversePyramidDialog.ui" line="28"/> + <source>triangular</source> + <translation>triangulaire</translation> + </message> + <message> + <location filename="Operations/InversePyramidDialog.ui" line="33"/> + <source>gaussian</source> + <translation>gaussien</translation> + </message> + <message> + <location filename="Operations/InversePyramidDialog.ui" line="38"/> + <source>trimodal</source> + <translation>trimodal</translation> + </message> + <message> + <location filename="Operations/InversePyramidDialog.ui" line="43"/> + <source>rectangular</source> + <translation>rectangulaire</translation> + </message> + <message> + <location filename="Operations/InversePyramidDialog.ui" line="48"/> + <source>qmf</source> + <translation>qmf</translation> + </message> + <message> + <location filename="Operations/InversePyramidDialog.ui" line="69"/> + <source>Number of steps in the pyramid : </source> + <translation>Nombre d'étages dans la pyramide : </translation> + </message> + <message> + <location filename="Operations/InversePyramidDialog.ui" line="102"/> + <source>Step to reconstruct :</source> + <translation>Étage à reconstruire : </translation> + </message> +</context> +<context> + <name>MICD</name> + <message> + <source>MICD Encoding</source> + <translation type="obsolete">Encodage MICD</translation> + </message> + <message> + <location filename="Operations/MICDEncodingOp.cpp" line="53"/> + <source>Error while loading quantification file</source> + <translation>Erreur lors du chargement du fichier de quantification</translation> + </message> + <message> + <location filename="Operations/MICDEncodingOp.cpp" line="53"/> + <source>The specified quantification file could not be opened !</source> + <translation>Le fichier de quantification spécifié n'a pas pu être ouvert !</translation> + </message> + <message> + <location filename="Operations/MICDEncodingOp.cpp" line="60"/> + <source>Error image</source> + <translation>Image d'erreur</translation> + </message> + <message> + <location filename="Operations/MICDEncodingOp.cpp" line="61"/> + <source>Reconstructed image</source> + <translation>Image reconstruite</translation> + </message> +</context> +<context> + <name>MICDDialog</name> + <message> + <source>Dialog</source> + <translation type="obsolete">Dialog</translation> + </message> + <message> + <location filename="Operations/MICDDialog.ui" line="14"/> + <source>MICD encoding</source> + <translation>Encodage MICD</translation> + </message> + <message> + <location filename="Operations/MICDDialog.ui" line="35"/> + <source>Predictor P(X)</source> + <translation>Prédicteur P(X)</translation> + </message> + <message> + <location filename="Operations/MICDDialog.ui" line="41"/> + <source>A</source> + <translation>A</translation> + </message> + <message> + <location filename="Operations/MICDDialog.ui" line="51"/> + <source>C</source> + <translation>C</translation> + </message> + <message> + <location filename="Operations/MICDDialog.ui" line="58"/> + <source>( A + C ) / 2</source> + <translation>( A + C ) / 2</translation> + </message> + <message> + <location filename="Operations/MICDDialog.ui" line="65"/> + <source>Modified Graham's</source> + <translation>Graham modifié</translation> + </message> + <message> + <location filename="Operations/MICDDialog.ui" line="74"/> + <source>Q = </source> + <translation></translation> + </message> + <message> + <location filename="Operations/MICDDialog.ui" line="115"/> + <source>Quantifier</source> + <translation>Quantifieur</translation> + </message> + <message> + <location filename="Operations/MICDDialog.ui" line="121"/> + <source>Quantification file :</source> + <translation>Fichier de quantification : </translation> + </message> + <message> + <location filename="Operations/MICDDialog.ui" line="141"/> + <source>Browse</source> + <translation>Parcourir</translation> + </message> + <message> + <location filename="Operations/MICDDialog.ui" line="169"/> + <source>Open quantification editor</source> + <translation>Ouvrir l'éditeur de quantification</translation> + </message> + <message> + <location filename="Operations/MICDDialog.cpp" line="39"/> + <source>Open file</source> + <translation>Ouvrir un fichier</translation> + </message> + <message> + <location filename="Operations/MICDDialog.cpp" line="39"/> + <source>Loi de quantification (*.loi)</source> + <translation>Loi de quantification (*.loi)</translation> + </message> +</context> +<context> + <name>MICDEncodingOp</name> + <message> + <source>MICD Encoding</source> + <translation type="obsolete">Encodage MICD</translation> + </message> +</context> +<context> + <name>MeanSquareErrorOp</name> + <message> + <location filename="Operations/MeanSquaredErrorOp.cpp" line="84"/> + <source>Mean squarred error : %1 (mean error : %2)</source> + <translation>Erreur quadratique moyenne : %1 (erreur moyenne : %2)</translation> + </message> +</context> +<context> + <name>MeanSquaredErrorOp</name> + <message> + <source>Mean squared error</source> + <translation type="obsolete">Erreur quadratique moyenne</translation> + </message> + <message> + <source>Compare to...</source> + <translation type="obsolete">Comparer à ...</translation> + </message> +</context> +<context> + <name>NoiseOp</name> + <message> + <source>Add noise</source> + <translation type="obsolete">Ajouter du bruit</translation> + </message> + <message> + <source>Parameters</source> + <translation type="obsolete">Paramètres</translation> + </message> + <message> + <location filename="Operations/NoiseOp.cpp" line="54"/> + <source>Impulse noise</source> + <translation>Bruit impulsionnel</translation> + </message> + <message> + <location filename="Operations/NoiseOp.cpp" line="55"/> + <source>Gaussian noise</source> + <translation>Bruit gaussien</translation> + </message> + <message> + <location filename="Operations/NoiseOp.cpp" line="67"/> + <source>Mean : </source> + <translation>Moyenne : </translation> + </message> + <message> + <location filename="Operations/NoiseOp.cpp" line="68"/> + <source>Standard deviation : </source> + <translation>Equart type : </translation> + </message> + <message> + <location filename="Operations/NoiseOp.cpp" line="76"/> + <source>Percent of image : </source> + <translation>Pourcentage de l'image : </translation> + </message> + <message> + <source>Validate</source> + <translation type="obsolete">Valider</translation> + </message> + <message> + <location filename="Operations/NoiseOp.cpp" line="118"/> + <location filename="Operations/NoiseOp.cpp" line="134"/> + <source>impulse noise</source> + <translation>bruit impulsionnel</translation> + </message> + <message> + <location filename="Operations/NoiseOp.cpp" line="152"/> + <location filename="Operations/NoiseOp.cpp" line="161"/> + <source>gaussian noise</source> + <translation>bruit gaussien</translation> + </message> +</context> +<context> + <name>Operations</name> + <message> + <location filename="Operations/BFlitOp.cpp" line="37"/> + <source>BFilt</source> + <oldsource>BFlit</oldsource> + <translation>BFilt</translation> + </message> + <message> + <location filename="Operations/BFlitOp.cpp" line="49"/> + <location filename="Operations/CombineColorOp.cpp" line="49"/> + <location filename="Operations/IFFTOp.cpp" line="49"/> + <location filename="Operations/NoiseOp.cpp" line="49"/> + <location filename="Operations/PointOp.cpp" line="114"/> + <source>Parameters</source> + <translation>Paramètres</translation> + </message> + <message> + <location filename="Operations/BFlitOp.cpp" line="62"/> + <location filename="Operations/NoiseOp.cpp" line="90"/> + <location filename="Operations/PointOp.cpp" line="192"/> + <location filename="Operations/RandomImgOp.cpp" line="105"/> + <source>Validate</source> + <translation>Valider</translation> + </message> + <message> + <source>Colorimetry</source> + <translation type="obsolete">Colorimétrie</translation> + </message> + <message> + <location filename="Operations/CombineColorOp.cpp" line="38"/> + <source>Combine color planes</source> + <translation>Combiner les plans de couleurs</translation> + </message> + <message> + <location filename="Operations/CroissanceOp.cpp" line="37"/> + <location filename="Operations/CroissanceOp.cpp" line="48"/> + <source>Croissance</source> + <translation>Croissance</translation> + </message> + <message> + <location filename="Operations/DMMOp.cpp" line="33"/> + <source>DMM</source> + <translation>DMM</translation> + </message> + <message> + <location filename="Operations/EntropyOp.cpp" line="28"/> + <source>Calcul d'entropie</source> + <translation>Calcul d'entropie</translation> + </message> + <message> + <location filename="Operations/EntropyOp.cpp" line="45"/> + <source>Entropy of the image = %1</source> + <translation>Entropie de l'image = %1</translation> + </message> + <message> + <location filename="Operations/FFTOp.cpp" line="28"/> + <source>Fourier transform</source> + <oldsource>Discrete Fourier transform</oldsource> + <translation>Transformée de Fourrier</translation> + </message> + <message> + <location filename="Operations/HistogramOp.cpp" line="32"/> + <source>Histogram operations</source> + <translation>Opérations sur histogramme</translation> + </message> + <message> + <location filename="Operations/HuffmanOp.cpp" line="29"/> + <source>Huffman</source> + <translation>Huffman</translation> + </message> + <message> + <source>Discrete Fourier reconstruction</source> + <translation type="obsolete">Reconstruction de Fourrier discrète</translation> + </message> + <message> + <location filename="Operations/MICDEncodingOp.cpp" line="32"/> + <source>MICD Encoding</source> + <translation>Codage MICD</translation> + </message> + <message> + <location filename="Operations/MeanSquaredErrorOp.cpp" line="34"/> + <source>Mean squared error</source> + <translation>Erreur quadratique moyenne</translation> + </message> + <message> + <location filename="Operations/MeanSquaredErrorOp.cpp" line="45"/> + <location filename="Operations/SignalToNoiseOp.cpp" line="45"/> + <source>Compare to...</source> + <translation>Comparer à ...</translation> + </message> + <message> + <location filename="Operations/MeanSquaredErrorOp.cpp" line="53"/> + <location filename="Operations/SignalToNoiseOp.cpp" line="53"/> + <source>Compare %1 to : </source> + <translation>Comparer %1 à : </translation> + </message> + <message> + <location filename="Operations/NoiseOp.cpp" line="42"/> + <source>Add noise</source> + <translation>Ajouter du bruit</translation> + </message> + <message> + <source>impulse noise</source> + <translation type="obsolete">bruit impulsionnel</translation> + </message> + <message> + <source>gaussian noise</source> + <translation type="obsolete">bruit gaussien</translation> + </message> + <message> + <location filename="Operations/PointOp.cpp" line="44"/> + <source>Pixel operations</source> + <translation>Opération sur les pixels</translation> + </message> + <message> + <location filename="Operations/PseudoColorOp.cpp" line="28"/> + <source>Pseudo color</source> + <translation>Pseudo-couleur</translation> + </message> + <message> + <location filename="Operations/QuantificationOp.cpp" line="31"/> + <source>Quantification</source> + <translation>Quantification</translation> + </message> + <message> + <location filename="Operations/RandomImgOp.cpp" line="37"/> + <source>Generate random image</source> + <translation>Générer une image aléatoire</translation> + </message> + <message> + <location filename="Operations/RandomImgOp.cpp" line="129"/> + <location filename="Operations/RandomImgOp.cpp" line="149"/> + <source>Random image</source> + <translation>Image aléatoire</translation> + </message> + <message> + <location filename="Operations/RejectionRingOp.cpp" line="36"/> + <location filename="Operations/RejectionRingOp.cpp" line="42"/> + <source>Rejection ring</source> + <translation>Anneau de réjection</translation> + </message> + <message> + <source>Rejection ring (%1 %2 %3)</source> + <translation type="obsolete">Anneau de réjection (%1 %2 %3)</translation> + </message> + <message> + <location filename="Operations/RotateOp.cpp" line="32"/> + <source>Rotation</source> + <translation>Rotation</translation> + </message> + <message> + <location filename="Operations/ScalingOp.cpp" line="42"/> + <location filename="Operations/ScalingOp.cpp" line="57"/> + <source>Scaling</source> + <translation>Echantillonage</translation> + </message> + <message> + <location filename="Operations/SignalToNoiseOp.cpp" line="33"/> + <source>Signal-to-noise ratio</source> + <translation>Rapport signal-bruit</translation> + </message> + <message> + <source>+inf</source> + <translation type="obsolete">infini</translation> + </message> + <message> + <location filename="Operations/SinusSynthesisOp.cpp" line="38"/> + <location filename="Operations/SinusSynthesisOp.cpp" line="144"/> + <source>Sinus synthesis</source> + <translation>Synthèse image sinus</translation> + </message> + <message> + <source>Test</source> + <translation type="obsolete">Test</translation> + </message> + <message> + <location filename="Operations/ThresholdOp.cpp" line="11"/> + <source>Thresholding</source> + <translation>Seuillage</translation> + </message> + <message> + <location filename="Operations/TranslateOp.cpp" line="12"/> + <source>Translation</source> + <translation>Translation</translation> + </message> + <message> + <location filename="Operations/ZeroCrossingOp.cpp" line="33"/> + <source>Zero crossing</source> + <translation>Passages par zéro</translation> + </message> + <message> + <location filename="Operations/CenterOp.cpp" line="32"/> + <source>Center</source> + <translation>Centrer</translation> + </message> + <message> + <location filename="Operations/SplitColorOp.cpp" line="31"/> + <source>Split color planes</source> + <translation>Séparer les plans de couleurs </translation> + </message> + <message> + <location filename="Operations/FlipOp.cpp" line="30"/> + <source>Flip %1</source> + <translation>Symétrie %1</translation> + </message> + <message> + <source>Class analysis</source> + <translation type="obsolete">Classification</translation> + </message> + <message> + <location filename="Operations/DCTOp.cpp" line="30"/> + <source>Discrete cosinus transform</source> + <translation>DCT 16x16 avec réduction des coef.</translation> + </message> + <message> + <location filename="Operations/HadamardOp.cpp" line="39"/> + <location filename="Operations/HadamardOp.cpp" line="51"/> + <source>8x8 transforms</source> + <translation>Transformées 8x8 (Haar, Hadamard, DCT)</translation> + </message> + <message> + <location filename="Operations/HoughOp.cpp" line="30"/> + <source>Hough transform</source> + <translation>Transformée de Hough</translation> + </message> + <message> + <location filename="Operations/InverseHoughOp.cpp" line="28"/> + <source>Houghman inverse transform</source> + <translation>Transformée de Hough inverse</translation> + </message> + <message> + <location filename="Operations/InversePyramidOp.cpp" line="31"/> + <source>Pyramidal reconstruction</source> + <oldsource>Reconstruct pyramid</oldsource> + <translation>Reconstruction pyramidale</translation> + </message> + <message> + <location filename="Operations/InversePyramidOp.cpp" line="41"/> + <location filename="Operations/InversePyramidOp.cpp" line="46"/> + <location filename="Operations/PyramidOp.cpp" line="43"/> + <location filename="Operations/PyramidOp.cpp" line="48"/> + <source>The operation can't be applied on this image</source> + <translation>L'opération ne peut pas être appliquée sur cette image</translation> + </message> + <message> + <location filename="Operations/InversePyramidOp.cpp" line="42"/> + <source>The image width must be twice the image height.</source> + <translation>La largeur de l'image doit être deux fois la hauteur de l'image.</translation> + </message> + <message> + <location filename="Operations/InversePyramidOp.cpp" line="47"/> + <location filename="Operations/PyramidOp.cpp" line="49"/> + <source>The image dimensions must be power of 2.</source> + <translation>Les dimensions de l'images doivent être puissances de 2.</translation> + </message> + <message> + <source>Create pyramid</source> + <translation type="obsolete">Construire une pyramide</translation> + </message> + <message> + <location filename="Operations/PyramidOp.cpp" line="32"/> + <source>Pyramidal decomposition</source> + <translation>Décomposition pyramidale</translation> + </message> + <message> + <location filename="Operations/PyramidOp.cpp" line="44"/> + <source>The image width must equal the image height.</source> + <translation>La largeur de l'image doit être égale à sa hauteur.</translation> + </message> + <message> + <location filename="Operations/ClassResultOp.cpp" line="37"/> + <source>Classification results</source> + <translation>Résultats de classification</translation> + </message> + <message> + <location filename="Operations/ColorimetryOp.cpp" line="34"/> + <source>Generate RGB image</source> + <translation>Générer une image RVB</translation> + </message> + <message> + <location filename="Operations/ColorimetryOp.cpp" line="45"/> + <source>RGB image generator</source> + <translation>Générateur d'image RVB</translation> + </message> + <message> + <location filename="Operations/IFFTOp.cpp" line="38"/> + <source>Inverse Fourier transform</source> + <translation>Transformée de Fourier inverse</translation> + </message> + <message> + <location filename="Operations/ClassAnalysisOp.cpp" line="33"/> + <source>Supervised classification</source> + <translation>Classification supervisée</translation> + </message> +</context> +<context> + <name>PluginManager</name> + <message> + <location filename="Services/PluginManager.cpp" line="36"/> + <source>Plugins</source> + <translation>Plugins</translation> + </message> + <message> + <location filename="Services/PluginManager.cpp" line="52"/> + <source>&Plugin</source> + <translation>&Plugin</translation> + </message> + <message> + <location filename="Services/PluginManager.cpp" line="54"/> + <source>&Load plugin</source> + <translation>&Charger un plugin</translation> + </message> + <message> + <location filename="Services/PluginManager.cpp" line="55"/> + <source>&Unload all plugins</source> + <translation>&Décharger tous les plugins</translation> + </message> + <message> + <location filename="Services/PluginManager.cpp" line="78"/> + <source>Load plugin</source> + <translation>Charger un plugin</translation> + </message> + <message> + <location filename="Services/PluginManager.cpp" line="78"/> + <source>Plugin (*.dll *.so *.dylib)</source> + <translation>Plugin (*.dll *.so *.dylib)</translation> + </message> + <message> + <location filename="Services/PluginManager.cpp" line="173"/> + <location filename="Services/PluginManager.cpp" line="184"/> + <location filename="Services/PluginManager.cpp" line="196"/> + <source>Error loading plugin</source> + <translation>Erreur lors du chargement d'un plugin</translation> + </message> + <message> + <location filename="Services/PluginManager.cpp" line="184"/> + <source>Could not find the plugin's entry point "loadPlugin"</source> + <translation>Point d'entrée "loadPlugin" introuvable</translation> + </message> + <message> + <location filename="Services/PluginManager.cpp" line="196"/> + <source>The getPlugin entry point does not return a valid Plugin</source> + <translation>Le point d'entrée getPlugin ne retourne pas un Plugin valide</translation> + </message> +</context> +<context> + <name>PointOp</name> + <message> + <source>Pixel operations</source> + <translation type="obsolete">Opération sur les pixels</translation> + </message> + <message> + <source>Parameter</source> + <translation type="obsolete">Paramètres</translation> + </message> + <message> + <location filename="Operations/PointOp.cpp" line="119"/> + <source>Second operand</source> + <translation>Second opérande</translation> + </message> + <message> + <location filename="Operations/PointOp.cpp" line="120"/> + <source>Value</source> + <translation>Valeur</translation> + </message> + <message> + <location filename="Operations/PointOp.cpp" line="121"/> + <source>Image</source> + <translation>Image</translation> + </message> + <message> + <location filename="Operations/PointOp.cpp" line="128"/> + <source>Explode colors</source> + <translation>Eclater les couleurs</translation> + </message> + <message> + <source>Validate</source> + <translation type="obsolete">Valider</translation> + </message> +</context> +<context> + <name>PseudoColorOp</name> + <message> + <location filename="Operations/PseudoColorOp.cpp" line="53"/> + <source>Pseudo color</source> + <translation>Pseudo-couleur</translation> + </message> +</context> +<context> + <name>PyramidDialog</name> + <message> + <source>Dialog</source> + <translation type="obsolete">Dialog</translation> + </message> + <message> + <source>Pyramid generator</source> + <translation type="obsolete">Pyramide - génération</translation> + </message> + <message> + <location filename="Operations/PyramidDialog.ui" line="14"/> + <source>Pyramidal decomposition</source> + <translation>Décomposition pyramidale</translation> + </message> + <message> + <location filename="Operations/PyramidDialog.ui" line="20"/> + <source>Type of pyramid</source> + <translation>Type de pyramide</translation> + </message> + <message> + <location filename="Operations/PyramidDialog.ui" line="26"/> + <location filename="Operations/PyramidDialog.ui" line="61"/> + <source>gaussian</source> + <translation>gaussien</translation> + </message> + <message> + <location filename="Operations/PyramidDialog.ui" line="36"/> + <source>laplacian</source> + <translation>laplacien</translation> + </message> + <message> + <location filename="Operations/PyramidDialog.ui" line="48"/> + <source>Filter : </source> + <translation>Filtre : </translation> + </message> + <message> + <location filename="Operations/PyramidDialog.ui" line="56"/> + <source>triangular</source> + <translation>triangulaire</translation> + </message> + <message> + <location filename="Operations/PyramidDialog.ui" line="66"/> + <source>trimodal</source> + <translation>trimodal</translation> + </message> + <message> + <location filename="Operations/PyramidDialog.ui" line="71"/> + <source>rectangular</source> + <translation>rectangulaire</translation> + </message> + <message> + <location filename="Operations/PyramidDialog.ui" line="76"/> + <source>qmf</source> + <translation>qmf</translation> + </message> + <message> + <location filename="Operations/PyramidDialog.ui" line="84"/> + <source>Number of steps : </source> + <translation>Nombre d'étage : </translation> + </message> + <message> + <location filename="Operations/PyramidDialog.ui" line="105"/> + <source>Create only one step :</source> + <translation>Créer unique l'étage : </translation> + </message> +</context> +<context> + <name>QuantificationDialog</name> + <message> + <source>Quantification</source> + <translation type="obsolete">Quantification</translation> + </message> + <message> + <location filename="Operations/QuantificationDialog.cpp" line="40"/> + <source>Quantification file editor</source> + <translation>Éditeur de fichiers de quantification</translation> + </message> + <message> + <location filename="Operations/QuantificationDialog.cpp" line="43"/> + <source>Quantification of %1</source> + <translation>Quantification de %1</translation> + </message> + <message> + <location filename="Operations/QuantificationDialog.cpp" line="54"/> + <source>Linear with centered value</source> + <translation>Linéaire à valeurs centrées</translation> + </message> + <message> + <location filename="Operations/QuantificationDialog.cpp" line="56"/> + <source>Non linear with centered value</source> + <translation>Non linéaire à valeurs centrées</translation> + </message> + <message> + <location filename="Operations/QuantificationDialog.cpp" line="57"/> + <source>Non linear with mean value</source> + <translation>Non linéaire à valeurs moyennes</translation> + </message> + <message> + <location filename="Operations/QuantificationDialog.cpp" line="59"/> + <source>Custom</source> + <translation>Personnalisée</translation> + </message> + <message> + <location filename="Operations/QuantificationDialog.cpp" line="60"/> + <source>Quantification : </source> + <translation>Quantification : </translation> + </message> + <message> + <location filename="Operations/QuantificationDialog.cpp" line="61"/> + <source>Number of values : </source> + <translation>Nombre de valeurs : </translation> + </message> + <message> + <location filename="Operations/QuantificationDialog.cpp" line="87"/> + <source>Exit</source> + <translation>Quitter</translation> + </message> + <message> + <location filename="Operations/QuantificationDialog.cpp" line="90"/> + <source>Apply</source> + <translation>Appliquer</translation> + </message> + <message> + <location filename="Operations/QuantificationDialog.cpp" line="123"/> + <source>Open a file</source> + <translation>Ouvrir un fichier</translation> + </message> + <message> + <location filename="Operations/QuantificationDialog.cpp" line="123"/> + <location filename="Operations/QuantificationDialog.cpp" line="132"/> + <source>Loi de quantification (*.loi)</source> + <translation>Loi de quantification (*.loi)</translation> + </message> + <message> + <location filename="Operations/QuantificationDialog.cpp" line="132"/> + <source>Save to file</source> + <translation>Enregistrer dans un fichier</translation> + </message> +</context> +<context> + <name>QuantificationOp</name> + <message> + <source>Quantification</source> + <translation type="obsolete">Quantification</translation> + </message> + <message> + <location filename="Operations/QuantificationOp.cpp" line="75"/> + <source>quantified</source> + <translation>quantifiée</translation> + </message> +</context> +<context> + <name>QuantificationWidget</name> + <message> + <location filename="Operations/QuantificationWidget.cpp" line="43"/> + <source>Thresholds +(low to high)</source> + <translation>Seuils +(ordre croissant)</translation> + </message> + <message> + <location filename="Operations/QuantificationWidget.cpp" line="45"/> + <source>Values</source> + <translation>Valeurs</translation> + </message> +</context> +<context> + <name>RandomImgOp</name> + <message> + <source>Generate random image</source> + <translation type="obsolete">Générer une image aléatoire</translation> + </message> + <message> + <location filename="Operations/RandomImgOp.cpp" line="43"/> + <source>Parameters</source> + <translation>Paramètres</translation> + </message> + <message> + <location filename="Operations/RandomImgOp.cpp" line="47"/> + <source>Image type</source> + <translation>Type d'image</translation> + </message> + <message> + <location filename="Operations/RandomImgOp.cpp" line="48"/> + <source>8-bit integer</source> + <translation>Entier 8 bit</translation> + </message> + <message> + <location filename="Operations/RandomImgOp.cpp" line="49"/> + <source>Floating point</source> + <translation>Nombre flottant</translation> + </message> + <message> + <location filename="Operations/RandomImgOp.cpp" line="59"/> + <source>Width : </source> + <translation>Largeur : </translation> + </message> + <message> + <location filename="Operations/RandomImgOp.cpp" line="64"/> + <source>Height : </source> + <translation>Hauteur : </translation> + </message> + <message> + <location filename="Operations/RandomImgOp.cpp" line="69"/> + <source>Number of channels : </source> + <translation>Nombre de canaux : </translation> + </message> + <message> + <location filename="Operations/RandomImgOp.cpp" line="79"/> + <location filename="Operations/RandomImgOp.cpp" line="93"/> + <source>Range : </source> + <translation>Plage de valeurs : </translation> + </message> + <message> + <location filename="Operations/RandomImgOp.cpp" line="81"/> + <location filename="Operations/RandomImgOp.cpp" line="95"/> + <source> to </source> + <translation> à </translation> + </message> + <message> + <source>Validate</source> + <translation type="obsolete">Valider</translation> + </message> + <message> + <source>Random image</source> + <translation type="obsolete">Image aléatoire</translation> + </message> +</context> +<context> + <name>RejectionRingOp</name> + <message> + <source>Rejection ring</source> + <translation type="obsolete">Anneau de réjection</translation> + </message> + <message> + <location filename="Operations/RejectionRingOp.cpp" line="49"/> + <source>Width=Height : </source> + <translation>Largeur=Hauteur : </translation> + </message> + <message> + <location filename="Operations/RejectionRingOp.cpp" line="53"/> + <source>Radius : </source> + <translation>Rayon : </translation> + </message> + <message> + <location filename="Operations/RejectionRingOp.cpp" line="57"/> + <source>Thickness (beyond radius) : </source> + <translation>Epaisseur (au delà du rayon) : </translation> + </message> + <message> + <location filename="Operations/RejectionRingOp.cpp" line="99"/> + <source>Rejection ring (%1 %2 %3)</source> + <translation>Anneau de réjection (%1 %2 %3)</translation> + </message> +</context> +<context> + <name>RotateOp</name> + <message> + <source>Rotation</source> + <translation type="obsolete">Rotation</translation> + </message> + <message> + <source>Rotating %1</source> + <translation type="obsolete">Rotation %1</translation> + </message> +</context> +<context> + <name>Rotation</name> + <message> + <location filename="Operations/RotateOp.cpp" line="58"/> + <source>Rotating %1</source> + <translation>Rotation %1</translation> + </message> + <message> + <location filename="Operations/RotateOp.cpp" line="67"/> + <source>Expand image</source> + <translation>Agrandir l'image</translation> + </message> + <message> + <location filename="Operations/RotateOp.cpp" line="76"/> + <source>Rotation angle : </source> + <translation>Angle de rotation : </translation> + </message> + <message> + <location filename="Operations/RotateOp.cpp" line="78"/> + <source>Fill value : </source> + <translation>Valeur de remplissage : </translation> + </message> + <message> + <location filename="Operations/RotateOp.cpp" line="150"/> + <source>rotated %1</source> + <translation>rotation-%1</translation> + </message> +</context> +<context> + <name>ScalingOp</name> + <message> + <source>Scaling</source> + <translation type="obsolete">Echantillonage</translation> + </message> + <message> + <location filename="Operations/ScalingOp.cpp" line="70"/> + <source>Nearest neighboor (standard)</source> + <translation>Standard (plus proche voisin)</translation> + </message> + <message> + <location filename="Operations/ScalingOp.cpp" line="71"/> + <source>Bi-linear</source> + <translation>Bilinéaire</translation> + </message> + <message> + <location filename="Operations/ScalingOp.cpp" line="72"/> + <source>Parabolic</source> + <translation>Parabolique</translation> + </message> + <message> + <location filename="Operations/ScalingOp.cpp" line="73"/> + <source>Spline</source> + <translation>Spline</translation> + </message> + <message> + <location filename="Operations/ScalingOp.cpp" line="74"/> + <source>Interpolation : </source> + <translation>Interpolation : </translation> + </message> + <message> + <location filename="Operations/ScalingOp.cpp" line="75"/> + <source>X scale factor : </source> + <translation>Facteur d'échelle en X : </translation> + </message> + <message> + <location filename="Operations/ScalingOp.cpp" line="76"/> + <source>Y scale factor : </source> + <translation>Facteur d'echelle en Y : </translation> + </message> + <message> + <location filename="Operations/ScalingOp.cpp" line="118"/> + <location filename="Operations/ScalingOp.cpp" line="124"/> + <source>scaled</source> + <translation>échantillonée</translation> + </message> +</context> +<context> + <name>SignalToNoiseOp</name> + <message> + <source>Signal-to-noise ratio</source> + <translation type="obsolete">Rapport signal-bruit</translation> + </message> + <message> + <source>Compare to...</source> + <translation type="obsolete">Comparer à ...</translation> + </message> + <message> + <source>+inf</source> + <translation type="obsolete">infini</translation> + </message> + <message> + <location filename="Operations/SignalToNoiseOp.cpp" line="83"/> + <source>Signal-to-noise ratio : %1</source> + <translation>Rapport signal-bruit : %1</translation> + </message> +</context> +<context> + <name>SinusSynthesisOp</name> + <message> + <location filename="Operations/SinusSynthesisOp.cpp" line="49"/> + <source>Sinus synthesis</source> + <translation>Synthèse sinus</translation> + </message> + <message> + <location filename="Operations/SinusSynthesisOp.cpp" line="55"/> + <source>Linear</source> + <translation>Linéaire</translation> + </message> + <message> + <location filename="Operations/SinusSynthesisOp.cpp" line="56"/> + <source>Circular</source> + <translation>Circulaire</translation> + </message> + <message> + <location filename="Operations/SinusSynthesisOp.cpp" line="70"/> + <source>256</source> + <translation>256</translation> + </message> + <message> + <location filename="Operations/SinusSynthesisOp.cpp" line="71"/> + <source>2 (Black and white)</source> + <translation>2 (Noir et blanc)</translation> + </message> + <message> + <location filename="Operations/SinusSynthesisOp.cpp" line="73"/> + <source>Image size (width=height) : </source> + <translation>Taille de l'image (hauteur=largeur) : </translation> + </message> + <message> + <location filename="Operations/SinusSynthesisOp.cpp" line="74"/> + <source>Signal period (pixel) : </source> + <translation>Période du signal (pixel) : </translation> + </message> + <message> + <location filename="Operations/SinusSynthesisOp.cpp" line="75"/> + <source>Orientation (°): </source> + <translation>Orientation (°): </translation> + </message> + <message> + <location filename="Operations/SinusSynthesisOp.cpp" line="77"/> + <source>Niveaux de gris : </source> + <translation>Niveaux de gris : </translation> + </message> +</context> +<context> + <name>SplitColorOp</name> + <message> + <source>Split color planes</source> + <translation type="obsolete">Séparer les plans de couleurs </translation> + </message> +</context> +<context> + <name>StructElemWindow</name> + <message> + <location filename="Widgets/StructElemWindow.cpp" line="41"/> + <source>&Open file</source> + <translation>&Ouvrir un fichier</translation> + </message> + <message> + <location filename="Widgets/StructElemWindow.cpp" line="42"/> + <source>&Save as...</source> + <translation>&Enregistrer-sous...</translation> + </message> + <message> + <location filename="Widgets/StructElemWindow.cpp" line="53"/> + <source>Basic shapes :</source> + <translation>Formes simples : </translation> + </message> + <message> + <location filename="Widgets/StructElemWindow.cpp" line="56"/> + <location filename="Widgets/StructElemWindow.cpp" line="195"/> + <source>Diamond</source> + <translation>Diamant</translation> + </message> + <message> + <location filename="Widgets/StructElemWindow.cpp" line="57"/> + <location filename="Widgets/StructElemWindow.cpp" line="175"/> + <source>Disc</source> + <translation>Disque</translation> + </message> + <message> + <location filename="Widgets/StructElemWindow.cpp" line="58"/> + <source>Empty</source> + <translation>Vide</translation> + </message> + <message> + <location filename="Widgets/StructElemWindow.cpp" line="65"/> + <source>Generate</source> + <translation>Génerer</translation> + </message> + <message> + <location filename="Widgets/StructElemWindow.cpp" line="76"/> + <source>Scale :</source> + <translation>Echelle :</translation> + </message> + <message> + <location filename="Widgets/StructElemWindow.cpp" line="247"/> + <source>Open a file</source> + <translation>Ouvrir un fichier</translation> + </message> + <message> + <location filename="Widgets/StructElemWindow.cpp" line="247"/> + <location filename="Widgets/StructElemWindow.cpp" line="268"/> + <source>Images (*.png *.bmp *.jpg *.jpeg)</source> + <translation>Images (*.png *.bmp *.jpg *.jpeg)</translation> + </message> + <message> + <location filename="Widgets/StructElemWindow.cpp" line="268"/> + <source>Save file</source> + <translation>Enregistrer sous</translation> + </message> +</context> +<context> + <name>TestOp</name> + <message> + <source>Test</source> + <translation type="obsolete">Test</translation> + </message> +</context> +<context> + <name>ThresholdDialog</name> + <message> + <location filename="Operations/ThresholdDialog.cpp" line="44"/> + <source>Threshold #1 : </source> + <translation>Seuil n°1 : </translation> + </message> + <message> + <location filename="Operations/ThresholdDialog.cpp" line="48"/> + <location filename="Operations/ThresholdDialog.cpp" line="75"/> + <source>Threshold : </source> + <translation>Seuil : </translation> + </message> + <message> + <location filename="Operations/ThresholdDialog.cpp" line="59"/> + <source>ThresholdOp</source> + <translation>Seuillage</translation> + </message> + <message> + <location filename="Operations/ThresholdDialog.cpp" line="65"/> + <source><font color=red><i>Information : The input image has been converted to grayscale.</i></font></source> + <translation><font color=red><i>Information : L'image d'entrée a été convertie en niveaux de gris.</i></font></translation> + </message> + <message> + <location filename="Operations/ThresholdDialog.cpp" line="68"/> + <source>Threshold</source> + <translation>Seuil</translation> + </message> + <message> + <location filename="Operations/ThresholdDialog.cpp" line="70"/> + <source>Double threshold</source> + <translation>Double seuil</translation> + </message> + <message> + <location filename="Operations/ThresholdDialog.cpp" line="79"/> + <source>Otsu</source> + <translation>Otsu</translation> + </message> + <message> + <location filename="Operations/ThresholdDialog.cpp" line="86"/> + <source>Threshold #2 : </source> + <translation>Seuil n°2 : </translation> + </message> + <message> + <location filename="Operations/ThresholdDialog.cpp" line="97"/> + <source>Color between thresholds :</source> + <translation>Couleur entre les seuils :</translation> + </message> + <message> + <location filename="Operations/ThresholdDialog.cpp" line="98"/> + <source>White</source> + <translation>Blanc</translation> + </message> + <message> + <location filename="Operations/ThresholdDialog.cpp" line="99"/> + <source>Black</source> + <translation>Noir</translation> + </message> + <message> + <location filename="Operations/ThresholdDialog.cpp" line="130"/> + <source>Validate</source> + <translation>Valider</translation> + </message> +</context> +<context> + <name>ThresholdOp</name> + <message> + <source>Thresholding</source> + <translation type="obsolete">Seuillage</translation> + </message> +</context> +<context> + <name>Tools</name> + <message> + <source>Combine color planes</source> + <translation type="obsolete">Combiner les plans de couleurs</translation> + </message> + <message> + <source>Discrete Fourier transform</source> + <translation type="obsolete">Transformée de Fourrier discrète</translation> + </message> + <message> + <source>Discrete Fourier reconstruction</source> + <translation type="obsolete">Reconstruction de Fourrier discrète</translation> + </message> + <message> + <source>Mean squared error</source> + <translation type="obsolete">Erreur quadratique moyenne</translation> + </message> + <message> + <source>Signal-to-noise ratio</source> + <translation type="obsolete">Rapport signal-bruit</translation> + </message> + <message> + <source>+inf</source> + <translation type="obsolete">infini</translation> + </message> + <message> + <source>Black</source> + <translation type="obsolete">Noir</translation> + </message> + <message> + <source>Alpha</source> + <translation type="obsolete">Alpha</translation> + </message> + <message> + <source>Red</source> + <translation type="obsolete">Rouge</translation> + </message> + <message> + <source>Green</source> + <translation type="obsolete">Vert</translation> + </message> + <message> + <source>Blue</source> + <translation type="obsolete">Bleu</translation> + </message> + <message> + <source>Color</source> + <translation type="obsolete">Couleur</translation> + </message> + <message> + <source>BFlit</source> + <translation type="obsolete">BFlit</translation> + </message> + <message> + <source>Colorimetry</source> + <translation type="obsolete">Colorimétrie</translation> + </message> + <message> + <source>Croissance</source> + <translation type="obsolete">Croissance</translation> + </message> + <message> + <source>DMM</source> + <translation type="obsolete">DMM</translation> + </message> + <message> + <source>Calcul d'entropie</source> + <translation type="obsolete">Calcul d'entropie</translation> + </message> + <message> + <source>Entropy of the image = %1</source> + <translation type="obsolete">Entropie de l'image = %1</translation> + </message> + <message> + <source>Histogram operations</source> + <translation type="obsolete">Opération sur-histogramme</translation> + </message> + <message> + <source>Huffman</source> + <translation type="obsolete">Huffman</translation> + </message> + <message> + <source>MICD Encoding</source> + <translation type="obsolete">Encodage MICD</translation> + </message> + <message> + <source>Add noise</source> + <translation type="obsolete">Ajouter du bruit</translation> + </message> + <message> + <source>impulse noise</source> + <translation type="obsolete">bruit impulsionnel</translation> + </message> + <message> + <source>gaussian noise</source> + <translation type="obsolete">bruit gaussien</translation> + </message> + <message> + <source>Pixel operations</source> + <translation type="obsolete">Opération sur les pixels</translation> + </message> + <message> + <source>Pseudo color</source> + <translation type="obsolete">Pseudo-couleur</translation> + </message> + <message> + <source>Quantification</source> + <translation type="obsolete">Quantification</translation> + </message> + <message> + <source>Generate random image</source> + <translation type="obsolete">Générer une image aléatoire</translation> + </message> + <message> + <source>Random image</source> + <translation type="obsolete">Image aléatoire</translation> + </message> + <message> + <source>Rejection ring</source> + <translation type="obsolete">Anneau de réjection</translation> + </message> + <message> + <source>Rejection ring (%1 %2 %3)</source> + <translation type="obsolete">Anneau de réjection (%1 %2 %3)</translation> + </message> + <message> + <source>Rotation</source> + <translation type="obsolete">Rotation</translation> + </message> + <message> + <source>Scaling</source> + <translation type="obsolete">Echantillonage</translation> + </message> + <message> + <source>Sinus synthesis</source> + <translation type="obsolete">Synthèse d'image sinus</translation> + </message> + <message> + <source>Test</source> + <translation type="obsolete">Test</translation> + </message> + <message> + <source>Thresholding</source> + <translation type="obsolete">Seuillage</translation> + </message> + <message> + <source>Translation</source> + <translation type="obsolete">Translation</translation> + </message> + <message> + <source>Zero crossing</source> + <translation type="obsolete">Passages par zéro</translation> + </message> +</context> +<context> + <name>Transforms</name> + <message> + <location filename="Operations/HadamardOp.cpp" line="57"/> + <source><b>Select the coefficients to keep : </b></source> + <translation><b>Sélectionner les coefficients à conserver : </b></translation> + </message> + <message> + <location filename="Operations/HadamardOp.cpp" line="62"/> + <source>Clear selection</source> + <translation>Effacer la sélection</translation> + </message> + <message> + <location filename="Operations/HadamardOp.cpp" line="63"/> + <source>Invert selection</source> + <translation>Inverser la sélection</translation> + </message> + <message> + <location filename="Operations/HadamardOp.cpp" line="112"/> + <source>Hadamard transform</source> + <translation>Transformée d'hadamard</translation> + </message> + <message> + <location filename="Operations/HadamardOp.cpp" line="113"/> + <source>Hadamard reconstruction</source> + <translation>Reconstruction d'hadamard</translation> + </message> + <message> + <location filename="Operations/HadamardOp.cpp" line="117"/> + <source>Haar transform</source> + <translation>Transformée de Haar</translation> + </message> + <message> + <location filename="Operations/HadamardOp.cpp" line="118"/> + <source>Haar reconstruction</source> + <translation>Reconstruction de Haar</translation> + </message> + <message> + <location filename="Operations/HadamardOp.cpp" line="122"/> + <source>cosinus transform</source> + <translation>DCT</translation> + </message> + <message> + <location filename="Operations/HadamardOp.cpp" line="123"/> + <source>cosinus reconstruction</source> + <translation>DCT inverse</translation> + </message> +</context> +<context> + <name>TranslateOp</name> + <message> + <source>Translation</source> + <translation type="obsolete">Translation</translation> + </message> + <message> + <source>Translating %1</source> + <translation type="obsolete">Translation de %1</translation> + </message> + <message> + <location filename="Operations/TranslateOp.cpp" line="34"/> + <source>Expand image</source> + <translation>Agrandir l'image</translation> + </message> + <message> + <location filename="Operations/TranslateOp.cpp" line="42"/> + <source>X offset : </source> + <translation>Décalage en X : </translation> + </message> + <message> + <location filename="Operations/TranslateOp.cpp" line="43"/> + <source>Y offset : </source> + <translation>Décalage en Y : </translation> + </message> + <message> + <location filename="Operations/TranslateOp.cpp" line="45"/> + <source>Fill value : </source> + <translation>Valeur de remplissage : </translation> + </message> + <message> + <location filename="Operations/TranslateOp.cpp" line="85"/> + <source>Translated %1:%2</source> + <translation>Translation %1:%2</translation> + </message> +</context> +<context> + <name>Translation</name> + <message> + <location filename="Operations/TranslateOp.cpp" line="24"/> + <source>Translating %1</source> + <translation>Translation de %1</translation> + </message> +</context> +<context> + <name>ZeroCrossingOp</name> + <message> + <location filename="Operations/ZeroCrossingOp.cpp" line="44"/> + <source>Zero crossing</source> + <translation>Passages par zéro</translation> + </message> + <message> + <location filename="Operations/ZeroCrossingOp.cpp" line="52"/> + <source>Threshold : </source> + <translation>Seuil : </translation> + </message> + <message> + <location filename="Operations/ZeroCrossingOp.cpp" line="110"/> + <source>contours bruts</source> + <translation>Contours bruts</translation> + </message> + <message> + <location filename="Operations/ZeroCrossingOp.cpp" line="111"/> + <source>contours nettoyes</source> + <translation>Contours nettoyés</translation> + </message> +</context> +<context> + <name>dialog</name> + <message> + <source>Parameters</source> + <translation type="obsolete">Paramètres</translation> + </message> + <message> + <source>Validate</source> + <translation type="obsolete">Valider</translation> + </message> + <message> + <source>Red : </source> + <translation type="obsolete">Rouge : </translation> + </message> + <message> + <source>Green : </source> + <translation type="obsolete">Vert : </translation> + </message> + <message> + <source>Blue : </source> + <translation type="obsolete">Bleu : </translation> + </message> + <message> + <source>Hue : </source> + <translation type="obsolete">Teinte : </translation> + </message> + <message> + <source>Saturation : </source> + <translation type="obsolete">Saturation : </translation> + </message> + <message> + <source>Value : </source> + <translation type="obsolete">Valeur : </translation> + </message> + <message> + <source>Croissance</source> + <translation type="obsolete">Croissance</translation> + </message> + <message> + <source>At origin</source> + <translation type="obsolete">A l'origine</translation> + </message> + <message> + <source>Point of lowest luminance</source> + <translation type="obsolete">Point de luminance minimale</translation> + </message> + <message> + <source>| current - mean | < threshold</source> + <translation type="obsolete">| actuel - moyenne | < seuil</translation> + </message> + <message> + <source>| current - initial | < threshold</source> + <translation type="obsolete">| actuel - initial | < seuil</translation> + </message> + <message> + <source>Threshold : </source> + <translation type="obsolete">Seuil : </translation> + </message> + <message> + <source>Initial germ : </source> + <translation type="obsolete">Germe initial : </translation> + </message> + <message> + <source>Stopping point : </source> + <translation type="obsolete">Point d'arrêt : </translation> + </message> + <message> + <source>Equalize</source> + <translation type="obsolete">Egaliser</translation> + </message> + <message> + <source>Normalize</source> + <translation type="obsolete">Normaliser</translation> + </message> + <message> + <source>Operation : </source> + <translation type="obsolete">Opération : </translation> + </message> + <message> + <source>Compare to...</source> + <translation type="obsolete">Comparer à ...</translation> + </message> + <message> + <source>Impulse noise</source> + <translation type="obsolete">Bruit impulsionnel</translation> + </message> + <message> + <source>Gaussian noise</source> + <translation type="obsolete">Bruit gaussien</translation> + </message> + <message> + <source>Parameter</source> + <translation type="obsolete">Paramètres</translation> + </message> + <message> + <source>Second operand</source> + <translation type="obsolete">Second opérande</translation> + </message> + <message> + <source>Value</source> + <translation type="obsolete">Valeur</translation> + </message> + <message> + <source>Image</source> + <translation type="obsolete">Image</translation> + </message> + <message> + <source>Explode colors</source> + <translation type="obsolete">Eclater les couleurs</translation> + </message> + <message> + <source>8-bit integer</source> + <translation type="obsolete">Entier 8 bit</translation> + </message> + <message> + <source>Floating point</source> + <translation type="obsolete">Nombre flottant</translation> + </message> + <message> + <source>Rejection ring</source> + <translation type="obsolete">Anneau de réjection</translation> + </message> + <message> + <source>Rotating %1</source> + <translation type="obsolete">Rotation %1</translation> + </message> + <message> + <source>Scaling</source> + <translation type="obsolete">Echantillonage</translation> + </message> + <message> + <source>Nearest neighboor (standard)</source> + <translation type="obsolete">Standard (plus proche voisin)</translation> + </message> + <message> + <source>Bi-linear</source> + <translation type="obsolete">Bilinéaire</translation> + </message> + <message> + <source>Parabolic</source> + <translation type="obsolete">Parabolique</translation> + </message> + <message> + <source>Spline</source> + <translation type="obsolete">Spline</translation> + </message> + <message> + <source>Interpolation : </source> + <translation type="obsolete">Interpolation : </translation> + </message> + <message> + <source>X scale factor : </source> + <translation type="obsolete">Facteur d'échelle en X : </translation> + </message> + <message> + <source>Y scale factor : </source> + <translation type="obsolete">Facteur d'echelle en Y : </translation> + </message> + <message> + <source>Linear</source> + <translation type="obsolete">Linéaire</translation> + </message> + <message> + <source>Circular</source> + <translation type="obsolete">Circulaire</translation> + </message> + <message> + <source>256</source> + <translation type="obsolete">256</translation> + </message> + <message> + <source>2 (Black and white)</source> + <translation type="obsolete">2 (Noir et blanc)</translation> + </message> + <message> + <source>Image size (width=height) : </source> + <translation type="obsolete">Taille de l'image (hauteur=largeur) : </translation> + </message> + <message> + <source>Signal period (pixel) : </source> + <translation type="obsolete">Période du signal (pixel) : </translation> + </message> + <message> + <source>Orientation (°): </source> + <translation type="obsolete">Orientation (°): </translation> + </message> + <message> + <source>Niveaux de gris : </source> + <translation type="obsolete">Niveaux de gris : </translation> + </message> + <message> + <source>Translating %1</source> + <translation type="obsolete">Translation de %1</translation> + </message> +</context> +<context> + <name>filtrme::FilterChoice</name> + <message> + <location filename="Widgets/FilterChoice.cpp" line="74"/> + <source>FilterChoice</source> + <translation>Choix du filtre</translation> + </message> + <message> + <location filename="Widgets/FilterChoice.cpp" line="82"/> + <source>Filter configuration</source> + <translation>Configuration du filtre</translation> + </message> + <message> + <location filename="Widgets/FilterChoice.cpp" line="86"/> + <source>Filter:</source> + <translation>Filtre :</translation> + </message> + <message> + <location filename="Widgets/FilterChoice.cpp" line="95"/> + <source>Edge policy: </source> + <translation>Politique pour les bords : </translation> + </message> + <message> + <location filename="Widgets/FilterChoice.cpp" line="97"/> + <source>Black</source> + <translation>Noir</translation> + </message> + <message> + <location filename="Widgets/FilterChoice.cpp" line="97"/> + <source>Mirror</source> + <translation>Mirroir</translation> + </message> + <message> + <location filename="Widgets/FilterChoice.cpp" line="97"/> + <source>Nearest</source> + <translation>Plus proche voisin</translation> + </message> + <message> + <location filename="Widgets/FilterChoice.cpp" line="97"/> + <source>Spherical</source> + <translation>Sphérique</translation> + </message> + <message> + <source>Number of pixels:</source> + <translation type="obsolete">Nombre de pixels :</translation> + </message> + <message> + <location filename="Widgets/FilterChoice.cpp" line="103"/> + <source>Filter size:</source> + <translation>Taille du filtre : </translation> + </message> + <message> + <location filename="Widgets/FilterChoice.cpp" line="109"/> + <source>Standard deviation : </source> + <translation>Equart type : </translation> + </message> + <message> + <location filename="Widgets/FilterChoice.cpp" line="118"/> + <source>Resulting image type</source> + <translation>Type de l'image résultat</translation> + </message> + <message> + <location filename="Widgets/FilterChoice.cpp" line="119"/> + <source>Standard</source> + <translation>Standard</translation> + </message> + <message> + <location filename="Widgets/FilterChoice.cpp" line="120"/> + <source>Floating point</source> + <translation>Nombre flottant</translation> + </message> + <message> + <location filename="Widgets/FilterChoice.cpp" line="163"/> + <source>Apply filter</source> + <translation>Appliquer le filtre</translation> + </message> + <message> + <location filename="Widgets/FilterChoice.cpp" line="164"/> + <source>Delete filter</source> + <translation>Supprimer le filtre</translation> + </message> + <message> + <location filename="Widgets/FilterChoice.cpp" line="194"/> + <source>Uniform</source> + <translation>Uniforme</translation> + </message> + <message> + <location filename="Widgets/FilterChoice.cpp" line="194"/> + <source>Gaussian</source> + <translation>Gaussien</translation> + </message> + <message> + <location filename="Widgets/FilterChoice.cpp" line="194"/> + <source>Prewitt</source> + <translation>Prewitt</translation> + </message> + <message> + <location filename="Widgets/FilterChoice.cpp" line="194"/> + <source>Roberts</source> + <translation>Roberts</translation> + </message> + <message> + <location filename="Widgets/FilterChoice.cpp" line="194"/> + <source>Sobel</source> + <translation>Sobel</translation> + </message> + <message> + <location filename="Widgets/FilterChoice.cpp" line="194"/> + <source>SquareLaplacien</source> + <translation>SquareLaplacien</translation> + </message> + <message> + <location filename="Widgets/FilterChoice.cpp" line="339"/> + <source>Warning!</source> + <translation>Attention !</translation> + </message> + <message> + <location filename="Widgets/FilterChoice.cpp" line="339"/> + <source>This filter will be permanently deleted ?</source> + <translation>Ce filtre sera effacé définitivement !</translation> + </message> + <message> + <location filename="Widgets/FilterChoice.cpp" line="340"/> + <source>Do you want to continue?</source> + <translation>Voulez-vous continuer ?</translation> + </message> + <message> + <source>Number of Pixels:</source> + <translation type="obsolete">Nombre de pixels :</translation> + </message> + <message> + <source>Coefficient:</source> + <translation type="obsolete">Coefficient :</translation> + </message> +</context> +<context> + <name>filtrme::FilterEditor</name> + <message> + <location filename="Widgets/FilterEditor.cpp" line="69"/> + <source>Name:</source> + <translation>Nom :</translation> + </message> + <message> + <location filename="Widgets/FilterEditor.cpp" line="72"/> + <source>Number of filters:</source> + <translation>Nombre de filtres :</translation> + </message> + <message> + <location filename="Widgets/FilterEditor.cpp" line="105"/> + <source>FilterEditor</source> + <translation>Editeur de filtre</translation> + </message> + <message> + <location filename="Widgets/FilterEditor.cpp" line="117"/> + <location filename="Widgets/FilterEditor.cpp" line="240"/> + <source>Error!</source> + <translation>Erreur !</translation> + </message> + <message> + <location filename="Widgets/FilterEditor.cpp" line="117"/> + <source>Your filter has to have a name to be saved.</source> + <translation>Votre filtre doit avoir un nom pour être sauvegardé.</translation> + </message> + <message> + <location filename="Widgets/FilterEditor.cpp" line="166"/> + <location filename="Widgets/FilterEditor.cpp" line="254"/> + <source>Warning!</source> + <translation>Attention !</translation> + </message> + <message> + <location filename="Widgets/FilterEditor.cpp" line="166"/> + <source>This filter name is already use.</source> + <translation>Ce nom de filtre est déjà utilisé.</translation> + </message> + <message> + <location filename="Widgets/FilterEditor.cpp" line="167"/> + <source>Do you want to replace it?</source> + <translation>Voulez-vous le remplacer ?</translation> + </message> + <message> + <location filename="Widgets/FilterEditor.cpp" line="240"/> + <source>Every square have to be completed by int value.</source> + <translation>Chaque case doit être complétée par une valeur.</translation> + </message> + <message> + <location filename="Widgets/FilterEditor.cpp" line="241"/> + <source>Filter %1 isn't ok.</source> + <translation>Le filtre n°%1 n'est pas correct.</translation> + </message> + <message> + <location filename="Widgets/FilterEditor.cpp" line="254"/> + <source>Unsaved changes will be lost.</source> + <translation>Les changements non sauvegardés seront perdus.</translation> + </message> + <message> + <location filename="Widgets/FilterEditor.cpp" line="255"/> + <source>Do you want to continue?</source> + <translation>Voulez-vous continuer ?</translation> + </message> +</context> +<context> + <name>filtrme::FilterEditorItem</name> + <message> + <location filename="Widgets/FilterEditorItem.cpp" line="80"/> + <source>Width:</source> + <translation>Largeur :</translation> + </message> + <message> + <location filename="Widgets/FilterEditorItem.cpp" line="83"/> + <source>Height:</source> + <translation>Hauteur :</translation> + </message> +</context> +<context> + <name>filtrme::FilteringService</name> + <message> + <source>Filtering</source> + <translation type="obsolete">Filtrage</translation> + </message> + <message> + <location filename="Services/FilteringService.cpp" line="40"/> + <source>&Apply filter</source> + <translation>&Appliquer un filtre</translation> + </message> + <message> + <location filename="Services/FilteringService.cpp" line="42"/> + <source>&Edit filters</source> + <translation>&Editer un filtre</translation> + </message> +</context> +<context> + <name>genericinterface::GenericInterface</name> + <message> + <source>Filtering</source> + <translation type="obsolete">Filtrage</translation> + </message> +</context> +<context> + <name>genericinterface::MorphoMatService</name> + <message> + <source>&Mathematical morphology</source> + <translation type="obsolete">&Morphologie mathématique</translation> + </message> + <message> + <location filename="Services/MorphoMatService.cpp" line="58"/> + <source>&Erosion</source> + <translation>&Erosion</translation> + </message> + <message> + <location filename="Services/MorphoMatService.cpp" line="59"/> + <source>&Dilatation</source> + <translation>&Dilatation</translation> + </message> + <message> + <location filename="Services/MorphoMatService.cpp" line="60"/> + <source>&Opening</source> + <translation>&Ouverture</translation> + </message> + <message> + <location filename="Services/MorphoMatService.cpp" line="61"/> + <source>&Closing</source> + <translation>&Fermeture</translation> + </message> + <message> + <location filename="Services/MorphoMatService.cpp" line="62"/> + <source>&Gradient</source> + <translation>&Gradient</translation> + </message> + <message> + <location filename="Services/MorphoMatService.cpp" line="63"/> + <source>&White top hat</source> + <translation>&White top hat</translation> + </message> + <message> + <location filename="Services/MorphoMatService.cpp" line="64"/> + <source>&Black top hat</source> + <translation>&Black top hat</translation> + </message> + <message> + <location filename="Services/MorphoMatService.cpp" line="66"/> + <source>&Structuring element</source> + <translation>Elément &structurant</translation> + </message> +</context> +<context> + <name>gi</name> + <message> + <source>Filtering</source> + <translation type="obsolete">Filtrage</translation> + </message> +</context> +</TS> diff --git a/app/img/micd.png b/app/img/micd.png new file mode 100644 index 0000000000000000000000000000000000000000..412a7888473cb32d9259d94e3b7125ba6874d9e6 Binary files /dev/null and b/app/img/micd.png differ diff --git a/app/main.cpp b/app/main.cpp index 339925ace6947a554342116f631cd193ff4404c2..38015a41ba2b5f3108e276df98bb62682e58e967 100644 --- a/app/main.cpp +++ b/app/main.cpp @@ -30,7 +30,6 @@ #include "Services/PluginManager.h" #include "Services/EIImageService.h" -#include "Operations/TestOp.h" #include "Operations/PointOp.h" #include "Operations/ThresholdOp.h" #include "Operations/TranslateOp.h" @@ -59,6 +58,15 @@ #include "Operations/HuffmanOp.h" #include "Operations/RejectionRingOp.h" #include "Operations/MICDEncodingOp.h" +#include "Operations/HadamardOp.h" +#include "Operations/DCTOp.h" +#include "Operations/HoughOp.h" +#include "Operations/InverseHoughOp.h" +#include "Operations/PyramidOp.h" +#include "Operations/InversePyramidOp.h" +#include "Operations/ClassAnalysisOp.h" +#include "Operations/ClassResultOp.h" +#include "Operations/SeparatorOp.h" #include "Services/MorphoMatService.h" @@ -75,19 +83,30 @@ int main(int argc, char** argv) Log::configure(true, false, 0); + QString lang = QString("en_US"); + if(argc > 1) { + lang = QString(argv[1]); + } + lang = "fr_FR"; QTranslator qtTranslator; - QString tr = "qt_fr_FR"; - qtTranslator.load(tr, QLibraryInfo::location(QLibraryInfo::TranslationsPath)); - cout << tr.toStdString(); + QString tr = "qt_"; + tr += lang; + if(!qtTranslator.load(tr, QLibraryInfo::location(QLibraryInfo::TranslationsPath))) { + cout << "Error while loading " << tr.toStdString() << endl; + } app.installTranslator(&qtTranslator); QTranslator giTranslator; - giTranslator.load("genericinterface_fr"); + if(!giTranslator.load(QString("genericinterface_") + lang.mid(0, 2))) { + cout << "Error while loading genericinterface_en.qm" << endl; + } app.installTranslator(&giTranslator); QTranslator eiiTranslator; - eiiTranslator.load("eiimage_fr"); + if(!eiiTranslator.load(QString("eiimage_") + lang.mid(0, 2))) { + cout << "Error while loading eiimage_en.qm" << endl; + } app.installTranslator(&eiiTranslator); GenericInterface gi("eiimage", Qt::LeftDockWidgetArea); @@ -95,7 +114,6 @@ int main(int argc, char** argv) PluginManager* pluginManager = new PluginManager(&gi); EIImageService* eiimageService = new EIImageService(&gi); - gi.addService(pluginManager); // gi.addService(eiimageService); gi.changeService(GenericInterface::WINDOW_SERVICE, eiimageService); // gi.addService(GenericInterface::WINDOW_SERVICE, eiimageService); @@ -103,43 +121,72 @@ int main(int argc, char** argv) QObject::connect(pluginManager, SIGNAL(addPlugin(OpSet*)), eiimageService, SLOT(addOpSet(OpSet*))); QObject::connect(pluginManager, SIGNAL(removePlugin(OpSet*)), eiimageService, SLOT(removeOpSet(OpSet*))); - - BuiltinOpSet* opSet = new BuiltinOpSet("Operations"); - opSet->addOperation(new QuantificationOp()); - opSet->addOperation(new PointOp()); - opSet->addOperation(new ThresholdOp()); - opSet->addOperation(new TranslateOp()); - opSet->addOperation(new RotateOp()); - opSet->addOperation(new FlipOp(FlipOp::Horizontal)); - opSet->addOperation(new FlipOp(FlipOp::Vertical)); - opSet->addOperation(new CenterOp()); - opSet->addOperation(new SplitColorOp()); - opSet->addOperation(new CombineColorOp()); - opSet->addOperation(new SignalToNoiseOp()); - opSet->addOperation(new MeanSquaredErrorOp()); - opSet->addOperation(new FFTOp()); - opSet->addOperation(new IFFTOp()); - opSet->addOperation(new RandomImgOp()); - opSet->addOperation(new NoiseOp()); - opSet->addOperation(new BFlitOp()); - opSet->addOperation(new DMMOp()); - opSet->addOperation(new TestOp()); - opSet->addOperation(new PseudoColorOp()); - opSet->addOperation(new CroissanceOp()); - opSet->addOperation(new ZeroCrossingOp()); - opSet->addOperation(new HistogramOp()); - opSet->addOperation(new ColorimetryOp()); - opSet->addOperation(new SinusSynthesisOp()); - opSet->addOperation(new ScalingOp()); - opSet->addOperation(new EntropyOp()); - opSet->addOperation(new HuffmanOp()); - opSet->addOperation(new RejectionRingOp()); - opSet->addOperation(new MICDEncodingOp()); - - eiimageService->addOpSet(opSet); - + BuiltinOpSet* image = new BuiltinOpSet(qApp->translate("", "&Image").toStdString()); + image->addOperation(new PointOp()); + image->addOperation(new TranslateOp()); + image->addOperation(new RotateOp()); + image->addOperation(new CenterOp()); + image->addOperation(new FlipOp(FlipOp::Horizontal)); + image->addOperation(new FlipOp(FlipOp::Vertical)); + image->addOperation(new SeparatorOp()); + image->addOperation(new SplitColorOp()); + image->addOperation(new CombineColorOp()); + image->addOperation(new ScalingOp()); + image->addOperation(new QuantificationOp()); + image->addOperation(new ThresholdOp()); + image->addOperation(new HistogramOp()); + + BuiltinOpSet* tools = new BuiltinOpSet(qApp->translate("", "&Tools").toStdString()); + + tools->addOperation(new SignalToNoiseOp()); + tools->addOperation(new MeanSquaredErrorOp()); + tools->addOperation(new EntropyOp()); + tools->addOperation(new NoiseOp()); + tools->addOperation(new SeparatorOp()); + tools->addOperation(new RandomImgOp()); + tools->addOperation(new ColorimetryOp()); + tools->addOperation(new RejectionRingOp()); + tools->addOperation(new SinusSynthesisOp()); + + BuiltinOpSet* encode = new BuiltinOpSet(qApp->translate("", "&Encoding").toStdString()); + encode->addOperation(new HuffmanOp()); + encode->addOperation(new MICDEncodingOp()); + + BuiltinOpSet* morpho = new BuiltinOpSet("&Morpho. math."); + morpho->addOperation(new DMMOp()); + morpho->addOperation(new SeparatorOp()); + + BuiltinOpSet* transfo = new BuiltinOpSet(qApp->translate("", "Transforms").toStdString()); + transfo->addOperation(new FFTOp()); + transfo->addOperation(new IFFTOp()); + transfo->addOperation(new HadamardOp()); + transfo->addOperation(new DCTOp()); + transfo->addOperation(new HoughOp()); + transfo->addOperation(new InverseHoughOp()); + + BuiltinOpSet* analyse = new BuiltinOpSet(qApp->translate("", "Analysis").toStdString()); + analyse->addOperation(new CroissanceOp()); + analyse->addOperation(new ZeroCrossingOp()); + analyse->addOperation(new PyramidOp()); + analyse->addOperation(new InversePyramidOp()); + analyse->addOperation(new ClassAnalysisOp()); + analyse->addOperation(new ClassResultOp()); + analyse->addOperation(new PseudoColorOp()); + + BuiltinOpSet* filter = new BuiltinOpSet(qApp->translate("", "Filtering").toStdString()); + filter->addOperation(new BFlitOp()); + + eiimageService->addOpSet(image); + eiimageService->addOpSet(encode); + eiimageService->addOpSet(morpho); + eiimageService->addOpSet(analyse); + eiimageService->addOpSet(transfo); gi.addService(new MorphoMatService); gi.addService(new filtrme::FilteringService); + eiimageService->addOpSet(filter); + eiimageService->addOpSet(tools); + + gi.addService(pluginManager); gi.run(); diff --git a/core/BuiltinOpSet.h b/core/BuiltinOpSet.h index 00147e69ff76c1293fb2cc8f6438a849a30701bc..03be2a2fe2b4650d1ad4ea4590331cec5cce0c60 100644 --- a/core/BuiltinOpSet.h +++ b/core/BuiltinOpSet.h @@ -25,14 +25,30 @@ #include "OpSet.h" +/** + * @brief A BuiltinOpSet is an implementation of OpSet containing GenericOperation + * + * This class is used inside the eiimage application to organize the built-in operations. + * + */ class BuiltinOpSet : public OpSet { public: +/** + * @brief Constructor + * + * @param name Name of the operation set, as it should be displayed to the user + */ BuiltinOpSet(std::string name); std::vector<GenericOperation*> getOperations(); - void addOperation(GenericOperation*); + /** + * @brief Add a GenericOperation to this operation set + * + * @param The operation to add. + */ + void addOperation(GenericOperation* op); private: - std::vector<GenericOperation*> _operations; + std::vector<GenericOperation*> _operations; /**< List of the operations stored in this OpSet */ }; #endif //!EIIMAGE_BUILTINOPSET_H diff --git a/core/Doxyfile b/core/Doxyfile new file mode 100644 index 0000000000000000000000000000000000000000..6745966a49b02ac96462abc936f7886825643cc4 --- /dev/null +++ b/core/Doxyfile @@ -0,0 +1,1772 @@ +# Doxyfile 1.7.6.1 + +# This file describes the settings to be used by the documentation system +# doxygen (www.doxygen.org) for a project +# +# All text after a hash (#) is considered a comment and will be ignored +# The format is: +# TAG = value [value, ...] +# For lists items can also be appended using: +# TAG += value [value, ...] +# Values that contain spaces should be placed between quotes (" ") + +#--------------------------------------------------------------------------- +# Project related configuration options +#--------------------------------------------------------------------------- + +# This tag specifies the encoding used for all characters in the config file +# that follow. The default is UTF-8 which is also the encoding used for all +# text before the first occurrence of this tag. Doxygen uses libiconv (or the +# iconv built into libc) for the transcoding. See +# http://www.gnu.org/software/libiconv for the list of possible encodings. + +DOXYFILE_ENCODING = UTF-8 + +# The PROJECT_NAME tag is a single word (or sequence of words) that should +# identify the project. Note that if you do not use Doxywizard you need +# to put quotes around the project name if it contains spaces. + +PROJECT_NAME = "eiimage core" + +# The PROJECT_NUMBER tag can be used to enter a project or revision number. +# This could be handy for archiving the generated documentation or +# if some version control system is used. + +PROJECT_NUMBER = 1 + +# Using the PROJECT_BRIEF tag one can provide an optional one line description +# for a project that appears at the top of each page and should give viewer +# a quick idea about the purpose of the project. Keep the description short. + +PROJECT_BRIEF = "eiimage's core library" + +# With the PROJECT_LOGO tag one can specify an logo or icon that is +# included in the documentation. The maximum height of the logo should not +# exceed 55 pixels and the maximum width should not exceed 200 pixels. +# Doxygen will copy the logo to the output directory. + +PROJECT_LOGO = + +# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) +# base path where the generated documentation will be put. +# If a relative path is entered, it will be relative to the location +# where doxygen was started. If left blank the current directory will be used. + +OUTPUT_DIRECTORY = + +# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create +# 4096 sub-directories (in 2 levels) under the output directory of each output +# format and will distribute the generated files over these directories. +# Enabling this option can be useful when feeding doxygen a huge amount of +# source files, where putting all generated files in the same directory would +# otherwise cause performance problems for the file system. + +CREATE_SUBDIRS = NO + +# The OUTPUT_LANGUAGE tag is used to specify the language in which all +# documentation generated by doxygen is written. Doxygen will use this +# information to generate all constant output in the proper language. +# The default language is English, other supported languages are: +# Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional, +# Croatian, Czech, Danish, Dutch, Esperanto, Farsi, Finnish, French, German, +# Greek, Hungarian, Italian, Japanese, Japanese-en (Japanese with English +# messages), Korean, Korean-en, Lithuanian, Norwegian, Macedonian, Persian, +# Polish, Portuguese, Romanian, Russian, Serbian, Serbian-Cyrillic, Slovak, +# Slovene, Spanish, Swedish, Ukrainian, and Vietnamese. + +OUTPUT_LANGUAGE = English + +# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will +# include brief member descriptions after the members that are listed in +# the file and class documentation (similar to JavaDoc). +# Set to NO to disable this. + +BRIEF_MEMBER_DESC = YES + +# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend +# the brief description of a member or function before the detailed description. +# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the +# brief descriptions will be completely suppressed. + +REPEAT_BRIEF = YES + +# This tag implements a quasi-intelligent brief description abbreviator +# that is used to form the text in various listings. Each string +# in this list, if found as the leading text of the brief description, will be +# stripped from the text and the result after processing the whole list, is +# used as the annotated text. Otherwise, the brief description is used as-is. +# If left blank, the following values are used ("$name" is automatically +# replaced with the name of the entity): "The $name class" "The $name widget" +# "The $name file" "is" "provides" "specifies" "contains" +# "represents" "a" "an" "the" + +ABBREVIATE_BRIEF = + +# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then +# Doxygen will generate a detailed section even if there is only a brief +# description. + +ALWAYS_DETAILED_SEC = NO + +# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all +# inherited members of a class in the documentation of that class as if those +# members were ordinary class members. Constructors, destructors and assignment +# operators of the base classes will not be shown. + +INLINE_INHERITED_MEMB = NO + +# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full +# path before files name in the file list and in the header files. If set +# to NO the shortest path that makes the file name unique will be used. + +FULL_PATH_NAMES = YES + +# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag +# can be used to strip a user-defined part of the path. Stripping is +# only done if one of the specified strings matches the left-hand part of +# the path. The tag can be used to show relative paths in the file list. +# If left blank the directory from which doxygen is run is used as the +# path to strip. + +STRIP_FROM_PATH = + +# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of +# the path mentioned in the documentation of a class, which tells +# the reader which header file to include in order to use a class. +# If left blank only the name of the header file containing the class +# definition is used. Otherwise one should specify the include paths that +# are normally passed to the compiler using the -I flag. + +STRIP_FROM_INC_PATH = + +# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter +# (but less readable) file names. This can be useful if your file system +# doesn't support long names like on DOS, Mac, or CD-ROM. + +SHORT_NAMES = NO + +# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen +# will interpret the first line (until the first dot) of a JavaDoc-style +# comment as the brief description. If set to NO, the JavaDoc +# comments will behave just like regular Qt-style comments +# (thus requiring an explicit @brief command for a brief description.) + +JAVADOC_AUTOBRIEF = NO + +# If the QT_AUTOBRIEF tag is set to YES then Doxygen will +# interpret the first line (until the first dot) of a Qt-style +# comment as the brief description. If set to NO, the comments +# will behave just like regular Qt-style comments (thus requiring +# an explicit \brief command for a brief description.) + +QT_AUTOBRIEF = NO + +# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen +# treat a multi-line C++ special comment block (i.e. a block of //! or /// +# comments) as a brief description. This used to be the default behaviour. +# The new default is to treat a multi-line C++ comment block as a detailed +# description. Set this tag to YES if you prefer the old behaviour instead. + +MULTILINE_CPP_IS_BRIEF = NO + +# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented +# member inherits the documentation from any documented member that it +# re-implements. + +INHERIT_DOCS = YES + +# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce +# a new page for each member. If set to NO, the documentation of a member will +# be part of the file/class/namespace that contains it. + +SEPARATE_MEMBER_PAGES = NO + +# The TAB_SIZE tag can be used to set the number of spaces in a tab. +# Doxygen uses this value to replace tabs by spaces in code fragments. + +TAB_SIZE = 8 + +# This tag can be used to specify a number of aliases that acts +# as commands in the documentation. An alias has the form "name=value". +# For example adding "sideeffect=\par Side Effects:\n" will allow you to +# put the command \sideeffect (or @sideeffect) in the documentation, which +# will result in a user-defined paragraph with heading "Side Effects:". +# You can put \n's in the value part of an alias to insert newlines. + +ALIASES = + +# This tag can be used to specify a number of word-keyword mappings (TCL only). +# A mapping has the form "name=value". For example adding +# "class=itcl::class" will allow you to use the command class in the +# itcl::class meaning. + +TCL_SUBST = + +# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C +# sources only. Doxygen will then generate output that is more tailored for C. +# For instance, some of the names that are used will be different. The list +# of all members will be omitted, etc. + +OPTIMIZE_OUTPUT_FOR_C = NO + +# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java +# sources only. Doxygen will then generate output that is more tailored for +# Java. For instance, namespaces will be presented as packages, qualified +# scopes will look different, etc. + +OPTIMIZE_OUTPUT_JAVA = NO + +# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran +# sources only. Doxygen will then generate output that is more tailored for +# Fortran. + +OPTIMIZE_FOR_FORTRAN = NO + +# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL +# sources. Doxygen will then generate output that is tailored for +# VHDL. + +OPTIMIZE_OUTPUT_VHDL = NO + +# Doxygen selects the parser to use depending on the extension of the files it +# parses. With this tag you can assign which parser to use for a given extension. +# Doxygen has a built-in mapping, but you can override or extend it using this +# tag. The format is ext=language, where ext is a file extension, and language +# is one of the parsers supported by doxygen: IDL, Java, Javascript, CSharp, C, +# C++, D, PHP, Objective-C, Python, Fortran, VHDL, C, C++. For instance to make +# doxygen treat .inc files as Fortran files (default is PHP), and .f files as C +# (default is Fortran), use: inc=Fortran f=C. Note that for custom extensions +# you also need to set FILE_PATTERNS otherwise the files are not read by doxygen. + +EXTENSION_MAPPING = + +# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want +# to include (a tag file for) the STL sources as input, then you should +# set this tag to YES in order to let doxygen match functions declarations and +# definitions whose arguments contain STL classes (e.g. func(std::string); v.s. +# func(std::string) {}). This also makes the inheritance and collaboration +# diagrams that involve STL classes more complete and accurate. + +BUILTIN_STL_SUPPORT = NO + +# If you use Microsoft's C++/CLI language, you should set this option to YES to +# enable parsing support. + +CPP_CLI_SUPPORT = NO + +# Set the SIP_SUPPORT tag to YES if your project consists of sip sources only. +# Doxygen will parse them like normal C++ but will assume all classes use public +# instead of private inheritance when no explicit protection keyword is present. + +SIP_SUPPORT = NO + +# For Microsoft's IDL there are propget and propput attributes to indicate getter +# and setter methods for a property. Setting this option to YES (the default) +# will make doxygen replace the get and set methods by a property in the +# documentation. This will only work if the methods are indeed getting or +# setting a simple type. If this is not the case, or you want to show the +# methods anyway, you should set this option to NO. + +IDL_PROPERTY_SUPPORT = YES + +# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC +# tag is set to YES, then doxygen will reuse the documentation of the first +# member in the group (if any) for the other members of the group. By default +# all members of a group must be documented explicitly. + +DISTRIBUTE_GROUP_DOC = NO + +# Set the SUBGROUPING tag to YES (the default) to allow class member groups of +# the same type (for instance a group of public functions) to be put as a +# subgroup of that type (e.g. under the Public Functions section). Set it to +# NO to prevent subgrouping. Alternatively, this can be done per class using +# the \nosubgrouping command. + +SUBGROUPING = YES + +# When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and +# unions are shown inside the group in which they are included (e.g. using +# @ingroup) instead of on a separate page (for HTML and Man pages) or +# section (for LaTeX and RTF). + +INLINE_GROUPED_CLASSES = NO + +# When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and +# unions with only public data fields will be shown inline in the documentation +# of the scope in which they are defined (i.e. file, namespace, or group +# documentation), provided this scope is documented. If set to NO (the default), +# structs, classes, and unions are shown on a separate page (for HTML and Man +# pages) or section (for LaTeX and RTF). + +INLINE_SIMPLE_STRUCTS = NO + +# When TYPEDEF_HIDES_STRUCT is enabled, a typedef of a struct, union, or enum +# is documented as struct, union, or enum with the name of the typedef. So +# typedef struct TypeS {} TypeT, will appear in the documentation as a struct +# with name TypeT. When disabled the typedef will appear as a member of a file, +# namespace, or class. And the struct will be named TypeS. This can typically +# be useful for C code in case the coding convention dictates that all compound +# types are typedef'ed and only the typedef is referenced, never the tag name. + +TYPEDEF_HIDES_STRUCT = NO + +# The SYMBOL_CACHE_SIZE determines the size of the internal cache use to +# determine which symbols to keep in memory and which to flush to disk. +# When the cache is full, less often used symbols will be written to disk. +# For small to medium size projects (<1000 input files) the default value is +# probably good enough. For larger projects a too small cache size can cause +# doxygen to be busy swapping symbols to and from disk most of the time +# causing a significant performance penalty. +# If the system has enough physical memory increasing the cache will improve the +# performance by keeping more symbols in memory. Note that the value works on +# a logarithmic scale so increasing the size by one will roughly double the +# memory usage. The cache size is given by this formula: +# 2^(16+SYMBOL_CACHE_SIZE). The valid range is 0..9, the default is 0, +# corresponding to a cache size of 2^16 = 65536 symbols. + +SYMBOL_CACHE_SIZE = 0 + +# Similar to the SYMBOL_CACHE_SIZE the size of the symbol lookup cache can be +# set using LOOKUP_CACHE_SIZE. This cache is used to resolve symbols given +# their name and scope. Since this can be an expensive process and often the +# same symbol appear multiple times in the code, doxygen keeps a cache of +# pre-resolved symbols. If the cache is too small doxygen will become slower. +# If the cache is too large, memory is wasted. The cache size is given by this +# formula: 2^(16+LOOKUP_CACHE_SIZE). The valid range is 0..9, the default is 0, +# corresponding to a cache size of 2^16 = 65536 symbols. + +LOOKUP_CACHE_SIZE = 0 + +#--------------------------------------------------------------------------- +# Build related configuration options +#--------------------------------------------------------------------------- + +# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in +# documentation are documented, even if no documentation was available. +# Private class members and static file members will be hidden unless +# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES + +EXTRACT_ALL = YES + +# If the EXTRACT_PRIVATE tag is set to YES all private members of a class +# will be included in the documentation. + +EXTRACT_PRIVATE = NO + +# If the EXTRACT_STATIC tag is set to YES all static members of a file +# will be included in the documentation. + +EXTRACT_STATIC = NO + +# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) +# defined locally in source files will be included in the documentation. +# If set to NO only classes defined in header files are included. + +EXTRACT_LOCAL_CLASSES = YES + +# This flag is only useful for Objective-C code. When set to YES local +# methods, which are defined in the implementation section but not in +# the interface are included in the documentation. +# If set to NO (the default) only methods in the interface are included. + +EXTRACT_LOCAL_METHODS = NO + +# If this flag is set to YES, the members of anonymous namespaces will be +# extracted and appear in the documentation as a namespace called +# 'anonymous_namespace{file}', where file will be replaced with the base +# name of the file that contains the anonymous namespace. By default +# anonymous namespaces are hidden. + +EXTRACT_ANON_NSPACES = NO + +# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all +# undocumented members of documented classes, files or namespaces. +# If set to NO (the default) these members will be included in the +# various overviews, but no documentation section is generated. +# This option has no effect if EXTRACT_ALL is enabled. + +HIDE_UNDOC_MEMBERS = NO + +# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all +# undocumented classes that are normally visible in the class hierarchy. +# If set to NO (the default) these classes will be included in the various +# overviews. This option has no effect if EXTRACT_ALL is enabled. + +HIDE_UNDOC_CLASSES = NO + +# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all +# friend (class|struct|union) declarations. +# If set to NO (the default) these declarations will be included in the +# documentation. + +HIDE_FRIEND_COMPOUNDS = NO + +# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any +# documentation blocks found inside the body of a function. +# If set to NO (the default) these blocks will be appended to the +# function's detailed documentation block. + +HIDE_IN_BODY_DOCS = NO + +# The INTERNAL_DOCS tag determines if documentation +# that is typed after a \internal command is included. If the tag is set +# to NO (the default) then the documentation will be excluded. +# Set it to YES to include the internal documentation. + +INTERNAL_DOCS = NO + +# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate +# file names in lower-case letters. If set to YES upper-case letters are also +# allowed. This is useful if you have classes or files whose names only differ +# in case and if your file system supports case sensitive file names. Windows +# and Mac users are advised to set this option to NO. + +CASE_SENSE_NAMES = YES + +# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen +# will show members with their full class and namespace scopes in the +# documentation. If set to YES the scope will be hidden. + +HIDE_SCOPE_NAMES = NO + +# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen +# will put a list of the files that are included by a file in the documentation +# of that file. + +SHOW_INCLUDE_FILES = YES + +# If the FORCE_LOCAL_INCLUDES tag is set to YES then Doxygen +# will list include files with double quotes in the documentation +# rather than with sharp brackets. + +FORCE_LOCAL_INCLUDES = NO + +# If the INLINE_INFO tag is set to YES (the default) then a tag [inline] +# is inserted in the documentation for inline members. + +INLINE_INFO = YES + +# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen +# will sort the (detailed) documentation of file and class members +# alphabetically by member name. If set to NO the members will appear in +# declaration order. + +SORT_MEMBER_DOCS = YES + +# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the +# brief documentation of file, namespace and class members alphabetically +# by member name. If set to NO (the default) the members will appear in +# declaration order. + +SORT_BRIEF_DOCS = NO + +# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen +# will sort the (brief and detailed) documentation of class members so that +# constructors and destructors are listed first. If set to NO (the default) +# the constructors will appear in the respective orders defined by +# SORT_MEMBER_DOCS and SORT_BRIEF_DOCS. +# This tag will be ignored for brief docs if SORT_BRIEF_DOCS is set to NO +# and ignored for detailed docs if SORT_MEMBER_DOCS is set to NO. + +SORT_MEMBERS_CTORS_1ST = NO + +# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the +# hierarchy of group names into alphabetical order. If set to NO (the default) +# the group names will appear in their defined order. + +SORT_GROUP_NAMES = NO + +# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be +# sorted by fully-qualified names, including namespaces. If set to +# NO (the default), the class list will be sorted only by class name, +# not including the namespace part. +# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. +# Note: This option applies only to the class list, not to the +# alphabetical list. + +SORT_BY_SCOPE_NAME = NO + +# If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to +# do proper type resolution of all parameters of a function it will reject a +# match between the prototype and the implementation of a member function even +# if there is only one candidate or it is obvious which candidate to choose +# by doing a simple string match. By disabling STRICT_PROTO_MATCHING doxygen +# will still accept a match between prototype and implementation in such cases. + +STRICT_PROTO_MATCHING = NO + +# The GENERATE_TODOLIST tag can be used to enable (YES) or +# disable (NO) the todo list. This list is created by putting \todo +# commands in the documentation. + +GENERATE_TODOLIST = YES + +# The GENERATE_TESTLIST tag can be used to enable (YES) or +# disable (NO) the test list. This list is created by putting \test +# commands in the documentation. + +GENERATE_TESTLIST = YES + +# The GENERATE_BUGLIST tag can be used to enable (YES) or +# disable (NO) the bug list. This list is created by putting \bug +# commands in the documentation. + +GENERATE_BUGLIST = YES + +# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or +# disable (NO) the deprecated list. This list is created by putting +# \deprecated commands in the documentation. + +GENERATE_DEPRECATEDLIST= YES + +# The ENABLED_SECTIONS tag can be used to enable conditional +# documentation sections, marked by \if sectionname ... \endif. + +ENABLED_SECTIONS = + +# The MAX_INITIALIZER_LINES tag determines the maximum number of lines +# the initial value of a variable or macro consists of for it to appear in +# the documentation. If the initializer consists of more lines than specified +# here it will be hidden. Use a value of 0 to hide initializers completely. +# The appearance of the initializer of individual variables and macros in the +# documentation can be controlled using \showinitializer or \hideinitializer +# command in the documentation regardless of this setting. + +MAX_INITIALIZER_LINES = 30 + +# Set the SHOW_USED_FILES tag to NO to disable the list of files generated +# at the bottom of the documentation of classes and structs. If set to YES the +# list will mention the files that were used to generate the documentation. + +SHOW_USED_FILES = YES + +# If the sources in your project are distributed over multiple directories +# then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy +# in the documentation. The default is NO. + +SHOW_DIRECTORIES = NO + +# Set the SHOW_FILES tag to NO to disable the generation of the Files page. +# This will remove the Files entry from the Quick Index and from the +# Folder Tree View (if specified). The default is YES. + +SHOW_FILES = YES + +# Set the SHOW_NAMESPACES tag to NO to disable the generation of the +# Namespaces page. This will remove the Namespaces entry from the Quick Index +# and from the Folder Tree View (if specified). The default is YES. + +SHOW_NAMESPACES = YES + +# The FILE_VERSION_FILTER tag can be used to specify a program or script that +# doxygen should invoke to get the current version for each file (typically from +# the version control system). Doxygen will invoke the program by executing (via +# popen()) the command <command> <input-file>, where <command> is the value of +# the FILE_VERSION_FILTER tag, and <input-file> is the name of an input file +# provided by doxygen. Whatever the program writes to standard output +# is used as the file version. See the manual for examples. + +FILE_VERSION_FILTER = + +# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed +# by doxygen. The layout file controls the global structure of the generated +# output files in an output format independent way. The create the layout file +# that represents doxygen's defaults, run doxygen with the -l option. +# You can optionally specify a file name after the option, if omitted +# DoxygenLayout.xml will be used as the name of the layout file. + +LAYOUT_FILE = + +# The CITE_BIB_FILES tag can be used to specify one or more bib files +# containing the references data. This must be a list of .bib files. The +# .bib extension is automatically appended if omitted. Using this command +# requires the bibtex tool to be installed. See also +# http://en.wikipedia.org/wiki/BibTeX for more info. For LaTeX the style +# of the bibliography can be controlled using LATEX_BIB_STYLE. To use this +# feature you need bibtex and perl available in the search path. + +CITE_BIB_FILES = + +#--------------------------------------------------------------------------- +# configuration options related to warning and progress messages +#--------------------------------------------------------------------------- + +# The QUIET tag can be used to turn on/off the messages that are generated +# by doxygen. Possible values are YES and NO. If left blank NO is used. + +QUIET = NO + +# The WARNINGS tag can be used to turn on/off the warning messages that are +# generated by doxygen. Possible values are YES and NO. If left blank +# NO is used. + +WARNINGS = YES + +# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings +# for undocumented members. If EXTRACT_ALL is set to YES then this flag will +# automatically be disabled. + +WARN_IF_UNDOCUMENTED = YES + +# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for +# potential errors in the documentation, such as not documenting some +# parameters in a documented function, or documenting parameters that +# don't exist or using markup commands wrongly. + +WARN_IF_DOC_ERROR = YES + +# The WARN_NO_PARAMDOC option can be enabled to get warnings for +# functions that are documented, but have no documentation for their parameters +# or return value. If set to NO (the default) doxygen will only warn about +# wrong or incomplete parameter documentation, but not about the absence of +# documentation. + +WARN_NO_PARAMDOC = NO + +# The WARN_FORMAT tag determines the format of the warning messages that +# doxygen can produce. The string should contain the $file, $line, and $text +# tags, which will be replaced by the file and line number from which the +# warning originated and the warning text. Optionally the format may contain +# $version, which will be replaced by the version of the file (if it could +# be obtained via FILE_VERSION_FILTER) + +WARN_FORMAT = "$file:$line: $text" + +# The WARN_LOGFILE tag can be used to specify a file to which warning +# and error messages should be written. If left blank the output is written +# to stderr. + +WARN_LOGFILE = + +#--------------------------------------------------------------------------- +# configuration options related to the input files +#--------------------------------------------------------------------------- + +# The INPUT tag can be used to specify the files and/or directories that contain +# documented source files. You may enter file names like "myfile.cpp" or +# directories like "/usr/src/myproject". Separate the files or directories +# with spaces. + +INPUT = + +# This tag can be used to specify the character encoding of the source files +# that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is +# also the default input encoding. Doxygen uses libiconv (or the iconv built +# into libc) for the transcoding. See http://www.gnu.org/software/libiconv for +# the list of possible encodings. + +INPUT_ENCODING = UTF-8 + +# If the value of the INPUT tag contains directories, you can use the +# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp +# and *.h) to filter out the source-files in the directories. If left +# blank the following patterns are tested: +# *.c *.cc *.cxx *.cpp *.c++ *.d *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh +# *.hxx *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.dox *.py +# *.f90 *.f *.for *.vhd *.vhdl + +FILE_PATTERNS = + +# The RECURSIVE tag can be used to turn specify whether or not subdirectories +# should be searched for input files as well. Possible values are YES and NO. +# If left blank NO is used. + +RECURSIVE = NO + +# The EXCLUDE tag can be used to specify files and/or directories that should be +# excluded from the INPUT source files. This way you can easily exclude a +# subdirectory from a directory tree whose root is specified with the INPUT tag. +# Note that relative paths are relative to the directory from which doxygen is +# run. + +EXCLUDE = + +# The EXCLUDE_SYMLINKS tag can be used to select whether or not files or +# directories that are symbolic links (a Unix file system feature) are excluded +# from the input. + +EXCLUDE_SYMLINKS = NO + +# If the value of the INPUT tag contains directories, you can use the +# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude +# certain files from those directories. Note that the wildcards are matched +# against the file with absolute path, so to exclude all test directories +# for example use the pattern */test/* + +EXCLUDE_PATTERNS = + +# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names +# (namespaces, classes, functions, etc.) that should be excluded from the +# output. The symbol name can be a fully qualified name, a word, or if the +# wildcard * is used, a substring. Examples: ANamespace, AClass, +# AClass::ANamespace, ANamespace::*Test + +EXCLUDE_SYMBOLS = + +# The EXAMPLE_PATH tag can be used to specify one or more files or +# directories that contain example code fragments that are included (see +# the \include command). + +EXAMPLE_PATH = + +# If the value of the EXAMPLE_PATH tag contains directories, you can use the +# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp +# and *.h) to filter out the source-files in the directories. If left +# blank all files are included. + +EXAMPLE_PATTERNS = + +# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be +# searched for input files to be used with the \include or \dontinclude +# commands irrespective of the value of the RECURSIVE tag. +# Possible values are YES and NO. If left blank NO is used. + +EXAMPLE_RECURSIVE = NO + +# The IMAGE_PATH tag can be used to specify one or more files or +# directories that contain image that are included in the documentation (see +# the \image command). + +IMAGE_PATH = + +# The INPUT_FILTER tag can be used to specify a program that doxygen should +# invoke to filter for each input file. Doxygen will invoke the filter program +# by executing (via popen()) the command <filter> <input-file>, where <filter> +# is the value of the INPUT_FILTER tag, and <input-file> is the name of an +# input file. Doxygen will then use the output that the filter program writes +# to standard output. If FILTER_PATTERNS is specified, this tag will be +# ignored. + +INPUT_FILTER = + +# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern +# basis. Doxygen will compare the file name with each pattern and apply the +# filter if there is a match. The filters are a list of the form: +# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further +# info on how filters are used. If FILTER_PATTERNS is empty or if +# non of the patterns match the file name, INPUT_FILTER is applied. + +FILTER_PATTERNS = + +# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using +# INPUT_FILTER) will be used to filter the input files when producing source +# files to browse (i.e. when SOURCE_BROWSER is set to YES). + +FILTER_SOURCE_FILES = NO + +# The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file +# pattern. A pattern will override the setting for FILTER_PATTERN (if any) +# and it is also possible to disable source filtering for a specific pattern +# using *.ext= (so without naming a filter). This option only has effect when +# FILTER_SOURCE_FILES is enabled. + +FILTER_SOURCE_PATTERNS = + +#--------------------------------------------------------------------------- +# configuration options related to source browsing +#--------------------------------------------------------------------------- + +# If the SOURCE_BROWSER tag is set to YES then a list of source files will +# be generated. Documented entities will be cross-referenced with these sources. +# Note: To get rid of all source code in the generated output, make sure also +# VERBATIM_HEADERS is set to NO. + +SOURCE_BROWSER = NO + +# Setting the INLINE_SOURCES tag to YES will include the body +# of functions and classes directly in the documentation. + +INLINE_SOURCES = NO + +# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct +# doxygen to hide any special comment blocks from generated source code +# fragments. Normal C and C++ comments will always remain visible. + +STRIP_CODE_COMMENTS = YES + +# If the REFERENCED_BY_RELATION tag is set to YES +# then for each documented function all documented +# functions referencing it will be listed. + +REFERENCED_BY_RELATION = NO + +# If the REFERENCES_RELATION tag is set to YES +# then for each documented function all documented entities +# called/used by that function will be listed. + +REFERENCES_RELATION = NO + +# If the REFERENCES_LINK_SOURCE tag is set to YES (the default) +# and SOURCE_BROWSER tag is set to YES, then the hyperlinks from +# functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will +# link to the source code. Otherwise they will link to the documentation. + +REFERENCES_LINK_SOURCE = YES + +# If the USE_HTAGS tag is set to YES then the references to source code +# will point to the HTML generated by the htags(1) tool instead of doxygen +# built-in source browser. The htags tool is part of GNU's global source +# tagging system (see http://www.gnu.org/software/global/global.html). You +# will need version 4.8.6 or higher. + +USE_HTAGS = NO + +# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen +# will generate a verbatim copy of the header file for each class for +# which an include is specified. Set to NO to disable this. + +VERBATIM_HEADERS = YES + +#--------------------------------------------------------------------------- +# configuration options related to the alphabetical class index +#--------------------------------------------------------------------------- + +# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index +# of all compounds will be generated. Enable this if the project +# contains a lot of classes, structs, unions or interfaces. + +ALPHABETICAL_INDEX = YES + +# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then +# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns +# in which this list will be split (can be a number in the range [1..20]) + +COLS_IN_ALPHA_INDEX = 5 + +# In case all classes in a project start with a common prefix, all +# classes will be put under the same header in the alphabetical index. +# The IGNORE_PREFIX tag can be used to specify one or more prefixes that +# should be ignored while generating the index headers. + +IGNORE_PREFIX = + +#--------------------------------------------------------------------------- +# configuration options related to the HTML output +#--------------------------------------------------------------------------- + +# If the GENERATE_HTML tag is set to YES (the default) Doxygen will +# generate HTML output. + +GENERATE_HTML = YES + +# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `html' will be used as the default path. + +HTML_OUTPUT = html + +# The HTML_FILE_EXTENSION tag can be used to specify the file extension for +# each generated HTML page (for example: .htm,.php,.asp). If it is left blank +# doxygen will generate files with .html extension. + +HTML_FILE_EXTENSION = .html + +# The HTML_HEADER tag can be used to specify a personal HTML header for +# each generated HTML page. If it is left blank doxygen will generate a +# standard header. Note that when using a custom header you are responsible +# for the proper inclusion of any scripts and style sheets that doxygen +# needs, which is dependent on the configuration options used. +# It is advised to generate a default header using "doxygen -w html +# header.html footer.html stylesheet.css YourConfigFile" and then modify +# that header. Note that the header is subject to change so you typically +# have to redo this when upgrading to a newer version of doxygen or when +# changing the value of configuration settings such as GENERATE_TREEVIEW! + +HTML_HEADER = + +# The HTML_FOOTER tag can be used to specify a personal HTML footer for +# each generated HTML page. If it is left blank doxygen will generate a +# standard footer. + +HTML_FOOTER = + +# The HTML_STYLESHEET tag can be used to specify a user-defined cascading +# style sheet that is used by each HTML page. It can be used to +# fine-tune the look of the HTML output. If the tag is left blank doxygen +# will generate a default style sheet. Note that doxygen will try to copy +# the style sheet file to the HTML output directory, so don't put your own +# style sheet in the HTML output directory as well, or it will be erased! + +HTML_STYLESHEET = + +# The HTML_EXTRA_FILES tag can be used to specify one or more extra images or +# other source files which should be copied to the HTML output directory. Note +# that these files will be copied to the base HTML output directory. Use the +# $relpath$ marker in the HTML_HEADER and/or HTML_FOOTER files to load these +# files. In the HTML_STYLESHEET file, use the file name only. Also note that +# the files will be copied as-is; there are no commands or markers available. + +HTML_EXTRA_FILES = + +# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. +# Doxygen will adjust the colors in the style sheet and background images +# according to this color. Hue is specified as an angle on a colorwheel, +# see http://en.wikipedia.org/wiki/Hue for more information. +# For instance the value 0 represents red, 60 is yellow, 120 is green, +# 180 is cyan, 240 is blue, 300 purple, and 360 is red again. +# The allowed range is 0 to 359. + +HTML_COLORSTYLE_HUE = 220 + +# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of +# the colors in the HTML output. For a value of 0 the output will use +# grayscales only. A value of 255 will produce the most vivid colors. + +HTML_COLORSTYLE_SAT = 100 + +# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to +# the luminance component of the colors in the HTML output. Values below +# 100 gradually make the output lighter, whereas values above 100 make +# the output darker. The value divided by 100 is the actual gamma applied, +# so 80 represents a gamma of 0.8, The value 220 represents a gamma of 2.2, +# and 100 does not change the gamma. + +HTML_COLORSTYLE_GAMMA = 80 + +# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML +# page will contain the date and time when the page was generated. Setting +# this to NO can help when comparing the output of multiple runs. + +HTML_TIMESTAMP = YES + +# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes, +# files or namespaces will be aligned in HTML using tables. If set to +# NO a bullet list will be used. + +HTML_ALIGN_MEMBERS = YES + +# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML +# documentation will contain sections that can be hidden and shown after the +# page has loaded. For this to work a browser that supports +# JavaScript and DHTML is required (for instance Mozilla 1.0+, Firefox +# Netscape 6.0+, Internet explorer 5.0+, Konqueror, or Safari). + +HTML_DYNAMIC_SECTIONS = NO + +# If the GENERATE_DOCSET tag is set to YES, additional index files +# will be generated that can be used as input for Apple's Xcode 3 +# integrated development environment, introduced with OSX 10.5 (Leopard). +# To create a documentation set, doxygen will generate a Makefile in the +# HTML output directory. Running make will produce the docset in that +# directory and running "make install" will install the docset in +# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find +# it at startup. +# See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html +# for more information. + +GENERATE_DOCSET = NO + +# When GENERATE_DOCSET tag is set to YES, this tag determines the name of the +# feed. A documentation feed provides an umbrella under which multiple +# documentation sets from a single provider (such as a company or product suite) +# can be grouped. + +DOCSET_FEEDNAME = "Doxygen generated docs" + +# When GENERATE_DOCSET tag is set to YES, this tag specifies a string that +# should uniquely identify the documentation set bundle. This should be a +# reverse domain-name style string, e.g. com.mycompany.MyDocSet. Doxygen +# will append .docset to the name. + +DOCSET_BUNDLE_ID = org.doxygen.Project + +# When GENERATE_PUBLISHER_ID tag specifies a string that should uniquely identify +# the documentation publisher. This should be a reverse domain-name style +# string, e.g. com.mycompany.MyDocSet.documentation. + +DOCSET_PUBLISHER_ID = org.doxygen.Publisher + +# The GENERATE_PUBLISHER_NAME tag identifies the documentation publisher. + +DOCSET_PUBLISHER_NAME = Publisher + +# If the GENERATE_HTMLHELP tag is set to YES, additional index files +# will be generated that can be used as input for tools like the +# Microsoft HTML help workshop to generate a compiled HTML help file (.chm) +# of the generated HTML documentation. + +GENERATE_HTMLHELP = NO + +# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can +# be used to specify the file name of the resulting .chm file. You +# can add a path in front of the file if the result should not be +# written to the html output directory. + +CHM_FILE = + +# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can +# be used to specify the location (absolute path including file name) of +# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run +# the HTML help compiler on the generated index.hhp. + +HHC_LOCATION = + +# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag +# controls if a separate .chi index file is generated (YES) or that +# it should be included in the master .chm file (NO). + +GENERATE_CHI = NO + +# If the GENERATE_HTMLHELP tag is set to YES, the CHM_INDEX_ENCODING +# is used to encode HtmlHelp index (hhk), content (hhc) and project file +# content. + +CHM_INDEX_ENCODING = + +# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag +# controls whether a binary table of contents is generated (YES) or a +# normal table of contents (NO) in the .chm file. + +BINARY_TOC = NO + +# The TOC_EXPAND flag can be set to YES to add extra items for group members +# to the contents of the HTML help documentation and to the tree view. + +TOC_EXPAND = NO + +# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and +# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated +# that can be used as input for Qt's qhelpgenerator to generate a +# Qt Compressed Help (.qch) of the generated HTML documentation. + +GENERATE_QHP = NO + +# If the QHG_LOCATION tag is specified, the QCH_FILE tag can +# be used to specify the file name of the resulting .qch file. +# The path specified is relative to the HTML output folder. + +QCH_FILE = + +# The QHP_NAMESPACE tag specifies the namespace to use when generating +# Qt Help Project output. For more information please see +# http://doc.trolltech.com/qthelpproject.html#namespace + +QHP_NAMESPACE = org.doxygen.Project + +# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating +# Qt Help Project output. For more information please see +# http://doc.trolltech.com/qthelpproject.html#virtual-folders + +QHP_VIRTUAL_FOLDER = doc + +# If QHP_CUST_FILTER_NAME is set, it specifies the name of a custom filter to +# add. For more information please see +# http://doc.trolltech.com/qthelpproject.html#custom-filters + +QHP_CUST_FILTER_NAME = + +# The QHP_CUST_FILT_ATTRS tag specifies the list of the attributes of the +# custom filter to add. For more information please see +# <a href="http://doc.trolltech.com/qthelpproject.html#custom-filters"> +# Qt Help Project / Custom Filters</a>. + +QHP_CUST_FILTER_ATTRS = + +# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this +# project's +# filter section matches. +# <a href="http://doc.trolltech.com/qthelpproject.html#filter-attributes"> +# Qt Help Project / Filter Attributes</a>. + +QHP_SECT_FILTER_ATTRS = + +# If the GENERATE_QHP tag is set to YES, the QHG_LOCATION tag can +# be used to specify the location of Qt's qhelpgenerator. +# If non-empty doxygen will try to run qhelpgenerator on the generated +# .qhp file. + +QHG_LOCATION = + +# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files +# will be generated, which together with the HTML files, form an Eclipse help +# plugin. To install this plugin and make it available under the help contents +# menu in Eclipse, the contents of the directory containing the HTML and XML +# files needs to be copied into the plugins directory of eclipse. The name of +# the directory within the plugins directory should be the same as +# the ECLIPSE_DOC_ID value. After copying Eclipse needs to be restarted before +# the help appears. + +GENERATE_ECLIPSEHELP = NO + +# A unique identifier for the eclipse help plugin. When installing the plugin +# the directory name containing the HTML and XML files should also have +# this name. + +ECLIPSE_DOC_ID = org.doxygen.Project + +# The DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs) +# at top of each HTML page. The value NO (the default) enables the index and +# the value YES disables it. Since the tabs have the same information as the +# navigation tree you can set this option to NO if you already set +# GENERATE_TREEVIEW to YES. + +DISABLE_INDEX = NO + +# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index +# structure should be generated to display hierarchical information. +# If the tag value is set to YES, a side panel will be generated +# containing a tree-like index structure (just like the one that +# is generated for HTML Help). For this to work a browser that supports +# JavaScript, DHTML, CSS and frames is required (i.e. any modern browser). +# Windows users are probably better off using the HTML help feature. +# Since the tree basically has the same information as the tab index you +# could consider to set DISABLE_INDEX to NO when enabling this option. + +GENERATE_TREEVIEW = NO + +# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values +# (range [0,1..20]) that doxygen will group on one line in the generated HTML +# documentation. Note that a value of 0 will completely suppress the enum +# values from appearing in the overview section. + +ENUM_VALUES_PER_LINE = 4 + +# By enabling USE_INLINE_TREES, doxygen will generate the Groups, Directories, +# and Class Hierarchy pages using a tree view instead of an ordered list. + +USE_INLINE_TREES = NO + +# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be +# used to set the initial width (in pixels) of the frame in which the tree +# is shown. + +TREEVIEW_WIDTH = 250 + +# When the EXT_LINKS_IN_WINDOW option is set to YES doxygen will open +# links to external symbols imported via tag files in a separate window. + +EXT_LINKS_IN_WINDOW = NO + +# Use this tag to change the font size of Latex formulas included +# as images in the HTML documentation. The default is 10. Note that +# when you change the font size after a successful doxygen run you need +# to manually remove any form_*.png images from the HTML output directory +# to force them to be regenerated. + +FORMULA_FONTSIZE = 10 + +# Use the FORMULA_TRANPARENT tag to determine whether or not the images +# generated for formulas are transparent PNGs. Transparent PNGs are +# not supported properly for IE 6.0, but are supported on all modern browsers. +# Note that when changing this option you need to delete any form_*.png files +# in the HTML output before the changes have effect. + +FORMULA_TRANSPARENT = YES + +# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax +# (see http://www.mathjax.org) which uses client side Javascript for the +# rendering instead of using prerendered bitmaps. Use this if you do not +# have LaTeX installed or if you want to formulas look prettier in the HTML +# output. When enabled you also need to install MathJax separately and +# configure the path to it using the MATHJAX_RELPATH option. + +USE_MATHJAX = NO + +# When MathJax is enabled you need to specify the location relative to the +# HTML output directory using the MATHJAX_RELPATH option. The destination +# directory should contain the MathJax.js script. For instance, if the mathjax +# directory is located at the same level as the HTML output directory, then +# MATHJAX_RELPATH should be ../mathjax. The default value points to the +# mathjax.org site, so you can quickly see the result without installing +# MathJax, but it is strongly recommended to install a local copy of MathJax +# before deployment. + +MATHJAX_RELPATH = http://www.mathjax.org/mathjax + +# The MATHJAX_EXTENSIONS tag can be used to specify one or MathJax extension +# names that should be enabled during MathJax rendering. + +MATHJAX_EXTENSIONS = + +# When the SEARCHENGINE tag is enabled doxygen will generate a search box +# for the HTML output. The underlying search engine uses javascript +# and DHTML and should work on any modern browser. Note that when using +# HTML help (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets +# (GENERATE_DOCSET) there is already a search function so this one should +# typically be disabled. For large projects the javascript based search engine +# can be slow, then enabling SERVER_BASED_SEARCH may provide a better solution. + +SEARCHENGINE = YES + +# When the SERVER_BASED_SEARCH tag is enabled the search engine will be +# implemented using a PHP enabled web server instead of at the web client +# using Javascript. Doxygen will generate the search PHP script and index +# file to put on the web server. The advantage of the server +# based approach is that it scales better to large projects and allows +# full text search. The disadvantages are that it is more difficult to setup +# and does not have live searching capabilities. + +SERVER_BASED_SEARCH = NO + +#--------------------------------------------------------------------------- +# configuration options related to the LaTeX output +#--------------------------------------------------------------------------- + +# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will +# generate Latex output. + +GENERATE_LATEX = YES + +# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `latex' will be used as the default path. + +LATEX_OUTPUT = latex + +# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be +# invoked. If left blank `latex' will be used as the default command name. +# Note that when enabling USE_PDFLATEX this option is only used for +# generating bitmaps for formulas in the HTML output, but not in the +# Makefile that is written to the output directory. + +LATEX_CMD_NAME = latex + +# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to +# generate index for LaTeX. If left blank `makeindex' will be used as the +# default command name. + +MAKEINDEX_CMD_NAME = makeindex + +# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact +# LaTeX documents. This may be useful for small projects and may help to +# save some trees in general. + +COMPACT_LATEX = NO + +# The PAPER_TYPE tag can be used to set the paper type that is used +# by the printer. Possible values are: a4, letter, legal and +# executive. If left blank a4wide will be used. + +PAPER_TYPE = a4 + +# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX +# packages that should be included in the LaTeX output. + +EXTRA_PACKAGES = + +# The LATEX_HEADER tag can be used to specify a personal LaTeX header for +# the generated latex document. The header should contain everything until +# the first chapter. If it is left blank doxygen will generate a +# standard header. Notice: only use this tag if you know what you are doing! + +LATEX_HEADER = + +# The LATEX_FOOTER tag can be used to specify a personal LaTeX footer for +# the generated latex document. The footer should contain everything after +# the last chapter. If it is left blank doxygen will generate a +# standard footer. Notice: only use this tag if you know what you are doing! + +LATEX_FOOTER = + +# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated +# is prepared for conversion to pdf (using ps2pdf). The pdf file will +# contain links (just like the HTML output) instead of page references +# This makes the output suitable for online browsing using a pdf viewer. + +PDF_HYPERLINKS = YES + +# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of +# plain latex in the generated Makefile. Set this option to YES to get a +# higher quality PDF documentation. + +USE_PDFLATEX = YES + +# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. +# command to the generated LaTeX files. This will instruct LaTeX to keep +# running if errors occur, instead of asking the user for help. +# This option is also used when generating formulas in HTML. + +LATEX_BATCHMODE = NO + +# If LATEX_HIDE_INDICES is set to YES then doxygen will not +# include the index chapters (such as File Index, Compound Index, etc.) +# in the output. + +LATEX_HIDE_INDICES = NO + +# If LATEX_SOURCE_CODE is set to YES then doxygen will include +# source code with syntax highlighting in the LaTeX output. +# Note that which sources are shown also depends on other settings +# such as SOURCE_BROWSER. + +LATEX_SOURCE_CODE = NO + +# The LATEX_BIB_STYLE tag can be used to specify the style to use for the +# bibliography, e.g. plainnat, or ieeetr. The default style is "plain". See +# http://en.wikipedia.org/wiki/BibTeX for more info. + +LATEX_BIB_STYLE = plain + +#--------------------------------------------------------------------------- +# configuration options related to the RTF output +#--------------------------------------------------------------------------- + +# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output +# The RTF output is optimized for Word 97 and may not look very pretty with +# other RTF readers or editors. + +GENERATE_RTF = NO + +# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `rtf' will be used as the default path. + +RTF_OUTPUT = rtf + +# If the COMPACT_RTF tag is set to YES Doxygen generates more compact +# RTF documents. This may be useful for small projects and may help to +# save some trees in general. + +COMPACT_RTF = NO + +# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated +# will contain hyperlink fields. The RTF file will +# contain links (just like the HTML output) instead of page references. +# This makes the output suitable for online browsing using WORD or other +# programs which support those fields. +# Note: wordpad (write) and others do not support links. + +RTF_HYPERLINKS = NO + +# Load style sheet definitions from file. Syntax is similar to doxygen's +# config file, i.e. a series of assignments. You only have to provide +# replacements, missing definitions are set to their default value. + +RTF_STYLESHEET_FILE = + +# Set optional variables used in the generation of an rtf document. +# Syntax is similar to doxygen's config file. + +RTF_EXTENSIONS_FILE = + +#--------------------------------------------------------------------------- +# configuration options related to the man page output +#--------------------------------------------------------------------------- + +# If the GENERATE_MAN tag is set to YES (the default) Doxygen will +# generate man pages + +GENERATE_MAN = NO + +# The MAN_OUTPUT tag is used to specify where the man pages will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `man' will be used as the default path. + +MAN_OUTPUT = man + +# The MAN_EXTENSION tag determines the extension that is added to +# the generated man pages (default is the subroutine's section .3) + +MAN_EXTENSION = .3 + +# If the MAN_LINKS tag is set to YES and Doxygen generates man output, +# then it will generate one additional man file for each entity +# documented in the real man page(s). These additional files +# only source the real man page, but without them the man command +# would be unable to find the correct page. The default is NO. + +MAN_LINKS = NO + +#--------------------------------------------------------------------------- +# configuration options related to the XML output +#--------------------------------------------------------------------------- + +# If the GENERATE_XML tag is set to YES Doxygen will +# generate an XML file that captures the structure of +# the code including all documentation. + +GENERATE_XML = NO + +# The XML_OUTPUT tag is used to specify where the XML pages will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `xml' will be used as the default path. + +XML_OUTPUT = xml + +# The XML_SCHEMA tag can be used to specify an XML schema, +# which can be used by a validating XML parser to check the +# syntax of the XML files. + +XML_SCHEMA = + +# The XML_DTD tag can be used to specify an XML DTD, +# which can be used by a validating XML parser to check the +# syntax of the XML files. + +XML_DTD = + +# If the XML_PROGRAMLISTING tag is set to YES Doxygen will +# dump the program listings (including syntax highlighting +# and cross-referencing information) to the XML output. Note that +# enabling this will significantly increase the size of the XML output. + +XML_PROGRAMLISTING = YES + +#--------------------------------------------------------------------------- +# configuration options for the AutoGen Definitions output +#--------------------------------------------------------------------------- + +# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will +# generate an AutoGen Definitions (see autogen.sf.net) file +# that captures the structure of the code including all +# documentation. Note that this feature is still experimental +# and incomplete at the moment. + +GENERATE_AUTOGEN_DEF = NO + +#--------------------------------------------------------------------------- +# configuration options related to the Perl module output +#--------------------------------------------------------------------------- + +# If the GENERATE_PERLMOD tag is set to YES Doxygen will +# generate a Perl module file that captures the structure of +# the code including all documentation. Note that this +# feature is still experimental and incomplete at the +# moment. + +GENERATE_PERLMOD = NO + +# If the PERLMOD_LATEX tag is set to YES Doxygen will generate +# the necessary Makefile rules, Perl scripts and LaTeX code to be able +# to generate PDF and DVI output from the Perl module output. + +PERLMOD_LATEX = NO + +# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be +# nicely formatted so it can be parsed by a human reader. This is useful +# if you want to understand what is going on. On the other hand, if this +# tag is set to NO the size of the Perl module output will be much smaller +# and Perl will parse it just the same. + +PERLMOD_PRETTY = YES + +# The names of the make variables in the generated doxyrules.make file +# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. +# This is useful so different doxyrules.make files included by the same +# Makefile don't overwrite each other's variables. + +PERLMOD_MAKEVAR_PREFIX = + +#--------------------------------------------------------------------------- +# Configuration options related to the preprocessor +#--------------------------------------------------------------------------- + +# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will +# evaluate all C-preprocessor directives found in the sources and include +# files. + +ENABLE_PREPROCESSING = YES + +# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro +# names in the source code. If set to NO (the default) only conditional +# compilation will be performed. Macro expansion can be done in a controlled +# way by setting EXPAND_ONLY_PREDEF to YES. + +MACRO_EXPANSION = NO + +# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES +# then the macro expansion is limited to the macros specified with the +# PREDEFINED and EXPAND_AS_DEFINED tags. + +EXPAND_ONLY_PREDEF = NO + +# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files +# pointed to by INCLUDE_PATH will be searched when a #include is found. + +SEARCH_INCLUDES = YES + +# The INCLUDE_PATH tag can be used to specify one or more directories that +# contain include files that are not input files but should be processed by +# the preprocessor. + +INCLUDE_PATH = + +# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard +# patterns (like *.h and *.hpp) to filter out the header-files in the +# directories. If left blank, the patterns specified with FILE_PATTERNS will +# be used. + +INCLUDE_FILE_PATTERNS = + +# The PREDEFINED tag can be used to specify one or more macro names that +# are defined before the preprocessor is started (similar to the -D option of +# gcc). The argument of the tag is a list of macros of the form: name +# or name=definition (no spaces). If the definition and the = are +# omitted =1 is assumed. To prevent a macro definition from being +# undefined via #undef or recursively expanded use the := operator +# instead of the = operator. + +PREDEFINED = + +# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then +# this tag can be used to specify a list of macro names that should be expanded. +# The macro definition that is found in the sources will be used. +# Use the PREDEFINED tag if you want to use a different macro definition that +# overrules the definition found in the source code. + +EXPAND_AS_DEFINED = + +# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then +# doxygen's preprocessor will remove all references to function-like macros +# that are alone on a line, have an all uppercase name, and do not end with a +# semicolon, because these will confuse the parser if not removed. + +SKIP_FUNCTION_MACROS = YES + +#--------------------------------------------------------------------------- +# Configuration::additions related to external references +#--------------------------------------------------------------------------- + +# The TAGFILES option can be used to specify one or more tagfiles. +# Optionally an initial location of the external documentation +# can be added for each tagfile. The format of a tag file without +# this location is as follows: +# TAGFILES = file1 file2 ... +# Adding location for the tag files is done as follows: +# TAGFILES = file1=loc1 "file2 = loc2" ... +# where "loc1" and "loc2" can be relative or absolute paths or +# URLs. If a location is present for each tag, the installdox tool +# does not have to be run to correct the links. +# Note that each tag file must have a unique name +# (where the name does NOT include the path) +# If a tag file is not located in the directory in which doxygen +# is run, you must also specify the path to the tagfile here. + +TAGFILES = + +# When a file name is specified after GENERATE_TAGFILE, doxygen will create +# a tag file that is based on the input files it reads. + +GENERATE_TAGFILE = + +# If the ALLEXTERNALS tag is set to YES all external classes will be listed +# in the class index. If set to NO only the inherited external classes +# will be listed. + +ALLEXTERNALS = NO + +# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed +# in the modules index. If set to NO, only the current project's groups will +# be listed. + +EXTERNAL_GROUPS = YES + +# The PERL_PATH should be the absolute path and name of the perl script +# interpreter (i.e. the result of `which perl'). + +PERL_PATH = /usr/bin/perl + +#--------------------------------------------------------------------------- +# Configuration options related to the dot tool +#--------------------------------------------------------------------------- + +# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will +# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base +# or super classes. Setting the tag to NO turns the diagrams off. Note that +# this option also works with HAVE_DOT disabled, but it is recommended to +# install and use dot, since it yields more powerful graphs. + +CLASS_DIAGRAMS = YES + +# You can define message sequence charts within doxygen comments using the \msc +# command. Doxygen will then run the mscgen tool (see +# http://www.mcternan.me.uk/mscgen/) to produce the chart and insert it in the +# documentation. The MSCGEN_PATH tag allows you to specify the directory where +# the mscgen tool resides. If left empty the tool is assumed to be found in the +# default search path. + +MSCGEN_PATH = + +# If set to YES, the inheritance and collaboration graphs will hide +# inheritance and usage relations if the target is undocumented +# or is not a class. + +HIDE_UNDOC_RELATIONS = YES + +# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is +# available from the path. This tool is part of Graphviz, a graph visualization +# toolkit from AT&T and Lucent Bell Labs. The other options in this section +# have no effect if this option is set to NO (the default) + +HAVE_DOT = NO + +# The DOT_NUM_THREADS specifies the number of dot invocations doxygen is +# allowed to run in parallel. When set to 0 (the default) doxygen will +# base this on the number of processors available in the system. You can set it +# explicitly to a value larger than 0 to get control over the balance +# between CPU load and processing speed. + +DOT_NUM_THREADS = 0 + +# By default doxygen will use the Helvetica font for all dot files that +# doxygen generates. When you want a differently looking font you can specify +# the font name using DOT_FONTNAME. You need to make sure dot is able to find +# the font, which can be done by putting it in a standard location or by setting +# the DOTFONTPATH environment variable or by setting DOT_FONTPATH to the +# directory containing the font. + +DOT_FONTNAME = Helvetica + +# The DOT_FONTSIZE tag can be used to set the size of the font of dot graphs. +# The default size is 10pt. + +DOT_FONTSIZE = 10 + +# By default doxygen will tell dot to use the Helvetica font. +# If you specify a different font using DOT_FONTNAME you can use DOT_FONTPATH to +# set the path where dot can find it. + +DOT_FONTPATH = + +# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for each documented class showing the direct and +# indirect inheritance relations. Setting this tag to YES will force the +# CLASS_DIAGRAMS tag to NO. + +CLASS_GRAPH = YES + +# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for each documented class showing the direct and +# indirect implementation dependencies (inheritance, containment, and +# class references variables) of the class with other documented classes. + +COLLABORATION_GRAPH = YES + +# If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for groups, showing the direct groups dependencies + +GROUP_GRAPHS = YES + +# If the UML_LOOK tag is set to YES doxygen will generate inheritance and +# collaboration diagrams in a style similar to the OMG's Unified Modeling +# Language. + +UML_LOOK = NO + +# If set to YES, the inheritance and collaboration graphs will show the +# relations between templates and their instances. + +TEMPLATE_RELATIONS = NO + +# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT +# tags are set to YES then doxygen will generate a graph for each documented +# file showing the direct and indirect include dependencies of the file with +# other documented files. + +INCLUDE_GRAPH = YES + +# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and +# HAVE_DOT tags are set to YES then doxygen will generate a graph for each +# documented header file showing the documented files that directly or +# indirectly include this file. + +INCLUDED_BY_GRAPH = YES + +# If the CALL_GRAPH and HAVE_DOT options are set to YES then +# doxygen will generate a call dependency graph for every global function +# or class method. Note that enabling this option will significantly increase +# the time of a run. So in most cases it will be better to enable call graphs +# for selected functions only using the \callgraph command. + +CALL_GRAPH = NO + +# If the CALLER_GRAPH and HAVE_DOT tags are set to YES then +# doxygen will generate a caller dependency graph for every global function +# or class method. Note that enabling this option will significantly increase +# the time of a run. So in most cases it will be better to enable caller +# graphs for selected functions only using the \callergraph command. + +CALLER_GRAPH = NO + +# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen +# will generate a graphical hierarchy of all classes instead of a textual one. + +GRAPHICAL_HIERARCHY = YES + +# If the DIRECTORY_GRAPH, SHOW_DIRECTORIES and HAVE_DOT tags are set to YES +# then doxygen will show the dependencies a directory has on other directories +# in a graphical way. The dependency relations are determined by the #include +# relations between the files in the directories. + +DIRECTORY_GRAPH = YES + +# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images +# generated by dot. Possible values are svg, png, jpg, or gif. +# If left blank png will be used. If you choose svg you need to set +# HTML_FILE_EXTENSION to xhtml in order to make the SVG files +# visible in IE 9+ (other browsers do not have this requirement). + +DOT_IMAGE_FORMAT = png + +# If DOT_IMAGE_FORMAT is set to svg, then this option can be set to YES to +# enable generation of interactive SVG images that allow zooming and panning. +# Note that this requires a modern browser other than Internet Explorer. +# Tested and working are Firefox, Chrome, Safari, and Opera. For IE 9+ you +# need to set HTML_FILE_EXTENSION to xhtml in order to make the SVG files +# visible. Older versions of IE do not have SVG support. + +INTERACTIVE_SVG = NO + +# The tag DOT_PATH can be used to specify the path where the dot tool can be +# found. If left blank, it is assumed the dot tool can be found in the path. + +DOT_PATH = + +# The DOTFILE_DIRS tag can be used to specify one or more directories that +# contain dot files that are included in the documentation (see the +# \dotfile command). + +DOTFILE_DIRS = + +# The MSCFILE_DIRS tag can be used to specify one or more directories that +# contain msc files that are included in the documentation (see the +# \mscfile command). + +MSCFILE_DIRS = + +# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of +# nodes that will be shown in the graph. If the number of nodes in a graph +# becomes larger than this value, doxygen will truncate the graph, which is +# visualized by representing a node as a red box. Note that doxygen if the +# number of direct children of the root node in a graph is already larger than +# DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note +# that the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH. + +DOT_GRAPH_MAX_NODES = 50 + +# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the +# graphs generated by dot. A depth value of 3 means that only nodes reachable +# from the root by following a path via at most 3 edges will be shown. Nodes +# that lay further from the root node will be omitted. Note that setting this +# option to 1 or 2 may greatly reduce the computation time needed for large +# code bases. Also note that the size of a graph can be further restricted by +# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction. + +MAX_DOT_GRAPH_DEPTH = 0 + +# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent +# background. This is disabled by default, because dot on Windows does not +# seem to support this out of the box. Warning: Depending on the platform used, +# enabling this option may lead to badly anti-aliased labels on the edges of +# a graph (i.e. they become hard to read). + +DOT_TRANSPARENT = NO + +# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output +# files in one run (i.e. multiple -o and -T options on the command line). This +# makes dot run faster, but since only newer versions of dot (>1.8.10) +# support this, this feature is disabled by default. + +DOT_MULTI_TARGETS = YES + +# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will +# generate a legend page explaining the meaning of the various boxes and +# arrows in the dot generated graphs. + +GENERATE_LEGEND = YES + +# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will +# remove the intermediate dot files that are used to generate +# the various graphs. + +DOT_CLEANUP = YES diff --git a/core/ImgParam.cpp b/core/ImgParam.cpp index a6af4769d95a1fef717a2073e5b0cff968bbaccc..3f63cb1971d8efd94792f1446aff85a9f48ff1b3 100644 --- a/core/ImgParam.cpp +++ b/core/ImgParam.cpp @@ -17,15 +17,37 @@ * along with EIImage. If not, see <http://www.gnu.org/licenses/>. */ - +#include <Widgets/ImageListBox.h> +#include <QWidget> +#include <QFormLayout> +#include <QDialog> #include "ImgParam.h" +#include <Widgets/ImageWidgets/StandardImageWindow.h> +#include <Widgets/ImageWidgets/DoubleImageWindow.h> +using namespace std; using namespace imagein; +using namespace genericinterface; -void ImgParam::fillDialog(QDialog*) { +void ImgParam::fillDialog(QDialog* dialog, const ImageWindow* currentWnd, const vector<const ImageWindow*>& wndList) { + QString currentImgName = currentWnd->windowTitle(); + map<const Image*,string> imgList; + for(vector<const ImageWindow*>::const_iterator it = wndList.begin(); it != wndList.end(); ++it) { + if((*it)->isStandard()) { + const StandardImageWindow* stdImgWnd = dynamic_cast<const StandardImageWindow*>(*it); + imgList.insert(pair<const Image*, string>(stdImgWnd->getImage(), stdImgWnd->windowTitle().toStdString())); + } + } + QWidget *widget = new QWidget(); + QFormLayout* layout = new QFormLayout(); + _imgListBox = new ImageListBox(widget, NULL, imgList); + layout->insertRow(1, QString(this->_name.c_str()) + " : ", _imgListBox); + widget->setLayout(layout); + dialog->layout()->addWidget(widget); } void ImgParam::pickValue() { + *this->_ptr = *_imgListBox->currentImage(); } Parameter<Image>* ImgParam::clone() const { diff --git a/core/ImgParam.h b/core/ImgParam.h index cd0889608ee0b051e653e9bf999d91ec0550555d..db82aff2fea55ae6cea539b67797aa5fc53938ec 100644 --- a/core/ImgParam.h +++ b/core/ImgParam.h @@ -22,16 +22,31 @@ #include <vector> #include <string> +#include <map> #include "Image.h" #include "Parameter.h" +template<typename D> +class ImageListBox_t; +/** + * @brief This class describes a way to get an Image parameter from the user + * + */ class ImgParam : public Parameter<imagein::Image> { public: - ImgParam(std::string name, imagein::Image* ptr = NULL) : Parameter(name, ptr) {} - virtual void fillDialog(QDialog*); +/** + * @brief Constructor, will be directly called in the PlugOperation. + * + * @param name Name of the input. + * @param ptr Pointer in which to store the given input. + */ + ImgParam(std::string name, imagein::Image* ptr = NULL) : Parameter<imagein::Image >(name, ptr) {} + virtual void fillDialog(QDialog* dialog, const genericinterface::ImageWindow* currentWnd, const std::vector<const genericinterface::ImageWindow*>& wndList); virtual void pickValue(); - virtual Parameter* clone() const; + virtual Parameter<imagein::Image >* clone() const; + protected: + ImageListBox_t<uint8_t>* _imgListBox; }; -#endif //!EIIMAGE_IMGPARAM_H \ No newline at end of file +#endif //!EIIMAGE_IMGPARAM_H diff --git a/core/Input.h b/core/Input.h index 8248f8613081ad3bc25059eebd9497330d60f6bf..b5f7282799a7298f55930e9a5e46d70e37d09c4f 100644 --- a/core/Input.h +++ b/core/Input.h @@ -21,15 +21,46 @@ #define EIIMAGE_INPUT_H #include <vector> +#include <map> #include <string> - +#include <Image.h> class QDialog; +namespace genericinterface { + class ImageWindow; +} +/** + * @brief Input represents a data input from the user. + * + * Input is an interface describing the behavior of all kind of input used in a PlugOperation. + * An input must implement the method fillDialog() in order to fill a given dialog with all the widgets needed to get the specific data from the user. + * Then, the input must implement the pickValue() method to get the data and store it in a given lcoation. + * + */ class Input { public: + /** + * @brief Copy constructor + * + * @return Input A copy of this instance + */ virtual Input* clone() const = 0; - virtual void fillDialog(QDialog*) = 0; + /** + * @brief Fill the dialog with all necessary widgets + * + * This method is called right before the dialog is shown to the user. + * + * @param dialog The dialog to put all the necessary widgets in. + * @param imgList The list of all the images opened in the application. + */ + virtual void fillDialog(QDialog* dialog, const genericinterface::ImageWindow* currentWnd, const std::vector<const genericinterface::ImageWindow*>& wndList) = 0; + /** + * @brief Pick the data from the widgets an store it in a given location. + * + * This method is called right after the user validate the dialog. + * + */ virtual void pickValue() = 0; }; -#endif //!EIIMAGE_INPUT_H \ No newline at end of file +#endif //!EIIMAGE_INPUT_H diff --git a/core/IntParam.cpp b/core/IntParam.cpp index 19eb3409c6689073d3411e5ecc647a15e296f455..c7134a0a8fb877f3de1ff380bbf69d61d7c77201 100644 --- a/core/IntParam.cpp +++ b/core/IntParam.cpp @@ -26,13 +26,15 @@ #include "IntParam.h" using namespace imagein; +using namespace std; +using namespace genericinterface; -IntParam::IntParam(std::string name, int min, int max, int def) : Parameter(name), _min(min), _max(max) { +IntParam::IntParam(std::string name, int min, int max, int def) : Parameter<int>(name), _min(min), _max(max) { _def = std::min(def, _max); _def = std::max(def, _min); } -void IntParam::fillDialog(QDialog* dialog) { +void IntParam::fillDialog(QDialog* dialog, const ImageWindow*, const vector<const ImageWindow*>&) { QWidget *widget = new QWidget(); QFormLayout* layout = new QFormLayout(); _spinbox = new QSpinBox(); diff --git a/core/IntParam.h b/core/IntParam.h index 81aa5f93edcce5553688869b269eab8f320c0c40..d74d2f488caeb51dec5d9bafa2733a94ede2134b 100644 --- a/core/IntParam.h +++ b/core/IntParam.h @@ -28,15 +28,42 @@ class QSpinBox; class QDialog; +/** + * @brief This class describes a way to get an int parameter from the user. + * + */ class IntParam : public Parameter<int> { public: +/** + * @brief Constructor of the input, wille be directly called inside the PlugOperation constructor. + * + * @param name Name of the input as it will be displayed to the user + * @param min Lower bound of the possible values + * @param max Upper bound of the possible values + * @param def Default value of the input + */ IntParam(std::string name, int min, int max, int def = 0); - virtual void fillDialog(QDialog*); + /** + * @brief Add a QSpinBox with the specified name to the dialog. + * + * @param dialog The dialog in which to add the widgets. + */ + virtual void fillDialog(QDialog* dialog, const genericinterface::ImageWindow* currentWnd, const std::vector<const genericinterface::ImageWindow*>& wndList); + + /** + * @brief Get the value of the QSpinBox and store it in the location pointerd by Parameter::_ptr + * + */ virtual void pickValue(); + /** + * @brief Copy constructor + * + * @return IntParam A copy of this instance + */ virtual IntParam* clone() const; protected: - int _min, _max, _def; - QSpinBox* _spinbox; + int _min, _max, _def; /**< The QSpinBox parameters */ + QSpinBox* _spinbox; /**< The QSpinBox widget to get the value from */ }; -#endif //!EIIMAGE_INTPARAM_H \ No newline at end of file +#endif //!EIIMAGE_INTPARAM_H diff --git a/core/OpSet.h b/core/OpSet.h index dd42e54d11aad3bebf733bf42c480abbecba6256..8c4d1382285f3d5be44e6471884a7cdd78494e07 100644 --- a/core/OpSet.h +++ b/core/OpSet.h @@ -25,14 +25,35 @@ #include "Operation.h" +/** + * @brief Set of GenericOperation objects. + * + * An Operation set is used to represent a set of instances of differents implementations of the interface GenericOperation. + * + */ class OpSet { public: +/** + * @brief Constructor + * + * @param name The name of the OpSet, as it should appear to the user. + */ OpSet(std::string name) : _name(name) {} + /** + * @brief Operations accessor + * + * @return std::vector<GenericOperation *> The set of operations contained in this Opset + */ virtual std::vector<GenericOperation*> getOperations() = 0; + /** + * @brief Name accessor + * + * @return std::string The name of this OpSet + */ inline std::string getName() { return _name; } private: - std::string _name; + std::string _name; /**< The name of this OpSet */ }; #endif //!EIIMAGE_OPSET_H diff --git a/core/Operation.cpp b/core/Operation.cpp index 494254de0b8da67c6668d26d5434c613b8f41c92..1d78a0cc3538ba025169ad734587eaf3ba2d0d4d 100644 --- a/core/Operation.cpp +++ b/core/Operation.cpp @@ -20,6 +20,7 @@ #include "Operation.h" #include <Widgets/ImageWidgets/StandardImageWindow.h> #include <Widgets/ImageWidgets/DoubleImageWindow.h> +#include <Services/WindowService.h> using namespace std; using namespace imagein; @@ -33,10 +34,10 @@ class EIImageService : public genericinterface::WindowService void outputText(QString text); }; -void GenericOperation::operator()(EIImageService* ws) { +void GenericOperation::operator()(WindowService* ws) { _ws = ws; _curImgWnd = ws->getCurrentImageWindow(); - vector<ImageWindow*> wndList = ws->getImageWindows(); + vector<const ImageWindow*> wndList = ws->getImageWindows(); return this->operator ()(_curImgWnd, wndList); } @@ -67,17 +68,17 @@ void GenericOperation::outImage(imagein::Image* img, string title) { this->outImgWnd(wnd, title); } -void GenericOperation::outDoubleImage(imagein::Image_t<double>* img, string title, bool norm, bool log) { - DoubleImageWindow* wnd = new DoubleImageWindow(img, QString(), norm, log); +void GenericOperation::outDoubleImage(imagein::Image_t<double>* img, string title, bool norm, bool log, double logScale, bool abs) { + DoubleImageWindow* wnd = new DoubleImageWindow(img, QString(), norm, log, logScale, abs); this->outImgWnd(wnd, title); } void GenericOperation::outText(std::string text) { if(_ws == NULL) return; - _ws->outputText(QString(text.c_str())); + _ws->addText(text); } -void Operation::operator()(const ImageWindow* currentWnd, vector<ImageWindow*>& wndList) { +void Operation::operator()(const ImageWindow* currentWnd, const vector<const ImageWindow*>& wndList) { const StandardImageWindow* curImgWnd = dynamic_cast<const StandardImageWindow*>(currentWnd); const Image* image = curImgWnd ? curImgWnd->getImage() : NULL; const Image* curImg = image; @@ -91,8 +92,9 @@ void Operation::operator()(const ImageWindow* currentWnd, vector<ImageWindow*>& } } } + map<const Image*, string> imgList; - for(vector<ImageWindow*>::iterator it = wndList.begin(); it != wndList.end(); ++it) { + for(vector<const ImageWindow*>::const_iterator it = wndList.begin(); it != wndList.end(); ++it) { const StandardImageWindow* imgWnd = dynamic_cast<const StandardImageWindow*>(*it); if(imgWnd) { const Image* img = imgWnd->getImage(); @@ -100,7 +102,7 @@ void Operation::operator()(const ImageWindow* currentWnd, vector<ImageWindow*>& imgList.insert(pair<const Image*, string>(img, imgWnd->windowTitle().toStdString())); } } - outText("Hello world!"); + this->operator()(image, imgList); for(vector<const Image*>::iterator it = imgToDelete.begin(); it < imgToDelete.end(); ++it) { @@ -112,11 +114,11 @@ bool Operation::isValidImgWnd(const genericinterface::ImageWindow* imgWnd) const return (dynamic_cast<const StandardImageWindow*>(imgWnd) != NULL); } -void DoubleOperation::operator()(const ImageWindow* currentWnd, vector<ImageWindow*>& wndList) { +void DoubleOperation::operator()(const ImageWindow* currentWnd, const vector<const ImageWindow*>& wndList) { const DoubleImageWindow* curImgWnd = dynamic_cast<const DoubleImageWindow*>(currentWnd); const Image_t<double>* image = curImgWnd ? curImgWnd->getImage() : NULL; map<const Image_t<double>*, string> imgList; - for(vector<ImageWindow*>::iterator it = wndList.begin(); it != wndList.end(); ++it) { + for(vector<const ImageWindow*>::const_iterator it = wndList.begin(); it != wndList.end(); ++it) { const DoubleImageWindow* imgWnd = dynamic_cast<const DoubleImageWindow*>(*it); if(imgWnd) { imgList.insert(pair<const Image_t<double>*, string>(imgWnd->getImage(), imgWnd->windowTitle().toStdString())); diff --git a/core/Operation.h b/core/Operation.h index b970a60ed22be54581928de88977973af5e14f78..148a194161baae8f8d9f168211c19f26e9a93662 100644 --- a/core/Operation.h +++ b/core/Operation.h @@ -23,58 +23,208 @@ #include <map> #include <string> -#include "Output.h" #include "Image.h" class QWidget; -class EIImageService; namespace genericinterface { class ImageWindow; + class WindowService; } +/** + * @brief The base class for all kind of operation. + * + * A GenericOperation run an image-processing algorithm, it may take some images and parameters as input and return some images, text or other widgets as output.\n + * For implementing an operation working with standard 8bit unsigned integer Image (ie Image_t<uint8_t> or simply Image), see the Operation class.\n + * For implementing an operation working with double-precision floating point Image (ie Image_t<double>), see the DoubleOperation class.\n + * This class is a generic class and should not be directly used except for creating a generic operation (ie an operation working on different type of Image).\n + * For an exemple of a true generic operation class, see the PointOp implementation in eiimage source code. + */ class GenericOperation { public: +/** + * @brief Constructor + * + * @param name The name of the operation, as it should be displayed to the user. + */ GenericOperation(std::string name) : _name(name), _ws(NULL), _curImgWnd(NULL) {} + /** + * @brief Name accessor + * + * @return std::string The name of the operation. + */ inline std::string getName() { return _name; } - virtual void operator()(const genericinterface::ImageWindow* currentWnd, std::vector<genericinterface::ImageWindow*>&) = 0; - virtual void operator()(EIImageService*); + /** + * @brief Pure virtual function call operator containing the implementation of the operation process. + * + * @param currentWnd A pointer to the ImageWindow having the user's focus if such exists, a NULL pointer otherwise. + * @param imgWndList A vector containing all the ImageWindow existing in the application. + */ + virtual void operator()(const genericinterface::ImageWindow* currentWnd, const std::vector<const genericinterface::ImageWindow*>& imgWndList) = 0; + /** + * @brief The function call operator which is called by the application, it is the entry point of this operation and it calls the pure virtual function call operator. + * + * @param ws The eiimage implementation of the genericinterface::WindowService + */ + virtual void operator()(genericinterface::WindowService* ws); + /** + * @brief This method should return wether this Operation need the currentWnd parameter. + * + * If this method returns true, the application guarantees that this operation cannot be called without the user having the focus on a valid image window (see isValidImgWnd()), therefore the parameter currentWnd given to the function call operation cannot be NULL. \n + * If this method returns false, this operation can be called wether or not there is a valid current image window, and so the currentWnd parameter may be a NULL pointer. + * + * @return bool Wether this operation need a valid current ImageWindow. + * \sa isValidImgWnd() + */ virtual bool needCurrentImg() const = 0; + /** + * @brief This method should determine wether an ImageWindow is valid or not for this operation. + * + * This method is used to check the current ImageWindow if needCurrentImg() returns true. + * It is also used to generate the ImageWindow list given to the function call operation, it is guarenteed that all ImageWindow contained in the imgWndList passed this test. + * + * @param imgWnd The ImageWindow to check. + * @return bool True if imgWnd is valid for this operation, false otherwise. + * \sa needCurrentImg() + */ virtual bool isValidImgWnd(const genericinterface::ImageWindow* imgWnd) const = 0; protected: - void outImage(imagein::Image*, std::string title = ""); - void outDoubleImage(imagein::Image_t<double>*, std::string title = "", bool norm=false, bool log=false); + + + /** + * @brief %Output a standard Image to the user interface. + + * This method is used inside the operation process to output a standard Image to the user interface. + * + * @param img The image to output + * @param title A title to distinguished this image from other images. + */ + void outImage(imagein::Image* img, std::string title = ""); + + + /** + * @brief %Output a floating point Image to the user interface. + + * This method is similar to outImage but is used to output a floating point Image while specifying the display parameters. + + * @param img The floating point image to output + * @param title A title to distinguished this image from other images + * @param norm Wether to display a normalized version of the Image (doesn't affect the data contained in the image, compatible with any other options). + * @param log Wether to display a log scaled version of the Image (doesn't affect the data contained in the image, compatible with any other options). + * @param logScale The logarithm scale constant to apply if the Image is displayed using log. scale (value from 8^-3 to 8^3, see genericinterface::DoubleImageWindow for more details). + * @param abs wether to display an absolute value version of the Image (doesn't affect the data contained in the image, compatible with any other options). + */ + void outDoubleImage(imagein::Image_t<double>* img, std::string title = "", bool norm=false, bool log=false, double logScale = 1., bool abs = false); + + + /** + * @brief %Output some text to th user interface. + * + * @param std::string The text to output, may contain multiple lines. + */ void outText(std::string); - std::string _name; - EIImageService* _ws; - genericinterface::ImageWindow* _curImgWnd; + + std::string _name; /**< The name of the operation */ + genericinterface::WindowService* _ws; /**< A pointer to the eiimage window service, only valid inside the function call operator */ + genericinterface::ImageWindow* _curImgWnd; /**< A pointer to the current image window, only valid inside the function call operator */ private: + /** + * @brief Private method used to output an ImageWindow, this method is called inside outImage and outDoubleImage. + * + * @param imgWnd The ImageWindow to output + * @param title The title of the ImageWindow + */ void outImgWnd(genericinterface::ImageWindow* imgWnd, std::string title); }; +/** + * @brief Implementation of GenericOperation specialized in standard Image. + * + * An Operation only gets as parameters only StandardImageWindow containing standard Image. \n + * Therefore the manipulation of ImageWindow is not need anymore, an implementation of Operation only manipulates standard Image instead of ImageWindow. + * + */ class Operation : public GenericOperation { public: + /** + * @brief Constructor + * + * @param name The name of the operation + */ Operation(std::string name) : GenericOperation(name) {} - virtual void operator()(const genericinterface::ImageWindow* currentWnd, std::vector<genericinterface::ImageWindow*>&); - virtual void operator()(const imagein::Image*, const std::map<const imagein::Image*, std::string>&) = 0; + + /** + * @brief Implementation of GenericOperation::operator()() + * This implementation get the standard images contained in the image windows and pass them to the other function call operator. + * + * @param currentWnd see GenericOperation::operator()() + * @param wndList see GenericOperation::operator()() + * \sa operator()(const imagein::Image*, const std::map<const imagein::Image*, std::string>&) + */ + virtual void operator()(const genericinterface::ImageWindow* currentWnd, const std::vector<const genericinterface::ImageWindow*>& wndList); + + /** + * @brief Pure virtual function call operator containing the implementation of the operation process. + * + * @param img A pointer to the Image having the user's focus if such exists, a NULL pointer otherwise. + * @param imgList A map containing all the opened Image in the application and their respective names. + */ + virtual void operator()(const imagein::Image* img, const std::map<const imagein::Image*, std::string>& imgList) = 0; + + /** + * @brief Implementation of GenericOperation::isValidImgWnd() + * + * @param imgWnd The ImageWindow to check + * @return bool True if imgWnd is a StandardImageWindow instance, false otherwise. + */ virtual bool isValidImgWnd(const genericinterface::ImageWindow* imgWnd) const; protected: - imagein::Image* _currentImg; + imagein::Image* _currentImg; /**< The current image, only valid inside the function call operator */ }; +/** + * @brief Implementation of GenericOperation specialized in double-precision floating point Image. + * + */ class DoubleOperation : public GenericOperation { public: +/** + * @brief Constructor + * + * @param name Name of the operation + */ DoubleOperation(std::string name) : GenericOperation(name) {} - virtual void operator()(const genericinterface::ImageWindow* currentWnd, std::vector<genericinterface::ImageWindow*>&); + /** + * @brief Implementation of GenericOperation::operator()() + * This implementation get the floating point images contained in the image windows and pass them to the other function call operator. + * + * @param currentWnd see GenericOperation::operator()() + * @param wndList see GenericOperation::operator()() + * \sa operator()(const imagein::Image*, const std::map<const imagein::Image*, std::string>&) + */ + virtual void operator()(const genericinterface::ImageWindow* currentWnd, const std::vector<const genericinterface::ImageWindow*>&); + /** + * @brief Pure virtual function call operator containing the implementation of the operation process. + * + * @param img A pointer to the Image having the user's focus if such exists, a NULL pointer otherwise. + * @param imgList A map containing all the opened Image in the application and their respective names. + */ virtual void operator()(const imagein::Image_t<double>*, const std::map<const imagein::Image_t<double>*, std::string>&) = 0; + /** + * @brief Implementation of GenericOperation::isValidImgWnd() + * + * @param imgWnd The ImageWindow to check + * @return bool True if imgWnd is a DoubleImageWindow instance, false otherwise. + */ virtual bool isValidImgWnd(const genericinterface::ImageWindow* imgWnd) const; protected: - imagein::Image_t<double>* _currentImg; + imagein::Image_t<double>* _currentImg; /**< The current image, only valid in the function call operator */ }; #endif //!EIIMAGE_OPERATION_H diff --git a/core/Parameter.h b/core/Parameter.h index 7829d7c9c73eb48c47293a0e98a8517e4b254693..41a5f5d8ece64dc74d62fb5776c0310508c6dfb7 100644 --- a/core/Parameter.h +++ b/core/Parameter.h @@ -25,15 +25,32 @@ #include "Input.h" template<typename T> +/** + * @brief Parameter is a generic partial implementation of Input + * + * This class gather common code of most of the Input implementations. + * + */ class Parameter : public Input { public: +/** + * @brief Constructor + * + * @param name Name of the input, as it will be displayed to the user + * @param ptr Pointer to the location in which to store the given input. + */ Parameter(std::string name, T* ptr = NULL) : _ptr(ptr), _name(name) {} + /** + * @brief Copy constructor + * + * @return Parameter<T> Copy ot this instance + */ virtual Parameter<T>* clone() const = 0; protected: - T* _ptr; - std::string _name; + T* _ptr; /**< Pointer to the location in which to store the input */ + std::string _name; /**< Name of the input */ friend class PlugOperation; diff --git a/core/PlugOperation.cpp b/core/PlugOperation.cpp index 14f59bfd3f8e75a75427b3e51bcb361de4948e42..669585fa6af2950ab912b6552bd8326649acae14 100644 --- a/core/PlugOperation.cpp +++ b/core/PlugOperation.cpp @@ -21,14 +21,18 @@ #include <QWidget> #include <QVBoxLayout> #include <QPushButton> +#include <QApplication> #include "PlugOperation.h" +#include <Widgets/ImageWidgets/StandardImageWindow.h> +#include <Widgets/ImageWidgets/DoubleImageWindow.h> using namespace std; using namespace imagein; +using namespace genericinterface; -PlugOperation::PlugOperation(string name) : Operation(name), _needCurrentImg(false), _currentImg(NULL) { +PlugOperation::PlugOperation(string name) : GenericOperation(name), _needCurrentImg(false), _currentStdImg(NULL), _currentDblImg(NULL), _doubleCurrentImg(false) { } void PlugOperation::addInput(Input* input) { @@ -39,30 +43,47 @@ void PlugOperation::addInput(const Input& input) { this->_inputs.push_back(input.clone()); } -void PlugOperation::addOutput(const Output& output) { - _outputs.push_back(output.clone()); +bool PlugOperation::isValidImgWnd(const genericinterface::ImageWindow* imgWnd) const { + if(!this->needCurrentImg()) { + return true; + } + if(_doubleCurrentImg) { + const DoubleImageWindow* diw = dynamic_cast<const DoubleImageWindow*>(imgWnd); + return diw != NULL; + } + else { + const StandardImageWindow* siw = dynamic_cast<const StandardImageWindow*>(imgWnd); + return siw != NULL; + } } +void PlugOperation::operator()(const genericinterface::ImageWindow* currentWnd, const std::vector<const genericinterface::ImageWindow*>& imgWndList) { -void PlugOperation::operator()(const Image* currentImg, const std::map<const Image*, std::string>&) { - if(this->needCurrentImg()) { - if(currentImg==NULL) return; - *_currentImg = *currentImg; + if(_doubleCurrentImg) { + const DoubleImageWindow* diw = dynamic_cast<const DoubleImageWindow*>(currentWnd); + if(diw ==NULL) return; + *_currentDblImg = *diw->getImage(); + } + else { + const StandardImageWindow* siw = dynamic_cast<const StandardImageWindow*>(currentWnd); + if(siw == NULL) return; + *_currentStdImg = *siw->getImage(); + } } if(_inputs.size()>0) { QDialog* dialog = new QDialog(); - dialog->setWindowTitle("Paramètres"); + dialog->setWindowTitle(qApp->translate("PlugOperation", "Parameters")); dialog->setMinimumWidth(160); QVBoxLayout* layout = new QVBoxLayout(); dialog->setLayout(layout); for(vector<Input*>::iterator it = _inputs.begin(); it < _inputs.end(); ++it) { - (*it)->fillDialog(dialog); + (*it)->fillDialog(dialog, currentWnd, imgWndList); } - QPushButton *okButton = new QPushButton("Valider", dialog); + QPushButton *okButton = new QPushButton(qApp->translate("PlugOperation", "Validate"), dialog); okButton->setDefault(true); layout->addWidget(okButton); QObject::connect(okButton, SIGNAL(clicked()), dialog, SLOT(accept())); @@ -79,11 +100,5 @@ void PlugOperation::operator()(const Image* currentImg, const std::map<const Ima } } - - _outputs.clear(); this->operation(); - - for(vector<Output*>::iterator it = _outputs.begin(); it < _outputs.end(); ++it) { -// result.push_back((*it)->getWidget()); - } } diff --git a/core/PlugOperation.h b/core/PlugOperation.h index 4d54bc3dba3a42f137d26a804283f56972ccf996..2baa8da720fda38c32da8a36df35516084c82d1b 100644 --- a/core/PlugOperation.h +++ b/core/PlugOperation.h @@ -25,16 +25,30 @@ #include "Input.h" #include "Parameter.h" -#include "Output.h" -#include "Image.h" +#include <Image.h> #include "Operation.h" class QWidget; -struct CurrentImg { -}; +/** + * @brief Empty class used to identify the current standard image input. + * + */ +struct CurrentImg {}; +/** + * @brief Empty class used to identify the current double image input. + * + */ +struct CurrentDoubleImg {}; -class PlugOperation : public Operation { +/** + * @brief A PlugOperation is the base class for all Plugin's operations + * + * The PlugOperation class is used to easily implement an operation without writing user-interface code.\n + * All the parameters of a PlugOperation must be defined in it's constructor using the addParam() methods. \n + * The operation() method must implement the image processing algorithm and output some data using methods such as GenericOperation::outImage() or GenericOperation::outText(). + */ +class PlugOperation : public GenericOperation { private: template<class D, class B> struct Derived_from { static void constraints(D* p) { B* pb = p; } @@ -42,22 +56,46 @@ class PlugOperation : public Operation { }; public: +/** + * @brief A PlugOperation + * + * @param name Name of the operation + */ PlugOperation(std::string name); - void operator()(const imagein::Image*, const std::map<const imagein::Image*, std::string>&); - + void operator()(const genericinterface::ImageWindow* currentWnd, const std::vector<const genericinterface::ImageWindow*>& imgWndList); virtual bool needCurrentImg() const { return _needCurrentImg; } - + virtual bool isValidImgWnd(const genericinterface::ImageWindow* imgWnd) const; + protected: + /** + * @brief This method is called after the user specified all the operation's parameters, it should contains the operation's algorithm. + * + */ virtual void operation() = 0; + /** + * @brief Add an input to the PlugOperation. + * + * @param input The input to add. + */ void addInput(Input* input); + /** + * @brief Add an input to the PlugOperation. + * + * @param input The input to add. + */ void addInput(const Input& input); - void addOutput(const Output& output); template<typename T, class C> + /** + * @brief Add a Parameter input to the PlugOperation + * + * @param param The parameter to add. + * @param C::ptr A pointer to the location where the input will be stored. + */ void addParam(const Parameter<T>& param, T C::* ptr) { - Derived_from<C, Operation>(); + Derived_from<C, GenericOperation>(); C* object = dynamic_cast<C*>(this); if(object==NULL) { throw "The parameter's pointer doesn't belong to the class which add it"; @@ -68,21 +106,45 @@ class PlugOperation : public Operation { } template<class C> + /** + * @brief Add the current standard image as a parameter + * + * @param C::ptr A pointer to the location where the input will be stored. + */ void addParam(const CurrentImg&, imagein::Image C::* ptr) { - Derived_from<C, Operation>(); + Derived_from<C, GenericOperation>(); C* object = dynamic_cast<C*>(this); if(object==NULL) { throw "The parameter's pointer doesn't belong to the class which add it"; } _needCurrentImg = true; - _currentImg = &(object->*ptr); + _doubleCurrentImg = false; + _currentStdImg = &(object->*ptr); } - + + template<class C> + /** + * @brief Add the current double image as a parameter + * + * @param C::ptr A pointer to the location where the input will be stored. + */ + void addParam(const CurrentDoubleImg&, imagein::Image_t<double> C::* ptr) { + Derived_from<C, GenericOperation>(); + C* object = dynamic_cast<C*>(this); + if(object==NULL) { + throw "The parameter's pointer doesn't belong to the class which add it"; + } + _needCurrentImg = true; + _doubleCurrentImg = true; + _currentDblImg = &(object->*ptr); + } + private: - std::vector<Input*> _inputs; - std::vector<Output*> _outputs; - bool _needCurrentImg; - imagein::Image* _currentImg; + std::vector<Input*> _inputs; /**< List of the PlugOperation's inputs. */ + bool _needCurrentImg; /**< Wether this operation need a current image of not. */ + imagein::Image* _currentStdImg; /**< Pointer to the current standard Image if such exists, NULL otherwise. */ + imagein::Image_t<double>* _currentDblImg; /**< Point to the current double Image if such exists, NULL otherwise. */ + bool _doubleCurrentImg; /**< Wether this operation need a double wurrent image or a standard current image. */ }; #endif //!EIIMAGE_OPERATION_H diff --git a/core/Plugin.h b/core/Plugin.h index c8fdedd97d71432912894bfe17a0e15127b8844c..3282af05c359b4710c4df8cc021e1f3b68e2e1ff 100644 --- a/core/Plugin.h +++ b/core/Plugin.h @@ -26,14 +26,30 @@ #include "OpSet.h" #include "PlugOperation.h" +/** + * @brief A Plugin is an implementation of OpSet containing PlugOperation + * + * Unlike a BuiltinOpSet, a Plugin should only contain PlugOperation + */ class Plugin : public OpSet { public: +/** + * @brief Constructor + * + * @param name The name of the plugin, as it should be displayed to the user. + */ Plugin(std::string name); + std::vector<GenericOperation*> getOperations(); - void addOperation(PlugOperation*); + /** + * @brief Add a PlugOperation to this Plugin. + * + * @param The operation to add. + */ + void addOperation(PlugOperation* op); private: - std::vector<GenericOperation*> _operations; + std::vector<GenericOperation*> _operations; /**< List of all the operations stored in this OpSet */ }; #endif //!EIIMAGE_PLUGIN_H diff --git a/plugins/Segmentation/segmentation.cpp b/plugins/Segmentation/segmentation.cpp index 4cc39217070639514b8ce8f35b219be71d6c9764..36b8a3f8a5b211daf116d9b2f652a2c95b43c23c 100644 --- a/plugins/Segmentation/segmentation.cpp +++ b/plugins/Segmentation/segmentation.cpp @@ -30,7 +30,6 @@ #include "Plugin.h" #include "ImgParam.h" #include "IntParam.h" -#include "ImgOutput.h" using namespace std; using namespace imagein; @@ -73,6 +72,7 @@ class Dithering : public PlugOperation { public: Dithering() : PlugOperation("Dithering") { this->addParam(CurrentImg(), &Dithering::img); +// this->addParam(ImgParam("Image"), &Dithering::img); } void operation() {