Skip to content

Commit

Permalink
Merge pull request #220 from Tom94/save-cropped
Browse files Browse the repository at this point in the history
Respect crop when saving / copying image
  • Loading branch information
Tom94 authored Jan 12, 2024
2 parents 6b69ca7 + e3b39ae commit fdc8ae0
Show file tree
Hide file tree
Showing 6 changed files with 137 additions and 137 deletions.
34 changes: 28 additions & 6 deletions include/tev/Box.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,16 @@ struct Box {
return nanogui::max(max - min, Vector{(T)0});
}

T area() const {
auto size = this->size();
T result = (T)1;
for (uint32_t i = 0; i < N_DIMS; ++i) {
result *= size[i];
}

return result;
}

Vector middle() const {
return (min + max) / (T)2;
}
Expand All @@ -39,6 +49,7 @@ struct Box {
for (uint32_t i = 0; i < N_DIMS; ++i) {
result &= max[i] >= min[i];
}

return result;
}

Expand All @@ -47,6 +58,7 @@ struct Box {
for (uint32_t i = 0; i < N_DIMS; ++i) {
result &= pos[i] >= min[i] && pos[i] < max[i];
}

return result;
}

Expand All @@ -55,6 +67,7 @@ struct Box {
for (uint32_t i = 0; i < N_DIMS; ++i) {
result &= pos[i] >= min[i] && pos[i] <= max[i];
}

return result;
}

Expand All @@ -81,12 +94,6 @@ struct Box {
Vector min, max;
};

template <typename Stream, typename T, uint32_t N_DIMS, std::enable_if_t<std::is_base_of_v<std::ostream, Stream>, int> = 0>
Stream& operator<<(Stream& os, const Box<T, N_DIMS>& v) {
os << '[' << v.min << ", " << v.max << ']';
return os;
}

using Box2f = Box<float, 2>;
using Box3f = Box<float, 3>;
using Box4f = Box<float, 4>;
Expand All @@ -95,3 +102,18 @@ using Box3i = Box<int32_t, 3>;
using Box4i = Box<int32_t, 4>;

}

template <typename T, uint32_t N_DIMS>
struct fmt::formatter<tev::Box<T, N_DIMS>> : fmt::formatter<std::string_view> {
template <typename FormatContext>
auto format(const tev::Box<T, N_DIMS>& box, FormatContext& ctx) {
return formatter<std::string_view>::format(fmt::format("[{}, {}]", box.min, box.max), ctx);
}
};

template <typename Stream, typename T, uint32_t N_DIMS, std::enable_if_t<std::is_base_of_v<std::ostream, Stream>, int> = 0>
Stream& operator<<(Stream& os, const tev::Box<T, N_DIMS>& v) {
os << '[' << v.min << ", " << v.max << ']';
return os;
}

10 changes: 10 additions & 0 deletions include/tev/Common.h
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,16 @@ struct fmt::formatter<std::filesystem::path> : fmt::formatter<std::string_view>
}
};

template <typename T, uint32_t N_DIMS>
struct fmt::formatter<nanogui::Array<T, N_DIMS>> : fmt::formatter<std::string_view> {
template <typename FormatContext>
auto format(const nanogui::Array<T, N_DIMS>& v, FormatContext& ctx) {
std::ostringstream s;
s << v;
return formatter<std::string_view>::format(s.str(), ctx);
}
};

struct NVGcontext;

namespace nanogui {
Expand Down
86 changes: 24 additions & 62 deletions include/tev/ImageCanvas.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,38 +36,20 @@ class ImageCanvas : public nanogui::Canvas {

void translate(const nanogui::Vector2f& amount);
void scale(float amount, const nanogui::Vector2f& origin);
float scale() const {
return nanogui::extractScale(mTransform);
}

void setExposure(float exposure) {
mExposure = exposure;
}
float scale() const { return nanogui::extractScale(mTransform); }

void setOffset(float offset) {
mOffset = offset;
}

void setGamma(float gamma) {
mGamma = gamma;
}
void setExposure(float exposure) { mExposure = exposure; }
void setOffset(float offset) { mOffset = offset; }
void setGamma(float gamma) { mGamma = gamma; }

float applyExposureAndOffset(float value) const;

void setImage(std::shared_ptr<Image> image) {
mImage = image;
}
void setImage(std::shared_ptr<Image> image) { mImage = image; }
void setReference(std::shared_ptr<Image> reference) { mReference = reference; }
void setRequestedChannelGroup(const std::string& groupName) { mRequestedChannelGroup = groupName; }

void setReference(std::shared_ptr<Image> reference) {
mReference = reference;
}

void setRequestedChannelGroup(const std::string& groupName) {
mRequestedChannelGroup = groupName;
}

nanogui::Vector2i getImageCoords(const Image& image, nanogui::Vector2i mousePos);
nanogui::Vector2i getDisplayWindowCoords(const Image& image, nanogui::Vector2i mousePos);
nanogui::Vector2i getImageCoords(const Image* image, nanogui::Vector2i mousePos);
nanogui::Vector2i getDisplayWindowCoords(const Image* image, nanogui::Vector2i mousePos);

void getValuesAtNanoPos(nanogui::Vector2i nanoPos, std::vector<float>& result, const std::vector<std::string>& channels);
std::vector<float> getValuesAtNanoPos(nanogui::Vector2i nanoPos, const std::vector<std::string>& channels) {
Expand All @@ -76,59 +58,39 @@ class ImageCanvas : public nanogui::Canvas {
return result;
}

ETonemap tonemap() const {
return mTonemap;
}

void setTonemap(ETonemap tonemap) {
mTonemap = tonemap;
}
ETonemap tonemap() const { return mTonemap; }
void setTonemap(ETonemap tonemap) { mTonemap = tonemap; }

static nanogui::Vector3f applyTonemap(const nanogui::Vector3f& value, float gamma, ETonemap tonemap);
nanogui::Vector3f applyTonemap(const nanogui::Vector3f& value) const {
return applyTonemap(value, mGamma, mTonemap);
}

EMetric metric() const {
return mMetric;
}

void setMetric(EMetric metric) {
mMetric = metric;
}

void setCrop(const std::optional<Box2i>& crop) {
mCrop = crop;
}

std::optional<Box2i> getCrop() {
return mCrop;
}
EMetric metric() const { return mMetric; }
void setMetric(EMetric metric) { mMetric = metric; }

static float applyMetric(float value, float reference, EMetric metric);
float applyMetric(float value, float reference) const {
return applyMetric(value, reference, mMetric);
}

auto backgroundColor() {
return mShader->backgroundColor();
}
std::optional<Box2i> crop() { return mCrop; }
void setCrop(const std::optional<Box2i>& crop) { mCrop = crop; }
Box2i cropInImageCoords() const;

void setBackgroundColor(const nanogui::Color& color) {
mShader->setBackgroundColor(color);
}
auto backgroundColor() { return mShader->backgroundColor(); }
void setBackgroundColor(const nanogui::Color& color) { mShader->setBackgroundColor(color); }

void fitImageToScreen(const Image& image);
void resetTransform();

void setClipToLdr(bool value) {
mClipToLdr = value;
}

bool clipToLdr() const {
return mClipToLdr;
}
bool clipToLdr() const { return mClipToLdr; }
void setClipToLdr(bool value) { mClipToLdr = value; }

// The following functions return four values per pixel in RGBA order. The number of pixels is given by
// `imageDataSize()`. If the canvas does not currently hold an image, or no channels are displayed, then zero pixels
// are returned.
nanogui::Vector2i imageDataSize() const { return cropInImageCoords().size(); }
std::vector<float> getHdrImageData(bool divideAlpha, int priority) const;
std::vector<char> getLdrImageData(bool divideAlpha, int priority) const;

Expand Down
2 changes: 1 addition & 1 deletion src/HelpWindow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ HelpWindow::HelpWindow(Widget* parent, bool supportsHdr, function<void()> closeC
addRow(imageSelection, "Space", "Toggle playback of images as video");

addRow(imageSelection, "Click & Drag (+Shift/" + COMMAND + ")", "Translate image");
addRow(imageSelection, "Click & Drag+C (hold)", "Select region of histogram");
addRow(imageSelection, "Click & Drag+C (hold)", "Crop image");
addRow(imageSelection, "+ / - / Scroll (+Shift/" + COMMAND + ")", "Zoom in / out of image");

addRow(imageSelection, COMMAND + "+0", "Zoom to actual size");
Expand Down
Loading

0 comments on commit fdc8ae0

Please sign in to comment.