void PanoOptimizePage::process() { QMutexLocker lock(&d->progressMutex); d->title->setText(i18n("<qt>" "<p>Optimization is in progress, please wait.</p>" "<p>This can take a while...</p>" "</qt>")); d->horizonCheckbox->hide(); // d->projectionAndSizeCheckbox->hide(); d->progressTimer->start(300); connect(d->mngr->thread(), SIGNAL(stepFinished(DigikamGenericPanoramaPlugin::PanoActionData)), this, SLOT(slotPanoAction(DigikamGenericPanoramaPlugin::PanoActionData))); connect(d->mngr->thread(), SIGNAL(jobCollectionFinished(DigikamGenericPanoramaPlugin::PanoActionData)), this, SLOT(slotPanoAction(DigikamGenericPanoramaPlugin::PanoActionData))); d->mngr->resetAutoOptimisePto(); d->mngr->resetViewAndCropOptimisePto(); d->mngr->thread()->optimizeProject(d->mngr->cpCleanPtoUrl(), d->mngr->autoOptimisePtoUrl(), d->mngr->viewAndCropOptimisePtoUrl(), d->horizonCheckbox->isChecked(), d->mngr->gPano(), d->mngr->autoOptimiserBinary().path(), d->mngr->panoModifyBinary().path()); }
void AVDemuxThread::frameDeliveredOnStepForward() { AVThread *thread = video_thread ? video_thread : audio_thread; Q_ASSERT(thread); QMutexLocker locker(&next_frame_mutex); Q_UNUSED(locker); disconnect(thread, SIGNAL(frameDelivered()), this, SLOT(frameDeliveredOnStepForward())); disconnect(thread, SIGNAL(eofDecoded()), this, SLOT(eofDecodedOnStepForward())); if (user_paused) { pause(true); // restore pause state Q_EMIT requestClockPause(true); // need direct connection // pause both video and audio thread if (video_thread) video_thread->pause(true); if (audio_thread) audio_thread->pause(true); } if (clock_type >= 0) { thread->clock()->setClockAuto(clock_type & 1); thread->clock()->setClockType(AVClock::ClockType(clock_type/2)); clock_type = -1; thread->clock()->updateExternalClock((thread->previousHistoryPts() - thread->clock()->initialValue())*1000.0); } Q_EMIT stepFinished(); }
void AVDemuxThread::eofDecodedOnStepForward() { AVThread *thread = video_thread ? video_thread : audio_thread; Q_ASSERT(thread); QMutexLocker locker(&next_frame_mutex); Q_UNUSED(locker); disconnect(thread, SIGNAL(frameDelivered()), this, SLOT(frameDeliveredOnStepForward())); disconnect(thread, SIGNAL(eofDecoded()), this, SLOT(eofDecodedOnStepForward())); pause(false); end = true; if (clock_type >= 0) { thread->clock()->setClockAuto(clock_type & 1); thread->clock()->setClockType(AVClock::ClockType(clock_type/2)); clock_type = -1; } Q_EMIT stepFinished(); }
void PanoOptimizePage::cleanupPage() { d->canceled = true; disconnect(d->mngr->thread(), SIGNAL(stepFinished(DigikamGenericPanoramaPlugin::PanoActionData)), this, SLOT(slotPanoAction(DigikamGenericPanoramaPlugin::PanoActionData))); disconnect(d->mngr->thread(), SIGNAL(jobCollectionFinished(DigikamGenericPanoramaPlugin::PanoActionData)), this, SLOT(slotPanoAction(DigikamGenericPanoramaPlugin::PanoActionData))); d->mngr->thread()->cancel(); QMutexLocker lock(&d->progressMutex); if (d->progressTimer->isActive()) { d->progressTimer->stop(); d->progressLabel->clear(); } }
void PanoPreviewPage::computePreview() { // Cancel any stitching being processed if (d->stitchingBusy) { cleanupPage(); } QMutexLocker lock(&d->previewBusyMutex); connect(d->mngr->thread(), SIGNAL(stepFinished(Digikam::PanoActionData)), this, SLOT(slotPanoAction(Digikam::PanoActionData))); connect(d->mngr->thread(), SIGNAL(jobCollectionFinished(Digikam::PanoActionData)), this, SLOT(slotPanoAction(Digikam::PanoActionData))); d->canceled = false; d->previewWidget->setBusy(true, i18n("Processing Panorama Preview...")); d->previewDone = false; d->previewBusy = true; d->mngr->resetPreviewPto(); d->mngr->resetPreviewUrl(); d->mngr->resetPreviewMkUrl(); d->mngr->thread()->generatePanoramaPreview(d->mngr->viewAndCropOptimisePtoData(), d->mngr->previewPtoUrl(), d->mngr->previewMkUrl(), d->mngr->previewUrl(), d->mngr->preProcessedMap(), d->mngr->makeBinary().path(), d->mngr->pto2MkBinary().path(), d->mngr->huginExecutorBinary().path(), d->mngr->hugin2015(), d->mngr->enblendBinary().path(), d->mngr->nonaBinary().path()); }
float Remesh::RunStep() { cur_iter++; // COMPUTE THE MESH DISPLACEMENT for (Vertex_iterator vi = data->mesh.p.vertices_begin(); vi!=data->mesh.p.vertices_end(); vi++) vi->delta = Kernel::Vector_3(0,0,0); // from current to the closest destination point for (Vertex_iterator vi = data->mesh.p.vertices_begin(); vi!=data->mesh.p.vertices_end(); vi++) { Kernel::Point_3 closest_point = dst_mesh.closestPoint(vi->point()); //cerr << "closest_point (" << closest_point << ") has ID " << dst_mesh.vertex_mapping[closest_point]->id << endl; Kernel::Vector_3 closest_normal = dst_mesh.vertex_mapping[closest_point]->normal(); //Kernel::Vector_3 closest_normal = dst_mesh.vertexMapping(closest_point)->normal(); /* vi->delta = closest_point - vi->point(); bool is_outside = v_norm((closest_point + closest_normal*v_norm(vi->delta)) - vi->point()) < v_norm(vi->delta); // bool is_outside = v_norm(v_normalized(closest_normal) + v_normalized(vi->delta)) < 1.4142; // bool is_outside = v_angle(closest_normal, vi->delta) > PI/2; double dist_sign = (is_outside?1:-1); vi->delta = vi->normal()*v_norm(vi->delta)*(-1)*dist_sign; */ vi->delta = vi->normal()* (closest_normal*(closest_point-vi->point())); // vi->delta == v_normalized(data->mesh.computeVectorComponent(vi->normal(),vi->delta,1))*v_norm(vi->delta); // vi->delta = v_normalized(vi->delta)*data->mesh.computeVertexStatistics(*vi,1)*0.05; // vi->delta = vi->normal(); //*alg_dt } // NORMALIZE the movements float total_movement = 0; int total_elements = 0; double max_delta = data->mesh.edge_avg*alg_dt; for (Vertex_iterator vi = data->mesh.p.vertices_begin(); vi!=data->mesh.p.vertices_end(); vi++) { //vi->delta = v_normalized(vi->delta)*data->mesh.computeVertexStatistics(*vi,1)*0.1; // double max_delta = data->mesh.computeVertexStatistics(*vi,1)*alg_dt; // double min_delta = data->mesh.edge_avg/5; // vi->delta = vi->delta; // vi->delta = vi->delta + v_normalized(vi->delta)*(RAND_MAX/2-std::rand())*1.0/RAND_MAX*data->mesh.edge_avg/2*alg_smoothing; // vi->delta = v_normalized(vi->delta)*max_delta; double the_norm = v_norm(vi->delta); if (the_norm > max_delta) { vi->delta = v_normalized(vi->delta)*max_delta; } // if (the_norm < min_delta) vi->delta = v_normalized(vi->delta)*min_delta; the_norm = v_norm(vi->delta); if (the_norm > max_delta*0.5) { total_elements++; total_movement += v_norm(vi->delta); } //vi->delta = vi->delta + Kernel::Vector_3((RAND_MAX/2-std::rand())*1.0/RAND_MAX, (RAND_MAX/2-std::rand())*1.0/RAND_MAX, (RAND_MAX/2-std::rand())*1.0/RAND_MAX)*data->mesh.computeVertexStatistics(*vi,1)*alg_smoothing; // vi->delta = vi->delta + data->mesh.computeVectorComponent(vi->normal(),vi->laplacian()*alg_dt,0); if (vi->border()==false) vi->delta = vi->delta + vi->laplacian()*alg_smoothing; } // MOVE THE MESH OpenGLContext::mutex.lock(); data->mesh.lock(); for (Vertex_iterator vi = data->mesh.p.vertices_begin(); vi!=data->mesh.p.vertices_end(); vi++) { if (alg_keepVerticesConstant) vi->delta = vi->normal()*(vi->delta*vi->normal()); vi->prev_delta = vi->delta; vi->border()=false; vi->move ( vi->delta ); } data->mesh.unlock(); data->mesh.updateMeshData(); OpenGLContext::mutex.unlock(); //saveOutput if (alg_saveOutput) { char filename[300]; sprintf(filename,"%s/output_%04d.off",alg_saveOutputPrefix,cur_iter); data->mesh.saveFormat(filename,"off"); sprintf(filename,"%s/output_%04d.diff",alg_saveOutputPrefix,cur_iter); data->mesh.saveVectorField(filename); sprintf(filename,"%s/output_%04d.idx",alg_saveOutputPrefix,cur_iter); data->mesh.saveVertexIndices(filename); } emit stepFinished(); return total_elements; // return (++cur_iter < iter); }
////////////////////////////////////////////////////////////////////////////////////////////////////// // run a step float Remesh::RunColorStep() { cur_iter++; cerr << "ITERATION ( " << cur_iter << ") " << endl; // COMPUTE THE MESH DISPLACEMENT for (Vertex_iterator vi = data->mesh.p.vertices_begin(); vi!=data->mesh.p.vertices_end(); vi++) { vi->delta = Kernel::Vector_3(0,0,0); vi->delta_tmp = Kernel::Vector_3(0,0,0); } // from current to the closest destination point for (Vertex_iterator vi = data->mesh.p.vertices_begin(); vi!=data->mesh.p.vertices_end(); vi++) { #if MOVE_THE_MESH Kernel::Point_3 closest_point = dst_mesh.closestColorPoint(vi->point(), (float *)(vi->color)); //Kernel::Point_3 closest_point = dst_mesh.closestPoint(vi->point()); #else Kernel::Point_3 tmp_point = vi->point() + vi->motion_vec; Kernel::Point_3 closest_point = dst_mesh.closestColorPoint(tmp_point, (float *)(vi->color)); #endif //cerr << "closest_point (" << closest_point << ") has ID " << dst_mesh.vertex_mapping[closest_point]->id << endl; //Kernel::Vector_3 closest_normal = dst_mesh.vertex_mapping[closest_point]->normal(); //Kernel::Vector_3 closest_normal = dst_mesh.vertexMapping(closest_point)->normal(); /* vi->delta = closest_point - vi->point(); bool is_outside = v_norm((closest_point + closest_normal*v_norm(vi->delta)) - vi->point()) < v_norm(vi->delta); // bool is_outside = v_norm(v_normalized(closest_normal) + v_normalized(vi->delta)) < 1.4142; // bool is_outside = v_angle(closest_normal, vi->delta) > PI/2; double dist_sign = (is_outside?1:-1); vi->delta = vi->normal()*v_norm(vi->delta)*(-1)*dist_sign; */ vi->delta = closest_point- (vi->point() + vi->motion_vec); //vi->delta = vi->normal()* (closest_normal*(closest_point-vi->point())); // vi->delta == v_normalized(data->mesh.computeVectorComponent(vi->normal(),vi->delta,1))*v_norm(vi->delta); // vi->delta = v_normalized(vi->delta)*data->mesh.computeVertexStatistics(*vi,1)*0.05; // vi->delta = vi->normal(); //*alg_dt } // NORMALIZE the movements float total_movement = 0; int total_elements = 0; double max_delta = data->mesh.edge_avg*alg_dt; for (Vertex_iterator vi = data->mesh.p.vertices_begin(); vi!=data->mesh.p.vertices_end(); vi++) { //vi->delta = v_normalized(vi->delta)*data->mesh.computeVertexStatistics(*vi,1)*0.1; // double max_delta = data->mesh.computeVertexStatistics(*vi,1)*alg_dt; // double min_delta = data->mesh.edge_avg/5; // vi->delta = vi->delta; // vi->delta = vi->delta + v_normalized(vi->delta)*(RAND_MAX/2-std::rand())*1.0/RAND_MAX*data->mesh.edge_avg/2*alg_smoothing; // vi->delta = v_normalized(vi->delta)*max_delta; double the_norm = v_norm(vi->delta); if (the_norm > max_delta) { vi->delta = v_normalized(vi->delta)*max_delta; } // if (the_norm < min_delta) vi->delta = v_normalized(vi->delta)*min_delta; the_norm = v_norm(vi->delta); if (! MOVE_THE_MESH || the_norm > max_delta*0.5) { total_elements++; total_movement += v_norm(vi->delta); } //vi->delta = vi->delta + Kernel::Vector_3((RAND_MAX/2-std::rand())*1.0/RAND_MAX, (RAND_MAX/2-std::rand())*1.0/RAND_MAX, (RAND_MAX/2-std::rand())*1.0/RAND_MAX)*data->mesh.computeVertexStatistics(*vi,1)*alg_smoothing; // vi->delta = vi->delta + data->mesh.computeVectorComponent(vi->normal(),vi->laplacian()*alg_dt,0); //vi->delta = vi->delta + vi->laplacian()*alg_smoothing; } data->mesh.diffuse(alg_smoothing, 0); #if ADD_LENGTH_CONSTRAINT for (Vertex_iterator vi = data->mesh.p.vertices_begin(); vi!=data->mesh.p.vertices_end(); vi++) { // Add a cost for preserving the smoothness and the geometry of the mesh HV_circulator h = vi->vertex_begin(); double geom_vx = 0 ; double geom_vy = 0 ; double geom_vz = 0 ; int order=0; do { const float xx = TO_FLOAT ( vi->point().x() ); const float yy = TO_FLOAT ( vi->point().y() ); const float zz = TO_FLOAT ( vi->point().z() ); const float xxx = TO_FLOAT ( h->opposite()->vertex()->point().x()) ; const float yyy = TO_FLOAT ( h->opposite()->vertex()->point().y()) ; const float zzz = TO_FLOAT ( h->opposite()->vertex()->point().z()) ; double d = (xx - xxx) * (xx - xxx) + (yy - yyy) * (yy - yyy) + (zz - zzz) * (zz - zzz) ; #if MOVE_THE_MESH double t_d2x = (xx + vi->delta[0]) - (xxx + h->opposite()->vertex()->delta[0]) ; double t_d2y = (yy + vi->delta[1]) - (yyy + h->opposite()->vertex()->delta[1]) ; double t_d2z = (zz + vi->delta[2]) - (zzz + h->opposite()->vertex()->delta[2]) ; #else double t_d2x = (xx + vi->motion_vec[0] + vi->delta[0]) - (xxx + h->opposite()->vertex()->motion_vec[0] + h->opposite()->vertex()->delta[0]) ; double t_d2y = (yy + vi->motion_vec[1] + vi->delta[1]) - (yyy + h->opposite()->vertex()->motion_vec[1] + h->opposite()->vertex()->delta[1]) ; double t_d2z = (zz + vi->motion_vec[2] + vi->delta[2]) - (zzz + h->opposite()->vertex()->motion_vec[2] + h->opposite()->vertex()->delta[2]) ; #endif double d2 = t_d2x * t_d2x + t_d2y * t_d2y + t_d2z * t_d2z; geom_vx += t_d2x * (sqrt(d2) - sqrt(d)) / sqrt(d2) ; geom_vy += t_d2y * (sqrt(d2) - sqrt(d)) / sqrt(d2) ; geom_vz += t_d2z * (sqrt(d2) - sqrt(d)) / sqrt(d2) ; order++; } while ( ++h != vi->vertex_begin() ); geom_vx /= order ; geom_vy /= order ; geom_vz /= order ; double alpha = 1 ; vi->delta_tmp = alpha * Vector(-geom_vx, -geom_vy, -geom_vz) ; #if 0 if(v_norm(vi->delta_tmp) > 0.001) std::cout << vi->delta << " + " << geom_vx << " " << geom_vy << " " << geom_vz <<std::endl ; #endif } for (Vertex_iterator vi = data->mesh.p.vertices_begin(); vi!=data->mesh.p.vertices_end(); vi++) { double alpha1 = 0.9, alpha2 = 0.1 ; if(v_norm(vi->delta)<0.01) { alpha2 = 0.9; alpha1 = 0.1; } vi->delta = alpha1 * vi->delta + alpha2 * vi->delta_tmp; } #endif // MOVE THE MESH OpenGLContext::mutex.lock(); data->mesh.lock(); for (Vertex_iterator vi = data->mesh.p.vertices_begin(); vi!=data->mesh.p.vertices_end(); vi++) { if (alg_keepVerticesConstant) vi->delta = vi->normal()*(vi->delta*vi->normal()); vi->prev_delta = vi->delta; #if MOVE_THE_MESH vi->move ( vi->delta ); #else vi->motion_vec = vi->motion_vec + vi->delta; #endif } data->mesh.unlock(); #if MOVE_THE_MESH data->mesh.updateMeshData(); #else //for (Vertex_iterator vi = data->mesh.p.vertices_begin(); vi!=data->mesh.p.vertices_end(); vi++) { // vi->motion_vec = vi->motion_vec + vi->laplacian() * alg_smoothing; // smooth the motion vectors //} #endif OpenGLContext::mutex.unlock(); //saveOutput if (alg_saveOutput) { char filename[300]; sprintf(filename,"%s/output_%04d.off",alg_saveOutputPrefix,cur_iter); data->mesh.saveFormat(filename,"off"); sprintf(filename,"%s/output_%04d.diff",alg_saveOutputPrefix,cur_iter); data->mesh.saveVectorField(filename); sprintf(filename,"%s/output_%04d.idx",alg_saveOutputPrefix,cur_iter); data->mesh.saveVertexIndices(filename); } emit stepFinished(); return total_movement; //return total_elements; // return (++cur_iter < iter); }
void PanoOptimizePage::slotPanoAction(const DigikamGenericPanoramaPlugin::PanoActionData& ad) { qCDebug(DIGIKAM_DPLUGIN_GENERIC_LOG) << "SlotPanoAction (optimize)"; qCDebug(DIGIKAM_DPLUGIN_GENERIC_LOG) << "starting, success, canceled, action: " << ad.starting << ad.success << d->canceled << ad.action; QString text; QMutexLocker lock(&d->progressMutex); if (!ad.starting) // Something is complete... { if (!ad.success) // Something is failed... { if (d->canceled) // In that case, the error is expected { return; } switch (ad.action) { case PANO_OPTIMIZE: case PANO_AUTOCROP: { disconnect(d->mngr->thread(), SIGNAL(stepFinished(DigikamGenericPanoramaPlugin::PanoActionData)), this, SLOT(slotPanoAction(DigikamGenericPanoramaPlugin::PanoActionData))); disconnect(d->mngr->thread(), SIGNAL(jobCollectionFinished(DigikamGenericPanoramaPlugin::PanoActionData)), this, SLOT(slotPanoAction(DigikamGenericPanoramaPlugin::PanoActionData))); qCWarning(DIGIKAM_DPLUGIN_GENERIC_LOG) << "Job failed (optimize): " << ad.action; if (d->detailsText->isHidden()) { d->title->setText(i18n("<qt>" "<h1>Optimization has failed.</h1>" "<p>See processing messages below.</p>" "</qt>")); d->progressTimer->stop(); d->horizonCheckbox->hide(); // d->projectionAndSizeCheckbox->hide(); d->detailsText->show(); d->progressLabel->clear(); d->detailsText->setText(ad.message); setComplete(false); emit completeChanged(); } break; } default: { qCWarning(DIGIKAM_DPLUGIN_GENERIC_LOG) << "Unknown action (optimize) " << ad.action; break; } } } else // Something is done... { switch (ad.action) { case PANO_OPTIMIZE: { return; } case PANO_AUTOCROP: { disconnect(d->mngr->thread(), SIGNAL(stepFinished(DigikamGenericPanoramaPlugin::PanoActionData)), this, SLOT(slotPanoAction(DigikamGenericPanoramaPlugin::PanoActionData))); disconnect(d->mngr->thread(), SIGNAL(jobCollectionFinished(DigikamGenericPanoramaPlugin::PanoActionData)), this, SLOT(slotPanoAction(DigikamGenericPanoramaPlugin::PanoActionData))); d->progressTimer->stop(); d->progressLabel->clear(); d->optimisationDone = true; emit signalOptimized(); initializePage(); break; } default: { qCWarning(DIGIKAM_DPLUGIN_GENERIC_LOG) << "Unknown action (optimize) " << ad.action; break; } } } } }
void PanoPreviewPage::slotPanoAction(const Digikam::PanoActionData& ad) { qCDebug(DIGIKAM_GENERAL_LOG) << "SlotPanoAction (preview)"; qCDebug(DIGIKAM_GENERAL_LOG) << "\tstarting, success, canceled, action: " << ad.starting << ad.success << d->canceled << ad.action; QString text; QMutexLocker lock(&d->previewBusyMutex); qCDebug(DIGIKAM_GENERAL_LOG) << "\tbusy (preview / stitch):" << d->previewBusy << d->stitchingBusy; if (!ad.starting) // Something is complete... { if (!ad.success) // Something is failed... { switch (ad.action) { case PANO_CREATEPREVIEWPTO: case PANO_NONAFILEPREVIEW: case PANO_STITCHPREVIEW: case PANO_CREATEMKPREVIEW: case PANO_HUGINEXECUTORPREVIEW: { if (!d->previewBusy) { lock.unlock(); emit signalPreviewFinished(); return; } disconnect(d->mngr->thread(), SIGNAL(stepFinished(Digikam::PanoActionData)), this, SLOT(slotPanoAction(Digikam::PanoActionData))); disconnect(d->mngr->thread(), SIGNAL(jobCollectionFinished(Digikam::PanoActionData)), this, SLOT(slotPanoAction(Digikam::PanoActionData))); d->output = ad.message; d->previewWidget->setBusy(false); d->previewBusy = false; qCWarning(DIGIKAM_GENERAL_LOG) << "Preview compilation failed: " << ad.message; QString errorString(i18n("<h1><b>Error</b></h1><p>%1</p>", ad.message)); d->previewWidget->setText(errorString); d->previewWidget->setSelectionAreaPossible(false); setComplete(false); emit completeChanged(); lock.unlock(); emit signalPreviewFinished(); break; } case PANO_CREATEMK: { if (!d->stitchingBusy) { return; } disconnect(d->mngr->thread(), SIGNAL(starting(Digikam::PanoActionData)), this, SLOT(slotPanoAction(Digikam::PanoActionData))); disconnect(d->mngr->thread(), SIGNAL(stepFinished(Digikam::PanoActionData)), this, SLOT(slotPanoAction(Digikam::PanoActionData))); disconnect(d->mngr->thread(), SIGNAL(jobCollectionFinished(Digikam::PanoActionData)), this, SLOT(slotPanoAction(Digikam::PanoActionData))); d->stitchingBusy = false; QString message = i18nc("Here a makefile is a script for GNU Make", "<p><b>Cannot create makefile: </b></p><p>%1</p>", ad.message); qCWarning(DIGIKAM_GENERAL_LOG) << "pto2mk call failed"; d->postProcessing->addEntry(message, DHistoryView::ErrorEntry); setComplete(false); emit completeChanged(); break; } case PANO_CREATEFINALPTO: { if (!d->stitchingBusy) { return; } disconnect(d->mngr->thread(), SIGNAL(starting(Digikam::PanoActionData)), this, SLOT(slotPanoAction(Digikam::PanoActionData))); disconnect(d->mngr->thread(), SIGNAL(stepFinished(Digikam::PanoActionData)), this, SLOT(slotPanoAction(Digikam::PanoActionData))); disconnect(d->mngr->thread(), SIGNAL(jobCollectionFinished(Digikam::PanoActionData)), this, SLOT(slotPanoAction(Digikam::PanoActionData))); d->stitchingBusy = false; QString message = i18nc("a project file is a .pto file, as given to hugin to build a panorama", "<p><b>Cannot create project file: </b></p><p>%1</p>", ad.message); qCWarning(DIGIKAM_GENERAL_LOG) << "pto creation failed"; d->postProcessing->addEntry(message, DHistoryView::ErrorEntry); setComplete(false); emit completeChanged(); break; } case PANO_NONAFILE: { if (!d->stitchingBusy) { return; } disconnect(d->mngr->thread(), SIGNAL(starting(Digikam::PanoActionData)), this, SLOT(slotPanoAction(Digikam::PanoActionData))); disconnect(d->mngr->thread(), SIGNAL(stepFinished(Digikam::PanoActionData)), this, SLOT(slotPanoAction(Digikam::PanoActionData))); disconnect(d->mngr->thread(), SIGNAL(jobCollectionFinished(Digikam::PanoActionData)), this, SLOT(slotPanoAction(Digikam::PanoActionData))); d->stitchingBusy = false; QString message = i18nc("Error message for image file number %1 out of %2", "<p><b>Processing file %1 / %2: </b></p><p>%3</p>", QString::number(ad.id + 1), QString::number(d->totalProgress - 1), ad.message); qCWarning(DIGIKAM_GENERAL_LOG) << "Nona call failed for file #" << ad.id; d->postProcessing->addEntry(message, DHistoryView::ErrorEntry); setComplete(false); emit completeChanged(); break; } case PANO_STITCH: case PANO_HUGINEXECUTOR: { if (!d->stitchingBusy) { return; } disconnect(d->mngr->thread(), SIGNAL(starting(Digikam::PanoActionData)), this, SLOT(slotPanoAction(Digikam::PanoActionData))); disconnect(d->mngr->thread(), SIGNAL(stepFinished(Digikam::PanoActionData)), this, SLOT(slotPanoAction(Digikam::PanoActionData))); disconnect(d->mngr->thread(), SIGNAL(jobCollectionFinished(Digikam::PanoActionData)), this, SLOT(slotPanoAction(Digikam::PanoActionData))); d->stitchingBusy = false; d->postProcessing->addEntry(i18nc("Error message for panorama compilation", "<p><b>Panorama compilation: </b></p><p>%1</p>", ad.message.toHtmlEscaped()), DHistoryView::ErrorEntry); qCWarning(DIGIKAM_GENERAL_LOG) << "Enblend call failed"; setComplete(false); emit completeChanged(); break; } default: { qCWarning(DIGIKAM_GENERAL_LOG) << "Unknown action (preview) " << ad.action; break; } } } else // Something is done... { switch (ad.action) { case PANO_CREATEPREVIEWPTO: case PANO_CREATEMKPREVIEW: case PANO_NONAFILEPREVIEW: case PANO_CREATEFINALPTO: case PANO_CREATEMK: { // Nothing to do yet, a step is finished, that's all break; } case PANO_STITCHPREVIEW: case PANO_HUGINEXECUTORPREVIEW: { if (d->previewBusy) { disconnect(d->mngr->thread(), SIGNAL(stepFinished(Digikam::PanoActionData)), this, SLOT(slotPanoAction(Digikam::PanoActionData))); disconnect(d->mngr->thread(), SIGNAL(jobCollectionFinished(Digikam::PanoActionData)), this, SLOT(slotPanoAction(Digikam::PanoActionData))); } d->previewBusy = false; d->previewDone = true; lock.unlock(); emit signalPreviewFinished(); d->title->setText(i18n("<qt>" "<h1>Panorama Preview</h1>" "<p>Draw a rectangle if you want to crop the image.</p>" "<p>Pressing the <i>Next</i> button will then launch the final " "stitching process.</p>" "</qt>")); d->previewWidget->setSelectionAreaPossible(true); // d->previewWidget->load(QUrl::fromLocalFile(d->mngr->previewUrl().toLocalFile()), true); d->previewWidget->load(d->mngr->previewUrl(), true); QSize panoSize = d->mngr->viewAndCropOptimisePtoData()->project.size; QRect panoCrop = d->mngr->viewAndCropOptimisePtoData()->project.crop; QSize previewSize = d->mngr->previewPtoData()->project.size; d->previewWidget->setSelectionArea(QRectF( ((double) panoCrop.left()) / panoSize.width() * previewSize.width(), ((double) panoCrop.top()) / panoSize.height() * previewSize.height(), ((double) panoCrop.width()) / panoSize.width() * previewSize.width(), ((double) panoCrop.height()) / panoSize.height() * previewSize.height() )); break; } case PANO_NONAFILE: { QString message = i18nc("Success for image file number %1 out of %2", "Processing file %1 / %2", QString::number(ad.id + 1), QString::number(d->totalProgress - 1)); d->postProcessing->addEntry(message, DHistoryView::SuccessEntry); d->curProgress++; d->progressBar->setValue(d->curProgress); d->progressBar->setMaximum(d->totalProgress); break; } case PANO_STITCH: case PANO_HUGINEXECUTOR: { if (!d->stitchingBusy) { return; } disconnect(d->mngr->thread(), SIGNAL(starting(Digikam::PanoActionData)), this, SLOT(slotPanoAction(Digikam::PanoActionData))); disconnect(d->mngr->thread(), SIGNAL(stepFinished(Digikam::PanoActionData)), this, SLOT(slotPanoAction(Digikam::PanoActionData))); disconnect(d->mngr->thread(), SIGNAL(jobCollectionFinished(Digikam::PanoActionData)), this, SLOT(slotPanoAction(Digikam::PanoActionData))); d->stitchingBusy = false; d->postProcessing->addEntry(i18nc("Success for panorama compilation", "Panorama compilation"), DHistoryView::SuccessEntry); d->curProgress++; d->progressBar->setValue(d->curProgress); d->progressBar->setMaximum(d->totalProgress); d->progressBar->progressCompleted(); d->progressBar->hide(); d->postProcessing->hide(); d->stitchingDone = true; emit signalStitchingFinished(); preInitializePage(); break; } default: { qCWarning(DIGIKAM_GENERAL_LOG) << "Unknown action (preview) " << ad.action; break; } } } } else // Some step is started... { switch (ad.action) { case PANO_CREATEPREVIEWPTO: case PANO_CREATEMKPREVIEW: case PANO_NONAFILEPREVIEW: case PANO_STITCHPREVIEW: case PANO_CREATEFINALPTO: case PANO_CREATEMK: case PANO_HUGINEXECUTORPREVIEW: { // Nothing to do... break; } case PANO_NONAFILE: { QString message = i18nc("Compilation started for image file number %1 out of %2", "Processing file %1 / %2", QString::number(ad.id + 1), QString::number(d->totalProgress - 1)); d->postProcessing->addEntry(message, DHistoryView::StartingEntry); break; } case PANO_STITCH: case PANO_HUGINEXECUTOR: { d->postProcessing->addEntry(i18nc("Panorama compilation started", "Panorama compilation"), DHistoryView::StartingEntry); break; } default: { qCWarning(DIGIKAM_GENERAL_LOG) << "Unknown starting action (preview) " << ad.action; break; } } } }
void PanoPreviewPage::startStitching() { QMutexLocker lock(&d->previewBusyMutex); if (d->previewBusy) { // The real beginning of the stitching starts after preview has finished / failed connect(this, SIGNAL(signalPreviewFinished()), this, SLOT(slotStartStitching())); cleanupPage(lock); return; } connect(d->mngr->thread(), SIGNAL(starting(Digikam::PanoActionData)), this, SLOT(slotPanoAction(Digikam::PanoActionData))); connect(d->mngr->thread(), SIGNAL(stepFinished(Digikam::PanoActionData)), this, SLOT(slotPanoAction(Digikam::PanoActionData))); connect(d->mngr->thread(), SIGNAL(jobCollectionFinished(Digikam::PanoActionData)), this, SLOT(slotPanoAction(Digikam::PanoActionData))); d->canceled = false; d->stitchingBusy = true; d->curProgress = 0; if (d->mngr->hugin2015()) { d->totalProgress = 1; } else { d->totalProgress = d->mngr->preProcessedMap().size() + 1; } d->previewWidget->hide(); QSize panoSize = d->mngr->viewAndCropOptimisePtoData()->project.size; QRect panoSelection = d->mngr->viewAndCropOptimisePtoData()->project.crop; if (d->previewDone) { QSize previewSize = d->mngr->previewPtoData()->project.size; QRectF selection = d->previewWidget->getSelectionArea(); QRectF proportionSelection(selection.x() / previewSize.width(), selection.y() / previewSize.height(), selection.width() / previewSize.width(), selection.height() / previewSize.height()); // At this point, if no selection area was created, proportionSelection is null, // hence panoSelection becomes a null rectangle panoSelection = QRect(proportionSelection.x() * panoSize.width(), proportionSelection.y() * panoSize.height(), proportionSelection.width() * panoSize.width(), proportionSelection.height() * panoSize.height()); } d->title->setText(i18n("<qt>" "<p><h1>Panorama Post-Processing</h1></p>" "</qt>")); d->progressBar->reset(); d->progressBar->setMaximum(d->totalProgress); d->progressBar->progressScheduled(i18nc("@title:group", "Panorama Post-Processing"), true, true); d->progressBar->progressThumbnailChanged(QIcon::fromTheme(QLatin1String("panorama")).pixmap(22, 22)); d->progressBar->show(); d->postProcessing->show(); d->mngr->resetPanoPto(); d->mngr->resetMkUrl(); d->mngr->resetPanoUrl(); d->mngr->thread()->compileProject(d->mngr->viewAndCropOptimisePtoData(), d->mngr->panoPtoUrl(), d->mngr->mkUrl(), d->mngr->panoUrl(), d->mngr->preProcessedMap(), d->mngr->format(), panoSelection, d->mngr->makeBinary().path(), d->mngr->pto2MkBinary().path(), d->mngr->huginExecutorBinary().path(), d->mngr->hugin2015(), d->mngr->enblendBinary().path(), d->mngr->nonaBinary().path()); }