Camera RAW import through LibRaw with a develop sheet (12.6a)

This commit is contained in:
雷电芽衣 committed 2026-09-27 09:19:59 -04:00
1 parent 374ba8ec73
commit 5a2fa91bc7
29 files changed
+1794 -257

No files matched your search

+57
View File
@@ -1,6 +1,8 @@
#include "Document/EditorSession.h"
#include "Document/ProjectWorkspace.h"
#include "Document/PixelAdjust.h"
#include "IO/PSD/PSDReader.h"
#include "IO/RawImporter.h"
#include "Logging.h"
#include <QtConcurrent>
@@ -105,6 +107,10 @@ void EditorSession::decodeNext()
}
}
const QUrl url = request.urls[m_importIndex];
if (url.isLocalFile() && RawImporter::matches(url.toLocalFile())) {
decodeRaw(url.toLocalFile(), 100'000'000 - usedPixels);
return;
}
if (url.isLocalFile() && PSDReader::matches(url.toLocalFile())) {
beginPSDReading(QStringLiteral("Open “%1”?").arg(url.fileName()), QStringLiteral("Import"));
m_photoshopReader.setFuture(QtConcurrent::run([path = url.toLocalFile(), remaining = 100'000'000 - usedPixels]() -> PhotoshopRead {
@@ -133,6 +139,57 @@ void EditorSession::decodeNext()
}));
}
void EditorSession::decodeRaw(const QString &path, qint64 remaining)
{
const QString name = QFileInfo(path).fileName();
const std::optional<QSize> size = RawImporter::pixelSize(path);
const auto refuse = [&](ImageImportError::Kind kind) {
m_importFailures << name + ": " + ImageImportError(kind).what();
m_importIndex += 1;
decodeNext();
};
if (!size)
return refuse(ImageImportError::Kind::unreadable);
if (size->width() > 30'000 || size->height() > 30'000 || qint64(size->width()) * size->height() > remaining)
return refuse(ImageImportError::Kind::tooLarge);
developRaw(path, [this, path, name](std::optional<RawDevelopSettings> settings) {
if (!settings) {
m_importIndex += 1;
decodeNext();
return;
}
// Seconds of work: a worker, so the window keeps drawing.
m_decoder.setFuture(QtConcurrent::run([path, name, settings = *settings]() -> Decoded {
try {
const QImage developed = RawImporter::Queue::shared().develop(path, settings, std::nullopt);
return {ImportedImage(developed, PixelAdjust::thumbnail(developed), ProjectTab::nameWithoutSuffix(path)), QString()};
} catch (const ImageImportError &error) {
return {std::nullopt, name + ": " + error.what()};
} catch (const ExportError &error) {
return {std::nullopt, name + ": " + error.what()};
}
}));
});
}
void EditorSession::developRaw(const QString &path, std::function<void(std::optional<RawDevelopSettings>)> answer)
{
m_rawAnswer = std::move(answer);
m_rawDevelop = RawDevelopRequest{path, RawImporter::asShot(path).value_or(RawDevelopSettings())};
notify();
}
void EditorSession::finishRawDevelop(std::optional<RawDevelopSettings> settings)
{
m_rawDevelop = std::nullopt;
notify();
// Frees the preview's decode on a worker, behind any preview.
(void)QtConcurrent::run([] { RawImporter::Queue::shared().release(); });
// The import resumes from the event loop, as a task.
if (const auto answer = std::exchange(m_rawAnswer, {}))
QMetaObject::invokeMethod(this, [answer, settings] { answer(settings); }, Qt::QueuedConnection);
}
void EditorSession::finishDecode()
{
const Decoded decoded = m_decoder.result();
+8
View File
@@ -17,6 +17,7 @@
#include "Document/EditorSession+Model.h"
#include "IO/ProjectStore.h"
#include "IO/PSD/PSDDocumentBuilder.h"
#include "IO/RawImporter.h"
#include "UI/PSDConversionSheet.h"
#include "Rendering/CanvasViewport.h"
#include "Rendering/EffectsPreviewCache.h"
@@ -70,6 +71,9 @@ public:
void setImportError(std::optional<QString> error);
bool showsConversionSheet() const { return m_showsConversionSheet; }
const std::optional<PSDConversionRequest> &conversionRequest() const { return m_conversionRequest; }
// The RAW file the develop sheet shows, while it shows.
const std::optional<RawDevelopRequest> &rawDevelop() const { return m_rawDevelop; }
void finishRawDevelop(std::optional<RawDevelopSettings> settings);
std::optional<QUuid> renamingLayerID() const { return m_renamingLayerID; }
void setRenamingLayerID(std::optional<QUuid> id);
@@ -242,6 +246,8 @@ public:
void finishPSDReading(const std::vector<PSDConversion> &conversions, std::function<void(bool)> answer);
void endPSDReading();
void finishConversion(bool confirmed);
void decodeRaw(const QString &path, qint64 remaining);
void developRaw(const QString &path, std::function<void(std::optional<RawDevelopSettings>)> answer);
void insertPhotoshop(const PSDImport &imported, const QString &named, std::optional<QPointF> centeredAt = std::nullopt);
void createDocument(int width, int height, bool emptyLayer = false);
void fit();
@@ -386,6 +392,8 @@ private:
bool m_showsConversionSheet = false;
std::optional<PSDConversionRequest> m_conversionRequest;
std::function<void(bool)> m_conversionAnswer;
std::optional<RawDevelopRequest> m_rawDevelop;
std::function<void(std::optional<RawDevelopSettings>)> m_rawAnswer;
// Cancel pressed while the file was still read.
bool m_conversionCancelled = false;
std::optional<QString> m_brushError;