Skip to content

Commit 0f0379c

Browse files
committed
be safer with RAII + some tweaks
1 parent 298f3b4 commit 0f0379c

File tree

3 files changed

+40
-43
lines changed

3 files changed

+40
-43
lines changed

opencv.cpp

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
#include "tone_mapping.hpp"
33

44
#include <stdbool.h>
5+
#include <cstdio>
6+
#include <memory>
57
#include <opencv2/highgui.hpp>
68
#include <opencv2/imgproc.hpp>
79
#include <jpeglib.h>
@@ -217,31 +219,32 @@ bool opencv_encoder_write_with_tone_mapping(
217219
size_t icc_len,
218220
bool force_sdr)
219221
{
220-
auto e_ptr = static_cast<cv::ImageEncoder*>(e);
222+
// Validate input early
221223
auto mat = static_cast<const cv::Mat*>(src);
224+
if (!mat || mat->empty()) {
225+
return false;
226+
}
227+
228+
auto e_ptr = static_cast<cv::ImageEncoder*>(e);
222229
std::vector<int> params;
223230
for (size_t i = 0; i < opt_len; i++) {
224231
params.push_back(opt[i]);
225232
}
226233

227234
// Apply tone mapping if requested and ICC profile is available
228235
const cv::Mat* mat_to_encode = mat;
229-
cv::Mat* transformed_mat = nullptr;
236+
std::unique_ptr<cv::Mat> transformed_mat;
230237

231238
if (force_sdr && icc_data && icc_len > 0) {
232-
transformed_mat = apply_tone_mapping(mat, icc_data, icc_len);
239+
transformed_mat.reset(apply_tone_mapping(mat, icc_data, icc_len));
233240
if (transformed_mat) {
234-
mat_to_encode = transformed_mat;
241+
mat_to_encode = transformed_mat.get();
242+
} else {
243+
fprintf(stderr, "PNG: Tone mapping failed, falling back to regular encoding\n");
235244
}
236245
}
237246

238-
bool result = e_ptr->write(*mat_to_encode, params);
239-
240-
if (transformed_mat) {
241-
delete transformed_mat;
242-
}
243-
244-
return result;
247+
return e_ptr->write(*mat_to_encode, params);
245248
}
246249

247250
void opencv_mat_resize(const opencv_mat src,

tone_mapping.cpp

Lines changed: 16 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
11
#include "tone_mapping.hpp"
22
#include <cstring>
3+
#include <memory>
4+
5+
// Tone mapping constants
6+
constexpr float MIN_LUMA_THRESHOLD = 0.001f; // Threshold to avoid division by near-zero luminance
7+
constexpr float REINHARD_LUMINANCE_SCALE = 1.2f; // Gentle luminance boost before tone mapping
38

49
cv::Mat* apply_hdr_to_sdr_tone_mapping(
510
const cv::Mat* src,
@@ -41,13 +46,13 @@ cv::Mat* apply_hdr_to_sdr_tone_mapping(
4146

4247
// Handle alpha channel separately - alpha should NOT be tone mapped
4348
bool has_alpha = (channels == 4);
44-
cv::Mat* bgr_only = nullptr;
45-
cv::Mat* alpha_channel = nullptr;
49+
std::unique_ptr<cv::Mat> bgr_only;
50+
std::unique_ptr<cv::Mat> alpha_channel;
4651
const cv::Mat* src_for_transform = src;
4752

4853
if (has_alpha) {
49-
bgr_only = new cv::Mat(src->rows, src->cols, CV_8UC3);
50-
alpha_channel = new cv::Mat(src->rows, src->cols, CV_8UC1);
54+
bgr_only = std::make_unique<cv::Mat>(src->rows, src->cols, CV_8UC3);
55+
alpha_channel = std::make_unique<cv::Mat>(src->rows, src->cols, CV_8UC1);
5156

5257
cv::Mat channels_split[4];
5358
cv::split(*src, channels_split);
@@ -56,11 +61,11 @@ cv::Mat* apply_hdr_to_sdr_tone_mapping(
5661
cv::merge(bgr_channels, 3, *bgr_only);
5762
*alpha_channel = channels_split[3];
5863

59-
src_for_transform = bgr_only;
64+
src_for_transform = bgr_only.get();
6065
}
6166

6267
// Apply Reinhard tone mapping
63-
cv::Mat* dst_bgr = new cv::Mat(src_for_transform->rows, src_for_transform->cols, CV_8UC3);
68+
std::unique_ptr<cv::Mat> dst_bgr = std::make_unique<cv::Mat>(src_for_transform->rows, src_for_transform->cols, CV_8UC3);
6469

6570
// Apply luminance-based tone mapping to preserve color relationships
6671
// This prevents oversaturation by operating on brightness only
@@ -79,32 +84,26 @@ cv::Mat* apply_hdr_to_sdr_tone_mapping(
7984
float luma = 0.2126f * r + 0.7152f * g + 0.0722f * b;
8085

8186
// Apply gentle Reinhard tone mapping to luminance only
82-
float luma_scaled = luma * 1.2f; // Gentle scaling
87+
float luma_scaled = luma * REINHARD_LUMINANCE_SCALE;
8388
float luma_mapped = luma_scaled / (1.0f + luma_scaled);
8489

8590
// Scale RGB channels by the luminance ratio to preserve color
86-
float ratio = (luma > 0.001f) ? (luma_mapped / luma) : 0.0f;
91+
float ratio = (luma > MIN_LUMA_THRESHOLD) ? (luma_mapped / luma) : 0.0f;
8792

8893
dst_row[idx + 0] = static_cast<uint8_t>(std::min(b * ratio * 255.0f, 255.0f));
8994
dst_row[idx + 1] = static_cast<uint8_t>(std::min(g * ratio * 255.0f, 255.0f));
9095
dst_row[idx + 2] = static_cast<uint8_t>(std::min(r * ratio * 255.0f, 255.0f));
9196
}
9297
}
9398

94-
// Merge alpha back if needed
95-
cv::Mat* result = nullptr;
9699
if (has_alpha) {
97-
result = new cv::Mat(src->rows, src->cols, src->type());
100+
auto result = std::make_unique<cv::Mat>(src->rows, src->cols, src->type());
98101
cv::Mat bgr_channels_out[3];
99102
cv::split(*dst_bgr, bgr_channels_out);
100103
cv::Mat final_channels[4] = {bgr_channels_out[0], bgr_channels_out[1], bgr_channels_out[2], *alpha_channel};
101104
cv::merge(final_channels, 4, *result);
102-
delete bgr_only;
103-
delete alpha_channel;
104-
delete dst_bgr;
105+
return result.release();
105106
} else {
106-
result = dst_bgr;
107+
return dst_bgr.release();
107108
}
108-
109-
return result;
110109
}

webp.cpp

Lines changed: 10 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
#include <webp/demux.h>
99
#include <stdbool.h>
1010
#include <lcms2.h>
11-
#include <iostream>
11+
#include <memory>
1212

1313
struct webp_decoder_struct {
1414
WebPMux* mux;
@@ -781,29 +781,24 @@ size_t webp_encoder_write_with_tone_mapping(webp_encoder e,
781781
size_t icc_len,
782782
bool force_sdr)
783783
{
784-
// If not forcing SDR or no ICC data, just use regular encoding
785-
if (!force_sdr || !icc_data || icc_len == 0) {
786-
return webp_encoder_write(e, src, opt, opt_len, delay, blend, dispose, x_offset, y_offset);
787-
}
788-
789-
// Apply tone mapping to the source Mat
784+
// Validate input early
790785
auto mat = static_cast<const cv::Mat*>(src);
791786
if (!mat || mat->empty()) {
787+
return 0;
788+
}
789+
790+
// If not forcing SDR or no ICC data, just use regular encoding
791+
if (!force_sdr || !icc_data || icc_len == 0) {
792792
return webp_encoder_write(e, src, opt, opt_len, delay, blend, dispose, x_offset, y_offset);
793793
}
794794

795-
cv::Mat* tone_mapped = apply_tone_mapping_webp(mat, icc_data, icc_len);
795+
std::unique_ptr<cv::Mat> tone_mapped(apply_tone_mapping_webp(mat, icc_data, icc_len));
796796
if (!tone_mapped) {
797+
fprintf(stderr, "WebP: Tone mapping failed, falling back to regular encoding\n");
797798
return webp_encoder_write(e, src, opt, opt_len, delay, blend, dispose, x_offset, y_offset);
798799
}
799800

800-
// Encode the tone-mapped image
801-
size_t result = webp_encoder_write(e, tone_mapped, opt, opt_len, delay, blend, dispose, x_offset, y_offset);
802-
803-
// Clean up the tone-mapped Mat
804-
delete tone_mapped;
805-
806-
return result;
801+
return webp_encoder_write(e, tone_mapped.get(), opt, opt_len, delay, blend, dispose, x_offset, y_offset);
807802
}
808803

809804
/**

0 commit comments

Comments
 (0)