Add most dominant colour to image stats #640

This commit is contained in:
Lovell Fuller
2020-07-15 19:58:54 +01:00
parent dcc42f8514
commit c42de19d2a
10 changed files with 130 additions and 36 deletions

View File

@@ -724,4 +724,25 @@ namespace sharp {
return std::make_tuple(image, alphaColour);
}
/*
Removes alpha channel, if any.
*/
VImage RemoveAlpha(VImage image) {
if (HasAlpha(image)) {
image = image.extract_band(0, VImage::option()->set("n", image.bands() - 1));
}
return image;
}
/*
Ensures alpha channel, if missing.
*/
VImage EnsureAlpha(VImage image) {
if (!HasAlpha(image)) {
std::vector<double> alpha;
alpha.push_back(sharp::MaximumImageAlpha(image.interpretation()));
image = image.bandjoin_const(alpha);
}
return image;
}
} // namespace sharp

View File

@@ -271,6 +271,16 @@ namespace sharp {
*/
std::tuple<VImage, std::vector<double>> ApplyAlpha(VImage image, std::vector<double> colour);
/*
Removes alpha channel, if any.
*/
VImage RemoveAlpha(VImage image);
/*
Ensures alpha channel, if missing.
*/
VImage EnsureAlpha(VImage image);
} // namespace sharp
#endif // SRC_COMMON_H_

View File

@@ -27,29 +27,6 @@ using vips::VImage;
using vips::VError;
namespace sharp {
/*
Removes alpha channel, if any.
*/
VImage RemoveAlpha(VImage image) {
if (HasAlpha(image)) {
image = image.extract_band(0, VImage::option()->set("n", image.bands() - 1));
}
return image;
}
/*
Ensures alpha channel, if missing.
*/
VImage EnsureAlpha(VImage image) {
if (!HasAlpha(image)) {
std::vector<double> alpha;
alpha.push_back(sharp::MaximumImageAlpha(image.interpretation()));
image = image.bandjoin_const(alpha);
}
return image;
}
/*
* Tint an image using the specified chroma, preserving the original image luminance
*/

View File

@@ -25,16 +25,6 @@ using vips::VImage;
namespace sharp {
/*
Removes alpha channel, if any.
*/
VImage RemoveAlpha(VImage image);
/*
Ensures alpha channel, if missing.
*/
VImage EnsureAlpha(VImage image);
/*
* Tint an image using the specified chroma, preserving the original image luminance
*/

View File

@@ -86,6 +86,18 @@ class StatsWorker : public Napi::AsyncWorker {
0.0, 1.0, 0.0);
laplacian.set("scale", 9.0);
baton->sharpness = greyscale.conv(laplacian).deviate();
// Most dominant sRGB colour via 4096-bin 3D histogram
vips::VImage hist = sharp::RemoveAlpha(image)
.colourspace(VIPS_INTERPRETATION_sRGB)
.hist_find_ndim(VImage::option()->set("bins", 16));
std::complex<double> maxpos = hist.maxpos();
int const dx = static_cast<int>(std::real(maxpos));
int const dy = static_cast<int>(std::imag(maxpos));
std::vector<double> pel = hist(dx, dy);
int const dz = std::distance(pel.begin(), std::find(pel.begin(), pel.end(), hist.max()));
baton->dominantRed = dx * 16 + 8;
baton->dominantGreen = dy * 16 + 8;
baton->dominantBlue = dz * 16 + 8;
} catch (vips::VError const &err) {
(baton->err).append(err.what());
}
@@ -133,6 +145,11 @@ class StatsWorker : public Napi::AsyncWorker {
info.Set("isOpaque", baton->isOpaque);
info.Set("entropy", baton->entropy);
info.Set("sharpness", baton->sharpness);
Napi::Object dominant = Napi::Object::New(env);
dominant.Set("r", baton->dominantRed);
dominant.Set("g", baton->dominantGreen);
dominant.Set("b", baton->dominantBlue);
info.Set("dominant", dominant);
Callback().MakeCallback(Receiver().Value(), { env.Null(), info });
} else {
Callback().MakeCallback(Receiver().Value(), { Napi::Error::New(env, baton->err).Value() });

View File

@@ -48,6 +48,9 @@ struct StatsBaton {
bool isOpaque;
double entropy;
double sharpness;
int dominantRed;
int dominantGreen;
int dominantBlue;
std::string err;
@@ -55,7 +58,10 @@ struct StatsBaton {
input(nullptr),
isOpaque(true),
entropy(0.0),
sharpness(0.0)
sharpness(0.0),
dominantRed(0),
dominantGreen(0),
dominantBlue(0)
{}
};