Skip to content

Commit 8e464e5

Browse files
committed
External alpha support
• Support for external alpha/mask • External mask read only once per batch • Drag & Drop window - always on top
1 parent ac82b54 commit 8e464e5

File tree

5 files changed

+83
-29
lines changed

5 files changed

+83
-29
lines changed

README.md

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,21 @@ Check console to progress information.
1313

1414
Tool expecting RGBA image file. Output files will be write in same folder as a source files with a name **Source_file_name_fill.ext** as RGB without alpha channel.
1515

16+
From v1.1 possible to use external alpha channel as a single channel file with **_mask.ext** or **_alpha.ext** in name (case insencitive).
17+
Tool will read external alpha channel file only once per batch.
18+
19+
Dependencies
20+
------------
21+
22+
### Required dependencies
23+
* OpenImageIO
24+
* QT5
25+
26+
Changelog
27+
---------
28+
* 1.1 - External alpha/mask channel support. Drag&Drop window always on top.
29+
* 1.0 - Initial release
30+
1631
License
1732
-------
1833

src/Solidify.cpp

Lines changed: 44 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -36,33 +36,51 @@ bool progress_callback(void* opaque_data, float portion_done)
3636
return (portion_done >= 1.f);
3737
}
3838

39-
//int main(int argc, char* argv[]) {
40-
int solidify_main(const std::string& mask_file, const std::string& inputFileName, const std::string& outputFileName) {
39+
std::pair<ImageBuf, ImageBuf> mask_load(const std::string& mask_file) {
40+
ImageBuf mask_buf(mask_file);
41+
std::cout << "Reading " << mask_file << std::endl;
42+
bool read_ok = mask_buf.read(0, 0, 0, 1, true, TypeDesc::FLOAT, nullptr, nullptr);
43+
if (!read_ok) {
44+
std::cerr << "Error: Could not read mask image\n";
45+
exit(-1);
46+
}
47+
48+
ImageBuf rgb_alpha, temp_buff;
49+
50+
bool ok = ImageBufAlgo::channel_append(temp_buff, mask_buf, mask_buf);
51+
ok = ok && ImageBufAlgo::channel_append(rgb_alpha, temp_buff, mask_buf);
52+
if (!ok) {
53+
std::cerr << "Error: Could not append channels\n";
54+
exit(-1);
55+
}
56+
57+
temp_buff.clear();
58+
59+
return { mask_buf, rgb_alpha };
60+
}
61+
62+
bool solidify_main(const std::string& inputFileName, const std::string& outputFileName, std::pair<ImageBuf, ImageBuf> mask_pair) {
4163
Timer g_timer;
4264

4365
// Create an ImageBuf object for the input file
4466
ImageBuf input_buf(inputFileName);
45-
ImageBuf mask_buf(mask_file);
67+
68+
bool external_alpha = false;
69+
70+
if (mask_pair.first.initialized() && mask_pair.second.initialized()) {
71+
external_alpha = true;
72+
}
4673

4774
// Read the image with a progress callback
4875

49-
int last_channel = -1;
76+
int last_channel = (external_alpha) ? 3 : -1; // If we have an external alpha, read only 3 channels
5077

51-
if (mask_file != "") {
52-
last_channel = 3;
53-
std::cout << "Reading " << mask_file << std::endl;
54-
bool read_ok = mask_buf.read(0, 0, 0, 1, true, TypeDesc::FLOAT, nullptr, nullptr);
55-
if (!read_ok) {
56-
std::cerr << "Error: Could not read mask image\n";
57-
return 1;
58-
}
59-
}
6078
std::cout << "Reading " << inputFileName << std::endl;
6179

6280
bool read_ok = input_buf.read(0, 0, 0, last_channel, true, TypeUnknown, *progress_callback, nullptr);
6381
if (!read_ok) {
6482
std::cerr << "Error: Could not read input image\n";
65-
return 1;
83+
return false;
6684
}
6785
std::cout << std::endl;
6886

@@ -73,33 +91,31 @@ int solidify_main(const std::string& mask_file, const std::string& inputFileName
7391

7492
Timer pushpull_timer;
7593

76-
if (mask_file != "") {
77-
ImageBuf alpha_ch, alpha_c3;
78-
bool ok = ImageBufAlgo::channel_append(alpha_ch, mask_buf, mask_buf);
79-
ok = ok && ImageBufAlgo::channel_append(alpha_c3, alpha_ch, mask_buf);
80-
ImageBufAlgo::mul(input_buf, input_buf, alpha_c3);
81-
ok = ok && ImageBufAlgo::channel_append(rgba_buf, input_buf, mask_buf);
94+
if (external_alpha) {
95+
bool ok = ImageBufAlgo::mul(input_buf, input_buf, mask_pair.second);
96+
ok = ok && ImageBufAlgo::channel_append(rgba_buf, input_buf, mask_pair.first);
8297
if (!ok) {
8398
std::cerr << "Error: " << rgba_buf.geterror() << std::endl;
84-
return 1;
99+
return false;
85100
}
86101
}
87102

88-
// Call fillholes_pushpull
103+
ImageBuf* input_buf_ptr = external_alpha ? &rgba_buf : &input_buf; // Use the multiplied RGBA buffer if have an external alpha
89104

90-
bool ok = ImageBufAlgo::fillholes_pushpull(result_buf, (mask_file == "") ? input_buf : rgba_buf);
105+
// Call fillholes_pushpull
106+
bool ok = ImageBufAlgo::fillholes_pushpull(result_buf, *input_buf_ptr);
91107

92108
if (!ok) {
93109
std::cerr << "Error: " << result_buf.geterror() << std::endl;
94-
return 1;
110+
return false;
95111
}
96112

97113
std::cout << "Push-Pull time : " << pushpull_timer.nowText() << std::endl;
98114

99115
auto out = ImageOutput::create(outputFileName);
100116
if (!out) {
101117
std::cerr << "Could not create output file: " << outputFileName << std::endl;
102-
return 1;
118+
return false;
103119
}
104120

105121
ImageSpec spec = result_buf.spec();
@@ -116,6 +132,8 @@ int solidify_main(const std::string& mask_file, const std::string& inputFileName
116132
out->close();
117133

118134
#if 0
135+
136+
// Write RGBA buffer for debug
119137
spec = rgba_buf.spec();
120138
spec.nchannels = 4;
121139

@@ -130,5 +148,5 @@ int solidify_main(const std::string& mask_file, const std::string& inputFileName
130148

131149
std::cout << std::endl << "Total processing time : " << g_timer.nowText() << std::endl;
132150

133-
return 0;
151+
return true;
134152
}

src/processing.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,8 +62,11 @@ bool doProcessing(QList<QUrl> urls) {
6262
// Check if there is an alpha channel files
6363
QString mask_file = checkAlpha(fileNames);
6464

65+
std::pair<ImageBuf, ImageBuf> mask_pair;
66+
6567
if (mask_file != "") {
6668
qDebug() << "Mask file: " << mask_file << " will be used.";
69+
mask_pair = mask_load(mask_file.toStdString());
6770
}
6871

6972
for (int i = 0; i < fileNames.size(); i++) {
@@ -78,7 +81,7 @@ bool doProcessing(QList<QUrl> urls) {
7881
QString outName = path + "/" + baseName + "_fill." + fileInfo.completeSuffix();
7982

8083
// Call the solidify_main function
81-
if (solidify_main(mask_file.toStdString(), fileNames[i].toStdString(), outName.toStdString())) {
84+
if (!solidify_main(fileNames[i].toStdString(), outName.toStdString(), mask_pair)) {
8285
exit(-1);
8386
};
8487
}

src/solidify.h

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,4 +16,12 @@
1616
*/
1717
#pragma once
1818

19-
int solidify_main(const std::string& mask_file, const std::string& inputFileName, const std::string& outputFileName);
19+
#include <OpenImageIO/imageio.h>
20+
#include <OpenImageIO/imagebuf.h>
21+
#include <OpenImageIO/imagebufalgo.h>
22+
23+
using namespace OIIO;
24+
25+
std::pair<ImageBuf, ImageBuf> mask_load(const std::string& mask_file);
26+
27+
bool solidify_main(const std::string& inputFileName, const std::string& outputFileName, std::pair<ImageBuf, ImageBuf> mask_pair);

src/ui.cpp

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,16 @@ class DropArea : public QLabel {
3030
DropArea() {
3131
setAcceptDrops(true);
3232
resize(400, 400);
33-
setText("Drag-n-drop files here"); // Set text
33+
setMinimumSize(400, 400);
34+
setMaximumSize(400, 400);
35+
setWindowFlags(Qt::WindowStaysOnTopHint);
36+
setWindowTitle("Solidify 1.1");
37+
setText("Drag & drop files here"); // Set text
3438
setAlignment(Qt::AlignCenter); // Set alignment to center
39+
40+
QFont font = this->font();
41+
font.setPointSize(16);
42+
setFont(font);
3543
}
3644

3745
protected:
@@ -55,6 +63,8 @@ class DropArea : public QLabel {
5563
bool success = doProcessing(urls);
5664

5765
qDebug() << "Done!";
66+
67+
return;
5868
}
5969
};
6070

0 commit comments

Comments
 (0)