Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
138 changes: 97 additions & 41 deletions Source/FreeImage/SimpleTools.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,104 @@
#include "SimpleTools.h"
#include <cstring>
#include <algorithm>
#include "yato/types.h"

namespace {

struct YuvBrightness
{
template <typename Ty_>
inline
auto operator()(const Ty_& p, std::enable_if_t<IsPixelType<Ty_>::value, void*> = nullptr)
{
return p.red;
}
};

template <typename PixelTy_, typename BrightnessOp_ = Brightness>
std::tuple<PixelTy_*, PixelTy_*, double, double> FindMinMax(FIBITMAP* src, BrightnessOp_ brightnessOp = BrightnessOp_{})
{
PixelTy_* minIt{}, * maxIt{};
double minVal = 0.0, maxVal = 0.0;
if (src) {
const unsigned h = FreeImage_GetHeight(src);
const unsigned w = FreeImage_GetWidth(src);
const unsigned pitch = FreeImage_GetPitch(src);
uint8_t *srcLine = FreeImage_GetBits(src);
for (unsigned j = 0; j < h; ++j, srcLine += pitch) {
auto pixIt = yato::pointer_cast<PixelTy_*>(srcLine);
for (unsigned i = 0; i < w; ++i, ++pixIt) {
if (IsNan(*pixIt)) {
continue;
}
const auto b = static_cast<double>(brightnessOp(*pixIt));
if (!minIt || !maxIt) {
minIt = maxIt = pixIt;
minVal = maxVal = b;
}
else {
if (b < minVal) {
minIt = pixIt;
minVal = b;
}
if (maxVal < b) {
maxIt = pixIt;
maxVal = b;
}
}
}
}
}
return std::make_tuple(minIt, maxIt, minVal, maxVal);
}

template <typename PixelType_>
inline constexpr
void PixelFill(PixelType_& p, const ToValueType<PixelType_>& v)
{
SetChannel<0>(p, v);
SetChannel<1>(p, v);
SetChannel<2>(p, v);
SetChannel<3>(p, v);
}

template <typename PixelType_>
void FindMinMaxValueImpl(FIBITMAP* src, void* out_min_value, void* out_max_value)
{
PixelType_ minVal, maxVal;
PixelFill(minVal, std::numeric_limits<ToValueType<PixelType_>>::max());
PixelFill(maxVal, std::numeric_limits<ToValueType<PixelType_>>::lowest());

const unsigned width = FreeImage_GetWidth(src);
const unsigned height = FreeImage_GetHeight(src);
const unsigned src_pitch = FreeImage_GetPitch(src);

const uint8_t* src_bits = FreeImage_GetBits(src);
for (unsigned y = 0; y < height; ++y) {
auto src_pixel = yato::pointer_cast<const PixelType_*>(src_bits);
for (unsigned x = 0; x < width; ++x) {
const PixelType_ val = src_pixel[x];
SetChannel<0>(minVal, std::min(GetChannel<0>(minVal), GetChannel<0>(val)));
SetChannel<1>(minVal, std::min(GetChannel<1>(minVal), GetChannel<1>(val)));
SetChannel<2>(minVal, std::min(GetChannel<2>(minVal), GetChannel<2>(val)));
SetChannel<3>(minVal, std::min(GetChannel<3>(minVal), GetChannel<3>(val)));
SetChannel<0>(maxVal, std::max(GetChannel<0>(maxVal), GetChannel<0>(val)));
SetChannel<1>(maxVal, std::max(GetChannel<1>(maxVal), GetChannel<1>(val)));
SetChannel<2>(maxVal, std::max(GetChannel<2>(maxVal), GetChannel<2>(val)));
SetChannel<3>(maxVal, std::max(GetChannel<3>(maxVal), GetChannel<3>(val)));
}
src_bits += src_pitch;
}

if (out_min_value) {
*static_cast<PixelType_*>(out_min_value) = minVal;
}
if (out_max_value) {
*static_cast<PixelType_*>(out_max_value) = maxVal;
}
}

} // unnamed namespace

FIBOOL DLL_CALLCONV
FreeImage_FindMinMax(FIBITMAP* dib, double* min_brightness, double* max_brightness, void** min_ptr, void** max_ptr)
Expand Down Expand Up @@ -134,47 +231,6 @@ FreeImage_FindMinMax(FIBITMAP* dib, double* min_brightness, double* max_brightne
return success ? TRUE : FALSE;
}

namespace
{

template <typename PixelType_>
void FindMinMaxValueImpl(FIBITMAP* src, void* out_min_value, void* out_max_value)
{
PixelType_ minVal, maxVal;
PixelFill(minVal, std::numeric_limits<ToValueType<PixelType_>>::max());
PixelFill(maxVal, std::numeric_limits<ToValueType<PixelType_>>::lowest());

const unsigned width = FreeImage_GetWidth(src);
const unsigned height = FreeImage_GetHeight(src);
const unsigned src_pitch = FreeImage_GetPitch(src);

uint8_t* src_bits = FreeImage_GetBits(src);
for (unsigned y = 0; y < height; ++y) {
auto src_pixel = static_cast<PixelType_*>(static_cast<void*>(src_bits));
for (unsigned x = 0; x < width; ++x) {
const PixelType_ val = src_pixel[x];
SetChannel<0>(minVal, std::min(GetChannel<0>(minVal), GetChannel<0>(val)));
SetChannel<1>(minVal, std::min(GetChannel<1>(minVal), GetChannel<1>(val)));
SetChannel<2>(minVal, std::min(GetChannel<2>(minVal), GetChannel<2>(val)));
SetChannel<3>(minVal, std::min(GetChannel<3>(minVal), GetChannel<3>(val)));
SetChannel<0>(maxVal, std::max(GetChannel<0>(maxVal), GetChannel<0>(val)));
SetChannel<1>(maxVal, std::max(GetChannel<1>(maxVal), GetChannel<1>(val)));
SetChannel<2>(maxVal, std::max(GetChannel<2>(maxVal), GetChannel<2>(val)));
SetChannel<3>(maxVal, std::max(GetChannel<3>(maxVal), GetChannel<3>(val)));
}
src_bits += src_pitch;
}

if (out_min_value) {
*static_cast<PixelType_*>(out_min_value) = minVal;
}
if (out_max_value) {
*static_cast<PixelType_*>(out_max_value) = maxVal;
}
}

} // namespace

FIBOOL DLL_CALLCONV
FreeImage_FindMinMaxValue(FIBITMAP* dib, void* min_value, void* max_value)
{
Expand Down
168 changes: 0 additions & 168 deletions Source/FreeImage/SimpleTools.h
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,6 @@ void BitmapTransform(FIBITMAP* dst, FIBITMAP* src, UnaryOperation_ unary_op)
}
}


template <typename Ty_>
using IsIntPixelType = std::integral_constant<bool,
std::is_same_v<Ty_, FIRGB8> ||
Expand Down Expand Up @@ -102,46 +101,6 @@ namespace details
template <typename PixelType_>
using ToValueType = typename details::ToValueTypeImpl<PixelType_>::type;


namespace details
{
template <typename Ty_>
struct ToWiderTypeImpl {};

template <> struct ToWiderTypeImpl<uint64_t> { using type = uint64_t; };
template <> struct ToWiderTypeImpl<int64_t> { using type = int64_t; };
template <> struct ToWiderTypeImpl<uint32_t> { using type = uint64_t; };
template <> struct ToWiderTypeImpl<int32_t> { using type = int64_t; };
template <> struct ToWiderTypeImpl<uint16_t> { using type = uint32_t; };
template <> struct ToWiderTypeImpl<int16_t> { using type = int32_t; };
template <> struct ToWiderTypeImpl<uint8_t> { using type = uint32_t; };
template <> struct ToWiderTypeImpl<int8_t> { using type = int32_t; };
}

template <typename Ty_>
using ToWiderType = typename details::ToWiderTypeImpl<Ty_>::type;


namespace details
{
template <typename Ty_>
struct ToUnsignedTypeImpl {};

template <> struct ToUnsignedTypeImpl<uint64_t> { using type = uint64_t; };
template <> struct ToUnsignedTypeImpl<int64_t> { using type = uint64_t; };
template <> struct ToUnsignedTypeImpl<uint32_t> { using type = uint32_t; };
template <> struct ToUnsignedTypeImpl<int32_t> { using type = uint32_t; };
template <> struct ToUnsignedTypeImpl<uint16_t> { using type = uint16_t; };
template <> struct ToUnsignedTypeImpl<int16_t> { using type = uint16_t; };
template <> struct ToUnsignedTypeImpl<uint8_t> { using type = uint8_t; };
template <> struct ToUnsignedTypeImpl<int8_t> { using type = uint8_t; };
}

template <typename Ty_>
using ToUnsignedType = typename details::ToUnsignedTypeImpl<Ty_>::type;



template <uint32_t Value_>
using uint32_constant = std::integral_constant<uint32_t, Value_>;

Expand All @@ -159,26 +118,6 @@ template <> struct PixelChannelsNumber<FIRGB8> : public uint32_constant<3> {};
template <> struct PixelChannelsNumber<FICOMPLEX> : public uint32_constant<2> {};
template <> struct PixelChannelsNumber<FICOMPLEXF> : public uint32_constant<2> {};

namespace details
{
template <typename PixelType_>
struct ToNoAlphaTypeImpl
{
using type = PixelType_;
};

template <> struct ToNoAlphaTypeImpl<FIRGBAF> { using type = FIRGBF; };
template <> struct ToNoAlphaTypeImpl<FIRGBA32> { using type = FIRGB32; };
template <> struct ToNoAlphaTypeImpl<FIRGBA16> { using type = FIRGB16; };
template <> struct ToNoAlphaTypeImpl<FIRGBA8> { using type = FIRGB8; };

}

template <typename PixelType_>
using ToNoAlphaType = typename details::ToNoAlphaTypeImpl<PixelType_>::type;



template <uint32_t ChannelIndex_, typename PixelType_>
inline constexpr
void SetChannel(PixelType_& p, ToValueType<PixelType_> v)
Expand All @@ -200,61 +139,6 @@ ToValueType<PixelType_> GetChannel(const PixelType_& p, ToValueType<PixelType_>
}
}

template <typename PixelType_>
inline constexpr
void PixelFill(PixelType_& p, const ToValueType<PixelType_>& v)
{
SetChannel<0>(p, v);
SetChannel<1>(p, v);
SetChannel<2>(p, v);
SetChannel<3>(p, v);
}

template <typename PixelType_, typename BinaryOperation_>
inline constexpr
auto PixelReduce(const PixelType_& p, ToValueType<PixelType_> init, BinaryOperation_&& op)
{
constexpr uint32_t channelsNumber = PixelChannelsNumber<PixelType_>::value;
if constexpr (channelsNumber > 0) {
init = op(std::move(init), GetChannel<0>(p));
}
if constexpr (channelsNumber > 1) {
init = op(std::move(init), GetChannel<1>(p));
}
if constexpr (channelsNumber > 2) {
init = op(std::move(init), GetChannel<2>(p));
}
if constexpr (channelsNumber > 3) {
init = op(std::move(init), GetChannel<3>(p));
}
return init;
}

template <typename PixelType_>
inline constexpr
auto PixelMin(const PixelType_& p, ToValueType<PixelType_> init = std::numeric_limits<ToValueType<PixelType_>>::max())
{
return PixelReduce(p, init, [](const auto& lhs, const auto& rhs) { return std::min(lhs, rhs); });
}

template <typename PixelType_>
inline constexpr
auto PixelMax(const PixelType_& p, ToValueType<PixelType_> init = std::numeric_limits<ToValueType<PixelType_>>::lowest())
{
return PixelReduce(p, init, [](const auto& lhs, const auto& rhs) { return std::max(lhs, rhs); });
}

template <typename PixelType_>
inline constexpr
auto StripAlpha(PixelType_&& p)
{
return ToNoAlphaType<PixelType_>(std::forward<PixelType_>(p));
}





inline
bool IsNan(float p) {
return std::isnan(p);
Expand Down Expand Up @@ -283,8 +167,6 @@ std::enable_if_t<std::is_integral_v<Ty_> || IsIntPixelType<Ty_>::value, bool> Is
return false;
}



struct Brightness
{
template <typename Ty_>
Expand All @@ -302,54 +184,4 @@ struct Brightness
}
};

struct YuvBrightness
{
template <typename Ty_>
inline
auto operator()(const Ty_& p, std::enable_if_t<IsPixelType<Ty_>::value, void*> = nullptr)
{
return p.red;
}
};


template <typename PixelTy_, typename BrightnessOp_ = Brightness>
std::tuple<PixelTy_*, PixelTy_*, double, double> FindMinMax(FIBITMAP* src, BrightnessOp_ brightnessOp = BrightnessOp_{})
{
PixelTy_* minIt{}, * maxIt{};
double minVal = 0.0, maxVal = 0.0;
if (src) {
const unsigned h = FreeImage_GetHeight(src);
const unsigned w = FreeImage_GetWidth(src);
const unsigned pitch = FreeImage_GetPitch(src);
auto srcLine = static_cast<uint8_t*>(static_cast<void*>(FreeImage_GetBits(src)));
for (unsigned j = 0; j < h; ++j, srcLine += pitch) {
auto pixIt = static_cast<PixelTy_*>(static_cast<void*>(srcLine));
for (unsigned i = 0; i < w; ++i, ++pixIt) {
if (IsNan(*pixIt)) {
continue;
}
const auto b = static_cast<double>(brightnessOp(*pixIt));
if (!minIt || !maxIt) {
minIt = maxIt = pixIt;
minVal = maxVal = b;
}
else {
if (b < minVal) {
minIt = pixIt;
minVal = b;
}
if (maxVal < b) {
maxIt = pixIt;
maxVal = b;
}
}
}
}
}
return std::make_tuple(minIt, maxIt, minVal, maxVal);
}



#endif //FREEIMAGE_SIMPLE_TOOLS_H_
1 change: 0 additions & 1 deletion Source/FreeImage/tmoColorConvert.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@
#include "FreeImage.h"
#include "Utilities.h"
#include "ToneMapping.h"
#include <algorithm>

// ----------------------------------------------------------
// Convert RGB to and from Yxy, same as in Reinhard et al. SIGGRAPH 2002
Expand Down
1 change: 0 additions & 1 deletion Source/FreeImage/tmoReinhard05.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@
#include "FreeImage.h"
#include "Utilities.h"
#include "ToneMapping.h"
#include <algorithm>

// ----------------------------------------------------------
// Global and/or local tone mapping operator
Expand Down
Loading