Merge pull request #3432 from Beep6581/fix_image_datas_convert_to
Use full range in `ImageDatas::convertTo<>` (#3429)
This commit is contained in:
@@ -58,10 +58,10 @@ enum TypeInterpolation { TI_Nearest, TI_Bilinear };
|
||||
class ImageDatas : virtual public ImageDimensions
|
||||
{
|
||||
public:
|
||||
template <class S, class D >
|
||||
void convertTo (S srcValue, D &dstValue)
|
||||
template<class S, class D>
|
||||
void convertTo(S src, D& dst) const
|
||||
{
|
||||
dstValue = static_cast<D>(srcValue);
|
||||
dst = src;
|
||||
}
|
||||
|
||||
// parameters that will never be used, replaced by the subclasses r, g and b parameters!
|
||||
@@ -100,30 +100,30 @@ public:
|
||||
|
||||
};
|
||||
|
||||
template <>
|
||||
inline void ImageDatas::convertTo<unsigned short, unsigned char> (const unsigned short srcValue, unsigned char &dstValue)
|
||||
template<>
|
||||
inline void ImageDatas::convertTo(unsigned short src, unsigned char& dst) const
|
||||
{
|
||||
dstValue = (unsigned char)(srcValue >> 8);
|
||||
dst = uint16ToUint8Rounded(src);
|
||||
}
|
||||
template <>
|
||||
inline void ImageDatas::convertTo<unsigned char, int> (const unsigned char srcValue, int &dstValue)
|
||||
template<>
|
||||
inline void ImageDatas::convertTo(unsigned char src, int& dst) const
|
||||
{
|
||||
dstValue = (int)(srcValue) << 8;
|
||||
dst = src * 257;
|
||||
}
|
||||
template <>
|
||||
inline void ImageDatas::convertTo<unsigned char, unsigned short> (const unsigned char srcValue, unsigned short &dstValue)
|
||||
template<>
|
||||
inline void ImageDatas::convertTo(unsigned char src, unsigned short& dst) const
|
||||
{
|
||||
dstValue = (unsigned short)(srcValue) << 8;
|
||||
dst = src * 257;
|
||||
}
|
||||
template <>
|
||||
inline void ImageDatas::convertTo<float, unsigned char> (const float srcValue, unsigned char &dstValue)
|
||||
template<>
|
||||
inline void ImageDatas::convertTo(float src, unsigned char& dst) const
|
||||
{
|
||||
dstValue = (unsigned char)( (unsigned short)(srcValue) >> 8 );
|
||||
dst = uint16ToUint8Rounded(src);
|
||||
}
|
||||
template <>
|
||||
inline void ImageDatas::convertTo<unsigned char, float> (const unsigned char srcValue, float &dstValue)
|
||||
template<>
|
||||
inline void ImageDatas::convertTo(unsigned char src, float& dst) const
|
||||
{
|
||||
dstValue = float( (unsigned short)(srcValue) << 8 );
|
||||
dst = src * 257;
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
@@ -28,9 +28,9 @@ namespace
|
||||
void getScanline8 (const uint16_t *red, const uint16_t *green, const uint16_t *blue, int width, unsigned char* buffer)
|
||||
{
|
||||
for (int i = 0, ix = 0; i < width; i++) {
|
||||
buffer[ix++] = red[i] >> 8;
|
||||
buffer[ix++] = green[i] >> 8;
|
||||
buffer[ix++] = blue[i] >> 8;
|
||||
buffer[ix++] = rtengine::uint16ToUint8Rounded(red[i]);
|
||||
buffer[ix++] = rtengine::uint16ToUint8Rounded(green[i]);
|
||||
buffer[ix++] = rtengine::uint16ToUint8Rounded(blue[i]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -92,10 +92,10 @@ void Image16::setScanline (int row, unsigned char* buffer, int bps, float *minVa
|
||||
case (IIOSF_UNSIGNED_CHAR): {
|
||||
int ix = 0;
|
||||
|
||||
for (int i = 0; i < width; i++) {
|
||||
r(row, i) = (unsigned short)(buffer[ix++]) << 8;
|
||||
g(row, i) = (unsigned short)(buffer[ix++]) << 8;
|
||||
b(row, i) = (unsigned short)(buffer[ix++]) << 8;
|
||||
for (int i = 0; i < width; ++i) {
|
||||
r(row, i) = static_cast<unsigned short>(buffer[ix++]) * 257;
|
||||
g(row, i) = static_cast<unsigned short>(buffer[ix++]) * 257;
|
||||
b(row, i) = static_cast<unsigned short>(buffer[ix++]) * 257;
|
||||
}
|
||||
|
||||
break;
|
||||
@@ -105,7 +105,7 @@ void Image16::setScanline (int row, unsigned char* buffer, int bps, float *minVa
|
||||
unsigned short* sbuffer = (unsigned short*) buffer;
|
||||
int ix = 0;
|
||||
|
||||
for (int i = 0; i < width; i++) {
|
||||
for (int i = 0; i < width; ++i) {
|
||||
r(row, i) = sbuffer[ix++];
|
||||
g(row, i) = sbuffer[ix++];
|
||||
b(row, i) = sbuffer[ix++];
|
||||
@@ -298,11 +298,11 @@ Image16::to8()
|
||||
{
|
||||
Image8* img8 = new Image8(width, height);
|
||||
|
||||
for ( int h = 0; h < height; ++h ) {
|
||||
for ( int w = 0; w < width; ++w ) {
|
||||
img8->r(h, w) = (unsigned char)( r(h, w) >> 8);
|
||||
img8->g(h, w) = (unsigned char)( g(h, w) >> 8);
|
||||
img8->b(h, w) = (unsigned char)( b(h, w) >> 8);
|
||||
for (int h = 0; h < height; ++h) {
|
||||
for (int w = 0; w < width; ++w) {
|
||||
img8->r(h, w) = uint16ToUint8Rounded(r(h, w));
|
||||
img8->g(h, w) = uint16ToUint8Rounded(g(h, w));
|
||||
img8->b(h, w) = uint16ToUint8Rounded(b(h, w));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -314,11 +314,11 @@ Image16::tofloat()
|
||||
{
|
||||
Imagefloat* imgfloat = new Imagefloat(width, height);
|
||||
|
||||
for ( int h = 0; h < height; ++h ) {
|
||||
for ( int w = 0; w < width; ++w ) {
|
||||
imgfloat->r(h, w) = (float)r(h, w);
|
||||
imgfloat->g(h, w) = (float)g(h, w);
|
||||
imgfloat->b(h, w) = (float)b(h, w);
|
||||
for (int h = 0; h < height; ++h) {
|
||||
for (int w = 0; w < width; ++w) {
|
||||
imgfloat->r(h, w) = r(h, w);
|
||||
imgfloat->g(h, w) = g(h, w);
|
||||
imgfloat->b(h, w) = b(h, w);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -49,8 +49,8 @@ void Image8::getScanline (int row, unsigned char* buffer, int bps)
|
||||
} else if (bps == 16) {
|
||||
unsigned short* sbuffer = (unsigned short*) buffer;
|
||||
|
||||
for (int i = 0, ix = row * width * 3; i < width * 3; i++, ix++) {
|
||||
sbuffer[i] = (unsigned short)(data[ix]) << 8;
|
||||
for (int i = 0, ix = row * width * 3; i < width * 3; ++i, ++ix) {
|
||||
sbuffer[i] = static_cast<unsigned short>(data[ix]) * 257;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -73,8 +73,8 @@ void Image8::setScanline (int row, unsigned char* buffer, int bps, float *minVal
|
||||
case (IIOSF_UNSIGNED_SHORT): {
|
||||
unsigned short* sbuffer = (unsigned short*) buffer;
|
||||
|
||||
for (int i = 0, ix = row * width * 3; i < width * 3; i++, ix++) {
|
||||
data[ix] = sbuffer[i] >> 8;
|
||||
for (int i = 0, ix = row * width * 3; i < width * 3; ++i, ++ix) {
|
||||
data[ix] = uint16ToUint8Rounded(sbuffer[i]);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
@@ -333,11 +333,11 @@ Imagefloat::to8()
|
||||
#pragma omp parallel for schedule(static)
|
||||
#endif
|
||||
|
||||
for ( int h = 0; h < height; ++h ) {
|
||||
for ( int w = 0; w < width; ++w ) {
|
||||
img8->r(h, w) = (unsigned char)( (unsigned short)(r(h, w)) >> 8);
|
||||
img8->g(h, w) = (unsigned char)( (unsigned short)(g(h, w)) >> 8);
|
||||
img8->b(h, w) = (unsigned char)( (unsigned short)(b(h, w)) >> 8);
|
||||
for (int h = 0; h < height; ++h) {
|
||||
for (int w = 0; w < width; ++w) {
|
||||
img8->r(h, w) = uint16ToUint8Rounded(r(h, w));
|
||||
img8->g(h, w) = uint16ToUint8Rounded(g(h, w));
|
||||
img8->b(h, w) = uint16ToUint8Rounded(b(h, w));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -352,11 +352,11 @@ Imagefloat::to16()
|
||||
#pragma omp parallel for schedule(static)
|
||||
#endif
|
||||
|
||||
for ( int h = 0; h < height; ++h ) {
|
||||
for ( int w = 0; w < width; ++w ) {
|
||||
img16->r( h, w) = (unsigned short)(r(h, w));
|
||||
img16->g( h, w) = (unsigned short)(g(h, w));
|
||||
img16->b( h, w) = (unsigned short)(b(h, w));
|
||||
for (int h = 0; h < height; ++h) {
|
||||
for (int w = 0; w < width; ++w) {
|
||||
img16->r(h, w) = r(h, w);
|
||||
img16->g(h, w) = g(h, w);
|
||||
img16->b(h, w) = b(h, w);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -88,36 +88,28 @@ void ImProcFunctions::lab2monitorRgb (LabImage* lab, Image8* image)
|
||||
#pragma omp parallel for schedule(dynamic,16) if (multiThread)
|
||||
#endif
|
||||
|
||||
for (int i = 0; i < H; i++) {
|
||||
for (int i = 0; i < H; ++i) {
|
||||
float* rL = lab->L[i];
|
||||
float* ra = lab->a[i];
|
||||
float* rb = lab->b[i];
|
||||
int ix = i * 3 * W;
|
||||
|
||||
float R, G, B;
|
||||
float fy, fx, fz, x_, y_, z_, LL;
|
||||
float x_, y_, z_;
|
||||
|
||||
for (int j = 0; j < W; j++) {
|
||||
for (int j = 0; j < W; ++j) {
|
||||
|
||||
//float L1=rL[j],a1=ra[j],b1=rb[j];//for testing
|
||||
|
||||
fy = (0.00862069 * rL[j]) / 327.68 + 0.137932; // (L+16)/116
|
||||
fx = (0.002 * ra[j]) / 327.68 + fy;
|
||||
fz = fy - (0.005 * rb[j]) / 327.68;
|
||||
LL = rL[j] / 327.68;
|
||||
|
||||
x_ = 65535.0 * Color::f2xyz(fx) * Color::D50x;
|
||||
// y_ = 65535.0 * Color::f2xyz(fy);
|
||||
z_ = 65535.0 * Color::f2xyz(fz) * Color::D50z;
|
||||
y_ = (LL > Color::epskap) ? 65535.0 * fy * fy * fy : 65535.0 * LL / Color::kappa;
|
||||
Color::Lab2XYZ(rL[j], ra[j], rb[j], x_, y_, z_ );
|
||||
|
||||
Color::xyz2srgb(x_, y_, z_, R, G, B);
|
||||
|
||||
/* copy RGB */
|
||||
//int R1=((int)gamma2curve[(R)])
|
||||
data[ix++] = ((int)Color::gamma2curve[R]) >> 8;
|
||||
data[ix++] = ((int)Color::gamma2curve[G]) >> 8;
|
||||
data[ix++] = ((int)Color::gamma2curve[B]) >> 8;
|
||||
data[ix++] = uint16ToUint8Rounded(Color::gamma2curve[R]);
|
||||
data[ix++] = uint16ToUint8Rounded(Color::gamma2curve[G]);
|
||||
data[ix++] = uint16ToUint8Rounded(Color::gamma2curve[B]);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -205,30 +197,23 @@ Image8* ImProcFunctions::lab2rgb (LabImage* lab, int cx, int cy, int cw, int ch,
|
||||
#pragma omp parallel for schedule(dynamic,16) if (multiThread)
|
||||
#endif
|
||||
|
||||
for (int i = cy; i < cy + ch; i++) {
|
||||
float R, G, B;
|
||||
for (int i = cy; i < cy + ch; ++i) {
|
||||
float* rL = lab->L[i];
|
||||
float* ra = lab->a[i];
|
||||
float* rb = lab->b[i];
|
||||
int ix = 3 * i * cw;
|
||||
|
||||
for (int j = cx; j < cx + cw; j++) {
|
||||
float R, G, B;
|
||||
float x_, y_, z_;
|
||||
|
||||
float fy = (0.00862069 * rL[j]) / 327.68 + 0.137932; // (L+16)/116
|
||||
float fx = (0.002 * ra[j]) / 327.68 + fy;
|
||||
float fz = fy - (0.005 * rb[j]) / 327.68;
|
||||
float LL = rL[j] / 327.68;
|
||||
|
||||
float x_ = 65535.0 * Color::f2xyz(fx) * Color::D50x;
|
||||
//float y_ = 65535.0 * Color::f2xyz(fy);
|
||||
float z_ = 65535.0 * Color::f2xyz(fz) * Color::D50z;
|
||||
float y_ = (LL > Color::epskap) ? 65535.0 * fy * fy * fy : 65535.0 * LL / Color::kappa;
|
||||
for (int j = cx; j < cx + cw; ++j) {
|
||||
Color::Lab2XYZ(rL[j], ra[j], rb[j], x_, y_, z_);
|
||||
|
||||
Color::xyz2rgb(x_, y_, z_, R, G, B, xyz_rgb);
|
||||
|
||||
image->data[ix++] = (int)Color::gamma2curve[R] >> 8;
|
||||
image->data[ix++] = (int)Color::gamma2curve[G] >> 8;
|
||||
image->data[ix++] = (int)Color::gamma2curve[B] >> 8;
|
||||
image->data[ix++] = uint16ToUint8Rounded(Color::gamma2curve[R]);
|
||||
image->data[ix++] = uint16ToUint8Rounded(Color::gamma2curve[G]);
|
||||
image->data[ix++] = uint16ToUint8Rounded(Color::gamma2curve[B]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,14 +1,15 @@
|
||||
#ifndef _MYMATH_
|
||||
#define _MYMATH_
|
||||
#include <cmath>
|
||||
#include <algorithm>
|
||||
#pragma once
|
||||
|
||||
#include <algorithm>
|
||||
#include <cmath>
|
||||
#include <cstdint>
|
||||
|
||||
namespace rtengine
|
||||
{
|
||||
static const int MAXVAL = 0xffff;
|
||||
static const float MAXVALF = float(MAXVAL); // float version of MAXVAL
|
||||
static const double MAXVALD = double(MAXVAL); // double version of MAXVAL
|
||||
|
||||
constexpr int MAXVAL = 0xffff;
|
||||
constexpr float MAXVALF = static_cast<float>(MAXVAL); // float version of MAXVAL
|
||||
constexpr double MAXVALD = static_cast<double>(MAXVAL); // double version of MAXVAL
|
||||
|
||||
template <typename _Tp>
|
||||
inline _Tp SQR (_Tp x)
|
||||
@@ -107,6 +108,9 @@ inline int float2uint16range(float d) // clips input to [0;65535] and rounds
|
||||
return d + 0.5f;
|
||||
}
|
||||
|
||||
constexpr std::uint8_t uint16ToUint8Rounded(std::uint16_t i)
|
||||
{
|
||||
return ((i + 128) - ((i + 128) >> 8)) >> 8;
|
||||
}
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user