From 414ff7e24f04f408560ee48a175ddb27119ac899 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sacha=20Percot-T=C3=A9tu?= <zakinster@zakinster.com> Date: Wed, 19 Sep 2012 18:14:35 +0200 Subject: [PATCH] Added the Pyramid algorithms and operations --- app/Algorithms/Pyramid.cpp | 711 ++++++++++++++++++++++++ app/Algorithms/Pyramid.h | 73 +++ app/Operations/InversePyramidDialog.cpp | 54 ++ app/Operations/InversePyramidDialog.h | 46 ++ app/Operations/InversePyramidDialog.ui | 166 ++++++ app/Operations/InversePyramidOp.cpp | 70 +++ app/Operations/InversePyramidOp.h | 35 ++ app/Operations/PyramidDialog.cpp | 62 +++ app/Operations/PyramidDialog.h | 47 ++ app/Operations/PyramidDialog.ui | 219 ++++++++ app/Operations/PyramidOp.cpp | 86 +++ app/Operations/PyramidOp.h | 35 ++ 12 files changed, 1604 insertions(+) create mode 100644 app/Algorithms/Pyramid.cpp create mode 100644 app/Algorithms/Pyramid.h create mode 100644 app/Operations/InversePyramidDialog.cpp create mode 100644 app/Operations/InversePyramidDialog.h create mode 100644 app/Operations/InversePyramidDialog.ui create mode 100644 app/Operations/InversePyramidOp.cpp create mode 100644 app/Operations/InversePyramidOp.h create mode 100644 app/Operations/PyramidDialog.cpp create mode 100644 app/Operations/PyramidDialog.h create mode 100644 app/Operations/PyramidDialog.ui create mode 100644 app/Operations/PyramidOp.cpp create mode 100644 app/Operations/PyramidOp.h diff --git a/app/Algorithms/Pyramid.cpp b/app/Algorithms/Pyramid.cpp new file mode 100644 index 0000000..d865a26 --- /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 0000000..4ff5433 --- /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/InversePyramidDialog.cpp b/app/Operations/InversePyramidDialog.cpp new file mode 100644 index 0000000..b8f4712 --- /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 0000000..3a29ec3 --- /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 0000000..6338a5c --- /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>213</height> + </rect> + </property> + <property name="windowTitle"> + <string>Dialog</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 0000000..f0930c3 --- /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", "Reconstruct pyramid").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 0000000..2c56a1b --- /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/PyramidDialog.cpp b/app/Operations/PyramidDialog.cpp new file mode 100644 index 0000000..185f65d --- /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 0000000..9065a0f --- /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 0000000..d0c85b4 --- /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>259</width> + <height>231</height> + </rect> + </property> + <property name="windowTitle"> + <string>Dialog</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 0000000..eb52b7c --- /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", "Create pyramid").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 0000000..88dbe6a --- /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 -- GitLab