diff --git a/Source/EmberCommon/JpegUtils.h b/Source/EmberCommon/JpegUtils.h index 46df92f..16c4a82 100644 --- a/Source/EmberCommon/JpegUtils.h +++ b/Source/EmberCommon/JpegUtils.h @@ -116,7 +116,8 @@ static bool WriteJpeg(const char* filename, unsigned char* image, size_t width, jpeg_destroy_compress(&info); if (file != nullptr) - fclose(file); + if (fclose(file))//Non-zero indicates failure. + return false; b = true; } @@ -225,7 +226,8 @@ static bool WritePng(const char* filename, unsigned char* image, size_t width, s png_destroy_write_struct(&png_ptr, &info_ptr); if (file != nullptr) - fclose(file); + if (fclose(file)) + return false; b = true; } diff --git a/Source/Fractorium/FinalRenderEmberController.cpp b/Source/Fractorium/FinalRenderEmberController.cpp index fb2f32e..f4ef2a5 100644 --- a/Source/Fractorium/FinalRenderEmberController.cpp +++ b/Source/Fractorium/FinalRenderEmberController.cpp @@ -107,6 +107,7 @@ bool FinalRenderEmberController::RenderSingleEmber(Ember& ember, bool full return false; } + auto ret = true; ember.m_TemporalSamples = 1;//No temporal sampling. m_Renderer->SetEmber(ember, fullRender ? eProcessAction::FULL_RENDER : eProcessAction::KEEP_ITERATING, /* updatePointer */ true); m_Renderer->PrepFinalAccumVector(m_FinalImage);//Must manually call this first because it could be erroneously made smaller due to strips if called inside Renderer::Run(). @@ -119,15 +120,19 @@ bool FinalRenderEmberController::RenderSingleEmber(Ember& ember, bool full { Output("Rendering failed.\n"); m_Fractorium->ErrorReportToQTextEdit(m_Renderer->ErrorReport(), m_FinalRenderDialog->ui.FinalRenderTextOutput, false);//Internally calls invoke. + ret = false; }, [&](Ember& finalEmber) { m_FinishedImageCount.fetch_add(1); - SaveCurrentRender(finalEmber); + + if (SaveCurrentRender(finalEmber) == "") + m_Run = ret = false; + RenderComplete(finalEmber); HandleFinishedProgress(); });//Final strip. - return true; + return ret; } /// @@ -188,13 +193,14 @@ bool FinalRenderEmberController::RenderSingleEmberFromSeries(std::atomicImageComments(stats, 0, true); writeThread = std::thread([&](size_t tempTime, size_t threadFinalImageIndex) { - SaveCurrentRender(*m_EmberFile.Get(tempTime), - comments,//These all don't change during the renders, so it's ok to access them in the thread. - finalImages[threadFinalImageIndex], - renderer->FinalRasW(), - renderer->FinalRasH(), - m_FinalRenderDialog->Png16Bit(), - m_FinalRenderDialog->Transparency()); + if (SaveCurrentRender(*m_EmberFile.Get(tempTime), + comments,//These all don't change during the renders, so it's ok to access them in the thread. + finalImages[threadFinalImageIndex], + renderer->FinalRasW(), + renderer->FinalRasH(), + m_FinalRenderDialog->Png16Bit(), + m_FinalRenderDialog->Transparency()) == "") + m_Run = false; }, ftime, finalImageIndex); m_FinishedImageCount.fetch_add(1); RenderComplete(*m_EmberFile.Get(ftime), stats, renderTimer); @@ -336,7 +342,8 @@ FinalRenderEmberController::FinalRenderEmberController(FractoriumFinalRenderD Output("No renderer present, aborting."); } - const QString totalTimeString = "All renders completed in: " + QString::fromStdString(m_TotalTimer.Format(m_TotalTimer.Toc())) + "."; + const QString totalTimeString = m_Run ? "All renders completed in: " + QString::fromStdString(m_TotalTimer.Format(m_TotalTimer.Toc())) + "." + : "Render aborted."; Output(totalTimeString); QFile::remove(backup); QMetaObject::invokeMethod(m_FinalRenderDialog, "Pause", Qt::QueuedConnection, Q_ARG(bool, false)); @@ -856,13 +863,12 @@ QString FinalRenderEmberController::SaveCurrentRender(Ember& ember) /// The height in pixels of the image /// Whether to use 16 bits per channel per pixel when saving as Png/32-bits per channel when saving as Exr. /// Whether to use alpha when saving as Png or Exr. -/// The full path and filename the image was saved to. +/// The full path and filename the image was saved to. Empty string is saving failed. template QString FinalRenderEmberController::SaveCurrentRender(Ember& ember, const EmberImageComments& comments, vector& pixels, size_t width, size_t height, bool png16Bit, bool transparency) { const auto filename = ComposePath(QString::fromStdString(ember.m_Name)); - FractoriumEmberControllerBase::SaveCurrentRender(filename, comments, pixels, width, height, png16Bit, transparency); - return filename; + return FractoriumEmberControllerBase::SaveCurrentRender(filename, comments, pixels, width, height, png16Bit, transparency) ? filename : ""; } /// diff --git a/Source/Fractorium/FractoriumEmberController.h b/Source/Fractorium/FractoriumEmberController.h index 127a073..e0792d6 100644 --- a/Source/Fractorium/FractoriumEmberController.h +++ b/Source/Fractorium/FractoriumEmberController.h @@ -285,7 +285,7 @@ public: void ClearFinalImages(); void Shutdown(); void UpdateRender(eProcessAction action = eProcessAction::FULL_RENDER); - void SaveCurrentRender(const QString& filename, const EmberImageComments& comments, vector& pixels, size_t width, size_t height, bool png16Bit, bool transparency); + bool SaveCurrentRender(const QString& filename, const EmberImageComments& comments, vector& pixels, size_t width, size_t height, bool png16Bit, bool transparency); RendererBase* Renderer() { return m_Renderer.get(); } vector* FinalImage() { return &(m_FinalImage); } vector* PreviewFinalImage() { return &m_PreviewFinalImage; } diff --git a/Source/Fractorium/FractoriumRender.cpp b/Source/Fractorium/FractoriumRender.cpp index ca5edde..c7b0048 100644 --- a/Source/Fractorium/FractoriumRender.cpp +++ b/Source/Fractorium/FractoriumRender.cpp @@ -120,11 +120,12 @@ void FractoriumEmberController::DeleteRenderer() /// The height in pixels of the image /// Whether to use 16 bits per channel per pixel when saving as Png/32-bits per channel when saving as Exr. /// Whether to use alpha when saving as Png or Exr. -void FractoriumEmberControllerBase::SaveCurrentRender(const QString& filename, const EmberImageComments& comments, vector& pixels, size_t width, size_t height, bool png16Bit, bool transparency) +bool FractoriumEmberControllerBase::SaveCurrentRender(const QString& filename, const EmberImageComments& comments, vector& pixels, size_t width, size_t height, bool png16Bit, bool transparency) { + bool ret = false; + if (filename != "") { - bool ret = false; const auto size = width * height; auto settings = m_Fractorium->m_Settings; QFileInfo fileInfo(filename); @@ -138,7 +139,7 @@ void FractoriumEmberControllerBase::SaveCurrentRender(const QString& filename, c if (pixels.size() < size) { m_Fractorium->ShowCritical("Save Failed", "Dimensions didn't match, not saving.", true); - return; + return ret; } auto data = pixels.data(); @@ -189,7 +190,7 @@ void FractoriumEmberControllerBase::SaveCurrentRender(const QString& filename, c else { m_Fractorium->ShowCritical("Save Failed", "Unrecognized format " + suffix + ", not saving.", true); - return; + return ret; } if (ret) @@ -197,6 +198,8 @@ void FractoriumEmberControllerBase::SaveCurrentRender(const QString& filename, c else m_Fractorium->ShowCritical("Save Failed", "Could not save file, try saving to a different folder.", true); } + + return ret; } ///