void ThumbnailsCommand::Execute()
{
        NotificarProgreso(0.05f,_Std("Creating Thumbnail..."));
        m_Error = true;
        GTRACE("Arrancando comando generar thumbnails  " << m_pThumbParams->m_ruta)
        //std::string tarea_Std("Generando thumbnails...");
        //pillamos el uid
        m_pThumbParams->m_fileModel = GNC::GCS::HistoryController::Instance()->GetFileModel(m_pThumbParams->m_file_pk);
        if(m_pThumbParams->m_fileModel.sopiuid.empty()) {
                wxBitmap bmp = GinkgoResourcesManager::History::GetIcoUnknownFile();
                m_pThumbParams->m_wxImg = new wxImage();
                (*m_pThumbParams->m_wxImg) = bmp.ConvertToImage();
                GuardarImagen();
                m_Error = false;
                return;
        }
        //if is wado linked...
        if (m_pThumbParams->m_fileModel.location == GNC::GCS::IHistoryController::TL_WadoLinked) {
                wxBitmap bmp = GinkgoResourcesManager::History::GetIcoWadoLinkedPreview();
                m_pThumbParams->m_wxImg = new wxImage();
                (*m_pThumbParams->m_wxImg) = bmp.ConvertToImage();
                m_Error = false;
                return;
        }
        //comprobar si el thumbnail ya estaba generado
        m_pThumbParams->m_wxImg = GetImageFromBD();
        if(m_pThumbParams->m_wxImg != NULL) {
                GTRACE("Saliendo generar thumbnails salida2  " << m_pThumbParams->m_ruta);
                NotificarProgreso(1.0f,_Std("Creating Thumbnail..."));
                m_Error = false;
                return;
        } else {
                //try to make thumbnail with extensions...
                ::GNC::ControladorExtensiones::ListaModulos listaModulos = ::GNC::ControladorExtensiones::Instance()->Modulos();
                for(GNC::ControladorExtensiones::IteradorListaModulos it=listaModulos.begin(); it!=listaModulos.end(); ++it) {
                        GNC::GCS::IModuleController* modulo = (*it).second;
                        GNC::GCS::Ptr<ImgProxy<UCHAR3> >pImgCapture(new ImgProxy<UCHAR3>());
                        if (modulo->MakeThumbnail(m_pThumbParams->m_fileModel, *pImgCapture)) {
                                wxImage* pImage = new wxImage(pImgCapture->anchura, pImgCapture->altura, (unsigned char*)pImgCapture->data, true);
                                if (pImage->IsOk()) {
                                        double scaleX = ((double) SIZE_THUMBNAILS)/((double) pImgCapture->anchura);
                                        double scaleY = ((double) SIZE_THUMBNAILS)/((double) pImgCapture->altura);

                                        if (scaleX < 1.0 || scaleY < 1.0) {
                                                double scale = wxMin(scaleX, scaleY);
                                                int newWidth = (int) (scale * pImgCapture->anchura);
                                                int newHeight = (int) (scale * pImgCapture->altura);
                                                m_pThumbParams->m_wxImg = new wxImage(pImage->Scale(newWidth, newHeight, wxIMAGE_QUALITY_HIGH));
                                        } else {
                                                m_pThumbParams->m_wxImg = new wxImage(*pImage);
                                        }
                                        delete pImage;

                                        GuardarImagen();
                                        m_Error = false;
                                        return;
                                }
                        }
                }

                if (m_pThumbParams->m_fileModel.tsuid== GKUID_MPEG2MainProfileAtMainLevelTransferSyntax || m_pThumbParams->m_fileModel.tsuid == GKUID_MPEG2MainProfileAtHighLevelTransferSyntax) {
                        wxBitmap bmp = GinkgoResourcesManager::History::GetMoviePreview();
                        m_pThumbParams->m_wxImg = new wxImage();
                        (*m_pThumbParams->m_wxImg) = bmp.ConvertToImage();
                        GuardarImagen();
                        m_Error = false;
                        return;
                }
                if (m_pThumbParams->m_fileModel.sopcuid == GKUID_EncapsulatedPDFStorage) {
                        wxBitmap bmp = GinkgoResourcesManager::History::GetPDFPreview();
                        m_pThumbParams->m_wxImg = new wxImage();
                        (*m_pThumbParams->m_wxImg) = bmp.ConvertToImage();
                        m_Error = false;
                        return;
                }

                double size[2]   = {0.0, 0.0};
                int dimensions[3] = {0, 0, 0};
                double spacing[3] = {0.0, 0.0, 0.0};
                double origin[3] = {0.0, 0.0, 0.0};

                size[0] = SIZE_THUMBNAILS;
                size[1] = SIZE_THUMBNAILS;

                {
                        //esto es una nyapa para recuperarnos de errores, antes de leer guardamos en bbdd una imagen negra, si finalmente
                        //el thumbnail se genera bien pues se mete, si no pues se quedara con unknown
                        wxImage img = GinkgoResourcesManager::History::GetIcoUnknownFile().ConvertToImage();
                        m_pThumbParams->m_wxImg = &img;
                        GuardarImagen();
                        m_pThumbParams->m_wxImg = NULL;
                }

                typedef itk::RGBPixel<unsigned char> PixelType;
                typedef itk::Image< PixelType,  2 > ImageType;

                typedef itk::ImageRegionConstIterator< ImageType > ImageIteratorType;

                typedef itk::VTKImageToImageFilter<ImageType> TipoFiltro;

                ImageType::SizeType outputSize;
                ImageType::SpacingType outputSpacing;
                ImageType::PointType outputOrigin;

                vtkSmartPointer<vtkImageShiftScale> normalizeFilter = vtkSmartPointer<vtkImageShiftScale>::New();

                outputSize[0] = size[0];
                outputSize[1] = size[1];

                unsigned long imgsize = outputSize[0] * outputSize[1] * sizeof(unsigned char) * 3;
                unsigned char* data = new unsigned char[imgsize];

                try {

                        GNC::StreamingLoader loader;

                        loader.SetInput(m_pThumbParams->m_fileModel.real_path);

                        loader.GetDimensions(dimensions);
                        loader.GetSpacing(spacing);
                        loader.SetOutputOrigin(origin);

                        vtkSmartPointer<vtkImageReslice> pReslice = vtkSmartPointer<vtkImageReslice>::New();
                        TipoFiltro::Pointer VTK2ITKfiltro = TipoFiltro::New();

                        vtkSmartPointer<vtkMatrix4x4> resliceAxes = vtkSmartPointer<vtkMatrix4x4>::New();


                        if ( dimensions[0] == 0 || dimensions[1] == 0 || spacing[0] == 0 || spacing[1] == 0) {
                                if ( !loader.IsSignalFile()) {
                                        m_Error = true;
                                        delete[] data;
                                        data = NULL;
                                        LOG_WARN("GenerarThumbnails", "Error: imagen de tamaƱo 0, generaciĆ³n ignorada.");
                                        return;
                                }

                                NotificarProgreso(0.8f,_Std("Creating Thumbnail..."));

                                memset(data, 0, imgsize);
                                double x, y;
                                unsigned int ix, iy;
                                const double resx = M_PI * 4.0 / (double) outputSize[0];
                                const double resy = (double) 0.25 * outputSize[1];
                                const double sy = (double) 0.5 * outputSize[1];

                                for (ix = 0; ix < outputSize[0]; ++ix) {

                                        x = ((double) ix);
                                        y = resy * std::sin(x * resx);
                                        y += sy;
                                        iy = std::max<int>(0, std::min<int>(outputSize[0] - 1, (int) std::floor(y + 0.5)) );

                                        unsigned char* pixel = data + (3 * (iy * outputSize[0] + ix));
                                        pixel[0] = 0;
                                        pixel[1] = 255;
                                        pixel[2] = 128;
                                }

                        } else {


                                pReslice->SetInputConnection(loader.GetOutputPort());
                                pReslice->SetOutputDimensionality(2);
                                pReslice->SetResliceAxesDirectionCosines(1, 0, 0,
                                                0, 1, 0,
                                                0, 0, 1);
                                outputSize[0] = size[0];
                                outputSize[1] = size[1];

                                double dInputSize[3];
                                dInputSize[0] = (double)dimensions[0];
                                dInputSize[1] = (double)dimensions[1];
                                dInputSize[2] = 1.0;

                                double dOutputSize[3];
                                dOutputSize[0] = (double)outputSize[0];
                                dOutputSize[1] = (double)outputSize[1];
                                dOutputSize[2] = 1.0;

                                double sX = dOutputSize[0] / dInputSize[0];
                                double sY = dOutputSize[1] / dInputSize[1];

                                double s = std::min<double>(sX, sY);

                                double dOutputSpacing[3];
                                dOutputSpacing[0] = spacing[0] / s;
                                dOutputSpacing[1] = spacing[1] / s;
                                dOutputSpacing[2] = spacing[2];

                                pReslice->SetOutputExtent(0, dOutputSize[0] - 1, 0, dOutputSize[1] - 1,  0, 1);
                                pReslice->SetOutputSpacing(dOutputSpacing);
                                //moves image vertical or horizontal to center thumbnail. x + => left; - => right. y + => up; - => down
                                //formula is tested with color images and images with spacing and origin
                                origin[0] = (((s - sX) * dInputSize[0] / 2.0f) / s) * spacing[0];
                                origin[1] = (((s - sY) * dInputSize[1] / 2.0f) / s)  * spacing[0];
                                pReslice->SetOutputOrigin(origin);

                                pReslice->SetInterpolationModeToCubic();

                                pReslice->Update();

                                vtkImageData *timg = pReslice->GetOutput();

                                if(timg->GetNumberOfScalarComponents() > 1) {
                                        normalizeFilter->SetInputConnection(pReslice->GetOutputPort());
                                        normalizeFilter->SetOutputScalarTypeToUnsignedChar();

                                        if (timg->GetScalarType() != VTK_UNSIGNED_CHAR) {
                                                double range[2];
                                                timg->GetScalarRange(range);

                                                double diff = range[1]-range[0];
                                                if (diff > std::numeric_limits<double>::epsilon()) {
                                                        normalizeFilter->SetShift(-range[0]);
                                                        normalizeFilter->SetScale(255.0/(range[1]-range[0]));
                                                }
                                        }
                                        normalizeFilter->Update();
                                        VTK2ITKfiltro->SetInput(normalizeFilter->GetOutput());

                                } else {
                                        vtkSmartPointer<vtkImageMapToColors> pImageMap = vtkSmartPointer<vtkImageMapToColors>::New();

                                        pImageMap->SetInputConnection(pReslice->GetOutputPort());

                                        vtkSmartPointer<vtkLookupTable> pLookupTable = vtkLookupTableManager::GetLinearLookupTable();

                                        pImageMap->SetLookupTable(pLookupTable);
                                        pImageMap->SetOutputFormatToRGB();

                                        if (timg->GetNumberOfScalarComponents() == 1) {

                                                double window, level;
                                                if (loader.GetDefaultWindowLevel(window,level) && window != 0.0) {
                                                        double v_min = (level) - 0.5 * window;
                                                        double v_max = level + 0.5 * window;
                                                        pLookupTable->SetRange(v_min, v_max);
                                                } else {
                                                        double range[2];
                                                        timg->GetScalarRange(range);

                                                        double diff = range[1]-range[0];

                                                        window = range[1]-range[0];
                                                        level = 0.5*(range[1]+range[0]);

                                                        if (diff > std::numeric_limits<double>::epsilon()) {
                                                                double v_min = (level) - 0.5 * window;
                                                                double v_max = level + 0.5 * window;
                                                                pLookupTable->SetRange(v_min, v_max);
                                                        }
                                                }
                                        }
                                        pImageMap->SetLookupTable(pLookupTable);

                                        pImageMap->Update();
                                        VTK2ITKfiltro->SetInput( pImageMap->GetOutput());
                                }
                                NotificarProgreso(0.6f,_Std("Creating Thumbnail..."));

                                VTK2ITKfiltro->GetImporter()->UpdateLargestPossibleRegion();

                                const ImageType* img = VTK2ITKfiltro->GetOutput();
                                NotificarProgreso(0.8f,_Std("Creating Thumbnail..."));

                                ImageType::RegionType region = img->GetLargestPossibleRegion();

                                ImageIteratorType it (img, region);

                                std::cout << "imgsize = " << imgsize << std::endl;

                                std::cout << "region = ";
                                region.Print(std::cout);
                                std::cout << std::endl;

                                unsigned long off = 0;
                                for (it.GoToBegin(); !it.IsAtEnd() && off < imgsize; ++it) {
                                        const ImageType::PixelType& pixel = it.Value();
                                        data[off++] = pixel.GetRed();
                                        data[off++] = pixel.GetGreen();
                                        data[off++] = pixel.GetBlue();
                                }
                        }

                        m_pThumbParams->m_wxImg = new wxImage(outputSize[0], outputSize[1], data, false);
                        GuardarImagen();
                        NotificarProgreso(1.0f,_Std("Generating thumbnail ..."));

                        m_Error = false;

                } catch (GNC::GCS::ControladorCargaException &ex1) {
                        LOG_ERROR("GenerarThumnails", "Unable to create thumbnail for file [" << m_pThumbParams->m_file_pk << "]: " << ex1.str());
                        if (data != NULL) {
                                delete[] data;
                                data = NULL;
                        }
                        //si se cancela el comando
                        return;
                } catch(itk::ExceptionObject& ex2) {
                        LOG_ERROR("GenerarThumnails", "Unable to create thumbnail for file [" << m_pThumbParams->m_file_pk << "]: " << ex2.GetDescription());
                        //std::string descr = ex2.GetDescription();
                        if (data != NULL) {
                                delete[] data;
                                data = NULL;
                        }
                        return;
                } catch(std::exception &ex3) {
                        LOG_ERROR("GenerarThumnails", "Unable to create thumbnail for file [" << m_pThumbParams->m_file_pk << "]: " << ex3.what());
                        //std::string descr = ex3.what();
                        //si se cancela el comando
                        if (data != NULL) {
                                delete[] data;
                                data = NULL;
                        }
                        return;
                } catch(...) {
                        LOG_ERROR("GenerarThumnails", "Unable to create thumbnail for file [" << m_pThumbParams->m_file_pk << "]: Internal error" );
                        //si se cancela el comando
                        if (data != NULL) {
                                delete[] data;
                                data = NULL;
                        }
                        return;
                }
        }
}