diff --git a/HPPA/HPPA.cpp b/HPPA/HPPA.cpp index e3b6054..9be4330 100644 --- a/HPPA/HPPA.cpp +++ b/HPPA/HPPA.cpp @@ -265,29 +265,29 @@ sizePolicy1.setHeightForWidth(graphicsView_delete->sizePolicy().hasHeightForWidt //dock_layers->setMaximumHeight(498); - //高光谱查看 - QDockWidget* dock_hyperimgViewer = new CustomDockWidgetBase(QString::fromLocal8Bit("hyimgViewer"), this); - dock_hyperimgViewer->setObjectName("hyimgViewer"); + //高光谱查看 + QDockWidget* dock_hyperimgViewer = new CustomDockWidgetBase(QString::fromLocal8Bit("hyimgViewer"), this); + dock_hyperimgViewer->setObjectName("hyimgViewer"); - QWidget* dock_hyperimgViewerWidgetContents = new QWidget(); - dock_hyperimgViewerWidgetContents->setObjectName(QString::fromUtf8("dock_hyperimgViewerWidgetContents")); - QGridLayout* gridLayout_hyperimgViewer = new QGridLayout(dock_hyperimgViewerWidgetContents); - gridLayout_hyperimgViewer->setSpacing(6); - gridLayout_hyperimgViewer->setObjectName(QString::fromUtf8("gridLayout_hyperimgViewer")); - gridLayout_hyperimgViewer->setVerticalSpacing(6); - gridLayout_hyperimgViewer->setContentsMargins(1, 2, 1, 2); + QWidget* dock_hyperimgViewerWidgetContents = new QWidget(); + dock_hyperimgViewerWidgetContents->setObjectName(QString::fromUtf8("dock_hyperimgViewerWidgetContents")); + QGridLayout* gridLayout_hyperimgViewer = new QGridLayout(dock_hyperimgViewerWidgetContents); + gridLayout_hyperimgViewer->setSpacing(6); + gridLayout_hyperimgViewer->setObjectName(QString::fromUtf8("gridLayout_hyperimgViewer")); + gridLayout_hyperimgViewer->setVerticalSpacing(6); + gridLayout_hyperimgViewer->setContentsMargins(1, 2, 1, 2); - m_imageViewerTabWidget = new QTabWidget(); + m_imageViewerTabWidget = new QTabWidget(); //m_imageViewerTabWidget->tabBar()->setFixedHeight(40);//没有效果,在qss中设置高度才有效果,为啥???? m_imageViewerTabWidget->clear();//必须放在最前面,首先删除所有的tab - QToolButton* maxButton = new QToolButton(); - maxButton->setIcon(style()->standardIcon(QStyle::SP_TitleBarMaxButton)); - connect(maxButton, SIGNAL(clicked()), dock_hyperimgViewer, SLOT(toggleMaximize())); - m_imageViewerTabWidget->setCornerWidget(maxButton, Qt::TopRightCorner); + QToolButton* maxButton = new QToolButton(); + maxButton->setIcon(style()->standardIcon(QStyle::SP_TitleBarMaxButton)); + connect(maxButton, SIGNAL(clicked()), dock_hyperimgViewer, SLOT(toggleMaximize())); + m_imageViewerTabWidget->setCornerWidget(maxButton, Qt::TopRightCorner); //onCreateTab(0); //m_imageViewerTabWidget->setTabsClosable(true);//这样每页都会有关闭按钮 - connect(m_imageViewerTabWidget, SIGNAL(currentChanged(int)), this, SLOT(onTabWidgetCurrentChanged(int))); - m_imageViewerTabWidget->setStyleSheet(R"( + connect(m_imageViewerTabWidget, SIGNAL(currentChanged(int)), this, SLOT(onTabWidgetCurrentChanged(int))); + m_imageViewerTabWidget->setStyleSheet(R"( QTabBar::tab { background: #0E1C4C; color: white; @@ -676,7 +676,6 @@ void HPPA::initMenubarToolbar() } )"); - QWidget* topWidget = new QWidget(); topWidget->setStyleSheet("background-color: #040125;"); QVBoxLayout* verticalLayout_topWidget = new QVBoxLayout(topWidget); @@ -934,8 +933,6 @@ void HPPA::createOneMotorScenario() m_tabManager->showTab(m_omc); - - m_view3DModelManager->switchScenario(View3DModelManager::ScenarioType::OneMotor); //右上角轮播 @@ -964,8 +961,6 @@ void HPPA::createPlantPhenotypeScenario() m_tabManager->showTab(m_pc); m_tabManager->showTab(m_tmc); - - m_view3DModelManager->switchScenario(View3DModelManager::ScenarioType::PlantPhenotype); //右上角轮播 @@ -1078,7 +1073,7 @@ void HPPA::onStartRecordStep1() m_RecordState -= 1; ui.action_start_recording->setText(QString::fromLocal8Bit("采集")); - ui.mainToolBar->widgetForAction(ui.action_start_recording)->setStyleSheet("QWidget{background-color:rgb(0,255,0);}"); + ui.mainToolBar->widgetForAction(ui.action_start_recording)->setStyleSheet("QWidget{background-color:rgb(0,255,0);}"); } return; } @@ -1124,42 +1119,41 @@ void HPPA::onStartRecordStep1() void HPPA::onCreateTab(int trackNumber) { - if (trackNumber >= 0) - { - m_numberOfRecording = trackNumber; + if (trackNumber >= 0) + { + m_numberOfRecording = trackNumber; - QWidget* tabTmp = new QWidget(); + QWidget* tabTmp = new QWidget(); - QGridLayout* GridLayout = new QGridLayout(); - GridLayout->addWidget(new ImageViewer(tabTmp)); + QGridLayout* GridLayout = new QGridLayout(); + GridLayout->addWidget(new mapcavas(tabTmp)); - tabTmp->setLayout(GridLayout); + tabTmp->setLayout(GridLayout); - m_imageViewerTabWidget->addTab(tabTmp, QString::number(trackNumber + 1)); + m_imageViewerTabWidget->addTab(tabTmp, QString::number(trackNumber + 1)); - m_imageViewerTabWidget->setCurrentIndex(trackNumber); - } + m_imageViewerTabWidget->setCurrentIndex(trackNumber); + } } void HPPA::onTabWidgetCurrentChanged(int index)//代码新建一个tab,会调用onTabWidgetCurrentChanged函数! { - if (index < 0)//当删除所有tab时,index=-1 - { - return; - } + if (index < 0)//当删除所有tab时,index=-1 + { + return; + } + //记录当前 + m_TabWidgetCurrentIndex = index; - //记录当前 - m_TabWidgetCurrentIndex = index; + //获取绘图控件 + QWidget* currentWidget = m_imageViewerTabWidget->widget(index); + QList currentImageViewer = currentWidget->findChildren(); - //获取绘图控件 - QWidget* currentWidget = m_imageViewerTabWidget->widget(index); - QList currentImageViewer = currentWidget->findChildren(); - - //先disconnect然后再connect,否则每次切换一次都会connect一次,会累积connect很多次! - disconnect(currentImageViewer[0], SIGNAL(leftMouseButtonPressed(int, int)), this, SLOT(onLeftMouseButtonPressed(int, int))); - connect(currentImageViewer[0], SIGNAL(leftMouseButtonPressed(int, int)), this, SLOT(onLeftMouseButtonPressed(int, int))); + //先disconnect然后再connect,否则每次切换一次都会connect一次,会累积connect很多次! + disconnect(currentImageViewer[0], SIGNAL(leftMouseButtonPressed(int, int)), this, SLOT(onLeftMouseButtonPressed(int, int))); + connect(currentImageViewer[0], SIGNAL(leftMouseButtonPressed(int, int)), this, SLOT(onLeftMouseButtonPressed(int, int))); } void HPPA::onActionOpenDirectory() @@ -1169,34 +1163,6 @@ void HPPA::onActionOpenDirectory() QDesktopServices::openUrl(QUrl::fromLocalFile(QString::fromStdString(directory))); - //QDesktopServices::openUrl(QUrl("file:C:\ASD", QUrl::TolerantMode)); - - - ////std::cout << "保存影像文件!" << std::endl; - // - //FileOperation * fileOperation = new FileOperation(); - //string directory = fileOperation->getDirectoryFromString(); - - //string sourceImg = directory + "\\tmp_image"; - //string sourceHdr = sourceImg + ".hdr"; - // - - //QString FileName2Save = QFileDialog::getSaveFileName(this,tr("save image")); - - //if (FileName2Save.length()>0) - //{ - // string targetImg = FileName2Save.toStdString(); - // string targetHdr = targetImg + ".hdr"; - - // emit CopyFileThreadSignal(QString::fromStdString(sourceHdr), QString::fromStdString(targetHdr)); - // emit CopyFileThreadSignal(QString::fromStdString(sourceImg), QString::fromStdString(targetImg)); - - // this->setEnabled(false); - //} - //else - //{ - // std::cout << "文件名长度:" << FileName2Save.length() << std::endl; - //} } @@ -1274,6 +1240,7 @@ void HPPA::onLeftMouseButtonPressed(int x, int y) QLineSeries* series = new QLineSeries(); //series->clear();////////////////////////////// + QString imagerSelected = mImagerGroup->checkedAction()->objectName(); if (imagerSelected == "mActionPica_L" || imagerSelected == "mActionCorning_410" || imagerSelected == "mActionPika_XC2") { @@ -1385,7 +1352,6 @@ void HPPA::onPlotRgbImage() int height = m_cam_label->height(); QPixmap fitpixmap = pixmap.scaled(width, height, Qt::KeepAspectRatio, Qt::SmoothTransformation); //按比例缩放 - m_cam_label->setPixmap(fitpixmap); } @@ -1444,6 +1410,53 @@ void HPPA::onExit() void HPPA::onOpenImg() { + // 1) 弹出文件对话框获取uri + QString uri = QFileDialog::getOpenFileName(this, tr("Open Image"), QString(), tr("Raster Files (*.bil *.hdr *.tif *.tiff *.img *.raw);;All Files (*)")); + if (uri.isEmpty()) + return; + + // 2) 创建 RasterLayer,然后添加到图层管理器 + if (!m_LayerTreeModel || !m_RasterGroup) + { + QMessageBox::warning(this, tr("Error"), tr("Layer model is not initialized.")); + return; + } + + QFileInfo fi(uri); + QString baseName = fi.completeBaseName(); + + // Create RasterLayer and wrap in LayerTreeLayerNode + RasterLayer* rl = new RasterLayer(baseName, uri); + auto* layerNode = new LayerTreeLayerNode(rl); + m_LayerTreeModel->addLayer(m_RasterGroup, layerNode); + + // 3) 渲染一副图像并保存到 C:\2 + RasterLayer::RenderParams params; // use defaults + QImage img = rl->render(params); + if (img.isNull()) + { + QMessageBox::warning(this, tr("Render failed"), tr("Failed to render image from %1").arg(uri)); + return; + } + + QDir outDir("C:/2"); + if (!outDir.exists()) + { + if (!outDir.mkpath(".")) + { + QMessageBox::warning(this, tr("Save failed"), tr("Failed to create output directory C:/2")); + return; + } + } + + QString outPath = outDir.filePath(baseName + "_render.png"); + if (!img.save(outPath)) + { + QMessageBox::warning(this, tr("Save failed"), tr("Failed to save rendered image to %1").arg(outPath)); + return; + } + + QMessageBox::information(this, tr("Saved"), tr("Rendered image saved to %1").arg(outPath)); } void HPPA::onconnect() @@ -1638,7 +1651,7 @@ void HPPA::onFocus2(int command) QWidget* tabTmp = new QWidget(); QGridLayout* GridLayout = new QGridLayout(); - GridLayout->addWidget(new ImageViewer(tabTmp)); + GridLayout->addWidget(new mapcavas(tabTmp)); tabTmp->setLayout(GridLayout); @@ -1726,28 +1739,28 @@ void HPPA::recordWhiteFinish() void HPPA::onPlotHyperspectralImageRgbImage(int fileNumber, int frameNumber) { - //使用机械臂采集时,会在停止采集后的瞬间又开始采集,会导致上次采集最后发射的信号调用此槽函数报错 - QAction* checked = moveplatformActionGroup->checkedAction(); - QString checkedName = checked->objectName(); - if (frameNumber == -1 && checkedName == "mAction_RobotArm") - { - return; - } + //使用机械臂采集时,会在停止采集后的瞬间又开始采集,会导致上次采集最后发射的信号调用此槽函数报错 + QAction* checked = moveplatformActionGroup->checkedAction(); + QString checkedName = checked->objectName(); + if (frameNumber == -1 && checkedName == "mAction_RobotArm") + { + return; + } - //return; - //获取绘图控件 - QWidget* currentWidget = m_imageViewerTabWidget->widget(fileNumber); - QList currentImageViewer = currentWidget->findChildren(); - currentImageViewer[0]->DisplayFrameNumber(m_Imager->getFrameCounter());//界面中显示已经采集的帧数 + //return; + //获取绘图控件 + QWidget* currentWidget = m_imageViewerTabWidget->widget(fileNumber); + QList currentImageViewer = currentWidget->findChildren(); + currentImageViewer[0]->DisplayFrameNumber(m_Imager->getFrameCounter());//界面中显示已经采集的帧数 - //创建需要显示的图像--opencv版本 - ImageProcessor imageProcessor; - //cv::Mat rgbImage(*m_Imager->getRgbImage()->m_matRgbImage, cv::Range(0, m_Imager->getFrameCounter()), cv::Range::all());//2022.3.18重构的 - cv::Mat rgbImage(*m_Imager->getMatRgbImage(), cv::Range(0, m_Imager->getFrameCounter()), cv::Range::all()); - cv::Mat rgbImageStretched = imageProcessor.CStretch(rgbImage, 0.02); + //创建需要显示的图像--opencv版本 + ImageProcessor imageProcessor; + //cv::Mat rgbImage(*m_Imager->getRgbImage()->m_matRgbImage, cv::Range(0, m_Imager->getFrameCounter()), cv::Range::all());//2022.3.18重构的 + cv::Mat rgbImage(*m_Imager->getMatRgbImage(), cv::Range(0, m_Imager->getFrameCounter()), cv::Range::all()); + cv::Mat rgbImageStretched = imageProcessor.CStretch(rgbImage, 0.02); - //在界面中显示图像 - currentImageViewer[0]->SetImage(&QPixmap::fromImage(imageProcessor.Mat2QImage(rgbImageStretched)));//绘制图像 + //在界面中显示图像 + currentImageViewer[0]->SetImage(&QPixmap::fromImage(imageProcessor.Mat2QImage(rgbImageStretched)));//绘制图像 //20241225 //保存拉伸后的rgb @@ -1768,12 +1781,12 @@ void HPPA::onPlotHyperspectralImageRgbImage(int fileNumber, int frameNumber) void HPPA::PlotSpectral(int state) { - if (state == 1) - { - //显示影像 - QWidget* currentWidget = m_imageViewerTabWidget->currentWidget(); - QList currentImageViewer = currentWidget->findChildren(); - currentImageViewer[0]->DisplayFrameNumber(m_Imager->getFocusFrameCounter());//界面中显示已经采集的帧数 + if (state == 1) + { + //显示影像 + QWidget* currentWidget = m_imageViewerTabWidget->currentWidget(); + QList currentImageViewer = currentWidget->findChildren(); + currentImageViewer[0]->DisplayFrameNumber(m_Imager->getFocusFrameCounter());//界面中显示已经采集的帧数 ImageProcessor imageProcessor; //cv::Mat grayImage(*m_Imager->getRgbImage()->m_matFocusGrayImage, cv::Range::all(), cv::Range::all());//2022.3.18重构的 @@ -1782,26 +1795,26 @@ void HPPA::PlotSpectral(int state) currentImageViewer[0]->SetImage(&QPixmap::fromImage(m_Imager->getQImageFocusGrayImage()));//绘制图像 - //绘制光谱 - QLineSeries* series = new QLineSeries(); - //series->clear();////////////////////////////// - int sampleCount = m_Imager->getSampleCount(); - for (size_t i = 0; i < sampleCount; i++) - { - //malloc申请的内存用法1:可以当做数组用 - //series->append(i, m_Imager->buffer[i + 5 * 900]); - //series->append(i, m_Imager->buffer[900 * 150 + i]); - series->append(i, m_Imager->buffer[1368 * 150 + i]); - } + //绘制光谱 + QLineSeries* series = new QLineSeries(); + //series->clear();////////////////////////////// + int sampleCount = m_Imager->getSampleCount(); + for (size_t i = 0; i < sampleCount; i++) + { + //malloc申请的内存用法1:可以当做数组用 + //series->append(i, m_Imager->buffer[i + 5 * 900]); + //series->append(i, m_Imager->buffer[900 * 150 + i]); + series->append(i, m_Imager->buffer[1368 * 150 + i]); + } - QChart* chart = new QChart(); - chart->legend()->hide(); - chart->addSeries(series); - chart->createDefaultAxes(); - //chart->setTitle("Simple line chart example"); + QChart* chart = new QChart(); + chart->legend()->hide(); + chart->addSeries(series); + chart->createDefaultAxes(); + //chart->setTitle("Simple line chart example"); - m_chartView->setChart(chart); - } + m_chartView->setChart(chart); + } else { //改变界面上的按钮文字 diff --git a/HPPA/HPPA.vcxproj b/HPPA/HPPA.vcxproj index 6ec8f21..7206375 100644 --- a/HPPA/HPPA.vcxproj +++ b/HPPA/HPPA.vcxproj @@ -125,7 +125,9 @@ + + @@ -194,6 +196,8 @@ + + diff --git a/HPPA/HPPA.vcxproj.filters b/HPPA/HPPA.vcxproj.filters index fa1daaa..7a3619b 100644 --- a/HPPA/HPPA.vcxproj.filters +++ b/HPPA/HPPA.vcxproj.filters @@ -160,6 +160,12 @@ Source Files + + Source Files + + + Source Files + @@ -287,6 +293,12 @@ Header Files + + Header Files + + + Header Files + diff --git a/HPPA/ImageViewer.cpp b/HPPA/ImageViewer.cpp index 042acca..8dace79 100644 --- a/HPPA/ImageViewer.cpp +++ b/HPPA/ImageViewer.cpp @@ -5,240 +5,217 @@ #include #include "ImageViewer.h" +#include "RasterLayer.h" #define VIEW_CENTER viewport()->rect().center() #define VIEW_WIDTH viewport()->rect().width() #define VIEW_HEIGHT viewport()->rect().height() - -ImageViewer::ImageViewer(QWidget* pParent) :QGraphicsView(pParent) +mapcavas::mapcavas(QWidget* pParent) :QGraphicsView(pParent) { - setRenderHint(QPainter::Antialiasing); - setRenderHint(QPainter::SmoothPixmapTransform); - setDragMode(QGraphicsView::ScrollHandDrag); + setRenderHint(QPainter::Antialiasing); + setRenderHint(QPainter::SmoothPixmapTransform); + setDragMode(QGraphicsView::ScrollHandDrag); - // ؼ㣺ʹ Qt Ĭϵ anchorԼ - setTransformationAnchor(QGraphicsView::NoAnchor); - setResizeAnchor(QGraphicsView::NoAnchor); + // ʹ Qt Ĭ anchor Ϊ + setTransformationAnchor(QGraphicsView::NoAnchor); + setResizeAnchor(QGraphicsView::NoAnchor); - m_qtGraphicsScene = new QGraphicsScene(this); - this->setScene(m_qtGraphicsScene); - m_qtGraphicsScene->setSceneRect(-1e6, -1e6, 2e6, 2e6); + m_qtGraphicsScene = new QGraphicsScene(this); + this->setScene(m_qtGraphicsScene); + m_qtGraphicsScene->setSceneRect(-1e6, -1e6, 2e6, 2e6); - m_framNumberLabel = new QLabel(this); - m_framNumberLabel->setAlignment(Qt::AlignHCenter); - m_framNumberLabel->setAlignment(Qt::AlignVCenter); + m_framNumberLabel = new QLabel(this); + m_framNumberLabel->setAlignment(Qt::AlignHCenter); + m_framNumberLabel->setAlignment(Qt::AlignVCenter); - QFont ft; - ft.setPointSize(14); - m_framNumberLabel->setFont(ft); + QFont ft; + ft.setPointSize(14); + m_framNumberLabel->setFont(ft); m_framNumberLabel->setText("0"); - m_GraphicsPixmapItemHandle = nullptr; + m_GraphicsPixmapItemHandle = nullptr; - m_scale = 1.0; - m_zoomDelta = 0.1; - m_translateSpeed = 1.0; - m_bMouseTranslate = false; + m_scale = 1.0; + m_zoomDelta = 0.1; + m_translateSpeed = 1.0; + m_bMouseTranslate = false; - setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); - setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); - setFrameShape(QFrame::NoFrame); + setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); + setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); + setFrameShape(QFrame::NoFrame); } -ImageViewer::~ImageViewer() +mapcavas::~mapcavas() { } -void ImageViewer::DisplayFrameNumber(int frameNumber) +void mapcavas::DisplayFrameNumber(int frameNumber) { - m_framNumberLabel->setText(QString::number(frameNumber)); - m_framNumberLabel->adjustSize(); + m_framNumberLabel->setText(QString::number(frameNumber)); + m_framNumberLabel->adjustSize(); } -void ImageViewer::SetImage(QPixmap *image) +void mapcavas::SetImage(QPixmap *image) { - if (!HasImage()) - { - m_GraphicsPixmapItemHandle = m_qtGraphicsScene->addPixmap(*image); - } - else - { - m_GraphicsPixmapItemHandle->setPixmap(*image); - } - ensureSceneVisible(); + if (!HasImage()) + { + m_GraphicsPixmapItemHandle = m_qtGraphicsScene->addPixmap(*image); + } + else + { + m_GraphicsPixmapItemHandle->setPixmap(*image); + } + ensureSceneVisible(); } -void ImageViewer::ensureSceneVisible() +void mapcavas::ensureSceneVisible() { - resetTransform(); + resetTransform(); - auto view_rect = viewport()->rect(); - auto scene_rect = this->scene()->itemsBoundingRect(); + auto view_rect = viewport()->rect(); + auto scene_rect = this->scene()->itemsBoundingRect(); - double x_ratio = view_rect.width() / scene_rect.width(); - double y_ratio = view_rect.height() / scene_rect.height(); - double scale_factor = std::min(x_ratio, y_ratio) * 0.9; + double x_ratio = view_rect.width() / scene_rect.width(); + double y_ratio = view_rect.height() / scene_rect.height(); + double scale_factor = std::min(x_ratio, y_ratio) * 0.9; - scale(scale_factor, scale_factor); - m_scale *= scale_factor; + scale(scale_factor, scale_factor); + m_scale *= scale_factor; - centerOn(scene_rect.center()); + centerOn(scene_rect.center()); } -bool ImageViewer::HasImage() +bool mapcavas::HasImage() { - if (m_GraphicsPixmapItemHandle == nullptr) - { - return false; - } - else - { - return true; - } + if (m_GraphicsPixmapItemHandle == nullptr) + { + return false; + } + else + { + return true; + } } -void ImageViewer::wheelEvent(QWheelEvent *event) +void mapcavas::wheelEvent(QWheelEvent *event) { - //qDebug() << "---------------+++++++++++++++++++++++++++++++++++++++++++++++++++ "; - //if (true)//HasImage() - //{ - // //ΧŴhttps://blog.csdn.net/GoForwardToStep/article/details/77035287?utm_medium=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-3.channel_param&depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-3.channel_param - // // ȡǰviewλ; - // QPointF cursorPoint = event->pos(); - // // ȡǰsceneλ; - // QPointF scenePos = this->mapToScene(QPoint(cursorPoint.x(), cursorPoint.y())); + if (HasImage()) + { + QPointF oldPos = mapToScene(event->pos()); - // // ȡviewĿ; - // qreal viewWidth = this->viewport()->width(); - // qreal viewHeight = this->viewport()->height(); + QPoint scrollAmount = event->angleDelta(); + scrollAmount.y() > 0 ? zoomIn() : zoomOut(); - // // ȡǰλ൱viewСĺݱ; - // qreal hScale = cursorPoint.x() / viewWidth; - // qreal vScale = cursorPoint.y() / viewHeight; + QPointF newPos = mapToScene(event->pos()); - - // // ֵĹ - // QPoint scrollAmount = event->angleDelta(); - // // ֵʾԶʹ߷ŴֵʾʹС - // scrollAmount.y() > 0 ? zoomIn() : zoomOut(); - - - // // sceneתΪŴС; - // QPointF viewPoint = this->matrix().map(scenePos); - // // ͨviewŴСչʾsceneλ; - // horizontalScrollBar()->setValue(int(viewPoint.x() - viewWidth * hScale)); - // verticalScrollBar()->setValue(int(viewPoint.y() - viewHeight * vScale)); - //} - - if (HasImage()) - { - QPointF oldPos = mapToScene(event->pos()); - - QPoint scrollAmount = event->angleDelta(); - scrollAmount.y() > 0 ? zoomIn() : zoomOut(); - - QPointF newPos = mapToScene(event->pos()); - - QPointF delta = newPos - oldPos; - translate(delta.x(), delta.y()); - } - - //QGraphicsView::wheelEvent(event);// + QPointF delta = newPos - oldPos; + translate(delta.x(), delta.y()); + } } -void ImageViewer::scaling(qreal scaleFactor) +void mapcavas::scaling(qreal scaleFactor) { - //qDebug() << this->sceneRect(); - scale(scaleFactor, scaleFactor); + scale(scaleFactor, scaleFactor); } -void ImageViewer::mousePressEvent(QMouseEvent *event) +void mapcavas::mousePressEvent(QMouseEvent *event) { - if (event->button()==Qt::LeftButton) - { - m_bMouseTranslate = true; - m_lastMousePos = event->pos(); + if (event->button()==Qt::LeftButton) + { + m_bMouseTranslate = true; + m_lastMousePos = event->pos(); - //qDebug() << mapToScene(m_lastMousePos); - - emit leftMouseButtonPressed(mapToScene(m_lastMousePos).x(), mapToScene(m_lastMousePos).y()); - } - - - //If you do not perform all the necessary work in your implementation of the virtual function, you may need to call the base class's implementation. - QGraphicsView::mousePressEvent(event); + emit leftMouseButtonPressed(mapToScene(m_lastMousePos).x(), mapToScene(m_lastMousePos).y()); + } + QGraphicsView::mousePressEvent(event); } -void ImageViewer::mouseMoveEvent(QMouseEvent *event) +void mapcavas::mouseMoveEvent(QMouseEvent *event) { - if (m_bMouseTranslate){ - QPointF mouseDelta = mapToScene(event->pos()) - mapToScene(m_lastMousePos); - translate(mouseDelta.x(),mouseDelta.y()); - } + if (m_bMouseTranslate){ + QPointF mouseDelta = mapToScene(event->pos()) - mapToScene(m_lastMousePos); + translate(mouseDelta.x(),mouseDelta.y()); + } - m_lastMousePos = event->pos(); - QGraphicsView::mousePressEvent(event); + m_lastMousePos = event->pos(); + QGraphicsView::mousePressEvent(event); } -void ImageViewer::mouseReleaseEvent(QMouseEvent *event) +void mapcavas::mouseReleaseEvent(QMouseEvent *event) { - m_bMouseTranslate = false; - QGraphicsView::mouseReleaseEvent(event); + m_bMouseTranslate = false; + QGraphicsView::mouseReleaseEvent(event); } -void ImageViewer::mouseDoubleClickEvent(QMouseEvent *event) +void mapcavas::mouseDoubleClickEvent(QMouseEvent *event) { - QGraphicsView::mouseDoubleClickEvent(event); + QGraphicsView::mouseDoubleClickEvent(event); } -void ImageViewer::zoomIn() +void mapcavas::zoomIn() { - zoom(1 + m_zoomDelta); + zoom(1 + m_zoomDelta); } -void ImageViewer::zoomOut() +void mapcavas::zoomOut() { - zoom(1 - m_zoomDelta); + zoom(1 - m_zoomDelta); } -void ImageViewer::zoom(float scaleFactor) +void mapcavas::zoom(float scaleFactor) { - // ֹС - qreal factor = transform().scale(scaleFactor, scaleFactor).mapRect(QRectF(0, 0, 1, 1)).width(); - if (factor < 0.07 || factor > 100) - return; + qreal factor = transform().scale(scaleFactor, scaleFactor).mapRect(QRectF(0, 0, 1, 1)).width(); + if (factor < 0.07 || factor > 100) + return; - scale(scaleFactor, scaleFactor); - m_scale *= scaleFactor; + scale(scaleFactor, scaleFactor); + m_scale *= scaleFactor; } -void ImageViewer::setTranslateSpeed(qreal speed) +void mapcavas::setTranslateSpeed(qreal speed) { - // ٶȷΧ - Q_ASSERT_X(speed >= 0.0 && speed <= 2.0, - "InteractiveView::setTranslateSpeed", "Speed should be in range [0.0, 2.0]."); - m_translateSpeed = speed; + Q_ASSERT_X(speed >= 0.0 && speed <= 2.0, + "InteractiveView::setTranslateSpeed", "Speed should be in range [0.0, 2.0]."); + m_translateSpeed = speed; } -qreal ImageViewer::translateSpeed() const +qreal mapcavas::translateSpeed() const { - return m_translateSpeed; + return m_translateSpeed; } -void ImageViewer::setZoomDelta(qreal delta) +void mapcavas::setZoomDelta(qreal delta) { - // Χ - Q_ASSERT_X(delta >= 0.0 && delta <= 1.0, - "InteractiveView::setZoomDelta", "Delta should be in range [0.0, 1.0]."); - m_zoomDelta = delta; + Q_ASSERT_X(delta >= 0.0 && delta <= 1.0, + "InteractiveView::setZoomDelta", "Delta should be in range [0.0, 1.0]."); + m_zoomDelta = delta; } -qreal ImageViewer::zoomDelta() const +qreal mapcavas::zoomDelta() const { - return m_zoomDelta; + return m_zoomDelta; +} + +// new: set associated raster layer +void mapcavas::setLayers(RasterLayer* layer) +{ + m_rasterLayer = layer; +} + +// new: refresh the map by rendering using the RasterLayer's render method +void mapcavas::freshmap() +{ + if (!m_rasterLayer) return; + + RasterLayer::RenderParams params; // default params; could be extended + QImage img = m_rasterLayer->render(params); + if (img.isNull()) return; + + QPixmap pm = QPixmap::fromImage(img); + SetImage(&pm); } diff --git a/HPPA/ImageViewer.h b/HPPA/ImageViewer.h index 86f4dd0..50cb4ef 100644 --- a/HPPA/ImageViewer.h +++ b/HPPA/ImageViewer.h @@ -1,15 +1,18 @@ -#ifndef IMAGE_VIEWER -#define IMAGE_VIEWER +#ifndef MAPCAVAS_H +#define MAPCAVAS_H #include "QGraphicsView" #include "qlabel.h" -class ImageViewer :public QGraphicsView + +class RasterLayer; // forward + +class mapcavas : public QGraphicsView { Q_OBJECT public: - ImageViewer(QWidget* pParent = NULL); - ~ImageViewer(); + mapcavas(QWidget* pParent = NULL); + ~mapcavas(); void DisplayFrameNumber(int frameNumber); @@ -38,12 +41,18 @@ public: // ŵ void setZoomDelta(qreal delta); qreal zoomDelta() const; + + // new: set raster layer and refresh map + void setLayers(RasterLayer* layer); + void freshmap(); + protected: QGraphicsScene *m_qtGraphicsScene; private: QGraphicsPixmapItem *m_GraphicsPixmapItemHandle; QLabel *m_framNumberLabel;//ʾʵʱɼ֡ - + + RasterLayer* m_rasterLayer = nullptr; // associated raster layer qreal m_translateSpeed; // ƽٶ qreal m_zoomDelta; // ŵ diff --git a/HPPA/LayerTreeLayerNode.cpp b/HPPA/LayerTreeLayerNode.cpp index aa81f67..d85a4f6 100644 --- a/HPPA/LayerTreeLayerNode.cpp +++ b/HPPA/LayerTreeLayerNode.cpp @@ -4,3 +4,19 @@ LayerTreeLayerNode::LayerTreeLayerNode(MapLayer* layer, QObject* parent) : LayerTreeNode(layer ? layer->name() : QString(), parent), m_layer(layer) { } + +LayerTreeNode::Type LayerTreeLayerNode::type() const +{ + return Type::Layer; +} + +// һ MapLayer ָ루ӵУ +void LayerTreeLayerNode::setMapLayer(MapLayer* layer) +{ + m_layer = layer; +} + +MapLayer* LayerTreeLayerNode::mapLayer() const +{ + return m_layer; +} diff --git a/HPPA/LayerTreeLayerNode.h b/HPPA/LayerTreeLayerNode.h index 6c3e3bd..d95966e 100644 --- a/HPPA/LayerTreeLayerNode.h +++ b/HPPA/LayerTreeLayerNode.h @@ -7,14 +7,13 @@ class LayerTreeLayerNode : public LayerTreeNode { Q_OBJECT public: - explicit LayerTreeLayerNode(MapLayer* layer, - QObject* parent = nullptr); + explicit LayerTreeLayerNode(MapLayer* layer, QObject* parent = nullptr); - Type type() const override { return Type::Layer; } + Type type() const override; // һ MapLayer ָ루ӵУ - void setMapLayer(MapLayer* layer) { m_layer = layer; } - MapLayer* mapLayer() const { return m_layer; } + void setMapLayer(MapLayer* layer); + MapLayer* mapLayer() const; private: MapLayer* m_layer = nullptr; diff --git a/HPPA/RasterDataProvider.cpp b/HPPA/RasterDataProvider.cpp new file mode 100644 index 0000000..5245f72 --- /dev/null +++ b/HPPA/RasterDataProvider.cpp @@ -0,0 +1,123 @@ +#include "RasterDataProvider.h" +#include +#include + +#if HPPA_HAVE_GDAL +#include +#include +#endif + +RasterDataProvider::RasterDataProvider(const QString& uri) + : m_uri(uri), m_dataset(nullptr) +{ +} + +RasterDataProvider::~RasterDataProvider() +{ + close(); +} + +bool RasterDataProvider::open() +{ +#if HPPA_HAVE_GDAL + GDALAllRegister(); + m_dataset = (GDALDataset*)GDALOpen((const char*)m_uri.toLocal8Bit().constData(), GA_ReadOnly); + if (!m_dataset) { + qWarning() << "RasterDataProvider: failed to open dataset:" << m_uri; + return false; + } + return true; +#else + Q_UNUSED(m_uri); + qWarning() << "RasterDataProvider: GDAL not available, open will fail."; + return false; +#endif +} + +void RasterDataProvider::close() +{ +#if HPPA_HAVE_GDAL + if (m_dataset) { + GDALClose((GDALDatasetH)m_dataset); + m_dataset = nullptr; + } +#else + m_dataset = nullptr; +#endif +} + +int RasterDataProvider::bandCount() const +{ +#if HPPA_HAVE_GDAL + if (!m_dataset) return 0; + return m_dataset->GetRasterCount(); +#else + Q_UNUSED(this); + return 0; +#endif +} + +int RasterDataProvider::width() const +{ +#if HPPA_HAVE_GDAL + if (!m_dataset) return 0; + return m_dataset->GetRasterXSize(); +#else + Q_UNUSED(this); + return 0; +#endif +} + +int RasterDataProvider::height() const +{ +#if HPPA_HAVE_GDAL + if (!m_dataset) return 0; + return m_dataset->GetRasterYSize(); +#else + Q_UNUSED(this); + return 0; +#endif +} + +std::vector RasterDataProvider::bandWavelengths() const +{ + std::vector res; +#if HPPA_HAVE_GDAL + if (!m_dataset) return res; + for (int i = 1; i <= m_dataset->GetRasterCount(); ++i) { + GDALRasterBand* band = m_dataset->GetRasterBand(i); + if (!band) continue; + // Attempt to read wavelength from metadata (commonly "Wavelength" or "wavelength") + const char* val = band->GetMetadataItem("Wavelength"); + if (!val) val = band->GetMetadataItem("wavelength"); + if (val) { + double v = atof(val); + res.push_back(v); + } else { + // push a negative to indicate unknown + res.push_back(-1.0); + } + } +#endif + return res; +} + +bool RasterDataProvider::readBandAsFloat(int bandIndex, std::vector& outBuffer) const +{ +#if HPPA_HAVE_GDAL + if (!m_dataset) return false; + int bands = m_dataset->GetRasterCount(); + if (bandIndex < 0 || bandIndex >= bands) return false; + GDALRasterBand* band = m_dataset->GetRasterBand(bandIndex + 1); + if (!band) return false; + int w = m_dataset->GetRasterXSize(); + int h = m_dataset->GetRasterYSize(); + outBuffer.assign(w * h, 0.0f); + CPLErr err = band->RasterIO(GF_Read, 0, 0, w, h, outBuffer.data(), w, h, GDT_Float32, 0, 0); + return err == CE_None; +#else + Q_UNUSED(bandIndex); + Q_UNUSED(outBuffer); + return false; +#endif +} diff --git a/HPPA/RasterDataProvider.h b/HPPA/RasterDataProvider.h new file mode 100644 index 0000000..aea28b1 --- /dev/null +++ b/HPPA/RasterDataProvider.h @@ -0,0 +1,44 @@ +#pragma once + +#include +#include + +#if __has_include() +#define HPPA_HAVE_GDAL 1 +#include +#include +#else +#define HPPA_HAVE_GDAL 0 +#endif + +class RasterDataProvider +{ +public: + explicit RasterDataProvider(const QString& uri); + ~RasterDataProvider(); + + bool open(); + void close(); + + int bandCount() const; + int width() const; + int height() const; + + // Returns per-band wavelength metadata if available. If not available, returns empty vector. + std::vector bandWavelengths() const; + + // Read a single band (0-based index) into a float buffer of size width()*height(). + // Returns true on success. + bool readBandAsFloat(int bandIndex, std::vector& outBuffer) const; + + QString uri() const { return m_uri; } + +private: + QString m_uri; +#if HPPA_HAVE_GDAL + GDALDataset* m_dataset = nullptr; +#else + // no-op when GDAL not available + void* m_dataset = nullptr; +#endif +}; diff --git a/HPPA/RasterLayer.cpp b/HPPA/RasterLayer.cpp index 44db3e6..fee8c6b 100644 --- a/HPPA/RasterLayer.cpp +++ b/HPPA/RasterLayer.cpp @@ -1,12 +1,48 @@ #include "RasterLayer.h" +#include "RasterDataProvider.h" +#include "RasterRenderer.h" RasterLayer::RasterLayer(const QString& name, const QString& uri) : MapLayer(name, uri) { - + // lazy creation } MapLayer::LayerType RasterLayer::layerType() const { return MapLayer::LayerType::Raster; } + +RasterDataProvider* RasterLayer::dataProvider() const +{ + return m_provider ? m_provider.get() : nullptr; +} + +RasterRenderer* RasterLayer::renderer() const +{ + return m_renderer ? m_renderer.get() : nullptr; +} + +bool RasterLayer::openDataProvider() +{ + if (!m_provider) m_provider = std::make_unique(dataPath()); + if (!m_provider) return false; + bool ok = m_provider->open(); + if (ok && !m_renderer) m_renderer = std::make_unique(m_provider.get()); + return ok; +} + +QImage RasterLayer::render(const RenderParams& params) +{ + if (!m_provider) { + if (!openDataProvider()) return QImage(); + } + if (!m_renderer) m_renderer = std::make_unique(m_provider.get()); + RasterRenderer::Params p; + p.rWave = params.rWave; + p.gWave = params.gWave; + p.bWave = params.bWave; + p.minValue = params.minValue; + p.maxValue = params.maxValue; + return m_renderer->render(p); +} diff --git a/HPPA/RasterLayer.h b/HPPA/RasterLayer.h index 8674a8a..776a732 100644 --- a/HPPA/RasterLayer.h +++ b/HPPA/RasterLayer.h @@ -1,6 +1,11 @@ #pragma once #include "MapLayer.h" +#include +#include + +class RasterDataProvider; +class RasterRenderer; class RasterLayer : public MapLayer { @@ -10,5 +15,25 @@ public: LayerType layerType() const override; - // future: renderer, data provider, etc. + // Access provider/renderer + RasterDataProvider* dataProvider() const; + RasterRenderer* renderer() const; + + // Create or open provider based on this layer's uri + bool openDataProvider(); + + struct RenderParams { + double rWave = 665.0; // default wavelengths (nm) + double gWave = 560.0; + double bWave = 490.0; + double minValue = 0.0; // optional stretch + double maxValue = 255.0; + }; + + // Render the raster using current provider and renderer. Returns an empty QImage on failure. + QImage render(const RenderParams& params); + +private: + std::unique_ptr m_provider; + std::unique_ptr m_renderer; }; diff --git a/HPPA/RasterRenderer.cpp b/HPPA/RasterRenderer.cpp new file mode 100644 index 0000000..6e045be --- /dev/null +++ b/HPPA/RasterRenderer.cpp @@ -0,0 +1,86 @@ +#include "RasterRenderer.h" +#include "RasterDataProvider.h" +#include +#include + +RasterRenderer::RasterRenderer(RasterDataProvider* provider) + : m_provider(provider) +{ +} + +void RasterRenderer::stretchTo8bit(const std::vector& in, std::vector& out, float minVal, float maxVal) +{ + size_t n = in.size(); + out.resize(n); + if (maxVal <= minVal) { + std::fill(out.begin(), out.end(), 0); + return; + } + float denom = 1.0f / (maxVal - minVal); + for (size_t i = 0; i < n; ++i) { + float v = (in[i] - minVal) * denom; + v = std::min(std::max(v, 0.0f), 1.0f); + out[i] = static_cast(v * 255.0f); + } +} + +QImage RasterRenderer::render(const Params& params) +{ + if (!m_provider) return QImage(); + int bands = m_provider->bandCount(); + int w = m_provider->width(); + int h = m_provider->height(); + if (w <= 0 || h <= 0) return QImage(); + + // Find nearest bands for requested wavelengths if wavelengths available + std::vector wavelengths = m_provider->bandWavelengths(); + + auto chooseBandIndexForWave = [&](double wave)->int { + if (wavelengths.empty()) { + // fallback: select R,G,B as first three bands + if (bands >= 3) return (wave==params.rWave?0:(wave==params.gWave?1:2)); + if (bands >= 1) return 0; + return -1; + } + int best = -1; double bestDiff = 1e12; + for (int i = 0; i < (int)wavelengths.size(); ++i) { + if (wavelengths[i] < 0) continue; + double d = std::abs(wavelengths[i] - wave); + if (d < bestDiff) { bestDiff = d; best = i; } + } + if (best >= 0) return best; + // fallback + return std::min(2, bands-1); + }; + + int rIdx = chooseBandIndexForWave(params.rWave); + int gIdx = chooseBandIndexForWave(params.gWave); + int bIdx = chooseBandIndexForWave(params.bWave); + + std::vector rbuf, gbuf, bbuf; + if (rIdx >= 0) m_provider->readBandAsFloat(rIdx, rbuf); + if (gIdx >= 0) m_provider->readBandAsFloat(gIdx, gbuf); + if (bIdx >= 0) m_provider->readBandAsFloat(bIdx, bbuf); + + std::vector r8, g8, b8; + float minV = static_cast(params.minValue); + float maxV = static_cast(params.maxValue); + if (!rbuf.empty()) stretchTo8bit(rbuf, r8, minV, maxV); + if (!gbuf.empty()) stretchTo8bit(gbuf, g8, minV, maxV); + if (!bbuf.empty()) stretchTo8bit(bbuf, b8, minV, maxV); + + QImage out(w, h, QImage::Format_RGB888); + for (int y = 0; y < h; ++y) { + unsigned char* scan = out.scanLine(y); + for (int x = 0; x < w; ++x) { + int idx = y * w + x; + unsigned char rc = (r8.size() > (size_t)idx) ? r8[idx] : 0; + unsigned char gc = (g8.size() > (size_t)idx) ? g8[idx] : 0; + unsigned char bc = (b8.size() > (size_t)idx) ? b8[idx] : 0; + scan[x*3 + 0] = rc; + scan[x*3 + 1] = gc; + scan[x*3 + 2] = bc; + } + } + return out; +} diff --git a/HPPA/RasterRenderer.h b/HPPA/RasterRenderer.h new file mode 100644 index 0000000..8ba412b --- /dev/null +++ b/HPPA/RasterRenderer.h @@ -0,0 +1,29 @@ +#pragma once + +#include +#include + +class RasterDataProvider; + +class RasterRenderer +{ +public: + struct Params { + double rWave = 665.0; + double gWave = 560.0; + double bWave = 490.0; + double minValue = 0.0; + double maxValue = 255.0; + }; + + explicit RasterRenderer(RasterDataProvider* provider); + + // Render to an 8-bit RGB image. Returns empty image on failure. + QImage render(const Params& params); + +private: + RasterDataProvider* m_provider; + + // helper to map float buffer to 8-bit with min/max stretch + static void stretchTo8bit(const std::vector& in, std::vector& out, float minVal, float maxVal); +};